mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: refactor user extension handling and update MPW generation
- Updated README.md to clarify the status of KianV RV32IMA and PicoRV32 in the user-extension map. - Modified Makefile to include USER_EXTENSIONS_SOURCE in MPW variant stamp dependencies. - Enhanced integration README.md to better describe the relationship between user_extensions.json and mpw.toml. - Updated generate_user_extensions.py to include design_id in ExtensionTarget and enforce unique design IDs. - Changed user_extensions.json schema version to 2 and added design_id fields for core and IP targets. - Refactored generate_mpw.py to support the new manifest structure and validate design selections. - Adjusted sysctrl_tb.sv test cases to reflect changes in user core reset states. - Enhanced test_opipsram.py to utilize ccache for improved compilation performance. - Updated test_script_tools.py to include new tests for active manifest generation. - Modified test_user_extensions.py to validate isolated scalar bindings and reject duplicate design selections.
This commit is contained in:
23 files changed
+1058
-2979
No files matched your search
@@ -19,8 +19,8 @@ under the [Mulan Permissive Software License, Version 2](LICENSE).
|
||||
## Highlights
|
||||
|
||||
- A fixed Hazard3 management core with a permanent JTAG Debug Module, plus
|
||||
software-selected user-core and user-IP extension slots, including PicoRV32
|
||||
at user-core slot C5.
|
||||
software-selected user-core and user-IP extension slots. The active user
|
||||
cores are KianV RV32I, SERV, FemtoRV32, and DarkRISCV at slots C0-C3.
|
||||
- A documented [Tiny/Mini/Std/Pro product direction](docs/soc-family-positioning.md)
|
||||
anchored by Mini and a trusted Hazard3 management model. The higher Linux,
|
||||
graphics, AI, and RV64 configurations are roadmap targets, not supported
|
||||
@@ -67,8 +67,7 @@ under the [Mulan Permissive Software License, Version 2](LICENSE).
|
||||
The committed profiles are the supported starting points. They select an ISA,
|
||||
PDK, application, linker layout, and optional features as one reproducible
|
||||
configuration. The management core is fixed to Hazard3. The user-extension
|
||||
fabric exposes stable C0-C5 user-core slots and software selects one active
|
||||
user core.
|
||||
fabric exposes C0-C3 user-core slots and software selects one active user core.
|
||||
|
||||
| Profile | ISA | Application | Coverage |
|
||||
| --- | --- | --- | --- |
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
This directory contains committed Make configuration profiles. Each profile
|
||||
selects SoC, PDK, ISA, CSR support, application, linker layout, and the
|
||||
supported validation tier. The management core is fixed to Hazard3 with its
|
||||
JTAG Debug Module enabled. The user-extension fabric exposes stable C0-C5
|
||||
slots, with PicoRV32 at C5.
|
||||
JTAG Debug Module enabled. The user-extension fabric exposes C0-C3 slots for
|
||||
KianV RV32I, SERV, FemtoRV32, and DarkRISCV.
|
||||
|
||||
`ci/` contains pull-request profiles, `cluster/` contains configurations
|
||||
requiring site tools or PDKs, and `benchmark/` contains fixed-workload baseline
|
||||
|
||||
@@ -13,8 +13,8 @@ a second SoC bus master. Debugger memory operations execute through the halted
|
||||
hart and remain subject to the AXI4 interconnect access policy. User cores,
|
||||
peripherals, clocks, and pad control stay outside the debug-reset scope.
|
||||
|
||||
PicoRV32 is available as software-selected user core C5 through mini-ver-mpw;
|
||||
it is not a management-core option and has no management Debug Module.
|
||||
The C0-C3 user cores are software-selected through mini-ver-mpw. They are not
|
||||
management-core options and do not have a management Debug Module.
|
||||
|
||||
## Reset And Clocking
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ digraph mini_soc_block_diagram {
|
||||
];
|
||||
user_core [
|
||||
fillcolor="#DDF2E3",
|
||||
label="Selected user core\nC0-C5, one active\nPicoRV32 at C5"
|
||||
label="Selected user core\nC0-C3, one active\nKianV / SERV / FemtoRV32 / DarkRISCV"
|
||||
];
|
||||
dma [
|
||||
fillcolor="#DDF2E3",
|
||||
|
||||
@@ -225,9 +225,9 @@
|
||||
<!-- debug_module->timers -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>debug_module->timers</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M2557.3,-671.05C2509.22,-665.15 2455,-658.48 2455,-658.48 2455,-658.48 1325,-581.98 1325,-581.98 1325,-581.98 1325,-581.98 1325,-356 1325,-356 1320,-289 1320,-289 1320,-289 991,-266 991,-266 991,-266 984.42,-264.48 974.38,-262.17"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M2557.3,-671.05C2509.22,-665.15 2455,-658.48 2455,-658.48 2455,-658.48 1389,-581.98 1389,-581.98 1389,-581.98 1389,-581.98 1389,-356 1389,-356 1384,-289 1384,-289 1384,-289 991,-266 991,-266 991,-266 984.42,-264.48 974.38,-262.17"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="974.69,-259.72 967.32,-260.54 973.59,-264.5 974.69,-259.72"/>
|
||||
<text text-anchor="middle" x="1336" y="-464.84" font-family="Arial" font-size="8.00" fill="#374151">halted</text>
|
||||
<text text-anchor="middle" x="1400" y="-464.84" font-family="Arial" font-size="8.00" fill="#374151">halted</text>
|
||||
</g>
|
||||
<!-- mgmt_adapter->fabric -->
|
||||
<g id="edge10" class="edge">
|
||||
@@ -239,32 +239,32 @@
|
||||
<!-- user_core -->
|
||||
<g id="node13" class="node">
|
||||
<title>user_core</title>
|
||||
<path fill="#ddf2e3" stroke="#4b5563" stroke-width="1.1" d="M2847,-603.48C2847,-603.48 2771,-603.48 2771,-603.48 2765,-603.48 2759,-597.48 2759,-591.48 2759,-591.48 2759,-570.48 2759,-570.48 2759,-564.48 2765,-558.48 2771,-558.48 2771,-558.48 2847,-558.48 2847,-558.48 2853,-558.48 2859,-564.48 2859,-570.48 2859,-570.48 2859,-591.48 2859,-591.48 2859,-597.48 2853,-603.48 2847,-603.48"/>
|
||||
<text text-anchor="middle" x="2809" y="-589.48" font-family="Arial" font-size="10.00" fill="#111827">Selected user core</text>
|
||||
<text text-anchor="middle" x="2809" y="-578.48" font-family="Arial" font-size="10.00" fill="#111827">C0-C5, one active</text>
|
||||
<text text-anchor="middle" x="2809" y="-567.48" font-family="Arial" font-size="10.00" fill="#111827">PicoRV32 at C5</text>
|
||||
<path fill="#ddf2e3" stroke="#4b5563" stroke-width="1.1" d="M2847.5,-603.48C2847.5,-603.48 2668.5,-603.48 2668.5,-603.48 2662.5,-603.48 2656.5,-597.48 2656.5,-591.48 2656.5,-591.48 2656.5,-570.48 2656.5,-570.48 2656.5,-564.48 2662.5,-558.48 2668.5,-558.48 2668.5,-558.48 2847.5,-558.48 2847.5,-558.48 2853.5,-558.48 2859.5,-564.48 2859.5,-570.48 2859.5,-570.48 2859.5,-591.48 2859.5,-591.48 2859.5,-597.48 2853.5,-603.48 2847.5,-603.48"/>
|
||||
<text text-anchor="middle" x="2758" y="-589.48" font-family="Arial" font-size="10.00" fill="#111827">Selected user core</text>
|
||||
<text text-anchor="middle" x="2758" y="-578.48" font-family="Arial" font-size="10.00" fill="#111827">C0-C3, one active</text>
|
||||
<text text-anchor="middle" x="2758" y="-567.48" font-family="Arial" font-size="10.00" fill="#111827">KianV / SERV / FemtoRV32 / DarkRISCV</text>
|
||||
</g>
|
||||
<!-- user_core->fabric -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>user_core->fabric</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M2801.48,-558.34C2796.79,-544.85 2790.6,-527.03 2784.95,-510.75"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2787.17,-509.7 2782.56,-503.89 2782.54,-511.31 2787.17,-509.7"/>
|
||||
<text text-anchor="middle" x="2801" y="-529.08" font-family="Arial" font-size="8.00" fill="#374151">AXI4</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M2760.31,-558.34C2761.74,-544.97 2763.63,-527.34 2765.35,-511.19"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2767.83,-511.11 2766.14,-503.89 2762.95,-510.59 2767.83,-511.11"/>
|
||||
<text text-anchor="middle" x="2772" y="-529.08" font-family="Arial" font-size="8.00" fill="#374151">AXI4</text>
|
||||
</g>
|
||||
<!-- dma -->
|
||||
<g id="node14" class="node">
|
||||
<title>dma</title>
|
||||
<path fill="#ddf2e3" stroke="#4b5563" stroke-width="1.1" d="M1851,-603.48C1851,-603.48 1703,-603.48 1703,-603.48 1697,-603.48 1691,-597.48 1691,-591.48 1691,-591.48 1691,-570.48 1691,-570.48 1691,-564.48 1697,-558.48 1703,-558.48 1703,-558.48 1851,-558.48 1851,-558.48 1857,-558.48 1863,-564.48 1863,-570.48 1863,-570.48 1863,-591.48 1863,-591.48 1863,-597.48 1857,-603.48 1851,-603.48"/>
|
||||
<text text-anchor="middle" x="1777" y="-589.48" font-family="Arial" font-size="10.00" fill="#111827">DMA</text>
|
||||
<text text-anchor="middle" x="1777" y="-578.48" font-family="Arial" font-size="10.00" fill="#111827">4-channel native AXI4 burst master</text>
|
||||
<text text-anchor="middle" x="1777" y="-567.48" font-family="Arial" font-size="10.00" fill="#111827">APB4 target, AXI4-Stream, IRQ20</text>
|
||||
<path fill="#ddf2e3" stroke="#4b5563" stroke-width="1.1" d="M1898,-603.48C1898,-603.48 1750,-603.48 1750,-603.48 1744,-603.48 1738,-597.48 1738,-591.48 1738,-591.48 1738,-570.48 1738,-570.48 1738,-564.48 1744,-558.48 1750,-558.48 1750,-558.48 1898,-558.48 1898,-558.48 1904,-558.48 1910,-564.48 1910,-570.48 1910,-570.48 1910,-591.48 1910,-591.48 1910,-597.48 1904,-603.48 1898,-603.48"/>
|
||||
<text text-anchor="middle" x="1824" y="-589.48" font-family="Arial" font-size="10.00" fill="#111827">DMA</text>
|
||||
<text text-anchor="middle" x="1824" y="-578.48" font-family="Arial" font-size="10.00" fill="#111827">4-channel native AXI4 burst master</text>
|
||||
<text text-anchor="middle" x="1824" y="-567.48" font-family="Arial" font-size="10.00" fill="#111827">APB4 target, AXI4-Stream, IRQ20</text>
|
||||
</g>
|
||||
<!-- dma->fabric -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>dma->fabric</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1863.39,-570.22C2028.43,-551.56 2391.09,-510.57 2604.34,-486.47"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2604.87,-488.87 2611.55,-485.65 2604.32,-484 2604.87,-488.87"/>
|
||||
<text text-anchor="middle" x="2252" y="-529.08" font-family="Arial" font-size="8.00" fill="#374151">AXI4</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1910.04,-569.78C2067.47,-551.1 2404.28,-511.14 2606.51,-487.14"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2606.99,-489.55 2613.65,-486.29 2606.41,-484.69 2606.99,-489.55"/>
|
||||
<text text-anchor="middle" x="2277" y="-529.08" font-family="Arial" font-size="8.00" fill="#374151">AXI4</text>
|
||||
</g>
|
||||
<!-- stream_io -->
|
||||
<g id="node24" class="node">
|
||||
@@ -278,8 +278,8 @@
|
||||
<!-- dma->stream_io -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>dma->stream_io</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1870.52,-575.36C2133.25,-562.37 2859,-526.48 2859,-526.48 2859,-526.48 3376,-503.48 3376,-503.48 3376,-503.48 4267,-266 4267,-266 4267,-266 4269.6,-265.28 4273.96,-264.06"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1870.13,-572.93 1863.26,-575.72 1870.37,-577.82 1870.13,-572.93"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1917.05,-575.17C2171.32,-562.03 2859,-526.48 2859,-526.48 2859,-526.48 3376,-503.48 3376,-503.48 3376,-503.48 4267,-266 4267,-266 4267,-266 4269.6,-265.28 4273.96,-264.06"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1916.88,-572.73 1910.02,-575.54 1917.14,-577.62 1916.88,-572.73"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="4274.81,-266.37 4280.9,-262.13 4273.5,-261.65 4274.81,-266.37"/>
|
||||
<text text-anchor="middle" x="3793.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">AXI4-Stream</text>
|
||||
</g>
|
||||
@@ -294,9 +294,9 @@
|
||||
<!-- dma->uart0 -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>dma->uart0</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1770.61,-558.11C1750.84,-490.44 1692,-289 1692,-289 1692,-289 1668.98,-276.49 1645.97,-263.98"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1647.14,-261.83 1639.82,-260.64 1644.8,-266.14 1647.14,-261.83"/>
|
||||
<text text-anchor="middle" x="1746.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">TX/RX data</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1813.2,-558.38C1781.67,-495.33 1692,-316 1692,-316 1692,-316 1682,-289 1682,-289 1682,-289 1661.97,-276.79 1641.72,-264.44"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1642.98,-262.34 1635.73,-260.79 1640.43,-266.52 1642.98,-262.34"/>
|
||||
<text text-anchor="middle" x="1758.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">TX/RX data</text>
|
||||
</g>
|
||||
<!-- i2c_controllers -->
|
||||
<g id="node26" class="node">
|
||||
@@ -309,9 +309,9 @@
|
||||
<!-- dma->i2c_controllers -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>dma->i2c_controllers</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1757.01,-558.11C1695.15,-490.44 1511,-289 1511,-289 1511,-289 1468.1,-275.68 1426.59,-262.79"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1427.09,-260.38 1419.68,-260.64 1425.64,-265.06 1427.09,-260.38"/>
|
||||
<text text-anchor="middle" x="1657" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">DATA_CMD / RXDATA</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1801.29,-558.27C1777.64,-535.65 1744,-503.48 1744,-503.48 1744,-503.48 1646,-407 1646,-407 1646,-407 1555,-316 1555,-316 1555,-316 1534,-289 1534,-289 1534,-289 1484.19,-275.46 1436.4,-262.48"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1436.77,-260.04 1429.37,-260.57 1435.48,-264.77 1436.77,-260.04"/>
|
||||
<text text-anchor="middle" x="1687" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">DATA_CMD / RXDATA</text>
|
||||
</g>
|
||||
<!-- ws2812 -->
|
||||
<g id="node29" class="node">
|
||||
@@ -324,9 +324,9 @@
|
||||
<!-- dma->ws2812 -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>dma->ws2812</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1777.38,-558.11C1778.54,-490.44 1782,-289 1782,-289 1782,-289 1791.31,-277.91 1801.17,-266.18"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1803.07,-267.72 1805.7,-260.79 1799.32,-264.57 1803.07,-267.72"/>
|
||||
<text text-anchor="middle" x="1807.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">TXDATA writes</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1824,-558.4C1824,-499.33 1824,-335.03 1824,-268.02"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1826.45,-267.71 1824,-260.71 1821.55,-267.71 1826.45,-267.71"/>
|
||||
<text text-anchor="middle" x="1851.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">TXDATA writes</text>
|
||||
</g>
|
||||
<!-- fault -->
|
||||
<g id="node16" class="node">
|
||||
@@ -360,16 +360,16 @@
|
||||
<!-- apb4_periph -->
|
||||
<g id="node18" class="node">
|
||||
<title>apb4_periph</title>
|
||||
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M1922.5,-375C1922.5,-375 1817.5,-375 1817.5,-375 1811.5,-375 1805.5,-369 1805.5,-363 1805.5,-363 1805.5,-351 1805.5,-351 1805.5,-345 1811.5,-339 1817.5,-339 1817.5,-339 1922.5,-339 1922.5,-339 1928.5,-339 1934.5,-345 1934.5,-351 1934.5,-351 1934.5,-363 1934.5,-363 1934.5,-369 1928.5,-375 1922.5,-375"/>
|
||||
<text text-anchor="middle" x="1870" y="-360" font-family="Arial" font-size="10.00" fill="#111827">AXI42APB</text>
|
||||
<text text-anchor="middle" x="1870" y="-349" font-family="Arial" font-size="10.00" fill="#111827">APB4 configuration plane</text>
|
||||
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M1969.5,-375C1969.5,-375 1864.5,-375 1864.5,-375 1858.5,-375 1852.5,-369 1852.5,-363 1852.5,-363 1852.5,-351 1852.5,-351 1852.5,-345 1858.5,-339 1864.5,-339 1864.5,-339 1969.5,-339 1969.5,-339 1975.5,-339 1981.5,-345 1981.5,-351 1981.5,-351 1981.5,-363 1981.5,-363 1981.5,-369 1975.5,-375 1969.5,-375"/>
|
||||
<text text-anchor="middle" x="1917" y="-360" font-family="Arial" font-size="10.00" fill="#111827">AXI42APB</text>
|
||||
<text text-anchor="middle" x="1917" y="-349" font-family="Arial" font-size="10.00" fill="#111827">APB4 configuration plane</text>
|
||||
</g>
|
||||
<!-- fabric->apb4_periph -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>fabric->apb4_periph</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M2614,-447.07C2417.16,-423.5 2086.85,-383.96 1941.89,-366.61"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1941.95,-364.15 1934.71,-365.75 1941.36,-369.01 1941.95,-364.15"/>
|
||||
<text text-anchor="middle" x="2286.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">AXI4 config</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M2616.02,-446.29C2430.51,-422.86 2126.63,-384.48 1988.89,-367.08"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1988.91,-364.61 1981.66,-366.17 1988.29,-369.47 1988.91,-364.61"/>
|
||||
<text text-anchor="middle" x="2312.5" y="-400.6" font-family="Arial" font-size="8.00" fill="#374151">AXI4 config</text>
|
||||
</g>
|
||||
<!-- apb4_system -->
|
||||
<g id="node19" class="node">
|
||||
@@ -411,16 +411,16 @@
|
||||
<!-- apb4_periph->sysctrl -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>apb4_periph->sysctrl</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1922.09,-338.92C1955.25,-328.05 1992,-316 1992,-316 1992,-316 2070,-289 2070,-289 2070,-289 2166,-266 2166,-266 2166,-266 2171.79,-264.54 2180.67,-262.3"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1957.99,-338.92C1984.08,-328.05 2013,-316 2013,-316 2013,-316 2070,-289 2070,-289 2070,-289 2166,-266 2166,-266 2166,-266 2171.79,-264.54 2180.67,-262.3"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2181.47,-264.62 2187.65,-260.54 2180.27,-259.87 2181.47,-264.62"/>
|
||||
<text text-anchor="middle" x="2080.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_periph->clint -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>apb4_periph->clint</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1805.28,-339.82C1803.2,-339.3 1802,-339 1802,-339 1802,-339 1430,-316 1430,-316 1430,-316 1329,-289 1329,-289 1329,-289 554,-266 554,-266 554,-266 549.74,-264.68 543.1,-262.62"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1852.28,-339.82C1850.2,-339.3 1849,-339 1849,-339 1849,-339 1453,-316 1453,-316 1453,-316 1392,-289 1392,-289 1392,-289 554,-266 554,-266 554,-266 549.74,-264.68 543.1,-262.62"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="543.81,-260.27 536.39,-260.54 542.35,-264.95 543.81,-260.27"/>
|
||||
<text text-anchor="middle" x="1440.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<text text-anchor="middle" x="1463.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_periph_targets -->
|
||||
<g id="node22" class="node">
|
||||
@@ -433,23 +433,23 @@
|
||||
<!-- apb4_periph->apb4_periph_targets -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>apb4_periph->apb4_periph_targets</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1894.86,-338.99C1923.38,-319.48 1970.43,-287.28 2003.43,-264.71"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2005.02,-266.59 2009.41,-260.61 2002.25,-262.54 2005.02,-266.59"/>
|
||||
<text text-anchor="middle" x="1975.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1935.03,-338.99C1955.39,-319.78 1988.78,-288.28 2012.64,-265.76"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2014.47,-267.41 2017.88,-260.82 2011.1,-263.84 2014.47,-267.41"/>
|
||||
<text text-anchor="middle" x="1996.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_periph->uart0 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>apb4_periph->uart0</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1844,-338.92C1813.78,-319.07 1768,-289 1768,-289 1768,-289 1723.05,-275.62 1679.65,-262.71"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1680.12,-260.29 1672.71,-260.64 1678.72,-264.98 1680.12,-260.29"/>
|
||||
<text text-anchor="middle" x="1816.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1883.35,-338.92C1844.24,-319.07 1785,-289 1785,-289 1785,-289 1734.71,-275.41 1686.57,-262.4"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1687.2,-260.03 1679.8,-260.57 1685.92,-264.76 1687.2,-260.03"/>
|
||||
<text text-anchor="middle" x="1845.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_periph->i2c_controllers -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>apb4_periph->i2c_controllers</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1814.92,-338.92C1779.86,-328.05 1741,-316 1741,-316 1741,-316 1692,-289 1692,-289 1692,-289 1469,-266 1469,-266 1469,-266 1462.18,-264.45 1451.81,-262.1"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1852.33,-339.73C1808.31,-328.66 1758,-316 1758,-316 1758,-316 1683,-289 1683,-289 1683,-289 1469,-266 1469,-266 1469,-266 1462.18,-264.45 1451.81,-262.1"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1452.29,-259.7 1444.92,-260.54 1451.2,-264.47 1452.29,-259.7"/>
|
||||
<text text-anchor="middle" x="1751.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<text text-anchor="middle" x="1768.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- gpio_controller -->
|
||||
<g id="node27" class="node">
|
||||
@@ -462,7 +462,7 @@
|
||||
<!-- apb4_periph->gpio_controller -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>apb4_periph->gpio_controller</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1934.55,-352.83C2127.08,-343.37 2684,-316 2684,-316 2684,-316 2684,-289 2684,-289 2684,-289 2628.59,-275.35 2575.67,-262.32"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1981.73,-352.62C2166.65,-342.98 2684,-316 2684,-316 2684,-316 2684,-289 2684,-289 2684,-289 2628.59,-275.35 2575.67,-262.32"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2575.95,-259.86 2568.56,-260.57 2574.77,-264.62 2575.95,-259.86"/>
|
||||
<text text-anchor="middle" x="2704" y="-305.1" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<text text-anchor="middle" x="2704" y="-296.1" font-family="Arial" font-size="8.00" fill="#374151">user/admin</text>
|
||||
@@ -470,16 +470,16 @@
|
||||
<!-- apb4_periph->timers -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>apb4_periph->timers</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1805.23,-346.37C1725.63,-334.53 1601,-316 1601,-316 1601,-316 1511,-289 1511,-289 1511,-289 991,-266 991,-266 991,-266 984.42,-264.48 974.38,-262.17"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1852.4,-348.05C1757.62,-336.38 1592,-316 1592,-316 1592,-316 1534,-289 1534,-289 1534,-289 991,-266 991,-266 991,-266 984.42,-264.48 974.38,-262.17"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="974.69,-259.72 967.32,-260.54 973.59,-264.5 974.69,-259.72"/>
|
||||
<text text-anchor="middle" x="1611.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<text text-anchor="middle" x="1602.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_periph->ws2812 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>apb4_periph->ws2812</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1863.31,-338.99C1855.95,-320.26 1843.99,-289.86 1835.2,-267.48"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1837.42,-266.44 1832.58,-260.82 1832.86,-268.23 1837.42,-266.44"/>
|
||||
<text text-anchor="middle" x="1863.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M1908.5,-338.75C1898.72,-318.89 1884,-289 1884,-289 1884,-289 1870.21,-277.51 1855.86,-265.55"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="1857.09,-263.38 1850.14,-260.79 1853.95,-267.15 1857.09,-263.38"/>
|
||||
<text text-anchor="middle" x="1906.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- apb4_system_targets -->
|
||||
<g id="node30" class="node">
|
||||
@@ -513,9 +513,9 @@
|
||||
<!-- apb4_system->wdg -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>apb4_system->wdg</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M3040.86,-354.82C2775.92,-348.22 1484,-316 1484,-316 1484,-316 1453,-289 1453,-289 1453,-289 758,-266 758,-266 758,-266 752.59,-264.57 744.26,-262.36"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M3040.68,-354.8C2777.62,-348.15 1507,-316 1507,-316 1507,-316 1476,-289 1476,-289 1476,-289 758,-266 758,-266 758,-266 752.59,-264.57 744.26,-262.36"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="744.75,-259.96 737.36,-260.54 743.5,-264.7 744.75,-259.96"/>
|
||||
<text text-anchor="middle" x="1494.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
<text text-anchor="middle" x="1517.5" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">APB4</text>
|
||||
</g>
|
||||
<!-- crc -->
|
||||
<g id="node33" class="node">
|
||||
@@ -757,9 +757,9 @@
|
||||
<!-- rtc->sysctrl -->
|
||||
<g id="edge56" class="edge">
|
||||
<title>rtc->sysctrl</title>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1208.38,-260.53C1222.3,-263.75 1232,-266 1232,-266 1232,-266 1628,-297 1628,-297 1628,-297 1686,-297 1686,-297 1686,-297 2166,-266 2166,-266 2166,-266 2171.45,-264.57 2179.89,-262.37"/>
|
||||
<path fill="none" stroke="#4b5563" stroke-width="1.2" stroke-dasharray="5,2" d="M1208.38,-260.53C1222.3,-263.75 1232,-266 1232,-266 1232,-266 1619,-297 1619,-297 1619,-297 1677,-297 1677,-297 1677,-297 2166,-266 2166,-266 2166,-266 2171.45,-264.57 2179.89,-262.37"/>
|
||||
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="2180.73,-264.68 2186.88,-260.53 2179.49,-259.94 2180.73,-264.68"/>
|
||||
<text text-anchor="middle" x="1657" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">wake live / sticky</text>
|
||||
<text text-anchor="middle" x="1648" y="-300.6" font-family="Arial" font-size="8.00" fill="#374151">wake live / sticky</text>
|
||||
</g>
|
||||
<!-- rtc->irq -->
|
||||
<g id="edge55" class="edge">
|
||||
|
||||
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
@@ -133,7 +133,7 @@ capabilities:
|
||||
|
||||
- A fixed Hazard3 management core owns system control and has a permanent JTAG
|
||||
Debug Module.
|
||||
- The C0-C5 extension fabric permits one selected user core to run at a time.
|
||||
- The C0-C3 extension fabric permits one selected user core to run at a time.
|
||||
- SYSCTRL controls user-core selection, reset, interrupt admission, and bus
|
||||
admission. A stop request blocks new user transactions, drains an accepted
|
||||
transaction, and then asserts reset.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# PDK-specific Liberty inputs for the reproducible core-STA baseline.
|
||||
|
||||
ifeq ($(PDK),IHP130)
|
||||
OPENSTA_LIBERTY := $(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_stdcell/lib/sg13g2_stdcell_slow_1p08V_125C.lib
|
||||
OPENSTA_LINK_LIBS := $(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_io/lib/sg13g2_io_slow_1p08V_3p0V_125C.lib
|
||||
OPENSTA_LIBERTY := $(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_stdcell/lib/sg13g2_stdcell_slow_1p08V_125C.lib
|
||||
OPENSTA_LINK_LIBS := $(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_io/lib/sg13g2_io_slow_1p08V_3p0V_125C.lib
|
||||
IHP130_USB2_SRAM_LIBS := \
|
||||
$(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_sram/lib/RM_IHPSG13_1P_4096x16_c3_bm_bist_slow_1p08V_125C.lib \
|
||||
$(ROOT_PATH)/physical/pdk/IHP-Open-PDK/ihp-sg13g2/libs.ref/sg13g2_sram/lib/RM_IHPSG13_1P_4096x8_c3_bm_bist_slow_1p08V_125C.lib
|
||||
@@ -24,4 +24,4 @@ else
|
||||
$(error OpenSTA core-STA does not support PDK=$(PDK))
|
||||
endif
|
||||
|
||||
OPENSTA_SRAM_LIBS ?=
|
||||
OPENSTA_SRAM_LIBS ?=
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -11,7 +11,7 @@
|
||||
"signature": "56c5f69398be8d7b"
|
||||
},
|
||||
{
|
||||
"count": 10,
|
||||
"count": 13,
|
||||
"example": "warning:The network is combinational (run \"fraig\" or \"fraig_sweep\").",
|
||||
"signature": "62cc5ee554312205"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -5,6 +5,8 @@ ordinary self-owned IP workflow.
|
||||
|
||||
- clusterip contains repositories locked by dependencies/dependencies.lock.json.
|
||||
- mpw contains the locked Mini-ver-MPW generator and its prepared core inputs.
|
||||
KianV RV32IMA and PicoRV32 remain available as managed sources but are
|
||||
omitted by the active retroSoC user-extension map.
|
||||
- third_party contains the locked external IP repository.
|
||||
- picorv32 contains the repository-vendored PicoRV32 source and its
|
||||
flow-generated picorv32_ver.v derivative.
|
||||
@@ -12,4 +14,4 @@ ordinary self-owned IP workflow.
|
||||
Use the top-level setup targets to update locked inputs. Do not edit MPW output
|
||||
or locked checkouts in place. The PicoRV32 derivative is regenerated by the
|
||||
setup-core target from the vendored source and preserves the project macro
|
||||
contract used by the active filelist.
|
||||
contract if the core is re-enabled.
|
||||
+1
-1
@@ -53,7 +53,7 @@ $(MPW_STAMP):
|
||||
@mkdir -p $(@D)
|
||||
@touch $@
|
||||
|
||||
$(MPW_VARIANT_STAMP): $(MPW_STAMP) $(ROOT_PATH)/scripts/generate_mpw.py
|
||||
$(MPW_VARIANT_STAMP): $(MPW_STAMP) $(USER_EXTENSIONS_SOURCE) $(ROOT_PATH)/scripts/generate_mpw.py
|
||||
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/generate_mpw.py --root $(ROOT_PATH) \
|
||||
--output $(MPW_OUTPUT_DIR) \
|
||||
--lock-file $(CACHE_ROOT)/locks/mpw.lock
|
||||
|
||||
@@ -52,10 +52,11 @@ core IRQ bit unallocated and driven low. Firmware does not
|
||||
expose a generic external interrupt API until the SoC includes a claim/complete
|
||||
interrupt controller.
|
||||
|
||||
`user_extensions.json` defines the SoC-level user-core and user-IP slots.
|
||||
The locked mini-ver-mpw `mpw.toml` remains the source of truth for enabled
|
||||
design IDs, module names, slots, and reset type. `scripts/generate_mpw.py`
|
||||
verifies that both descriptions agree before RTL generation.
|
||||
`user_extensions.json` defines the active SoC-level user-core and user-IP
|
||||
design IDs, slots, module names, and reset types. The locked mini-ver-mpw
|
||||
`mpw.toml` remains the source of truth for available design metadata and source
|
||||
locations. `scripts/generate_mpw.py` selects and renumbers the configured
|
||||
designs, then verifies the generated manifest before RTL generation.
|
||||
`generate_user_extensions.py` then creates isolated default routing and one
|
||||
explicit instance per selected slot for `user_core_top.sv` and `user_ip_top.sv`.
|
||||
User cores keep `ribp_if.master ribp` at the extension ABI and are converted to
|
||||
|
||||
@@ -20,6 +20,7 @@ APB_REQUEST_SIGNALS = ("paddr", "pprot", "psel", "penable", "pwrite", "pwdata",
|
||||
@dataclass(frozen=True)
|
||||
class ExtensionTarget:
|
||||
slot: int
|
||||
design_id: str
|
||||
module: str
|
||||
instance: str
|
||||
bus: str
|
||||
@@ -74,12 +75,14 @@ def parse_targets(
|
||||
raise ValueError(f"{field} must be a non-empty list")
|
||||
targets: list[ExtensionTarget] = []
|
||||
slots: set[int] = set()
|
||||
design_ids: set[str] = set()
|
||||
instances: set[str] = set()
|
||||
for index, entry in enumerate(value):
|
||||
target = require_object(entry, f"{field}[{index}]")
|
||||
slot = target.get("slot")
|
||||
if not isinstance(slot, int) or not first_slot <= slot < (1 << selector_width):
|
||||
raise ValueError(f"{field}[{index}].slot must be within the selector range")
|
||||
design_id = require_identifier(target.get("design_id"), f"{field}[{index}].design_id")
|
||||
module = require_identifier(target.get("module"), f"{field}[{index}].module")
|
||||
instance = require_identifier(target.get("instance"), f"{field}[{index}].instance")
|
||||
if field == "core_targets":
|
||||
@@ -94,11 +97,14 @@ def parse_targets(
|
||||
reset = "async"
|
||||
if slot in slots:
|
||||
raise ValueError(f"{field} slot {slot} is duplicated")
|
||||
if design_id in design_ids:
|
||||
raise ValueError(f"{field} design_id {design_id} is duplicated")
|
||||
if instance in instances:
|
||||
raise ValueError(f"{field} instance {instance} is duplicated")
|
||||
slots.add(slot)
|
||||
design_ids.add(design_id)
|
||||
instances.add(instance)
|
||||
targets.append(ExtensionTarget(slot, module, instance, bus, reset))
|
||||
targets.append(ExtensionTarget(slot, design_id, module, instance, bus, reset))
|
||||
ordered = tuple(sorted(targets, key=lambda item: item.slot))
|
||||
if [target.slot for target in ordered] != list(range(first_slot, first_slot + len(ordered))):
|
||||
raise ValueError(f"{field} slots must be contiguous from {first_slot}")
|
||||
@@ -107,8 +113,8 @@ def parse_targets(
|
||||
|
||||
def read_extensions(path: Path) -> ExtensionMap:
|
||||
document = require_object(json.loads(path.read_text(encoding="utf-8")), "user extensions")
|
||||
if document.get("schema_version") != 1:
|
||||
raise ValueError("schema_version must be 1")
|
||||
if document.get("schema_version") != 2:
|
||||
raise ValueError("schema_version must be 2")
|
||||
core_selector_width = require_positive_integer(
|
||||
document.get("core_selector_width"), "core_selector_width"
|
||||
)
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"schema_version": 2,
|
||||
"core_selector_width": 5,
|
||||
"ip_selector_width": 8,
|
||||
"gpio_width": 32,
|
||||
"core_targets": [
|
||||
{"slot": 0, "module": "mpw_c0", "instance": "u_mpw_core_kianv_rv32i", "bus": "ribp", "reset": "sync"},
|
||||
{"slot": 1, "module": "mpw_c1", "instance": "u_mpw_core_kianv_rv32ima", "bus": "ribp", "reset": "sync"},
|
||||
{"slot": 2, "module": "mpw_c2", "instance": "u_mpw_core_serv", "bus": "ribp", "reset": "async"},
|
||||
{"slot": 3, "module": "mpw_c3", "instance": "u_mpw_core_femtorv32", "bus": "ribp", "reset": "async"},
|
||||
{"slot": 4, "module": "mpw_c4", "instance": "u_mpw_core_darkriscv", "bus": "ribp", "reset": "async"},
|
||||
{"slot": 5, "module": "mpw_c5", "instance": "u_mpw_core_picorv32", "bus": "ribp", "reset": "sync"}
|
||||
{"slot": 0, "design_id": "kianv_rv32i", "module": "mpw_c0", "instance": "u_mpw_core_kianv_rv32i", "bus": "ribp", "reset": "sync"},
|
||||
{"slot": 1, "design_id": "serv", "module": "mpw_c1", "instance": "u_mpw_core_serv", "bus": "ribp", "reset": "async"},
|
||||
{"slot": 2, "design_id": "femtorv32", "module": "mpw_c2", "instance": "u_mpw_core_femtorv32", "bus": "ribp", "reset": "async"},
|
||||
{"slot": 3, "design_id": "darkriscv", "module": "mpw_c3", "instance": "u_mpw_core_darkriscv", "bus": "ribp", "reset": "async"}
|
||||
],
|
||||
"ip_targets": [
|
||||
{"slot": 1, "module": "mpw_i1", "instance": "u_mpw_ip_tiny_timer"},
|
||||
{"slot": 2, "module": "mpw_i2", "instance": "u_mpw_ip_tiny_gpio"}
|
||||
{"slot": 1, "design_id": "tiny_timer", "module": "mpw_i1", "instance": "u_mpw_ip_tiny_timer"},
|
||||
{"slot": 2, "design_id": "tiny_gpio", "module": "mpw_i2", "instance": "u_mpw_ip_tiny_gpio"}
|
||||
]
|
||||
}
|
||||
@@ -215,4 +215,4 @@ firmware: $(FIRMWARE_ELF)
|
||||
|
||||
firmware asm: | manifest
|
||||
|
||||
.PHONY: FORCE_VERSION
|
||||
.PHONY: FORCE_VERSION
|
||||
+114
-11
@@ -6,27 +6,126 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import fcntl
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
import tomllib
|
||||
except ModuleNotFoundError: # Python 3.10
|
||||
import tomli as tomllib
|
||||
|
||||
|
||||
def toml_value(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "true" if value else "false"
|
||||
if isinstance(value, int):
|
||||
return str(value)
|
||||
if isinstance(value, str):
|
||||
return json.dumps(value, ensure_ascii=True)
|
||||
if isinstance(value, list) and all(isinstance(item, str) for item in value):
|
||||
return "[" + ", ".join(json.dumps(item, ensure_ascii=True) for item in value) + "]"
|
||||
raise ValueError(f"unsupported MPW manifest value: {value!r}")
|
||||
|
||||
|
||||
def render_active_manifest(manifest_path: Path, extensions_path: Path) -> str:
|
||||
"""Select and renumber locked MPW designs from the self-owned extension map."""
|
||||
document = tomllib.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
if document.get("schema_version") != 2:
|
||||
raise ValueError(f"{manifest_path}: schema_version must be 2")
|
||||
generator = document.get("generator")
|
||||
if not isinstance(generator, dict):
|
||||
raise ValueError(f"{manifest_path}: generator must be a table")
|
||||
designs = document.get("design")
|
||||
if not isinstance(designs, list):
|
||||
raise ValueError(f"{manifest_path}: design must be an array")
|
||||
|
||||
available: dict[tuple[str, str], dict[str, Any]] = {}
|
||||
for design in designs:
|
||||
if not isinstance(design, dict):
|
||||
raise ValueError(f"{manifest_path}: design contains a non-table entry")
|
||||
key = (design.get("kind"), design.get("id"))
|
||||
if not all(isinstance(item, str) for item in key):
|
||||
raise ValueError(f"{manifest_path}: every design requires string kind and id")
|
||||
if key in available:
|
||||
raise ValueError(f"{manifest_path}: duplicate {key[0]} design id {key[1]}")
|
||||
available[key] = design
|
||||
|
||||
extensions = json.loads(extensions_path.read_text(encoding="utf-8"))
|
||||
if not isinstance(extensions, dict) or extensions.get("schema_version") != 2:
|
||||
raise ValueError(f"{extensions_path}: schema_version must be 2")
|
||||
selected: list[dict[str, Any]] = []
|
||||
selected_ids: set[tuple[str, str]] = set()
|
||||
for kind, target_key in (("core", "core_targets"), ("ip", "ip_targets")):
|
||||
targets = extensions.get(target_key)
|
||||
if not isinstance(targets, list):
|
||||
raise ValueError(f"{extensions_path}: {target_key} must be a list")
|
||||
for index, target in enumerate(targets):
|
||||
if not isinstance(target, dict):
|
||||
raise ValueError(f"{extensions_path}: {target_key}[{index}] must be an object")
|
||||
design_id = target.get("design_id")
|
||||
slot = target.get("slot")
|
||||
key = (kind, design_id)
|
||||
if not isinstance(design_id, str) or key not in available:
|
||||
raise ValueError(
|
||||
f"{extensions_path}: {target_key}[{index}] selects unknown {kind} design {design_id!r}"
|
||||
)
|
||||
if key in selected_ids:
|
||||
raise ValueError(f"{extensions_path}: {kind} design {design_id} is selected more than once")
|
||||
if not isinstance(slot, int) or slot < 0:
|
||||
raise ValueError(f"{extensions_path}: {target_key}[{index}].slot must be non-negative")
|
||||
expected_module = f"mpw_{kind[0]}{slot}"
|
||||
if target.get("module") != expected_module:
|
||||
raise ValueError(
|
||||
f"{extensions_path}: {target_key}[{index}].module must be {expected_module}"
|
||||
)
|
||||
design = dict(available[key])
|
||||
if kind == "core" and target.get("reset") != design.get("reset"):
|
||||
raise ValueError(
|
||||
f"{extensions_path}: {target_key}[{index}].reset does not match {design_id}"
|
||||
)
|
||||
design["slot"] = slot
|
||||
design.pop("enabled", None)
|
||||
selected.append(design)
|
||||
selected_ids.add(key)
|
||||
|
||||
lines = [f"schema_version = {document['schema_version']}", "", "[generator]"]
|
||||
lines.extend(f"{key} = {toml_value(value)}" for key, value in generator.items())
|
||||
for design in selected:
|
||||
lines.extend(["", "[[design]]"])
|
||||
lines.extend(f"{key} = {toml_value(value)}" for key, value in design.items())
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def generate(root: Path, output: Path) -> None:
|
||||
managed_mpw = root / "rtl/managed/mpw"
|
||||
manifest = managed_mpw / "mpw.toml"
|
||||
extensions = root / "rtl/mini/integration/user_extensions.json"
|
||||
if not manifest.is_file():
|
||||
raise FileNotFoundError(f"MPW v2 manifest is missing: {manifest}")
|
||||
command = [
|
||||
sys.executable,
|
||||
"-m",
|
||||
"mpwgen",
|
||||
"generate",
|
||||
"--manifest",
|
||||
str(manifest),
|
||||
"--output",
|
||||
str(output),
|
||||
]
|
||||
subprocess.run(command, cwd=managed_mpw, check=True)
|
||||
descriptor, manifest_name = tempfile.mkstemp(
|
||||
prefix=".retrosoc-active-", suffix=".toml", dir=managed_mpw
|
||||
)
|
||||
active_manifest = Path(manifest_name)
|
||||
try:
|
||||
with os.fdopen(descriptor, "w", encoding="utf-8", newline="\n") as stream:
|
||||
stream.write(render_active_manifest(manifest, extensions))
|
||||
command = [
|
||||
sys.executable,
|
||||
"-m",
|
||||
"mpwgen",
|
||||
"generate",
|
||||
"--manifest",
|
||||
str(active_manifest),
|
||||
"--output",
|
||||
str(output),
|
||||
]
|
||||
subprocess.run(command, cwd=managed_mpw, check=True)
|
||||
finally:
|
||||
active_manifest.unlink(missing_ok=True)
|
||||
validate_extension_bindings(root, output)
|
||||
|
||||
|
||||
@@ -63,6 +162,10 @@ def validate_extension_bindings(root: Path, output: Path) -> None:
|
||||
raise ValueError(f"{extensions_path}: {target_key} slots do not match MPW v2")
|
||||
for slot, design in expected.items():
|
||||
target = actual[slot]
|
||||
if target.get("design_id") != design.get("id"):
|
||||
raise ValueError(
|
||||
f"{extensions_path}: {kind} slot {slot} design ID does not match MPW v2"
|
||||
)
|
||||
if target.get("module") != design.get("top"):
|
||||
raise ValueError(
|
||||
f"{extensions_path}: {kind} slot {slot} does not match {design.get('top')}"
|
||||
|
||||
@@ -155,20 +155,20 @@ module sysctrl_tb;
|
||||
if (read_data !== 32'd151) $fatal(1, "USB2 performance snapshot was not recorded");
|
||||
|
||||
read_register(32'h1000_B020, read_data);
|
||||
if (read_data !== 32'h0000_003F) $fatal(1, "user cores were not held in reset");
|
||||
write_register(32'h1000_B000, 32'h0000_0006);
|
||||
if (read_data !== 32'h0000_000F) $fatal(1, "user cores were not held in reset");
|
||||
write_register(32'h1000_B000, 32'h0000_0004);
|
||||
read_register(32'h1000_B024, read_data);
|
||||
if ((read_data & 32'h0000_083F) !== 32'h0000_0800) begin
|
||||
$fatal(1, "out-of-range user core selection was accepted");
|
||||
end
|
||||
write_register(32'h1000_B024, 32'h0000_0800);
|
||||
write_register(32'h1000_B000, 32'h0000_0001);
|
||||
write_register(32'h1000_B020, 32'h0000_003D);
|
||||
write_register(32'h1000_B020, 32'h0000_000D);
|
||||
read_register(32'h1000_B024, read_data);
|
||||
if ((read_data & 32'h0000_0300) !== 32'h0000_0300 || (read_data & 32'h1F) != 1) begin
|
||||
$fatal(1, "user core start state was not recorded");
|
||||
end
|
||||
write_register(32'h1000_B020, 32'h0000_003F);
|
||||
write_register(32'h1000_B020, 32'h0000_000F);
|
||||
read_register(32'h1000_B024, read_data);
|
||||
if ((read_data & 32'h0000_0300) !== 32'h0000_0200) begin
|
||||
$fatal(1, "user core stop state was not recorded");
|
||||
|
||||
+11
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -46,6 +47,13 @@ def test_opipsram_protocol_model_compiles_and_runs() -> None:
|
||||
work = ROOT / ".cache" / "test-opipsram"
|
||||
shutil.rmtree(work, ignore_errors=True)
|
||||
work.mkdir(parents=True, exist_ok=True)
|
||||
ccache_dir = work / "ccache"
|
||||
ccache_tmp = work / "ccache-tmp"
|
||||
ccache_dir.mkdir()
|
||||
ccache_tmp.mkdir()
|
||||
environment = os.environ.copy()
|
||||
environment["CCACHE_DIR"] = str(ccache_dir)
|
||||
environment["CCACHE_TEMPDIR"] = str(ccache_tmp)
|
||||
output = work / "opipsram_tb"
|
||||
sources = [
|
||||
ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv",
|
||||
@@ -93,7 +101,9 @@ def test_opipsram_protocol_model_compiles_and_runs() -> None:
|
||||
str(output),
|
||||
]
|
||||
try:
|
||||
compile_result = subprocess.run(command, check=False, text=True, capture_output=True)
|
||||
compile_result = subprocess.run(
|
||||
command, check=False, text=True, capture_output=True, env=environment
|
||||
)
|
||||
if compile_result.returncode != 0:
|
||||
pytest.fail(
|
||||
"production OPI PSRAM RTL does not compile with the locked model list:\n"
|
||||
|
||||
@@ -38,7 +38,7 @@ from scripts.development_environment import ( # noqa: E402
|
||||
render_activation,
|
||||
stamp_data,
|
||||
)
|
||||
from scripts.generate_mpw import validate_extension_bindings # noqa: E402
|
||||
from scripts.generate_mpw import render_active_manifest, validate_extension_bindings # noqa: E402
|
||||
from scripts.install_toolchain import safe_extract # noqa: E402
|
||||
from scripts.package import make_sbom # noqa: E402
|
||||
from scripts import regress # noqa: E402
|
||||
@@ -395,7 +395,69 @@ def test_mpw_generator_uses_only_the_native_v2_contract() -> None:
|
||||
|
||||
assert "migrate_user_" not in source
|
||||
assert "prepare_legacy_mpw_workspace" not in source
|
||||
assert '"-m",\n "mpwgen"' in source
|
||||
assert '"mpwgen"' in source
|
||||
assert '"generate"' in source
|
||||
|
||||
|
||||
def test_mpw_active_manifest_uses_self_owned_design_selection(tmp_path: Path) -> None:
|
||||
manifest = tmp_path / "mpw.toml"
|
||||
manifest.write_text(
|
||||
"""schema_version = 2
|
||||
[generator]
|
||||
api_version = "retrosoc-mpw-v2"
|
||||
[[design]]
|
||||
kind = "core"
|
||||
id = "slow_core"
|
||||
slot = 0
|
||||
enabled = false
|
||||
source_dir = "core/slow"
|
||||
top = "user_core_design"
|
||||
filelist = "usercore.fl"
|
||||
reset = "sync"
|
||||
name = "Slow"
|
||||
isa = "rv32i"
|
||||
maintainer = "owner"
|
||||
repo = "https://example.com/slow"
|
||||
[[design]]
|
||||
kind = "core"
|
||||
id = "selected_core"
|
||||
slot = 5
|
||||
source_dir = "core/selected"
|
||||
top = "user_core_design"
|
||||
filelist = "usercore.fl"
|
||||
reset = "async"
|
||||
name = "Selected"
|
||||
isa = "rv32i"
|
||||
maintainer = "owner"
|
||||
repo = "https://example.com/selected"
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
extensions = tmp_path / "user_extensions.json"
|
||||
extensions.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": 2,
|
||||
"core_targets": [
|
||||
{
|
||||
"slot": 0,
|
||||
"design_id": "selected_core",
|
||||
"module": "mpw_c0",
|
||||
"reset": "async",
|
||||
}
|
||||
],
|
||||
"ip_targets": [],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
active = render_active_manifest(manifest, extensions)
|
||||
|
||||
assert 'id = "selected_core"' in active
|
||||
assert 'id = "slow_core"' not in active
|
||||
assert "slot = 0" in active
|
||||
assert "enabled" not in active
|
||||
|
||||
|
||||
def test_mpw_extension_bindings_match_generated_manifest(tmp_path: Path) -> None:
|
||||
@@ -403,10 +465,15 @@ def test_mpw_extension_bindings_match_generated_manifest(tmp_path: Path) -> None
|
||||
extensions_path.parent.mkdir(parents=True)
|
||||
extensions = {
|
||||
"core_targets": [
|
||||
{"slot": 0, "module": "mpw_core_zero", "reset": "sync"},
|
||||
{
|
||||
"slot": 0,
|
||||
"design_id": "core_zero",
|
||||
"module": "mpw_core_zero",
|
||||
"reset": "sync",
|
||||
},
|
||||
],
|
||||
"ip_targets": [
|
||||
{"slot": 1, "module": "mpw_ip_one"},
|
||||
{"slot": 1, "design_id": "ip_one", "module": "mpw_ip_one"},
|
||||
],
|
||||
}
|
||||
extensions_path.write_text(json.dumps(extensions), encoding="utf-8")
|
||||
@@ -414,8 +481,14 @@ def test_mpw_extension_bindings_match_generated_manifest(tmp_path: Path) -> None
|
||||
output.mkdir()
|
||||
manifest = {
|
||||
"designs": [
|
||||
{"kind": "core", "slot": 0, "top": "mpw_core_zero", "reset": "sync"},
|
||||
{"kind": "ip", "slot": 1, "top": "mpw_ip_one"},
|
||||
{
|
||||
"kind": "core",
|
||||
"id": "core_zero",
|
||||
"slot": 0,
|
||||
"top": "mpw_core_zero",
|
||||
"reset": "sync",
|
||||
},
|
||||
{"kind": "ip", "id": "ip_one", "slot": 1, "top": "mpw_ip_one"},
|
||||
]
|
||||
}
|
||||
(output / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
|
||||
|
||||
@@ -49,18 +49,22 @@ def test_extensions_generate_isolated_scalar_bindings(tmp_path: Path) -> None:
|
||||
filelist = (tmp_path / "user_extensions.fl").read_text(encoding="utf-8")
|
||||
config = (tmp_path / "rtl/user_extensions_config.svh").read_text(encoding="utf-8")
|
||||
|
||||
assert core.count("rib_if u_user_") == 6
|
||||
assert core.count("ribp_if u_user_") == 6
|
||||
assert core.count("ribp2rib #(") == 6
|
||||
assert core.count(".SyncReset(1'b1)") == 3
|
||||
assert core.count("rib_if u_user_") == 4
|
||||
assert core.count("ribp_if u_user_") == 4
|
||||
assert core.count("ribp2rib #(") == 4
|
||||
assert core.count(".SyncReset(1'b1)") == 1
|
||||
assert core.count(".SyncReset(1'b0)") == 3
|
||||
assert "u_user_rib_if.cmd_valid = '0;" in core
|
||||
assert "5'd0: begin" in core
|
||||
assert "5'd4: begin" in core
|
||||
assert "5'd5: begin" in core
|
||||
assert "5'd3: begin" in core
|
||||
assert "5'd4: begin" not in core
|
||||
assert "core_reset_i[0]" in core
|
||||
assert "mpw_c0 #(0)" in core
|
||||
assert "mpw_c5 #(5)" in core
|
||||
assert "mpw_c1 #(1)" in core
|
||||
assert "mpw_c3 #(3)" in core
|
||||
assert "u_mpw_core_serv" in core
|
||||
assert "u_mpw_core_kianv_rv32ima" not in core
|
||||
assert "u_mpw_core_picorv32" not in core
|
||||
assert "mpw_i1 #(1)" in ip
|
||||
assert "User core 0 uses the RIBP contract" in core
|
||||
assert ip.count("user_gpio_if #(`USER_GPIO_NUM)") == 2
|
||||
@@ -68,7 +72,7 @@ def test_extensions_generate_isolated_scalar_bindings(tmp_path: Path) -> None:
|
||||
assert "8'd2: begin" in ip
|
||||
assert "u_user_2_apb4_if.psel = apb.psel;" in ip
|
||||
assert filelist.startswith("+incdir+")
|
||||
assert "`define USER_CORE_COUNT 6" in config
|
||||
assert "`define USER_CORE_COUNT 4" in config
|
||||
|
||||
|
||||
def test_extensions_reject_noncontiguous_slots_and_invalid_modules(tmp_path: Path) -> None:
|
||||
@@ -91,3 +95,11 @@ def test_extensions_reject_invalid_core_reset_style(tmp_path: Path) -> None:
|
||||
result = validate(write_invalid_extensions(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert ".reset must be sync or async" in result.stderr
|
||||
|
||||
|
||||
def test_extensions_reject_duplicate_design_selection(tmp_path: Path) -> None:
|
||||
document = json.loads(EXTENSIONS.read_text(encoding="utf-8"))
|
||||
document["core_targets"][1]["design_id"] = document["core_targets"][0]["design_id"]
|
||||
result = validate(write_invalid_extensions(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert "design_id kianv_rv32i is duplicated" in result.stderr
|
||||
Reference in new issue
Block a user