mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat: enhance testbench and system control for GA2D and data plane fault handling
- Updated onchip_ram64_tb to increase ID_WIDTH from 6 to 7 and adjusted related write/read tasks. - Modified resource_controller_tb to accommodate an expanded resource count from 8 to 9, updating related logic signals. - Enhanced sysctrl_tb to introduce new fault handling logic for data plane faults, including additional fault validation and delivery mechanisms. - Added tests for clock and reset domains to ensure proper handling of data plane faults and their reset contracts. - Introduced new test_ga2d_platform.py to verify GA2D Phase 2 functionality, including lifecycle and recovery processes. - Updated test_soc_topology.py to ensure proper data master policies and validate GA2D integration within the system. - Enhanced sysctrl.py to ensure the fault master retains the high bit for data plane faults.
This commit is contained in:
61 files changed
+2911
-610
No files matched your search
@@ -13,9 +13,11 @@ typedef enum {
|
||||
RS_FABRIC_MASTER_IO_A = 3,
|
||||
RS_FABRIC_MASTER_IO_B = 4,
|
||||
RS_FABRIC_MASTER_LP = 5,
|
||||
RS_FABRIC_MASTER_RESERVED = 6,
|
||||
RS_FABRIC_MASTER_JPEG = 6,
|
||||
RS_FABRIC_MASTER_RESERVED = RS_FABRIC_MASTER_JPEG,
|
||||
RS_FABRIC_MASTER_EXT_H = 7,
|
||||
RS_FABRIC_MASTER_COUNT = 8,
|
||||
RS_FABRIC_MASTER_GA2D = 8,
|
||||
RS_FABRIC_MASTER_COUNT = 9,
|
||||
} rs_fabric_master_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -15,7 +15,8 @@ typedef enum {
|
||||
RS_RESOURCE_EXT_H = 5,
|
||||
RS_RESOURCE_JPEG = 6,
|
||||
RS_RESOURCE_APU = 7,
|
||||
RS_RESOURCE_COUNT = 8,
|
||||
RS_RESOURCE_GA2D = 8,
|
||||
RS_RESOURCE_COUNT = 9,
|
||||
} rs_resource_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -4,35 +4,45 @@
|
||||
#include <retrosoc/core/soc.h>
|
||||
#include <retrosoc/hal/fabric_monitor.h>
|
||||
|
||||
#define RS_FABRIC_CONTROL_OFFSET UINT32_C(0x00C)
|
||||
#define RS_FABRIC_STATUS_OFFSET UINT32_C(0x010)
|
||||
#define RS_FABRIC_FAULT_OFFSET UINT32_C(0x014)
|
||||
#define RS_FABRIC_FAULT_ADDR_OFFSET UINT32_C(0x018)
|
||||
#define RS_FABRIC_FLUSH_COUNT_OFFSET UINT32_C(0x01C)
|
||||
#define RS_FABRIC_FAULT_COUNT_OFFSET UINT32_C(0x020)
|
||||
#define RS_FABRIC_MASTER_BASE UINT32_C(0x100)
|
||||
#define RS_FABRIC_TARGET_BASE UINT32_C(0x300)
|
||||
#define RS_FABRIC_ENTRY_STRIDE UINT32_C(0x020)
|
||||
#define RS_FABRIC_CONTROL_ENABLE UINT32_C(0x00000001)
|
||||
#define RS_FABRIC_CONTROL_FREEZE UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_CONTROL_CLEAR UINT32_C(0x00000004)
|
||||
#define RS_FABRIC_CONTROL_SNAPSHOT UINT32_C(0x00000008)
|
||||
#define RS_FABRIC_STATUS_IDLE UINT32_C(0x00000001)
|
||||
#define RS_FABRIC_STATUS_RECOVERY UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_STATUS_FLUSH_BUSY UINT32_C(0x00000004)
|
||||
#define RS_FABRIC_STATUS_READ_SHIFT 8U
|
||||
#define RS_FABRIC_STATUS_WRITE_SHIFT 16U
|
||||
#define RS_FABRIC_HIGH_WATER_MASK UINT32_C(0x00000007)
|
||||
#define RS_FABRIC_WRITE_HIGH_SHIFT 3U
|
||||
#define RS_FABRIC_FAULT_WRITE UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_FAULT_MASTER_SHIFT 2U
|
||||
#define RS_FABRIC_FAULT_TARGET_SHIFT 5U
|
||||
#define RS_FABRIC_FAULT_REASON_SHIFT 8U
|
||||
#define RS_FABRIC_FAULT_FIELD_MASK UINT32_C(0x00000007)
|
||||
#define RS_FABRIC_FAULT_REASON_MASK UINT32_C(0x0000000F)
|
||||
#define RS_FABRIC_CONTROL_OFFSET UINT32_C(0x00C)
|
||||
#define RS_FABRIC_STATUS_OFFSET UINT32_C(0x010)
|
||||
#define RS_FABRIC_FAULT_OFFSET UINT32_C(0x014)
|
||||
#define RS_FABRIC_IP_VERSION_OFFSET UINT32_C(0x004)
|
||||
#define RS_FABRIC_FAULT_ADDR_OFFSET UINT32_C(0x018)
|
||||
#define RS_FABRIC_FLUSH_COUNT_OFFSET UINT32_C(0x01C)
|
||||
#define RS_FABRIC_FAULT_COUNT_OFFSET UINT32_C(0x020)
|
||||
#define RS_FABRIC_MASTER_BASE UINT32_C(0x100)
|
||||
#define RS_FABRIC_TARGET_BASE UINT32_C(0x300)
|
||||
#define RS_FABRIC_ENTRY_STRIDE UINT32_C(0x020)
|
||||
#define RS_FABRIC_CONTROL_ENABLE UINT32_C(0x00000001)
|
||||
#define RS_FABRIC_CONTROL_FREEZE UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_CONTROL_CLEAR UINT32_C(0x00000004)
|
||||
#define RS_FABRIC_CONTROL_SNAPSHOT UINT32_C(0x00000008)
|
||||
#define RS_FABRIC_STATUS_IDLE UINT32_C(0x00000001)
|
||||
#define RS_FABRIC_STATUS_RECOVERY UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_STATUS_FLUSH_BUSY UINT32_C(0x00000004)
|
||||
#define RS_FABRIC_STATUS_READ_SHIFT 8U
|
||||
#define RS_FABRIC_STATUS_WRITE_SHIFT 16U
|
||||
#define RS_FABRIC_HIGH_WATER_MASK UINT32_C(0x00000007)
|
||||
#define RS_FABRIC_WRITE_HIGH_SHIFT 3U
|
||||
#define RS_FABRIC_FAULT_WRITE UINT32_C(0x00000002)
|
||||
#define RS_FABRIC_FAULT_MASTER_SHIFT 2U
|
||||
#define RS_FABRIC_FAULT_TARGET_SHIFT 5U
|
||||
#define RS_FABRIC_FAULT_REASON_SHIFT 8U
|
||||
#define RS_FABRIC_FAULT_FIELD_MASK UINT32_C(0x00000007)
|
||||
#define RS_FABRIC_FAULT_REASON_MASK UINT32_C(0x0000000F)
|
||||
#define RS_FABRIC_FAULT_MASTER_HIGH UINT32_C(0x00001000)
|
||||
#define RS_FABRIC_FAULT_MASTER_HIGH_SHIFT 9U
|
||||
#define RS_FABRIC_IP_VERSION_V1_1 UINT32_C(0x00010001)
|
||||
|
||||
static volatile uint32_t *rs_fabric_register(uint32_t offset) {
|
||||
#if defined(RS_FABRIC_MONITOR_TEST_MMIO)
|
||||
extern volatile uint32_t rs_fabric_monitor_test_mmio[1024];
|
||||
|
||||
return &rs_fabric_monitor_test_mmio[offset / sizeof(uint32_t)];
|
||||
#else
|
||||
return (volatile uint32_t *)(RS_SOC_APB4_FABRIC_MONITOR_BASE + (uintptr_t)offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t rs_fabric_control_value(bool enable, bool freeze) {
|
||||
@@ -93,14 +103,20 @@ rs_status_t rs_fabric_monitor_get_flush_count(uint32_t *count) {
|
||||
|
||||
rs_status_t rs_fabric_monitor_read_fault(rs_fabric_fault_t *fault) {
|
||||
uint32_t value;
|
||||
uint32_t version;
|
||||
|
||||
if (fault == NULL) {
|
||||
return RS_EINVAL;
|
||||
}
|
||||
version = *rs_fabric_register(RS_FABRIC_IP_VERSION_OFFSET);
|
||||
value = *rs_fabric_register(RS_FABRIC_FAULT_OFFSET);
|
||||
fault->address = *rs_fabric_register(RS_FABRIC_FAULT_ADDR_OFFSET);
|
||||
fault->count = *rs_fabric_register(RS_FABRIC_FAULT_COUNT_OFFSET);
|
||||
fault->master = (uint8_t)((value >> RS_FABRIC_FAULT_MASTER_SHIFT) & RS_FABRIC_FAULT_FIELD_MASK);
|
||||
if (version >= RS_FABRIC_IP_VERSION_V1_1) {
|
||||
fault->master |=
|
||||
(uint8_t)((value & RS_FABRIC_FAULT_MASTER_HIGH) >> RS_FABRIC_FAULT_MASTER_HIGH_SHIFT);
|
||||
}
|
||||
fault->target = (uint8_t)((value >> RS_FABRIC_FAULT_TARGET_SHIFT) & RS_FABRIC_FAULT_FIELD_MASK);
|
||||
fault->reason =
|
||||
(uint8_t)((value >> RS_FABRIC_FAULT_REASON_SHIFT) & RS_FABRIC_FAULT_REASON_MASK);
|
||||
|
||||
+16
-10
@@ -6,10 +6,13 @@ plane. Common `axi4_if`, `memory_map.json`, and `soc_topology.json` are the
|
||||
executable protocol, address, and integration sources of truth.
|
||||
|
||||
[GA2D Phase 2](ip/ga2d.md#phase-2---expand-axi64-fabric-and-resource-integration)
|
||||
is the approved, pending expansion to nine native masters and seven-bit global
|
||||
IDs. It adds master 8 and preserves all existing identities, target policy,
|
||||
and timeout behavior. The GA2D specification also records the existing
|
||||
master-6/JPEG admission discrepancy; it must not be interpreted as a free port.
|
||||
expands the fabric to nine native masters and seven-bit global IDs. It adds
|
||||
master 8 and preserves all existing identities, target policy, and timeout
|
||||
behavior. Master 8 is fed only by its dedicated PCLK-to-HP AXI64/ID3 bridge,
|
||||
whose source is idle. `APB4_GA` remains reserved and inactive; the GA2D APB
|
||||
shell, IRQ, payload/DMA, and pixel function remain deferred. The GA2D
|
||||
specification also records the existing master-6/JPEG admission discrepancy;
|
||||
it must not be interpreted as a free port.
|
||||
|
||||
## LP control plane
|
||||
|
||||
@@ -31,8 +34,8 @@ master from writing SYSCTRL/RCU, watchdog, and GPIO administration windows.
|
||||
|
||||
## HP data plane
|
||||
|
||||
The native payload fabric is AXI64 with 32-bit addresses and six-bit global
|
||||
IDs. It has eight masters:
|
||||
The native payload fabric is AXI64 with 32-bit addresses and seven-bit global
|
||||
IDs. It has nine masters:
|
||||
|
||||
| Index | Master | Adaptation |
|
||||
| ---: | --- | --- |
|
||||
@@ -42,10 +45,12 @@ IDs. It has eight masters:
|
||||
| 3 | I/O gateway A | USB2 and SDIO0, PCLK-to-HP CDC, AXI32-to-64 |
|
||||
| 4 | I/O gateway B | SDIO1 and SPI-SD, PCLK-to-HP CDC, AXI32-to-64 |
|
||||
| 5 | LP data gateway | Hazard3 memory traffic, LP-to-HP CDC, AXI32-to-64 |
|
||||
| 6 | reserved | permanently idle and denied |
|
||||
| 6 | JPEG | PCLK-to-HP AXI64 CDC; zero normal admission credit (`GA2D-GAP-01`) |
|
||||
| 7 | EXT-H | PCLK-to-HP AXI64 CDC |
|
||||
| 8 | GA2D bridge placeholder | dedicated PCLK-to-HP AXI64/ID3 CDC; source held idle |
|
||||
|
||||
Each source receives a fixed three-bit master prefix. The crossbar maintains
|
||||
Each source receives a fixed four-bit master prefix over a three-bit source
|
||||
ID. The crossbar maintains
|
||||
independent read and write arbitration for each target, enabling read/write
|
||||
overlap and cross-target concurrency. Different IDs from HP/DMA/EXT-H may be
|
||||
active on the same or different targets up to master and target credits. The
|
||||
@@ -54,7 +59,7 @@ reads and two writes; serial and error targets use one read and one write.
|
||||
|
||||
| Target | Current backend |
|
||||
| --- | --- |
|
||||
| on-chip SRAM | native AXI64/ID6 striped technology macros in HP |
|
||||
| on-chip SRAM | native AXI64/ID7 striped technology macros in HP |
|
||||
| SDRAM | HP-to-memory AXI64 CDC, local 64-to-32 SDRAM adaptation |
|
||||
| QPI PSRAM | AXI64-to-32, CDC, selected QPI frontend |
|
||||
| OPI/HyperBus | AXI64-to-32, CDC, selected OPI frontend |
|
||||
@@ -69,7 +74,8 @@ the integration RTL:
|
||||
| HP I-cache | all five memories | none | allowed | cache attributes preserved |
|
||||
| HP D-cache | all five memories | SRAM, SDRAM, QPI, OPI | denied | cache attributes preserved |
|
||||
| DMA, I/O A/B, LP gateway | all five memories | SRAM, SDRAM, QPI, OPI | denied | `AxCACHE=0` required |
|
||||
| reserved | none | none | denied | fail-closed |
|
||||
| GA2D bridge placeholder | all five memories | SRAM, SDRAM, QPI, OPI | denied | `AxCACHE=0` required; source is idle in P2 |
|
||||
| JPEG | none | none | denied | zero normal admission credit (`GA2D-GAP-01`) |
|
||||
| EXT-H | all five memories within slot ACL | SRAM, SDRAM, QPI, OPI within slot ACL | denied | `AxCACHE=0` required |
|
||||
|
||||
XPI is read-only on the data plane. A denied target, instruction access,
|
||||
|
||||
@@ -15,16 +15,19 @@ ecosystem of the referenced devices. Official sources were rechecked on
|
||||
| [NXP i.MX RT1180](https://www.nxp.com/products/i.MX-RT1180) and [reference manual](https://www.nxp.com/docs/en/reference-manual/IMXRT1180RM.pdf) | Heterogeneous M7/M33 resource isolation and recovery; TRDC assigns initiators to fixed domains and protects memory/peripheral regions, while SRC owns slice reset | Current product; RM Rev 10.0 and data-sheet updates were published in 2026. Depends on TrustZone/security lifecycle and NXP clock/reset IP | Reuse immutable master identity, root-owned policy, fail-closed regions, and slice lifecycle. Avoid pretending a software owner field alone is a security boundary or importing the full secure lifecycle |
|
||||
| [ST STM32MP resource manager](https://wiki.st.com/stm32mpu/wiki/Resource_manager_for_coprocessing), [coprocessor management](https://wiki.st.com/stm32mpu/wiki/Coprocessor_management_overview), and [RIFSC](https://wiki.st.com/stm32mpu/wiki/RIFSC_internal_peripheral) | Prevents Linux and MCU firmware from driving the same peripheral; boot-time ETZPC/RIF hardware assignment is mirrored in device tree, RemoteProc/RPMsg/mailbox, and resource-manager software | Active STM32MP1/MP2 documentation, updated through 2025-2026. Depends on TF-A, OP-TEE, Linux device tree, mailbox, and remoteproc services | Reuse quiesce-before-owner-change, hardware exclusion, and one-owner IRQ routing. Defer the Linux resource driver; avoid split hardware/software ownership tables without parity checks |
|
||||
| [TI AM62x host identities](https://software-dl.ti.com/tisci/esd/latest/5_soc_doc/am62x/hosts.html), [firewalls](https://software-dl.ti.com/tisci/esd/11_01_05/5_soc_doc/am62x/firewalls.html), and [RM board configuration](https://software-dl.ti.com/mcu-plus-sdk/esd/AM62X/09_00_00_19/exports/docs/api_guide_am62x/RESOURCE_ALLOCATION_GUIDE.html) | Prevents initiator spoofing and unauthorized memory/resource use; immutable host IDs select boot-configured firewall permissions and resource ranges through system firmware | Current TISCI/Processor SDK pages were published or crawled in 2026. Depends on TIFS/DM firmware, secure proxy, boardcfg, and interconnect privilege IDs | Reuse generated fixed identities, boot policy, explicit read/write/cache permissions, and first-fault evidence. Avoid a privileged message stack and runtime-reprogrammable policy in this MVP |
|
||||
| [Arm NIC-400 optimization](https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Cycle%20Models/White%20Papers/ARM%20CoreLink%20NIC-400%20Optimization.pdf) and [Arm system QoS](https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Quality%20of%20Service%20QoS%20in%20Arm%20Systems.pdf) | Scales mixed AXI/AHB/APB widths and clocks while controlling latency and bandwidth; target-local buffering, register slices, outstanding limits, hierarchical gateways, and QoS regulators are topology parameters | NIC-400 is mature rather than new; Arm still published an updated QoS guide in 2026. Commercial use depends on licensed IP/configuration and performance modelling | Reuse target-aware credits, independent channel/CDC boundaries, hierarchical I/O gateways, measurable wait/high-water counters, and bounded promotion. Avoid a packetized NoC, virtual networks, and opaque generated RTL for an 8x6 fabric |
|
||||
| [Arm NIC-400 optimization](https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Cycle%20Models/White%20Papers/ARM%20CoreLink%20NIC-400%20Optimization.pdf) and [Arm system QoS](https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Quality%20of%20Service%20QoS%20in%20Arm%20Systems.pdf) | Scales mixed AXI/AHB/APB widths and clocks while controlling latency and bandwidth; target-local buffering, register slices, outstanding limits, hierarchical gateways, and QoS regulators are topology parameters | NIC-400 is mature rather than new; Arm still published an updated QoS guide in 2026. Commercial use depends on licensed IP/configuration and performance modelling | Reuse target-aware credits, independent channel/CDC boundaries, hierarchical I/O gateways, measurable wait/high-water counters, and bounded promotion. Avoid a packetized NoC, virtual networks, and opaque generated RTL for a 9x6 fabric |
|
||||
|
||||
## Technical Selection
|
||||
|
||||
Mini remains a small, non-coherent, performance-first SoC. Hazard3 is the
|
||||
only root-management master. Vexii I/D, DMA, I/O gateways, the LP data gateway,
|
||||
and EXT-H use an eight-master native AXI64 data plane. APB remains a separate
|
||||
control plane. Every data initiator has a generated fixed identity, target
|
||||
permissions, execute/cache-attribute rules, outstanding limit, QoS class, and
|
||||
fault attribution.
|
||||
EXT-H, and an idle GA2D bridge placeholder use a nine-master native AXI64 data
|
||||
plane with seven-bit global IDs. The placeholder is a dedicated
|
||||
PCLK-to-HP AXI64/ID3 bridge only: `APB4_GA` remains reserved and inactive, and
|
||||
the GA2D APB shell, IRQ, payload/DMA, and pixel function remain deferred. APB
|
||||
remains a separate control plane. Every data initiator has a generated fixed
|
||||
identity, target permissions, execute/cache-attribute rules, outstanding
|
||||
limit, QoS class, and fault attribution.
|
||||
|
||||
The design combines the references at their smallest useful boundary:
|
||||
|
||||
|
||||
+2
-2
@@ -227,8 +227,8 @@ contract.
|
||||
The APU provides one PCLK-domain 32-bit AXI4 master with 32-bit addresses,
|
||||
one-bit ID/user, and ID zero. It occupies the unused third input of I/O Gateway
|
||||
A and uses the existing PCLK-to-HP `axi4_async_bridge` and 32-to-64 upsizer.
|
||||
It retains global data-master identity 3; the eight-master crossbar and global
|
||||
ID width do not expand.
|
||||
It retains global data-master identity 3; the nine-master crossbar and
|
||||
seven-bit global ID width preserve that identity.
|
||||
|
||||
Gateway A MUST replace its fixed-priority selection with a burst-boundary
|
||||
Common round-robin arbiter among APU, SDIO0, and USB2. Ownership is retained
|
||||
|
||||
+15
-11
@@ -1,10 +1,11 @@
|
||||
# Mini Data-Plane Fabric Monitor
|
||||
|
||||
The approved [GA2D Phase 2](ga2d.md#phase-2---expand-axi64-fabric-and-resource-integration)
|
||||
[GA2D Phase 2](ga2d.md#phase-2---expand-axi64-fabric-and-resource-integration)
|
||||
adds master bank 8, version 1.1, and master bit 3 at `FAULT[12]`, preserving
|
||||
the existing packed fields. It also requires complete four-bit master identity
|
||||
through SYSCTRL. These are pending implementation changes, not current monitor
|
||||
capabilities; the freeze does not alter executable RTL or HAL definitions.
|
||||
the existing packed fields. It also carries the complete four-bit master
|
||||
identity through SYSCTRL. Bank 8 observes the dedicated PCLK-to-HP
|
||||
AXI64/ID3 GA2D bridge placeholder, whose source is idle; it does not imply an
|
||||
implemented GA2D APB shell, IRQ, payload/DMA, or pixel function.
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -24,11 +25,11 @@ so a multi-register sample is stable while live counting continues.
|
||||
| Offset | Name | Access | Contract |
|
||||
| ---: | --- | --- | --- |
|
||||
| `0x000` | `IP_ID` | RO | `0x44504D4E` (`DPMN`) |
|
||||
| `0x004` | `IP_VERSION` | RO | `0x00010000` |
|
||||
| `0x004` | `IP_VERSION` | RO | `0x00010001` |
|
||||
| `0x008` | `CAPABILITY` | RO | target count `[31:24]`, master count `[23:16]`, saturating/snapshot capability `[1:0]` |
|
||||
| `0x00C` | `CONTROL` | RW | enable bit 0, freeze bit 1, clear pulse bit 2, snapshot pulse bit 3 |
|
||||
| `0x010` | `STATUS` | RO | write outstanding `[23:16]`, read outstanding `[15:8]`, flush busy bit 2, recovery bit 1, idle bit 0 |
|
||||
| `0x014` | `FAULT` | RO | reason `[11:8]`, target `[7:5]`, master `[4:2]`, write bit 1, valid bit 0 |
|
||||
| `0x014` | `FAULT` | RO | master high bit 3 `[12]`, reason `[11:8]`, target `[7:5]`, master low bits `[4:2]`, write bit 1, valid bit 0 |
|
||||
| `0x018` | `FAULT_ADDRESS` | RO | address of the first retained fault |
|
||||
| `0x01C` | `FLUSH_COUNT` | RO | snapshotted warm-flush rising-edge count |
|
||||
| `0x020` | `FAULT_COUNT` | RO | live count of all observed fault events |
|
||||
@@ -41,12 +42,14 @@ does not clear state.
|
||||
|
||||
The first fault after reset or clear is sticky. Later faults increment
|
||||
`FAULT_COUNT` but do not overwrite its identity or address. This preserves the
|
||||
root cause across the PCLK-to-HP bridge and prevents a short data-plane pulse
|
||||
from being missed by software.
|
||||
root cause across the PCLK-to-HP bridge. The monitor counts data-plane faults
|
||||
only when their HP valid/ready report handshake succeeds, so mailbox
|
||||
backpressure does not duplicate or lose an accepted event.
|
||||
|
||||
## Master Counter Banks
|
||||
|
||||
Eight master banks start at `0x100 + master * 0x20`:
|
||||
Nine master banks start at `0x100 + master * 0x20`. Master bank 8 occupies
|
||||
`0x200..0x21F`:
|
||||
|
||||
| Relative offset | Counter |
|
||||
| ---: | --- |
|
||||
@@ -60,8 +63,9 @@ Eight master banks start at `0x100 + master * 0x20`:
|
||||
| `0x1C` | write high-water `[5:3]`, read high-water `[2:0]` |
|
||||
|
||||
Master indices are HP I-cache, HP D-cache, central DMA, I/O gateway A, I/O
|
||||
gateway B, LP data gateway, reserved, and EXT-H. The reserved slot remains
|
||||
visible so an integration defect cannot silently disappear from accounting.
|
||||
gateway B, LP data gateway, JPEG, EXT-H, and the idle GA2D bridge placeholder.
|
||||
JPEG remains visible with zero normal admission credit (`GA2D-GAP-01`), so an
|
||||
integration defect cannot silently disappear from accounting.
|
||||
|
||||
## Target Counter Banks
|
||||
|
||||
|
||||
+16
-7
@@ -898,7 +898,14 @@ comparing recipes. The full product must be analyzed, including wider ID and
|
||||
interrupt routing. Report unclosed timing honestly; it blocks a frequency or
|
||||
verified-readiness claim rather than authorizing a new timing contract.
|
||||
|
||||
The existing implementation workflow's final IHP130 command is:
|
||||
Only Phase 6 executes synthesis, OpenSTA, netlist simulation, warning
|
||||
collection, and metric collection for GA2D. Earlier phases require their
|
||||
listed directed functional, integration, firmware, and lint/formal evidence,
|
||||
but defer full-product physical evidence to Phase 6. This scheduling does not
|
||||
waive any GA2D-V14 requirement or permit an earlier phase to claim
|
||||
verified-readiness.
|
||||
|
||||
The Phase 6 final IHP130 command is:
|
||||
|
||||
```sh
|
||||
python3 scripts/regress.py --root . --suite pr --pdk IHP130 --netsim-boot-only
|
||||
@@ -987,9 +994,9 @@ make CONFIG=configs/cluster/mini-mpw.mk SIMU=VERILATOR comp
|
||||
```
|
||||
|
||||
Completion: GA2D-V01/V02 pass for this boundary; all old IRQ mappings and
|
||||
debug/timer/exception paths remain usable. Report missing synthesis/timing
|
||||
evidence for the expanded priority encoder; do not change priority width or
|
||||
reset behavior to avoid a failure.
|
||||
debug/timer/exception paths remain usable. Synthesis/timing evidence is
|
||||
deferred exclusively to Phase 6; do not change priority width or reset
|
||||
behavior to avoid a failure.
|
||||
|
||||
### Phase 2 - Expand AXI64 Fabric and Resource Integration
|
||||
|
||||
@@ -1021,8 +1028,9 @@ make CONFIG=configs/ci/ihp130.mk HAVE_CSR=YES APP=ci_smoke SIMU=VERILATOR firmwa
|
||||
|
||||
Completion: GA2D-V01/V03/V08 platform cases pass with master-8 BFM traffic,
|
||||
old/new IDs cannot alias, the new source has one credit per direction, and
|
||||
all target/monitor routes retain ID7. Include affected synthesis/STA and
|
||||
export/netlist evidence; a parameter-only elaboration pass is insufficient.
|
||||
all target/monitor routes retain ID7. Synthesis, STA, netlist, warning, and
|
||||
metric evidence is deferred exclusively to Phase 6; a parameter-only
|
||||
elaboration pass is insufficient for this phase's directed platform cases.
|
||||
|
||||
### Phase 3 - GA2D Naming Migration and APB4 Shell
|
||||
|
||||
@@ -1115,7 +1123,8 @@ ID: `GA2D-P6`.
|
||||
Dependencies: Phase 5 and resolution/evidence of applicable baseline gaps.
|
||||
Scope: complete HAL/host checks, real LP ISR and HP acceptance payloads,
|
||||
cache/ownership handoff, deterministic benchmark/report artifacts, randomized
|
||||
campaign, competing-master progress, full regression, and physical evidence.
|
||||
campaign, competing-master progress, full regression, and the only GA2D
|
||||
synthesis/timing/netlist/physical-evidence execution phase.
|
||||
|
||||
Changes: tests, SDK/app acceptance and benchmark integration, documentation
|
||||
and evidence/readiness records justified by results. No frozen allocation,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
The Mini SoC on-chip SRAM is a synthesis-time configurable AXI4 target backed
|
||||
by fixed 32-bit single-port technology wrappers. The reusable module keeps a
|
||||
32-bit/ID1 compatibility mode; the Mini product instantiates native
|
||||
64-bit/ID6 and stripes each beat over two wrappers. Supported capacities are
|
||||
64-bit/ID7 and stripes each beat over two wrappers. Supported capacities are
|
||||
4, 16, 32, 64, and 128 KiB in compatibility mode; the product selects 32 KiB.
|
||||
The data aperture starts at
|
||||
`0x3000_0000`; its generated end address and linker length match the selected
|
||||
@@ -59,7 +59,7 @@ with `PRESENT=0`, zero memory bytes, and zero banks.
|
||||
|
||||
## AXI4 datapath
|
||||
|
||||
The product target uses 32-bit addresses, 64-bit data, six-bit ID, and one-bit
|
||||
The product target uses 32-bit addresses, 64-bit data, seven-bit ID, and one-bit
|
||||
USER. It accepts one active read or write transaction, gives AR priority when
|
||||
AR and AW are simultaneously valid, and preserves the ID to the terminal
|
||||
response. The compatibility parameterization retains 32-bit data and one-bit
|
||||
@@ -142,7 +142,7 @@ malformed accesses, counters, all four PDK wrapper polarities and masks, and
|
||||
the GF180 511/512 depth boundary. The setup tests independently validate the
|
||||
SKY130 artifact manifest and generated-file hashes. Full Verilator regression
|
||||
firmware exercises the first and last locations through the SoC interconnect.
|
||||
The native AXI64 test additionally covers six-bit IDs, continuous 64-bit bursts,
|
||||
The native AXI64 test additionally covers seven-bit IDs, continuous 64-bit bursts,
|
||||
and upper/lower 32-bit byte strobes.
|
||||
|
||||
`make CONFIG=configs/ci/ihp130.mk formal-onchip-ram` runs a 20-cycle bounded
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Mini Resource Controller
|
||||
|
||||
The approved [GA2D contract](ga2d.md) adds resource 8 and version 1.1 during
|
||||
its Phase 2, with LP vector 32 / HP PLIC source 11 connected in Phase 3.
|
||||
Its source-stop/drain-before-block sequence is specified there. These changes
|
||||
are pending implementation; the existing resources and register fields below
|
||||
are not renumbered or reinterpreted by the documentation freeze.
|
||||
[GA2D Phase 2](ga2d.md#phase-2---expand-axi64-fabric-and-resource-integration)
|
||||
adds resource 8 and version 1.1. It covers only the dedicated PCLK-to-HP
|
||||
AXI64/ID3 GA2D bridge placeholder, whose source is idle. LP vector 32 / HP
|
||||
PLIC source 11 and GA2D APB-shell wiring remain Phase 3 work; `APB4_GA`
|
||||
therefore remains reserved and inactive. Its source-stop/drain-before-block
|
||||
sequence is specified there. Existing resources and register fields are not
|
||||
renumbered or reinterpreted.
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -27,17 +29,20 @@ Resource indices are fixed:
|
||||
| 5 | EXT-H | 3 |
|
||||
| 6 | JPEG | 9 |
|
||||
| 7 | APU | 10 |
|
||||
| 8 | GA2D bridge placeholder (idle) | 11, not routed until Phase 3 |
|
||||
|
||||
Owner `0` routes the resource interrupt to the existing LP vector. Owner `1`
|
||||
removes it from LP and routes it to the listed HP PLIC source. Reset masks both
|
||||
routes. Hardware never delivers one resource interrupt to both owners.
|
||||
For resources 0 through 7, owner `0` routes the resource interrupt to the
|
||||
existing LP vector. Owner `1` removes it from LP and routes it to the listed HP
|
||||
PLIC source. Resource 8 has a fixed-inactive raw IRQ and no LP or HP IRQ route
|
||||
until Phase 3. Reset masks both applicable routes. Hardware never delivers one
|
||||
resource interrupt to both owners.
|
||||
|
||||
## Register ABI
|
||||
|
||||
| Offset | Name | Access | Contract |
|
||||
| ---: | --- | --- | --- |
|
||||
| `0x000` | `IP_ID` | RO | `0x52534354` (`RSCT`) |
|
||||
| `0x004` | `IP_VERSION` | RO | `0x00010000` |
|
||||
| `0x004` | `IP_VERSION` | RO | `0x00010001` |
|
||||
| `0x008` | `CAPABILITY` | RO | resource count and ABI capability |
|
||||
| `0x00C` | `GLOBAL_STATUS` | RO | cache request/clean and resource fault summary |
|
||||
| `0x010` | `CACHE_CONTROL` | RW | bit 0 clean ACK, bit 1 live request |
|
||||
@@ -61,6 +66,13 @@ leaves the owner unchanged, and raises the resource-fault interrupt on LP IRQ
|
||||
condition for DMA and I/O resources; this is safe but can delay an otherwise
|
||||
independent handoff.
|
||||
|
||||
For resource 8, the PCLK source stop admits an already presented address
|
||||
handshake before closing new traffic. Its HP block and acknowledgement require
|
||||
a fresh synchronized source-quiesced confirmation after the source has drained
|
||||
its AXI state. This prevents a stale idle indication from acknowledging a legal
|
||||
`WVALID`-before-`AWVALID` write. The PCLK controller view also qualifies
|
||||
resource-8 idle and ACK with the live source-safe-idle signal.
|
||||
|
||||
## Cache Maintenance
|
||||
|
||||
VexiiRiscv implements `Zicbom` with a 64-byte CBO block. On HP shutdown the AON
|
||||
@@ -78,11 +90,13 @@ and a Linux platform driver remain software responsibilities.
|
||||
## Delivery Boundary
|
||||
|
||||
Central owner/lock, quiesce-gated handoff, cache request/ACK, fault IRQ, and
|
||||
LP/HP IRQ routing are implemented and directed-tested. `CONTROL.QUIESCE`
|
||||
blocks the corresponding data-crossbar master and waits per-master outstanding
|
||||
zero; shared I/O gateways are conservatively blocked as a pair. `CONTROL.RESET`
|
||||
also blocks new data and masks IRQ but is not yet connected to every peripheral
|
||||
engine's internal reset state machine. The APU-P1 shell is an exception: its
|
||||
index-7 quiesce acknowledgement and reset are connected locally in PCLK. It
|
||||
must not be described as independent peripheral power isolation or reset containment until
|
||||
LP/HP IRQ routing are implemented and directed-tested. P2 appends resource 8
|
||||
for the idle GA2D bridge placeholder only; it creates no GA2D IRQ route or
|
||||
functional GA2D peripheral. `CONTROL.QUIESCE` blocks the corresponding
|
||||
data-crossbar master and waits per-master outstanding zero; shared I/O gateways
|
||||
are conservatively blocked as a pair. `CONTROL.RESET` also blocks new data and
|
||||
masks IRQ but is not yet connected to every peripheral engine's internal reset
|
||||
state machine. The APU-P1 shell is an exception: its index-7 quiesce
|
||||
acknowledgement and reset are connected locally in PCLK. It must not be
|
||||
described as independent peripheral power isolation or reset containment until
|
||||
those downstream acknowledgements and fault-injection tests exist.
|
||||
+1
-1
@@ -12,7 +12,7 @@ timings expressed in SDRAM-clock cycles.
|
||||
| AXI4 data window | `0x38000000` - `0x3BFFFFFF` |
|
||||
| Data window size | 64 MiB |
|
||||
| APB4 configuration window | `0x1000D000` - `0x1000DFFF` |
|
||||
| SoC data boundary | 64-bit AXI/ID6 from HP into the stable memory domain |
|
||||
| SoC data boundary | 64-bit AXI/ID7 from HP into the stable memory domain |
|
||||
| Controller frontend | local 64-to-32 adaptation, then 32-bit AXI over SDRAM x16 |
|
||||
| Address organization | 2-bit bank, 13-bit row, 10-bit column |
|
||||
| Physical interface | `sdram_if` (`BA[1:0]`, `A[12:0]`, `DQ[15:0]`) |
|
||||
|
||||
+9
-2
@@ -17,7 +17,14 @@ enable/clear, and sticky terminal test result. It receives user-bus idle,
|
||||
fault metadata, ten wait counters (including independent SDIO0 and SDIO1
|
||||
master wait counters), and asynchronous RTC wake. `sysctrl_core`
|
||||
synchronizes RTC wake with the Common `cdc_sync` primitive before storing its
|
||||
sticky state.
|
||||
sticky state. HP data-plane faults cross into PCLK through an acknowledged
|
||||
mailbox. Their HP sources use valid/ready flow control and retain the complete
|
||||
44-bit `{master,target,address,write,reason}` payload until the mailbox
|
||||
accepts it, so every accepted no-reset event is delivered once with coherent
|
||||
metadata. A reset in either mailbox domain aborts an item already accepted by
|
||||
the mailbox; a unilateral PCLK reset backpressures an unaccepted HP source
|
||||
event until the link is released. A data-plane fault visible in the same PCLK
|
||||
cycle as a local bus fault retains data-plane priority.
|
||||
|
||||
`pll_ctrl_if` carries a one-request PLL configuration handshake. SystemCtrl
|
||||
asserts `req_valid_o` after a valid `PLL_CMD.APPLY`, holds `busy` until the
|
||||
@@ -56,7 +63,7 @@ offset macros.
|
||||
| `0x01C` | `PLL_STATUS` | RO | Active profile, valid, busy, error/error reason, safe clock, lock, and capability. |
|
||||
| `0x020` | `USER_CORE_RESET` | RO/unsupported | Product reads all ones and rejects writes. MPW retains its reset mask. |
|
||||
| `0x024` | `USER_CORE_STATUS` | RO/unsupported | Product reports present=0, idle=1, and sticky unsupported-write error. |
|
||||
| `0x028` | `FAULT_MASTER` | RO | First fault master, a three-bit AXI master ID (0..7); HP is 7. |
|
||||
| `0x028` | `FAULT_MASTER` | RO | First fault master, a four-bit AXI master ID (0..8); HP is 7 and the P2 GA2D bridge placeholder is 8. The offset is unchanged. |
|
||||
| `0x02C` | `FAULT_DETAIL` | RO | First raw RIB response code. |
|
||||
| `0x040` | `PERF_CTRL` | RW | Bit 0 enable, bit 1 clear pulse, bit 2 snapshot pulse. |
|
||||
| `0x044`-`0x098` | `PERF_*_WAIT_{LO,HI}` | RO | Snapshot of management, user, central DMA, SDIO0, SDIO1, APB4, SDRAM, PSRAM, and flash wait counters. |
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# Mini Product LP/HP Architecture
|
||||
|
||||
The frozen [GA2D specification](ip/ga2d.md) approves a phased expansion to a
|
||||
64-bit LP interrupt vector, nine AXI64 masters with seven-bit global IDs, and
|
||||
Resource Controller entry 8. These are pending implementation requirements;
|
||||
this document's current-product descriptions do not imply those phases have
|
||||
already been delivered. Existing hart, memory, and source identities remain fixed.
|
||||
The frozen [GA2D specification](ip/ga2d.md) defines the phased GA2D delivery.
|
||||
Phase 2 expands the implemented platform to nine AXI64 masters with seven-bit
|
||||
global IDs and Resource Controller entry 8. Its dedicated PCLK-to-HP
|
||||
AXI64/ID3 bridge is an idle placeholder only. `APB4_GA` remains reserved and
|
||||
inactive, and the GA2D APB shell, IRQ, payload/DMA, and pixel function remain
|
||||
deferred. Existing hart, memory, and source identities remain fixed.
|
||||
|
||||
## Product contract
|
||||
|
||||
@@ -78,7 +79,7 @@ same memory admission, inactive-pad, ACL, and fault path as HP and DMA.
|
||||
|
||||
## Native AXI64 data plane
|
||||
|
||||
`soc_data_plane` contains an 8-master, 6-target AXI64 crossbar. Read and write
|
||||
`soc_data_plane` contains a 9-master, 6-target AXI64 crossbar. Read and write
|
||||
channels progress independently, and different source IDs may be active against
|
||||
the same or different targets. The same source ID is blocked until completion.
|
||||
SRAM and SDRAM accept four reads and two writes; serial memories and the error
|
||||
@@ -94,9 +95,10 @@ and a Common FIFO preserves write-data order where AXI4 W has no ID.
|
||||
| I/O gateway B | SDIO1 and SPI-SD, then PCLK-to-HP CDC and upsizer |
|
||||
| LP data gateway | Hazard3 memory traffic, LP-to-HP CDC and upsizer |
|
||||
| EXT-H | PCLK-to-HP AXI64 async bridge, ID prefix 7 |
|
||||
| GA2D bridge placeholder | dedicated PCLK-to-HP AXI64/ID3 async bridge; source held idle |
|
||||
|
||||
Targets are SRAM, SDRAM, QPI PSRAM, OPI/HyperBus PSRAM, XPI/flash, and a
|
||||
finite-latency error slave. SRAM is a native AXI64, six-bit-ID target in HP and
|
||||
finite-latency error slave. SRAM is a native AXI64, seven-bit-ID target in HP and
|
||||
stripes each beat across two existing 32-bit technology macros. SDRAM, QPI,
|
||||
OPI, and XPI cross directly from HP to the stable memory domain as AXI64 and
|
||||
are downsized only beside their current 32-bit controller frontends. Serial
|
||||
@@ -113,6 +115,14 @@ All async AXI channels use Common coordinated warm-flush FIFOs and expose a
|
||||
source-domain epoch. HP shutdown holds a flush request until every bridge sees
|
||||
it, then waits for bridge recovery before resetting the core.
|
||||
|
||||
`data_plane_fault_cdc` carries HP fault metadata to PCLK through Common's
|
||||
one-entry `async_reqack` mailbox. The crossbar and target guards hold a
|
||||
valid, stable 44-bit fault payload until its ready handshake, applying
|
||||
backpressure before another reportable fault can retire. Reset in either
|
||||
mailbox domain aborts an item already accepted by the mailbox; a unilateral
|
||||
PCLK reset keeps an unaccepted HP-source event backpressured until the link
|
||||
is released.
|
||||
|
||||
## Memory and shared pads
|
||||
|
||||
Product profiles instantiate on-chip SRAM, SDRAM, QPI, OPI/HyperBus, and XPI
|
||||
@@ -144,11 +154,16 @@ Its IRQ is delivered to LP IRQ 28 or HP PLIC source 3 according to owner,
|
||||
never both. Software discovers it through `<retrosoc/hal/extension.h>`.
|
||||
|
||||
The Resource Controller at `0x2000_A000` is the central owner and IRQ authority
|
||||
for DMA, USB2, SDIO0/1, SPI-SD, EXT-H, JPEG, and APU. Handoff requires idle,
|
||||
for DMA, USB2, SDIO0/1, SPI-SD, EXT-H, JPEG, and APU, and the lifecycle
|
||||
authority for the idle GA2D bridge placeholder. Resource 8 has no routed IRQ
|
||||
until Phase 3. Handoff requires idle,
|
||||
owner lock is sticky, and rejected handoffs raise LP IRQ 29. APU index 7 routes
|
||||
exclusively to LP IRQ31 or HP PLIC source10. The controller also carries the
|
||||
AON cache request/clean acknowledgement used before HP drain. See
|
||||
[`ip/resource-controller.md`](ip/resource-controller.md).
|
||||
Resource 8 qualifies its HP block acknowledgement with a fresh synchronized
|
||||
source-quiesced state, so an old idle sample cannot hand off a
|
||||
`WVALID`-before-`AWVALID` write.
|
||||
|
||||
The root-only Fabric Monitor at `0x2000_B000` records per-master and
|
||||
per-target traffic, wait, promotion, credit high-water, timeout, isolation,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| Target-aware multi-outstanding AXI64 | Data crossbar | Multi-ID, ordering, backpressure, and formal tests | implemented: SRAM/SDRAM use 4R/2W credits; serial targets use 1R/1W; full formal proof pending |
|
||||
| LP access to every memory window through the data plane | LP data gateway | no-PLL boot and memory-window smoke | implemented |
|
||||
| Bounded QoS and recovery priority | Data crossbar | starvation and emergency-promotion test | implemented and directed-tested at a reduced four-cycle bound; production bound is 256 cycles and full liveness proof remains pending |
|
||||
| Initiator ACL and first-fault attribution | Generated data policy, crossbar, SYSCTRL, and Fabric Monitor | target/execute/cache/range denial and injection tests | implemented: fixed policy is topology-generated and the monitor retains the first pulse across APB CDC |
|
||||
| Initiator ACL and first-fault attribution | Generated data policy, crossbar, SYSCTRL, and Fabric Monitor | target/execute/cache/range denial and injection tests | implemented: fixed policy is topology-generated and valid/ready fault reporting retains every accepted event across the HP/PCLK CDC |
|
||||
| Stable memory functional clocks | Memory integration | HP DFS while refresh/protocol engines continue | implemented digitally: SRAM is native HP AXI64; SDRAM and all serial targets cross directly from HP to stable memory as AXI64 before local downsizing |
|
||||
| Reset epoch and stale-response rejection | Async bridges | unilateral reset and clock-stop matrix | partial: coordinated warm flush and epoch implemented |
|
||||
| HP normal and forced hot reset | AON lifecycle controller and Resource Controller | cache request/ACK, drain, timeout, flush, and recovery tests | implemented digitally: Zicbom and bounded ACK window exist; range policy and Linux service remain software work |
|
||||
|
||||
@@ -114,7 +114,7 @@ digraph mini_soc_block_diagram {
|
||||
];
|
||||
data_plane [
|
||||
fillcolor="#BFDBFE",
|
||||
label="Native AXI64 Data Plane\n8 masters x 6 targets, global ID6\ntarget credits, QoS aging, generated ACL",
|
||||
label="Native AXI64 Data Plane\n9 masters x 6 targets, global ID7\ntarget credits, QoS aging, generated ACL",
|
||||
shape=hexagon
|
||||
];
|
||||
guards [
|
||||
@@ -123,7 +123,7 @@ digraph mini_soc_block_diagram {
|
||||
];
|
||||
sram [
|
||||
fillcolor="#FDE68A",
|
||||
label="32 KiB on-chip SRAM\nnative AXI64 / ID6"
|
||||
label="32 KiB on-chip SRAM\nnative AXI64 / ID7"
|
||||
];
|
||||
monitor [
|
||||
fillcolor="#FCE7F3",
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
<title>data_plane</title>
|
||||
<path fill="#bfdbfe" stroke="#4b5563" stroke-width="1.1" d="M1871.04,-420.1C1871.04,-420.1 1811.22,-448.16 1811.22,-448.16 1805.79,-450.7 1794.36,-453.25 1788.36,-453.25 1788.36,-453.25 1649.26,-453.25 1649.26,-453.25 1643.26,-453.25 1631.83,-450.7 1626.39,-448.16 1626.39,-448.16 1566.57,-420.1 1566.57,-420.1 1561.14,-417.55 1561.14,-412.45 1566.57,-409.9 1566.57,-409.9 1626.39,-381.84 1626.39,-381.84 1631.83,-379.3 1643.26,-376.75 1649.26,-376.75 1649.26,-376.75 1788.36,-376.75 1788.36,-376.75 1794.36,-376.75 1805.79,-379.3 1811.22,-381.84 1811.22,-381.84 1871.04,-409.9 1871.04,-409.9 1876.47,-412.45 1876.47,-417.55 1871.04,-420.1"/>
|
||||
<text text-anchor="middle" x="1718.81" y="-423.5" font-family="Arial" font-size="10.00" fill="#111827">Native AXI64 Data Plane</text>
|
||||
<text text-anchor="middle" x="1718.81" y="-412.5" font-family="Arial" font-size="10.00" fill="#111827">8 masters x 6 targets, global ID6</text>
|
||||
<text text-anchor="middle" x="1718.81" y="-412.5" font-family="Arial" font-size="10.00" fill="#111827">9 masters x 6 targets, global ID7</text>
|
||||
<text text-anchor="middle" x="1718.81" y="-401.5" font-family="Arial" font-size="10.00" fill="#111827">target credits, QoS aging, generated ACL</text>
|
||||
</g>
|
||||
<!-- aon->data_plane -->
|
||||
@@ -297,7 +297,7 @@
|
||||
<title>sram</title>
|
||||
<path fill="#fde68a" stroke="#4b5563" stroke-width="1.1" d="M2498.61,-491C2498.61,-491 2405.61,-491 2405.61,-491 2399.61,-491 2393.61,-485 2393.61,-479 2393.61,-479 2393.61,-467 2393.61,-467 2393.61,-461 2399.61,-455 2405.61,-455 2405.61,-455 2498.61,-455 2498.61,-455 2504.61,-455 2510.61,-461 2510.61,-467 2510.61,-467 2510.61,-479 2510.61,-479 2510.61,-485 2504.61,-491 2498.61,-491"/>
|
||||
<text text-anchor="middle" x="2452.11" y="-476" font-family="Arial" font-size="10.00" fill="#111827">32 KiB on-chip SRAM</text>
|
||||
<text text-anchor="middle" x="2452.11" y="-465" font-family="Arial" font-size="10.00" fill="#111827">native AXI64 / ID6</text>
|
||||
<text text-anchor="middle" x="2452.11" y="-465" font-family="Arial" font-size="10.00" fill="#111827">native AXI64 / ID7</text>
|
||||
</g>
|
||||
<!-- guards->sram -->
|
||||
<g id="edge17" class="edge">
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -141,9 +141,12 @@ capabilities:
|
||||
- The canonical address map exposes configurable on-chip SRAM, a 64 MiB SDRAM
|
||||
window, and an 8 MiB PSRAM window. Address-window capacity does not guarantee
|
||||
that every implementation includes the corresponding physical memory.
|
||||
- AXI4 uses a 32-bit LP control plane and an 8x6 native AXI64 HP data plane.
|
||||
Vexii I/D ports remain independent; DMA and I/O masters cross into HP and
|
||||
current memory frontends are reached through 64-to-32 target adapters.
|
||||
- AXI4 uses a 32-bit LP control plane and a 9x6 native AXI64 HP data plane
|
||||
with seven-bit global IDs. Vexii I/D ports remain independent; DMA and I/O
|
||||
masters cross into HP and current memory frontends are reached through
|
||||
64-to-32 target adapters. Master 8 is a dedicated PCLK-to-HP AXI64/ID3 GA2D
|
||||
bridge whose source is idle; `APB4_GA` remains reserved and inactive, and no
|
||||
GA2D APB shell, IRQ, payload/DMA, or pixel function is implemented.
|
||||
- Current external-memory targets serialize accepted AXI4 bursts into ordered
|
||||
scalar engine accesses. They do not yet combine a burst into a native SDRAM,
|
||||
PSRAM, flash, or SPI-SD physical transaction.
|
||||
|
||||
@@ -8020,19 +8020,19 @@
|
||||
{
|
||||
"id": "p1",
|
||||
"direction": "in",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "west"
|
||||
},
|
||||
{
|
||||
"id": "p2",
|
||||
"direction": "out",
|
||||
"width": 16,
|
||||
"width": 18,
|
||||
"side": "east"
|
||||
},
|
||||
{
|
||||
"id": "p3",
|
||||
"direction": "out",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "south"
|
||||
}
|
||||
],
|
||||
@@ -8058,7 +8058,7 @@
|
||||
{
|
||||
"id": "p1",
|
||||
"direction": "out",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "east"
|
||||
}
|
||||
],
|
||||
@@ -8077,7 +8077,7 @@
|
||||
{
|
||||
"id": "p2",
|
||||
"direction": "in",
|
||||
"width": 16,
|
||||
"width": 18,
|
||||
"side": "west"
|
||||
}
|
||||
],
|
||||
@@ -8096,7 +8096,7 @@
|
||||
{
|
||||
"id": "p3",
|
||||
"direction": "in",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "north"
|
||||
}
|
||||
],
|
||||
@@ -8144,7 +8144,7 @@
|
||||
"file": "rtl/mini/top/apb4_system.sv",
|
||||
"scope": "apb4_system",
|
||||
"symbol": "resource_idle_i",
|
||||
"bits": 8
|
||||
"bits": 9
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -8172,7 +8172,7 @@
|
||||
"file": "rtl/mini/top/apb4_system.sv",
|
||||
"scope": "apb4_system",
|
||||
"symbol": "s_resource_owner",
|
||||
"bits": 16
|
||||
"bits": 18
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -8200,7 +8200,7 @@
|
||||
"file": "rtl/mini/top/apb4_system.sv",
|
||||
"scope": "apb4_system",
|
||||
"symbol": "s_resource_irq_lp",
|
||||
"bits": 8
|
||||
"bits": 9
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -8213,7 +8213,7 @@
|
||||
"zigzag-dir": "horizontal"
|
||||
}
|
||||
],
|
||||
"note": "Eight resources retain independent owner/lock/quiesce/reset state. IRQ steering and cache-clean coordination are control relationships, not a hardware cache-coherence implementation."
|
||||
"note": "Nine resources retain independent owner/lock/quiesce/reset state; resource 8 is the idle GA2D bridge placeholder only. IRQ steering and cache-clean coordination are control relationships, not a hardware cache-coherence implementation."
|
||||
},
|
||||
"monitor": {
|
||||
"nodes": [
|
||||
@@ -8228,7 +8228,7 @@
|
||||
{
|
||||
"id": "p0",
|
||||
"direction": "out",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "east"
|
||||
}
|
||||
],
|
||||
@@ -8247,7 +8247,7 @@
|
||||
{
|
||||
"id": "p0",
|
||||
"direction": "in",
|
||||
"width": 8,
|
||||
"width": 9,
|
||||
"side": "west"
|
||||
},
|
||||
{
|
||||
@@ -8331,7 +8331,7 @@
|
||||
"file": "rtl/mini/top/soc_data_plane.sv",
|
||||
"scope": "soc_data_plane",
|
||||
"symbol": "s_monitor_master_read_accept",
|
||||
"bits": 8
|
||||
"bits": 9
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -8351,7 +8351,7 @@
|
||||
"bindings": [
|
||||
{
|
||||
"file": "rtl/mini/top/soc_data_plane.sv",
|
||||
"text": ".fault_valid_i(fault_valid_o)"
|
||||
"text": ".fault_valid_i(fault_valid_o && fault_ready_i)"
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
@@ -8366,7 +8366,7 @@
|
||||
{
|
||||
"node": "core",
|
||||
"port": "fault_valid_i",
|
||||
"expression": "fault_valid_o"
|
||||
"expression": "fault_valid_o && fault_ready_i"
|
||||
}
|
||||
],
|
||||
"zigzag-dir": "horizontal"
|
||||
@@ -8573,7 +8573,7 @@
|
||||
"instance_ports": []
|
||||
}
|
||||
],
|
||||
"note": "PRODUCT uses a native AXI64/ID6 SRAM target in the HP clock domain. The selected IHP130 profile supplies 32 KiB. Bank count and physical macro organization are distinct from the address aperture."
|
||||
"note": "PRODUCT uses a native AXI64/ID7 SRAM target in the HP clock domain. The selected IHP130 profile supplies 32 KiB. Bank count and physical macro organization are distinct from the address aperture."
|
||||
},
|
||||
"xpi": {
|
||||
"nodes": [
|
||||
@@ -9676,7 +9676,7 @@
|
||||
},
|
||||
{
|
||||
"file": "rtl/mini/top/axi4_data_crossbar.sv",
|
||||
"text": "function automatic logic [CountWidth-1:0] master_read_limit(input int unsigned master); if ((master <= 2) || (master == 7)) return CountWidth'(4); if ((master == 3) || (master == 4)) return CountWidth'(2); if (master == 5) return CountWidth'(1); return '0; endfunction"
|
||||
"text": "function automatic logic [CountWidth-1:0] master_read_limit(input int unsigned master); if ((master <= 2) || (master == 7)) return CountWidth'(4); if ((master == 3) || (master == 4)) return CountWidth'(2); if (master == 5) return CountWidth'(1); if (master == 8) return CountWidth'(1); return '0; endfunction"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -10903,7 +10903,7 @@
|
||||
},
|
||||
{
|
||||
"id": "sram",
|
||||
"title": "HP-domain SRAM\nnative AXI64 / ID6",
|
||||
"title": "HP-domain SRAM\nnative AXI64 / ID7",
|
||||
"x": 12.6,
|
||||
"y": 3.5,
|
||||
"w": 4.0,
|
||||
@@ -11513,7 +11513,7 @@
|
||||
},
|
||||
{
|
||||
"file": "rtl/mini/top/axi4_data_crossbar.sv",
|
||||
"text": "function automatic logic [CountWidth-1:0] master_read_limit(input int unsigned master); if ((master <= 2) || (master == 7)) return CountWidth'(4); if ((master == 3) || (master == 4)) return CountWidth'(2); if (master == 5) return CountWidth'(1); return '0; endfunction"
|
||||
"text": "function automatic logic [CountWidth-1:0] master_read_limit(input int unsigned master); if ((master <= 2) || (master == 7)) return CountWidth'(4); if ((master == 3) || (master == 4)) return CountWidth'(2); if (master == 5) return CountWidth'(1); if (master == 8) return CountWidth'(1); return '0; endfunction"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
|
||||
@@ -150,12 +150,12 @@
|
||||
"Lifecycle-gated device identity reads."
|
||||
],
|
||||
"resource": [
|
||||
"Eight independently managed shared resources.",
|
||||
"Nine independently managed shared resources; resource 8 is the idle GA2D bridge placeholder only.",
|
||||
"Owner locks, quiesce/reset and LP/HP IRQ routing.",
|
||||
"Explicit cache-maintenance handoff and sticky faults."
|
||||
],
|
||||
"monitor": [
|
||||
"Eight master and six target observation banks.",
|
||||
"Nine master and six target observation banks; bank 8 observes the idle GA2D bridge placeholder.",
|
||||
"Saturating counters, snapshots and outstanding high-water marks.",
|
||||
"Sticky first-fault attribution and live isolation status."
|
||||
],
|
||||
|
||||
@@ -333,7 +333,7 @@
|
||||
"sources": [
|
||||
"docs/ip/resource-controller.md"
|
||||
],
|
||||
"summary": "LP-controlled ownership, quiesce, reset and LP/HP IRQ routing for eight resources."
|
||||
"summary": "LP-controlled ownership, quiesce, reset and LP/HP IRQ routing for nine resources; resource 8 is the idle GA2D bridge placeholder only."
|
||||
},
|
||||
{
|
||||
"id": "monitor",
|
||||
@@ -344,7 +344,7 @@
|
||||
"sources": [
|
||||
"docs/ip/fabric-monitor.md"
|
||||
],
|
||||
"summary": "Snapshot counters and sticky fault attribution beside the HP data crossbar."
|
||||
"summary": "Nine-master/six-target snapshot counters and sticky fault attribution beside the HP data crossbar; bank 8 observes the idle GA2D bridge placeholder."
|
||||
},
|
||||
{
|
||||
"id": "i2s",
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#ip("resource")
|
||||
|
||||
#ip-reference("resource","resource",4,legacy:[
|
||||
Eight resources are managed: central DMA, USB2, SDIO0, SDIO1, SPI-SD, EXT-H, JPEG and APU.
|
||||
Nine resources are managed: central DMA, USB2, SDIO0, SDIO1, SPI-SD, EXT-H, JPEG,
|
||||
APU, and the idle GA2D bridge placeholder. Resource 8 has no routed IRQ in Phase 2.
|
||||
Ownership changes require quiesce, completion of accepted traffic and cache-maintenance
|
||||
handoff. HP can inspect allowed status but cannot take over root writes. An ownership grant
|
||||
does not bypass the target access policy or EXT-H address bounds.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#ip-reference("sram","sram",5,legacy:[
|
||||
The reference profile selects eight 4 KiB banks for 32 KiB total. The configuration accepts
|
||||
4, 16, 32, 64 or 128 KiB; only 32 KiB is selected by the committed product profiles.
|
||||
SRAM has a native AXI64/ID6 data interface in the HP domain and an APB4 configuration window.
|
||||
SRAM has a native AXI64/ID7 data interface in the HP domain and an APB4 configuration window.
|
||||
Technology macros and behavioral models are selected by the configuration. A larger configurable
|
||||
capacity is not a statement of qualified area, timing or yield.
|
||||
])
|
||||
|
||||
@@ -35,7 +35,7 @@ paths and APB4 register targets. The compatibility RIBP boundary for selected MP
|
||||
described in @mpw. It is not the PRODUCT data fabric.
|
||||
|
||||
The LP control fabric uses 32-bit data. APB accesses cross LP to PCLK through asynchronous
|
||||
request/response bridges. The HP data plane uses 64-bit data, 32-bit addresses and six-bit
|
||||
request/response bridges. The HP data plane uses 64-bit data, 32-bit addresses and seven-bit
|
||||
global transaction IDs. Adapters preserve byte lanes and response attribution across width
|
||||
and clock boundaries. HP MMIO cannot write root-owned SYSCTRL/RCU, watchdog, GPIO administration
|
||||
and other protected management controls.
|
||||
|
||||
@@ -590,7 +590,7 @@
|
||||
"id": "resource",
|
||||
"title": "Resource Controller",
|
||||
"implementation": "Partial",
|
||||
"scope": "Eight independently managed shared resources.",
|
||||
"scope": "Nine independently managed shared resources; resource 8 is the idle GA2D bridge placeholder only.",
|
||||
"dependencies": "No additional off-chip component implied; use the selected clock/reset and access policy.",
|
||||
"hal": "Published API and syntax example; see the IP chapter.",
|
||||
"linux": "Native driver support not established in this publication.",
|
||||
@@ -610,7 +610,7 @@
|
||||
"id": "monitor",
|
||||
"title": "Fabric Monitor",
|
||||
"implementation": "Integrated",
|
||||
"scope": "Eight master and six target observation banks.",
|
||||
"scope": "Nine master and six target observation banks; bank 8 observes the idle GA2D bridge placeholder.",
|
||||
"dependencies": "No additional off-chip component implied; use the selected clock/reset and access policy.",
|
||||
"hal": "Published API and syntax example; see the IP chapter.",
|
||||
"linux": "Native driver support not established in this publication.",
|
||||
|
||||
@@ -206,10 +206,10 @@
|
||||
"parameters": {
|
||||
"ADDR_WIDTH": 32,
|
||||
"DATA_WIDTH": 64,
|
||||
"ID_WIDTH": 6,
|
||||
"ID_WIDTH": 7,
|
||||
"USER_WIDTH": 1
|
||||
},
|
||||
"parameter_note": "Native PRODUCT data fabric is AXI64 with six-bit IDs; this example uses only the data channel."
|
||||
"parameter_note": "Native PRODUCT data fabric is AXI64 with seven-bit IDs; this example uses only the data channel."
|
||||
},
|
||||
"axis": {
|
||||
"source": {
|
||||
@@ -2059,9 +2059,9 @@
|
||||
],
|
||||
"review_note": "Replaced resource-busy/cache-handoff prose with actual admission, idle, acknowledgement and owner ports. Reviewed owner-write guards.",
|
||||
"parameters": {
|
||||
"ResourceCount": 8
|
||||
"ResourceCount": 9
|
||||
},
|
||||
"parameter_note": "The reviewed resource-controller integration tracks eight resource positions."
|
||||
"parameter_note": "The reviewed resource-controller integration tracks nine resource positions."
|
||||
},
|
||||
"monitor": {
|
||||
"source": {
|
||||
@@ -2134,10 +2134,10 @@
|
||||
],
|
||||
"review_note": "Removed invented SNAPSHOT and snapshot-valid signals; used actual control decode and live/snapshot register arrays.",
|
||||
"parameters": {
|
||||
"NumMasters": 8,
|
||||
"NumMasters": 9,
|
||||
"NumTargets": 6
|
||||
},
|
||||
"parameter_note": "Reference monitor parameters are eight masters and six target positions."
|
||||
"parameter_note": "Reference monitor parameters are nine masters and six target positions."
|
||||
},
|
||||
"sysctrl": {
|
||||
"source": {
|
||||
@@ -2319,7 +2319,7 @@
|
||||
"parameters": {
|
||||
"ADDR_WIDTH": 32,
|
||||
"DATA_WIDTH": 64,
|
||||
"ID_WIDTH": 6,
|
||||
"ID_WIDTH": 7,
|
||||
"USER_WIDTH": 1
|
||||
},
|
||||
"parameter_note": "The PRODUCT SRAM data port is native AXI64."
|
||||
|
||||
@@ -124,7 +124,7 @@ module sysctrl_core (
|
||||
logic [2:0] s_fault_detail_d, s_fault_detail_q;
|
||||
logic [31:0] s_fault_addr_d, s_fault_addr_q;
|
||||
logic [31:0] s_fault_count_d, s_fault_count_q;
|
||||
logic [2:0] s_fault_master_d, s_fault_master_q;
|
||||
logic [3:0] s_fault_master_d, s_fault_master_q;
|
||||
logic s_perf_en_d, s_perf_en_q;
|
||||
logic [63:0] s_perf_mgmt_wait_d, s_perf_mgmt_wait_q;
|
||||
logic [63:0] s_perf_user_wait_d, s_perf_user_wait_q;
|
||||
@@ -653,7 +653,7 @@ module sysctrl_core (
|
||||
s_sysctrl_coresel_q
|
||||
};
|
||||
`endif
|
||||
FaultMaster: read_data_o = {29'd0, s_fault_master_q};
|
||||
FaultMaster: read_data_o = {28'd0, s_fault_master_q};
|
||||
FaultDetail: read_data_o = {29'd0, s_fault_detail_q};
|
||||
PerfCtrl: read_data_o = {31'd0, s_perf_en_q};
|
||||
PerfMgmtWaitLo: read_data_o = s_perf_mgmt_wait_q[31:0];
|
||||
|
||||
@@ -16,7 +16,7 @@ interface sysctrl_if ();
|
||||
logic user_bus_enable_o;
|
||||
logic user_bus_idle_i;
|
||||
logic fault_access_i;
|
||||
logic [ 2:0] fault_master_i;
|
||||
logic [ 3:0] fault_master_i;
|
||||
logic [ 2:0] fault_code_i;
|
||||
logic perf_enable_o;
|
||||
logic perf_clear_o;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
/top/axi4_target_guard.sv
|
||||
/top/fabric_monitor.sv
|
||||
/top/soc_data_plane.sv
|
||||
/top/data_plane_fault_cdc.sv
|
||||
/top/axi4_error_slave.sv
|
||||
/top/rib2axi4.sv
|
||||
/top/ahbl2axi4.sv
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
`soc_topology.json` is the source of truth for internal Mini SoC integration
|
||||
that is not part of the software address-map ABI or the package pad map.
|
||||
|
||||
[GA2D](../../../docs/ip/ga2d.md) defines approved, not yet implemented changes:
|
||||
Phase 1 expands the root LP IRQ vector to 64 bits while retaining the legacy
|
||||
32-bit user-core interface; Phase 2 adds data master/resource 8 and ID7;
|
||||
Phase 3 appends APB slot 28 and GA2D's LP32/HP PLIC11 interrupt. Existing
|
||||
allocations remain stable. Until those phases land, the manifest and generated
|
||||
outputs retain the baseline capacities described below. The Xh3irq SDK path
|
||||
also requires the Phase 1 implementation; a wiring-only expansion is insufficient.
|
||||
[GA2D](../../../docs/ip/ga2d.md) Phase 2 expands the topology to data
|
||||
master/resource 8 and seven-bit global IDs while retaining all existing
|
||||
allocations. It adds only a dedicated PCLK-to-HP AXI64/ID3 GA2D bridge whose
|
||||
source is held idle. `APB4_GA` remains reserved and inactive; the GA2D APB
|
||||
shell, IRQ wiring, payload/DMA, and pixel function remain deferred to later
|
||||
phases. Phase 3 appends APB slot 28 and GA2D's LP32/HP PLIC11 interrupt. The
|
||||
Xh3irq SDK path also requires the Phase 1 implementation; a wiring-only
|
||||
expansion is insufficient.
|
||||
|
||||
The topology generator validates APB4 island ownership against
|
||||
`../address_map/memory_map.json` and emits generated SystemVerilog include
|
||||
@@ -46,7 +47,7 @@ the canonical memory map. Slot 10 is the Resource Controller; slot 11 is the
|
||||
external HP-domain Fabric Monitor reached through its explicit PCLK-to-HP APB
|
||||
bridge.
|
||||
|
||||
`data_master_policies` defines all eight native data-plane master identities,
|
||||
`data_master_policies` defines all nine native data-plane master identities,
|
||||
read/write target sets, instruction permission, and non-cacheable attribute
|
||||
requirements. The generator rejects missing, reordered, or unknown entries
|
||||
and emits packed `soc_data_policy.svh` constants consumed by the crossbar.
|
||||
|
||||
@@ -108,9 +108,28 @@
|
||||
{"name": "sdram_config", "source": "pclk", "destination": "memory", "primitive": "apb4_async_bridge", "path": "rtl/mini/top/retrosoc.sv", "instance": "u_sdram_cfg_cdc"},
|
||||
{"name": "sram_config", "source": "pclk", "destination": "hp", "primitive": "apb4_async_bridge", "path": "rtl/mini/top/retrosoc.sv", "instance": "u_sram_cfg_cdc"},
|
||||
{"name": "fabric_monitor", "source": "pclk", "destination": "hp", "primitive": "apb4_async_bridge", "path": "rtl/mini/top/retrosoc.sv", "instance": "u_fabric_monitor_cdc"},
|
||||
{
|
||||
"name": "data_plane_fault",
|
||||
"source": "hp",
|
||||
"destination": "pclk",
|
||||
"primitive": "async_reqack",
|
||||
"path": "rtl/mini/top/data_plane_fault_cdc.sv",
|
||||
"instance": "u_fault_mailbox",
|
||||
"unilateral_reset": {
|
||||
"source_reset": "abort_accepted_mailbox_item",
|
||||
"destination_reset": "abort_accepted_item_backpressure_unaccepted_source"
|
||||
}
|
||||
},
|
||||
{"name": "io_dma_data", "source": "pclk", "destination": "hp", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_io_cdc"},
|
||||
{"name": "apu_data", "source": "pclk", "destination": "hp", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_io_cdc"},
|
||||
{"name": "jpeg_data", "source": "pclk", "destination": "hp", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_jpeg_cdc"},
|
||||
{"name": "ga2d_data", "source": "pclk", "destination": "hp", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_cdc"},
|
||||
{"name": "ga2d_source_idle", "source": "pclk", "destination": "hp", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_source_idle_sync"},
|
||||
{"name": "ga2d_source_quiesced", "source": "pclk", "destination": "hp", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_source_quiesced_sync"},
|
||||
{"name": "ga2d_hp_reset", "source": "hp", "destination": "pclk", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_hp_reset_sync"},
|
||||
{"name": "ga2d_flush", "source": "hp", "destination": "pclk", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_flush_sync"},
|
||||
{"name": "ga2d_master_idle", "source": "hp", "destination": "pclk", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_master_idle_sync"},
|
||||
{"name": "ga2d_block_ack", "source": "hp", "destination": "pclk", "primitive": "cdc_sync", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ga2d_block_ack_sync"},
|
||||
{"name": "extension_h_data", "source": "pclk", "destination": "hp", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_ext_h_cdc"},
|
||||
{"name": "sdram_data", "source": "hp", "destination": "memory", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_target_cdc"},
|
||||
{"name": "serial_memory_data", "source": "hp", "destination": "memory", "primitive": "axi4_async_bridge", "path": "rtl/mini/top/soc_data_plane.sv", "instance": "u_target_cdc"},
|
||||
|
||||
@@ -29,6 +29,7 @@ DATA_MASTER_NAMES = (
|
||||
"lp_gateway",
|
||||
"jpeg",
|
||||
"ext_h",
|
||||
"ga2d",
|
||||
)
|
||||
DATA_TARGET_NAMES = ("sram", "sdram", "qpi", "opi", "xpi")
|
||||
COMPATIBILITY_IRQ_BINDINGS = (
|
||||
@@ -327,7 +328,9 @@ def parse_fabric_links(value: Any) -> list[FabricLink]:
|
||||
|
||||
def parse_data_master_policies(value: Any) -> list[DataMasterPolicy]:
|
||||
if not isinstance(value, list) or len(value) != len(DATA_MASTER_NAMES):
|
||||
raise ValueError("data_master_policies must define all eight data masters")
|
||||
raise ValueError(
|
||||
f"data_master_policies must define all {len(DATA_MASTER_NAMES)} data masters"
|
||||
)
|
||||
policies: list[DataMasterPolicy] = []
|
||||
for position, entry in enumerate(value):
|
||||
policy = require_object(entry, f"data_master_policies[{position}]")
|
||||
@@ -575,7 +578,7 @@ def render_data_policy(policies: list[DataMasterPolicy]) -> str:
|
||||
)
|
||||
for policy in reversed(policies)
|
||||
)
|
||||
return f"40'b{bits}"
|
||||
return f"{len(policies) * len(DATA_TARGET_NAMES)}'b{bits}"
|
||||
|
||||
instruction_bits = "".join(
|
||||
"1" if policy.allow_instruction else "0" for policy in reversed(policies)
|
||||
@@ -588,8 +591,8 @@ def render_data_policy(policies: list[DataMasterPolicy]) -> str:
|
||||
"// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit.",
|
||||
f"`define {'SOC_DATA_POLICY_READ_TARGET_MASK':<44} {packed_target_mask('read_targets')}",
|
||||
f"`define {'SOC_DATA_POLICY_WRITE_TARGET_MASK':<44} {packed_target_mask('write_targets')}",
|
||||
f"`define {'SOC_DATA_POLICY_ALLOW_INSTRUCTION':<44} 8'b{instruction_bits}",
|
||||
f"`define {'SOC_DATA_POLICY_REQUIRE_NONCACHEABLE':<44} 8'b{noncacheable_bits}",
|
||||
f"`define {'SOC_DATA_POLICY_ALLOW_INSTRUCTION':<44} {len(policies)}'b{instruction_bits}",
|
||||
f"`define {'SOC_DATA_POLICY_REQUIRE_NONCACHEABLE':<44} {len(policies)}'b{noncacheable_bits}",
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
@@ -409,6 +409,14 @@
|
||||
"write_targets": ["sram", "sdram", "qpi", "opi"],
|
||||
"allow_instruction": false,
|
||||
"require_noncacheable": true
|
||||
},
|
||||
{
|
||||
"index": 8,
|
||||
"name": "ga2d",
|
||||
"read_targets": ["sram", "sdram", "qpi", "opi", "xpi"],
|
||||
"write_targets": ["sram", "sdram", "qpi", "opi"],
|
||||
"allow_instruction": false,
|
||||
"require_noncacheable": true
|
||||
}
|
||||
],
|
||||
"apb4_periph_targets": [
|
||||
|
||||
+15
-15
@@ -23,8 +23,8 @@ module apb4_system (
|
||||
input logic rst_aud_n_i,
|
||||
input logic debug_halted_i,
|
||||
input logic ext_h_data_idle_i,
|
||||
input logic [7:0] resource_idle_i,
|
||||
input logic [7:0] resource_block_ack_i,
|
||||
input logic [8:0] resource_idle_i,
|
||||
input logic [8:0] resource_block_ack_i,
|
||||
input logic [6:0] resource_irq_i,
|
||||
input logic cache_request_i,
|
||||
axi4_if.slave axi4,
|
||||
@@ -45,10 +45,10 @@ module apb4_system (
|
||||
output logic ext_h_irq_raw_o,
|
||||
output logic [1:0] ext_h_owner_o,
|
||||
output logic cache_clean_o,
|
||||
output logic [7:0][1:0] resource_owner_o,
|
||||
output logic [7:0] resource_owner_lock_o,
|
||||
output logic [7:0] resource_quiesce_o,
|
||||
output logic [7:0] resource_reset_o,
|
||||
output logic [8:0][1:0] resource_owner_o,
|
||||
output logic [8:0] resource_owner_lock_o,
|
||||
output logic [8:0] resource_quiesce_o,
|
||||
output logic [8:0] resource_reset_o,
|
||||
output logic [6:0] resource_irq_lp_o,
|
||||
output logic [6:0] resource_irq_hp_o,
|
||||
output logic [`SOC_IRQ_APB4_SYSTEM_WIDTH-1:0] irq_o
|
||||
@@ -98,13 +98,13 @@ module apb4_system (
|
||||
logic s_ext_h_irq;
|
||||
logic s_ext_h_irq_raw;
|
||||
logic [ 1:0] unused_ext_h_owner;
|
||||
logic [ 7:0] s_resource_irq;
|
||||
logic [ 7:0] s_resource_irq_lp;
|
||||
logic [ 7:0] s_resource_irq_hp;
|
||||
logic [ 7:0][1:0] s_resource_owner;
|
||||
logic [ 7:0] s_resource_owner_lock;
|
||||
logic [ 7:0] s_resource_quiesce;
|
||||
logic [ 7:0] s_resource_reset;
|
||||
logic [ 8:0] s_resource_irq;
|
||||
logic [ 8:0] s_resource_irq_lp;
|
||||
logic [ 8:0] s_resource_irq_hp;
|
||||
logic [ 8:0][1:0] s_resource_owner;
|
||||
logic [ 8:0] s_resource_owner_lock;
|
||||
logic [ 8:0] s_resource_quiesce;
|
||||
logic [ 8:0] s_resource_reset;
|
||||
logic s_resource_fault_irq;
|
||||
logic s_cache_clean;
|
||||
logic s_unused_resource;
|
||||
@@ -112,7 +112,7 @@ module apb4_system (
|
||||
logic s_unused_product_input;
|
||||
`endif
|
||||
|
||||
assign s_resource_irq = {resource_irq_i[6:5], s_ext_h_irq_raw, resource_irq_i[4:0]};
|
||||
assign s_resource_irq = {1'b0, resource_irq_i[6:5], s_ext_h_irq_raw, resource_irq_i[4:0]};
|
||||
assign s_ext_h_irq = s_resource_irq_lp[5];
|
||||
assign ext_h_irq_raw_o = s_ext_h_irq_raw;
|
||||
assign ext_h_owner_o = s_resource_owner[5];
|
||||
@@ -234,7 +234,7 @@ module apb4_system (
|
||||
apb4_crc u_apb4_crc (.apb4(u_crc_apb4_if));
|
||||
|
||||
resource_controller #(
|
||||
.ResourceCount(8)
|
||||
.ResourceCount(9)
|
||||
) u_resource_controller (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
|
||||
@@ -5,9 +5,11 @@ module axi4_address_gate (
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
input logic block_new_i,
|
||||
input logic clear_i,
|
||||
axi4_if.slave source,
|
||||
axi4_if.master sink,
|
||||
output logic idle_o
|
||||
output logic idle_o,
|
||||
output logic write_pending_o
|
||||
);
|
||||
logic s_write_pending_d;
|
||||
logic s_write_pending_q;
|
||||
@@ -29,15 +31,15 @@ module axi4_address_gate (
|
||||
assign sink.awqos = source.awqos;
|
||||
assign sink.awregion = source.awregion;
|
||||
assign sink.awuser = source.awuser;
|
||||
assign sink.awvalid = source.awvalid && !block_new_i && !s_write_pending_q;
|
||||
assign source.awready = sink.awready && !block_new_i && !s_write_pending_q;
|
||||
assign sink.awvalid = source.awvalid && !block_new_i && !clear_i && !s_write_pending_q;
|
||||
assign source.awready = sink.awready && !block_new_i && !clear_i && !s_write_pending_q;
|
||||
|
||||
assign sink.wdata = source.wdata;
|
||||
assign sink.wstrb = source.wstrb;
|
||||
assign sink.wlast = source.wlast;
|
||||
assign sink.wuser = source.wuser;
|
||||
assign sink.wvalid = source.wvalid && (s_write_pending_q || s_aw_accept);
|
||||
assign source.wready = sink.wready && (s_write_pending_q || s_aw_accept);
|
||||
assign sink.wvalid = source.wvalid && !clear_i && (s_write_pending_q || s_aw_accept);
|
||||
assign source.wready = sink.wready && !clear_i && (s_write_pending_q || s_aw_accept);
|
||||
|
||||
assign source.bid = sink.bid;
|
||||
assign source.bresp = sink.bresp;
|
||||
@@ -56,8 +58,8 @@ module axi4_address_gate (
|
||||
assign sink.arqos = source.arqos;
|
||||
assign sink.arregion = source.arregion;
|
||||
assign sink.aruser = source.aruser;
|
||||
assign sink.arvalid = source.arvalid && !block_new_i && !s_read_pending_q;
|
||||
assign source.arready = sink.arready && !block_new_i && !s_read_pending_q;
|
||||
assign sink.arvalid = source.arvalid && !block_new_i && !clear_i && !s_read_pending_q;
|
||||
assign source.arready = sink.arready && !block_new_i && !clear_i && !s_read_pending_q;
|
||||
|
||||
assign source.rid = sink.rid;
|
||||
assign source.rdata = sink.rdata;
|
||||
@@ -71,7 +73,9 @@ module axi4_address_gate (
|
||||
assign s_b_accept = source.bvalid && source.bready;
|
||||
assign s_ar_accept = source.arvalid && source.arready;
|
||||
assign s_r_accept = source.rvalid && source.rready && source.rlast;
|
||||
assign idle_o = !s_write_pending_q && !s_read_pending_q && !source.awvalid && !source.arvalid;
|
||||
assign write_pending_o = s_write_pending_q || s_aw_accept;
|
||||
assign idle_o = !s_write_pending_q && !s_read_pending_q && !source.awvalid && !source.wvalid &&
|
||||
!source.arvalid;
|
||||
|
||||
always_comb begin
|
||||
s_write_pending_d = s_write_pending_q;
|
||||
@@ -80,6 +84,10 @@ module axi4_address_gate (
|
||||
if (s_aw_accept) s_write_pending_d = 1'b1;
|
||||
if (s_r_accept) s_read_pending_d = 1'b0;
|
||||
if (s_ar_accept) s_read_pending_d = 1'b1;
|
||||
if (clear_i) begin
|
||||
s_write_pending_d = 1'b0;
|
||||
s_read_pending_d = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
dffr #(
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
`include "mmap_define.svh"
|
||||
|
||||
module axi4_data_crossbar #(
|
||||
parameter int unsigned NumMasters = 8,
|
||||
parameter int unsigned NumMasters = 9,
|
||||
parameter int unsigned NumTargets = 6,
|
||||
parameter int unsigned StarvationCycles = 256,
|
||||
parameter logic [NumMasters-1:0][NumTargets-2:0] ReadTargetMask = '1,
|
||||
@@ -18,6 +18,8 @@ module axi4_data_crossbar #(
|
||||
input logic block_new_i,
|
||||
input logic [NumMasters-1:0] master_block_i,
|
||||
input logic recovery_i,
|
||||
input logic flush_i,
|
||||
input logic fault_ready_i,
|
||||
input logic [1:0] mem_pad_mode_i,
|
||||
input logic [31:0] ext_h_read_base_i,
|
||||
input logic [31:0] ext_h_read_limit_i,
|
||||
@@ -30,7 +32,7 @@ module axi4_data_crossbar #(
|
||||
output logic [7:0] outstanding_read_o,
|
||||
output logic [7:0] outstanding_write_o,
|
||||
output logic fault_valid_o,
|
||||
output logic [2:0] fault_master_o,
|
||||
output logic [3:0] fault_master_o,
|
||||
output logic [2:0] fault_target_o,
|
||||
output logic [31:0] fault_addr_o,
|
||||
output logic fault_write_o,
|
||||
@@ -72,7 +74,7 @@ module axi4_data_crossbar #(
|
||||
localparam logic [3:0] FaultProtocol = 4'd4;
|
||||
|
||||
typedef struct packed {
|
||||
logic [5:0] id;
|
||||
logic [6:0] id;
|
||||
logic [31:0] addr;
|
||||
logic [7:0] len;
|
||||
logic [2:0] size;
|
||||
@@ -93,13 +95,13 @@ module axi4_data_crossbar #(
|
||||
} write_channel_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [5:0] id;
|
||||
logic [6:0] id;
|
||||
logic [1:0] resp;
|
||||
logic user;
|
||||
} write_resp_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [5:0] id;
|
||||
logic [6:0] id;
|
||||
logic [63:0] data;
|
||||
logic [1:0] resp;
|
||||
logic last;
|
||||
@@ -161,6 +163,13 @@ module axi4_data_crossbar #(
|
||||
logic [NumMasters-1:0] s_write_resp_valid;
|
||||
logic [NumMasters-1:0] s_read_terminal;
|
||||
logic [NumMasters-1:0] s_write_terminal;
|
||||
logic [NumTargets-1:0] s_invalid_read_response;
|
||||
logic [NumTargets-1:0] s_invalid_write_response;
|
||||
logic [NumTargets-1:0] s_invalid_read_fault_accept;
|
||||
logic [NumTargets-1:0] s_invalid_write_fault_accept;
|
||||
logic s_protocol_fault_pending;
|
||||
logic s_protocol_fault_event;
|
||||
logic s_protocol_recovery_q;
|
||||
|
||||
logic [NumTargets-1:0] s_target_write_owner_full;
|
||||
logic [NumTargets-1:0] s_target_write_owner_empty;
|
||||
@@ -194,6 +203,10 @@ module axi4_data_crossbar #(
|
||||
|
||||
logic [NumMasters-1:0] s_read_accept;
|
||||
logic [NumMasters-1:0] s_write_accept;
|
||||
logic [NumMasters-1:0] s_read_accept_pre;
|
||||
logic [NumMasters-1:0] s_write_accept_pre;
|
||||
logic [NumMasters-1:0] s_read_fault_accept;
|
||||
logic [NumMasters-1:0] s_write_fault_accept;
|
||||
logic [NumMasters-1:0][TargetWidth-1:0] s_read_accept_target;
|
||||
logic [NumMasters-1:0][TargetWidth-1:0] s_write_accept_target;
|
||||
logic [NumMasters-1:0][ 2:0] s_read_accept_id;
|
||||
@@ -203,11 +216,12 @@ module axi4_data_crossbar #(
|
||||
logic [NumTargets-1:0][ 4:0] s_read_max_priority;
|
||||
logic [NumTargets-1:0][ 4:0] s_write_max_priority;
|
||||
logic s_fault_valid_d;
|
||||
logic [ 2:0] s_fault_master_d;
|
||||
logic [ 3:0] s_fault_master_d;
|
||||
logic [ 2:0] s_fault_target_d;
|
||||
logic [ 31:0] s_fault_addr_d;
|
||||
logic s_fault_write_d;
|
||||
logic [ 3:0] s_fault_reason_d;
|
||||
logic s_fault_slot_ready;
|
||||
|
||||
function automatic logic [TargetWidth-1:0] decode_target(input logic [31:0] addr,
|
||||
input logic [1:0] pad_mode);
|
||||
@@ -282,12 +296,14 @@ module axi4_data_crossbar #(
|
||||
if ((master <= 2) || (master == 7)) return CountWidth'(4);
|
||||
if ((master == 3) || (master == 4)) return CountWidth'(2);
|
||||
if (master == 5) return CountWidth'(1);
|
||||
if (master == 8) return CountWidth'(1);
|
||||
return '0;
|
||||
endfunction
|
||||
|
||||
function automatic logic [CountWidth-1:0] master_write_limit(input int unsigned master);
|
||||
if ((master == 1) || (master == 2) || (master == 7)) return CountWidth'(2);
|
||||
if ((master >= 3) && (master <= 5)) return CountWidth'(1);
|
||||
if (master == 8) return CountWidth'(1);
|
||||
return '0;
|
||||
endfunction
|
||||
|
||||
@@ -311,10 +327,12 @@ module axi4_data_crossbar #(
|
||||
3, 4: base_priority = 4'd10;
|
||||
2, 7: base_priority = 4'd8;
|
||||
5: base_priority = recovery ? 4'd15 : 4'd2;
|
||||
8: base_priority = 4'd8;
|
||||
default: base_priority = 4'd0;
|
||||
endcase
|
||||
if (recovery && (master == 5)) return 5'd31;
|
||||
if (aged) return 5'd16;
|
||||
if (master == 8) return {1'b0, base_priority};
|
||||
return {1'b0, (request_qos > base_priority) ? request_qos : base_priority};
|
||||
endfunction
|
||||
|
||||
@@ -466,7 +484,7 @@ module axi4_data_crossbar #(
|
||||
) u_write_owner_fifo (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.flush_i(1'b0),
|
||||
.flush_i(flush_i),
|
||||
.push_i (s_target_write_owner_push[target]),
|
||||
.full_o (s_target_write_owner_full[target]),
|
||||
.dat_i (s_write_selected[target]),
|
||||
@@ -540,7 +558,8 @@ module axi4_data_crossbar #(
|
||||
s_read_decoded_target[master] : TargetError;
|
||||
s_write_routed_target[master] = (s_write_fault_reason[master] == 4'd0) ?
|
||||
s_write_decoded_target[master] : TargetError;
|
||||
if (!block_new_i && !master_block_i[master] && m_arvalid[master] &&
|
||||
if (!block_new_i && !s_protocol_recovery_q && !s_protocol_fault_pending &&
|
||||
!master_block_i[master] && m_arvalid[master] &&
|
||||
(s_target_read_count_q[s_read_routed_target[master]] <
|
||||
target_read_limit(
|
||||
s_read_routed_target[master]
|
||||
@@ -550,7 +569,8 @@ module axi4_data_crossbar #(
|
||||
))) && !s_read_id_busy_q[master][m_ar[master].id[2:0]]) begin
|
||||
s_read_req[s_read_routed_target[master]][master] = 1'b1;
|
||||
end
|
||||
if (!block_new_i && !master_block_i[master] && m_awvalid[master] &&
|
||||
if (!block_new_i && !s_protocol_recovery_q && !s_protocol_fault_pending &&
|
||||
!master_block_i[master] && m_awvalid[master] &&
|
||||
!s_target_write_owner_full[s_write_routed_target[master]] &&
|
||||
(s_target_write_count_q[s_write_routed_target[master]] <
|
||||
target_write_limit(
|
||||
@@ -616,6 +636,21 @@ module axi4_data_crossbar #(
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_read_accept_pre = '0;
|
||||
s_write_accept_pre = '0;
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (s_read_grant_valid[target]) begin
|
||||
automatic logic [MasterWidth-1:0] owner = s_read_selected[target];
|
||||
s_read_accept_pre[owner] = m_arvalid[owner] && t_arready[target];
|
||||
end
|
||||
if (s_write_grant_valid[target]) begin
|
||||
automatic logic [MasterWidth-1:0] owner = s_write_selected[target];
|
||||
s_write_accept_pre[owner] = m_awvalid[owner] && t_awready[target];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
m_arready = '0;
|
||||
t_ar = '{default: '0};
|
||||
@@ -627,14 +662,17 @@ module axi4_data_crossbar #(
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (s_read_grant_valid[target]) begin
|
||||
automatic logic [MasterWidth-1:0] owner = s_read_selected[target];
|
||||
t_ar[target] = m_ar[owner];
|
||||
t_arvalid[target] = m_arvalid[owner];
|
||||
m_arready[owner] = t_arready[target];
|
||||
s_read_capture[target] = t_arvalid[target] && t_arready[target];
|
||||
if (s_read_capture[target]) begin
|
||||
s_read_accept[owner] = 1'b1;
|
||||
s_read_accept_target[owner] = TargetWidth'(target);
|
||||
s_read_accept_id[owner] = m_ar[owner].id[2:0];
|
||||
t_ar[target] = m_ar[owner];
|
||||
if (owner == MasterWidth'(8)) t_ar[target].qos = 4'd0;
|
||||
if ((s_read_fault_reason[owner] == 4'd0) || s_read_fault_accept[owner]) begin
|
||||
t_arvalid[target] = m_arvalid[owner];
|
||||
m_arready[owner] = t_arready[target];
|
||||
s_read_capture[target] = t_arvalid[target] && t_arready[target];
|
||||
if (s_read_capture[target]) begin
|
||||
s_read_accept[owner] = 1'b1;
|
||||
s_read_accept_target[owner] = TargetWidth'(target);
|
||||
s_read_accept_id[owner] = m_ar[owner].id[2:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -652,15 +690,18 @@ module axi4_data_crossbar #(
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (s_write_grant_valid[target]) begin
|
||||
automatic logic [MasterWidth-1:0] owner = s_write_selected[target];
|
||||
t_aw[target] = m_aw[owner];
|
||||
t_awvalid[target] = m_awvalid[owner];
|
||||
m_awready[owner] = t_awready[target];
|
||||
s_write_capture[target] = t_awvalid[target] && t_awready[target];
|
||||
s_target_write_owner_push[target] = s_write_capture[target];
|
||||
if (s_write_capture[target]) begin
|
||||
s_write_accept[owner] = 1'b1;
|
||||
s_write_accept_target[owner] = TargetWidth'(target);
|
||||
s_write_accept_id[owner] = m_aw[owner].id[2:0];
|
||||
t_aw[target] = m_aw[owner];
|
||||
if (owner == MasterWidth'(8)) t_aw[target].qos = 4'd0;
|
||||
if ((s_write_fault_reason[owner] == 4'd0) || s_write_fault_accept[owner]) begin
|
||||
t_awvalid[target] = m_awvalid[owner];
|
||||
m_awready[owner] = t_awready[target];
|
||||
s_write_capture[target] = t_awvalid[target] && t_awready[target];
|
||||
s_target_write_owner_push[target] = s_write_capture[target];
|
||||
if (s_write_capture[target]) begin
|
||||
s_write_accept[owner] = 1'b1;
|
||||
s_write_accept_target[owner] = TargetWidth'(target);
|
||||
s_write_accept_id[owner] = m_aw[owner].id[2:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -688,29 +729,105 @@ module axi4_data_crossbar #(
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_read_resp_req = '0;
|
||||
s_write_resp_req = '0;
|
||||
s_read_resp_req = '0;
|
||||
s_write_resp_req = '0;
|
||||
s_invalid_read_response = '0;
|
||||
s_invalid_write_response = '0;
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (t_rvalid[target]) begin
|
||||
s_read_resp_req[t_r[target].id[5:3]][target] = 1'b1;
|
||||
if (t_rvalid[target] && !flush_i) begin
|
||||
if (t_r[target].id[6:3] < 4'(NumMasters)) begin
|
||||
s_read_resp_req[t_r[target].id[6:3]][target] = 1'b1;
|
||||
end else begin
|
||||
s_invalid_read_response[target] = 1'b1;
|
||||
end
|
||||
end
|
||||
if (t_bvalid[target]) begin
|
||||
s_write_resp_req[t_b[target].id[5:3]][target] = 1'b1;
|
||||
if (t_bvalid[target] && !flush_i) begin
|
||||
if (t_b[target].id[6:3] < 4'(NumMasters)) begin
|
||||
s_write_resp_req[t_b[target].id[6:3]][target] = 1'b1;
|
||||
end else begin
|
||||
s_invalid_write_response[target] = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign s_protocol_fault_pending = (|s_invalid_read_response) || (|s_invalid_write_response);
|
||||
assign s_fault_slot_ready = !fault_valid_o || fault_ready_i;
|
||||
|
||||
always_comb begin
|
||||
s_fault_valid_d = 1'b0;
|
||||
s_fault_master_d = '0;
|
||||
s_fault_target_d = '0;
|
||||
s_fault_addr_d = '0;
|
||||
s_fault_write_d = 1'b0;
|
||||
s_fault_reason_d = '0;
|
||||
s_invalid_read_fault_accept = '0;
|
||||
s_invalid_write_fault_accept = '0;
|
||||
s_read_fault_accept = '0;
|
||||
s_write_fault_accept = '0;
|
||||
if (s_fault_slot_ready) begin
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (!s_fault_valid_d && !s_protocol_recovery_q && s_invalid_read_response[target]) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = t_r[target].id[6:3];
|
||||
s_fault_target_d = 3'(target);
|
||||
s_fault_addr_d = '0;
|
||||
s_fault_write_d = 1'b0;
|
||||
s_fault_reason_d = FaultProtocol;
|
||||
s_invalid_read_fault_accept[target] = 1'b1;
|
||||
end
|
||||
if (!s_fault_valid_d && !s_protocol_recovery_q && s_invalid_write_response[target]) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = t_b[target].id[6:3];
|
||||
s_fault_target_d = 3'(target);
|
||||
s_fault_addr_d = '0;
|
||||
s_fault_write_d = 1'b1;
|
||||
s_fault_reason_d = FaultProtocol;
|
||||
s_invalid_write_fault_accept[target] = 1'b1;
|
||||
end
|
||||
end
|
||||
for (int master = 0; master < NumMasters; master++) begin
|
||||
if (!s_fault_valid_d && s_read_accept_pre[master] &&
|
||||
(s_read_fault_reason[master] != 4'd0)) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = 4'(master);
|
||||
s_fault_target_d = 3'(s_read_decoded_target[master]);
|
||||
s_fault_addr_d = m_ar[master].addr;
|
||||
s_fault_write_d = 1'b0;
|
||||
s_fault_reason_d = s_read_fault_reason[master];
|
||||
s_read_fault_accept[master] = 1'b1;
|
||||
end
|
||||
if (!s_fault_valid_d && s_write_accept_pre[master] &&
|
||||
(s_write_fault_reason[master] != 4'd0)) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = 4'(master);
|
||||
s_fault_target_d = 3'(s_write_decoded_target[master]);
|
||||
s_fault_addr_d = m_aw[master].addr;
|
||||
s_fault_write_d = 1'b1;
|
||||
s_fault_reason_d = s_write_fault_reason[master];
|
||||
s_write_fault_accept[master] = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign s_protocol_fault_event = (|s_invalid_read_fault_accept) || (|s_invalid_write_fault_accept);
|
||||
|
||||
always_comb begin
|
||||
m_r = '{default: '0};
|
||||
m_rvalid = '0;
|
||||
t_rready = '0;
|
||||
t_rready = flush_i ? '1 : '0;
|
||||
s_read_terminal = '0;
|
||||
s_read_complete_id = '0;
|
||||
m_b = '{default: '0};
|
||||
m_bvalid = '0;
|
||||
t_bready = '0;
|
||||
t_bready = flush_i ? '1 : '0;
|
||||
s_write_terminal = '0;
|
||||
s_write_complete_id = '0;
|
||||
for (int target = 0; target < NumTargets; target++) begin
|
||||
if (s_invalid_read_fault_accept[target]) t_rready[target] = 1'b1;
|
||||
if (s_invalid_write_fault_accept[target]) t_bready[target] = 1'b1;
|
||||
end
|
||||
for (int master = 0; master < NumMasters; master++) begin
|
||||
if (s_read_resp_valid[master]) begin
|
||||
automatic logic [TargetWidth-1:0] target = s_read_resp_selected[master];
|
||||
@@ -810,33 +927,6 @@ module axi4_data_crossbar #(
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_fault_valid_d = 1'b0;
|
||||
s_fault_master_d = '0;
|
||||
s_fault_target_d = '0;
|
||||
s_fault_addr_d = '0;
|
||||
s_fault_write_d = 1'b0;
|
||||
s_fault_reason_d = '0;
|
||||
for (int master = 0; master < NumMasters; master++) begin
|
||||
if (!s_fault_valid_d && s_read_accept[master] && (s_read_fault_reason[master] != 4'd0)) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = 3'(master);
|
||||
s_fault_target_d = 3'(s_read_decoded_target[master]);
|
||||
s_fault_addr_d = m_ar[master].addr;
|
||||
s_fault_reason_d = s_read_fault_reason[master];
|
||||
end
|
||||
if (!s_fault_valid_d && s_write_accept[master] &&
|
||||
(s_write_fault_reason[master] != 4'd0)) begin
|
||||
s_fault_valid_d = 1'b1;
|
||||
s_fault_master_d = 3'(master);
|
||||
s_fault_target_d = 3'(s_write_decoded_target[master]);
|
||||
s_fault_addr_d = m_aw[master].addr;
|
||||
s_fault_write_d = 1'b1;
|
||||
s_fault_reason_d = s_write_fault_reason[master];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
outstanding_read_o = '0;
|
||||
outstanding_write_o = '0;
|
||||
@@ -846,8 +936,8 @@ module axi4_data_crossbar #(
|
||||
end
|
||||
end
|
||||
|
||||
assign idle_o = (outstanding_read_o == 8'd0) && (outstanding_write_o == 8'd0) &&
|
||||
!(|s_route_count_q);
|
||||
assign idle_o = !s_protocol_recovery_q && (outstanding_read_o == 8'd0) &&
|
||||
(outstanding_write_o == 8'd0) && !(|s_route_count_q);
|
||||
for (genvar master = 0; master < NumMasters; master++) begin : gen_master_idle
|
||||
assign master_idle_o[master] = (s_master_read_count_q[master] == '0) &&
|
||||
(s_master_write_count_q[master] == '0) && (s_route_count_q[master] == '0) &&
|
||||
@@ -897,6 +987,7 @@ module axi4_data_crossbar #(
|
||||
s_route_count_q <= '0;
|
||||
s_read_age_q <= '0;
|
||||
s_write_age_q <= '0;
|
||||
s_protocol_recovery_q <= 1'b0;
|
||||
fault_valid_o <= 1'b0;
|
||||
fault_master_o <= '0;
|
||||
fault_target_o <= '0;
|
||||
@@ -904,24 +995,43 @@ module axi4_data_crossbar #(
|
||||
fault_write_o <= 1'b0;
|
||||
fault_reason_o <= '0;
|
||||
end else begin
|
||||
s_master_read_count_q <= s_master_read_count_d;
|
||||
s_master_write_count_q <= s_master_write_count_d;
|
||||
s_target_read_count_q <= s_target_read_count_d;
|
||||
s_target_write_count_q <= s_target_write_count_d;
|
||||
s_read_id_busy_q <= s_read_id_busy_d;
|
||||
s_write_id_busy_q <= s_write_id_busy_d;
|
||||
s_write_route_q <= s_write_route_d;
|
||||
s_route_read_ptr_q <= s_route_read_ptr_d;
|
||||
s_route_write_ptr_q <= s_route_write_ptr_d;
|
||||
s_route_count_q <= s_route_count_d;
|
||||
s_read_age_q <= s_read_age_d;
|
||||
s_write_age_q <= s_write_age_d;
|
||||
fault_valid_o <= s_fault_valid_d;
|
||||
fault_master_o <= s_fault_master_d;
|
||||
fault_target_o <= s_fault_target_d;
|
||||
fault_addr_o <= s_fault_addr_d;
|
||||
fault_write_o <= s_fault_write_d;
|
||||
fault_reason_o <= s_fault_reason_d;
|
||||
if (flush_i) begin
|
||||
s_master_read_count_q <= '0;
|
||||
s_master_write_count_q <= '0;
|
||||
s_target_read_count_q <= '0;
|
||||
s_target_write_count_q <= '0;
|
||||
s_read_id_busy_q <= '0;
|
||||
s_write_id_busy_q <= '0;
|
||||
s_write_route_q <= '0;
|
||||
s_route_read_ptr_q <= '0;
|
||||
s_route_write_ptr_q <= '0;
|
||||
s_route_count_q <= '0;
|
||||
s_read_age_q <= '0;
|
||||
s_write_age_q <= '0;
|
||||
s_protocol_recovery_q <= 1'b0;
|
||||
end else begin
|
||||
s_master_read_count_q <= s_master_read_count_d;
|
||||
s_master_write_count_q <= s_master_write_count_d;
|
||||
s_target_read_count_q <= s_target_read_count_d;
|
||||
s_target_write_count_q <= s_target_write_count_d;
|
||||
s_read_id_busy_q <= s_read_id_busy_d;
|
||||
s_write_id_busy_q <= s_write_id_busy_d;
|
||||
s_write_route_q <= s_write_route_d;
|
||||
s_route_read_ptr_q <= s_route_read_ptr_d;
|
||||
s_route_write_ptr_q <= s_route_write_ptr_d;
|
||||
s_route_count_q <= s_route_count_d;
|
||||
s_read_age_q <= s_read_age_d;
|
||||
s_write_age_q <= s_write_age_d;
|
||||
if (s_protocol_fault_event) s_protocol_recovery_q <= 1'b1;
|
||||
end
|
||||
if (!fault_valid_o || fault_ready_i) begin
|
||||
fault_valid_o <= s_fault_valid_d;
|
||||
fault_master_o <= s_fault_master_d;
|
||||
fault_target_o <= s_fault_target_d;
|
||||
fault_addr_o <= s_fault_addr_d;
|
||||
fault_write_o <= s_fault_write_d;
|
||||
fault_reason_o <= s_fault_reason_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -938,7 +1048,7 @@ module axi4_data_crossbar #(
|
||||
end
|
||||
|
||||
initial begin
|
||||
if ((NumMasters != 8) || (NumTargets != 6) || (StarvationCycles < 2) ||
|
||||
if ((NumMasters != 9) || (NumTargets != 6) || (StarvationCycles < 2) ||
|
||||
((StarvationCycles & (StarvationCycles - 1)) != 0)) begin
|
||||
$fatal(1, "axi4_data_crossbar: invalid product topology or aging interval");
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
module axi4_id_prefix #(
|
||||
parameter logic [2:0] MasterIndex = 3'd0
|
||||
parameter logic [3:0] MasterIndex = 4'd0
|
||||
) (
|
||||
axi4_if.slave source,
|
||||
axi4_if.master sink
|
||||
|
||||
@@ -20,6 +20,7 @@ module axi4_target_guard #(
|
||||
output logic abort_o,
|
||||
input logic abort_done_i,
|
||||
output logic timeout_valid_o,
|
||||
input logic timeout_ready_i,
|
||||
output logic isolated_o,
|
||||
output logic timeout_write_o,
|
||||
output logic [IdWidth-1:0] timeout_id_o,
|
||||
@@ -100,13 +101,24 @@ module axi4_target_guard #(
|
||||
logic [31:0] s_write_timeout_d, s_write_timeout_q;
|
||||
logic s_write_last_seen_d, s_write_last_seen_q;
|
||||
logic s_isolated_d, s_isolated_q;
|
||||
logic s_timeout_read;
|
||||
logic s_timeout_write;
|
||||
logic s_read_progress;
|
||||
logic s_write_progress;
|
||||
logic s_read_timeout_enable;
|
||||
logic s_write_timeout_enable;
|
||||
logic s_read_missing_last;
|
||||
logic s_read_timeout_raw;
|
||||
logic s_write_timeout_raw;
|
||||
logic s_read_timeout_latched_d, s_read_timeout_latched_q;
|
||||
logic s_write_timeout_latched_d, s_write_timeout_latched_q;
|
||||
logic s_read_timeout_pending;
|
||||
logic s_write_timeout_pending;
|
||||
logic s_timeout_hold_d, s_timeout_hold_q;
|
||||
logic s_timeout_sel_write_d, s_timeout_sel_write_q;
|
||||
logic s_timeout_sel_write;
|
||||
logic s_timeout_accept;
|
||||
logic s_read_timeout_accept;
|
||||
logic s_write_timeout_accept;
|
||||
logic s_timeout_block;
|
||||
|
||||
assign s_ar_push_data = {
|
||||
source.arid,
|
||||
@@ -208,9 +220,9 @@ module axi4_target_guard #(
|
||||
assign sink.arqos = s_ar_qos;
|
||||
assign sink.arregion = s_ar_region;
|
||||
assign sink.aruser = s_ar_user;
|
||||
assign sink.arvalid = (s_read_state_q == ReadSend) && !s_isolated_q;
|
||||
assign sink.arvalid = (s_read_state_q == ReadSend) && !s_isolated_q && !s_read_timeout_pending;
|
||||
assign s_ar_pop = ((s_read_state_q == ReadSend) &&
|
||||
(sink.arready || s_timeout_read || s_isolated_q)) ||
|
||||
((sink.arvalid && sink.arready) || s_read_timeout_accept || s_isolated_q)) ||
|
||||
((s_read_state_q == ReadIdle) && s_isolated_q && !s_ar_empty);
|
||||
|
||||
assign s_read_missing_last = (s_read_state_q == ReadForward) && sink.rvalid &&
|
||||
@@ -224,7 +236,8 @@ module axi4_target_guard #(
|
||||
assign source.ruser = (s_read_state_q == ReadSynthetic) ? '0 : sink.ruser;
|
||||
assign source.rvalid = (s_read_state_q == ReadSynthetic) ||
|
||||
((s_read_state_q == ReadForward) && sink.rvalid);
|
||||
assign sink.rready = (s_read_state_q == ReadForward) ? source.rready :
|
||||
assign sink.rready = (s_read_state_q == ReadForward) && !s_read_timeout_pending ?
|
||||
source.rready :
|
||||
((s_read_state_q == ReadAbort) ||
|
||||
(s_read_state_q == ReadSynthetic));
|
||||
|
||||
@@ -234,7 +247,8 @@ module axi4_target_guard #(
|
||||
(((s_read_state_q == ReadSend) && !sink.arready) ||
|
||||
((s_read_state_q == ReadForward) && source.rready &&
|
||||
!sink.rvalid));
|
||||
assign s_timeout_read = s_read_timeout_enable && (s_read_timeout_q == timeout_i - 1'b1);
|
||||
assign s_read_timeout_raw = s_read_timeout_enable && (s_read_timeout_q == timeout_i - 1'b1);
|
||||
assign s_read_timeout_pending = s_read_timeout_latched_q || s_read_timeout_raw;
|
||||
|
||||
always_comb begin
|
||||
s_read_state_d = s_read_state_q;
|
||||
@@ -242,7 +256,9 @@ module axi4_target_guard #(
|
||||
s_read_addr_d = s_read_addr_q;
|
||||
s_read_remaining_d = s_read_remaining_q;
|
||||
s_read_timeout_d = s_read_timeout_q;
|
||||
if (s_read_state_q == ReadIdle) begin
|
||||
if (s_timeout_block) begin
|
||||
s_read_timeout_d = s_read_timeout_q;
|
||||
end else if (s_read_state_q == ReadIdle) begin
|
||||
s_read_timeout_d = '0;
|
||||
if (!s_ar_empty && s_isolated_q) begin
|
||||
s_read_id_d = s_ar_id;
|
||||
@@ -259,7 +275,7 @@ module axi4_target_guard #(
|
||||
s_read_state_d = ReadSynthetic;
|
||||
end else if (s_isolated_q && (s_read_state_q == ReadForward)) begin
|
||||
s_read_state_d = ReadAbort;
|
||||
end else if (s_timeout_read) begin
|
||||
end else if (s_read_timeout_accept) begin
|
||||
s_read_timeout_d = '0;
|
||||
if (s_read_state_q == ReadSend) begin
|
||||
s_read_id_d = s_ar_id;
|
||||
@@ -271,6 +287,8 @@ module axi4_target_guard #(
|
||||
s_read_addr_d = s_read_addr_q;
|
||||
s_read_state_d = ReadAbort;
|
||||
end
|
||||
end else if (s_read_timeout_pending) begin
|
||||
s_read_timeout_d = s_read_timeout_q;
|
||||
end else begin
|
||||
s_read_timeout_d = s_read_progress ? 32'd0 :
|
||||
s_read_timeout_enable ? s_read_timeout_q + 1'b1 : s_read_timeout_q;
|
||||
@@ -317,17 +335,19 @@ module axi4_target_guard #(
|
||||
assign sink.awqos = s_aw_qos;
|
||||
assign sink.awregion = s_aw_region;
|
||||
assign sink.awuser = s_aw_user;
|
||||
assign sink.awvalid = (s_write_state_q == WriteSend) && !s_isolated_q;
|
||||
assign sink.awvalid = (s_write_state_q == WriteSend) && !s_isolated_q && !s_write_timeout_pending;
|
||||
assign s_aw_pop = ((s_write_state_q == WriteSend) &&
|
||||
(sink.awready || s_timeout_write || s_isolated_q)) ||
|
||||
((sink.awvalid && sink.awready) || s_write_timeout_accept || s_isolated_q)) ||
|
||||
((s_write_state_q == WriteIdle) && s_isolated_q && !s_aw_empty);
|
||||
|
||||
assign sink.wdata = source.wdata;
|
||||
assign sink.wstrb = source.wstrb;
|
||||
assign sink.wlast = source.wlast;
|
||||
assign sink.wuser = source.wuser;
|
||||
assign sink.wvalid = (s_write_state_q == WriteStream) && source.wvalid;
|
||||
assign source.wready = (s_write_state_q == WriteStream) ? sink.wready :
|
||||
assign sink.wvalid = (s_write_state_q == WriteStream) && source.wvalid &&
|
||||
!s_write_timeout_pending;
|
||||
assign source.wready = (s_write_state_q == WriteStream) && !s_write_timeout_pending ?
|
||||
sink.wready :
|
||||
(s_write_state_q == WriteDrop);
|
||||
|
||||
assign source.bid = (s_write_state_q == WriteSynthetic) ? s_write_id_q : sink.bid;
|
||||
@@ -335,7 +355,8 @@ module axi4_target_guard #(
|
||||
assign source.buser = (s_write_state_q == WriteSynthetic) ? '0 : sink.buser;
|
||||
assign source.bvalid = (s_write_state_q == WriteSynthetic) ||
|
||||
((s_write_state_q == WriteResponse) && sink.bvalid);
|
||||
assign sink.bready = (s_write_state_q == WriteResponse) ? source.bready :
|
||||
assign sink.bready = (s_write_state_q == WriteResponse) && !s_write_timeout_pending ?
|
||||
source.bready :
|
||||
((s_write_state_q == WriteAbort) ||
|
||||
(s_write_state_q == WriteSynthetic));
|
||||
|
||||
@@ -346,7 +367,8 @@ module axi4_target_guard #(
|
||||
(((s_write_state_q == WriteSend) && !sink.awready) ||
|
||||
((s_write_state_q == WriteStream) && source.wvalid && !sink.wready) ||
|
||||
((s_write_state_q == WriteResponse) && source.bready && !sink.bvalid));
|
||||
assign s_timeout_write = s_write_timeout_enable && (s_write_timeout_q == timeout_i - 1'b1);
|
||||
assign s_write_timeout_raw = s_write_timeout_enable && (s_write_timeout_q == timeout_i - 1'b1);
|
||||
assign s_write_timeout_pending = s_write_timeout_latched_q || s_write_timeout_raw;
|
||||
|
||||
always_comb begin
|
||||
s_write_state_d = s_write_state_q;
|
||||
@@ -354,7 +376,9 @@ module axi4_target_guard #(
|
||||
s_write_addr_d = s_write_addr_q;
|
||||
s_write_timeout_d = s_write_timeout_q;
|
||||
s_write_last_seen_d = s_write_last_seen_q;
|
||||
if (s_write_state_q == WriteIdle) begin
|
||||
if (s_timeout_block) begin
|
||||
s_write_timeout_d = s_write_timeout_q;
|
||||
end else if (s_write_state_q == WriteIdle) begin
|
||||
s_write_timeout_d = '0;
|
||||
s_write_last_seen_d = 1'b0;
|
||||
if (!s_aw_empty && s_isolated_q) begin
|
||||
@@ -371,7 +395,7 @@ module axi4_target_guard #(
|
||||
end else if (s_isolated_q && ((s_write_state_q == WriteStream) ||
|
||||
(s_write_state_q == WriteResponse))) begin
|
||||
s_write_state_d = WriteAbort;
|
||||
end else if (s_timeout_write) begin
|
||||
end else if (s_write_timeout_accept) begin
|
||||
s_write_timeout_d = '0;
|
||||
if (s_write_state_q == WriteSend) begin
|
||||
s_write_id_d = s_aw_id;
|
||||
@@ -380,6 +404,8 @@ module axi4_target_guard #(
|
||||
end else begin
|
||||
s_write_state_d = WriteAbort;
|
||||
end
|
||||
end else if (s_write_timeout_pending) begin
|
||||
s_write_timeout_d = s_write_timeout_q;
|
||||
end else begin
|
||||
s_write_timeout_d = s_write_progress ? 32'd0 :
|
||||
s_write_timeout_enable ? s_write_timeout_q + 1'b1 : s_write_timeout_q;
|
||||
@@ -422,50 +448,96 @@ module axi4_target_guard #(
|
||||
|
||||
always_comb begin
|
||||
s_isolated_d = s_isolated_q;
|
||||
if ((s_timeout_read && (s_read_state_q == ReadForward)) ||
|
||||
(s_timeout_write && ((s_write_state_q == WriteStream) ||
|
||||
(s_write_state_q == WriteResponse)))) begin
|
||||
if ((s_read_timeout_accept && (s_read_state_q == ReadForward)) ||
|
||||
(s_write_timeout_accept && ((s_write_state_q == WriteStream) ||
|
||||
(s_write_state_q == WriteResponse)))) begin
|
||||
s_isolated_d = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
assign s_timeout_sel_write = s_timeout_hold_q ? s_timeout_sel_write_q :
|
||||
!s_read_timeout_pending && s_write_timeout_pending;
|
||||
assign timeout_valid_o = !clear_i &&
|
||||
(s_timeout_hold_q || s_read_timeout_pending ||
|
||||
s_write_timeout_pending);
|
||||
assign s_timeout_accept = timeout_valid_o && timeout_ready_i;
|
||||
assign s_read_timeout_accept = s_timeout_accept && !s_timeout_sel_write;
|
||||
assign s_write_timeout_accept = s_timeout_accept && s_timeout_sel_write;
|
||||
assign s_timeout_block = timeout_valid_o && !timeout_ready_i;
|
||||
|
||||
always_comb begin
|
||||
s_read_timeout_latched_d = s_read_timeout_latched_q;
|
||||
s_write_timeout_latched_d = s_write_timeout_latched_q;
|
||||
s_timeout_hold_d = s_timeout_hold_q;
|
||||
s_timeout_sel_write_d = s_timeout_sel_write_q;
|
||||
if (clear_i) begin
|
||||
s_read_timeout_latched_d = 1'b0;
|
||||
s_write_timeout_latched_d = 1'b0;
|
||||
s_timeout_hold_d = 1'b0;
|
||||
end else begin
|
||||
if (s_read_timeout_accept) begin
|
||||
s_read_timeout_latched_d = 1'b0;
|
||||
end else if (s_read_timeout_raw) begin
|
||||
s_read_timeout_latched_d = 1'b1;
|
||||
end
|
||||
if (s_write_timeout_accept) begin
|
||||
s_write_timeout_latched_d = 1'b0;
|
||||
end else if (s_write_timeout_raw) begin
|
||||
s_write_timeout_latched_d = 1'b1;
|
||||
end
|
||||
if (s_timeout_hold_q) begin
|
||||
if (s_timeout_accept) s_timeout_hold_d = 1'b0;
|
||||
end else if (timeout_valid_o && !timeout_ready_i) begin
|
||||
s_timeout_hold_d = 1'b1;
|
||||
s_timeout_sel_write_d = s_timeout_sel_write;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign abort_o = (s_read_state_q == ReadAbort) || (s_write_state_q == WriteAbort);
|
||||
assign clear_busy_o = clear_i || abort_o;
|
||||
assign timeout_valid_o = s_timeout_read || s_timeout_write;
|
||||
assign isolated_o = s_isolated_q;
|
||||
assign timeout_write_o = s_timeout_write;
|
||||
assign timeout_id_o = s_timeout_write ?
|
||||
assign timeout_write_o = s_timeout_sel_write;
|
||||
assign timeout_id_o = s_timeout_sel_write ?
|
||||
((s_write_state_q == WriteSend) ? s_aw_id : s_write_id_q) :
|
||||
((s_read_state_q == ReadSend) ? s_ar_id : s_read_id_q);
|
||||
assign timeout_addr_o = s_timeout_write ?
|
||||
assign timeout_addr_o = s_timeout_sel_write ?
|
||||
((s_write_state_q == WriteSend) ? s_aw_addr : s_write_addr_q) :
|
||||
((s_read_state_q == ReadSend) ? s_ar_addr : s_read_addr_q);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
s_read_state_q <= ReadIdle;
|
||||
s_read_id_q <= '0;
|
||||
s_read_addr_q <= '0;
|
||||
s_read_remaining_q <= '0;
|
||||
s_read_timeout_q <= '0;
|
||||
s_write_state_q <= WriteIdle;
|
||||
s_write_id_q <= '0;
|
||||
s_write_addr_q <= '0;
|
||||
s_write_timeout_q <= '0;
|
||||
s_write_last_seen_q <= 1'b0;
|
||||
s_isolated_q <= 1'b0;
|
||||
s_read_state_q <= ReadIdle;
|
||||
s_read_id_q <= '0;
|
||||
s_read_addr_q <= '0;
|
||||
s_read_remaining_q <= '0;
|
||||
s_read_timeout_q <= '0;
|
||||
s_write_state_q <= WriteIdle;
|
||||
s_write_id_q <= '0;
|
||||
s_write_addr_q <= '0;
|
||||
s_write_timeout_q <= '0;
|
||||
s_write_last_seen_q <= 1'b0;
|
||||
s_isolated_q <= 1'b0;
|
||||
s_read_timeout_latched_q <= 1'b0;
|
||||
s_write_timeout_latched_q <= 1'b0;
|
||||
s_timeout_hold_q <= 1'b0;
|
||||
s_timeout_sel_write_q <= 1'b0;
|
||||
end else begin
|
||||
s_read_state_q <= s_read_state_d;
|
||||
s_read_id_q <= s_read_id_d;
|
||||
s_read_addr_q <= s_read_addr_d;
|
||||
s_read_remaining_q <= s_read_remaining_d;
|
||||
s_read_timeout_q <= s_read_timeout_d;
|
||||
s_write_state_q <= s_write_state_d;
|
||||
s_write_id_q <= s_write_id_d;
|
||||
s_write_addr_q <= s_write_addr_d;
|
||||
s_write_timeout_q <= s_write_timeout_d;
|
||||
s_write_last_seen_q <= s_write_last_seen_d;
|
||||
s_isolated_q <= s_isolated_d;
|
||||
s_read_state_q <= s_read_state_d;
|
||||
s_read_id_q <= s_read_id_d;
|
||||
s_read_addr_q <= s_read_addr_d;
|
||||
s_read_remaining_q <= s_read_remaining_d;
|
||||
s_read_timeout_q <= s_read_timeout_d;
|
||||
s_write_state_q <= s_write_state_d;
|
||||
s_write_id_q <= s_write_id_d;
|
||||
s_write_addr_q <= s_write_addr_d;
|
||||
s_write_timeout_q <= s_write_timeout_d;
|
||||
s_write_last_seen_q <= s_write_last_seen_d;
|
||||
s_isolated_q <= s_isolated_d;
|
||||
s_read_timeout_latched_q <= s_read_timeout_latched_d;
|
||||
s_write_timeout_latched_q <= s_write_timeout_latched_d;
|
||||
s_timeout_hold_q <= s_timeout_hold_d;
|
||||
s_timeout_sel_write_q <= s_timeout_sel_write_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
module axi4_upsizer_32to64 #(
|
||||
parameter logic [2:0] MasterIndex = 3'd0
|
||||
parameter logic [3:0] MasterIndex = 4'd0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
module data_plane_fault_cdc (
|
||||
// verilog_format: off -- preserve the HP/PCLK fault-mailbox boundary columns
|
||||
input logic clk_hp_i,
|
||||
input logic rst_hp_n_i,
|
||||
input logic fault_valid_i,
|
||||
input logic [ 3:0] fault_master_i,
|
||||
input logic [ 2:0] fault_target_i,
|
||||
input logic [31:0] fault_addr_i,
|
||||
input logic fault_write_i,
|
||||
input logic [ 3:0] fault_reason_i,
|
||||
output logic fault_ready_o,
|
||||
input logic clk_pclk_i,
|
||||
input logic rst_pclk_n_i,
|
||||
output logic fault_valid_o,
|
||||
output logic [ 3:0] fault_master_o,
|
||||
output logic [ 2:0] fault_target_o,
|
||||
output logic [31:0] fault_addr_o,
|
||||
output logic fault_write_o,
|
||||
output logic [ 3:0] fault_reason_o
|
||||
// verilog_format: on
|
||||
);
|
||||
localparam int unsigned FaultPayloadWidth = 44;
|
||||
|
||||
logic s_fault_mailbox_ready;
|
||||
logic s_fault_mailbox_valid;
|
||||
logic [FaultPayloadWidth-1:0] s_fault_mailbox_data;
|
||||
logic [FaultPayloadWidth-1:0] s_fault_payload;
|
||||
|
||||
assign fault_valid_o = s_fault_mailbox_valid;
|
||||
assign fault_ready_o = s_fault_mailbox_ready;
|
||||
assign s_fault_payload = {
|
||||
fault_master_i, fault_target_i, fault_addr_i, fault_write_i, fault_reason_i
|
||||
};
|
||||
assign {fault_master_o, fault_target_o, fault_addr_o, fault_write_o, fault_reason_o} =
|
||||
s_fault_mailbox_data;
|
||||
|
||||
// The HP producer holds valid and this payload until fault_ready_o accepts it.
|
||||
async_reqack #(
|
||||
.DATA_WIDTH(FaultPayloadWidth)
|
||||
) u_fault_mailbox (
|
||||
.src_clk_i (clk_hp_i),
|
||||
.src_rst_n_i(rst_hp_n_i),
|
||||
.src_valid_i(fault_valid_i),
|
||||
.src_ready_o(s_fault_mailbox_ready),
|
||||
.src_data_i (s_fault_payload),
|
||||
.dst_clk_i (clk_pclk_i),
|
||||
.dst_rst_n_i(rst_pclk_n_i),
|
||||
.dst_valid_o(s_fault_mailbox_valid),
|
||||
.dst_ready_i(1'b1),
|
||||
.dst_data_o (s_fault_mailbox_data)
|
||||
);
|
||||
endmodule
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
module fabric_monitor #(
|
||||
parameter int unsigned NumMasters = 8,
|
||||
parameter int unsigned NumMasters = 9,
|
||||
parameter int unsigned NumTargets = 6
|
||||
) (
|
||||
// verilog_format: off -- preserve the monitor event boundary columns
|
||||
@@ -15,7 +15,7 @@ module fabric_monitor #(
|
||||
input logic [7:0] outstanding_read_i,
|
||||
input logic [7:0] outstanding_write_i,
|
||||
input logic fault_valid_i,
|
||||
input logic [2:0] fault_master_i,
|
||||
input logic [3:0] fault_master_i,
|
||||
input logic [2:0] fault_target_i,
|
||||
input logic [31:0] fault_addr_i,
|
||||
input logic fault_write_i,
|
||||
@@ -41,7 +41,7 @@ module fabric_monitor #(
|
||||
// verilog_format: on
|
||||
);
|
||||
localparam logic [31:0] IpId = 32'h4450_4D4E;
|
||||
localparam logic [31:0] IpVersion = 32'h0001_0000;
|
||||
localparam logic [31:0] IpVersion = 32'h0001_0001;
|
||||
localparam logic [11:0] IpIdOffset = 12'h000;
|
||||
localparam logic [11:0] IpVersionOffset = 12'h004;
|
||||
localparam logic [11:0] CapabilityOffset = 12'h008;
|
||||
@@ -60,7 +60,7 @@ module fabric_monitor #(
|
||||
logic s_flush_q;
|
||||
logic s_fault_valid_q;
|
||||
logic s_fault_write_q;
|
||||
logic [ 2:0] s_fault_master_q;
|
||||
logic [ 3:0] s_fault_master_q;
|
||||
logic [ 2:0] s_fault_target_q;
|
||||
logic [ 3:0] s_fault_reason_q;
|
||||
logic [31:0] s_fault_addr_q;
|
||||
@@ -126,10 +126,11 @@ module fabric_monitor #(
|
||||
};
|
||||
FaultOffset:
|
||||
s_read_data = {
|
||||
20'd0,
|
||||
19'd0,
|
||||
s_fault_master_q[3],
|
||||
s_fault_reason_q,
|
||||
s_fault_target_q,
|
||||
s_fault_master_q,
|
||||
s_fault_master_q[2:0],
|
||||
s_fault_write_q,
|
||||
s_fault_valid_q
|
||||
};
|
||||
@@ -417,8 +418,8 @@ module fabric_monitor #(
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
initial begin
|
||||
if ((NumMasters != 8) || (NumTargets != 6)) begin
|
||||
$fatal(1, "fabric_monitor: product topology must remain 8x6");
|
||||
if ((NumMasters != 9) || (NumTargets != 6)) begin
|
||||
$fatal(1, "fabric_monitor: product topology must remain 9x6");
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
module resource_controller #(
|
||||
parameter int unsigned ResourceCount = 8
|
||||
parameter int unsigned ResourceCount = 9
|
||||
) (
|
||||
// verilog_format: off -- preserve the resource ownership boundary columns
|
||||
input logic clk_i,
|
||||
@@ -23,7 +23,7 @@ module resource_controller #(
|
||||
// verilog_format: on
|
||||
);
|
||||
localparam logic [31:0] IpId = 32'h5253_4354;
|
||||
localparam logic [31:0] IpVersion = 32'h0001_0000;
|
||||
localparam logic [31:0] IpVersion = 32'h0001_0001;
|
||||
localparam logic [11:0] IpIdOffset = 12'h000;
|
||||
localparam logic [11:0] IpVersionOffset = 12'h004;
|
||||
localparam logic [11:0] CapabilityOffset = 12'h008;
|
||||
|
||||
+144
-90
@@ -87,6 +87,8 @@ module retrosoc (
|
||||
u_ext_h_wide_axi4_if (.aclk(clk_pclk_i), .aresetn(rst_pclk_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(64), .ID_WIDTH(3), .USER_WIDTH(1))
|
||||
u_jpeg_wide_axi4_if (.aclk(clk_pclk_i), .aresetn(rst_pclk_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(64), .ID_WIDTH(3), .USER_WIDTH(1))
|
||||
u_ga2d_wide_axi4_if (.aclk(clk_pclk_i), .aresetn(rst_pclk_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(32), .ID_WIDTH(1), .USER_WIDTH(1))
|
||||
u_apu_axi4_if (.aclk(clk_pclk_i), .aresetn(rst_pclk_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(64), .ID_WIDTH(3), .USER_WIDTH(1))
|
||||
@@ -101,7 +103,7 @@ module retrosoc (
|
||||
u_hp_mmio_gated_axi4_if (.aclk(clk_hp_i), .aresetn(rst_hp_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(32), .ID_WIDTH(1), .USER_WIDTH(1))
|
||||
u_hp_mmio_lp_axi4_if (.aclk(clk_lp_i), .aresetn(rst_lp_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(64), .ID_WIDTH(6), .USER_WIDTH(1))
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(64), .ID_WIDTH(7), .USER_WIDTH(1))
|
||||
u_data_sram_axi4_if (.aclk(clk_hp_i), .aresetn(rst_hp_n_i));
|
||||
axi4_if #(.ADDR_WIDTH(32), .DATA_WIDTH(32), .ID_WIDTH(1), .USER_WIDTH(1))
|
||||
u_retired_data_sram_axi4_if (.aclk(clk_lp_i), .aresetn(rst_lp_n_i));
|
||||
@@ -194,12 +196,19 @@ module retrosoc (
|
||||
logic [ 7:0] s_data_plane_outstanding_read;
|
||||
logic [ 7:0] s_data_plane_outstanding_write;
|
||||
logic [ 7:0] s_apu_bridge_epoch;
|
||||
logic s_data_plane_fault_valid;
|
||||
logic [ 2:0] s_data_plane_fault_master;
|
||||
logic [ 2:0] s_data_plane_fault_target;
|
||||
logic [31:0] s_data_plane_fault_addr;
|
||||
logic s_data_plane_fault_write;
|
||||
logic [ 3:0] s_data_plane_fault_reason;
|
||||
logic s_data_plane_fault_valid_hp;
|
||||
logic s_data_plane_fault_ready_hp;
|
||||
logic [ 3:0] s_data_plane_fault_master_hp;
|
||||
logic [ 2:0] s_data_plane_fault_target_hp;
|
||||
logic [31:0] s_data_plane_fault_addr_hp;
|
||||
logic s_data_plane_fault_write_hp;
|
||||
logic [ 3:0] s_data_plane_fault_reason_hp;
|
||||
logic s_data_plane_fault_valid_pclk;
|
||||
logic [ 3:0] s_data_plane_fault_master_pclk;
|
||||
logic [ 2:0] s_data_plane_fault_target_pclk;
|
||||
logic [31:0] s_data_plane_fault_addr_pclk;
|
||||
logic s_data_plane_fault_write_pclk;
|
||||
logic [ 3:0] s_data_plane_fault_reason_pclk;
|
||||
logic s_hp_mmio_idle;
|
||||
logic [ 3:0] s_pclk_pending_d;
|
||||
logic [ 3:0] s_pclk_pending_q;
|
||||
@@ -235,21 +244,26 @@ module retrosoc (
|
||||
logic [31:0] s_ext_h_timeout;
|
||||
logic s_ext_h_irq_raw;
|
||||
logic [ 1:0] s_ext_h_owner;
|
||||
logic [ 7:0][1:0] s_resource_owner;
|
||||
logic [ 7:0] s_resource_owner_lock;
|
||||
logic [ 7:0] s_resource_quiesce;
|
||||
logic [ 7:0] s_resource_reset;
|
||||
logic [ 7:0] s_resource_idle_hp;
|
||||
logic [ 7:0] s_resource_idle_pclk;
|
||||
logic [ 7:0] s_resource_block_ack_hp;
|
||||
logic [ 7:0] s_resource_block_ack_pclk;
|
||||
logic [ 8:0][1:0] s_resource_owner;
|
||||
logic [ 8:0] s_resource_owner_lock;
|
||||
logic [ 8:0] s_resource_quiesce;
|
||||
logic [ 8:0] s_resource_reset;
|
||||
logic [ 8:0] s_resource_idle_hp;
|
||||
logic [ 8:0] s_resource_idle_pclk;
|
||||
logic [ 8:0] s_resource_block_ack_hp;
|
||||
logic [ 8:0] s_resource_block_ack_pclk;
|
||||
logic [ 6:0] s_resource_irq_raw;
|
||||
logic [ 6:0] s_resource_irq_lp;
|
||||
logic [ 6:0] s_resource_irq_hp;
|
||||
logic s_apu_idle;
|
||||
logic s_jpeg_idle;
|
||||
logic [ 7:0] s_resource_idle_combined;
|
||||
logic [ 7:0] s_resource_block_ack_combined;
|
||||
logic [ 8:0] s_resource_idle_combined;
|
||||
logic [ 8:0] s_resource_block_ack_combined;
|
||||
logic s_ga2d_source_stop;
|
||||
logic s_ga2d_source_safe_idle;
|
||||
logic s_ga2d_bridge_clear_busy;
|
||||
logic [ 7:0] s_ga2d_bridge_epoch;
|
||||
logic s_ga2d_data_ready;
|
||||
logic [31:0] s_fault_addr_mux;
|
||||
logic [ 3:0] s_fault_wstrb_mux;
|
||||
logic s_fault_reserved_mux;
|
||||
@@ -262,12 +276,13 @@ module retrosoc (
|
||||
localparam bit SramPresent = 1'b0;
|
||||
`endif
|
||||
|
||||
assign u_sysctrl_if.fault_access_i = s_data_plane_fault_valid ?
|
||||
s_data_plane_fault_write : s_bus_fault_access;
|
||||
assign u_sysctrl_if.fault_master_i = s_data_plane_fault_valid ?
|
||||
s_data_plane_fault_master : s_bus_fault_master;
|
||||
assign u_sysctrl_if.fault_code_i = s_data_plane_fault_valid ?
|
||||
s_data_plane_fault_reason[2:0] : s_bus_fault_code;
|
||||
// PCLK-visible data-plane faults retain their legacy priority over local bus faults.
|
||||
assign u_sysctrl_if.fault_access_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_write_pclk : s_bus_fault_access;
|
||||
assign u_sysctrl_if.fault_master_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_master_pclk : {1'b0, s_bus_fault_master};
|
||||
assign u_sysctrl_if.fault_code_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_reason_pclk[2:0] : s_bus_fault_code;
|
||||
assign s_perf_en = u_sysctrl_if.perf_enable_o;
|
||||
assign s_perf_clear = u_sysctrl_if.perf_clear_o;
|
||||
assign test_done_o = u_sysctrl_if.test_done_o;
|
||||
@@ -294,10 +309,11 @@ module retrosoc (
|
||||
assign u_sysctrl_if.hp_actual_released_i = s_hp_lifecycle_stat_pclk[2];
|
||||
assign u_sysctrl_if.hp_draining_i = s_hp_lifecycle_stat_pclk[1];
|
||||
assign u_sysctrl_if.hp_forced_fault_i = s_hp_lifecycle_stat_pclk[0];
|
||||
assign s_fault_addr_mux = s_data_plane_fault_valid ? s_data_plane_fault_addr : s_bus_fault_addr;
|
||||
assign s_fault_wstrb_mux = s_data_plane_fault_valid && s_data_plane_fault_write ?
|
||||
assign s_fault_addr_mux = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_addr_pclk : s_bus_fault_addr;
|
||||
assign s_fault_wstrb_mux = s_data_plane_fault_valid_pclk && s_data_plane_fault_write_pclk ?
|
||||
4'hF : s_bus_fault_wstrb;
|
||||
assign s_fault_reserved_mux = s_data_plane_fault_valid ? 1'b0 : s_bus_fault_reserved;
|
||||
assign s_fault_reserved_mux = s_data_plane_fault_valid_pclk ? 1'b0 : s_bus_fault_reserved;
|
||||
assign u_uart0_if.rx_i = uart_rx_i;
|
||||
assign uart_tx_o = u_uart0_if.tx_o;
|
||||
assign u_uart1_if.rx_i = uart1_rx_i;
|
||||
@@ -467,12 +483,14 @@ module retrosoc (
|
||||
);
|
||||
|
||||
axi4_address_gate u_hp_mmio_gate (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i (rst_hp_n_i),
|
||||
.block_new_i(s_hp_block_hp),
|
||||
.source (u_hp_mmio_hp_axi4_if),
|
||||
.sink (u_hp_mmio_gated_axi4_if),
|
||||
.idle_o (s_hp_mmio_idle)
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i (rst_hp_n_i),
|
||||
.block_new_i (s_hp_block_hp),
|
||||
.clear_i (s_hp_flush_hp),
|
||||
.source (u_hp_mmio_hp_axi4_if),
|
||||
.sink (u_hp_mmio_gated_axi4_if),
|
||||
.idle_o (s_hp_mmio_idle),
|
||||
.write_pending_o()
|
||||
);
|
||||
|
||||
cdc_sync #(
|
||||
@@ -561,60 +579,87 @@ module retrosoc (
|
||||
);
|
||||
|
||||
soc_data_plane u_data_plane (
|
||||
.clk_lp_i (clk_lp_i),
|
||||
.rst_lp_n_i (rst_lp_n_i),
|
||||
.clk_io_i (clk_pclk_i),
|
||||
.rst_io_n_i (rst_pclk_n_i),
|
||||
.clk_hp_i (clk_hp_i),
|
||||
.rst_hp_n_i (rst_hp_n_i),
|
||||
.clk_mem_i (clk_mem_i),
|
||||
.rst_mem_n_i (rst_mem_n_i),
|
||||
.block_new_i (s_hp_block_hp),
|
||||
.recovery_i (s_hp_recovery_hp),
|
||||
.flush_i (s_hp_flush_hp),
|
||||
.resource_block_i (s_resource_quiesce | s_resource_reset),
|
||||
.mem_pad_mode_i (s_mem_pad_mode_lp),
|
||||
.ext_h_block_i (s_ext_h_block),
|
||||
.ext_h_read_base_i (s_ext_h_read_base),
|
||||
.ext_h_read_limit_i (s_ext_h_read_limit),
|
||||
.ext_h_write_base_i (s_ext_h_write_base),
|
||||
.ext_h_write_limit_i (s_ext_h_write_limit),
|
||||
.hp_icache_axi4 (u_hp_icache_axi4_if),
|
||||
.hp_dcache_axi4 (u_hp_dcache_axi4_if),
|
||||
.dma_axi4 (u_dma_axi4_if),
|
||||
.sdio0_axi4 (u_sdio0_axi4_if),
|
||||
.sdio1_axi4 (u_sdio1_axi4_if),
|
||||
.spisd_axi4 (u_spisd_axi4_if),
|
||||
.usb2_axi4 (u_usb2_axi4_if),
|
||||
.apu_axi4 (u_apu_axi4_if),
|
||||
.jpeg_axi4 (u_jpeg_wide_axi4_if),
|
||||
.lp_data_axi4 (u_mgmt_data_axi4_if),
|
||||
.ext_h_axi4 (u_ext_h_wide_axi4_if),
|
||||
.sram_gateway_axi4 (u_data_sram_axi4_if),
|
||||
.sdram_gateway_axi4 (u_data_sdram_axi4_if),
|
||||
.qpi_gateway_axi4 (u_data_qpi_axi4_if),
|
||||
.opi_gateway_axi4 (u_data_opi_axi4_if),
|
||||
.xpi_gateway_axi4 (u_data_xpi_axi4_if),
|
||||
.fabric_monitor_apb4 (u_fabric_monitor_hp_if),
|
||||
.idle_o (s_data_plane_idle),
|
||||
.flush_busy_o (s_data_plane_flush_busy),
|
||||
.ext_h_idle_o (s_ext_h_data_idle),
|
||||
.apu_bridge_epoch_o (s_apu_bridge_epoch),
|
||||
.resource_idle_o (s_resource_idle_hp),
|
||||
.resource_block_ack_o(s_resource_block_ack_hp),
|
||||
.outstanding_read_o (s_data_plane_outstanding_read),
|
||||
.outstanding_write_o (s_data_plane_outstanding_write),
|
||||
.fault_valid_o (s_data_plane_fault_valid),
|
||||
.fault_master_o (s_data_plane_fault_master),
|
||||
.fault_target_o (s_data_plane_fault_target),
|
||||
.fault_addr_o (s_data_plane_fault_addr),
|
||||
.fault_write_o (s_data_plane_fault_write),
|
||||
.fault_reason_o (s_data_plane_fault_reason)
|
||||
.clk_lp_i (clk_lp_i),
|
||||
.rst_lp_n_i (rst_lp_n_i),
|
||||
.clk_io_i (clk_pclk_i),
|
||||
.rst_io_n_i (rst_pclk_n_i),
|
||||
.clk_hp_i (clk_hp_i),
|
||||
.rst_hp_n_i (rst_hp_n_i),
|
||||
.clk_mem_i (clk_mem_i),
|
||||
.rst_mem_n_i (rst_mem_n_i),
|
||||
.block_new_i (s_hp_block_hp),
|
||||
.recovery_i (s_hp_recovery_hp),
|
||||
.flush_i (s_hp_flush_hp),
|
||||
.resource_block_i (s_resource_quiesce | s_resource_reset),
|
||||
.mem_pad_mode_i (s_mem_pad_mode_lp),
|
||||
.ext_h_block_i (s_ext_h_block),
|
||||
.ext_h_read_base_i (s_ext_h_read_base),
|
||||
.ext_h_read_limit_i (s_ext_h_read_limit),
|
||||
.ext_h_write_base_i (s_ext_h_write_base),
|
||||
.ext_h_write_limit_i (s_ext_h_write_limit),
|
||||
.hp_icache_axi4 (u_hp_icache_axi4_if),
|
||||
.hp_dcache_axi4 (u_hp_dcache_axi4_if),
|
||||
.dma_axi4 (u_dma_axi4_if),
|
||||
.sdio0_axi4 (u_sdio0_axi4_if),
|
||||
.sdio1_axi4 (u_sdio1_axi4_if),
|
||||
.spisd_axi4 (u_spisd_axi4_if),
|
||||
.usb2_axi4 (u_usb2_axi4_if),
|
||||
.apu_axi4 (u_apu_axi4_if),
|
||||
.jpeg_axi4 (u_jpeg_wide_axi4_if),
|
||||
.ga2d_axi4 (u_ga2d_wide_axi4_if),
|
||||
.lp_data_axi4 (u_mgmt_data_axi4_if),
|
||||
.ext_h_axi4 (u_ext_h_wide_axi4_if),
|
||||
.sram_gateway_axi4 (u_data_sram_axi4_if),
|
||||
.sdram_gateway_axi4 (u_data_sdram_axi4_if),
|
||||
.qpi_gateway_axi4 (u_data_qpi_axi4_if),
|
||||
.opi_gateway_axi4 (u_data_opi_axi4_if),
|
||||
.xpi_gateway_axi4 (u_data_xpi_axi4_if),
|
||||
.fabric_monitor_apb4 (u_fabric_monitor_hp_if),
|
||||
.idle_o (s_data_plane_idle),
|
||||
.flush_busy_o (s_data_plane_flush_busy),
|
||||
.ext_h_idle_o (s_ext_h_data_idle),
|
||||
.apu_bridge_epoch_o (s_apu_bridge_epoch),
|
||||
.ga2d_source_stop_o (s_ga2d_source_stop),
|
||||
.ga2d_source_safe_idle_o (s_ga2d_source_safe_idle),
|
||||
.ga2d_bridge_clear_busy_o(s_ga2d_bridge_clear_busy),
|
||||
.ga2d_bridge_epoch_o (s_ga2d_bridge_epoch),
|
||||
.ga2d_data_ready_o (s_ga2d_data_ready),
|
||||
.resource_idle_o (s_resource_idle_hp),
|
||||
.resource_block_ack_o (s_resource_block_ack_hp),
|
||||
.outstanding_read_o (s_data_plane_outstanding_read),
|
||||
.outstanding_write_o (s_data_plane_outstanding_write),
|
||||
.fault_valid_o (s_data_plane_fault_valid_hp),
|
||||
.fault_ready_i (s_data_plane_fault_ready_hp),
|
||||
.fault_master_o (s_data_plane_fault_master_hp),
|
||||
.fault_target_o (s_data_plane_fault_target_hp),
|
||||
.fault_addr_o (s_data_plane_fault_addr_hp),
|
||||
.fault_write_o (s_data_plane_fault_write_hp),
|
||||
.fault_reason_o (s_data_plane_fault_reason_hp)
|
||||
);
|
||||
|
||||
data_plane_fault_cdc u_data_plane_fault_cdc (
|
||||
.clk_hp_i (clk_hp_i),
|
||||
.rst_hp_n_i (rst_hp_n_i),
|
||||
.fault_valid_i (s_data_plane_fault_valid_hp),
|
||||
.fault_master_i(s_data_plane_fault_master_hp),
|
||||
.fault_target_i(s_data_plane_fault_target_hp),
|
||||
.fault_addr_i (s_data_plane_fault_addr_hp),
|
||||
.fault_write_i (s_data_plane_fault_write_hp),
|
||||
.fault_reason_i(s_data_plane_fault_reason_hp),
|
||||
.fault_ready_o (s_data_plane_fault_ready_hp),
|
||||
.clk_pclk_i (clk_pclk_i),
|
||||
.rst_pclk_n_i (rst_pclk_n_i),
|
||||
.fault_valid_o (s_data_plane_fault_valid_pclk),
|
||||
.fault_master_o(s_data_plane_fault_master_pclk),
|
||||
.fault_target_o(s_data_plane_fault_target_pclk),
|
||||
.fault_addr_o (s_data_plane_fault_addr_pclk),
|
||||
.fault_write_o (s_data_plane_fault_write_pclk),
|
||||
.fault_reason_o(s_data_plane_fault_reason_pclk)
|
||||
);
|
||||
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(8)
|
||||
.DATA_WIDTH(9)
|
||||
) u_resource_idle_sync (
|
||||
.clk_i (clk_pclk_i),
|
||||
.rst_n_i(rst_pclk_n_i),
|
||||
@@ -623,7 +668,7 @@ module retrosoc (
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(8)
|
||||
.DATA_WIDTH(9)
|
||||
) u_resource_block_ack_sync (
|
||||
.clk_i (clk_pclk_i),
|
||||
.rst_n_i(rst_pclk_n_i),
|
||||
@@ -632,6 +677,7 @@ module retrosoc (
|
||||
);
|
||||
|
||||
axi4_master_idle u_idle_master (.axi4(u_idle_axi4_if));
|
||||
axi4_master_idle u_ga2d_master_idle (.axi4(u_ga2d_wide_axi4_if));
|
||||
axi4_master_idle u_retired_sram_master (.axi4(u_retired_data_sram_axi4_if));
|
||||
axi4_master_idle u_retired_sdram_master (.axi4(u_retired_data_sdram_axi4_if));
|
||||
axi4_master_idle u_retired_qpi_master (.axi4(u_retired_data_qpi_axi4_if));
|
||||
@@ -723,7 +769,7 @@ module retrosoc (
|
||||
.Present (SramPresent),
|
||||
.CapacityKiB(`SOC_ADDR_SRAM_SIZE >> 10),
|
||||
.DataWidth (64),
|
||||
.IdWidth (6)
|
||||
.IdWidth (7)
|
||||
) u_onchip_ram (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i (rst_hp_n_i),
|
||||
@@ -855,7 +901,7 @@ module retrosoc (
|
||||
.usb2 (usb2),
|
||||
.opipsram (u_opipsram_raw_if),
|
||||
.i2c1 (u_i2c1_if),
|
||||
.fault_valid_i (s_data_plane_fault_valid || s_bus_fault_valid),
|
||||
.fault_valid_i (s_data_plane_fault_valid_pclk || s_bus_fault_valid),
|
||||
.fault_addr_i (s_fault_addr_mux),
|
||||
.fault_wstrb_i (s_fault_wstrb_mux),
|
||||
.fault_reserved_i (s_fault_reserved_mux),
|
||||
@@ -917,16 +963,19 @@ module retrosoc (
|
||||
);
|
||||
|
||||
assign s_resource_idle_combined = {
|
||||
s_ga2d_source_safe_idle && s_resource_idle_pclk[8],
|
||||
s_apu_idle && s_resource_idle_pclk[7],
|
||||
s_jpeg_idle && s_resource_idle_pclk[6],
|
||||
s_ext_h_data_idle && s_resource_idle_pclk[5],
|
||||
s_resource_idle_pclk[4:0]
|
||||
};
|
||||
assign s_resource_block_ack_combined = {
|
||||
s_apu_idle && s_resource_block_ack_pclk[7], s_resource_block_ack_pclk[6:0]
|
||||
s_ga2d_source_safe_idle && s_resource_block_ack_pclk[8],
|
||||
s_apu_idle && s_resource_block_ack_pclk[7],
|
||||
s_resource_block_ack_pclk[6:0]
|
||||
};
|
||||
|
||||
logic [36:0] s_unused_domain_inputs;
|
||||
logic [41:0] s_unused_domain_inputs;
|
||||
assign s_unused_domain_inputs = {
|
||||
clk_pclk_i,
|
||||
rst_pclk_n_i,
|
||||
@@ -934,9 +983,9 @@ module retrosoc (
|
||||
rst_mem_n_i ^ s_mem_pad_lock_lp,
|
||||
s_data_plane_outstanding_read,
|
||||
s_data_plane_outstanding_write,
|
||||
s_data_plane_fault_target,
|
||||
s_data_plane_fault_addr[1:0],
|
||||
s_data_plane_fault_reason[3],
|
||||
s_data_plane_fault_target_pclk,
|
||||
s_data_plane_fault_addr_pclk[1:0],
|
||||
s_data_plane_fault_reason_pclk[3],
|
||||
s_mgmt_router_idle,
|
||||
s_hp_lifecycle_draining,
|
||||
s_hp_lifecycle_fault,
|
||||
@@ -944,6 +993,11 @@ module retrosoc (
|
||||
^s_resource_owner_lock,
|
||||
^s_resource_quiesce,
|
||||
^s_resource_reset,
|
||||
s_ga2d_source_stop,
|
||||
s_ga2d_source_safe_idle,
|
||||
s_ga2d_bridge_clear_busy,
|
||||
^s_ga2d_bridge_epoch,
|
||||
s_ga2d_data_ready,
|
||||
^unused_cdc_clear_busy,
|
||||
^unused_cdc_epoch,
|
||||
^{s_hp_mmio_epoch, s_hp_mmio_clear_busy},
|
||||
|
||||
+386
-80
@@ -16,7 +16,7 @@ module soc_data_plane (
|
||||
input logic block_new_i,
|
||||
input logic recovery_i,
|
||||
input logic flush_i,
|
||||
input logic [7:0] resource_block_i,
|
||||
input logic [8:0] resource_block_i,
|
||||
input logic [1:0] mem_pad_mode_i,
|
||||
input logic ext_h_block_i,
|
||||
input logic [31:0] ext_h_read_base_i,
|
||||
@@ -32,6 +32,7 @@ module soc_data_plane (
|
||||
axi4_if.slave usb2_axi4,
|
||||
axi4_if.slave apu_axi4,
|
||||
axi4_if.slave jpeg_axi4,
|
||||
axi4_if.slave ga2d_axi4,
|
||||
axi4_if.slave lp_data_axi4,
|
||||
axi4_if.slave ext_h_axi4,
|
||||
axi4_if.master sram_gateway_axi4,
|
||||
@@ -40,16 +41,22 @@ module soc_data_plane (
|
||||
axi4_if.master opi_gateway_axi4,
|
||||
axi4_if.master xpi_gateway_axi4,
|
||||
apb4_if.slave fabric_monitor_apb4,
|
||||
input logic fault_ready_i,
|
||||
output logic idle_o,
|
||||
output logic flush_busy_o,
|
||||
output logic ext_h_idle_o,
|
||||
output logic [7:0] apu_bridge_epoch_o,
|
||||
output logic [7:0] resource_idle_o,
|
||||
output logic [7:0] resource_block_ack_o,
|
||||
output logic ga2d_source_stop_o,
|
||||
output logic ga2d_source_safe_idle_o,
|
||||
output logic ga2d_bridge_clear_busy_o,
|
||||
output logic [7:0] ga2d_bridge_epoch_o,
|
||||
output logic ga2d_data_ready_o,
|
||||
output logic [8:0] resource_idle_o,
|
||||
output logic [8:0] resource_block_ack_o,
|
||||
output logic [7:0] outstanding_read_o,
|
||||
output logic [7:0] outstanding_write_o,
|
||||
output logic fault_valid_o,
|
||||
output logic [2:0] fault_master_o,
|
||||
output logic [3:0] fault_master_o,
|
||||
output logic [2:0] fault_target_o,
|
||||
output logic [31:0] fault_addr_o,
|
||||
output logic fault_write_o,
|
||||
@@ -58,6 +65,9 @@ module soc_data_plane (
|
||||
);
|
||||
localparam int unsigned NumIoMasters = 3;
|
||||
localparam int unsigned NumMemoryTargets = 5;
|
||||
localparam int unsigned NumDataMasters = 9;
|
||||
localparam int unsigned NumFaultSources = NumMemoryTargets + 1;
|
||||
localparam int unsigned FaultSourceWidth = $clog2(NumFaultSources);
|
||||
localparam logic [3:0] FaultTimeout = 4'd5;
|
||||
|
||||
logic [ 1:0] s_mem_pad_mode_hp;
|
||||
@@ -70,58 +80,85 @@ module soc_data_plane (
|
||||
logic [NumMemoryTargets-1:0] s_guard_timeout_valid;
|
||||
logic [NumMemoryTargets-1:0] s_guard_isolated;
|
||||
logic [NumMemoryTargets-1:0] s_guard_timeout_write;
|
||||
logic [NumMemoryTargets-1:0][ 5:0] s_guard_timeout_id;
|
||||
logic [NumMemoryTargets-1:0][ 6:0] s_guard_timeout_id;
|
||||
logic [NumMemoryTargets-1:0][31:0] s_guard_timeout_addr;
|
||||
logic [NumMemoryTargets-1:0] s_target_abort_mem;
|
||||
logic s_crossbar_fault_valid;
|
||||
logic [ 2:0] s_crossbar_fault_master;
|
||||
logic [ 3:0] s_crossbar_fault_master;
|
||||
logic [ 2:0] s_crossbar_fault_target;
|
||||
logic [ 31:0] s_crossbar_fault_addr;
|
||||
logic s_crossbar_fault_write;
|
||||
logic [ 3:0] s_crossbar_fault_reason;
|
||||
logic s_lp_clear_busy;
|
||||
logic s_ext_clear_busy;
|
||||
logic s_jpeg_clear_busy;
|
||||
logic [ NumIoMasters-1:0][ 7:0] unused_io_epoch;
|
||||
logic [NumMemoryTargets-1:0][ 7:0] unused_target_epoch;
|
||||
logic [ 7:0] unused_lp_epoch;
|
||||
logic [ 7:0] unused_ext_epoch;
|
||||
logic [ 7:0] unused_jpeg_epoch;
|
||||
logic [ 2:0] s_unused_epoch;
|
||||
logic [ 7:0] s_resource_block_hp;
|
||||
logic [ 7:0] s_master_idle;
|
||||
logic [ 7:0] s_master_block;
|
||||
logic [ 7:0] s_monitor_master_read_accept;
|
||||
logic [ 7:0] s_monitor_master_write_accept;
|
||||
logic [ 7:0] s_monitor_master_read_beat;
|
||||
logic [ 7:0] s_monitor_master_write_beat;
|
||||
logic [ 7:0] s_monitor_master_wait;
|
||||
logic [ 7:0] s_monitor_master_promotion;
|
||||
logic [ 7:0][ 2:0] s_monitor_master_read_outstanding;
|
||||
logic [ 7:0][ 2:0] s_monitor_master_write_outstanding;
|
||||
logic [ 5:0] s_monitor_target_read_accept;
|
||||
logic [ 5:0] s_monitor_target_write_accept;
|
||||
logic [ 5:0] s_monitor_target_read_beat;
|
||||
logic [ 5:0] s_monitor_target_write_beat;
|
||||
logic [ 5:0] s_monitor_target_wait;
|
||||
logic [ 5:0][ 2:0] s_monitor_target_read_outstanding;
|
||||
logic [ 5:0][ 2:0] s_monitor_target_write_outstanding;
|
||||
logic [ 5:0] s_monitor_target_timeout;
|
||||
logic [ 5:0] s_monitor_target_isolated;
|
||||
logic s_crossbar_fault_ready;
|
||||
logic [NumMemoryTargets-1:0] s_guard_timeout_ready;
|
||||
logic [ NumFaultSources-1:0] s_fault_src_req;
|
||||
logic s_fault_src_candidate_valid;
|
||||
logic [FaultSourceWidth-1:0] s_fault_src_candidate;
|
||||
logic s_fault_src_hold_d, s_fault_src_hold_q;
|
||||
logic [FaultSourceWidth-1:0] s_fault_src_sel_d, s_fault_src_sel_q;
|
||||
logic [FaultSourceWidth-1:0] s_fault_src_last_d, s_fault_src_last_q;
|
||||
logic s_fault_src_valid;
|
||||
logic [FaultSourceWidth-1:0] s_fault_src_sel;
|
||||
logic s_lp_clear_busy;
|
||||
logic s_ext_clear_busy;
|
||||
logic s_jpeg_clear_busy;
|
||||
logic s_ga2d_clear_busy;
|
||||
logic [ NumIoMasters-1:0][7:0] unused_io_epoch;
|
||||
logic [NumMemoryTargets-1:0][7:0] unused_target_epoch;
|
||||
logic [ 7:0] unused_lp_epoch;
|
||||
logic [ 7:0] unused_ext_epoch;
|
||||
logic [ 7:0] unused_jpeg_epoch;
|
||||
logic [ 7:0] s_ga2d_epoch;
|
||||
logic [ 2:0] s_unused_epoch;
|
||||
logic s_ga2d_recovery_condition;
|
||||
logic s_ga2d_source_stop_q;
|
||||
logic s_ga2d_source_stop_ready;
|
||||
logic s_ga2d_source_safe_idle;
|
||||
logic s_ga2d_write_pending;
|
||||
logic s_ga2d_source_safe_idle_hp;
|
||||
logic s_ga2d_source_quiesced_q;
|
||||
logic s_ga2d_source_quiesced_hp;
|
||||
logic s_ga2d_hp_reset_n_pclk;
|
||||
logic s_ga2d_flush_pclk;
|
||||
logic [ 7:0] s_ga2d_epoch_seen_q;
|
||||
logic s_ga2d_data_ready_q;
|
||||
logic s_ga2d_rearm_q;
|
||||
logic s_ga2d_master_idle_pclk;
|
||||
logic s_ga2d_block_ack_pclk;
|
||||
logic [ 8:0] s_resource_block_hp;
|
||||
logic [ 8:0] s_master_idle;
|
||||
logic [ 8:0] s_master_block;
|
||||
logic [ 8:0] s_monitor_master_read_accept;
|
||||
logic [ 8:0] s_monitor_master_write_accept;
|
||||
logic [ 8:0] s_monitor_master_read_beat;
|
||||
logic [ 8:0] s_monitor_master_write_beat;
|
||||
logic [ 8:0] s_monitor_master_wait;
|
||||
logic [ 8:0] s_monitor_master_promotion;
|
||||
logic [ 8:0][2:0] s_monitor_master_read_outstanding;
|
||||
logic [ 8:0][2:0] s_monitor_master_write_outstanding;
|
||||
logic [ 5:0] s_monitor_target_read_accept;
|
||||
logic [ 5:0] s_monitor_target_write_accept;
|
||||
logic [ 5:0] s_monitor_target_read_beat;
|
||||
logic [ 5:0] s_monitor_target_write_beat;
|
||||
logic [ 5:0] s_monitor_target_wait;
|
||||
logic [ 5:0][2:0] s_monitor_target_read_outstanding;
|
||||
logic [ 5:0][2:0] s_monitor_target_write_outstanding;
|
||||
logic [ 5:0] s_monitor_target_timeout;
|
||||
logic [ 5:0] s_monitor_target_isolated;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_master_axi4[8] (
|
||||
) u_master_axi4[NumDataMasters] (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_crossbar_target_axi4[6] (
|
||||
.aclk (clk_hp_i),
|
||||
@@ -130,7 +167,7 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_target_axi4[NumMemoryTargets] (
|
||||
.aclk (clk_hp_i),
|
||||
@@ -139,7 +176,7 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_target_mem_axi4[NumMemoryTargets-1] (
|
||||
.aclk (clk_mem_i),
|
||||
@@ -157,7 +194,7 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_hp_icache_prefixed_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
@@ -166,7 +203,7 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_hp_dcache_prefixed_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
@@ -229,7 +266,7 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_ext_h_prefixed_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
@@ -247,12 +284,39 @@ module soc_data_plane (
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_jpeg_prefixed_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) u_ga2d_gated_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) u_ga2d_hp_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) u_ga2d_prefixed_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(2)
|
||||
@@ -264,15 +328,112 @@ module soc_data_plane (
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(8)
|
||||
.DATA_WIDTH(9)
|
||||
) u_resource_block_sync (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
.dat_i (resource_block_i),
|
||||
.dat_o (s_resource_block_hp)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_source_idle_sync (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
.dat_i (s_ga2d_source_safe_idle),
|
||||
.dat_o (s_ga2d_source_safe_idle_hp)
|
||||
);
|
||||
// A fresh source quiesce prevents stale idle from blocking W-before-AW traffic.
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_source_quiesced_sync (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
.dat_i (s_ga2d_source_quiesced_q),
|
||||
.dat_o (s_ga2d_source_quiesced_hp)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_hp_reset_sync (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i(rst_io_n_i),
|
||||
.dat_i (rst_hp_n_i),
|
||||
.dat_o (s_ga2d_hp_reset_n_pclk)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_flush_sync (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i(rst_io_n_i),
|
||||
.dat_i (flush_i),
|
||||
.dat_o (s_ga2d_flush_pclk)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_master_idle_sync (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i(rst_io_n_i),
|
||||
.dat_i (s_master_idle[8]),
|
||||
.dat_o (s_ga2d_master_idle_pclk)
|
||||
);
|
||||
cdc_sync #(
|
||||
.STAGE (2),
|
||||
.DATA_WIDTH(1)
|
||||
) u_ga2d_block_ack_sync (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i(rst_io_n_i),
|
||||
.dat_i (resource_block_ack_o[8]),
|
||||
.dat_o (s_ga2d_block_ack_pclk)
|
||||
);
|
||||
|
||||
assign s_ga2d_recovery_condition = resource_block_i[8] || !s_ga2d_hp_reset_n_pclk ||
|
||||
s_ga2d_flush_pclk || s_ga2d_clear_busy ||
|
||||
(s_ga2d_epoch != s_ga2d_epoch_seen_q);
|
||||
assign s_ga2d_source_stop_ready = (!ga2d_axi4.awvalid || ga2d_axi4.awready) &&
|
||||
(!ga2d_axi4.arvalid || ga2d_axi4.arready) &&
|
||||
(!ga2d_axi4.wvalid || s_ga2d_write_pending);
|
||||
assign ga2d_source_stop_o = s_ga2d_source_stop_q;
|
||||
assign ga2d_source_safe_idle_o = s_ga2d_source_safe_idle;
|
||||
assign ga2d_bridge_clear_busy_o = s_ga2d_clear_busy;
|
||||
assign ga2d_bridge_epoch_o = s_ga2d_epoch;
|
||||
assign ga2d_data_ready_o = s_ga2d_data_ready_q;
|
||||
|
||||
always_ff @(posedge clk_io_i or negedge rst_io_n_i) begin
|
||||
if (!rst_io_n_i) begin
|
||||
s_ga2d_source_stop_q <= 1'b1;
|
||||
s_ga2d_epoch_seen_q <= '0;
|
||||
s_ga2d_data_ready_q <= 1'b0;
|
||||
s_ga2d_rearm_q <= 1'b1;
|
||||
s_ga2d_source_quiesced_q <= 1'b0;
|
||||
end else begin
|
||||
s_ga2d_epoch_seen_q <= s_ga2d_epoch;
|
||||
s_ga2d_source_quiesced_q <= resource_block_i[8] && s_ga2d_source_stop_q &&
|
||||
s_ga2d_source_safe_idle;
|
||||
if (s_ga2d_recovery_condition) begin
|
||||
s_ga2d_rearm_q <= 1'b1;
|
||||
s_ga2d_data_ready_q <= 1'b0;
|
||||
if (s_ga2d_source_stop_ready) begin
|
||||
s_ga2d_source_stop_q <= 1'b1;
|
||||
end
|
||||
end else if (s_ga2d_rearm_q) begin
|
||||
s_ga2d_data_ready_q <= 1'b0;
|
||||
if (s_ga2d_source_safe_idle && s_ga2d_master_idle_pclk && !s_ga2d_block_ack_pclk) begin
|
||||
s_ga2d_source_stop_q <= 1'b0;
|
||||
s_ga2d_rearm_q <= 1'b0;
|
||||
end
|
||||
end else begin
|
||||
s_ga2d_data_ready_q <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign s_master_block = {
|
||||
s_resource_block_hp[8] && s_ga2d_source_quiesced_hp,
|
||||
s_resource_block_hp[5],
|
||||
s_resource_block_hp[6],
|
||||
1'b0,
|
||||
@@ -282,6 +443,8 @@ module soc_data_plane (
|
||||
2'b00
|
||||
};
|
||||
assign resource_idle_o = {
|
||||
(s_resource_block_hp[8] ? s_ga2d_source_quiesced_hp : s_ga2d_source_safe_idle_hp) &&
|
||||
s_master_idle[8],
|
||||
s_master_idle[3],
|
||||
s_master_idle[6],
|
||||
s_master_idle[7],
|
||||
@@ -291,10 +454,13 @@ module soc_data_plane (
|
||||
s_master_idle[3],
|
||||
s_master_idle[2]
|
||||
};
|
||||
assign resource_block_ack_o = s_resource_block_hp;
|
||||
assign resource_block_ack_o = {
|
||||
s_resource_block_hp[8] && s_ga2d_source_quiesced_hp && s_master_idle[8],
|
||||
s_resource_block_hp[7:0]
|
||||
};
|
||||
|
||||
axi4_id_prefix #(
|
||||
.MasterIndex(3'd0)
|
||||
.MasterIndex(4'd0)
|
||||
) u_hp_icache_prefix (
|
||||
.source(hp_icache_axi4),
|
||||
.sink (u_hp_icache_prefixed_axi4)
|
||||
@@ -304,7 +470,7 @@ module soc_data_plane (
|
||||
.sink (u_master_axi4[0])
|
||||
);
|
||||
axi4_id_prefix #(
|
||||
.MasterIndex(3'd1)
|
||||
.MasterIndex(4'd1)
|
||||
) u_hp_dcache_prefix (
|
||||
.source(hp_dcache_axi4),
|
||||
.sink (u_hp_dcache_prefixed_axi4)
|
||||
@@ -357,7 +523,7 @@ module soc_data_plane (
|
||||
.dst_axi4 (u_io_hp_axi4[master])
|
||||
);
|
||||
axi4_upsizer_32to64 #(
|
||||
.MasterIndex(3'(master + 2))
|
||||
.MasterIndex(4'(master + 2))
|
||||
) u_io_upsizer (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
@@ -381,7 +547,7 @@ module soc_data_plane (
|
||||
.dst_axi4 (u_lp_data_hp_axi4)
|
||||
);
|
||||
axi4_upsizer_32to64 #(
|
||||
.MasterIndex(3'd5)
|
||||
.MasterIndex(4'd5)
|
||||
) u_lp_data_upsizer (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
@@ -403,7 +569,7 @@ module soc_data_plane (
|
||||
.dst_axi4 (u_jpeg_hp_axi4)
|
||||
);
|
||||
axi4_id_prefix #(
|
||||
.MasterIndex(3'd6)
|
||||
.MasterIndex(4'd6)
|
||||
) u_jpeg_prefix (
|
||||
.source(u_jpeg_hp_axi4),
|
||||
.sink (u_jpeg_prefixed_axi4)
|
||||
@@ -413,6 +579,41 @@ module soc_data_plane (
|
||||
.sink (u_master_axi4[6])
|
||||
);
|
||||
|
||||
axi4_address_gate u_ga2d_source_gate (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i (rst_io_n_i),
|
||||
.block_new_i (s_ga2d_source_stop_q),
|
||||
.clear_i (s_ga2d_flush_pclk),
|
||||
.source (ga2d_axi4),
|
||||
.sink (u_ga2d_gated_axi4),
|
||||
.idle_o (s_ga2d_source_safe_idle),
|
||||
.write_pending_o(s_ga2d_write_pending)
|
||||
);
|
||||
axi4_async_bridge #(
|
||||
.DataWidth(64),
|
||||
.IdWidth (3)
|
||||
) u_ga2d_cdc (
|
||||
.src_clk_i (clk_io_i),
|
||||
.src_rst_n_i (rst_io_n_i),
|
||||
.dst_clk_i (clk_hp_i),
|
||||
.dst_rst_n_i (rst_hp_n_i),
|
||||
.clear_i (flush_i),
|
||||
.clear_busy_o(s_ga2d_clear_busy),
|
||||
.epoch_o (s_ga2d_epoch),
|
||||
.src_axi4 (u_ga2d_gated_axi4),
|
||||
.dst_axi4 (u_ga2d_hp_axi4)
|
||||
);
|
||||
axi4_id_prefix #(
|
||||
.MasterIndex(4'd8)
|
||||
) u_ga2d_prefix (
|
||||
.source(u_ga2d_hp_axi4),
|
||||
.sink (u_ga2d_prefixed_axi4)
|
||||
);
|
||||
axi4_connector u_ga2d_connector (
|
||||
.source(u_ga2d_prefixed_axi4),
|
||||
.sink (u_master_axi4[8])
|
||||
);
|
||||
|
||||
axi4_async_bridge #(
|
||||
.DataWidth(64),
|
||||
.IdWidth (3)
|
||||
@@ -428,15 +629,17 @@ module soc_data_plane (
|
||||
.dst_axi4 (u_ext_h_hp_axi4)
|
||||
);
|
||||
axi4_address_gate u_ext_h_address_gate (
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i (rst_io_n_i),
|
||||
.block_new_i(ext_h_block_i),
|
||||
.source (ext_h_axi4),
|
||||
.sink (u_ext_h_gated_axi4),
|
||||
.idle_o (ext_h_idle_o)
|
||||
.clk_i (clk_io_i),
|
||||
.rst_n_i (rst_io_n_i),
|
||||
.block_new_i (ext_h_block_i),
|
||||
.clear_i (1'b0),
|
||||
.source (ext_h_axi4),
|
||||
.sink (u_ext_h_gated_axi4),
|
||||
.idle_o (ext_h_idle_o),
|
||||
.write_pending_o()
|
||||
);
|
||||
axi4_id_prefix #(
|
||||
.MasterIndex(3'd7)
|
||||
.MasterIndex(4'd7)
|
||||
) u_ext_h_prefix (
|
||||
.source(u_ext_h_hp_axi4),
|
||||
.sink (u_ext_h_prefixed_axi4)
|
||||
@@ -447,6 +650,8 @@ module soc_data_plane (
|
||||
);
|
||||
|
||||
axi4_data_crossbar #(
|
||||
.NumMasters (NumDataMasters),
|
||||
.NumTargets (6),
|
||||
.ReadTargetMask (`SOC_DATA_POLICY_READ_TARGET_MASK),
|
||||
.WriteTargetMask (`SOC_DATA_POLICY_WRITE_TARGET_MASK),
|
||||
.AllowInstruction (`SOC_DATA_POLICY_ALLOW_INSTRUCTION),
|
||||
@@ -457,6 +662,8 @@ module soc_data_plane (
|
||||
.block_new_i (block_new_i),
|
||||
.master_block_i (s_master_block),
|
||||
.recovery_i (recovery_i),
|
||||
.flush_i (flush_i),
|
||||
.fault_ready_i (s_crossbar_fault_ready),
|
||||
.mem_pad_mode_i (s_mem_pad_mode_hp),
|
||||
.ext_h_read_base_i (ext_h_read_base_i),
|
||||
.ext_h_read_limit_i (ext_h_read_limit_i),
|
||||
@@ -496,6 +703,7 @@ module soc_data_plane (
|
||||
(target == 1) ? 32'd8192 : 32'd65535;
|
||||
|
||||
axi4_target_guard #(
|
||||
.IdWidth (7),
|
||||
.ReadDepth (target < 2 ? 4 : 2),
|
||||
.WriteDepth(2)
|
||||
) u_target_guard (
|
||||
@@ -507,6 +715,7 @@ module soc_data_plane (
|
||||
.abort_o (s_guard_abort[target]),
|
||||
.abort_done_i (s_guard_abort_done[target]),
|
||||
.timeout_valid_o(s_guard_timeout_valid[target]),
|
||||
.timeout_ready_i(s_guard_timeout_ready[target]),
|
||||
.isolated_o (s_guard_isolated[target]),
|
||||
.timeout_write_o(s_guard_timeout_write[target]),
|
||||
.timeout_id_o (s_guard_timeout_id[target]),
|
||||
@@ -524,7 +733,7 @@ module soc_data_plane (
|
||||
end else begin : gen_stable_memory
|
||||
axi4_async_bridge #(
|
||||
.DataWidth(64),
|
||||
.IdWidth (6)
|
||||
.IdWidth (7)
|
||||
) u_target_cdc (
|
||||
.src_clk_i (clk_hp_i),
|
||||
.src_rst_n_i (rst_hp_n_i),
|
||||
@@ -546,7 +755,7 @@ module soc_data_plane (
|
||||
.dat_o (s_target_abort_mem[target])
|
||||
);
|
||||
axi4_downsizer_64to32 #(
|
||||
.WideIdWidth(6)
|
||||
.WideIdWidth(7)
|
||||
) u_target_downsizer (
|
||||
.clk_i (clk_mem_i),
|
||||
.rst_n_i(rst_mem_n_i),
|
||||
@@ -560,17 +769,20 @@ module soc_data_plane (
|
||||
|
||||
axi4_error_slave #(
|
||||
.Response(2'b11),
|
||||
.IdWidth (6)
|
||||
.IdWidth (7)
|
||||
) u_data_error_slave (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i(rst_hp_n_i),
|
||||
.axi4 (u_crossbar_target_axi4[5])
|
||||
);
|
||||
|
||||
assign s_monitor_target_timeout = {1'b0, s_guard_timeout_valid};
|
||||
assign s_monitor_target_timeout = {1'b0, s_guard_timeout_valid & s_guard_timeout_ready};
|
||||
assign s_monitor_target_isolated = {1'b0, s_guard_isolated};
|
||||
|
||||
fabric_monitor u_fabric_monitor (
|
||||
fabric_monitor #(
|
||||
.NumMasters(NumDataMasters),
|
||||
.NumTargets(6)
|
||||
) u_fabric_monitor (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i (rst_hp_n_i),
|
||||
.idle_i (idle_o),
|
||||
@@ -579,7 +791,7 @@ module soc_data_plane (
|
||||
.flush_i (flush_i),
|
||||
.outstanding_read_i (outstanding_read_o),
|
||||
.outstanding_write_i (outstanding_write_o),
|
||||
.fault_valid_i (fault_valid_o),
|
||||
.fault_valid_i (fault_valid_o && fault_ready_i),
|
||||
.fault_master_i (fault_master_o),
|
||||
.fault_target_i (fault_target_o),
|
||||
.fault_addr_i (fault_addr_o),
|
||||
@@ -622,29 +834,123 @@ module soc_data_plane (
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
fault_valid_o = s_crossbar_fault_valid;
|
||||
fault_master_o = s_crossbar_fault_master;
|
||||
fault_target_o = s_crossbar_fault_target;
|
||||
fault_addr_o = s_crossbar_fault_addr;
|
||||
fault_write_o = s_crossbar_fault_write;
|
||||
fault_reason_o = s_crossbar_fault_reason;
|
||||
if (!s_crossbar_fault_valid) begin
|
||||
for (int target = NumMemoryTargets - 1; target >= 0; target--) begin
|
||||
if (s_guard_timeout_valid[target]) begin
|
||||
fault_valid_o = 1'b1;
|
||||
fault_master_o = s_guard_timeout_id[target][5:3];
|
||||
fault_target_o = 3'(target);
|
||||
fault_addr_o = s_guard_timeout_addr[target];
|
||||
fault_write_o = s_guard_timeout_write[target];
|
||||
fault_reason_o = FaultTimeout;
|
||||
s_fault_src_req = '0;
|
||||
s_fault_src_req[0] = s_crossbar_fault_valid;
|
||||
for (int target = 0; target < NumMemoryTargets; target++) begin
|
||||
s_fault_src_req[target+1] = s_guard_timeout_valid[target];
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_fault_src_candidate_valid = 1'b0;
|
||||
s_fault_src_candidate = '0;
|
||||
for (int offset = 1; offset <= NumFaultSources; offset++) begin
|
||||
int src;
|
||||
src = int'(s_fault_src_last_q) + offset;
|
||||
if (src >= NumFaultSources) src = src - NumFaultSources;
|
||||
if (!s_fault_src_candidate_valid && s_fault_src_req[src]) begin
|
||||
s_fault_src_candidate_valid = 1'b1;
|
||||
s_fault_src_candidate = FaultSourceWidth'(src);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_fault_src_valid = 1'b0;
|
||||
s_fault_src_sel = '0;
|
||||
if (s_fault_src_hold_q) begin
|
||||
s_fault_src_sel = s_fault_src_sel_q;
|
||||
s_fault_src_valid = s_fault_src_req[s_fault_src_sel_q];
|
||||
end else if (s_fault_src_candidate_valid) begin
|
||||
s_fault_src_sel = s_fault_src_candidate;
|
||||
s_fault_src_valid = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
fault_valid_o = s_fault_src_valid;
|
||||
fault_master_o = '0;
|
||||
fault_target_o = '0;
|
||||
fault_addr_o = '0;
|
||||
fault_write_o = 1'b0;
|
||||
fault_reason_o = '0;
|
||||
if (s_fault_src_valid) begin
|
||||
if (s_fault_src_sel == FaultSourceWidth'(0)) begin
|
||||
fault_master_o = s_crossbar_fault_master;
|
||||
fault_target_o = s_crossbar_fault_target;
|
||||
fault_addr_o = s_crossbar_fault_addr;
|
||||
fault_write_o = s_crossbar_fault_write;
|
||||
fault_reason_o = s_crossbar_fault_reason;
|
||||
end else begin
|
||||
for (int target = 0; target < NumMemoryTargets; target++) begin
|
||||
if (s_fault_src_sel == FaultSourceWidth'(target + 1)) begin
|
||||
fault_master_o = s_guard_timeout_id[target][6:3];
|
||||
fault_target_o = 3'(target);
|
||||
fault_addr_o = s_guard_timeout_addr[target];
|
||||
fault_write_o = s_guard_timeout_write[target];
|
||||
fault_reason_o = FaultTimeout;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_crossbar_fault_ready = 1'b0;
|
||||
s_guard_timeout_ready = '0;
|
||||
if (s_fault_src_valid && fault_ready_i) begin
|
||||
if (s_fault_src_sel == FaultSourceWidth'(0)) begin
|
||||
s_crossbar_fault_ready = 1'b1;
|
||||
end else begin
|
||||
for (int target = 0; target < NumMemoryTargets; target++) begin
|
||||
if (s_fault_src_sel == FaultSourceWidth'(target + 1)) begin
|
||||
s_guard_timeout_ready[target] = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
s_fault_src_hold_d = s_fault_src_hold_q;
|
||||
s_fault_src_sel_d = s_fault_src_sel_q;
|
||||
s_fault_src_last_d = s_fault_src_last_q;
|
||||
if (flush_i) begin
|
||||
s_fault_src_hold_d = 1'b0;
|
||||
end else if (s_fault_src_hold_q) begin
|
||||
if (!s_fault_src_valid) begin
|
||||
s_fault_src_hold_d = 1'b0;
|
||||
end else if (fault_ready_i) begin
|
||||
s_fault_src_hold_d = 1'b0;
|
||||
s_fault_src_last_d = s_fault_src_sel_q;
|
||||
end
|
||||
end else if (s_fault_src_candidate_valid) begin
|
||||
if (fault_ready_i) begin
|
||||
s_fault_src_last_d = s_fault_src_candidate;
|
||||
end else begin
|
||||
s_fault_src_hold_d = 1'b1;
|
||||
s_fault_src_sel_d = s_fault_src_candidate;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Each source holds its payload until accepted; the selector locks it while
|
||||
// the mailbox backpressures and rotates grants after every accepted event.
|
||||
always_ff @(posedge clk_hp_i or negedge rst_hp_n_i) begin
|
||||
if (!rst_hp_n_i) begin
|
||||
s_fault_src_hold_q <= 1'b0;
|
||||
s_fault_src_sel_q <= '0;
|
||||
s_fault_src_last_q <= FaultSourceWidth'(NumFaultSources - 1);
|
||||
end else begin
|
||||
s_fault_src_hold_q <= s_fault_src_hold_d;
|
||||
s_fault_src_sel_q <= s_fault_src_sel_d;
|
||||
s_fault_src_last_q <= s_fault_src_last_d;
|
||||
end
|
||||
end
|
||||
|
||||
assign flush_busy_o = (|s_io_clear_busy) || (|s_target_clear_busy) ||
|
||||
(|s_guard_clear_busy) || s_lp_clear_busy || s_ext_clear_busy ||
|
||||
s_jpeg_clear_busy;
|
||||
s_jpeg_clear_busy || s_ga2d_clear_busy;
|
||||
assign apu_bridge_epoch_o = unused_io_epoch[1];
|
||||
assign s_unused_epoch = {
|
||||
^unused_io_epoch, ^unused_target_epoch, ^{unused_lp_epoch, unused_ext_epoch, unused_jpeg_epoch}
|
||||
|
||||
@@ -342,6 +342,7 @@
|
||||
"core_wrapper.sv",
|
||||
"clock_config_controller.sv",
|
||||
"clock_frequency_monitor.sv",
|
||||
"data_plane_fault_cdc.sv",
|
||||
"extension_compat.sv",
|
||||
"extension_dma_master.sv",
|
||||
"extension_slot.sv",
|
||||
|
||||
@@ -23,6 +23,10 @@ CDC_PRIMITIVES = {
|
||||
"edge_det",
|
||||
"hazard3_apb_async_bridge",
|
||||
}
|
||||
DATA_PLANE_FAULT_RESET_CONTRACT = {
|
||||
"source_reset": "abort_accepted_mailbox_item",
|
||||
"destination_reset": "abort_accepted_item_backpressure_unaccepted_source",
|
||||
}
|
||||
IDENTIFIER_RE = re.compile(r"[A-Za-z_][A-Za-z0-9_]*$")
|
||||
HIERARCHICAL_PIN_RE = re.compile(
|
||||
r"[A-Za-z_][A-Za-z0-9_.]*(?:/[A-Za-z_][A-Za-z0-9_.]*)+$"
|
||||
@@ -144,6 +148,17 @@ def validate(document_path: Path, root: Path) -> None:
|
||||
raise ValueError(f"{field}.primitive is not an approved CDC primitive")
|
||||
path = root / require_string(crossing.get("path"), f"{field}.path")
|
||||
instance = require_identifier(crossing.get("instance"), f"{field}.instance")
|
||||
if name == "data_plane_fault":
|
||||
if primitive != "async_reqack" or instance != "u_fault_mailbox":
|
||||
raise ValueError(
|
||||
f"{field} must use async_reqack instance u_fault_mailbox"
|
||||
)
|
||||
reset_contract = crossing.get("unilateral_reset")
|
||||
if (not isinstance(reset_contract, dict) or
|
||||
reset_contract != DATA_PLANE_FAULT_RESET_CONTRACT):
|
||||
raise ValueError(
|
||||
f"{field}.unilateral_reset must declare the data-plane fault reset contract"
|
||||
)
|
||||
require_instance(path, primitive, instance, field)
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ TEST_SOURCES = (
|
||||
"crt/src/hal/dma_math.c",
|
||||
"crt/src/hal/jpeg_math.c",
|
||||
"crt/src/hal/apu.c",
|
||||
"crt/src/hal/fabric_monitor.c",
|
||||
"crt/src/hal/sysctrl.c",
|
||||
"crt/src/hal/clock.c",
|
||||
"crt/src/hal/resource.c",
|
||||
@@ -95,6 +96,7 @@ def main() -> int:
|
||||
"-Werror",
|
||||
"-fno-builtin",
|
||||
"-DRS_APU_TEST_MMIO",
|
||||
"-DRS_FABRIC_MONITOR_TEST_MMIO",
|
||||
"-I",
|
||||
str(memory_map_root / "include"),
|
||||
"-I",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <retrosoc/hal/clock.h>
|
||||
#include <retrosoc/hal/extension.h>
|
||||
#include <retrosoc/hal/dma.h>
|
||||
#include <retrosoc/hal/fabric_monitor.h>
|
||||
#include <retrosoc/hal/i2c.h>
|
||||
#include <retrosoc/hal/lcd.h>
|
||||
#include <retrosoc/hal/i2s.h>
|
||||
@@ -44,8 +45,10 @@ unsigned long long __umoddi3(unsigned long long dividend, unsigned long long div
|
||||
static uint8_t storage[32];
|
||||
static uint32_t image_call_count;
|
||||
volatile uint32_t rs_apu_test_mmio[1024];
|
||||
volatile uint32_t rs_fabric_monitor_test_mmio[1024];
|
||||
|
||||
#define APU_TEST_REG(offset) rs_apu_test_mmio[(offset) / 4U]
|
||||
#define FABRIC_MONITOR_TEST_REG(offset) rs_fabric_monitor_test_mmio[(offset) / 4U]
|
||||
|
||||
void putch(char ch) {
|
||||
(void)ch;
|
||||
@@ -855,6 +858,12 @@ static int test_extension_validation(void) {
|
||||
static int test_resource_validation(void) {
|
||||
rs_resource_status_t status;
|
||||
|
||||
if ((RS_RESOURCE_DMA != 0) || (RS_RESOURCE_USB2 != 1) || (RS_RESOURCE_SDIO0 != 2) ||
|
||||
(RS_RESOURCE_SDIO1 != 3) || (RS_RESOURCE_SPISD != 4) || (RS_RESOURCE_EXT_H != 5) ||
|
||||
(RS_RESOURCE_JPEG != 6) || (RS_RESOURCE_APU != 7) || (RS_RESOURCE_GA2D != 8) ||
|
||||
(RS_RESOURCE_COUNT != 9)) {
|
||||
return 1;
|
||||
}
|
||||
if ((rs_resource_get_status((rs_resource_t)RS_RESOURCE_COUNT, &status) != RS_EINVAL) ||
|
||||
(rs_resource_get_status(RS_RESOURCE_DMA, NULL) != RS_EINVAL) ||
|
||||
(rs_resource_set_owner((rs_resource_t)RS_RESOURCE_COUNT, RS_RESOURCE_OWNER_LP, false) !=
|
||||
@@ -863,8 +872,54 @@ static int test_resource_validation(void) {
|
||||
(rs_resource_set_lifecycle((rs_resource_t)RS_RESOURCE_COUNT, false, false) != RS_EINVAL) ||
|
||||
(rs_resource_clear_fault((rs_resource_t)RS_RESOURCE_COUNT) != RS_EINVAL) ||
|
||||
(rs_resource_get_cache_status(NULL) != RS_EINVAL)) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_fabric_monitor_mmio_reset(void) {
|
||||
for (size_t index = 0U;
|
||||
index < (sizeof(rs_fabric_monitor_test_mmio) / sizeof(rs_fabric_monitor_test_mmio[0]));
|
||||
++index) {
|
||||
rs_fabric_monitor_test_mmio[index] = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
static int test_fabric_monitor_hal_contract(void) {
|
||||
rs_fabric_fault_t fault;
|
||||
|
||||
if ((RS_FABRIC_MASTER_HP_ICACHE != 0) || (RS_FABRIC_MASTER_HP_DCACHE != 1) ||
|
||||
(RS_FABRIC_MASTER_DMA != 2) || (RS_FABRIC_MASTER_IO_A != 3) ||
|
||||
(RS_FABRIC_MASTER_IO_B != 4) || (RS_FABRIC_MASTER_LP != 5) ||
|
||||
(RS_FABRIC_MASTER_JPEG != 6) || (RS_FABRIC_MASTER_RESERVED != 6) ||
|
||||
(RS_FABRIC_MASTER_EXT_H != 7) || (RS_FABRIC_MASTER_GA2D != 8) ||
|
||||
(RS_FABRIC_MASTER_COUNT != 9)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
test_fabric_monitor_mmio_reset();
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x004)) = UINT32_C(0x00010000);
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x014)) =
|
||||
UINT32_C(0x00001000) | UINT32_C(0x0A00) | UINT32_C(0x0080) | UINT32_C(0x000C) |
|
||||
UINT32_C(0x0003);
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x018)) = UINT32_C(0x12345678);
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x020)) = UINT32_C(0x0000002A);
|
||||
if ((rs_fabric_monitor_read_fault(&fault) != RS_OK) || (fault.master != 3U) ||
|
||||
(fault.target != 4U) || (fault.reason != 10U) || !fault.valid || !fault.write ||
|
||||
(fault.address != UINT32_C(0x12345678)) || (fault.count != UINT32_C(0x0000002A))) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x004)) = UINT32_C(0x00010001);
|
||||
FABRIC_MONITOR_TEST_REG(UINT32_C(0x014)) =
|
||||
UINT32_C(0x00001000) | UINT32_C(0x0A00) | UINT32_C(0x0080) | UINT32_C(0x0003);
|
||||
if ((rs_fabric_monitor_read_fault(&fault) != RS_OK) ||
|
||||
(fault.master != RS_FABRIC_MASTER_GA2D)) {
|
||||
return 3;
|
||||
}
|
||||
if (rs_fabric_monitor_read_fault(NULL) != RS_EINVAL) {
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1205,6 +1260,7 @@ int main(void) {
|
||||
test_user_ip_validation(),
|
||||
test_extension_validation(),
|
||||
test_resource_validation(),
|
||||
test_fabric_monitor_hal_contract(),
|
||||
test_apu_validation(),
|
||||
test_apu_hal_contract(),
|
||||
test_jpeg_validation(),
|
||||
|
||||
@@ -374,6 +374,7 @@ module apu_p2_integration_tb;
|
||||
.abort_o (target_guard_abort),
|
||||
.abort_done_i (target_guard_abort),
|
||||
.timeout_valid_o(),
|
||||
.timeout_ready_i(1'b1),
|
||||
.isolated_o (),
|
||||
.timeout_write_o(),
|
||||
.timeout_id_o (),
|
||||
|
||||
@@ -4,7 +4,9 @@ module axi4_address_gate_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic block_new_i = 1'b0;
|
||||
logic clear_i = 1'b0;
|
||||
logic idle_o;
|
||||
logic write_pending_o;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
@@ -28,12 +30,14 @@ module axi4_address_gate_tb;
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
axi4_address_gate u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.block_new_i(block_new_i),
|
||||
.source (source),
|
||||
.sink (sink),
|
||||
.idle_o (idle_o)
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.block_new_i (block_new_i),
|
||||
.clear_i (clear_i),
|
||||
.source (source),
|
||||
.sink (sink),
|
||||
.idle_o (idle_o),
|
||||
.write_pending_o(write_pending_o)
|
||||
);
|
||||
|
||||
initial begin
|
||||
@@ -111,6 +115,15 @@ module axi4_address_gate_tb;
|
||||
sink.bvalid = 1'b0;
|
||||
if (!idle_o) $fatal(1, "write completion did not restore idle");
|
||||
|
||||
source.wvalid = 1'b1;
|
||||
#1;
|
||||
if (idle_o || source.wready || sink.wvalid || write_pending_o) begin
|
||||
$fatal(1, "write data before its address was accepted or reported idle");
|
||||
end
|
||||
source.wvalid = 1'b0;
|
||||
#1;
|
||||
if (!idle_o) $fatal(1, "unaccepted write data did not restore idle after withdrawal");
|
||||
|
||||
block_new_i = 1'b0;
|
||||
source.arvalid = 1'b1;
|
||||
@(posedge clk_i);
|
||||
@@ -128,6 +141,25 @@ module axi4_address_gate_tb;
|
||||
sink.rvalid = 1'b0;
|
||||
if (!idle_o) $fatal(1, "read completion did not restore idle");
|
||||
|
||||
block_new_i = 1'b0;
|
||||
clear_i = 1'b1;
|
||||
source.awvalid = 1'b1;
|
||||
source.wvalid = 1'b1;
|
||||
source.arvalid = 1'b1;
|
||||
#1;
|
||||
if (source.awready || source.wready || source.arready || sink.awvalid || sink.wvalid ||
|
||||
sink.arvalid) begin
|
||||
$fatal(1, "clear boundary accepted a source transaction");
|
||||
end
|
||||
@(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
source.awvalid = 1'b0;
|
||||
source.wvalid = 1'b0;
|
||||
source.arvalid = 1'b0;
|
||||
clear_i = 1'b0;
|
||||
#1;
|
||||
if (!idle_o) $fatal(1, "clear boundary did not restore the gate to idle");
|
||||
|
||||
$display("AXI4 address gate quiesce test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module axi4_data_crossbar_tb;
|
||||
localparam int NumMasters = 8;
|
||||
localparam int NumMasters = 9;
|
||||
localparam int NumTargets = 6;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic idle_o;
|
||||
logic [ 7:0] master_block_i = '0;
|
||||
logic [ 7:0] master_idle_o;
|
||||
logic [ 8:0] master_block_i = '0;
|
||||
logic [ 8:0] master_idle_o;
|
||||
logic [ 7:0] outstanding_read_o;
|
||||
logic [ 7:0] outstanding_write_o;
|
||||
logic fault_valid_o;
|
||||
logic [ 2:0] fault_master_o;
|
||||
logic fault_ready_i = 1'b1;
|
||||
logic [ 3:0] fault_master_o;
|
||||
logic [ 2:0] fault_target_o;
|
||||
logic [31:0] fault_addr_o;
|
||||
logic fault_write_o;
|
||||
logic [ 3:0] fault_reason_o;
|
||||
logic recovery_i = 1'b0;
|
||||
logic [ 7:0] monitor_master_promotion_o;
|
||||
logic flush_i = 1'b0;
|
||||
logic [ 8:0] monitor_master_promotion_o;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) masters[NumMasters] (
|
||||
.aclk (clk_i),
|
||||
@@ -32,7 +34,7 @@ module axi4_data_crossbar_tb;
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) targets[NumTargets] (
|
||||
.aclk (clk_i),
|
||||
@@ -47,17 +49,23 @@ module axi4_data_crossbar_tb;
|
||||
end
|
||||
|
||||
axi4_data_crossbar #(
|
||||
.StarvationCycles (4),
|
||||
.ReadTargetMask (40'b1111100000111111111111111111111111111111),
|
||||
.WriteTargetMask (40'b0111100000011110111101111011110111100000),
|
||||
.AllowInstruction (8'b00000001),
|
||||
.RequireNoncacheable(8'b11111100)
|
||||
.StarvationCycles(4),
|
||||
.ReadTargetMask(
|
||||
'{5'b11111, 5'b11111, 5'b11111, 5'b11111, 5'b11111, 5'b11111, 5'b11111, 5'b11111, 5'b11111}
|
||||
),
|
||||
.WriteTargetMask(
|
||||
'{5'b01111, 5'b01111, 5'b01111, 5'b01111, 5'b01111, 5'b01111, 5'b01111, 5'b01111, 5'b00000}
|
||||
),
|
||||
.AllowInstruction(9'b000000001),
|
||||
.RequireNoncacheable(9'b111111100)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.block_new_i (1'b0),
|
||||
.master_block_i (master_block_i),
|
||||
.recovery_i (recovery_i),
|
||||
.flush_i (flush_i),
|
||||
.fault_ready_i (fault_ready_i),
|
||||
.mem_pad_mode_i (2'd1),
|
||||
.ext_h_read_base_i (32'h3000_0000),
|
||||
.ext_h_read_limit_i (32'h4FFF_FFFF),
|
||||
@@ -78,7 +86,7 @@ module axi4_data_crossbar_tb;
|
||||
.monitor_master_promotion_o(monitor_master_promotion_o)
|
||||
);
|
||||
|
||||
task automatic issue_master1_read(input logic [5:0] id, input logic [31:0] addr);
|
||||
task automatic issue_master1_read(input logic [6:0] id, input logic [31:0] addr);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
masters[1].arid = id;
|
||||
@@ -90,7 +98,7 @@ module axi4_data_crossbar_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_target0_read(input logic [5:0] id, input logic [63:0] data);
|
||||
task automatic return_target0_read(input logic [6:0] id, input logic [63:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
targets[0].rid = id;
|
||||
@@ -104,7 +112,7 @@ module axi4_data_crossbar_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_target1_read(input logic [5:0] id, input logic [63:0] data);
|
||||
task automatic return_target1_read(input logic [6:0] id, input logic [63:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
targets[1].rid = id;
|
||||
@@ -118,7 +126,7 @@ module axi4_data_crossbar_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_target5_read(input logic [5:0] id);
|
||||
task automatic return_target5_read(input logic [6:0] id);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
targets[5].rid = id;
|
||||
@@ -131,6 +139,57 @@ module axi4_data_crossbar_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_target0_write(input logic [6:0] id);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
targets[0].bid = id;
|
||||
targets[0].bresp = 2'b00;
|
||||
targets[0].bvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!targets[0].bready);
|
||||
@(negedge clk_i);
|
||||
targets[0].bvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_invalid_target0_response(input logic [3:0] prefix,
|
||||
input logic write_access);
|
||||
logic [6:0] id;
|
||||
begin
|
||||
id = {prefix, 3'd0};
|
||||
@(negedge clk_i);
|
||||
if (write_access) begin
|
||||
targets[0].bid = id;
|
||||
targets[0].bresp = 2'b00;
|
||||
targets[0].bvalid = 1'b1;
|
||||
end else begin
|
||||
targets[0].rid = id;
|
||||
targets[0].rdata = 64'hDEAD_BEEF_0000_0000 | id;
|
||||
targets[0].rresp = 2'b00;
|
||||
targets[0].rlast = 1'b1;
|
||||
targets[0].rvalid = 1'b1;
|
||||
end
|
||||
#1;
|
||||
if (!(write_access ? targets[0].bready : targets[0].rready)) begin
|
||||
$fatal(1, "invalid returned master prefix was not accepted for containment");
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!fault_valid_o || (fault_master_o != prefix) || (fault_target_o != 3'd0) ||
|
||||
(fault_reason_o != 4'd4) || (fault_write_o != write_access)) begin
|
||||
$fatal(1, "invalid returned master prefix was not contained");
|
||||
end
|
||||
if (masters[0].rvalid || masters[0].bvalid) begin
|
||||
$fatal(1, "invalid response prefix fell back to master 0");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
if (write_access) begin
|
||||
targets[0].bvalid = 1'b0;
|
||||
end else begin
|
||||
targets[0].rvalid = 1'b0;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
`define INIT_MASTER(index) \
|
||||
masters[index].awid = '0; \
|
||||
masters[index].awaddr = '0; \
|
||||
@@ -188,6 +247,7 @@ module axi4_data_crossbar_tb;
|
||||
`INIT_MASTER(5)
|
||||
`INIT_MASTER(6)
|
||||
`INIT_MASTER(7)
|
||||
`INIT_MASTER(8)
|
||||
`INIT_TARGET(0)
|
||||
`INIT_TARGET(1)
|
||||
`INIT_TARGET(2)
|
||||
@@ -239,6 +299,83 @@ module axi4_data_crossbar_tb;
|
||||
$fatal(1, "read completion did not drain the crossbar");
|
||||
end
|
||||
|
||||
ga2d_master_id_credit_and_qos : begin
|
||||
@(negedge clk_i);
|
||||
targets[0].arready = 1'b0;
|
||||
masters[8].arid = 7'h40;
|
||||
masters[8].araddr = 32'h3000_0040;
|
||||
masters[8].arqos = 4'hF;
|
||||
masters[8].arvalid = 1'b1;
|
||||
#1;
|
||||
if (!targets[0].arvalid || (targets[0].arid != 7'h40) || (targets[0].arqos != 4'd0)) begin
|
||||
$fatal(1, "GA2D read ID prefix or AxQOS was not preserved");
|
||||
end
|
||||
targets[0].arready = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[8].arready);
|
||||
@(negedge clk_i);
|
||||
masters[8].arvalid = 1'b0;
|
||||
masters[8].arqos = '0;
|
||||
|
||||
@(negedge clk_i);
|
||||
targets[0].awready = 1'b0;
|
||||
masters[8].awid = 7'h41;
|
||||
masters[8].awaddr = 32'h3000_0080;
|
||||
masters[8].awqos = 4'hF;
|
||||
masters[8].awvalid = 1'b1;
|
||||
#1;
|
||||
if (!targets[0].awvalid || (targets[0].awid != 7'h41) || (targets[0].awqos != 4'd0)) begin
|
||||
$fatal(1, "GA2D write ID prefix or AxQOS was not preserved");
|
||||
end
|
||||
targets[0].awready = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[8].awready);
|
||||
@(negedge clk_i);
|
||||
masters[8].awvalid = 1'b0;
|
||||
masters[8].awqos = '0;
|
||||
masters[8].wdata = 64'hA5A5_5A5A_1122_3344;
|
||||
masters[8].wstrb = 8'hFF;
|
||||
masters[8].wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[8].wready);
|
||||
@(negedge clk_i);
|
||||
masters[8].wvalid = 1'b0;
|
||||
|
||||
@(negedge clk_i);
|
||||
masters[8].arid = 7'h42;
|
||||
masters[8].araddr = 32'h3000_00C0;
|
||||
masters[8].arvalid = 1'b1;
|
||||
masters[8].awid = 7'h43;
|
||||
masters[8].awaddr = 32'h3000_0100;
|
||||
masters[8].awvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[8].arready || masters[8].awready) begin
|
||||
$fatal(1, "GA2D exceeded its one-read plus one-write credit");
|
||||
end
|
||||
masters[8].arvalid = 1'b0;
|
||||
masters[8].awvalid = 1'b0;
|
||||
|
||||
fork
|
||||
return_target0_read(7'h40, 64'h8888_8888_8888_0040);
|
||||
begin
|
||||
wait (masters[8].rvalid);
|
||||
if ((masters[8].rid != 7'h40) || (masters[8].rdata != 64'h8888_8888_8888_0040)) begin
|
||||
$fatal(1, "GA2D read response did not return to master 8");
|
||||
end
|
||||
end
|
||||
join
|
||||
fork
|
||||
return_target0_write(7'h41);
|
||||
begin
|
||||
wait (masters[8].bvalid);
|
||||
if (masters[8].bid != 7'h41) begin
|
||||
$fatal(1, "GA2D write response did not return to master 8");
|
||||
end
|
||||
end
|
||||
join
|
||||
@(negedge clk_i);
|
||||
if (!idle_o || (outstanding_read_o != 8'd0) || (outstanding_write_o != 8'd0)) begin
|
||||
$fatal(1, "GA2D master credits did not drain independently");
|
||||
end
|
||||
end
|
||||
|
||||
issue_master1_read(6'b001_010, 32'h3000_0040);
|
||||
issue_master1_read(6'b001_011, 32'h3000_0080);
|
||||
if (outstanding_read_o != 8'd2) begin
|
||||
@@ -268,25 +405,76 @@ module axi4_data_crossbar_tb;
|
||||
$fatal(1, "same-target reads did not drain the crossbar");
|
||||
end
|
||||
|
||||
@(negedge clk_i);
|
||||
masters[6].arid = 6'b110_000;
|
||||
masters[6].araddr = 32'h3000_0000;
|
||||
masters[6].arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[6].arready);
|
||||
#1;
|
||||
if (!fault_valid_o || (fault_master_o != 3'd6) ||
|
||||
(fault_reason_o != 4'd3) || fault_write_o) begin
|
||||
$fatal(1, "reserved-master ACL fault attribution mismatch");
|
||||
jpeg_zero_credit : begin
|
||||
@(negedge clk_i);
|
||||
masters[6].arid = 7'h30;
|
||||
masters[6].araddr = 32'h3000_0000;
|
||||
masters[6].arvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[6].arready || targets[0].arvalid) begin
|
||||
$fatal(1, "JPEG read received normal admission credit");
|
||||
end
|
||||
masters[6].arvalid = 1'b0;
|
||||
|
||||
@(negedge clk_i);
|
||||
masters[6].awid = 7'h31;
|
||||
masters[6].awaddr = 32'h3000_0040;
|
||||
masters[6].awvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[6].awready || targets[0].awvalid) begin
|
||||
$fatal(1, "JPEG write received normal admission credit");
|
||||
end
|
||||
masters[6].awvalid = 1'b0;
|
||||
end
|
||||
|
||||
fault_backpressure : begin
|
||||
@(negedge clk_i);
|
||||
fault_ready_i = 1'b0;
|
||||
masters[2].arid = 6'b010_110;
|
||||
masters[2].araddr = 32'h3000_0060;
|
||||
masters[2].arcache = 4'b0011;
|
||||
masters[2].arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[2].arready);
|
||||
#1;
|
||||
if (!fault_valid_o || (fault_master_o != 4'd2) ||
|
||||
(fault_addr_o != 32'h3000_0060) || (fault_reason_o != 4'd3)) begin
|
||||
$fatal(1, "first backpressured fault was not retained");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
masters[2].arvalid = 1'b0;
|
||||
masters[2].arcache = '0;
|
||||
masters[1].arid = 6'b001_110;
|
||||
masters[1].araddr = 32'h3000_00A0;
|
||||
masters[1].arprot = 3'b100;
|
||||
masters[1].arvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[1].arready) begin
|
||||
$fatal(1, "second faulting request bypassed a full fault slot");
|
||||
end
|
||||
repeat (2) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!fault_valid_o || (fault_master_o != 4'd2) ||
|
||||
(fault_addr_o != 32'h3000_0060) || (fault_reason_o != 4'd3) ||
|
||||
masters[1].arready) begin
|
||||
$fatal(1, "backpressured fault payload or admission was not held");
|
||||
end
|
||||
end
|
||||
return_target5_read(6'b010_110);
|
||||
@(negedge clk_i);
|
||||
fault_ready_i = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[1].arready);
|
||||
#1;
|
||||
if (!fault_valid_o || (fault_master_o != 4'd1) ||
|
||||
(fault_addr_o != 32'h3000_00A0) || (fault_reason_o != 4'd3)) begin
|
||||
$fatal(1, "second backpressured fault was not delivered after release");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
masters[1].arvalid = 1'b0;
|
||||
masters[1].arprot = '0;
|
||||
return_target5_read(6'b001_110);
|
||||
@(posedge clk_i);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
masters[6].arvalid = 1'b0;
|
||||
targets[5].rid = 6'b110_000;
|
||||
targets[5].rresp = 2'b10;
|
||||
targets[5].rlast = 1'b1;
|
||||
targets[5].rvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!targets[5].rready);
|
||||
@(negedge clk_i);
|
||||
targets[5].rvalid = 1'b0;
|
||||
|
||||
@(negedge clk_i);
|
||||
masters[2].arid = 6'b010_001;
|
||||
@@ -399,6 +587,44 @@ module axi4_data_crossbar_tb;
|
||||
return_target0_read(6'b000_101, 64'h0000_0000_0000_0280);
|
||||
end
|
||||
|
||||
invalid_return_prefix_recovery : begin
|
||||
for (int prefix = 9; prefix < 16; prefix++) begin
|
||||
return_invalid_target0_response(4'(prefix), prefix[0]);
|
||||
|
||||
if (prefix == 9) begin
|
||||
masters[8].arid = 7'h42;
|
||||
masters[8].araddr = 32'h3000_0140;
|
||||
masters[8].arvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[8].arready || idle_o) begin
|
||||
$fatal(1, "protocol recovery accepted a new request before flush");
|
||||
end
|
||||
masters[8].arvalid = 1'b0;
|
||||
end
|
||||
|
||||
flush_i = 1'b1;
|
||||
@(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
flush_i = 1'b0;
|
||||
end
|
||||
|
||||
masters[8].arid = 7'h42;
|
||||
masters[8].araddr = 32'h3000_0140;
|
||||
masters[8].arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!masters[8].arready);
|
||||
@(negedge clk_i);
|
||||
masters[8].arvalid = 1'b0;
|
||||
fork
|
||||
return_target0_read(7'h42, 64'h8888_8888_8888_0042);
|
||||
begin
|
||||
wait (masters[8].rvalid);
|
||||
if ((masters[8].rid != 7'h42) || (masters[8].rdata != 64'h8888_8888_8888_0042)) begin
|
||||
$fatal(1, "crossbar did not recover after protocol flush");
|
||||
end
|
||||
end
|
||||
join
|
||||
end
|
||||
|
||||
@(negedge clk_i);
|
||||
if (!idle_o || (outstanding_read_o != 8'd0) || (outstanding_write_o != 8'd0)) begin
|
||||
$fatal(1, "ACL and QoS transactions did not drain the crossbar");
|
||||
|
||||
@@ -9,7 +9,7 @@ module axi4_downsizer_64to32_tb;
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) wide (
|
||||
.aclk (clk_i),
|
||||
@@ -27,7 +27,9 @@ module axi4_downsizer_64to32_tb;
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
axi4_downsizer_64to32 u_dut (
|
||||
axi4_downsizer_64to32 #(
|
||||
.WideIdWidth(7)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.clear_i(1'b0),
|
||||
@@ -85,7 +87,7 @@ module axi4_downsizer_64to32_tb;
|
||||
endtask
|
||||
|
||||
task automatic accept_read(input logic [31:0] address, input logic [7:0] length,
|
||||
input logic [2:0] size, input logic [2:0] id,
|
||||
input logic [2:0] size, input logic [6:0] id,
|
||||
input logic [7:0] expected_length);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
@@ -110,7 +112,7 @@ module axi4_downsizer_64to32_tb;
|
||||
endtask
|
||||
|
||||
task automatic accept_write(input logic [31:0] address, input logic [7:0] length,
|
||||
input logic [2:0] size, input logic [2:0] id,
|
||||
input logic [2:0] size, input logic [6:0] id,
|
||||
input logic [7:0] expected_length);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
@@ -134,7 +136,7 @@ module axi4_downsizer_64to32_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_write_response(input logic [2:0] expected_id, input logic [1:0] response);
|
||||
task automatic return_write_response(input logic [6:0] expected_id, input logic [1:0] response);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
narrow.bresp = response;
|
||||
@@ -166,7 +168,7 @@ module axi4_downsizer_64to32_tb;
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
accept_read(32'h0000_0040, 8'd0, 3'd3, 3'd5, 8'd1);
|
||||
accept_read(32'h0000_0040, 8'd0, 3'd3, 7'h40, 8'd1);
|
||||
@(negedge clk_i);
|
||||
narrow.rdata = 32'h1122_3344;
|
||||
narrow.rresp = `AXI4_RESP_SLAVE_ERROR;
|
||||
@@ -181,7 +183,7 @@ module axi4_downsizer_64to32_tb;
|
||||
narrow.rresp = `AXI4_RESP_OKAY;
|
||||
narrow.rlast = 1'b1;
|
||||
#1;
|
||||
if (!wide.rvalid || narrow.rready || wide.rid != 3'd5 ||
|
||||
if (!wide.rvalid || narrow.rready || wide.rid != 7'h40 ||
|
||||
wide.rdata != 64'h5566_7788_1122_3344 || wide.rresp != `AXI4_RESP_SLAVE_ERROR ||
|
||||
!wide.rlast) begin
|
||||
$fatal(1, "64-bit read assembly or backpressure mismatch");
|
||||
@@ -194,7 +196,7 @@ module axi4_downsizer_64to32_tb;
|
||||
wide.rready = 1'b0;
|
||||
narrow.rvalid = 1'b0;
|
||||
|
||||
accept_read(32'h0000_0000, 8'd1, 3'd2, 3'd3, 8'd1);
|
||||
accept_read(32'h0000_0000, 8'd1, 3'd2, 7'h41, 8'd1);
|
||||
@(negedge clk_i);
|
||||
narrow.rdata = 32'hA5A5_0000;
|
||||
narrow.rresp = `AXI4_RESP_OKAY;
|
||||
@@ -202,7 +204,7 @@ module axi4_downsizer_64to32_tb;
|
||||
narrow.rvalid = 1'b1;
|
||||
wide.rready = 1'b1;
|
||||
#1;
|
||||
if (wide.rdata != 64'h0000_0000_A5A5_0000 || wide.rid != 3'd3) begin
|
||||
if (wide.rdata != 64'h0000_0000_A5A5_0000 || wide.rid != 7'h41) begin
|
||||
$fatal(1, "lower 32-bit read lane mismatch");
|
||||
end
|
||||
@(posedge clk_i);
|
||||
@@ -218,7 +220,7 @@ module axi4_downsizer_64to32_tb;
|
||||
wide.rready = 1'b0;
|
||||
narrow.rvalid = 1'b0;
|
||||
|
||||
accept_write(32'h0000_0080, 8'd0, 3'd3, 3'd6, 8'd1);
|
||||
accept_write(32'h0000_0080, 8'd0, 3'd3, 7'h42, 8'd1);
|
||||
@(negedge clk_i);
|
||||
wide.wdata = 64'h1122_3344_5566_7788;
|
||||
wide.wstrb = 8'hF3;
|
||||
@@ -240,9 +242,9 @@ module axi4_downsizer_64to32_tb;
|
||||
@(negedge clk_i);
|
||||
wide.wvalid = 1'b0;
|
||||
narrow.wready = 1'b0;
|
||||
return_write_response(3'd6, `AXI4_RESP_DECODE_ERROR);
|
||||
return_write_response(7'h42, `AXI4_RESP_DECODE_ERROR);
|
||||
|
||||
accept_write(32'h0000_0004, 8'd1, 3'd2, 3'd2, 8'd1);
|
||||
accept_write(32'h0000_0004, 8'd1, 3'd2, 7'h43, 8'd1);
|
||||
@(negedge clk_i);
|
||||
wide.wdata = 64'hCAFE_0000_DEAD_0000;
|
||||
wide.wstrb = 8'hF0;
|
||||
@@ -266,7 +268,7 @@ module axi4_downsizer_64to32_tb;
|
||||
@(negedge clk_i);
|
||||
wide.wvalid = 1'b0;
|
||||
narrow.wready = 1'b0;
|
||||
return_write_response(3'd2, `AXI4_RESP_OKAY);
|
||||
return_write_response(7'h43, `AXI4_RESP_OKAY);
|
||||
|
||||
$display("AXI4 64-to-32 downsizer test passed");
|
||||
$finish;
|
||||
|
||||
@@ -5,14 +5,16 @@ module axi4_target_guard_tb;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic abort_o;
|
||||
logic timeout_valid_o;
|
||||
logic timeout_ready_i = 1'b1;
|
||||
logic isolated_o;
|
||||
logic timeout_write_o;
|
||||
logic [ 5:0] timeout_id_o;
|
||||
logic [ 6:0] timeout_id_o;
|
||||
logic [31:0] timeout_addr_o;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) source (
|
||||
.aclk (clk_i),
|
||||
@@ -21,7 +23,7 @@ module axi4_target_guard_tb;
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) sink (
|
||||
.aclk (clk_i),
|
||||
@@ -31,6 +33,7 @@ module axi4_target_guard_tb;
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
axi4_target_guard #(
|
||||
.IdWidth (7),
|
||||
.ReadDepth (4),
|
||||
.WriteDepth(2)
|
||||
) u_dut (
|
||||
@@ -42,6 +45,8 @@ module axi4_target_guard_tb;
|
||||
.abort_o (abort_o),
|
||||
.abort_done_i (abort_o),
|
||||
.timeout_valid_o(timeout_valid_o),
|
||||
.timeout_ready_i(timeout_ready_i),
|
||||
.isolated_o (isolated_o),
|
||||
.timeout_write_o(timeout_write_o),
|
||||
.timeout_id_o (timeout_id_o),
|
||||
.timeout_addr_o (timeout_addr_o),
|
||||
@@ -49,7 +54,7 @@ module axi4_target_guard_tb;
|
||||
.sink (sink)
|
||||
);
|
||||
|
||||
task automatic issue_read(input logic [5:0] id, input logic [7:0] len, input logic [31:0] addr);
|
||||
task automatic issue_read(input logic [6:0] id, input logic [7:0] len, input logic [31:0] addr);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
source.arid = id;
|
||||
@@ -62,7 +67,19 @@ module axi4_target_guard_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_error_read(input logic [5:0] id, input int unsigned beats);
|
||||
task automatic issue_write_address(input logic [6:0] id, input logic [31:0] addr);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
source.awid = id;
|
||||
source.awaddr = addr;
|
||||
source.awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.awready);
|
||||
@(negedge clk_i);
|
||||
source.awvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_error_read(input logic [6:0] id, input int unsigned beats);
|
||||
begin
|
||||
for (int beat = 0; beat < beats; beat++) begin
|
||||
do @(posedge clk_i); while (!source.rvalid);
|
||||
@@ -74,7 +91,7 @@ module axi4_target_guard_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic return_read_beat(input logic [5:0] id, input logic last, input logic expected_last,
|
||||
task automatic return_read_beat(input logic [6:0] id, input logic last, input logic expected_last,
|
||||
input logic [1:0] expected_resp);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
@@ -146,26 +163,93 @@ module axi4_target_guard_tb;
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
issue_read(6'h07, 8'd1, 32'h3800_0020);
|
||||
issue_read(7'h40, 8'd1, 32'h3800_0020);
|
||||
do @(posedge clk_i); while (!sink.arvalid);
|
||||
return_read_beat(6'h07, 1'b0, 1'b0, 2'b00);
|
||||
return_read_beat(6'h07, 1'b0, 1'b1, 2'b10);
|
||||
return_read_beat(7'h40, 1'b0, 1'b0, 2'b00);
|
||||
return_read_beat(7'h40, 1'b0, 1'b1, 2'b10);
|
||||
|
||||
issue_read(6'h08, 8'd0, 32'h3800_0030);
|
||||
do @(posedge clk_i); while (!sink.arvalid);
|
||||
return_read_beat(6'h08, 1'b1, 1'b1, 2'b00);
|
||||
|
||||
issue_read(6'h09, 8'd1, 32'h3800_0040);
|
||||
timeout_ready_i = 1'b0;
|
||||
sink.arready = 1'b0;
|
||||
issue_read(7'h09, 8'd1, 32'h3800_0040);
|
||||
wait (timeout_valid_o);
|
||||
if (timeout_write_o || (timeout_id_o != 6'h09) || (timeout_addr_o != 32'h3800_0040)) begin
|
||||
if (timeout_write_o || (timeout_id_o != 7'h09) || (timeout_addr_o != 32'h3800_0040)) begin
|
||||
$fatal(1, "backpressured target-guard timeout attribution mismatch");
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!timeout_valid_o) begin
|
||||
$fatal(1, "target-guard timeout was not latched before sink recovery");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
sink.arready = 1'b1;
|
||||
repeat (3) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!timeout_valid_o || timeout_write_o || (timeout_id_o != 7'h09) ||
|
||||
(timeout_addr_o != 32'h3800_0040) || sink.arvalid || source.rvalid) begin
|
||||
$fatal(1, "backpressured target-guard timeout was not held safely");
|
||||
end
|
||||
end
|
||||
@(negedge clk_i);
|
||||
timeout_ready_i = 1'b1;
|
||||
expect_error_read(7'h09, 2);
|
||||
if (isolated_o) begin
|
||||
$fatal(1, "pre-accept timeout incorrectly isolated the target");
|
||||
end
|
||||
|
||||
timeout_ready_i = 1'b0;
|
||||
sink.awready = 1'b0;
|
||||
issue_write_address(7'h4C, 32'h3800_0060);
|
||||
wait (timeout_valid_o);
|
||||
if (!timeout_write_o || (timeout_id_o != 7'h4C) || (timeout_addr_o != 32'h3800_0060)) begin
|
||||
$fatal(1, "backpressured target-guard write timeout attribution mismatch");
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!timeout_valid_o) begin
|
||||
$fatal(1, "target-guard write timeout was not latched before sink recovery");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
sink.awready = 1'b1;
|
||||
repeat (3) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!timeout_valid_o || !timeout_write_o || (timeout_id_o != 7'h4C) ||
|
||||
(timeout_addr_o != 32'h3800_0060) || sink.awvalid || source.bvalid) begin
|
||||
$fatal(1, "backpressured target-guard write timeout was not held safely");
|
||||
end
|
||||
end
|
||||
@(negedge clk_i);
|
||||
timeout_ready_i = 1'b1;
|
||||
source.wdata = 64'h0123_4567_89AB_CDEF;
|
||||
source.wstrb = 8'hFF;
|
||||
source.wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.wready);
|
||||
@(negedge clk_i);
|
||||
source.wvalid = 1'b0;
|
||||
do @(posedge clk_i); while (!source.bvalid);
|
||||
if ((source.bid != 7'h4C) || (source.bresp != 2'b10) || sink.awvalid || sink.wvalid) begin
|
||||
$fatal(1, "backpressured target-guard write termination mismatch");
|
||||
end
|
||||
if (isolated_o) begin
|
||||
$fatal(1, "pre-accept write timeout incorrectly isolated the target");
|
||||
end
|
||||
|
||||
issue_read(7'h0A, 8'd1, 32'h3800_0080);
|
||||
wait (timeout_valid_o);
|
||||
if (timeout_write_o || (timeout_id_o != 7'h0A) || (timeout_addr_o != 32'h3800_0080)) begin
|
||||
$fatal(1, "target guard read timeout attribution mismatch");
|
||||
end
|
||||
expect_error_read(6'h09, 2);
|
||||
expect_error_read(7'h0A, 2);
|
||||
|
||||
fork
|
||||
begin
|
||||
issue_read(6'h0A, 8'd0, 32'h3800_0080);
|
||||
expect_error_read(6'h0A, 1);
|
||||
issue_read(7'h0B, 8'd0, 32'h3800_00C0);
|
||||
expect_error_read(7'h0B, 1);
|
||||
end
|
||||
begin
|
||||
repeat (12) begin
|
||||
@@ -176,7 +260,7 @@ module axi4_target_guard_tb;
|
||||
join
|
||||
|
||||
@(negedge clk_i);
|
||||
source.awid = 6'h0B;
|
||||
source.awid = 7'h4B;
|
||||
source.awaddr = 32'h3800_0100;
|
||||
source.awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.awready);
|
||||
@@ -189,7 +273,7 @@ module axi4_target_guard_tb;
|
||||
@(negedge clk_i);
|
||||
source.wvalid = 1'b0;
|
||||
do @(posedge clk_i); while (!source.bvalid);
|
||||
if ((source.bid != 6'h0B) || (source.bresp != 2'b10) || sink.awvalid || sink.wvalid) begin
|
||||
if ((source.bid != 7'h4B) || (source.bresp != 2'b10) || sink.awvalid || sink.wvalid) begin
|
||||
$fatal(1, "isolated target write termination mismatch");
|
||||
end
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
module fabric_monitor_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [ 7:0] master_read_accept_i = '0;
|
||||
logic [ 7:0] master_write_accept_i = '0;
|
||||
logic [ 7:0] master_read_beat_i = '0;
|
||||
logic [ 7:0] master_write_beat_i = '0;
|
||||
logic [ 7:0] master_wait_i = '0;
|
||||
logic [ 7:0] master_promotion_i = '0;
|
||||
logic [ 7:0][2:0] master_read_outstanding_i = '0;
|
||||
logic [ 7:0][2:0] master_write_outstanding_i = '0;
|
||||
logic [ 8:0] master_read_accept_i = '0;
|
||||
logic [ 8:0] master_write_accept_i = '0;
|
||||
logic [ 8:0] master_read_beat_i = '0;
|
||||
logic [ 8:0] master_write_beat_i = '0;
|
||||
logic [ 8:0] master_wait_i = '0;
|
||||
logic [ 8:0] master_promotion_i = '0;
|
||||
logic [ 8:0][2:0] master_read_outstanding_i = '0;
|
||||
logic [ 8:0][2:0] master_write_outstanding_i = '0;
|
||||
logic [ 5:0] target_read_accept_i = '0;
|
||||
logic [ 5:0] target_write_accept_i = '0;
|
||||
logic [ 5:0] target_read_beat_i = '0;
|
||||
@@ -40,7 +40,7 @@ module fabric_monitor_tb;
|
||||
.outstanding_read_i (8'd2),
|
||||
.outstanding_write_i (8'd1),
|
||||
.fault_valid_i (fault_valid_i),
|
||||
.fault_master_i (3'd5),
|
||||
.fault_master_i (4'd8),
|
||||
.fault_target_i (3'd2),
|
||||
.fault_addr_i (32'h4000_0040),
|
||||
.fault_write_i (1'b1),
|
||||
@@ -112,9 +112,14 @@ module fabric_monitor_tb;
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
apb_read(12'h004, read_data);
|
||||
if (read_data != 32'h0001_0001) $fatal(1, "fabric monitor version mismatch");
|
||||
apb_read(12'h008, read_data);
|
||||
if (read_data != 32'h0609_0003) $fatal(1, "fabric monitor capability mismatch");
|
||||
apb_write(12'h00C, 32'h0000_0001);
|
||||
@(negedge clk_i);
|
||||
master_read_accept_i[0] = 1'b1;
|
||||
master_read_accept_i[8] = 1'b1;
|
||||
master_read_beat_i[0] = 1'b1;
|
||||
master_promotion_i[0] = 1'b1;
|
||||
master_read_outstanding_i[0] = 3'd3;
|
||||
@@ -147,6 +152,8 @@ module fabric_monitor_tb;
|
||||
apb_write(12'h00C, 32'h0000_0009);
|
||||
apb_read(12'h100, read_data);
|
||||
if (read_data != 32'd1) $fatal(1, "master read request count mismatch");
|
||||
apb_read(12'h200, read_data);
|
||||
if (read_data != 32'd1) $fatal(1, "GA2D master bank request count mismatch");
|
||||
apb_read(12'h110, read_data);
|
||||
if (read_data != 32'd3) $fatal(1, "master wait count mismatch");
|
||||
apb_read(12'h114, read_data);
|
||||
@@ -168,7 +175,7 @@ module fabric_monitor_tb;
|
||||
apb_read(12'h018, read_data);
|
||||
if (read_data != 32'h4000_0040) $fatal(1, "fault address mismatch");
|
||||
apb_read(12'h014, read_data);
|
||||
if (read_data != 32'h0000_0557) $fatal(1, "sticky fault attribution mismatch");
|
||||
if (read_data != 32'h0000_1543) $fatal(1, "sticky fault attribution mismatch");
|
||||
apb_read(12'h020, read_data);
|
||||
if (read_data != 32'd1) $fatal(1, "fault count mismatch");
|
||||
|
||||
|
||||
@@ -0,0 +1,737 @@
|
||||
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// SPDX-License-Identifier: MulanPSL-2.0
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module ga2d_platform_idle_target (
|
||||
axi4_if.slave axi4
|
||||
);
|
||||
assign axi4.awready = 1'b1;
|
||||
assign axi4.wready = 1'b1;
|
||||
assign axi4.bid = '0;
|
||||
assign axi4.bresp = 2'b00;
|
||||
assign axi4.buser = '0;
|
||||
assign axi4.bvalid = 1'b0;
|
||||
assign axi4.arready = 1'b1;
|
||||
assign axi4.rid = '0;
|
||||
assign axi4.rdata = '0;
|
||||
assign axi4.rresp = 2'b00;
|
||||
assign axi4.rlast = 1'b1;
|
||||
assign axi4.ruser = '0;
|
||||
assign axi4.rvalid = 1'b0;
|
||||
endmodule
|
||||
|
||||
module ga2d_platform_sram_target (
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
input logic hold_ar_i,
|
||||
input logic hold_response_i,
|
||||
output logic [6:0] last_arid_o,
|
||||
output logic saw_ga2d_o,
|
||||
output logic saw_legacy_o,
|
||||
output logic saw_ga2d_write_o,
|
||||
axi4_if.slave axi4
|
||||
);
|
||||
logic read_pending_q;
|
||||
logic [6:0] read_id_q;
|
||||
logic read_valid_q;
|
||||
logic write_address_pending_q;
|
||||
logic write_data_pending_q;
|
||||
logic [6:0] write_id_q;
|
||||
logic write_valid_q;
|
||||
|
||||
assign axi4.awready = !write_address_pending_q && !write_valid_q;
|
||||
assign axi4.wready = write_address_pending_q && !write_data_pending_q && !write_valid_q;
|
||||
assign axi4.bid = write_id_q;
|
||||
assign axi4.bresp = 2'b00;
|
||||
assign axi4.buser = '0;
|
||||
assign axi4.bvalid = write_valid_q;
|
||||
assign axi4.arready = !hold_ar_i && !read_pending_q;
|
||||
assign axi4.rid = read_id_q;
|
||||
assign axi4.rdata = 64'hA5A5_0000_0000_0000 | read_id_q;
|
||||
assign axi4.rresp = 2'b00;
|
||||
assign axi4.rlast = 1'b1;
|
||||
assign axi4.ruser = '0;
|
||||
assign axi4.rvalid = read_valid_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
read_pending_q <= 1'b0;
|
||||
read_id_q <= '0;
|
||||
read_valid_q <= 1'b0;
|
||||
write_address_pending_q <= 1'b0;
|
||||
write_data_pending_q <= 1'b0;
|
||||
write_id_q <= '0;
|
||||
write_valid_q <= 1'b0;
|
||||
last_arid_o <= '0;
|
||||
saw_ga2d_o <= 1'b0;
|
||||
saw_legacy_o <= 1'b0;
|
||||
saw_ga2d_write_o <= 1'b0;
|
||||
end else begin
|
||||
if (axi4.awvalid && axi4.awready) begin
|
||||
write_address_pending_q <= 1'b1;
|
||||
write_id_q <= axi4.awid;
|
||||
if (axi4.awid == 7'h40) saw_ga2d_write_o <= 1'b1;
|
||||
end
|
||||
if (axi4.wvalid && axi4.wready) begin
|
||||
write_data_pending_q <= 1'b1;
|
||||
end
|
||||
if (write_address_pending_q && (write_data_pending_q || (axi4.wvalid && axi4.wready))) begin
|
||||
write_valid_q <= 1'b1;
|
||||
end
|
||||
if (write_valid_q && axi4.bready) begin
|
||||
write_address_pending_q <= 1'b0;
|
||||
write_data_pending_q <= 1'b0;
|
||||
write_valid_q <= 1'b0;
|
||||
end
|
||||
if (axi4.arvalid && axi4.arready) begin
|
||||
read_pending_q <= 1'b1;
|
||||
read_id_q <= axi4.arid;
|
||||
last_arid_o <= axi4.arid;
|
||||
if (axi4.arid == 7'h40) saw_ga2d_o <= 1'b1;
|
||||
if (axi4.arid == 7'h08) saw_legacy_o <= 1'b1;
|
||||
end
|
||||
if (read_pending_q && !hold_response_i) begin
|
||||
read_valid_q <= 1'b1;
|
||||
if (read_valid_q && axi4.rready) begin
|
||||
read_pending_q <= 1'b0;
|
||||
read_valid_q <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
module ga2d_platform_tb;
|
||||
logic clk_lp_i = 1'b0;
|
||||
logic clk_io_i = 1'b0;
|
||||
logic clk_hp_i = 1'b0;
|
||||
logic clk_mem_i = 1'b0;
|
||||
logic rst_lp_n_i = 1'b0;
|
||||
logic rst_io_n_i = 1'b0;
|
||||
logic rst_hp_n_i = 1'b0;
|
||||
logic rst_mem_n_i = 1'b0;
|
||||
logic block_new_i = 1'b0;
|
||||
logic recovery_i = 1'b0;
|
||||
logic flush_i = 1'b0;
|
||||
logic [ 8:0] resource_block_i = '0;
|
||||
logic [ 1:0] mem_pad_mode_i = 2'd1;
|
||||
logic ext_h_block_i = 1'b0;
|
||||
logic sram_hold_ar_i = 1'b0;
|
||||
logic sram_hold_response_i = 1'b0;
|
||||
logic [ 6:0] sram_last_arid;
|
||||
logic sram_saw_ga2d;
|
||||
logic sram_saw_legacy;
|
||||
logic sram_saw_ga2d_write;
|
||||
logic idle_o;
|
||||
logic flush_busy_o;
|
||||
logic ext_h_idle_o;
|
||||
logic [ 7:0] apu_bridge_epoch_o;
|
||||
logic ga2d_source_stop_o;
|
||||
logic ga2d_source_safe_idle_o;
|
||||
logic ga2d_bridge_clear_busy_o;
|
||||
logic [ 7:0] ga2d_bridge_epoch_o;
|
||||
logic ga2d_data_ready_o;
|
||||
logic [ 8:0] resource_idle_o;
|
||||
logic [ 8:0] resource_block_ack_o;
|
||||
logic [ 7:0] outstanding_read_o;
|
||||
logic [ 7:0] outstanding_write_o;
|
||||
logic fault_valid_o;
|
||||
logic [ 3:0] fault_master_o;
|
||||
logic [ 2:0] fault_target_o;
|
||||
logic [31:0] fault_addr_o;
|
||||
logic fault_write_o;
|
||||
logic [ 3:0] fault_reason_o;
|
||||
logic [ 7:0] epoch_before;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) hp_icache_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) hp_dcache_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) dma_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) sdio0_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) sdio1_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) spisd_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) usb2_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) apu_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) jpeg_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) ga2d_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) lp_data_axi4 (
|
||||
.aclk (clk_lp_i),
|
||||
.aresetn(rst_lp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (3),
|
||||
.USER_WIDTH(1)
|
||||
) ext_h_axi4 (
|
||||
.aclk (clk_io_i),
|
||||
.aresetn(rst_io_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) sram_gateway_axi4 (
|
||||
.aclk (clk_hp_i),
|
||||
.aresetn(rst_hp_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) sdram_gateway_axi4 (
|
||||
.aclk (clk_mem_i),
|
||||
.aresetn(rst_mem_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) qpi_gateway_axi4 (
|
||||
.aclk (clk_mem_i),
|
||||
.aresetn(rst_mem_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) opi_gateway_axi4 (
|
||||
.aclk (clk_mem_i),
|
||||
.aresetn(rst_mem_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) xpi_gateway_axi4 (
|
||||
.aclk (clk_mem_i),
|
||||
.aresetn(rst_mem_n_i)
|
||||
);
|
||||
apb4_if fabric_monitor_apb4 (
|
||||
.pclk (clk_hp_i),
|
||||
.presetn(rst_hp_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_lp_i = ~clk_lp_i;
|
||||
always #7 clk_io_i = ~clk_io_i;
|
||||
always #11 clk_hp_i = ~clk_hp_i;
|
||||
always #13 clk_mem_i = ~clk_mem_i;
|
||||
|
||||
axi4_master_idle u_hp_icache_idle (.axi4(hp_icache_axi4));
|
||||
axi4_master_idle u_dma_idle (.axi4(dma_axi4));
|
||||
axi4_master_idle u_sdio0_idle (.axi4(sdio0_axi4));
|
||||
axi4_master_idle u_sdio1_idle (.axi4(sdio1_axi4));
|
||||
axi4_master_idle u_spisd_idle (.axi4(spisd_axi4));
|
||||
axi4_master_idle u_usb2_idle (.axi4(usb2_axi4));
|
||||
axi4_master_idle u_apu_idle (.axi4(apu_axi4));
|
||||
axi4_master_idle u_jpeg_idle (.axi4(jpeg_axi4));
|
||||
axi4_master_idle u_lp_data_idle (.axi4(lp_data_axi4));
|
||||
axi4_master_idle u_ext_h_idle (.axi4(ext_h_axi4));
|
||||
ga2d_platform_sram_target u_sram_target (
|
||||
.clk_i (clk_hp_i),
|
||||
.rst_n_i (rst_hp_n_i),
|
||||
.hold_ar_i (sram_hold_ar_i),
|
||||
.hold_response_i (sram_hold_response_i),
|
||||
.last_arid_o (sram_last_arid),
|
||||
.saw_ga2d_o (sram_saw_ga2d),
|
||||
.saw_legacy_o (sram_saw_legacy),
|
||||
.saw_ga2d_write_o(sram_saw_ga2d_write),
|
||||
.axi4 (sram_gateway_axi4)
|
||||
);
|
||||
ga2d_platform_idle_target u_sdram_target (.axi4(sdram_gateway_axi4));
|
||||
ga2d_platform_idle_target u_qpi_target (.axi4(qpi_gateway_axi4));
|
||||
ga2d_platform_idle_target u_opi_target (.axi4(opi_gateway_axi4));
|
||||
ga2d_platform_idle_target u_xpi_target (.axi4(xpi_gateway_axi4));
|
||||
|
||||
soc_data_plane u_dut (
|
||||
.clk_lp_i (clk_lp_i),
|
||||
.rst_lp_n_i (rst_lp_n_i),
|
||||
.clk_io_i (clk_io_i),
|
||||
.rst_io_n_i (rst_io_n_i),
|
||||
.clk_hp_i (clk_hp_i),
|
||||
.rst_hp_n_i (rst_hp_n_i),
|
||||
.clk_mem_i (clk_mem_i),
|
||||
.rst_mem_n_i (rst_mem_n_i),
|
||||
.block_new_i (block_new_i),
|
||||
.recovery_i (recovery_i),
|
||||
.flush_i (flush_i),
|
||||
.resource_block_i (resource_block_i),
|
||||
.mem_pad_mode_i (mem_pad_mode_i),
|
||||
.ext_h_block_i (ext_h_block_i),
|
||||
.ext_h_read_base_i (32'h3000_0000),
|
||||
.ext_h_read_limit_i (32'h4FFF_FFFF),
|
||||
.ext_h_write_base_i (32'h3000_0000),
|
||||
.ext_h_write_limit_i (32'h4FFF_FFFF),
|
||||
.hp_icache_axi4 (hp_icache_axi4),
|
||||
.hp_dcache_axi4 (hp_dcache_axi4),
|
||||
.dma_axi4 (dma_axi4),
|
||||
.sdio0_axi4 (sdio0_axi4),
|
||||
.sdio1_axi4 (sdio1_axi4),
|
||||
.spisd_axi4 (spisd_axi4),
|
||||
.usb2_axi4 (usb2_axi4),
|
||||
.apu_axi4 (apu_axi4),
|
||||
.jpeg_axi4 (jpeg_axi4),
|
||||
.ga2d_axi4 (ga2d_axi4),
|
||||
.lp_data_axi4 (lp_data_axi4),
|
||||
.ext_h_axi4 (ext_h_axi4),
|
||||
.sram_gateway_axi4 (sram_gateway_axi4),
|
||||
.sdram_gateway_axi4 (sdram_gateway_axi4),
|
||||
.qpi_gateway_axi4 (qpi_gateway_axi4),
|
||||
.opi_gateway_axi4 (opi_gateway_axi4),
|
||||
.xpi_gateway_axi4 (xpi_gateway_axi4),
|
||||
.fabric_monitor_apb4 (fabric_monitor_apb4),
|
||||
.idle_o (idle_o),
|
||||
.flush_busy_o (flush_busy_o),
|
||||
.ext_h_idle_o (ext_h_idle_o),
|
||||
.apu_bridge_epoch_o (apu_bridge_epoch_o),
|
||||
.ga2d_source_stop_o (ga2d_source_stop_o),
|
||||
.ga2d_source_safe_idle_o (ga2d_source_safe_idle_o),
|
||||
.ga2d_bridge_clear_busy_o(ga2d_bridge_clear_busy_o),
|
||||
.ga2d_bridge_epoch_o (ga2d_bridge_epoch_o),
|
||||
.ga2d_data_ready_o (ga2d_data_ready_o),
|
||||
.resource_idle_o (resource_idle_o),
|
||||
.resource_block_ack_o (resource_block_ack_o),
|
||||
.outstanding_read_o (outstanding_read_o),
|
||||
.outstanding_write_o (outstanding_write_o),
|
||||
.fault_valid_o (fault_valid_o),
|
||||
.fault_ready_i (1'b1),
|
||||
.fault_master_o (fault_master_o),
|
||||
.fault_target_o (fault_target_o),
|
||||
.fault_addr_o (fault_addr_o),
|
||||
.fault_write_o (fault_write_o),
|
||||
.fault_reason_o (fault_reason_o)
|
||||
);
|
||||
|
||||
task automatic issue_ga2d_read(input logic [2:0] id, input logic [31:0] address);
|
||||
begin
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.arid = id;
|
||||
ga2d_axi4.araddr = address;
|
||||
ga2d_axi4.arlen = '0;
|
||||
ga2d_axi4.arsize = 3'd3;
|
||||
ga2d_axi4.arburst = 2'b01;
|
||||
ga2d_axi4.arlock = 1'b0;
|
||||
ga2d_axi4.arcache = '0;
|
||||
ga2d_axi4.arprot = '0;
|
||||
ga2d_axi4.arqos = 4'hF;
|
||||
ga2d_axi4.arregion = '0;
|
||||
ga2d_axi4.aruser = '0;
|
||||
ga2d_axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_io_i); while (!ga2d_axi4.arready);
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.arvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_ga2d_read(input logic [2:0] id);
|
||||
begin
|
||||
wait (ga2d_axi4.rvalid);
|
||||
if ((ga2d_axi4.rid != id) || (ga2d_axi4.rresp != 2'b00)) begin
|
||||
$fatal(1, "GA2D response did not preserve the local source ID");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic issue_ga2d_write(input logic [2:0] id, input logic [31:0] address,
|
||||
input logic [63:0] data);
|
||||
begin
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.awid = id;
|
||||
ga2d_axi4.awaddr = address;
|
||||
ga2d_axi4.awlen = '0;
|
||||
ga2d_axi4.awsize = 3'd3;
|
||||
ga2d_axi4.awburst = 2'b01;
|
||||
ga2d_axi4.awlock = 1'b0;
|
||||
ga2d_axi4.awcache = '0;
|
||||
ga2d_axi4.awprot = '0;
|
||||
ga2d_axi4.awqos = 4'hF;
|
||||
ga2d_axi4.awregion = '0;
|
||||
ga2d_axi4.awuser = '0;
|
||||
ga2d_axi4.awvalid = 1'b1;
|
||||
do @(posedge clk_io_i); while (!ga2d_axi4.awready);
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.awvalid = 1'b0;
|
||||
ga2d_axi4.wdata = data;
|
||||
ga2d_axi4.wstrb = '1;
|
||||
ga2d_axi4.wlast = 1'b1;
|
||||
ga2d_axi4.wuser = '0;
|
||||
ga2d_axi4.wvalid = 1'b1;
|
||||
do @(posedge clk_io_i); while (!ga2d_axi4.wready);
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.wvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_ga2d_write(input logic [2:0] id);
|
||||
begin
|
||||
wait (ga2d_axi4.bvalid);
|
||||
if ((ga2d_axi4.bid != id) || (ga2d_axi4.bresp != 2'b00)) begin
|
||||
$fatal(1, "GA2D write response did not preserve the local source ID");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic issue_legacy_read(input logic [2:0] id, input logic [31:0] address);
|
||||
begin
|
||||
@(negedge clk_hp_i);
|
||||
hp_dcache_axi4.arid = id;
|
||||
hp_dcache_axi4.araddr = address;
|
||||
hp_dcache_axi4.arlen = '0;
|
||||
hp_dcache_axi4.arsize = 3'd3;
|
||||
hp_dcache_axi4.arburst = 2'b01;
|
||||
hp_dcache_axi4.arlock = 1'b0;
|
||||
hp_dcache_axi4.arcache = '0;
|
||||
hp_dcache_axi4.arprot = '0;
|
||||
hp_dcache_axi4.arqos = '0;
|
||||
hp_dcache_axi4.arregion = '0;
|
||||
hp_dcache_axi4.aruser = '0;
|
||||
hp_dcache_axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_hp_i); while (!hp_dcache_axi4.arready);
|
||||
@(negedge clk_hp_i);
|
||||
hp_dcache_axi4.arvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_legacy_read(input logic [2:0] id);
|
||||
begin
|
||||
wait (hp_dcache_axi4.rvalid);
|
||||
if ((hp_dcache_axi4.rid != id) || (hp_dcache_axi4.rresp != 2'b00)) begin
|
||||
$fatal(1, "legacy response did not preserve its source ID");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic wait_for_data_ready;
|
||||
begin
|
||||
wait (ga2d_data_ready_o && !ga2d_source_stop_o);
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
ga2d_axi4.awid = '0;
|
||||
ga2d_axi4.awaddr = '0;
|
||||
ga2d_axi4.awlen = '0;
|
||||
ga2d_axi4.awsize = 3'd3;
|
||||
ga2d_axi4.awburst = 2'b01;
|
||||
ga2d_axi4.awlock = 1'b0;
|
||||
ga2d_axi4.awcache = '0;
|
||||
ga2d_axi4.awprot = '0;
|
||||
ga2d_axi4.awqos = '0;
|
||||
ga2d_axi4.awregion = '0;
|
||||
ga2d_axi4.awuser = '0;
|
||||
ga2d_axi4.awvalid = 1'b0;
|
||||
ga2d_axi4.wdata = '0;
|
||||
ga2d_axi4.wstrb = '0;
|
||||
ga2d_axi4.wlast = 1'b1;
|
||||
ga2d_axi4.wuser = '0;
|
||||
ga2d_axi4.wvalid = 1'b0;
|
||||
ga2d_axi4.bready = 1'b1;
|
||||
ga2d_axi4.arid = '0;
|
||||
ga2d_axi4.araddr = '0;
|
||||
ga2d_axi4.arlen = '0;
|
||||
ga2d_axi4.arsize = 3'd3;
|
||||
ga2d_axi4.arburst = 2'b01;
|
||||
ga2d_axi4.arlock = 1'b0;
|
||||
ga2d_axi4.arcache = '0;
|
||||
ga2d_axi4.arprot = '0;
|
||||
ga2d_axi4.arqos = '0;
|
||||
ga2d_axi4.arregion = '0;
|
||||
ga2d_axi4.aruser = '0;
|
||||
ga2d_axi4.arvalid = 1'b0;
|
||||
ga2d_axi4.rready = 1'b1;
|
||||
|
||||
hp_dcache_axi4.awid = '0;
|
||||
hp_dcache_axi4.awaddr = '0;
|
||||
hp_dcache_axi4.awlen = '0;
|
||||
hp_dcache_axi4.awsize = 3'd3;
|
||||
hp_dcache_axi4.awburst = 2'b01;
|
||||
hp_dcache_axi4.awlock = 1'b0;
|
||||
hp_dcache_axi4.awcache = '0;
|
||||
hp_dcache_axi4.awprot = '0;
|
||||
hp_dcache_axi4.awqos = '0;
|
||||
hp_dcache_axi4.awregion = '0;
|
||||
hp_dcache_axi4.awuser = '0;
|
||||
hp_dcache_axi4.awvalid = 1'b0;
|
||||
hp_dcache_axi4.wdata = '0;
|
||||
hp_dcache_axi4.wstrb = '0;
|
||||
hp_dcache_axi4.wlast = 1'b1;
|
||||
hp_dcache_axi4.wuser = '0;
|
||||
hp_dcache_axi4.wvalid = 1'b0;
|
||||
hp_dcache_axi4.bready = 1'b1;
|
||||
hp_dcache_axi4.arid = '0;
|
||||
hp_dcache_axi4.araddr = '0;
|
||||
hp_dcache_axi4.arlen = '0;
|
||||
hp_dcache_axi4.arsize = 3'd3;
|
||||
hp_dcache_axi4.arburst = 2'b01;
|
||||
hp_dcache_axi4.arlock = 1'b0;
|
||||
hp_dcache_axi4.arcache = '0;
|
||||
hp_dcache_axi4.arprot = '0;
|
||||
hp_dcache_axi4.arqos = '0;
|
||||
hp_dcache_axi4.arregion = '0;
|
||||
hp_dcache_axi4.aruser = '0;
|
||||
hp_dcache_axi4.arvalid = 1'b0;
|
||||
hp_dcache_axi4.rready = 1'b1;
|
||||
|
||||
fabric_monitor_apb4.paddr = '0;
|
||||
fabric_monitor_apb4.pprot = '0;
|
||||
fabric_monitor_apb4.psel = 1'b0;
|
||||
fabric_monitor_apb4.penable = 1'b0;
|
||||
fabric_monitor_apb4.pwrite = 1'b0;
|
||||
fabric_monitor_apb4.pwdata = '0;
|
||||
fabric_monitor_apb4.pstrb = '0;
|
||||
|
||||
repeat (3) @(posedge clk_io_i);
|
||||
rst_lp_n_i = 1'b1;
|
||||
rst_io_n_i = 1'b1;
|
||||
rst_hp_n_i = 1'b1;
|
||||
rst_mem_n_i = 1'b1;
|
||||
wait_for_data_ready();
|
||||
|
||||
fork
|
||||
issue_ga2d_read(3'd0, 32'h3000_0040);
|
||||
expect_ga2d_read(3'd0);
|
||||
issue_legacy_read(3'd0, 32'h3000_0080);
|
||||
expect_legacy_read(3'd0);
|
||||
join
|
||||
if (!sram_saw_ga2d || !sram_saw_legacy) begin
|
||||
$fatal(1, "mixed legacy and GA2D IDs did not reach distinct global IDs");
|
||||
end
|
||||
|
||||
fork
|
||||
issue_ga2d_write(3'd0, 32'h3000_00C0, 64'h0123_4567_89AB_CDEF);
|
||||
expect_ga2d_write(3'd0);
|
||||
join
|
||||
if (!sram_saw_ga2d_write) begin
|
||||
$fatal(1, "GA2D write did not preserve global ID 7'h40");
|
||||
end
|
||||
|
||||
wait (ga2d_source_safe_idle_o);
|
||||
@(negedge clk_io_i);
|
||||
resource_block_i[8] = 1'b1;
|
||||
ga2d_axi4.wdata = 64'hCAFE_BABE_0123_4567;
|
||||
ga2d_axi4.wstrb = '1;
|
||||
ga2d_axi4.wlast = 1'b1;
|
||||
ga2d_axi4.wuser = '0;
|
||||
ga2d_axi4.wvalid = 1'b1;
|
||||
repeat (2) @(posedge clk_io_i);
|
||||
#1;
|
||||
if (ga2d_source_stop_o || ga2d_source_safe_idle_o || resource_block_ack_o[8] ||
|
||||
ga2d_axi4.wready) begin
|
||||
$fatal(1, "resource block accepted or acknowledged W-before-AW traffic");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.awid = 3'd3;
|
||||
ga2d_axi4.awaddr = 32'h3000_0120;
|
||||
ga2d_axi4.awlen = '0;
|
||||
ga2d_axi4.awsize = 3'd3;
|
||||
ga2d_axi4.awburst = 2'b01;
|
||||
ga2d_axi4.awlock = 1'b0;
|
||||
ga2d_axi4.awcache = '0;
|
||||
ga2d_axi4.awprot = '0;
|
||||
ga2d_axi4.awqos = '0;
|
||||
ga2d_axi4.awregion = '0;
|
||||
ga2d_axi4.awuser = '0;
|
||||
ga2d_axi4.awvalid = 1'b1;
|
||||
do @(posedge clk_io_i); while (!ga2d_axi4.awready);
|
||||
#1;
|
||||
if (!ga2d_source_stop_o) begin
|
||||
$fatal(1, "resource block did not close after the W-before-AW address handshake");
|
||||
end
|
||||
if (!ga2d_axi4.wready) begin
|
||||
$fatal(1, "W-before-AW write data was not accepted with its address");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.awvalid = 1'b0;
|
||||
ga2d_axi4.wvalid = 1'b0;
|
||||
if (resource_block_ack_o[8]) begin
|
||||
$fatal(1, "resource block acknowledged before the W-before-AW response drained");
|
||||
end
|
||||
expect_ga2d_write(3'd3);
|
||||
wait (resource_block_ack_o[8]);
|
||||
if (!ga2d_source_safe_idle_o || !resource_idle_o[8] || ga2d_data_ready_o) begin
|
||||
$fatal(1, "W-before-AW resource stop did not reach qualified idle");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
resource_block_i[8] = 1'b0;
|
||||
wait_for_data_ready();
|
||||
|
||||
sram_hold_ar_i = 1'b1;
|
||||
@(negedge clk_io_i);
|
||||
resource_block_i[8] = 1'b1;
|
||||
ga2d_axi4.arid = 3'd1;
|
||||
ga2d_axi4.araddr = 32'h3000_0100;
|
||||
ga2d_axi4.arlen = '0;
|
||||
ga2d_axi4.arsize = 3'd3;
|
||||
ga2d_axi4.arburst = 2'b01;
|
||||
ga2d_axi4.arlock = 1'b0;
|
||||
ga2d_axi4.arcache = '0;
|
||||
ga2d_axi4.arprot = '0;
|
||||
ga2d_axi4.arqos = '0;
|
||||
ga2d_axi4.arregion = '0;
|
||||
ga2d_axi4.aruser = '0;
|
||||
ga2d_axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_io_i); while (!ga2d_axi4.arready);
|
||||
#1;
|
||||
if (!ga2d_source_stop_o) begin
|
||||
$fatal(1, "resource stop did not close after the presented address entered transport");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
ga2d_axi4.arvalid = 1'b0;
|
||||
wait (ga2d_source_stop_o);
|
||||
if (ga2d_source_safe_idle_o || resource_block_ack_o[8]) begin
|
||||
$fatal(1, "resource block acknowledged before the accepted read drained");
|
||||
end
|
||||
sram_hold_ar_i = 1'b0;
|
||||
fork
|
||||
expect_ga2d_read(3'd1);
|
||||
wait (resource_block_ack_o[8]);
|
||||
join
|
||||
if (!ga2d_source_safe_idle_o || !resource_idle_o[8] || ga2d_data_ready_o) begin
|
||||
$fatal(1, "GA2D resource stop did not reach qualified idle");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
resource_block_i[8] = 1'b0;
|
||||
wait_for_data_ready();
|
||||
|
||||
sram_hold_response_i = 1'b1;
|
||||
issue_ga2d_read(3'd2, 32'h3000_0140);
|
||||
wait (sram_last_arid == 7'h42);
|
||||
epoch_before = ga2d_bridge_epoch_o;
|
||||
@(negedge clk_hp_i);
|
||||
flush_i = 1'b1;
|
||||
repeat (4) @(posedge clk_io_i);
|
||||
if (ga2d_data_ready_o) begin
|
||||
$fatal(1, "GA2D data-ready remained asserted during a warm flush");
|
||||
end
|
||||
repeat (4) @(posedge clk_hp_i);
|
||||
@(negedge clk_hp_i);
|
||||
flush_i = 1'b0;
|
||||
wait (ga2d_bridge_epoch_o != epoch_before);
|
||||
repeat (4) @(posedge clk_io_i);
|
||||
if (ga2d_axi4.rvalid) begin
|
||||
$fatal(1, "late pre-flush response reached the GA2D source");
|
||||
end
|
||||
sram_hold_response_i = 1'b0;
|
||||
wait_for_data_ready();
|
||||
|
||||
epoch_before = ga2d_bridge_epoch_o;
|
||||
@(negedge clk_hp_i);
|
||||
rst_hp_n_i = 1'b0;
|
||||
repeat (3) @(posedge clk_hp_i);
|
||||
if (ga2d_data_ready_o) begin
|
||||
$fatal(1, "GA2D data-ready remained asserted while HP reset was active");
|
||||
end
|
||||
@(negedge clk_hp_i);
|
||||
rst_hp_n_i = 1'b1;
|
||||
wait (ga2d_bridge_epoch_o != epoch_before);
|
||||
wait_for_data_ready();
|
||||
|
||||
@(negedge clk_io_i);
|
||||
rst_io_n_i = 1'b0;
|
||||
repeat (3) @(posedge clk_io_i);
|
||||
if (ga2d_data_ready_o || !ga2d_source_stop_o) begin
|
||||
$fatal(1, "PCLK reset did not close the GA2D source path");
|
||||
end
|
||||
@(negedge clk_io_i);
|
||||
rst_io_n_i = 1'b1;
|
||||
wait_for_data_ready();
|
||||
|
||||
$display("GA2D P2 bridge, ID7, lifecycle, flush, and reset test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
#50000;
|
||||
$fatal(1, "GA2D platform test timed out");
|
||||
end
|
||||
endmodule
|
||||
@@ -14,7 +14,7 @@ module onchip_ram64_tb #(
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.ID_WIDTH (7),
|
||||
.USER_WIDTH(1)
|
||||
) mem_axi4 (
|
||||
.aclk (clk_i),
|
||||
@@ -31,7 +31,7 @@ module onchip_ram64_tb #(
|
||||
.Present (1'b1),
|
||||
.CapacityKiB(CapacityKiB),
|
||||
.DataWidth (64),
|
||||
.IdWidth (6)
|
||||
.IdWidth (7)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
@@ -41,7 +41,7 @@ module onchip_ram64_tb #(
|
||||
.cfg_apb4 (cfg_apb4)
|
||||
);
|
||||
|
||||
task automatic issue_write(input logic [5:0] id, input logic [31:0] address,
|
||||
task automatic issue_write(input logic [6:0] id, input logic [31:0] address,
|
||||
input logic [7:0] length, input logic [2:0] size,
|
||||
input logic [63:0] seed, input logic [7:0] strobe);
|
||||
begin
|
||||
@@ -74,7 +74,7 @@ module onchip_ram64_tb #(
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_read(input logic [5:0] id, input logic [31:0] address,
|
||||
task automatic expect_read(input logic [6:0] id, input logic [31:0] address,
|
||||
input logic [7:0] length, input logic [63:0] seed);
|
||||
integer previous_cycle;
|
||||
integer cycle_count;
|
||||
@@ -154,10 +154,10 @@ module onchip_ram64_tb #(
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
issue_write(6'h2A, SramBase + 32'h100, 8'd3, 3'd3, 64'h1000_2000_3000_4000, 8'hFF);
|
||||
expect_read(6'h2B, SramBase + 32'h100, 8'd3, 64'h1000_2000_3000_4000);
|
||||
issue_write(6'h2C, SramBase + 32'h10C, 8'd0, 3'd2, 64'hDEAD_BEEF_0000_0000, 8'hF0);
|
||||
expect_read(6'h2D, SramBase + 32'h108, 8'd0, 64'hDEAD_BEEF_3000_4001);
|
||||
issue_write(7'h40, SramBase + 32'h100, 8'd3, 3'd3, 64'h1000_2000_3000_4000, 8'hFF);
|
||||
expect_read(7'h41, SramBase + 32'h100, 8'd3, 64'h1000_2000_3000_4000);
|
||||
issue_write(7'h42, SramBase + 32'h10C, 8'd0, 3'd2, 64'hDEAD_BEEF_0000_0000, 8'hF0);
|
||||
expect_read(7'h43, SramBase + 32'h108, 8'd0, 64'hDEAD_BEEF_3000_4001);
|
||||
|
||||
$display("native AXI64 on-chip SRAM test passed");
|
||||
$finish;
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
module resource_controller_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [ 7:0] idle_i = '0;
|
||||
logic [ 7:0] block_ack_i = '0;
|
||||
logic [ 7:0] irq_i = '0;
|
||||
logic [ 8:0] idle_i = '0;
|
||||
logic [ 8:0] block_ack_i = '0;
|
||||
logic [ 8:0] irq_i = '0;
|
||||
logic cache_request_i = 1'b0;
|
||||
logic cache_clean_o;
|
||||
logic [ 7:0][1:0] owner_o;
|
||||
logic [ 7:0] owner_lock_o;
|
||||
logic [ 7:0] quiesce_o;
|
||||
logic [ 7:0] reset_o;
|
||||
logic [ 7:0] irq_lp_o;
|
||||
logic [ 7:0] irq_hp_o;
|
||||
logic [ 8:0][1:0] owner_o;
|
||||
logic [ 8:0] owner_lock_o;
|
||||
logic [ 8:0] quiesce_o;
|
||||
logic [ 8:0] reset_o;
|
||||
logic [ 8:0] irq_lp_o;
|
||||
logic [ 8:0] irq_hp_o;
|
||||
logic fault_irq_o;
|
||||
logic [31:0] read_data;
|
||||
|
||||
@@ -92,10 +92,14 @@ module resource_controller_tb;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
idle_i = 8'hFF;
|
||||
idle_i = 9'h1FF;
|
||||
|
||||
apb_read(12'h000, read_data);
|
||||
if (read_data != 32'h5253_4354) $fatal(1, "resource controller ID mismatch");
|
||||
apb_read(12'h004, read_data);
|
||||
if (read_data != 32'h0001_0001) $fatal(1, "resource controller version mismatch");
|
||||
apb_read(12'h008, read_data);
|
||||
if (read_data != 32'h0000_0901) $fatal(1, "resource controller capability mismatch");
|
||||
|
||||
irq_i[1] = 1'b1;
|
||||
#1;
|
||||
@@ -147,6 +151,17 @@ module resource_controller_tb;
|
||||
$fatal(1, "APU resource index 7 ownership or IRQ routing mismatch");
|
||||
end
|
||||
|
||||
apb_read(12'h200, read_data);
|
||||
if (read_data != 32'd0 || owner_o[8] != 2'd0 || owner_lock_o[8]) begin
|
||||
$fatal(1, "GA2D resource 8 did not reset to unlocked LP ownership");
|
||||
end
|
||||
apb_write(12'h204, 32'h0000_0001, 1'b0);
|
||||
block_ack_i[8] = 1'b1;
|
||||
apb_write(12'h200, 32'h0000_0001, 1'b0);
|
||||
if ((owner_o[8] != 2'd1) || irq_lp_o[8] || irq_hp_o[8]) begin
|
||||
$fatal(1, "GA2D resource 8 lifecycle or inactive IRQ mismatch");
|
||||
end
|
||||
|
||||
$display("Resource Controller ownership, IRQ, and cache handshake test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
+185
-27
@@ -3,10 +3,38 @@
|
||||
module sysctrl_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic fault_valid_i = 1'b0;
|
||||
logic [31:0] fault_addr_i = '0;
|
||||
logic [ 3:0] fault_wstrb_i = '0;
|
||||
logic fault_reserved_i = 1'b0;
|
||||
logic clk_hp_i = 1'b0;
|
||||
logic rst_hp_n_i = 1'b0;
|
||||
logic s_bus_fault_valid;
|
||||
logic [31:0] s_bus_fault_addr;
|
||||
logic [ 3:0] s_bus_fault_wstrb;
|
||||
logic s_bus_fault_reserved;
|
||||
logic s_bus_fault_access;
|
||||
logic [ 3:0] s_bus_fault_master;
|
||||
logic [ 2:0] s_bus_fault_code;
|
||||
logic s_data_plane_fault_valid_hp;
|
||||
logic [ 3:0] s_data_plane_fault_master_hp;
|
||||
logic [ 2:0] s_data_plane_fault_target_hp;
|
||||
logic [31:0] s_data_plane_fault_addr_hp;
|
||||
logic s_data_plane_fault_write_hp;
|
||||
logic [ 3:0] s_data_plane_fault_reason_hp;
|
||||
logic s_data_plane_fault_ready_hp;
|
||||
logic s_data_plane_fault_valid_pclk;
|
||||
logic [ 3:0] s_data_plane_fault_master_pclk;
|
||||
logic [ 2:0] s_data_plane_fault_target_pclk;
|
||||
logic [31:0] s_data_plane_fault_addr_pclk;
|
||||
logic s_data_plane_fault_write_pclk;
|
||||
logic [ 3:0] s_data_plane_fault_reason_pclk;
|
||||
logic [ 3:0] s_data_plane_fault_delivery_count;
|
||||
logic [ 3:0] s_data_plane_fault_delivery_master[0:2];
|
||||
logic [ 2:0] s_data_plane_fault_delivery_target[0:2];
|
||||
logic [31:0] s_data_plane_fault_delivery_addr [0:2];
|
||||
logic s_data_plane_fault_delivery_write [0:2];
|
||||
logic [ 3:0] s_data_plane_fault_delivery_reason[0:2];
|
||||
logic fault_valid_i;
|
||||
logic [31:0] fault_addr_i;
|
||||
logic [ 3:0] fault_wstrb_i;
|
||||
logic fault_reserved_i;
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
@@ -15,7 +43,60 @@ module sysctrl_tb;
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
clock_ctrl_if clock_ctrl ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
always #17 clk_i = ~clk_i;
|
||||
always #3 clk_hp_i = ~clk_hp_i;
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
s_data_plane_fault_delivery_count <= '0;
|
||||
end else if (s_data_plane_fault_valid_pclk) begin
|
||||
if (s_data_plane_fault_delivery_count < 4'd3) begin
|
||||
s_data_plane_fault_delivery_master[s_data_plane_fault_delivery_count] <=
|
||||
s_data_plane_fault_master_pclk;
|
||||
s_data_plane_fault_delivery_target[s_data_plane_fault_delivery_count] <=
|
||||
s_data_plane_fault_target_pclk;
|
||||
s_data_plane_fault_delivery_addr[s_data_plane_fault_delivery_count] <=
|
||||
s_data_plane_fault_addr_pclk;
|
||||
s_data_plane_fault_delivery_write[s_data_plane_fault_delivery_count] <=
|
||||
s_data_plane_fault_write_pclk;
|
||||
s_data_plane_fault_delivery_reason[s_data_plane_fault_delivery_count] <=
|
||||
s_data_plane_fault_reason_pclk;
|
||||
end
|
||||
s_data_plane_fault_delivery_count <= s_data_plane_fault_delivery_count + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
data_plane_fault_cdc u_data_plane_fault_cdc (
|
||||
.clk_hp_i (clk_hp_i),
|
||||
.rst_hp_n_i (rst_hp_n_i),
|
||||
.fault_valid_i (s_data_plane_fault_valid_hp),
|
||||
.fault_master_i(s_data_plane_fault_master_hp),
|
||||
.fault_target_i(s_data_plane_fault_target_hp),
|
||||
.fault_addr_i (s_data_plane_fault_addr_hp),
|
||||
.fault_write_i (s_data_plane_fault_write_hp),
|
||||
.fault_reason_i(s_data_plane_fault_reason_hp),
|
||||
.fault_ready_o (s_data_plane_fault_ready_hp),
|
||||
.clk_pclk_i (clk_i),
|
||||
.rst_pclk_n_i (rst_n_i),
|
||||
.fault_valid_o (s_data_plane_fault_valid_pclk),
|
||||
.fault_master_o(s_data_plane_fault_master_pclk),
|
||||
.fault_target_o(s_data_plane_fault_target_pclk),
|
||||
.fault_addr_o (s_data_plane_fault_addr_pclk),
|
||||
.fault_write_o (s_data_plane_fault_write_pclk),
|
||||
.fault_reason_o(s_data_plane_fault_reason_pclk)
|
||||
);
|
||||
|
||||
assign fault_valid_i = s_data_plane_fault_valid_pclk || s_bus_fault_valid;
|
||||
assign sysctrl.fault_access_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_write_pclk : s_bus_fault_access;
|
||||
assign sysctrl.fault_master_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_master_pclk : s_bus_fault_master;
|
||||
assign sysctrl.fault_code_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_reason_pclk[2:0] : s_bus_fault_code;
|
||||
assign fault_addr_i = s_data_plane_fault_valid_pclk ?
|
||||
s_data_plane_fault_addr_pclk : s_bus_fault_addr;
|
||||
assign fault_wstrb_i = s_data_plane_fault_valid_pclk && s_data_plane_fault_write_pclk ?
|
||||
4'hF : s_bus_fault_wstrb;
|
||||
assign fault_reserved_i = s_data_plane_fault_valid_pclk ? 1'b0 : s_bus_fault_reserved;
|
||||
|
||||
apb4_sysctrl u_sysctrl (
|
||||
.clk_i (clk_i),
|
||||
@@ -30,6 +111,31 @@ module sysctrl_tb;
|
||||
.clock_ctrl (clock_ctrl)
|
||||
);
|
||||
|
||||
task automatic send_data_plane_fault(input logic [3:0] master, input logic [2:0] target,
|
||||
input logic [31:0] address, input logic write_access,
|
||||
input logic [3:0] reason, input logic require_backpressure);
|
||||
logic saw_backpressure;
|
||||
begin
|
||||
saw_backpressure = 1'b0;
|
||||
@(negedge clk_hp_i);
|
||||
s_data_plane_fault_master_hp = master;
|
||||
s_data_plane_fault_target_hp = target;
|
||||
s_data_plane_fault_addr_hp = address;
|
||||
s_data_plane_fault_write_hp = write_access;
|
||||
s_data_plane_fault_reason_hp = reason;
|
||||
s_data_plane_fault_valid_hp = 1'b1;
|
||||
do begin
|
||||
@(posedge clk_hp_i);
|
||||
if (!s_data_plane_fault_ready_hp) saw_backpressure = 1'b1;
|
||||
end while (!s_data_plane_fault_ready_hp);
|
||||
if (require_backpressure && !saw_backpressure) begin
|
||||
$fatal(1, "slow PCLK did not backpressure the successive HP fault");
|
||||
end
|
||||
@(negedge clk_hp_i);
|
||||
s_data_plane_fault_valid_hp = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
@@ -102,9 +208,19 @@ module sysctrl_tb;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
sysctrl.user_bus_idle_i = 1'b1;
|
||||
sysctrl.fault_access_i = 1'b0;
|
||||
sysctrl.fault_master_i = '0;
|
||||
sysctrl.fault_code_i = `RIB_RESP_RESERVED;
|
||||
s_bus_fault_valid = 1'b0;
|
||||
s_bus_fault_addr = '0;
|
||||
s_bus_fault_wstrb = '0;
|
||||
s_bus_fault_reserved = 1'b0;
|
||||
s_bus_fault_access = 1'b0;
|
||||
s_bus_fault_master = '0;
|
||||
s_bus_fault_code = `RIB_RESP_RESERVED;
|
||||
s_data_plane_fault_valid_hp = 1'b0;
|
||||
s_data_plane_fault_master_hp = '0;
|
||||
s_data_plane_fault_target_hp = '0;
|
||||
s_data_plane_fault_addr_hp = '0;
|
||||
s_data_plane_fault_write_hp = 1'b0;
|
||||
s_data_plane_fault_reason_hp = '0;
|
||||
sysctrl.perf_mgmt_wait_i = 64'd11;
|
||||
sysctrl.perf_user_wait_i = 64'd12;
|
||||
sysctrl.perf_dma_wait_i = 64'd13;
|
||||
@@ -136,41 +252,58 @@ module sysctrl_tb;
|
||||
clock_ctrl.fault_i = '0;
|
||||
clock_ctrl.memory_i = 32'h0000_0005;
|
||||
repeat (2) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
rst_n_i = 1'b1;
|
||||
rst_hp_n_i = 1'b1;
|
||||
repeat (3) @(posedge clk_hp_i);
|
||||
|
||||
@(negedge clk_i);
|
||||
sysctrl.fault_master_i = 3'd3;
|
||||
fault_valid_i = 1'b1;
|
||||
fault_addr_i = 32'h1001_2000;
|
||||
fault_wstrb_i = 4'hF;
|
||||
fault_reserved_i = 1'b1;
|
||||
@(negedge clk_i);
|
||||
fault_valid_i = 1'b0;
|
||||
send_data_plane_fault(4'd8, 3'd5, 32'h1001_2000, 1'b1, {1'b0, `RIB_RESP_RESERVED}, 1'b0);
|
||||
send_data_plane_fault(4'd4, 3'd2, 32'h1001_2800, 1'b0, {1'b0, `RIB_RESP_DECERR}, 1'b1);
|
||||
send_data_plane_fault(4'd1, 3'd4, 32'h1001_2C00, 1'b1, {1'b0, `RIB_RESP_SLVERR}, 1'b1);
|
||||
wait (s_data_plane_fault_delivery_count == 4'd3);
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if ((s_data_plane_fault_delivery_master[0] != 4'd8) ||
|
||||
(s_data_plane_fault_delivery_target[0] != 3'd5) ||
|
||||
(s_data_plane_fault_delivery_addr[0] != 32'h1001_2000) ||
|
||||
!s_data_plane_fault_delivery_write[0] ||
|
||||
(s_data_plane_fault_delivery_reason[0] != {1'b0, `RIB_RESP_RESERVED}) ||
|
||||
(s_data_plane_fault_delivery_master[1] != 4'd4) ||
|
||||
(s_data_plane_fault_delivery_target[1] != 3'd2) ||
|
||||
(s_data_plane_fault_delivery_addr[1] != 32'h1001_2800) ||
|
||||
s_data_plane_fault_delivery_write[1] ||
|
||||
(s_data_plane_fault_delivery_reason[1] != {1'b0, `RIB_RESP_DECERR}) ||
|
||||
(s_data_plane_fault_delivery_master[2] != 4'd1) ||
|
||||
(s_data_plane_fault_delivery_target[2] != 3'd4) ||
|
||||
(s_data_plane_fault_delivery_addr[2] != 32'h1001_2C00) ||
|
||||
!s_data_plane_fault_delivery_write[2] ||
|
||||
(s_data_plane_fault_delivery_reason[2] != {1'b0, `RIB_RESP_SLVERR})) begin
|
||||
$fatal(1, "successive HP faults were not delivered exactly once and coherently");
|
||||
end
|
||||
|
||||
read_register(32'h1000_B010, read_data);
|
||||
if (read_data !== 32'h0000_000B) $fatal(1, "fault status was not recorded");
|
||||
read_register(32'h1000_B014, read_data);
|
||||
if (read_data !== 32'h1001_2000) $fatal(1, "fault address was not recorded");
|
||||
read_register(32'h1000_B018, read_data);
|
||||
if (read_data !== 32'h0000_0001) $fatal(1, "fault count was not incremented");
|
||||
if (read_data !== 32'h0000_0003) $fatal(1, "consecutive data-plane faults were lost");
|
||||
read_register(32'h1000_B028, read_data);
|
||||
if (read_data !== 32'h0000_0003) $fatal(1, "three-bit fault master was not recorded");
|
||||
if (read_data !== 32'h0000_0008) $fatal(1, "four-bit fault master was not recorded");
|
||||
read_register(32'h1000_B02C, read_data);
|
||||
if (read_data !== `RIB_RESP_RESERVED) $fatal(1, "fault detail was not recorded");
|
||||
|
||||
@(negedge clk_i);
|
||||
sysctrl.fault_master_i = 3'd4;
|
||||
sysctrl.fault_code_i = `RIB_RESP_DECERR;
|
||||
fault_valid_i = 1'b1;
|
||||
fault_addr_i = 32'hA000_0000;
|
||||
fault_wstrb_i = 4'h0;
|
||||
fault_reserved_i = 1'b0;
|
||||
s_bus_fault_master = 4'd4;
|
||||
s_bus_fault_code = `RIB_RESP_DECERR;
|
||||
s_bus_fault_valid = 1'b1;
|
||||
s_bus_fault_addr = 32'hA000_0000;
|
||||
s_bus_fault_wstrb = 4'h0;
|
||||
s_bus_fault_reserved = 1'b0;
|
||||
@(negedge clk_i);
|
||||
fault_valid_i = 1'b0;
|
||||
s_bus_fault_valid = 1'b0;
|
||||
read_register(32'h1000_B014, read_data);
|
||||
if (read_data !== 32'h1001_2000) $fatal(1, "later fault overwrote first fault address");
|
||||
read_register(32'h1000_B018, read_data);
|
||||
if (read_data !== 32'h0000_0002) $fatal(1, "later fault did not increment count");
|
||||
if (read_data !== 32'h0000_0004) $fatal(1, "later fault did not increment count");
|
||||
read_register(32'h1000_B02C, read_data);
|
||||
if (read_data !== `RIB_RESP_RESERVED) $fatal(1, "later fault overwrote first fault detail");
|
||||
|
||||
@@ -178,6 +311,31 @@ module sysctrl_tb;
|
||||
read_register(32'h1000_B010, read_data);
|
||||
if (read_data !== 32'h0000_000A) $fatal(1, "fault W1C did not clear pending");
|
||||
|
||||
send_data_plane_fault(4'd8, 3'd2, 32'h1001_3000, 1'b0, {1'b0, `RIB_RESP_RESERVED}, 1'b0);
|
||||
wait (s_data_plane_fault_valid_pclk);
|
||||
@(negedge clk_i);
|
||||
s_bus_fault_master = 4'd4;
|
||||
s_bus_fault_code = `RIB_RESP_DECERR;
|
||||
s_bus_fault_valid = 1'b1;
|
||||
s_bus_fault_addr = 32'hA000_1000;
|
||||
s_bus_fault_wstrb = 4'h0;
|
||||
s_bus_fault_reserved = 1'b0;
|
||||
@(negedge clk_i);
|
||||
s_bus_fault_valid = 1'b0;
|
||||
read_register(32'h1000_B014, read_data);
|
||||
if (read_data !== 32'h1001_3000) begin
|
||||
$fatal(1, "simultaneous local fault overrode the PCLK-visible data-plane fault");
|
||||
end
|
||||
read_register(32'h1000_B028, read_data);
|
||||
if (read_data !== 32'h0000_0008) begin
|
||||
$fatal(1, "fault arbitration lost the data-plane master high bit");
|
||||
end
|
||||
wait (s_data_plane_fault_delivery_count == 4'd4);
|
||||
read_register(32'h1000_B018, read_data);
|
||||
if (read_data !== 32'h0000_0005) begin
|
||||
$fatal(1, "simultaneous local fault was not deterministically suppressed");
|
||||
end
|
||||
|
||||
write_register(32'h1000_B040, 32'h0000_0005);
|
||||
read_register(32'h1000_B044, read_data);
|
||||
if (read_data !== 32'd11) $fatal(1, "performance snapshot was not recorded");
|
||||
|
||||
@@ -51,13 +51,30 @@ def test_clock_reset_domain_inventory_matches_the_rcu() -> None:
|
||||
("clint_timebase", "aon", "lp"),
|
||||
("jtag_dmi", "jtag", "lp"),
|
||||
("hp_mmio", "hp", "lp"),
|
||||
("data_plane_fault", "hp", "pclk"),
|
||||
("io_dma_data", "pclk", "hp"),
|
||||
("apu_data", "pclk", "hp"),
|
||||
("ga2d_data", "pclk", "hp"),
|
||||
("ga2d_source_idle", "pclk", "hp"),
|
||||
("ga2d_source_quiesced", "pclk", "hp"),
|
||||
("ga2d_hp_reset", "hp", "pclk"),
|
||||
("ga2d_flush", "hp", "pclk"),
|
||||
("ga2d_master_idle", "hp", "pclk"),
|
||||
("ga2d_block_ack", "hp", "pclk"),
|
||||
}
|
||||
clint = next(
|
||||
crossing for crossing in document["crossings"] if crossing["name"] == "clint_timebase"
|
||||
)
|
||||
assert clint["primitive"] == "edge_det"
|
||||
data_plane_fault = next(
|
||||
crossing for crossing in document["crossings"] if crossing["name"] == "data_plane_fault"
|
||||
)
|
||||
assert data_plane_fault["primitive"] == "async_reqack"
|
||||
assert data_plane_fault["instance"] == "u_fault_mailbox"
|
||||
assert data_plane_fault["unilateral_reset"] == {
|
||||
"source_reset": "abort_accepted_mailbox_item",
|
||||
"destination_reset": "abort_accepted_item_backpressure_unaccepted_source",
|
||||
}
|
||||
assert {
|
||||
"usb2_work",
|
||||
"usb2_result",
|
||||
@@ -125,3 +142,25 @@ def test_clock_reset_domain_inventory_rejects_invalid_sta_net_driver(tmp_path: P
|
||||
result = check(write_invalid_map(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert "sta.net must be a SystemVerilog identifier" in result.stderr
|
||||
|
||||
|
||||
def test_clock_reset_domain_inventory_requires_data_plane_fault_reset_contract(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
document = json.loads(DOMAIN_MAP.read_text(encoding="utf-8"))
|
||||
data_plane_fault = next(
|
||||
crossing for crossing in document["crossings"] if crossing["name"] == "data_plane_fault"
|
||||
)
|
||||
data_plane_fault.pop("unilateral_reset")
|
||||
result = check(write_invalid_map(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert "unilateral_reset must declare the data-plane fault reset contract" in result.stderr
|
||||
|
||||
document = json.loads(DOMAIN_MAP.read_text(encoding="utf-8"))
|
||||
data_plane_fault = next(
|
||||
crossing for crossing in document["crossings"] if crossing["name"] == "data_plane_fault"
|
||||
)
|
||||
data_plane_fault["instance"] = "u_other_mailbox"
|
||||
result = check(write_invalid_map(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert "must use async_reqack instance u_fault_mailbox" in result.stderr
|
||||
@@ -0,0 +1,143 @@
|
||||
"""Directed GA2D Phase 2 fabric and lifecycle verification."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def test_ga2d_p2_preserves_deferred_apb_irq_and_payload_boundaries() -> None:
|
||||
memory_map = json.loads(
|
||||
(ROOT / "rtl/mini/address_map/memory_map.json").read_text(encoding="utf-8")
|
||||
)
|
||||
regions = {region["symbol"]: region for region in memory_map["regions"]}
|
||||
topology = json.loads(
|
||||
(ROOT / "rtl/mini/integration/soc_topology.json").read_text(encoding="utf-8")
|
||||
)
|
||||
apb4_system = (ROOT / "rtl/mini/top/apb4_system.sv").read_text(encoding="utf-8")
|
||||
top = (ROOT / "rtl/mini/top/retrosoc.sv").read_text(encoding="utf-8")
|
||||
|
||||
assert regions["APB4_GA"] == {
|
||||
"symbol": "APB4_GA",
|
||||
"base": "0x10012000",
|
||||
"size": "0x00001000",
|
||||
"route": "reserved",
|
||||
"kind": "reserved",
|
||||
"public": False,
|
||||
"user_access": "none",
|
||||
}
|
||||
assert all("ga2d" not in interrupt["name"].lower() for interrupt in topology["interrupts"])
|
||||
assert not list((ROOT / "rtl/ip/multimedia").glob("ga2d_*.sv"))
|
||||
assert ".ResourceCount(9)" in apb4_system
|
||||
assert "1'b0, resource_irq_i[6:5], s_ext_h_irq_raw, resource_irq_i[4:0]" in apb4_system
|
||||
assert "resource_irq_lp_o = {s_resource_irq_lp[7:6], s_resource_irq_lp[4:0]}" in apb4_system
|
||||
assert "s_ga2d_source_safe_idle && s_resource_idle_pclk[8]" in top
|
||||
assert "s_ga2d_source_safe_idle && s_resource_block_ack_pclk[8]" in top
|
||||
|
||||
|
||||
def test_ga2d_p2_bridge_prefix_lifecycle_and_recovery(tmp_path: Path) -> None:
|
||||
verilator = shutil.which("verilator")
|
||||
if verilator is None:
|
||||
return
|
||||
|
||||
topology = tmp_path / "topology"
|
||||
memory_map = tmp_path / "memory_map"
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "rtl/mini/integration/generate_soc_topology.py"),
|
||||
"--map",
|
||||
str(ROOT / "rtl/mini/integration/soc_topology.json"),
|
||||
"--memory-map",
|
||||
str(ROOT / "rtl/mini/address_map/memory_map.json"),
|
||||
"--output-dir",
|
||||
str(topology),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
|
||||
"--map",
|
||||
str(ROOT / "rtl/mini/address_map/memory_map.json"),
|
||||
"--output-dir",
|
||||
str(memory_map),
|
||||
"--have-sram-if",
|
||||
"YES",
|
||||
"--sram-size-kib",
|
||||
"32",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
common = ROOT / "rtl/managed/clusterip/common/rtl"
|
||||
top = ROOT / "rtl/mini/top"
|
||||
output = tmp_path / "ga2d_platform_tb"
|
||||
ccache_tmp = tmp_path / "ccache"
|
||||
ccache_tmp.mkdir()
|
||||
subprocess.run(
|
||||
[
|
||||
verilator,
|
||||
"--binary",
|
||||
"--timing",
|
||||
"-Wno-fatal",
|
||||
"--top-module",
|
||||
"ga2d_platform_tb",
|
||||
"-I" + str(topology / "rtl"),
|
||||
"-I" + str(memory_map / "rtl"),
|
||||
"-I" + str(common),
|
||||
"-I" + str(common / "cdc"),
|
||||
"-I" + str(common / "interface"),
|
||||
str(common / "interface/apb4_if.sv"),
|
||||
str(common / "interface/axi4_if.sv"),
|
||||
str(common / "interface/axi4_addr_gen.sv"),
|
||||
str(common / "utils/register.sv"),
|
||||
str(common / "utils/fifo.sv"),
|
||||
str(common / "utils/xchecker.sv"),
|
||||
str(common / "utils/spill_register.sv"),
|
||||
str(common / "utils/bin2gray.sv"),
|
||||
str(common / "utils/gray2bin.sv"),
|
||||
str(common / "stream/round_robin_arbiter.sv"),
|
||||
str(common / "cdc/cdc_sync.sv"),
|
||||
str(common / "cdc/cdc_rst_ctrlr.sv"),
|
||||
str(common / "cdc/cdc_2phase.sv"),
|
||||
str(common / "clkrst/rst_sync.sv"),
|
||||
str(top / "soc_common_cdc.sv"),
|
||||
str(top / "axi4_connector.sv"),
|
||||
str(top / "axi4_master_idle.sv"),
|
||||
str(top / "axi4_async_bridge.sv"),
|
||||
str(top / "axi4_address_gate.sv"),
|
||||
str(top / "axi4_upsizer_32to64.sv"),
|
||||
str(top / "axi4_id_prefix.sv"),
|
||||
str(top / "axi4_data_crossbar.sv"),
|
||||
str(top / "axi4_target_guard.sv"),
|
||||
str(top / "fabric_monitor.sv"),
|
||||
str(top / "axi4_error_slave.sv"),
|
||||
str(top / "axi4_downsizer_64to32.sv"),
|
||||
str(top / "hp_axi4_mux3.sv"),
|
||||
str(top / "soc_data_plane.sv"),
|
||||
str(ROOT / "tests/rtl/ga2d_platform_tb.sv"),
|
||||
"-Mdir",
|
||||
str(tmp_path / "obj"),
|
||||
"-o",
|
||||
str(output),
|
||||
],
|
||||
check=True,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
env={
|
||||
**os.environ,
|
||||
"CCACHE_DIR": str(ccache_tmp),
|
||||
"CCACHE_TEMPDIR": str(ccache_tmp),
|
||||
},
|
||||
)
|
||||
result = subprocess.run([output], check=True, text=True, capture_output=True)
|
||||
assert "GA2D P2 bridge, ID7, lifecycle, flush, and reset test passed" in result.stdout
|
||||
@@ -194,6 +194,10 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
||||
assert "SOC_DATA_POLICY_WRITE_TARGET_MASK" in data_policy
|
||||
assert "SOC_DATA_POLICY_ALLOW_INSTRUCTION" in data_policy
|
||||
assert "SOC_DATA_POLICY_REQUIRE_NONCACHEABLE" in data_policy
|
||||
assert "`define SOC_DATA_POLICY_READ_TARGET_MASK 45'b111111111111111111111111111111111111111111111" in data_policy
|
||||
assert "`define SOC_DATA_POLICY_WRITE_TARGET_MASK 45'b011110111101111011110111101111011110111100000" in data_policy
|
||||
assert "`define SOC_DATA_POLICY_ALLOW_INSTRUCTION 9'b000000001" in data_policy
|
||||
assert "`define SOC_DATA_POLICY_REQUIRE_NONCACHEABLE 9'b111111100" in data_policy
|
||||
assert "RS_SOC_IRQ_VECTOR_WIDTH UINT32_C(64)" in irq_metadata
|
||||
assert "RS_SOC_EXTERNAL_IRQ_COUNT UINT32_C(62)" in irq_metadata
|
||||
assert "RS_SOC_IRQ_UART0 UINT32_C(2)" in irq_metadata
|
||||
@@ -252,6 +256,37 @@ def test_topology_preserves_default_irq_compatibility_mapping() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_ga2d_p2_topology_is_data_master_only() -> None:
|
||||
document = json.loads(TOPOLOGY.read_text(encoding="utf-8"))
|
||||
policies = document["data_master_policies"]
|
||||
|
||||
assert [policy["name"] for policy in policies] == [
|
||||
"hp_icache",
|
||||
"hp_dcache",
|
||||
"dma",
|
||||
"io_gateway_a",
|
||||
"io_gateway_b",
|
||||
"lp_gateway",
|
||||
"jpeg",
|
||||
"ext_h",
|
||||
"ga2d",
|
||||
]
|
||||
assert [policy["index"] for policy in policies] == list(range(9))
|
||||
assert policies[8] == {
|
||||
"index": 8,
|
||||
"name": "ga2d",
|
||||
"read_targets": ["sram", "sdram", "qpi", "opi", "xpi"],
|
||||
"write_targets": ["sram", "sdram", "qpi", "opi"],
|
||||
"allow_instruction": False,
|
||||
"require_noncacheable": True,
|
||||
}
|
||||
assert all(
|
||||
target["name"] != "ga2d"
|
||||
for target in document["apb4_periph_targets"] + document["apb4_system_targets"]
|
||||
)
|
||||
assert all("ga2d" not in interrupt["name"] for interrupt in document["interrupts"])
|
||||
|
||||
|
||||
def test_apu_p1_fixed_resource_and_hp_irq_allocations() -> None:
|
||||
periph = (ROOT / "rtl/mini/top/apb4_periph.sv").read_text(encoding="utf-8")
|
||||
system = (ROOT / "rtl/mini/top/apb4_system.sv").read_text(encoding="utf-8")
|
||||
@@ -262,12 +297,12 @@ def test_apu_p1_fixed_resource_and_hp_irq_allocations() -> None:
|
||||
|
||||
assert "s_hp_plic_source[10] = resource_irq_hp_i[6];" in periph
|
||||
assert "s_apu_irq_raw, s_jpeg_irq_raw" in periph
|
||||
assert ".ResourceCount(8)" in system
|
||||
assert ".ResourceCount(9)" in system
|
||||
assert ".apu_owner_i (s_resource_owner[7])" in top
|
||||
assert ".apu_quiesce_i (s_resource_quiesce[7])" in top
|
||||
assert ".apu_reset_i (s_resource_reset[7])" in top
|
||||
assert "RS_RESOURCE_APU = 7" in resource_header
|
||||
assert "RS_RESOURCE_COUNT = 8" in resource_header
|
||||
assert "RS_RESOURCE_COUNT = 9" in resource_header
|
||||
|
||||
|
||||
def test_topology_always_adds_the_user_apb_target(tmp_path: Path) -> None:
|
||||
@@ -419,6 +454,14 @@ def test_topology_rejects_invalid_irq_groups_and_bindings(tmp_path: Path) -> Non
|
||||
assert "core interrupt bit 0 must retain its compatibility binding" in result.stderr
|
||||
|
||||
|
||||
def test_topology_rejects_missing_ga2d_data_policy(tmp_path: Path) -> None:
|
||||
document = json.loads(TOPOLOGY.read_text(encoding="utf-8"))
|
||||
document["data_master_policies"].pop()
|
||||
result = validate(write_invalid_topology(tmp_path, document))
|
||||
assert result.returncode != 0
|
||||
assert "all 9 data masters" in result.stderr
|
||||
|
||||
|
||||
def test_generated_irq_wiring_preserves_the_expected_core_vector(tmp_path: Path) -> None:
|
||||
iverilog = shutil.which("iverilog")
|
||||
vvp = shutil.which("vvp")
|
||||
|
||||
@@ -10,6 +10,23 @@ from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PERIPHERAL = ROOT / "rtl/ip/peripheral"
|
||||
TOP = ROOT / "rtl/mini/top"
|
||||
|
||||
|
||||
def test_sysctrl_fault_master_keeps_the_data_plane_high_bit() -> None:
|
||||
interface = (PERIPHERAL / "sysctrl_if.sv").read_text(encoding="utf-8")
|
||||
core = (PERIPHERAL / "sysctrl_core.sv").read_text(encoding="utf-8")
|
||||
top = (TOP / "retrosoc.sv").read_text(encoding="utf-8")
|
||||
fault_cdc = (TOP / "data_plane_fault_cdc.sv").read_text(encoding="utf-8")
|
||||
|
||||
assert "logic [ 3:0] fault_master_i;" in interface
|
||||
assert "28'd0, s_fault_master_q" in core
|
||||
assert "{1'b0, s_bus_fault_master}" in top
|
||||
assert "data_plane_fault_cdc u_data_plane_fault_cdc" in top
|
||||
assert ".fault_ready_i (s_data_plane_fault_ready_hp)" in top
|
||||
assert "s_data_plane_fault_valid_pclk || s_bus_fault_valid" in top
|
||||
assert "async_reqack" in fault_cdc
|
||||
assert "fault_ready_o" in fault_cdc
|
||||
|
||||
|
||||
def test_sysctrl_registers_lifecycle_faults_and_wake(tmp_path: Path) -> None:
|
||||
@@ -59,6 +76,10 @@ def test_sysctrl_registers_lifecycle_faults_and_wake(tmp_path: Path) -> None:
|
||||
str(common / "interface/apb4_if.sv"),
|
||||
str(common / "utils/register.sv"),
|
||||
str(common / "cdc/cdc_sync.sv"),
|
||||
str(common / "clkrst/rst_sync.sv"),
|
||||
str(common / "cdc/cdc_rst_ctrlr.sv"),
|
||||
str(TOP / "soc_common_cdc.sv"),
|
||||
str(TOP / "data_plane_fault_cdc.sv"),
|
||||
str(PERIPHERAL / "pll_ctrl_if.sv"),
|
||||
str(PERIPHERAL / "clock_ctrl_if.sv"),
|
||||
str(PERIPHERAL / "sysctrl_if.sv"),
|
||||
|
||||
Reference in new issue
Block a user