| name | ysyx-config-build |
| description | Operate the YSYX workbench's Config-driven NPC, ysyxSoC, NEMU-host, and FPGA construction workflow. Use when inspecting or changing Scala CDE Config composition, `make config=`, construction versions, `run`/`run-bat`, NEMU host builds, FPGA board settings, generated RTL routing, or NPC/SoC memory integration in this repository. |
YSYX Config Build
Treat a complete Scala Config as the hardware ABI, build policy, and runtime-host selection. Work from the workbench root; the NPC root is npc/.
Orient First
Read these sources before changing build behavior or Config composition:
npc/README.md and npc/chisel/configs/README.md for the public interface and layer model.
npc/chisel/configs/parameters/ConfigCatalogGenerator.scala for automatic terminal discovery.
npc/chisel/configs/npc/base/ConfigBase.scala and npc/chisel/configs/npc/core/ConstructionConfig.scala for NpcCoreConfigKey and L1 composition.
npc/chisel/configs/common/base/ConstructionTraits.scala, npc/chisel/configs/common/base/IpComputeSelectionTraits.scala, npc/chisel/configs/common/core/TerminalCoreTraits.scala, npc/chisel/configs/common/core/IpTerminalCoreTraits.scala, npc/chisel/configs/common/TerminalTraits.scala, and npc/chisel/configs/common/IpTerminalTraits.scala for the base construction interfaces, IP selection contract, terminal child groups, Make terminals, and FPGA/NEMU compute-IP terminals.
npc/Makefile, npc/scripts/construction-manager.sh, and am-kernels/tests/cpu-tests/Makefile for the actual lifecycle and user-facing commands.
Do not hand-edit npc/chisel/configs/resources/npc-config-catalog.tsv or infer public availability from class names. Make refreshes the catalog through Scala and only discovers complete, public, no-argument Configs from each terminal domain's root Configs.scala.
Config Rules
- Preserve
left ++ right precedence: the right side establishes defaults and the left side overrides identical CDE keys.
- Use
ConstructionConfig for reusable L1 NPC hardware. It publishes a completed NpcConfig through NpcCoreConfigKey.
- Let SoC and FPGA configurations consume that same key. A higher layer can override the default NPC by placing a complete L1 Config to the left of its SoC graph.
- Put parameter keys, ordinary data models, composition protocols, atomic
With...Config fragments, and low-level construction interfaces in base/. Base must not depend on core/, provide terminal catalog identity, or describe a directly runnable target. A terminal Config must never mix a base construction trait directly.
- Build terminal-ready, plainly named hardware combinations in
core/. Core consumes base; a terminal must select complete core hardware values instead of expanding base fragments again. Keep reusable integration and check-only Configs here without Make terminal identity.
- A root terminal file may declare only traits or Configs that a terminal can use directly. Put every child and child group directly composed by a terminal in
core/; put only those children's low-level dependencies, data models, protocols, and atomic fragments in base/. A root terminal trait must directly extend its named core aggregate rather than composing multiple base traits.
- Keep terminal-level files directly at the domain root, outside
base/ and core/. Put the six complete Make presets in root-level common/TerminalTraits.scala: LocalNpcTerminal, LocalSocTerminal, U55cNpcTerminal, U55cSocTerminal, Zcu102NpcTerminal, and Zcu102SocTerminal. Each preset must provide complete NEMU and optional FPGA toolchain defaults together with its fixed scope and target. The sibling common/IpTerminalTraits.scala may define only the two non-Make compute-IP terminals: FpgaIpTerminal selects the synthesis backend, while NemuSimulationIpTerminal applies matching timing through the built-in functional model. Keep their generic IpComputeSelection contract and non-terminal FPGA selection in common/base/IpComputeSelectionTraits.scala. Do not create a terminal/ directory for them.
- Treat compute-IP selection like NEMU-host selection: every runnable terminal Config must visibly mix exactly one matching IP terminal,
NemuSimulationIpTerminal or FpgaIpTerminal, which provides IpConstruction. The public terminal itself is the sole mounting point: ConstructionConfig, reusable NPC/SoC cores, and CDE ++ chains must not accept, pass, or select an IpComputeSelection. WithTerminalIpCoreConfig may only read the already-mounted terminal Config from CDE site for a reusable SoC default. Keep FpgaIpAttachment as the board-specific provider, route, timing, and generator contract, not as a replacement for the terminal IP selection.
- Keep every Make-selectable terminal Config in its domain root
Configs.scala, and keep only public no-argument terminal classes in that file. Make every built-in Config and ordinary example mix exactly one matching terminal preset and rely on its complete defaults, so the normal form is one-step mounting. Do not separately mix HostConstruction, NemuSimulationConstruction, FpgaConstruction, or MakeTerminal. Preserve advanced flexibility: an explicitly custom terminal may override configuredNemu or configuredFpga while retaining the preset's scope and target.
- Keep every terminal Config and terminal trait concise and elegant: express one directly runnable purpose through a short, one-step composition; do not repeat defaults, expand base fragments, or hide policy in anonymous intermediate
new ... chains. Move any policy that makes a terminal hard to scan into a plainly named core/ aggregate or base/ dependency first.
- Keep
CheckOnlyConstruction as the directly mountable core trait for non-Make check Configs. Name shared construction traits without a Trait suffix, and name files that define those traits with the *Traits.scala suffix.
- Do not add empty
Configs.scala files to common/ or nemu/; they have no hardware terminal Configs. common/TerminalTraits.scala is their shared root-level terminal protocol. FPGA boards share chisel/configs/fpga/common/base/, form terminal-ready board policy in each board's chisel/configs/fpga/<board>/core/, and define final terminals in that board's chisel/configs/fpga/<board>/Configs.scala.
- Keep hardware parameters in CDE. Define reusable ordinary
NemuHostConfig and grouped FpgaToolchainConfig presets in their core/ files, then bind complete defaults inside root-level terminal presets. Use nested copy(...) for a deliberate custom terminal override. Promote a recipe that is reused or should appear in ordinary examples to a named core preset and, when appropriate, a complete terminal trait; keep ordinary examples on the one-step preset form.
- Keep common FPGA arithmetic attachment contracts in
chisel/configs/common/base/FpgaIpAttachmentTraits.scala. An attachment extends the base FpgaIpComputeSelection and is the sole source for its provider, M routes, endpoint timing, and IP-generator fields; a board Config mounts it with WithFpgaIpAttachmentConfig, and both NPC and SoC consume the selected CDE key. Use NemuSimulationIpTerminal.from(attachment) when a local NEMU model must reproduce that attachment's timing. Keep FpgaPlatformSettings limited to physical addresses and clocks; do not duplicate IP latency or II there.
- Keep
check-only Configs out of Make's public catalog. Keep board policy at L4 under chisel/configs/fpga/u55c/ or chisel/configs/fpga/zcu102/.
- Put only common accelerator/IP parameters in
configs/common/; keep NPC-specific ISA, pipeline, interface, and memory fragments under configs/npc/.
Use the Public Interface
Use only the Config-driven commands unless explicitly repairing an internal build step:
make config-list
make build config=SimulationConfig
make rebuild config=SimulationConfig
make rebuild version=1
make host-build version=1
make build-host config=SimulationConfig
make rebuild-host version=1
make version
make -C npc config-list
make -C npc build config=SimulationConfig
make -C npc rebuild config=SimulationConfig
make -C npc resume-post-link config=U55cRv64CacheNpc150MHzPerformanceMonitorFpgaConfig
make -C npc host-build config=SimulationConfig
make -C npc version
make -C am-kernels/tests/cpu-tests run ALL=add config=SimulationConfig
make -C am-kernels/tests/cpu-tests run-bat ALL="forwarding matrix-mul" version=1,2 jobs=2
make -C am-kernels/tests/cpu-tests run-bat ALL=add version=2 reset=1
- Accept short Config names or registered FQCNs; resolve them through the generated catalog.
- Use
version=<positive index> as the stable reference to a saved construction. Do not expose internal timestamp IDs as normal user workflow.
- A construction immediately occupies its stable
constructions/<FQCN>/ directory with .incomplete, version.info, and version.tag at STATE=building; build, rebuild, completion, failure, and interruption never rename or hide that directory. After host/RTL/asset validation the tag becomes complete; interruption and failure update it to interrupted or failed. make -C npc version scans only those two files and never refreshes or parses Scala. Its valid? cell is + only for a complete formal construction whose local host and FPGA bitstream/xclbin remain present; incomplete or asset-missing constructions remain listed as invalid. The query only waits when a legacy formal construction needs its one-time tag/info migration. resolve version=<N> accepts only a valid formal record, while current config= resolution may refresh a Scala profile.
- Read the
version output as one table: Version RV32 RV64 M F Zicsr Pipe ID EX valid? Arch RunningTime Config. Feature and valid cells use +/blank; Arch is NPC/SoC, RunningTime is SIM/FPGA, and Config is the saved short name. Do not list a supplemental Config mapping or the current catalog. D=<positive versions> and delete=<positive versions> both delete saved constructions and compact later version numbers. A version list uses commas or hyphens, such as D=1,2,3 or D=1-2-3; resolve every selected original version before deleting anything, then reindex once. When both aliases are supplied, they must normalize to the same version set, although their order and separator may differ. Pipeline always occupies exactly the Pipe, ID-forwarding, and EX-forwarding cells.
- Before giving a user a
run or run-bat command for a Config, check make -C npc version config=<Config>. If a matching saved construction exists, present version=<positive index> as the preferred execution selector so the command uses its frozen hardware ABI, runtime host, and FPGA assets. For batches across saved constructions, prefer a version=1,2,... matrix. Use config=<Config> for execution only when no saved construction exists, the user explicitly requests current Config resolution, or the command creates or updates a construction with build/rebuild.
- Keep
run and run-bat focused on execution. Use make rebuild config=<FpgaConfig> or make rebuild version=<positive index> for a deliberate FPGA asset replacement. The version form reads the saved FQCN, resolves that same Config in the current catalog, and performs a complete rebuild from current source while retaining the construction's stable version index; it is an ordinary proactive update path and does not require the prior construction to be failed or invalid. Do not combine config= and version= on one rebuild.
- Use
make host-build config=<Config> (or the equivalent make -C npc ...) for NEMU-host C/C++ or NemuHostConfig changes. host-build version=<positive index> selects a saved formal construction directly, which is important when an old host's report clock no longer matches the frozen FPGA profile. With a saved formal construction it rereads the current terminal, atomically replaces only the saved profile's NEMU_* segment and host, and preserves hardware, FPGA toolchain fields, assets, version metadata, and runtime reports. For FPGA it compiles NEMU's performance-report frequency from the saved FPGA_CLOCK_MHZ, records it as CORE_CLOCK_MHZ in abi/nemu/host.env, and validates the value against the frozen hardware profile; this corrects a reporting-host mismatch without touching the xclbin. It can also recover a failed/interrupted FPGA construction only when a nemu-host phase failure is recorded and its existing manifest/SHA-256 assets pass validation; it then builds only the host and publishes the original version. Without a formal construction it creates constructions/.hosts/<FQCN>/ for local NPC/SoC, or constructions/.compatible/<FQCN>/ for FPGA with an empty fpga/artifacts/ and compatibility.env; the latter accepts an external U55C npc-<FPGA_PLATFORM>.xclbin or ZCU102 npc.bit plus npc-zcu102.env. Once present, compatible FPGA assets take priority over formal fpga/artifacts/ for both config= and version= runs. Compatibility metadata checks Config/board/platform/host ABI/protocol ABI, and U55C DATA_CLK is checked when xclbinutil is available. Neither cache is a formal version. config= and version= cannot be combined for one host-build; host-rebuild=1 remains a run/run-bat preparation option. Hardware replacement is make rebuild config=<Config> or make rebuild version=<positive index>; never pass a rebuild variable to a Make target.
- Treat
host-build as the canonical build-host/rebuild-host operation: use it first whenever only the NEMU host, its C/C++ dependencies, or NemuHostConfig changed. It must not elaborate RTL or invoke Vivado/Vitis/v++; it reuses verified FPGA assets and avoids an unnecessary full FPGA rebuild. Make targets build-host and rebuild-host are public aliases for host-build; the Make target host-rebuild remains rejected so it cannot be confused with the host-rebuild=1 run/run-bat preparation flag. Escalate to rebuild only for hardware/FPGA toolchain/ABI changes, absent or invalid FPGA assets, or a failed construction without verified post-link assets and nemu-host failure evidence. The local NemuHostConfig.LocalVcdTrace exception changes the frozen Verilator ABI (--trace, verilated_vcd_c.o, and npc_start_trace/npc_stop_trace), so moving to or from it always needs a full local build/rebuild, never host-build.
resume-post-link is a separate, narrow U55C FPGA recovery for a Vitis link that completed xclbin packaging but failed before manifest or host publication. It accepts only failed/interrupted formal constructions with a saved profile, synthesis stamp, Vitis-success log, expected xclbin, no manifest/link-complete stamp, and no frozen construction profile. It compares every non-NEMU_* field with the current Config, then actually checks DATA_CLK, WNS, artifact manifest/SHA-256, and builds the host before publishing the original version. It never invokes Vivado/Vitis and must reject any hardware/toolchain/ABI change or incomplete evidence; use rebuild in those cases.
- FPGA toolchain changes require
make -C npc rebuild config=<Config>; host-build intentionally does not absorb them for a saved formal construction.
- Use
jobs=-1 for unlimited batch execution. job= is ignored, and the removed host_rebuild= spelling fails with an explicit replacement message.
- Expect
run-bat to prepare selected constructions serially before launching its parallel version-by-test matrix. jobs=N applies only after preparation. To refresh every saved runnable NEMU host in parallel, use make -C npc host-build all=1 jobs=N, then run the batch without host-rebuild=1.
reset=1 is a NEMU run parameter valid only for FPGA Configs. On U55C it resets the selected card non-interactively with xbutil --batch --force reset --type user before every NEMU host loads its xclbin; without it, the card is not reset automatically. Core/mailbox reset alone cannot clear an outstanding HBM/AXI transaction, even after a mailbox mtestexit completion, so use reset=1 after interruption or suspected stale state. The NEMU host aborts a run after five seconds without either an architectural commit or a mailbox completion, irrespective of whether the mailbox reports a backpressure reason; it prints the sampled reason bits and cumulative stall counters before cleanup. U55C still requires jobs=1 for run-bat; the default XRT device index 0 discovers the first U55C BDF, while a nonzero NEMU_FPGA_DEVICE_INDEX requires NEMU_FPGA_XRT_BDF=<dddd:bb:dd.f> (and NEMU_FPGA_XBUTIL can override the xbutil path).
- Do not resurrect legacy selectors such as
S=1, fpga=, soc=, SIM_FPGA_CONFIG, or hand-written snapshot IDs.
Construction Lifecycle
- Store each Config at
npc/constructions/<FQCN>/; preserve its public version index and CREATED_AT across a successful rebuild.
- Build and rebuild directly in the stable FQCN directory so generic RTL browsers can follow it without staging rules.
build creates a missing construction or repairs any invalid (building, interrupted, failed, or asset-missing) construction; it must reject a valid?=+ construction and direct the user to rebuild. A hardware build or rebuild clears the previous ABI, FPGA assets, build logs, and runtime reports before starting; a failed or interrupted build leaves the same directory invalid and keeps failure evidence under .failed/.
- The global construction lock protects only short metadata work: migration, profile freeze, stable-directory preparation, and final publication. A long
build/rebuild holds constructions/.locks/<FQCN>.lock, so different Configs may run Chisel/Verilator/Vivado/Vitis concurrently while a same-FQCN request fails immediately. Local NPC/SoC construction passes construction-private .work directories to elaboration, Verilator, SoftFloat, and SoC simulation instead of sharing generated*, intermediate, or build-sim. delete must acquire every versioned FQCN lock before removal and reindexing; if any is held, reject the entire delete before changing files.
- Public construction output is phase-oriented: show compact stage progress (and live Chisel
N/M progress) while preserving complete raw tool output. In an interactive terminal, a passthrough phase with no new output for one second shows a transient spinner that never enters logs; the next tool line clears it. The latest hardware phases live in constructions/<FQCN>/logs/build/, and a host refresh lives in logs/host/; failed attempts additionally preserve their logs under constructions/.failed/<FQCN>/<build|host>/.
- The reusable current-source profile cache in
constructions/.profiles/ is keyed by a Scala/profile-input fingerprint. It automatically refreshes for resolve and config-list after Config or profile-source changes, while an already saved construction remains frozen until an explicit rebuild target.
- Keep every Vivado-participating phase live, including the U55C
v++ link flow. The arithmetic-IP Tcl stores one log per generated IP under fpga/ip-generated/logs/; other historical tool output remains in the phase log unless it is compact progress or a failure excerpt.
- Freeze the Alveo Vitis XRT environment policy in
FpgaToolchainConfig.flow.vitisXrtMode and render it as FPGA_VITIS_XRT_MODE; it applies only to v++, never to the saved runtime host. On the local U55C/Vitis 2022.2 flow use unset so Vitis selects its bundled xclbinutil rather than an incompatible newer XILINX_XRT installation.
- FPGA implementation-report depth and auxiliary-report switches are frozen in
FpgaToolchainConfig.reports, then rendered as FPGA_REPORT_* in profile.env; do not introduce Make overrides. U55C writes reports through a Vitis post-route hook and ZCU102 sources the same Tcl after impl_1 opens. Each implementation run owns npc-implementation-reports/; failed constructions preserve those directories.
run-bat must not interleave parallel child output. It reports a completion-ordered per-item table only after all tasks finish, then a stable version/Config/test comparison table and a per-item performance.html home-page index. Child reports are reached from that home page; do not print a parallel direct-link list or generate a batch HTML. Per-item raw run output is temporary; session TSV summaries and details.txt remain under log/constructions/runs/.
- Treat
profile.env, construction.env, saved host files, generated RTL, and FPGA manifests as one construction ABI. Do not mix files from the current checkout into an old FPGA construction.
NemuHostConfig.performanceHtml is the optional parent report feature. When enabled, a construction-backed run writes performance.html as the report home page and instructions.html as the searchable per-commit detail page under constructions/<FQCN>/runtime/<test>/<timestamp-ns>-<pid>/. pipelineHtml requires performanceHtml and reuses the same bounded commit records to add pipeline.html; do not collect a second trace. cacheHtml also requires performanceHtml: it writes a separate cache.html when any configured cache is enabled, with geometry, policies, instruction-buffer settings, and cache counters; local Verilator reports expose I$, D$, and unified L2$ counters, while the current FPGA mailbox ABI exposes I$/D$ hardware counters only. The parent page links to it only when that write succeeds. Local Verilator uses software records. Ordinary U55C v11 profiles keep all HTML features disabled. The batch-only U55cRv64Npc{100,125,150,200,250,300}MHzPerformanceMonitorFpgaConfig terminals and U55cRv64CacheNpc{150,300}MHzPerformanceMonitorFpgaConfig bind NemuHostConfig.U55cPerformanceMonitor and replay their v13 HBM prefix trace for performance, instruction, pipeline, and where applicable cache reports; they have FPGA_RUNTIME_SDB=0, so they do not synthesize SDB halt/step or wide architectural snapshots. The cache monitor additionally reads its elaborated I$/D$ configuration, instruction-buffer depth, and five counters through read-only mailbox registers 0x190..0x20c; after a cache-enabled mtestexit drain, the mailbox snapshots those values for the completed run before resetting the core. It must not add cache events to the fixed v13 trace record. Trace overflow leaves aggregates exact but labels detailed samples as prefix-derived, and saturated 16-bit stage values are lower bounds. The home page opens child reports in a new window, and each child links back. All local NPC/SoC simulation terminals currently bind NemuHostConfig.LocalPipelineTrace, enable per-commit NPC/NEMU software self-difftest, and generate performance, instruction, pipeline, and (for cache-enabled Configs) cache reports. Self-difftest compares GPRs, FPRs, FCSR, next PC, and main-memory store bus effects so the first architectural divergence is reported directly, including adjacent-lane corruption that shared memory would otherwise mask. Scalar cores show sequential stage residency; pipelined cores additionally show overlap and stalls. The wrapper atomically updates <test>/latest; optional SDB VCD clips use numbered wave-*.vcd files in the same directory. A full rebuild drops prior runtime reports with the old hardware ABI, while host-build preserves them.
- Let local NPC/SoC runs ensure their saved construction. For FPGA, require a complete saved asset set and validate board, manifest, checksum, platform, and runtime ABI before attempting board execution.
- Ordinary public U55C FPGA profiles use
npc-fpga-runtime-v11: the Vitis RTL kernel supplies explicit ip_c, ap_ctrl_hs, interrupt, and a 4 KiB s_axi_control metadata/control plane so XRT can open the CU context. They keep FPGA_RUNTIME_TRACE=0 and FPGA_RUNTIME_SDB=1, do not generate m_axi_trace, HBM[1] trace BOs, or URAM trace FIFOs, and keep NEMU performance and pipeline HTML disabled. U55cRv64Npc{100,125,150,200,250,300}MHzPerformanceMonitorFpgaConfig and U55cRv64CacheNpc{150,300}MHzPerformanceMonitorFpgaConfig are the explicit exceptions: they use npc-fpga-runtime-v13-performance-monitor, have CAPABILITY=batch, FPGA_RUNTIME_SDB=0, reject run, write 32-byte v2 records through a fixed 256-bit m_axi_trace to an 8 MiB HBM[1] BO, and use a 2048-record URAM FIFO with 16-record bursts. The cache variant preserves that trace ABI and adds only mailbox cache-status registers. FPGA_RUNTIME_SDB and FPGA_RUNTIME_TRACE are mutually exclusive. The stock xilinx_u55c_gen3x16_xdma_3_202210_1 platform binds HBM-connected RTL kernels to its fixed 300 MHz DATA_CLK; FPGA_PLATFORM_CLOCK_MHZ and xclbinutil validate that interface frequency. The monitor profile's FPGA_CLOCK_MHZ is the 100/125/150/200/250/300 MHz core target. Below 300 MHz, the packaged wrapper uses an MMCM-derived core clock and xpm_fifo_async for every AXI4/AXI-Lite channel, so the core cannot run above its profile. The monitor must be fully rebuilt; host-only work with a v11 external xclbin cannot provide hardware metrics. The physical AXI-Lite addresses are 12 bits and no raw ap_* control pins are exposed; the packaged wrapper materializes its XLEN define so Vitis retains the physical AXI data width. The NPC remains a mailbox-controlled continuous service. ZCU102 uses npc-fpga-runtime-v7. FPGA AM terminates by committing csrw 0x7c0, a0 to the non-standard machine CSR mtestexit; the mailbox snapshots completion and resets the core at that commit boundary. Before a next host starts, mailbox core-reset acknowledges stale completion and putch events and clears guest-MEIP. EBREAK remains a normal RISC-V breakpoint trap and is not a completion, debug halt, or RISC-V external interrupt. Mailbox guest-MEIP control is level-triggered and feeds core.io.interrupt independently. Public FPGA profiles freeze M vendor-IP OPERATOR_ROUTE_M_*, disable F/D with F=0 and D=0, and retain FPGA_NOTIFICATION_MODE only for runtime control. F instruction learning is local-Verilator-only and FPGA profiles have no OPERATOR_ROUTE_F_*. Any change to these fields or the runtime ABI requires rebuild, not only host-build=1; older constructions must be rebuilt.
ps-uio-irq profiles use the ZCU102 PS/UIO host interrupt path. xrt-poll profiles keep explicit U55C XRT polling because that runtime does not expose a consumable IRQ file descriptor. Neither notification mode is a RISC-V external interrupt.
Memory and SoC Integration
- Read
npc/chisel/rv-core/main/scala/protocol/axi/NpcMemoryFabric.scala before changing memory topology.
- Distinguish local simulation from external memory: local NPC uses DPI RAM/MMIO; external NPC merges IF and LSU-main-memory AXI-Lite requests, then bridges them to one AXI4-Full master.
- Do not describe the two Lite clients as a doubled data width. They are arbitrated request sources; the current bridge uses the same data width on Lite and Full.
- Do not assume ysyxSoC removes the NPC fabric. The NPC Lite arbiter, address split, and Lite-to-Full bridge remain; the SoC places Rocket AXI4 interconnect downstream. In current FPGA mode many SoC peripherals are intentionally absent, so retain or add the SoC path only when its system-level topology is needed.
- Treat a wider HBM/DDR beat as a separate width-adapter/cache-line design. It requires correct alignment, byte strobes, read extraction, burst semantics, and response ordering; changing one bus-width parameter is insufficient.
U55cRv64Hbm512CacheNpc150MHzPerformanceMonitorFpgaConfig is the explicit U55C wide-HBM cache ABI: the CPU and MMIO ports remain RV64/64-bit, while its cached line-memory port and m_axi_gmem are 512-bit with 64-byte I$/D$ lines. A refill or dirty writeback is one full HBM beat; it is not interchangeable with a 16-byte cache construction and requires its own make -C npc rebuild config=<Config>. U55cRv64Hbm512L2CacheNpc150MHzPerformanceMonitorFpgaConfig is its separate ABI with a unified 256 KiB, 64-byte, 8-way Tree-PLRU, write-back/write-allocate L2 between the L1 arbiter and the same 512-bit AXI4-Full bridge. It must not replace that addressable downstream path with AXI-Stream.
HbmJitterCacheSimulationConfig is the local L1-only functional-timing counterpart of the wide-L1 baseline. It keeps CPU/MMIO at 64 bits, uses a 512-bit local DPI cache-memory port, and expands each full transaction into eight parallel stable 64-bit DPI lanes. Its fixed-seed 73--81-cycle RAM response range applies only to main memory, not MMIO; it is useful for calibrated L1 miss stalls and local HTML traces, but is not a cycle-identical U55C HBM model because it omits wrapper FIFO, bank/queue, and broader arbitration effects. HbmJitterL2CacheSimulationConfig reuses that exact CPU/L1/DPI timing and inserts the unified 256 KiB L2 in a local IF/LSU-arbiter -> L2 -> DPI main-memory path; MMIO remains outside the L2. Both are simulation-only comparison endpoints and do not replace the FPGA HBM topology.
- NPC caches are an explicit Config choice.
SimulationConfig, ordinary SoC terminals, and ordinary U55C/ZCU102 terminals remain cache-disabled; cached terminals use the named cache core aggregates and expose their ICACHE_*, DCACHE_*, L2CACHE_*, INSTRUCTION_BUFFER_*, and ZIFENCEI fields in both the construction profile and FPGA elaboration manifest. Any cached FPGA geometry, policy, storage, or maintenance change requires make -C npc rebuild config=<CacheFpgaConfig>; local L2 comparison endpoints use a full local build/rebuild because the fabric topology changes.
- With caches enabled, the topology is
frontend -> I$ -> NpcMemoryFabric.instruction and backend -> D$ -> NpcMemoryFabric.data. Only main memory is cached; MMIO bypasses the cache, and line refill/writeback remain sequential AXI-Lite beats behind the existing fabric. Base FENCE conservatively treats every pred/succ combination as a full barrier: it drains D$ before later dispatch but leaves I$ and prefetched instructions intact. FENCE.I additionally invalidates I$ and discards younger buffered fetches before commit. When the unified L2 Config is selected, maintenance is strictly D$ -> L2 -> AXI4-Full memory. FPGA mtestexit must wait for the same drain, snapshot cache telemetry in the always-on mailbox, and only then reset the core; local self-difftest must consume architectural commit-store events rather than physical DPI writebacks.
- Treat
npc/chisel/ip-interface/ as the stable Chisel-only IP boundary. Its compact layout is scala/, resources/, test/, and sources/; Scala and test files sit directly in their respective roots, while resources/npc/ip/... remains the BlackBox classpath hierarchy. Do not reintroduce redundant src/, main/, or package-path wrappers. Keep ISA decode and operation mapping in rv-core and Diplomacy nodes plus address maps in ysyxSoC. Keep board providers and physical integration under npc/fpga/{common,u55c,zcu102}/; keep Xilinx adapters and generation Tcl under npc/fpga-ip-generator/, with generated XCI only in a construction's fpga/ip-generated/.
- Every NPC/SoC elaboration must emit
ip-sources.manifest. Simulation manifests may contain MODEL= evidence for embedded DPI/peripheral models but no XCI=; synthesis manifests may contain only RTL=/XCI= and must reject DPI, NEMU MMIO, fault sinks, and simulation peripherals. Verilator, construction freezing, and Vivado Tcl consume these manifests instead of recursively collecting ysyxSoC/perip/ or FPGA source trees.
Commit in Reviewable Slices
- Inspect the root worktree and affected submodules before editing, and identify independent commit boundaries for the task.
- Keep each commit to one coherent behavior change plus the tests and documentation required to verify it. Do not combine unrelated Config, NEMU, FPGA, memory, report, or cleanup work merely because they belong to one long-running task or already share a dirty worktree.
- After an independent slice passes its narrow regression, commit it immediately when the user has authorized commits. Without that authorization, report the ready commit boundary and ask before committing. Do not split work into commits that are knowingly uncompilable, untestable, or incomplete.
- Review the staged diff before every commit. Exclude construction caches, generated artifacts,
log/, failed-build evidence, and unrelated user changes unless they are explicitly part of that slice.
- Commit submodule changes inside the submodule first. When push is explicitly authorized, push those commits before committing and pushing the root repository's gitlink update. Authorization to commit does not by itself authorize a push.
- When the user requests Codex attribution, preserve the requested
Co-authored-by trailer on every applicable commit, not only the final commit in a series.
Verify Proportionally
For Config or construction changes, run the catalog and the narrowest relevant checks first:
make -C npc config-list
make -C npc version
cd npc && sbt "root/test"
cd npc/chisel/ysyxSoC && mill -i ysyxsoc.compile
Run mill -i ysyxsocTest.test when altering the SoC graph. Run construction or FPGA dry-run regressions when changing lifecycle, profile, board, AXI, or artifact logic. Do not start a full Vivado/Vitis implementation or real-board test unless the user specifically requests it.
Keep This Skill Current
Treat this skill as part of the runtime-layer contract. Before finishing any change that affects one of the following, compare the resulting source behavior with this file and update this file in the same task when the instructions, paths, command examples, or invariants have changed:
- public Make targets, arguments, defaults, or rejected legacy interfaces;
- Config discovery, terminal traits, CDE composition, names, scopes, or host traits;
- construction directory layout, version selection, rebuild/host-build behavior, atomic replacement, or validation;
- NEMU host configuration, FPGA board execution, mailbox/asset ABI, or generated-profile consumption;
- NPC/SoC memory routing, AXI topology, bus-width semantics, or where DPI/board memory is selected.
Read the affected implementation and public README first; update this skill only with durable workflow knowledge, not transient logs, one-off failures, generated catalog rows, or individual construction IDs. Run the skill validator after changing this file:
"${PYTHON_WITH_YAML:-$HOME/chipyard/.conda-env/bin/python3.10}" \
/home/pyx/.codex/skills/.system/skill-creator/scripts/quick_validate.py \
"$PWD/.codex/skills/ysyx-config-build"