mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
Extend the chapter 3 memory-swap documentation to GF180: hp-platform.md adds the tiling table (8-bit macro stacking with registered read muxes), notes the repo-owned functional models versus the vendor collateral in the locked PDK, and documents the SKY130 byte-mask blocker as the reason that PDK stays behavioral; hp-rv64-validation.md records the directed-TB, MEM_INTF, boot-testbench, and SoC macro-sim evidence; the two READMEs generalize the override wording to IHP130/ICS55/GF180. Physical qualification (Liberty registration, STA, LEC) stays explicitly deferred.
311 lines
18 KiB
Markdown
311 lines
18 KiB
Markdown
# HP RV64 Operating-System Platform
|
|
|
|
## Approved migration contract
|
|
|
|
The RV64 migration approved on 2026-09-25 extends the existing HP platform in
|
|
the phases below. These are requirements, not claims of completed validation.
|
|
LP remains the RV32 Hazard3 management hart (hart 0). HP is hart 1, a T-Head
|
|
OpenC906 core from [XUANTIE-RV/openc906](https://github.com/XUANTIE-RV/openc906)
|
|
(Apache-2.0), locked in `dependencies/dependencies.lock.json` and integrated
|
|
from its pre-generated `C906_RTL_FACTORY/gen_rtl` DEFAULT configuration:
|
|
RV64GC (RV64IMAFDC plus Zicsr and Zifencei) with M/S/U modes and Sv39,
|
|
32 KiB instruction and data caches with 64-byte lines, an eight-region PMP,
|
|
and a 16K-entry BHT. The earlier VexiiRiscv-based RV64 integration is
|
|
superseded; its validation evidence is retained only as historical in
|
|
[HP RV64 validation](../hp-rv64-validation.md). VexiiRiscv remains in the
|
|
repository solely as the frozen Std-series generator asset
|
|
(`scripts/vexiiriscv/GenerateRetroSocStd.scala`, driven by
|
|
`make std-vexii-generate`); Mini no longer consumes it and Mini profiles have
|
|
no `HP_CONFIG` selector.
|
|
|
|
The C906 drives 40-bit addresses; Mini physical addresses remain 32 bits and
|
|
the reset vector remains `0x38000000`. The core exposes a single 128-bit AXI4
|
|
master (8-bit IDs, `axim_clk_en` tied high for 1:1 clocking) that a
|
|
serializing `axi4_downsizer_128to64` and `axi4_mmio_demux` split into HP
|
|
data-fabric master slot 0 and the MMIO window `0x02000000-0x2FFFFFFF`; the
|
|
former separate I-cache/D-cache/MMIO port structure and crossbar master slot 1
|
|
are retired (slot 1 is tied idle, ID-prefix map preserved). MMIO continues
|
|
through the existing 64-to-32 downsizer/gate/CDC chain into the AXI32/APB32
|
|
control plane. Software accesses peripheral registers as 32-bit words,
|
|
including the two halves of CLINT timer registers. No new CDC or
|
|
hardware coherency is introduced. LP retains SYSCTRL and terminal-status
|
|
ownership, DMA channel 6, SDRAM initialization, and HP release control.
|
|
|
|
OpenC906 implements no Zicbom, Zicntr, or Zihpm; cache maintenance uses the
|
|
T-Head custom-0 `dcache.cva`/`dcache.iva` instructions. Debug uses the C906
|
|
internal Debug Module behind the external JTAG DTM (`tdt_dmi_top`).
|
|
OpenC906 hardwires `mhartid=0` upstream; retroSoC substitutes the reviewed
|
|
override `rtl/mini/ip_overrides/aq_sysio_kid.v` (only change:
|
|
`sysio_core_hartid = 3'd1`) during build-time filelist generation through
|
|
`scripts/generate_openc906.py`, which guards the pinned upstream sha256. A
|
|
second reviewed override, `rtl/mini/ip_overrides/sysmap.h`, replaces the
|
|
upstream default sysmap region table (which targets a 40-bit reference map
|
|
and would mark the Mini peripheral window cacheable/bufferable) with the Mini
|
|
address map: the MMIO window `0x02000000`-`0x2FFFFFFF` — including the
|
|
core-internal CLINT/PLIC window — is strong-order/non-cacheable device memory
|
|
as the OpenC906 user manual requires; SRAM/SDRAM/PSRAM/OPI and the flash/XIP
|
|
windows stay cacheable. The vendored checkout is never modified.
|
|
|
|
The OpenC906 integration manual chapter 3 memory swap is implemented for
|
|
simulation: the eight C906 single-port SRAM wrappers have reviewed overrides
|
|
in `rtl/mini/ip_overrides/aq_spsram_*.v`. With `PDK_IHP130` +
|
|
`HAVE_SRAM_MACRO` and without `PDK_BEHAV` each wrapper instantiates IHP130
|
|
`RM_IHPSG13_1P_*` macros (BIST pins tied off, `A_DLY=1`), stacked per manual
|
|
section 3.1.5:
|
|
|
|
| Wrapper | Macro combination | Stacking |
|
|
| --- | --- | --- |
|
|
| `aq_spsram_1024x16` (BHT) | 1x `RM_IHPSG13_1P_1024x32_c2_bm_bist` | low 16 bits used |
|
|
| `aq_spsram_2048x32` (ICache data) | 2x `RM_IHPSG13_1P_1024x32_c2_bm_bist` | depth, `A[10]` chip-select |
|
|
| `aq_spsram_256x59` (ICache tag) | 4x `RM_IHPSG13_1P_64x64_c2_bm_bist` | depth, `A[7:6]` chip-select |
|
|
| `aq_spsram_1024x64` (DCache data) | 2x `RM_IHPSG13_1P_1024x32_c2_bm_bist` | width, low/high 32 bits |
|
|
| `aq_spsram_128x8` (DCache dirty) | 2x `RM_IHPSG13_1P_64x64_c2_bm_bist` | depth, `A[6]` chip-select |
|
|
| `aq_spsram_64x58` (DCache tag) | 1x `RM_IHPSG13_1P_64x64_c2_bm_bist` | low 58 bits used |
|
|
| `aq_spsram_64x88` (JTLB data) | 2x `RM_IHPSG13_1P_64x64_c2_bm_bist` | width, low 64 + high 24 bits |
|
|
| `aq_spsram_64x98` (JTLB tag) | 2x `RM_IHPSG13_1P_64x64_c2_bm_bist` | width, low 64 + high 34 bits |
|
|
|
|
Depth stacks register the bank select on read transactions and mux the bank
|
|
outputs one cycle later (manual section 3.1.4 timing); unused upper
|
|
write-mask bits are tied off so unimplemented bits are never written.
|
|
|
|
With `PDK_ICS55` + `HAVE_SRAM_MACRO` and without `PDK_BEHAV`, each wrapper
|
|
instead instantiates its exact-geometry ICS55 OpenECOS macro
|
|
(`ics55_ecos_sram_1024x16_m8`, `_2048x32_m8`, `_256x59_m4`, `_1024x64_m8`,
|
|
`_128x8_m8`, `_64x58_m4`, `_64x88_m4`, `_64x98_m4`), materialized by
|
|
`make setup-pdk` from the locked `openecos-projects/ics55_ecos_sram` release
|
|
assets (`dependencies.lock.json` `pdk_ics55_sram_<geom>` entries). The macro
|
|
interface matches the wrapper polarity exactly (`CEB`/`GWEB`/per-bit `WEB`
|
|
are active-low at identical widths), so the replacement is a direct
|
|
connection with no inversion, padding, or stacking; `MARE`/`MAR` are tied
|
|
off as in `tc_sram.sv`.
|
|
|
|
With `PDK_GF180` + `HAVE_SRAM_MACRO` and without `PDK_BEHAV`, each wrapper is
|
|
tiled from the GF180 8-bit bit-write macros
|
|
(`gf180mcu_fd_ip_sram__sram{64,128,256,512}x8m8wm1`; active-low
|
|
`CEN`/`GWEN`/per-bit `WEN` match the wrapper polarity). The vendor verilog
|
|
views are timing-only, so the simulation models are repo-owned in
|
|
`rtl/tech/gf180_sram_sim_cells.sv` (the 512x8 SoC model plus the
|
|
64/128/256x8 tiles):
|
|
|
|
| Wrapper | Tile | Tiling |
|
|
| --- | --- | --- |
|
|
| `aq_spsram_1024x16` (BHT) | 512x8 | depth 2 (`A[9]`) x width 2 |
|
|
| `aq_spsram_2048x32` (ICache data) | 512x8 | depth 4 (`A[10:9]`) x width 4 |
|
|
| `aq_spsram_256x59` (ICache tag) | 256x8 | width 8; top tile's upper 5 bits tied inactive |
|
|
| `aq_spsram_1024x64` (DCache data) | 512x8 | depth 2 (`A[9]`) x width 8 |
|
|
| `aq_spsram_128x8` (DCache dirty) | 128x8 | exact, single tile |
|
|
| `aq_spsram_64x58` (DCache tag) | 64x8 | width 8; top tile's upper 6 bits tied inactive |
|
|
| `aq_spsram_64x88` (JTLB data) | 64x8 | width 11, exact |
|
|
| `aq_spsram_64x98` (JTLB tag) | 64x8 | width 13; top tile's upper 6 bits tied inactive |
|
|
|
|
Depth stacks register the bank select on read transactions and mux the tile
|
|
outputs, like the IHP130 stacks. SKY130 stays on the behavioral path: the
|
|
locked OpenRAM SRAM (`sky130_sram_4kbyte_1rw_32x1024_8`) offers only a
|
|
byte-granular write mask (`wmask0[3:0]` per 32-bit word) while the C906
|
|
wrappers require per-bit write enable, so no SKY130 SRAM macro can serve
|
|
them.
|
|
|
|
Every other configuration — including the committed `PDK_BEHAV=YES` CI
|
|
profiles — compiles the upstream behavioral `aq_f_spsram_*` instance
|
|
byte-identically.
|
|
|
|
The chapter 3 ICG swap is implemented alongside: `gated_clk_cell.v` (the 216
|
|
CPU clock gates), `tdt_gated_clk_cell.v` (the debug module gate), and
|
|
`BUFGCE.v` (the PLIC/CLINT divide-by-2 gate in `aq_mp_clk_top.v`) have
|
|
reviewed overrides in `rtl/mini/ip_overrides/`. With a PDK define and without
|
|
`PDK_BEHAV` — no `HAVE_SRAM_MACRO` knob, the ICG is a base cell — each
|
|
override instantiates the process clock-gating cell:
|
|
|
|
| PDK | ICG cell | Enable/scan mapping |
|
|
| --- | --- | --- |
|
|
| IHP130 | `sg13g2_slgcp_1` | `GATE`=enable, `SCE`=scan enable |
|
|
| ICS55 | `ICGX1H7R` | no test-enable pin: scan enable ORed into `E` |
|
|
| SKY130 | `sky130_fd_sc_hd__sdlclkp_1` | `GATE`=enable, `SCE`=scan enable |
|
|
| GF180 | `gf180mcu_fd_sc_mcu7t5v0__icgtp_1` | `E`=enable, `TE`=scan enable |
|
|
|
|
`BUFGCE` has no scan enable upstream, so SCE/TE tie off there. The GF180
|
|
vendor model cannot elaborate (its UDP latch primitive is not shipped in the
|
|
locked checkout), so its simulation model is repo-owned in
|
|
`rtl/tech/gf180_seq_sim_cells.v`, following the existing `dffq` precedent.
|
|
Because two-state simulators only apply an async-reset flop's reset value on
|
|
a real reset edge, `hp_core_wrapper` asserts `pad_yy_icg_scan_en`/
|
|
`pad_tdt_icg_scan_en` while the core/DTM is held in reset, keeping the gated
|
|
clocks transparent so flops behind closed gates initialize (the DTM sleeps at
|
|
boot and would otherwise hold `hartreset_n` low forever). `PDK_BEHAV` and
|
|
PDK-less builds keep the upstream defaults byte-identical (pass-through for
|
|
the two `*_gated_clk_cell`, the behavioral latch gate for `BUFGCE`), and
|
|
pass-through ignores the scan-enable input entirely.
|
|
Deferred this phase: low-power support
|
|
(`core0_pad_lpmd_b` unconnected), DFT (scan/mbist tied off), the debug SBA AXI
|
|
master (unconnected),
|
|
physical/LEC qualification of the macro and ICG paths (synthesis mapping,
|
|
STA), and
|
|
HP Linux re-qualification timing/performance evidence.
|
|
|
|
### Boot bundle V2
|
|
|
|
The little-endian header remains 128 bytes at flash offset `0x00100000`, with
|
|
four 24-byte entry slots and CRC32/ISO-HDLC protection. Version is 2. Header
|
|
word 7 identifies workload: 1 Linux, 2 GA2D smoke, 3 RT-Thread. Linux has four
|
|
entries (types 1 OpenSBI, 2 DTB, 3 Linux Image, 4 uncompressed CPIO), retaining
|
|
the established addresses and limits. Smoke and RT-Thread have one executable
|
|
entry of type 5, at `0x38000000`, at most 512 KiB; unused entries are zero.
|
|
Version 1, unknown workloads, incorrect entry counts/types/addresses, empty
|
|
payloads, overlaps, out-of-range sizes, and bad CRCs are rejected before HP
|
|
release. Build manifests record RV64, workload, sources and artifact hashes;
|
|
builders verify executable ELF class and RISC-V machine identity.
|
|
|
|
### Software acceptance protocol
|
|
|
|
Linux publishes event 1, argument `0x4c4e5801`, sequence 1 only after its
|
|
userspace acceptance succeeds. On a software failure it publishes event 3
|
|
with a nonzero error code. LP prints `HP_LINUX_READY` and terminates on Linux
|
|
success without entering the GA2D protocol.
|
|
|
|
RT-Thread publishes ready event 1, argument `0x52545401`, sequence 1 after
|
|
enabling the mailbox-doorbell PLIC ID (18) in the machine context. LP sends
|
|
command `0x52545402`,
|
|
argument `0x12345678`, sequence 1. Its ISR clears the HP mailbox source and
|
|
completes the PLIC claim; the test thread verifies the received message. Once
|
|
all tests pass, HP publishes event 2, argument `0x52545401`, sequence 2.
|
|
Event 3 reports a nonzero failure code at sequence 1 or 2. LP alone writes
|
|
SYSCTRL TEST_STATUS and prints `HP_RTTHREAD_PASS` on success. Publication is
|
|
code, argument, sequence, `fence iorw, iorw`, then doorbell. No shared cached
|
|
memory is used by this test protocol. Smoke retains the GA2D and cache-clean
|
|
handshake documented by its existing payload.
|
|
|
|
RT-Thread uses the official v5.3.0 commit
|
|
`99428a1e7f7447955aa860f7c969273a12095b8f` without vendor source modifications.
|
|
The BSP uses the common RISC-V M-mode port, static threads and IPC objects,
|
|
1000 Hz ticks, UART1, the internal CLINT MSIP/MTIMECMP pair, and the internal
|
|
PLIC plus the mailbox.
|
|
The first test image covers integer RV64 computation/context, preemption,
|
|
semaphore and message queue behavior, timeouts, and external mailbox IRQ.
|
|
RT-Smart, networking, filesystems, and floating-point task qualification are
|
|
outside this phase; hardware F/D support remains enabled.
|
|
|
|
Linux uses RV64 OpenSBI FW_JUMP, Sv39, and a static minimal BusyBox userspace.
|
|
The DT reserves `0x38000000..0x3807ffff` with `no-map` for resident OpenSBI;
|
|
Linux must never allocate or directly map that firmware window.
|
|
Its dedicated `/init` explicitly mounts devtmpfs, procfs, sysfs and tmpfs,
|
|
checks device nodes, file round trips and child execution, and reports through
|
|
the mailbox. Initial CPIO includes `/dev/console`. Effective kernel config,
|
|
not merely its fragment, must enable the required executable, console,
|
|
memory-management, filesystem and /dev/mem options. The acceptance CPIO is
|
|
uncompressed and does not run the full Buildroot services sequence.
|
|
|
|
### Development order and verification
|
|
|
|
#### Phase 2 - RV64 HP core and platform migration
|
|
|
|
Originally executed against a generated VexiiRiscv core; that integration is
|
|
superseded by the OpenC906 swap and its evidence is historical. The current
|
|
phase integrates the locked OpenC906 DEFAULT configuration, all PRODUCT
|
|
profiles, manifests and core reports. Use separate RV32 LP and RV64 HP tools.
|
|
Validate the 128-to-64 serializing downsizer, the MMIO demux, narrow MMIO
|
|
lanes, 64-bit memory accesses, and the migrated GA2D/cache-lifecycle smoke in
|
|
IHP130 Verilator.
|
|
|
|
#### Phase 3 - RT-Thread dependency, BSP and acceptance
|
|
|
|
Lock sources and build tools, add the self-owned BSP and V2 loader/packager,
|
|
and run `hp-rtthread-sim` from its committed IHP130 profile. All individual
|
|
test markers, `HP_RTTHREAD_PASS`, and `SIM_TEST_PASS code=0` are required.
|
|
Negative bundle and mailbox tests must demonstrate fail-closed behavior.
|
|
|
|
#### Phase 4 - RV64 Linux minimal-initramfs acceptance
|
|
|
|
Migrate OpenSBI, Linux, Buildroot and DTB together, verify effective configs,
|
|
then run real SoC `hp-linux-sim`. Required markers include Linux userspace
|
|
checks, `retroSoC HP Linux ready`, `HP_LINUX_READY`, and `SIM_TEST_PASS code=0`.
|
|
Unexpected console corruption remains a failure requiring diagnosis.
|
|
|
|
#### Phase 5 - Documentation and delivery evidence
|
|
|
|
Update architecture, guides and publication source bindings. Preserve prior
|
|
RV32 and pre-swap VexiiRiscv evidence as historical. Each workload writes
|
|
separate run logs and
|
|
structured results; an interrupted or ongoing run cannot reuse an old pass.
|
|
Run affected host/Python/C/RTL checks and IHP130 behavioral regressions.
|
|
Synthesis, netlist simulation, STA, and synthesis-dependent metrics are
|
|
explicitly deferred by user instruction, as are CDC/RDC/physical signoff and
|
|
commercial qualification. No PPA claim is made. The SRAM macro swap is no
|
|
longer deferred at simulation level: the `aq_spsram_*` overrides described
|
|
above run the IHP130 macro path in the focused boot testbench (see
|
|
[HP RV64 Validation](../hp-rv64-validation.md)); physical macro integration
|
|
remains deferred.
|
|
|
|
Reference boundaries: [RT-Thread v5.3.0](https://github.com/RT-Thread/rt-thread/releases/tag/v5.3.0)
|
|
supplies the OS/CPU port; the repository owns board integration. The C906
|
|
internal CLINT/PLIC (the `thead,c900-clint`/`thead,c900-plic` device-tree
|
|
bindings) and the locked OpenSBI platform supply the interrupt and supervisor
|
|
boot patterns; no third-party board register map is imported.
|
|
|
|
The LP/HP profile adds a bidirectional mailbox at `0x10019000` as a
|
|
self-owned APB4 peripheral. Its role in boot and lifecycle control is defined
|
|
by [LP/HP Architecture](../lp-hp-architecture.md).
|
|
|
|
## Interrupt and timer architecture
|
|
|
|
The former SoC-level HP ACLINT at `0x02000000` and HP PLIC at `0x0C000000`
|
|
are removed from the HP path; their self-owned RTL sources remain in the
|
|
repository but are no longer instantiated. Interrupt and timer delivery now
|
|
uses the CLINT and PLIC internal to the C906, which follow the T-Head c900
|
|
register layouts and are decoded inside the core BIU at the 128 MiB-aligned
|
|
window base `0x08000000`. That window never reaches the SoC fabric;
|
|
`rtl/mini/address_map/memory_map.json` reserves it as `HP_C906_SYS`:
|
|
|
|
| Address | Function |
|
|
| --- | --- |
|
|
| `0x08000000` | internal PLIC (`thead,c900-plic`) |
|
|
| `0x0C000000` | internal CLINT (`thead,c900-clint`): MSIP at +`0x0`, MTIMECMP at +`0x4000`, SSIP at +`0xC000`, STIMECMP at +`0xD000` |
|
|
|
|
The CLINT at `0x10020000` remains the LP/global CLINT and the mtime source.
|
|
Its mtime is delivered to the C906 through `pad_cpu_sys_cnt`; HP software
|
|
reads the `time` CSR and has no memory-mapped mtime.
|
|
|
|
SoC interrupt source numbers are unchanged at the boundary: source 1 is
|
|
UART1, source 2 is the HP-side mailbox doorbell, source 3 is EXT-H, and
|
|
sources 4 through 12 are central DMA, USB2, SDIO0, SDIO1, SPI-SD, JPEG, APU,
|
|
GA2D, and the NPU shell respectively. Sources 13 and above are reserved and
|
|
tied low. Resource-owned sources are suppressed unless HP is the exclusive
|
|
owner. The C906 maps external input *i* to PLIC ID *i*+16, so software claims
|
|
these sources as PLIC IDs 17 through 28; IDs 0-15 are reserved/internal.
|
|
LP-to-HP notification is exclusively the mailbox doorbell (PLIC ID 18); the
|
|
former LP-writes-HP-MSIP path no longer exists.
|
|
|
|
## Mailbox
|
|
|
|
LP writes the `LP_*` bank and rings `LP_DOORBELL`, which sets the HP interrupt
|
|
state. HP writes the `HP_*` bank and rings `HP_DOORBELL`, which sets the LP
|
|
interrupt state. State is sticky W1C and is qualified by a separate enable for
|
|
each destination.
|
|
|
|
| Offset | Register | Access | Purpose |
|
|
| --- | --- | --- | --- |
|
|
| `0x000` | `IP_VERSION` | RO | `0x00010000` |
|
|
| `0x004` | `CAPABILITY` | RO | `0x00000007` |
|
|
| `0x010` | `LP_COMMAND` | RW | LP-to-HP message code |
|
|
| `0x014` | `LP_ARG0` | RW | LP-to-HP argument |
|
|
| `0x018` | `LP_SEQUENCE` | RW | LP publication sequence; zero means none |
|
|
| `0x01C` | `LP_DOORBELL` | WO | Set HP interrupt state |
|
|
| `0x020` | `HP_EVENT` | RW | HP-to-LP event code |
|
|
| `0x024` | `HP_ARG0` | RW | HP-to-LP argument |
|
|
| `0x028` | `HP_SEQUENCE` | RW | HP publication sequence; zero means none |
|
|
| `0x02C` | `HP_DOORBELL` | WO | Set LP interrupt state |
|
|
| `0x030`/`0x034`/`0x038`/`0x03C` | LP interrupt state/enable/status/test | mixed | LP destination IRQ control |
|
|
| `0x040`/`0x044`/`0x048`/`0x04C` | HP interrupt state/enable/status/test | mixed | HP destination IRQ control |
|
|
|
|
The publication order is code, argument, sequence, memory fence, then
|
|
doorbell. `<retrosoc/hal/hp_mailbox.h>` supplies the LP-side API. The initial
|
|
Linux userspace acceptance script reports event 1, argument `0x4C4E5801`, and
|
|
sequence 1 after init; this is a bring-up verdict, not a general Linux mailbox
|
|
driver ABI.
|
|
|
|
`tests/rtl/hp_mailbox_tb.sv` covers mailbox register and interrupt behavior.
|
|
`tests/rtl/plic_tb.sv` covers the retained self-owned PLIC RTL, which is no
|
|
longer part of the HP interrupt path. `tests/test_hp_boot_bundle.py` enforces
|
|
the handwritten mailbox RTL/C offset parity. Production work still requires a
|
|
Linux mailbox driver, concurrent sequence/wrap policy, malformed-message
|
|
tests, lifecycle timeouts, and fault-injection coverage.
|