mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: add APU-P1 support and enhance test coverage
- Introduced new task in for handling high-performance APU writes with access fault checks. - Updated to support an expanded resource count, including ownership and IRQ routing for the new APU resource. - Enhanced to validate IRQ expectations for the newly added APU resource. - Created for directed verification of APU-P1 APB4 register shell and integrated IRQ ownership topology. - Added to ensure synchronization between RTL and SDK register ABI. - Modified to parameterize tests for product modes, improving flexibility in testing. - Updated to reflect changes in APU memory mapping and ensure correct assertions. - Enhanced to validate the complete IRQ and resource allocations for the APU.
This commit is contained in:
41 files changed
+2385
-134
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
#include <archinfo_regs.h>
|
#include <archinfo_regs.h>
|
||||||
#include <retrosoc/core/archinfo.h>
|
#include <retrosoc/core/archinfo.h>
|
||||||
#include <retrosoc/core/soc.h>
|
#include <retrosoc/core/soc.h>
|
||||||
|
#include <retrosoc/hal/apu.h>
|
||||||
#include <retrosoc/hal/clint.h>
|
#include <retrosoc/hal/clint.h>
|
||||||
#include <retrosoc/hal/crypto.h>
|
#include <retrosoc/hal/crypto.h>
|
||||||
#include <retrosoc/hal/extension.h>
|
#include <retrosoc/hal/extension.h>
|
||||||
@@ -25,6 +26,14 @@ static bool rs_ci_smoke_archinfo_v2(void) {
|
|||||||
(rs_archinfo_read_device_id(device_id) == RS_ENOTSUP) && (rs_rtc_probe() == RS_OK);
|
(rs_archinfo_read_device_id(device_id) == RS_ENOTSUP) && (rs_rtc_probe() == RS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rs_ci_smoke_apu_p1(void) {
|
||||||
|
rs_apu_info_t info;
|
||||||
|
|
||||||
|
return (rs_apu_probe(&info) == RS_OK) && (info.capability0 == RS_APU_CAPABILITY0_IMPLEMENTED) &&
|
||||||
|
(info.capability1 == RS_APU_CAPABILITY1_IMPLEMENTED) &&
|
||||||
|
(info.abi_digest == RS_APU_DIGEST_IMPLEMENTED);
|
||||||
|
}
|
||||||
|
|
||||||
static bool rs_ci_smoke_onchip_sram(void) {
|
static bool rs_ci_smoke_onchip_sram(void) {
|
||||||
rs_onchip_sram_info_t info;
|
rs_onchip_sram_info_t info;
|
||||||
rs_onchip_sram_perf_t performance;
|
rs_onchip_sram_perf_t performance;
|
||||||
@@ -376,6 +385,10 @@ int main(void) {
|
|||||||
rs_test_finish(RS_TEST_FAILED, 1U);
|
rs_test_finish(RS_TEST_FAILED, 1U);
|
||||||
}
|
}
|
||||||
printf("ci_smoke: archinfo passed\n");
|
printf("ci_smoke: archinfo passed\n");
|
||||||
|
if (!rs_ci_smoke_apu_p1()) {
|
||||||
|
rs_test_finish(RS_TEST_FAILED, 14U);
|
||||||
|
}
|
||||||
|
printf("ci_smoke: APU-P1 discovery passed\n");
|
||||||
if (!rs_ci_smoke_fabric_monitor_start()) {
|
if (!rs_ci_smoke_fabric_monitor_start()) {
|
||||||
rs_test_finish(RS_TEST_FAILED, 13U);
|
rs_test_finish(RS_TEST_FAILED, 13U);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -53,10 +53,15 @@ See the [extension contract](../docs/ip/extensions.md) and
|
|||||||
[legacy user-IP contract](../docs/ip/user-ip.md).
|
[legacy user-IP contract](../docs/ip/user-ip.md).
|
||||||
|
|
||||||
`<retrosoc/hal/resource.h>` owns the central DMA, USB2, SDIO0/1, SPI-SD,
|
`<retrosoc/hal/resource.h>` owns the central DMA, USB2, SDIO0/1, SPI-SD,
|
||||||
EXT-H, and JPEG owner/lock, lifecycle-request, fault, and HP cache-maintenance
|
EXT-H, JPEG, and APU owner/lock, lifecycle-request, fault, and HP cache-maintenance
|
||||||
handshake.
|
handshake.
|
||||||
See the [Resource Controller contract](../docs/ip/resource-controller.md).
|
See the [Resource Controller contract](../docs/ip/resource-controller.md).
|
||||||
|
|
||||||
|
`<retrosoc/hal/apu.h>` provides APU-P1 identity, ABI version, capability, and
|
||||||
|
ABI-digest discovery. The current shell reports zero datapath capabilities;
|
||||||
|
job, DMA, stream, microcode, codec, and KWS APIs remain unavailable until their
|
||||||
|
frozen implementation phases.
|
||||||
|
|
||||||
`<retrosoc/hal/fabric_monitor.h>` owns root-management access to native AXI64
|
`<retrosoc/hal/fabric_monitor.h>` owns root-management access to native AXI64
|
||||||
master/target counters, stable snapshots, warm-flush counts, target isolation,
|
master/target counters, stable snapshots, warm-flush counts, target isolation,
|
||||||
and the sticky first-fault record. See the
|
and the sticky first-fault record. See the
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef RETROSOC_HAL_APU_H
|
||||||
|
#define RETROSOC_HAL_APU_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <retrosoc/core/status.h>
|
||||||
|
#include <retrosoc/hal/apu_regs.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t ip_id;
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t capability0;
|
||||||
|
uint32_t capability1;
|
||||||
|
uint32_t abi_digest;
|
||||||
|
} rs_apu_info_t;
|
||||||
|
|
||||||
|
rs_status_t rs_apu_probe(rs_apu_info_t *info);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
#ifndef RETROSOC_HAL_APU_REGS_H
|
||||||
|
#define RETROSOC_HAL_APU_REGS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <retrosoc/core/soc.h>
|
||||||
|
|
||||||
|
/* Independently handwritten mirror of rtl/ip/multimedia/apu_define.svh. */
|
||||||
|
#define RS_APU_ABI_IP_ID UINT32_C(0x000)
|
||||||
|
#define RS_APU_ABI_IP_VERSION UINT32_C(0x004)
|
||||||
|
#define RS_APU_ABI_CAPABILITY0 UINT32_C(0x008)
|
||||||
|
#define RS_APU_ABI_CAPABILITY1 UINT32_C(0x00C)
|
||||||
|
#define RS_APU_ABI_COMMAND UINT32_C(0x010)
|
||||||
|
#define RS_APU_ABI_STATUS UINT32_C(0x014)
|
||||||
|
#define RS_APU_ABI_IRQ_STATE UINT32_C(0x018)
|
||||||
|
#define RS_APU_ABI_IRQ_ENABLE UINT32_C(0x01C)
|
||||||
|
#define RS_APU_ABI_IRQ_TEST UINT32_C(0x020)
|
||||||
|
#define RS_APU_ABI_ERROR_STATUS UINT32_C(0x024)
|
||||||
|
#define RS_APU_ABI_ERROR_ADDRESS UINT32_C(0x028)
|
||||||
|
#define RS_APU_ABI_ERROR_DETAIL UINT32_C(0x02C)
|
||||||
|
#define RS_APU_ABI_SEQUENCER_TIMEOUT UINT32_C(0x030)
|
||||||
|
#define RS_APU_ABI_STREAM_ROUTE UINT32_C(0x034)
|
||||||
|
#define RS_APU_ABI_STREAM_STATUS UINT32_C(0x038)
|
||||||
|
#define RS_APU_ABI_OWNER_STATUS UINT32_C(0x03C)
|
||||||
|
#define RS_APU_ABI_READ_BASE UINT32_C(0x040)
|
||||||
|
#define RS_APU_ABI_READ_LIMIT UINT32_C(0x044)
|
||||||
|
#define RS_APU_ABI_WRITE_BASE UINT32_C(0x048)
|
||||||
|
#define RS_APU_ABI_WRITE_LIMIT UINT32_C(0x04C)
|
||||||
|
#define RS_APU_ABI_DMA_TIMEOUT UINT32_C(0x050)
|
||||||
|
#define RS_APU_ABI_ABI_DIGEST UINT32_C(0x054)
|
||||||
|
#define RS_APU_ABI_SEQUENCER_STATUS UINT32_C(0x058)
|
||||||
|
#define RS_APU_ABI_SEQUENCER_RETIRED UINT32_C(0x05C)
|
||||||
|
#define RS_APU_ABI_MC_IMAGE_ADDRESS UINT32_C(0x080)
|
||||||
|
#define RS_APU_ABI_MC_IMAGE_SIZE UINT32_C(0x084)
|
||||||
|
#define RS_APU_ABI_MC_EXPECTED_CRC UINT32_C(0x088)
|
||||||
|
#define RS_APU_ABI_MC_STATUS UINT32_C(0x08C)
|
||||||
|
#define RS_APU_ABI_MC_ABI UINT32_C(0x090)
|
||||||
|
#define RS_APU_ABI_MC_BUILD_ID_LO UINT32_C(0x094)
|
||||||
|
#define RS_APU_ABI_MC_BUILD_ID_HI UINT32_C(0x098)
|
||||||
|
#define RS_APU_ABI_MC_LOCK UINT32_C(0x09C)
|
||||||
|
#define RS_APU_ABI_MC_ACTUAL_CRC UINT32_C(0x0A0)
|
||||||
|
#define RS_APU_ABI_MC_LOAD_COUNT UINT32_C(0x0A4)
|
||||||
|
#define RS_APU_ABI_JOB_CONTROL UINT32_C(0x100)
|
||||||
|
#define RS_APU_ABI_JOB_INPUT_ADDRESS UINT32_C(0x104)
|
||||||
|
#define RS_APU_ABI_JOB_INPUT_LENGTH UINT32_C(0x108)
|
||||||
|
#define RS_APU_ABI_JOB_OUTPUT_ADDRESS UINT32_C(0x10C)
|
||||||
|
#define RS_APU_ABI_JOB_OUTPUT_CAPACITY UINT32_C(0x110)
|
||||||
|
#define RS_APU_ABI_JOB_INPUT_CONFIG UINT32_C(0x114)
|
||||||
|
#define RS_APU_ABI_JOB_OUTPUT_CONFIG UINT32_C(0x118)
|
||||||
|
#define RS_APU_ABI_JOB_FLAGS UINT32_C(0x11C)
|
||||||
|
#define RS_APU_ABI_JOB_STATUS UINT32_C(0x120)
|
||||||
|
#define RS_APU_ABI_JOB_INPUT_USED UINT32_C(0x124)
|
||||||
|
#define RS_APU_ABI_JOB_OUTPUT_BYTES UINT32_C(0x128)
|
||||||
|
#define RS_APU_ABI_JOB_FRAMES UINT32_C(0x12C)
|
||||||
|
#define RS_APU_ABI_JOB_SOURCE_INFO UINT32_C(0x130)
|
||||||
|
#define RS_APU_ABI_JOB_CYCLES UINT32_C(0x134)
|
||||||
|
#define RS_APU_ABI_JOB_DETAIL UINT32_C(0x138)
|
||||||
|
#define RS_APU_ABI_RING_BASE UINT32_C(0x180)
|
||||||
|
#define RS_APU_ABI_RING_SIZE UINT32_C(0x184)
|
||||||
|
#define RS_APU_ABI_RING_HEAD UINT32_C(0x188)
|
||||||
|
#define RS_APU_ABI_RING_TAIL UINT32_C(0x18C)
|
||||||
|
#define RS_APU_ABI_RING_CONTROL UINT32_C(0x190)
|
||||||
|
#define RS_APU_ABI_RING_STATUS UINT32_C(0x194)
|
||||||
|
#define RS_APU_ABI_RING_COMPLETED UINT32_C(0x198)
|
||||||
|
#define RS_APU_ABI_RING_COALESCE UINT32_C(0x19C)
|
||||||
|
#define RS_APU_ABI_RING_DOORBELL UINT32_C(0x1A0)
|
||||||
|
#define RS_APU_ABI_KWS_MODEL_ADDRESS UINT32_C(0x200)
|
||||||
|
#define RS_APU_ABI_KWS_MODEL_SIZE UINT32_C(0x204)
|
||||||
|
#define RS_APU_ABI_KWS_MODEL_EXPECTED_CRC UINT32_C(0x208)
|
||||||
|
#define RS_APU_ABI_KWS_CONTROL UINT32_C(0x20C)
|
||||||
|
#define RS_APU_ABI_KWS_CONFIG UINT32_C(0x210)
|
||||||
|
#define RS_APU_ABI_KWS_STATUS UINT32_C(0x214)
|
||||||
|
#define RS_APU_ABI_KWS_RESULT UINT32_C(0x218)
|
||||||
|
#define RS_APU_ABI_KWS_TIMESTAMP_LO UINT32_C(0x21C)
|
||||||
|
#define RS_APU_ABI_KWS_TIMESTAMP_HI UINT32_C(0x220)
|
||||||
|
#define RS_APU_ABI_KWS_FRAME_COUNT UINT32_C(0x224)
|
||||||
|
#define RS_APU_ABI_KWS_INFERENCE_COUNT UINT32_C(0x228)
|
||||||
|
#define RS_APU_ABI_KWS_HIT_COUNT UINT32_C(0x22C)
|
||||||
|
#define RS_APU_ABI_KWS_OVERRUN_COUNT UINT32_C(0x230)
|
||||||
|
#define RS_APU_ABI_KWS_MODEL_STATUS UINT32_C(0x234)
|
||||||
|
#define RS_APU_ABI_KWS_MODEL_ACTUAL_CRC UINT32_C(0x238)
|
||||||
|
#define RS_APU_ABI_PERF_CONTROL UINT32_C(0x300)
|
||||||
|
#define RS_APU_ABI_PERF_STATUS UINT32_C(0x304)
|
||||||
|
#define RS_APU_ABI_PERF_ACTIVE_CYCLES_LO UINT32_C(0x308)
|
||||||
|
#define RS_APU_ABI_PERF_ACTIVE_CYCLES_HI UINT32_C(0x30C)
|
||||||
|
#define RS_APU_ABI_PERF_INPUT_BYTES_LO UINT32_C(0x310)
|
||||||
|
#define RS_APU_ABI_PERF_INPUT_BYTES_HI UINT32_C(0x314)
|
||||||
|
#define RS_APU_ABI_PERF_OUTPUT_BYTES_LO UINT32_C(0x318)
|
||||||
|
#define RS_APU_ABI_PERF_OUTPUT_BYTES_HI UINT32_C(0x31C)
|
||||||
|
#define RS_APU_ABI_PERF_DECODED_FRAMES_LO UINT32_C(0x320)
|
||||||
|
#define RS_APU_ABI_PERF_DECODED_FRAMES_HI UINT32_C(0x324)
|
||||||
|
#define RS_APU_ABI_PERF_DMA_READ_STALLS_LO UINT32_C(0x328)
|
||||||
|
#define RS_APU_ABI_PERF_DMA_READ_STALLS_HI UINT32_C(0x32C)
|
||||||
|
#define RS_APU_ABI_PERF_DMA_WRITE_STALLS_LO UINT32_C(0x330)
|
||||||
|
#define RS_APU_ABI_PERF_DMA_WRITE_STALLS_HI UINT32_C(0x334)
|
||||||
|
#define RS_APU_ABI_PERF_STREAM_STALLS_LO UINT32_C(0x338)
|
||||||
|
#define RS_APU_ABI_PERF_STREAM_STALLS_HI UINT32_C(0x33C)
|
||||||
|
#define RS_APU_ABI_PERF_SEQUENCER_INSTR_LO UINT32_C(0x340)
|
||||||
|
#define RS_APU_ABI_PERF_SEQUENCER_INSTR_HI UINT32_C(0x344)
|
||||||
|
#define RS_APU_ABI_PERF_KWS_CYCLES_LO UINT32_C(0x348)
|
||||||
|
#define RS_APU_ABI_PERF_KWS_CYCLES_HI UINT32_C(0x34C)
|
||||||
|
#define RS_APU_ABI_PERF_FAULTS_LO UINT32_C(0x350)
|
||||||
|
#define RS_APU_ABI_PERF_FAULTS_HI UINT32_C(0x354)
|
||||||
|
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_WAV 0U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_MP3 1U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_FLAC 2U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_PRIVATE_DMA 3U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_RING 4U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_STREAMS 5U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_KWS 6U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_SEQUENCER 7U
|
||||||
|
#define RS_APU_ABI_CAPABILITY0_RESAMPLER 8U
|
||||||
|
#define RS_APU_ABI_CAPABILITY1_CONTROL_KIB 0U
|
||||||
|
#define RS_APU_ABI_CAPABILITY1_DATA_KIB 8U
|
||||||
|
#define RS_APU_ABI_CAPABILITY1_MAX_CHANNELS 16U
|
||||||
|
#define RS_APU_ABI_CAPABILITY1_MAX_RATE_KHZ 18U
|
||||||
|
#define RS_APU_ABI_COMMAND_START_DIRECT 0U
|
||||||
|
#define RS_APU_ABI_COMMAND_ABORT 1U
|
||||||
|
#define RS_APU_ABI_COMMAND_SOFT_RESET 2U
|
||||||
|
#define RS_APU_ABI_COMMAND_RING_KICK 3U
|
||||||
|
#define RS_APU_ABI_COMMAND_MICROCODE_LOAD 4U
|
||||||
|
#define RS_APU_ABI_COMMAND_MODEL_LOAD 5U
|
||||||
|
#define RS_APU_ABI_COMMAND_CLEAR_COUNTERS 6U
|
||||||
|
#define RS_APU_ABI_STATUS_MICROCODE_VALID 0U
|
||||||
|
#define RS_APU_ABI_STATUS_MODEL_VALID 1U
|
||||||
|
#define RS_APU_ABI_STATUS_BUSY 2U
|
||||||
|
#define RS_APU_ABI_STATUS_RING 3U
|
||||||
|
#define RS_APU_ABI_STATUS_DECODE 4U
|
||||||
|
#define RS_APU_ABI_STATUS_KWS_LISTENING 5U
|
||||||
|
#define RS_APU_ABI_STATUS_QUIESCED 6U
|
||||||
|
#define RS_APU_ABI_STATUS_ABORTING 7U
|
||||||
|
#define RS_APU_ABI_STATUS_IDLE 8U
|
||||||
|
#define RS_APU_ABI_STATUS_SEQUENCER_TRAPPED 9U
|
||||||
|
#define RS_APU_ABI_IRQ_DIRECT_DONE 0U
|
||||||
|
#define RS_APU_ABI_IRQ_RING_EVENT 1U
|
||||||
|
#define RS_APU_ABI_IRQ_KWS_HIT 2U
|
||||||
|
#define RS_APU_ABI_IRQ_MICROCODE_LOAD_DONE 3U
|
||||||
|
#define RS_APU_ABI_IRQ_MODEL_LOAD_DONE 4U
|
||||||
|
#define RS_APU_ABI_IRQ_ABORT_DONE 5U
|
||||||
|
#define RS_APU_ABI_IRQ_INPUT_WATERMARK 6U
|
||||||
|
#define RS_APU_ABI_IRQ_OUTPUT_WATERMARK 7U
|
||||||
|
#define RS_APU_ABI_IRQ_FIRST_ERROR 8U
|
||||||
|
#define RS_APU_ABI_IRQ_STREAM_XRUN 9U
|
||||||
|
#define RS_APU_ABI_IRQ_SEQUENCER_TRAP 10U
|
||||||
|
#define RS_APU_ABI_ERROR_VALID 0U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE 1U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE 7U
|
||||||
|
#define RS_APU_ABI_ERROR_AXI_RESPONSE 11U
|
||||||
|
#define RS_APU_ABI_ERROR_DESCRIPTOR_INDEX 13U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_NONE 0U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_INVALID_CONFIG 1U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_INVALID_RING 2U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_UNSUPPORTED 3U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_MALFORMED 4U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_TRUNCATED 5U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_CODEC_CRC 6U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_DECODE 7U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_RECONSTRUCTION 8U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_MICROCODE 9U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_MICROCODE_CRC 10U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_SEQUENCER 11U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_KWS_MODEL 12U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_KWS_CRC 13U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_KWS_ARITHMETIC 14U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_AXI_READ 15U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_AXI_WRITE 16U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_DMA_TIMEOUT 17U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_STREAM_UNDERRUN 18U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_STREAM_OVERRUN 19U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_ABORT 20U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_RESOURCE_RESET 21U
|
||||||
|
#define RS_APU_ABI_ERROR_CODE_OVERFLOW 22U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_APB 0U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_LOADER 1U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_RING 2U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_DMA_READ 3U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_BITSTREAM 4U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_ENTROPY 5U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_RECONSTRUCTION 6U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_RESAMPLER 7U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_DMA_WRITE 8U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_KWS_FRONTEND 9U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_KWS_INFERENCE 10U
|
||||||
|
#define RS_APU_ABI_ERROR_STAGE_LIFECYCLE 11U
|
||||||
|
#define RS_APU_ABI_OWNER_STATUS_OWNER 0U
|
||||||
|
#define RS_APU_ABI_OWNER_STATUS_LOCK 8U
|
||||||
|
#define RS_APU_ABI_OWNER_STATUS_QUIESCE 9U
|
||||||
|
#define RS_APU_ABI_OWNER_STATUS_RESET 10U
|
||||||
|
#define RS_APU_ABI_PERF_CONTROL_ENABLE 0U
|
||||||
|
#define RS_APU_ABI_PERF_CONTROL_CLEAR 1U
|
||||||
|
#define RS_APU_ABI_PERF_CONTROL_SNAPSHOT 2U
|
||||||
|
#define RS_APU_ABI_PERF_STATUS_SNAPSHOT_VALID 0U
|
||||||
|
|
||||||
|
#define RS_APU_IP_ID_VALUE UINT32_C(0x41505530)
|
||||||
|
#define RS_APU_IP_VERSION_VALUE UINT32_C(0x00010000)
|
||||||
|
#define RS_APU_IP_VERSION_MAJOR_MASK UINT32_C(0xFFFF0000)
|
||||||
|
#define RS_APU_CAPABILITY0_IMPLEMENTED UINT32_C(0x00000000)
|
||||||
|
#define RS_APU_CAPABILITY1_IMPLEMENTED UINT32_C(0x00000000)
|
||||||
|
#define RS_APU_DIGEST_IMPLEMENTED UINT32_C(0x00000000)
|
||||||
|
#define RS_APU_IRQ_ALL UINT32_C(0x000007FF)
|
||||||
|
|
||||||
|
#define RS_APU_REG_IP_ID RS_APU_ABI_IP_ID
|
||||||
|
#define RS_APU_REG_IP_VERSION RS_APU_ABI_IP_VERSION
|
||||||
|
#define RS_APU_REG_CAPABILITY0 RS_APU_ABI_CAPABILITY0
|
||||||
|
#define RS_APU_REG_CAPABILITY1 RS_APU_ABI_CAPABILITY1
|
||||||
|
#define RS_APU_REG_ABI_DIGEST RS_APU_ABI_ABI_DIGEST
|
||||||
|
#define RS_APU_REG(offset) RS_SOC_REG32(RS_SOC_APB4_APU_BASE, (offset))
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -14,7 +14,8 @@ typedef enum {
|
|||||||
RS_RESOURCE_SPISD = 4,
|
RS_RESOURCE_SPISD = 4,
|
||||||
RS_RESOURCE_EXT_H = 5,
|
RS_RESOURCE_EXT_H = 5,
|
||||||
RS_RESOURCE_JPEG = 6,
|
RS_RESOURCE_JPEG = 6,
|
||||||
RS_RESOURCE_COUNT = 7,
|
RS_RESOURCE_APU = 7,
|
||||||
|
RS_RESOURCE_COUNT = 8,
|
||||||
} rs_resource_t;
|
} rs_resource_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <retrosoc/hal/apu.h>
|
||||||
|
|
||||||
|
rs_status_t rs_apu_probe(rs_apu_info_t *info) {
|
||||||
|
if (info == NULL) {
|
||||||
|
return RS_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->ip_id = RS_APU_REG(RS_APU_REG_IP_ID);
|
||||||
|
info->version = RS_APU_REG(RS_APU_REG_IP_VERSION);
|
||||||
|
info->capability0 = RS_APU_REG(RS_APU_REG_CAPABILITY0);
|
||||||
|
info->capability1 = RS_APU_REG(RS_APU_REG_CAPABILITY1);
|
||||||
|
info->abi_digest = RS_APU_REG(RS_APU_REG_ABI_DIGEST);
|
||||||
|
|
||||||
|
if ((info->ip_id != RS_APU_IP_ID_VALUE) ||
|
||||||
|
((info->version & RS_APU_IP_VERSION_MAJOR_MASK) != RS_APU_IP_VERSION_VALUE)) {
|
||||||
|
return RS_ENOTSUP;
|
||||||
|
}
|
||||||
|
return RS_OK;
|
||||||
|
}
|
||||||
@@ -127,6 +127,8 @@ static void rs_print_mmio_map(void) {
|
|||||||
(void *)(uintptr_t)RS_SOC_APB4_HP_MAILBOX_BASE);
|
(void *)(uintptr_t)RS_SOC_APB4_HP_MAILBOX_BASE);
|
||||||
printf(" 1 x JPEG @%p\n",
|
printf(" 1 x JPEG @%p\n",
|
||||||
(void *)(uintptr_t)RS_SOC_APB4_JPEG_BASE);
|
(void *)(uintptr_t)RS_SOC_APB4_JPEG_BASE);
|
||||||
|
printf(" 1 x APU @%p\n",
|
||||||
|
(void *)(uintptr_t)RS_SOC_APB4_APU_BASE);
|
||||||
printf(" 1 x CLINT @%p\n",
|
printf(" 1 x CLINT @%p\n",
|
||||||
(void *)(uintptr_t)RS_SOC_APB4_CLINT_BASE);
|
(void *)(uintptr_t)RS_SOC_APB4_CLINT_BASE);
|
||||||
printf(" 1 x ARCHINFO @%p\n",
|
printf(" 1 x ARCHINFO @%p\n",
|
||||||
|
|||||||
+6
-4
@@ -26,10 +26,12 @@ The design was frozen on 2026-09-02 from these repository sources of truth:
|
|||||||
programmable-LUT, and lifecycle patterns; and
|
programmable-LUT, and lifecycle patterns; and
|
||||||
- `dependencies/dependencies.lock.json` for managed inputs.
|
- `dependencies/dependencies.lock.json` for managed inputs.
|
||||||
|
|
||||||
This specification defines a target, not an implemented feature. The current
|
APU-P1 implements the APB4 register shell, Resource Controller index 7,
|
||||||
executable address map keeps `APB4_APU` reserved and disabled. No claim is made
|
LP IRQ31/HP PLIC source10 ownership routing, and HAL discovery. The shell
|
||||||
that APU RTL, microcode, assembler, codec conformance, KWS model, Linux driver,
|
advertises zero datapath capabilities and rejects every deferred datapath
|
||||||
timing closure, power closure, CDC/RDC signoff, or silicon qualification exists.
|
command. No claim is made that APU DMA, streams, microcode, sequencer, codec
|
||||||
|
engines, KWS, codec conformance, Linux driver, timing closure, power closure,
|
||||||
|
CDC/RDC signoff, or silicon qualification exists.
|
||||||
|
|
||||||
## Commercial References
|
## Commercial References
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ APB4 peripherals. Their role in boot and lifecycle control is defined by
|
|||||||
|
|
||||||
## PLIC
|
## PLIC
|
||||||
|
|
||||||
Source 0 is permanently reserved. Source 1 is UART1 and source 2 is the
|
Source 0 is permanently reserved. Source 1 is UART1, source 2 is the HP-side
|
||||||
HP-side mailbox doorbell; sources 3 through 31 are reserved and tied low. Each
|
mailbox doorbell, source 3 is EXT-H, and sources 4 through 10 are central DMA,
|
||||||
source has a three-bit priority. Context 0 drives HP machine external interrupt
|
USB2, SDIO0, SDIO1, SPI-SD, JPEG, and APU respectively. Sources 11 through 31
|
||||||
and context 1 drives HP supervisor external interrupt.
|
are reserved and tied low. Resource-owned sources are suppressed unless HP is
|
||||||
|
the exclusive owner. Each source has a three-bit priority. Context 0 drives HP
|
||||||
|
machine external interrupt and context 1 drives HP supervisor external interrupt.
|
||||||
|
|
||||||
| Address offset | Register | Access |
|
| Address offset | Register | Access |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
The Resource Controller at `0x2000_A000` is the root-management ownership and
|
The Resource Controller at `0x2000_A000` is the root-management ownership and
|
||||||
interrupt-routing authority for central DMA, USB2, SDIO0, SDIO1, SPI-SD, and
|
interrupt-routing authority for central DMA, USB2, SDIO0, SDIO1, SPI-SD,
|
||||||
EXT-H. Hazard3 has read/write access; HP MMIO may inspect status but writes are
|
EXT-H, JPEG, and APU. Hazard3 has read/write access; HP MMIO may inspect status
|
||||||
rejected by the root-control firewall.
|
but writes are rejected by the root-control firewall.
|
||||||
It is handwritten RTL and has a matching handwritten
|
It is handwritten RTL and has a matching handwritten
|
||||||
`<retrosoc/hal/resource.h>` API; no register generator is used.
|
`<retrosoc/hal/resource.h>` API; no register generator is used.
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@ Resource indices are fixed:
|
|||||||
| 3 | SDIO1 | 7 |
|
| 3 | SDIO1 | 7 |
|
||||||
| 4 | SPI-SD | 8 |
|
| 4 | SPI-SD | 8 |
|
||||||
| 5 | EXT-H | 3 |
|
| 5 | EXT-H | 3 |
|
||||||
|
| 6 | JPEG | 9 |
|
||||||
|
| 7 | APU | 10 |
|
||||||
|
|
||||||
Owner `0` routes the resource interrupt to the existing LP vector. Owner `1`
|
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
|
removes it from LP and routes it to the listed HP PLIC source. Reset masks both
|
||||||
@@ -74,6 +76,7 @@ LP/HP IRQ routing are implemented and directed-tested. `CONTROL.QUIESCE`
|
|||||||
blocks the corresponding data-crossbar master and waits per-master outstanding
|
blocks the corresponding data-crossbar master and waits per-master outstanding
|
||||||
zero; shared I/O gateways are conservatively blocked as a pair. `CONTROL.RESET`
|
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
|
also blocks new data and masks IRQ but is not yet connected to every peripheral
|
||||||
engine's internal reset state machine. It must not be
|
engine's internal reset state machine. The APU-P1 shell is an exception: its
|
||||||
described as independent peripheral power isolation or reset containment until
|
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.
|
those downstream acknowledgements and fault-injection tests exist.
|
||||||
@@ -138,9 +138,10 @@ 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>`.
|
never both. Software discovers it through `<retrosoc/hal/extension.h>`.
|
||||||
|
|
||||||
The Resource Controller at `0x2000_A000` is the central owner and IRQ authority
|
The Resource Controller at `0x2000_A000` is the central owner and IRQ authority
|
||||||
for DMA, USB2, SDIO0/1, SPI-SD, and EXT-H. Handoff requires idle, owner lock is
|
for DMA, USB2, SDIO0/1, SPI-SD, EXT-H, JPEG, and APU. Handoff requires idle,
|
||||||
sticky, and rejected handoffs raise LP IRQ 29. It also carries the AON cache
|
owner lock is sticky, and rejected handoffs raise LP IRQ 29. APU index 7 routes
|
||||||
request/clean acknowledgement used before HP drain. See
|
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).
|
[`ip/resource-controller.md`](ip/resource-controller.md).
|
||||||
|
|
||||||
The root-only Fabric Monitor at `0x2000_B000` records per-master and
|
The root-only Fabric Monitor at `0x2000_B000` records per-master and
|
||||||
|
|||||||
+6
-7
@@ -119,13 +119,12 @@ ownership. Its implemented limits, handwritten ABI, measured performance, and
|
|||||||
commercial release gates are documented in
|
commercial release gates are documented in
|
||||||
[Baseline JPEG Codec](../docs/ip/jpeg.md).
|
[Baseline JPEG Codec](../docs/ip/jpeg.md).
|
||||||
|
|
||||||
The planned Mini Audio Processing Unit has a frozen coreless architecture at
|
The Mini Audio Processing Unit has a frozen coreless architecture. APU-P1
|
||||||
the reserved `APB4_APU` window. LP loads one bounded microcode bundle containing
|
implements its fail-closed APB4 shell at `APB4_APU`, Resource Controller index
|
||||||
WAV, MP3, and FLAC entry points; a hardware sequencer drives fixed bitstream,
|
7, and exclusive LP IRQ31/HP PLIC source10 routing. The shell advertises no
|
||||||
entropy, transform, reconstruction, resampler, DMA, and I2S stream engines.
|
datapath capabilities: private DMA, streams, microcode, codec engines, and KWS
|
||||||
Continuous KWS uses a separate fixed INT8 engine. The feature is not implemented
|
remain deferred to their frozen phases. The complete ABI, phase order, and
|
||||||
or enabled by the current topology; its ABI, phases, verification, and evidence
|
evidence gates are defined in [Mini Audio Processing Unit](../docs/ip/apu.md).
|
||||||
gates are defined in [Mini Audio Processing Unit](../docs/ip/apu.md).
|
|
||||||
|
|
||||||
SystemCtrl uses `sysctrl_if.sv`, `sysctrl_define.svh`, `sysctrl_reg.sv`, and
|
SystemCtrl uses `sysctrl_if.sv`, `sysctrl_define.svh`, `sysctrl_reg.sv`, and
|
||||||
`sysctrl_core.sv` behind the stable `apb4_sysctrl` integration wrapper. Its
|
`sysctrl_core.sv` behind the stable `apb4_sysctrl` integration wrapper. Its
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||||
|
// retroSoC is licensed under Mulan PSL v2.
|
||||||
|
|
||||||
|
module apb4_apu (
|
||||||
|
// verilog_format: off -- preserve the APB and lifecycle boundary columns
|
||||||
|
input logic clk_i,
|
||||||
|
input logic rst_n_i,
|
||||||
|
input logic [1:0] owner_i,
|
||||||
|
input logic owner_lock_i,
|
||||||
|
input logic quiesce_i,
|
||||||
|
input logic resource_reset_i,
|
||||||
|
apb4_if.slave apb4,
|
||||||
|
output logic idle_o,
|
||||||
|
output logic irq_o
|
||||||
|
// verilog_format: on
|
||||||
|
);
|
||||||
|
apu_reg u_apu_reg (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.owner_i (owner_i),
|
||||||
|
.owner_lock_i (owner_lock_i),
|
||||||
|
.quiesce_i (quiesce_i),
|
||||||
|
.resource_reset_i(resource_reset_i),
|
||||||
|
.apb4 (apb4),
|
||||||
|
.idle_o (idle_o),
|
||||||
|
.irq_o (irq_o)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||||
|
// retroSoC is licensed under Mulan PSL v2.
|
||||||
|
|
||||||
|
`ifndef RETROSOC_APU_DEFINE_SVH
|
||||||
|
`define RETROSOC_APU_DEFINE_SVH
|
||||||
|
|
||||||
|
// verilog_format: off -- keep the handwritten hardware/software ABI column aligned
|
||||||
|
`define APB4_APU__IP_ID 12'h000
|
||||||
|
`define APB4_APU__IP_VERSION 12'h004
|
||||||
|
`define APB4_APU__CAPABILITY0 12'h008
|
||||||
|
`define APB4_APU__CAPABILITY1 12'h00c
|
||||||
|
`define APB4_APU__COMMAND 12'h010
|
||||||
|
`define APB4_APU__STATUS 12'h014
|
||||||
|
`define APB4_APU__IRQ_STATE 12'h018
|
||||||
|
`define APB4_APU__IRQ_ENABLE 12'h01c
|
||||||
|
`define APB4_APU__IRQ_TEST 12'h020
|
||||||
|
`define APB4_APU__ERROR_STATUS 12'h024
|
||||||
|
`define APB4_APU__ERROR_ADDRESS 12'h028
|
||||||
|
`define APB4_APU__ERROR_DETAIL 12'h02c
|
||||||
|
`define APB4_APU__SEQUENCER_TIMEOUT 12'h030
|
||||||
|
`define APB4_APU__STREAM_ROUTE 12'h034
|
||||||
|
`define APB4_APU__STREAM_STATUS 12'h038
|
||||||
|
`define APB4_APU__OWNER_STATUS 12'h03c
|
||||||
|
`define APB4_APU__READ_BASE 12'h040
|
||||||
|
`define APB4_APU__READ_LIMIT 12'h044
|
||||||
|
`define APB4_APU__WRITE_BASE 12'h048
|
||||||
|
`define APB4_APU__WRITE_LIMIT 12'h04c
|
||||||
|
`define APB4_APU__DMA_TIMEOUT 12'h050
|
||||||
|
`define APB4_APU__ABI_DIGEST 12'h054
|
||||||
|
`define APB4_APU__SEQUENCER_STATUS 12'h058
|
||||||
|
`define APB4_APU__SEQUENCER_RETIRED 12'h05c
|
||||||
|
|
||||||
|
`define APB4_APU__MC_IMAGE_ADDRESS 12'h080
|
||||||
|
`define APB4_APU__MC_IMAGE_SIZE 12'h084
|
||||||
|
`define APB4_APU__MC_EXPECTED_CRC 12'h088
|
||||||
|
`define APB4_APU__MC_STATUS 12'h08c
|
||||||
|
`define APB4_APU__MC_ABI 12'h090
|
||||||
|
`define APB4_APU__MC_BUILD_ID_LO 12'h094
|
||||||
|
`define APB4_APU__MC_BUILD_ID_HI 12'h098
|
||||||
|
`define APB4_APU__MC_LOCK 12'h09c
|
||||||
|
`define APB4_APU__MC_ACTUAL_CRC 12'h0a0
|
||||||
|
`define APB4_APU__MC_LOAD_COUNT 12'h0a4
|
||||||
|
|
||||||
|
`define APB4_APU__JOB_CONTROL 12'h100
|
||||||
|
`define APB4_APU__JOB_INPUT_ADDRESS 12'h104
|
||||||
|
`define APB4_APU__JOB_INPUT_LENGTH 12'h108
|
||||||
|
`define APB4_APU__JOB_OUTPUT_ADDRESS 12'h10c
|
||||||
|
`define APB4_APU__JOB_OUTPUT_CAPACITY 12'h110
|
||||||
|
`define APB4_APU__JOB_INPUT_CONFIG 12'h114
|
||||||
|
`define APB4_APU__JOB_OUTPUT_CONFIG 12'h118
|
||||||
|
`define APB4_APU__JOB_FLAGS 12'h11c
|
||||||
|
`define APB4_APU__JOB_STATUS 12'h120
|
||||||
|
`define APB4_APU__JOB_INPUT_USED 12'h124
|
||||||
|
`define APB4_APU__JOB_OUTPUT_BYTES 12'h128
|
||||||
|
`define APB4_APU__JOB_FRAMES 12'h12c
|
||||||
|
`define APB4_APU__JOB_SOURCE_INFO 12'h130
|
||||||
|
`define APB4_APU__JOB_CYCLES 12'h134
|
||||||
|
`define APB4_APU__JOB_DETAIL 12'h138
|
||||||
|
|
||||||
|
`define APB4_APU__RING_BASE 12'h180
|
||||||
|
`define APB4_APU__RING_SIZE 12'h184
|
||||||
|
`define APB4_APU__RING_HEAD 12'h188
|
||||||
|
`define APB4_APU__RING_TAIL 12'h18c
|
||||||
|
`define APB4_APU__RING_CONTROL 12'h190
|
||||||
|
`define APB4_APU__RING_STATUS 12'h194
|
||||||
|
`define APB4_APU__RING_COMPLETED 12'h198
|
||||||
|
`define APB4_APU__RING_COALESCE 12'h19c
|
||||||
|
`define APB4_APU__RING_DOORBELL 12'h1a0
|
||||||
|
|
||||||
|
`define APB4_APU__KWS_MODEL_ADDRESS 12'h200
|
||||||
|
`define APB4_APU__KWS_MODEL_SIZE 12'h204
|
||||||
|
`define APB4_APU__KWS_MODEL_EXPECTED_CRC 12'h208
|
||||||
|
`define APB4_APU__KWS_CONTROL 12'h20c
|
||||||
|
`define APB4_APU__KWS_CONFIG 12'h210
|
||||||
|
`define APB4_APU__KWS_STATUS 12'h214
|
||||||
|
`define APB4_APU__KWS_RESULT 12'h218
|
||||||
|
`define APB4_APU__KWS_TIMESTAMP_LO 12'h21c
|
||||||
|
`define APB4_APU__KWS_TIMESTAMP_HI 12'h220
|
||||||
|
`define APB4_APU__KWS_FRAME_COUNT 12'h224
|
||||||
|
`define APB4_APU__KWS_INFERENCE_COUNT 12'h228
|
||||||
|
`define APB4_APU__KWS_HIT_COUNT 12'h22c
|
||||||
|
`define APB4_APU__KWS_OVERRUN_COUNT 12'h230
|
||||||
|
`define APB4_APU__KWS_MODEL_STATUS 12'h234
|
||||||
|
`define APB4_APU__KWS_MODEL_ACTUAL_CRC 12'h238
|
||||||
|
|
||||||
|
`define APB4_APU__PERF_CONTROL 12'h300
|
||||||
|
`define APB4_APU__PERF_STATUS 12'h304
|
||||||
|
`define APB4_APU__PERF_ACTIVE_CYCLES_LO 12'h308
|
||||||
|
`define APB4_APU__PERF_ACTIVE_CYCLES_HI 12'h30c
|
||||||
|
`define APB4_APU__PERF_INPUT_BYTES_LO 12'h310
|
||||||
|
`define APB4_APU__PERF_INPUT_BYTES_HI 12'h314
|
||||||
|
`define APB4_APU__PERF_OUTPUT_BYTES_LO 12'h318
|
||||||
|
`define APB4_APU__PERF_OUTPUT_BYTES_HI 12'h31c
|
||||||
|
`define APB4_APU__PERF_DECODED_FRAMES_LO 12'h320
|
||||||
|
`define APB4_APU__PERF_DECODED_FRAMES_HI 12'h324
|
||||||
|
`define APB4_APU__PERF_DMA_READ_STALLS_LO 12'h328
|
||||||
|
`define APB4_APU__PERF_DMA_READ_STALLS_HI 12'h32c
|
||||||
|
`define APB4_APU__PERF_DMA_WRITE_STALLS_LO 12'h330
|
||||||
|
`define APB4_APU__PERF_DMA_WRITE_STALLS_HI 12'h334
|
||||||
|
`define APB4_APU__PERF_STREAM_STALLS_LO 12'h338
|
||||||
|
`define APB4_APU__PERF_STREAM_STALLS_HI 12'h33c
|
||||||
|
`define APB4_APU__PERF_SEQUENCER_INSTR_LO 12'h340
|
||||||
|
`define APB4_APU__PERF_SEQUENCER_INSTR_HI 12'h344
|
||||||
|
`define APB4_APU__PERF_KWS_CYCLES_LO 12'h348
|
||||||
|
`define APB4_APU__PERF_KWS_CYCLES_HI 12'h34c
|
||||||
|
`define APB4_APU__PERF_FAULTS_LO 12'h350
|
||||||
|
`define APB4_APU__PERF_FAULTS_HI 12'h354
|
||||||
|
|
||||||
|
`define APB4_APU__CAPABILITY0_WAV 0
|
||||||
|
`define APB4_APU__CAPABILITY0_MP3 1
|
||||||
|
`define APB4_APU__CAPABILITY0_FLAC 2
|
||||||
|
`define APB4_APU__CAPABILITY0_PRIVATE_DMA 3
|
||||||
|
`define APB4_APU__CAPABILITY0_RING 4
|
||||||
|
`define APB4_APU__CAPABILITY0_STREAMS 5
|
||||||
|
`define APB4_APU__CAPABILITY0_KWS 6
|
||||||
|
`define APB4_APU__CAPABILITY0_SEQUENCER 7
|
||||||
|
`define APB4_APU__CAPABILITY0_RESAMPLER 8
|
||||||
|
`define APB4_APU__CAPABILITY1_CONTROL_KIB 0
|
||||||
|
`define APB4_APU__CAPABILITY1_DATA_KIB 8
|
||||||
|
`define APB4_APU__CAPABILITY1_MAX_CHANNELS 16
|
||||||
|
`define APB4_APU__CAPABILITY1_MAX_RATE_KHZ 18
|
||||||
|
|
||||||
|
`define APB4_APU__COMMAND_START_DIRECT 0
|
||||||
|
`define APB4_APU__COMMAND_ABORT 1
|
||||||
|
`define APB4_APU__COMMAND_SOFT_RESET 2
|
||||||
|
`define APB4_APU__COMMAND_RING_KICK 3
|
||||||
|
`define APB4_APU__COMMAND_MICROCODE_LOAD 4
|
||||||
|
`define APB4_APU__COMMAND_MODEL_LOAD 5
|
||||||
|
`define APB4_APU__COMMAND_CLEAR_COUNTERS 6
|
||||||
|
|
||||||
|
`define APB4_APU__STATUS_MICROCODE_VALID 0
|
||||||
|
`define APB4_APU__STATUS_MODEL_VALID 1
|
||||||
|
`define APB4_APU__STATUS_BUSY 2
|
||||||
|
`define APB4_APU__STATUS_RING 3
|
||||||
|
`define APB4_APU__STATUS_DECODE 4
|
||||||
|
`define APB4_APU__STATUS_KWS_LISTENING 5
|
||||||
|
`define APB4_APU__STATUS_QUIESCED 6
|
||||||
|
`define APB4_APU__STATUS_ABORTING 7
|
||||||
|
`define APB4_APU__STATUS_IDLE 8
|
||||||
|
`define APB4_APU__STATUS_SEQUENCER_TRAPPED 9
|
||||||
|
|
||||||
|
`define APB4_APU__IRQ_DIRECT_DONE 0
|
||||||
|
`define APB4_APU__IRQ_RING_EVENT 1
|
||||||
|
`define APB4_APU__IRQ_KWS_HIT 2
|
||||||
|
`define APB4_APU__IRQ_MICROCODE_LOAD_DONE 3
|
||||||
|
`define APB4_APU__IRQ_MODEL_LOAD_DONE 4
|
||||||
|
`define APB4_APU__IRQ_ABORT_DONE 5
|
||||||
|
`define APB4_APU__IRQ_INPUT_WATERMARK 6
|
||||||
|
`define APB4_APU__IRQ_OUTPUT_WATERMARK 7
|
||||||
|
`define APB4_APU__IRQ_FIRST_ERROR 8
|
||||||
|
`define APB4_APU__IRQ_STREAM_XRUN 9
|
||||||
|
`define APB4_APU__IRQ_SEQUENCER_TRAP 10
|
||||||
|
|
||||||
|
`define APB4_APU__ERROR_VALID 0
|
||||||
|
`define APB4_APU__ERROR_CODE 1
|
||||||
|
`define APB4_APU__ERROR_STAGE 7
|
||||||
|
`define APB4_APU__ERROR_AXI_RESPONSE 11
|
||||||
|
`define APB4_APU__ERROR_DESCRIPTOR_INDEX 13
|
||||||
|
|
||||||
|
`define APB4_APU__ERROR_CODE_NONE 0
|
||||||
|
`define APB4_APU__ERROR_CODE_INVALID_CONFIG 1
|
||||||
|
`define APB4_APU__ERROR_CODE_INVALID_RING 2
|
||||||
|
`define APB4_APU__ERROR_CODE_UNSUPPORTED 3
|
||||||
|
`define APB4_APU__ERROR_CODE_MALFORMED 4
|
||||||
|
`define APB4_APU__ERROR_CODE_TRUNCATED 5
|
||||||
|
`define APB4_APU__ERROR_CODE_CODEC_CRC 6
|
||||||
|
`define APB4_APU__ERROR_CODE_DECODE 7
|
||||||
|
`define APB4_APU__ERROR_CODE_RECONSTRUCTION 8
|
||||||
|
`define APB4_APU__ERROR_CODE_MICROCODE 9
|
||||||
|
`define APB4_APU__ERROR_CODE_MICROCODE_CRC 10
|
||||||
|
`define APB4_APU__ERROR_CODE_SEQUENCER 11
|
||||||
|
`define APB4_APU__ERROR_CODE_KWS_MODEL 12
|
||||||
|
`define APB4_APU__ERROR_CODE_KWS_CRC 13
|
||||||
|
`define APB4_APU__ERROR_CODE_KWS_ARITHMETIC 14
|
||||||
|
`define APB4_APU__ERROR_CODE_AXI_READ 15
|
||||||
|
`define APB4_APU__ERROR_CODE_AXI_WRITE 16
|
||||||
|
`define APB4_APU__ERROR_CODE_DMA_TIMEOUT 17
|
||||||
|
`define APB4_APU__ERROR_CODE_STREAM_UNDERRUN 18
|
||||||
|
`define APB4_APU__ERROR_CODE_STREAM_OVERRUN 19
|
||||||
|
`define APB4_APU__ERROR_CODE_ABORT 20
|
||||||
|
`define APB4_APU__ERROR_CODE_RESOURCE_RESET 21
|
||||||
|
`define APB4_APU__ERROR_CODE_OVERFLOW 22
|
||||||
|
|
||||||
|
`define APB4_APU__ERROR_STAGE_APB 0
|
||||||
|
`define APB4_APU__ERROR_STAGE_LOADER 1
|
||||||
|
`define APB4_APU__ERROR_STAGE_RING 2
|
||||||
|
`define APB4_APU__ERROR_STAGE_DMA_READ 3
|
||||||
|
`define APB4_APU__ERROR_STAGE_BITSTREAM 4
|
||||||
|
`define APB4_APU__ERROR_STAGE_ENTROPY 5
|
||||||
|
`define APB4_APU__ERROR_STAGE_RECONSTRUCTION 6
|
||||||
|
`define APB4_APU__ERROR_STAGE_RESAMPLER 7
|
||||||
|
`define APB4_APU__ERROR_STAGE_DMA_WRITE 8
|
||||||
|
`define APB4_APU__ERROR_STAGE_KWS_FRONTEND 9
|
||||||
|
`define APB4_APU__ERROR_STAGE_KWS_INFERENCE 10
|
||||||
|
`define APB4_APU__ERROR_STAGE_LIFECYCLE 11
|
||||||
|
|
||||||
|
`define APB4_APU__OWNER_STATUS_OWNER 0
|
||||||
|
`define APB4_APU__OWNER_STATUS_LOCK 8
|
||||||
|
`define APB4_APU__OWNER_STATUS_QUIESCE 9
|
||||||
|
`define APB4_APU__OWNER_STATUS_RESET 10
|
||||||
|
`define APB4_APU__PERF_CONTROL_ENABLE 0
|
||||||
|
`define APB4_APU__PERF_CONTROL_CLEAR 1
|
||||||
|
`define APB4_APU__PERF_CONTROL_SNAPSHOT 2
|
||||||
|
`define APB4_APU__PERF_STATUS_SNAPSHOT_VALID 0
|
||||||
|
// verilog_format: on
|
||||||
|
|
||||||
|
`endif
|
||||||
@@ -0,0 +1,561 @@
|
|||||||
|
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||||
|
// retroSoC is licensed under Mulan PSL v2.
|
||||||
|
|
||||||
|
`include "apu_define.svh"
|
||||||
|
|
||||||
|
module apu_reg (
|
||||||
|
// verilog_format: off -- preserve the APB and lifecycle boundary columns
|
||||||
|
input logic clk_i,
|
||||||
|
input logic rst_n_i,
|
||||||
|
input logic [1:0] owner_i,
|
||||||
|
input logic owner_lock_i,
|
||||||
|
input logic quiesce_i,
|
||||||
|
input logic resource_reset_i,
|
||||||
|
apb4_if.slave apb4,
|
||||||
|
output logic idle_o,
|
||||||
|
output logic irq_o
|
||||||
|
// verilog_format: on
|
||||||
|
);
|
||||||
|
localparam logic [31:0] IpId = 32'h4150_5530;
|
||||||
|
localparam logic [31:0] IpVersion = 32'h0001_0000;
|
||||||
|
localparam logic [31:0] Capability0 = 32'd0;
|
||||||
|
localparam logic [31:0] Capability1 = 32'd0;
|
||||||
|
localparam logic [31:0] AbiDigest = 32'd0;
|
||||||
|
localparam logic [10:0] IrqMask = 11'h7ff;
|
||||||
|
localparam logic [31:0] TimeoutReset = 32'h0000_ffff;
|
||||||
|
localparam logic [31:0] RingCoalesceReset = 32'h0001_0001;
|
||||||
|
localparam logic [31:0] KwsConfigReset = 32'h0000_0380;
|
||||||
|
localparam logic [3:0][31:0] AclReset = {32'd0, 32'hffff_ffff, 32'd0, 32'hffff_ffff};
|
||||||
|
localparam logic [4:0][31:0] RingReset = {RingCoalesceReset, 32'd0, 32'd0, 32'd0, 32'd0};
|
||||||
|
|
||||||
|
logic s_apb4_ready_d, s_apb4_ready_q;
|
||||||
|
logic [31:0] s_apb4_rdata_q;
|
||||||
|
logic s_apb4_resp_err_d, s_apb4_resp_err_q;
|
||||||
|
logic s_req_accept;
|
||||||
|
logic s_write;
|
||||||
|
logic [11:0] s_offset;
|
||||||
|
logic [31:0] s_strobed_write;
|
||||||
|
logic [31:0] s_merged_write;
|
||||||
|
logic s_read_err;
|
||||||
|
logic s_write_err;
|
||||||
|
logic s_write_unsupported;
|
||||||
|
logic [31:0] s_read_data;
|
||||||
|
logic s_soft_reset;
|
||||||
|
logic s_cnt_clear;
|
||||||
|
logic [10:0] s_irq_clear;
|
||||||
|
logic [10:0] s_irq_set;
|
||||||
|
|
||||||
|
logic [10:0] s_irq_state_d, s_irq_state_q;
|
||||||
|
logic [10:0] s_irq_en_d, s_irq_en_q;
|
||||||
|
logic [31:0] s_err_stat_d, s_err_stat_q;
|
||||||
|
logic [31:0] s_err_addr_d, s_err_addr_q;
|
||||||
|
logic [31:0] s_err_detail_d, s_err_detail_q;
|
||||||
|
logic [1:0][31:0] s_timeout_d, s_timeout_q;
|
||||||
|
logic [3:0] s_stream_route_d, s_stream_route_q;
|
||||||
|
logic [3:0][31:0] s_acl_d, s_acl_q;
|
||||||
|
logic [2:0][31:0] s_mc_cfg_d, s_mc_cfg_q;
|
||||||
|
logic [7:0][31:0] s_job_cfg_d, s_job_cfg_q;
|
||||||
|
logic [4:0][31:0] s_ring_cfg_d, s_ring_cfg_q;
|
||||||
|
logic [2:0][31:0] s_kws_model_cfg_d, s_kws_model_cfg_q;
|
||||||
|
logic [15:0] s_kws_cfg_d, s_kws_cfg_q;
|
||||||
|
logic s_perf_en_d, s_perf_en_q;
|
||||||
|
logic s_perf_snapshot_valid_d, s_perf_snapshot_valid_q;
|
||||||
|
|
||||||
|
function automatic logic [31:0] apply_wstrb(
|
||||||
|
input logic [31:0] previous_i, input logic [31:0] value_i, input logic [3:0] strobe_i);
|
||||||
|
logic [31:0] s_value;
|
||||||
|
begin
|
||||||
|
s_value = previous_i;
|
||||||
|
for (int unsigned byte_index = 0; byte_index < 4; byte_index++) begin
|
||||||
|
if (strobe_i[byte_index]) begin
|
||||||
|
s_value[(byte_index*8)+:8] = value_i[(byte_index*8)+:8];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return s_value;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function automatic logic is_power_of_two(input logic [31:0] value_i);
|
||||||
|
return (value_i != 32'd0) && ((value_i & (value_i - 1'b1)) == 32'd0);
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
assign s_req_accept = apb4.psel && apb4.penable && !s_apb4_ready_q;
|
||||||
|
assign s_write = s_req_accept && apb4.pwrite;
|
||||||
|
assign s_offset = apb4.paddr[11:0];
|
||||||
|
assign s_strobed_write = apply_wstrb(32'd0, apb4.pwdata, apb4.pstrb);
|
||||||
|
assign s_apb4_ready_d = s_req_accept;
|
||||||
|
assign s_apb4_resp_err_d = s_req_accept && (apb4.pwrite ? s_write_err : s_read_err);
|
||||||
|
assign apb4.pready = s_apb4_ready_q;
|
||||||
|
assign apb4.prdata = s_apb4_rdata_q;
|
||||||
|
assign apb4.pslverr = s_apb4_resp_err_q;
|
||||||
|
assign idle_o = 1'b1;
|
||||||
|
assign irq_o = (s_irq_state_q & s_irq_en_q) != 11'd0;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
s_read_data = 32'd0;
|
||||||
|
s_read_err = s_offset[1:0] != 2'b00;
|
||||||
|
if (!s_read_err) begin
|
||||||
|
unique case (s_offset)
|
||||||
|
`APB4_APU__IP_ID: s_read_data = IpId;
|
||||||
|
`APB4_APU__IP_VERSION: s_read_data = IpVersion;
|
||||||
|
`APB4_APU__CAPABILITY0: s_read_data = Capability0;
|
||||||
|
`APB4_APU__CAPABILITY1: s_read_data = Capability1;
|
||||||
|
`APB4_APU__STATUS: s_read_data = {22'd0, 1'b0, 1'b1, 1'b0, quiesce_i, 6'd0};
|
||||||
|
`APB4_APU__IRQ_STATE: s_read_data = {21'd0, s_irq_state_q};
|
||||||
|
`APB4_APU__IRQ_ENABLE: s_read_data = {21'd0, s_irq_en_q};
|
||||||
|
`APB4_APU__ERROR_STATUS: s_read_data = s_err_stat_q;
|
||||||
|
`APB4_APU__ERROR_ADDRESS: s_read_data = s_err_addr_q;
|
||||||
|
`APB4_APU__ERROR_DETAIL: s_read_data = s_err_detail_q;
|
||||||
|
`APB4_APU__SEQUENCER_TIMEOUT: s_read_data = s_timeout_q[0];
|
||||||
|
`APB4_APU__STREAM_ROUTE: s_read_data = {28'd0, s_stream_route_q};
|
||||||
|
`APB4_APU__STREAM_STATUS: s_read_data = 32'd0;
|
||||||
|
`APB4_APU__OWNER_STATUS:
|
||||||
|
s_read_data = {21'd0, resource_reset_i, quiesce_i, owner_lock_i, 6'd0, owner_i};
|
||||||
|
`APB4_APU__READ_BASE: s_read_data = s_acl_q[0];
|
||||||
|
`APB4_APU__READ_LIMIT: s_read_data = s_acl_q[1];
|
||||||
|
`APB4_APU__WRITE_BASE: s_read_data = s_acl_q[2];
|
||||||
|
`APB4_APU__WRITE_LIMIT: s_read_data = s_acl_q[3];
|
||||||
|
`APB4_APU__DMA_TIMEOUT: s_read_data = s_timeout_q[1];
|
||||||
|
`APB4_APU__ABI_DIGEST: s_read_data = AbiDigest;
|
||||||
|
`APB4_APU__SEQUENCER_STATUS, `APB4_APU__SEQUENCER_RETIRED,
|
||||||
|
`APB4_APU__MC_STATUS, `APB4_APU__MC_ABI, `APB4_APU__MC_BUILD_ID_LO,
|
||||||
|
`APB4_APU__MC_BUILD_ID_HI, `APB4_APU__MC_LOCK, `APB4_APU__MC_ACTUAL_CRC,
|
||||||
|
`APB4_APU__MC_LOAD_COUNT, `APB4_APU__JOB_STATUS, `APB4_APU__JOB_INPUT_USED,
|
||||||
|
`APB4_APU__JOB_OUTPUT_BYTES, `APB4_APU__JOB_FRAMES,
|
||||||
|
`APB4_APU__JOB_SOURCE_INFO, `APB4_APU__JOB_CYCLES, `APB4_APU__JOB_DETAIL,
|
||||||
|
`APB4_APU__RING_HEAD, `APB4_APU__RING_STATUS, `APB4_APU__RING_COMPLETED,
|
||||||
|
`APB4_APU__KWS_STATUS, `APB4_APU__KWS_RESULT, `APB4_APU__KWS_TIMESTAMP_LO,
|
||||||
|
`APB4_APU__KWS_TIMESTAMP_HI, `APB4_APU__KWS_FRAME_COUNT,
|
||||||
|
`APB4_APU__KWS_INFERENCE_COUNT, `APB4_APU__KWS_HIT_COUNT,
|
||||||
|
`APB4_APU__KWS_OVERRUN_COUNT, `APB4_APU__KWS_MODEL_STATUS,
|
||||||
|
`APB4_APU__KWS_MODEL_ACTUAL_CRC:
|
||||||
|
s_read_data = 32'd0;
|
||||||
|
`APB4_APU__MC_IMAGE_ADDRESS: s_read_data = s_mc_cfg_q[0];
|
||||||
|
`APB4_APU__MC_IMAGE_SIZE: s_read_data = s_mc_cfg_q[1];
|
||||||
|
`APB4_APU__MC_EXPECTED_CRC: s_read_data = s_mc_cfg_q[2];
|
||||||
|
`APB4_APU__JOB_CONTROL: s_read_data = s_job_cfg_q[0];
|
||||||
|
`APB4_APU__JOB_INPUT_ADDRESS: s_read_data = s_job_cfg_q[1];
|
||||||
|
`APB4_APU__JOB_INPUT_LENGTH: s_read_data = s_job_cfg_q[2];
|
||||||
|
`APB4_APU__JOB_OUTPUT_ADDRESS: s_read_data = s_job_cfg_q[3];
|
||||||
|
`APB4_APU__JOB_OUTPUT_CAPACITY: s_read_data = s_job_cfg_q[4];
|
||||||
|
`APB4_APU__JOB_INPUT_CONFIG: s_read_data = s_job_cfg_q[5];
|
||||||
|
`APB4_APU__JOB_OUTPUT_CONFIG: s_read_data = s_job_cfg_q[6];
|
||||||
|
`APB4_APU__JOB_FLAGS: s_read_data = s_job_cfg_q[7];
|
||||||
|
`APB4_APU__RING_BASE: s_read_data = s_ring_cfg_q[0];
|
||||||
|
`APB4_APU__RING_SIZE: s_read_data = s_ring_cfg_q[1];
|
||||||
|
`APB4_APU__RING_TAIL: s_read_data = s_ring_cfg_q[2];
|
||||||
|
`APB4_APU__RING_CONTROL: s_read_data = s_ring_cfg_q[3];
|
||||||
|
`APB4_APU__RING_COALESCE: s_read_data = s_ring_cfg_q[4];
|
||||||
|
`APB4_APU__KWS_MODEL_ADDRESS: s_read_data = s_kws_model_cfg_q[0];
|
||||||
|
`APB4_APU__KWS_MODEL_SIZE: s_read_data = s_kws_model_cfg_q[1];
|
||||||
|
`APB4_APU__KWS_MODEL_EXPECTED_CRC: s_read_data = s_kws_model_cfg_q[2];
|
||||||
|
`APB4_APU__KWS_CONTROL: s_read_data = 32'd0;
|
||||||
|
`APB4_APU__KWS_CONFIG: s_read_data = {16'd0, s_kws_cfg_q};
|
||||||
|
`APB4_APU__PERF_CONTROL: s_read_data = {31'd0, s_perf_en_q};
|
||||||
|
`APB4_APU__PERF_STATUS: s_read_data = {31'd0, s_perf_snapshot_valid_q};
|
||||||
|
`APB4_APU__PERF_ACTIVE_CYCLES_LO, `APB4_APU__PERF_ACTIVE_CYCLES_HI,
|
||||||
|
`APB4_APU__PERF_INPUT_BYTES_LO, `APB4_APU__PERF_INPUT_BYTES_HI,
|
||||||
|
`APB4_APU__PERF_OUTPUT_BYTES_LO, `APB4_APU__PERF_OUTPUT_BYTES_HI,
|
||||||
|
`APB4_APU__PERF_DECODED_FRAMES_LO, `APB4_APU__PERF_DECODED_FRAMES_HI,
|
||||||
|
`APB4_APU__PERF_DMA_READ_STALLS_LO, `APB4_APU__PERF_DMA_READ_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_DMA_WRITE_STALLS_LO, `APB4_APU__PERF_DMA_WRITE_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_STREAM_STALLS_LO, `APB4_APU__PERF_STREAM_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_SEQUENCER_INSTR_LO, `APB4_APU__PERF_SEQUENCER_INSTR_HI,
|
||||||
|
`APB4_APU__PERF_KWS_CYCLES_LO, `APB4_APU__PERF_KWS_CYCLES_HI,
|
||||||
|
`APB4_APU__PERF_FAULTS_LO, `APB4_APU__PERF_FAULTS_HI:
|
||||||
|
s_read_data = 32'd0;
|
||||||
|
`APB4_APU__COMMAND, `APB4_APU__IRQ_TEST, `APB4_APU__RING_DOORBELL: begin
|
||||||
|
s_read_data = 32'd0;
|
||||||
|
s_read_err = 1'b1;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
s_read_data = 32'd0;
|
||||||
|
s_read_err = 1'b1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
s_write_err = s_offset[1:0] != 2'b00;
|
||||||
|
s_write_unsupported = 1'b0;
|
||||||
|
s_merged_write = s_strobed_write;
|
||||||
|
if (!s_write_err) begin
|
||||||
|
unique case (s_offset)
|
||||||
|
`APB4_APU__COMMAND: begin
|
||||||
|
s_write_unsupported = (apb4.pwdata & 32'h0000_003b) != 32'd0;
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) ||
|
||||||
|
((apb4.pwdata & 32'hffff_ff80) != 32'd0) ||
|
||||||
|
s_write_unsupported;
|
||||||
|
end
|
||||||
|
`APB4_APU__IRQ_STATE: s_write_err = (s_strobed_write & ~32'(IrqMask)) != 32'd0;
|
||||||
|
`APB4_APU__IRQ_ENABLE: begin
|
||||||
|
s_merged_write = apply_wstrb({21'd0, s_irq_en_q}, apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = (s_merged_write & ~32'(IrqMask)) != 32'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__IRQ_TEST:
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || ((apb4.pwdata & ~32'(IrqMask)) != 32'd0);
|
||||||
|
`APB4_APU__ERROR_STATUS: s_write_err = (s_strobed_write & 32'hffff_fffe) != 32'd0;
|
||||||
|
`APB4_APU__SEQUENCER_TIMEOUT: begin
|
||||||
|
s_merged_write = apply_wstrb(s_timeout_q[0], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = s_merged_write == 32'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__STREAM_ROUTE: begin
|
||||||
|
s_merged_write = apply_wstrb({28'd0, s_stream_route_q}, apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_unsupported = s_merged_write != 32'd0;
|
||||||
|
s_write_err = s_write_unsupported;
|
||||||
|
end
|
||||||
|
`APB4_APU__READ_BASE, `APB4_APU__READ_LIMIT, `APB4_APU__WRITE_BASE,
|
||||||
|
`APB4_APU__WRITE_LIMIT, `APB4_APU__MC_EXPECTED_CRC,
|
||||||
|
`APB4_APU__KWS_MODEL_EXPECTED_CRC:
|
||||||
|
s_write_err = apb4.pstrb != 4'hf;
|
||||||
|
`APB4_APU__DMA_TIMEOUT: begin
|
||||||
|
s_merged_write = apply_wstrb(s_timeout_q[1], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = s_merged_write == 32'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__MC_IMAGE_ADDRESS, `APB4_APU__KWS_MODEL_ADDRESS:
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[5:0] != 6'd0);
|
||||||
|
`APB4_APU__MC_IMAGE_SIZE, `APB4_APU__KWS_MODEL_SIZE:
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata == 32'd0);
|
||||||
|
`APB4_APU__JOB_CONTROL: begin
|
||||||
|
s_merged_write = apply_wstrb(s_job_cfg_q[0], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = (s_merged_write[31:12] != 20'd0) ||
|
||||||
|
(s_merged_write[3:0] > 4'd1) ||
|
||||||
|
(s_merged_write[7:4] > 4'd2) || (s_merged_write[9:8] > 2'd1);
|
||||||
|
end
|
||||||
|
`APB4_APU__JOB_INPUT_ADDRESS, `APB4_APU__JOB_INPUT_LENGTH,
|
||||||
|
`APB4_APU__JOB_OUTPUT_ADDRESS, `APB4_APU__JOB_OUTPUT_CAPACITY:
|
||||||
|
s_write_err = apb4.pstrb != 4'hf;
|
||||||
|
`APB4_APU__JOB_INPUT_CONFIG: begin
|
||||||
|
s_merged_write = apply_wstrb(s_job_cfg_q[5], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = s_merged_write[31:26] != 6'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__JOB_OUTPUT_CONFIG: begin
|
||||||
|
s_merged_write = apply_wstrb(s_job_cfg_q[6], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = (s_merged_write[31:21] != 11'd0) || (s_merged_write[20:19] > 2'd1);
|
||||||
|
end
|
||||||
|
`APB4_APU__JOB_FLAGS: begin
|
||||||
|
s_merged_write = apply_wstrb(s_job_cfg_q[7], apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = s_merged_write[31:1] != 31'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__RING_BASE: s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[6:0] != 7'd0);
|
||||||
|
`APB4_APU__RING_SIZE:
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata < 32'd2) ||
|
||||||
|
(apb4.pwdata > 32'd256) || !is_power_of_two(apb4.pwdata);
|
||||||
|
`APB4_APU__RING_TAIL: s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[31:8] != 24'd0);
|
||||||
|
`APB4_APU__RING_CONTROL: s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[31:2] != 30'd0);
|
||||||
|
`APB4_APU__RING_COALESCE:
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[15:8] != 8'd0) ||
|
||||||
|
(apb4.pwdata[7:0] == 8'd0) || (apb4.pwdata[31:16] == 16'd0);
|
||||||
|
`APB4_APU__RING_DOORBELL: begin
|
||||||
|
s_write_unsupported = 1'b1;
|
||||||
|
s_write_err = 1'b1;
|
||||||
|
end
|
||||||
|
`APB4_APU__KWS_CONTROL: begin
|
||||||
|
s_write_unsupported = apb4.pwdata[1:0] != 2'd0;
|
||||||
|
s_write_err = (apb4.pstrb != 4'hf) || (apb4.pwdata[31:3] != 29'd0) || s_write_unsupported;
|
||||||
|
end
|
||||||
|
`APB4_APU__KWS_CONFIG: begin
|
||||||
|
s_merged_write = apply_wstrb({16'd0, s_kws_cfg_q}, apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = (s_merged_write[31:16] != 16'd0) || (s_merged_write[15:8] == 8'd0);
|
||||||
|
end
|
||||||
|
`APB4_APU__PERF_CONTROL: begin
|
||||||
|
s_merged_write = apply_wstrb({31'd0, s_perf_en_q}, apb4.pwdata, apb4.pstrb);
|
||||||
|
s_write_err = s_merged_write[31:3] != 29'd0;
|
||||||
|
end
|
||||||
|
`APB4_APU__IP_ID, `APB4_APU__IP_VERSION, `APB4_APU__CAPABILITY0,
|
||||||
|
`APB4_APU__CAPABILITY1, `APB4_APU__STATUS, `APB4_APU__STREAM_STATUS,
|
||||||
|
`APB4_APU__OWNER_STATUS, `APB4_APU__ABI_DIGEST,
|
||||||
|
`APB4_APU__SEQUENCER_STATUS, `APB4_APU__SEQUENCER_RETIRED,
|
||||||
|
`APB4_APU__MC_STATUS, `APB4_APU__MC_ABI, `APB4_APU__MC_BUILD_ID_LO,
|
||||||
|
`APB4_APU__MC_BUILD_ID_HI, `APB4_APU__MC_LOCK, `APB4_APU__MC_ACTUAL_CRC,
|
||||||
|
`APB4_APU__MC_LOAD_COUNT, `APB4_APU__JOB_STATUS, `APB4_APU__JOB_INPUT_USED,
|
||||||
|
`APB4_APU__JOB_OUTPUT_BYTES, `APB4_APU__JOB_FRAMES,
|
||||||
|
`APB4_APU__JOB_SOURCE_INFO, `APB4_APU__JOB_CYCLES, `APB4_APU__JOB_DETAIL,
|
||||||
|
`APB4_APU__RING_HEAD, `APB4_APU__RING_STATUS, `APB4_APU__RING_COMPLETED,
|
||||||
|
`APB4_APU__KWS_STATUS, `APB4_APU__KWS_RESULT, `APB4_APU__KWS_TIMESTAMP_LO,
|
||||||
|
`APB4_APU__KWS_TIMESTAMP_HI, `APB4_APU__KWS_FRAME_COUNT,
|
||||||
|
`APB4_APU__KWS_INFERENCE_COUNT, `APB4_APU__KWS_HIT_COUNT,
|
||||||
|
`APB4_APU__KWS_OVERRUN_COUNT, `APB4_APU__KWS_MODEL_STATUS,
|
||||||
|
`APB4_APU__KWS_MODEL_ACTUAL_CRC, `APB4_APU__PERF_STATUS,
|
||||||
|
`APB4_APU__PERF_ACTIVE_CYCLES_LO, `APB4_APU__PERF_ACTIVE_CYCLES_HI,
|
||||||
|
`APB4_APU__PERF_INPUT_BYTES_LO, `APB4_APU__PERF_INPUT_BYTES_HI,
|
||||||
|
`APB4_APU__PERF_OUTPUT_BYTES_LO, `APB4_APU__PERF_OUTPUT_BYTES_HI,
|
||||||
|
`APB4_APU__PERF_DECODED_FRAMES_LO, `APB4_APU__PERF_DECODED_FRAMES_HI,
|
||||||
|
`APB4_APU__PERF_DMA_READ_STALLS_LO, `APB4_APU__PERF_DMA_READ_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_DMA_WRITE_STALLS_LO, `APB4_APU__PERF_DMA_WRITE_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_STREAM_STALLS_LO, `APB4_APU__PERF_STREAM_STALLS_HI,
|
||||||
|
`APB4_APU__PERF_SEQUENCER_INSTR_LO, `APB4_APU__PERF_SEQUENCER_INSTR_HI,
|
||||||
|
`APB4_APU__PERF_KWS_CYCLES_LO, `APB4_APU__PERF_KWS_CYCLES_HI,
|
||||||
|
`APB4_APU__PERF_FAULTS_LO, `APB4_APU__PERF_FAULTS_HI:
|
||||||
|
s_write_err = 1'b1;
|
||||||
|
default: s_write_err = 1'b1;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
s_irq_state_d = s_irq_state_q;
|
||||||
|
s_irq_en_d = s_irq_en_q;
|
||||||
|
s_err_stat_d = s_err_stat_q;
|
||||||
|
s_err_addr_d = s_err_addr_q;
|
||||||
|
s_err_detail_d = s_err_detail_q;
|
||||||
|
s_timeout_d = s_timeout_q;
|
||||||
|
s_stream_route_d = s_stream_route_q;
|
||||||
|
s_acl_d = s_acl_q;
|
||||||
|
s_mc_cfg_d = s_mc_cfg_q;
|
||||||
|
s_job_cfg_d = s_job_cfg_q;
|
||||||
|
s_ring_cfg_d = s_ring_cfg_q;
|
||||||
|
s_kws_model_cfg_d = s_kws_model_cfg_q;
|
||||||
|
s_kws_cfg_d = s_kws_cfg_q;
|
||||||
|
s_perf_en_d = s_perf_en_q;
|
||||||
|
s_perf_snapshot_valid_d = s_perf_snapshot_valid_q;
|
||||||
|
s_soft_reset = 1'b0;
|
||||||
|
s_cnt_clear = 1'b0;
|
||||||
|
s_irq_clear = 11'd0;
|
||||||
|
s_irq_set = 11'd0;
|
||||||
|
|
||||||
|
if (s_write && !s_write_err) begin
|
||||||
|
unique case (s_offset)
|
||||||
|
`APB4_APU__COMMAND: begin
|
||||||
|
s_soft_reset = apb4.pwdata[`APB4_APU__COMMAND_SOFT_RESET];
|
||||||
|
s_cnt_clear = apb4.pwdata[`APB4_APU__COMMAND_CLEAR_COUNTERS];
|
||||||
|
end
|
||||||
|
`APB4_APU__IRQ_STATE: s_irq_clear = s_strobed_write[10:0];
|
||||||
|
`APB4_APU__IRQ_ENABLE: s_irq_en_d = s_merged_write[10:0];
|
||||||
|
`APB4_APU__IRQ_TEST: s_irq_set = apb4.pwdata[10:0];
|
||||||
|
`APB4_APU__ERROR_STATUS: begin
|
||||||
|
if (s_strobed_write[0]) begin
|
||||||
|
s_err_stat_d = 32'd0;
|
||||||
|
s_err_addr_d = 32'd0;
|
||||||
|
s_err_detail_d = 32'd0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`APB4_APU__SEQUENCER_TIMEOUT: s_timeout_d[0] = s_merged_write;
|
||||||
|
`APB4_APU__STREAM_ROUTE: s_stream_route_d = s_merged_write[3:0];
|
||||||
|
`APB4_APU__READ_BASE: s_acl_d[0] = apb4.pwdata;
|
||||||
|
`APB4_APU__READ_LIMIT: s_acl_d[1] = apb4.pwdata;
|
||||||
|
`APB4_APU__WRITE_BASE: s_acl_d[2] = apb4.pwdata;
|
||||||
|
`APB4_APU__WRITE_LIMIT: s_acl_d[3] = apb4.pwdata;
|
||||||
|
`APB4_APU__DMA_TIMEOUT: s_timeout_d[1] = s_merged_write;
|
||||||
|
`APB4_APU__MC_IMAGE_ADDRESS: s_mc_cfg_d[0] = apb4.pwdata;
|
||||||
|
`APB4_APU__MC_IMAGE_SIZE: s_mc_cfg_d[1] = apb4.pwdata;
|
||||||
|
`APB4_APU__MC_EXPECTED_CRC: s_mc_cfg_d[2] = apb4.pwdata;
|
||||||
|
`APB4_APU__JOB_CONTROL: s_job_cfg_d[0] = s_merged_write;
|
||||||
|
`APB4_APU__JOB_INPUT_ADDRESS: s_job_cfg_d[1] = apb4.pwdata;
|
||||||
|
`APB4_APU__JOB_INPUT_LENGTH: s_job_cfg_d[2] = apb4.pwdata;
|
||||||
|
`APB4_APU__JOB_OUTPUT_ADDRESS: s_job_cfg_d[3] = apb4.pwdata;
|
||||||
|
`APB4_APU__JOB_OUTPUT_CAPACITY: s_job_cfg_d[4] = apb4.pwdata;
|
||||||
|
`APB4_APU__JOB_INPUT_CONFIG: s_job_cfg_d[5] = s_merged_write;
|
||||||
|
`APB4_APU__JOB_OUTPUT_CONFIG: s_job_cfg_d[6] = s_merged_write;
|
||||||
|
`APB4_APU__JOB_FLAGS: s_job_cfg_d[7] = s_merged_write;
|
||||||
|
`APB4_APU__RING_BASE: s_ring_cfg_d[0] = apb4.pwdata;
|
||||||
|
`APB4_APU__RING_SIZE: s_ring_cfg_d[1] = apb4.pwdata;
|
||||||
|
`APB4_APU__RING_TAIL: s_ring_cfg_d[2] = apb4.pwdata;
|
||||||
|
`APB4_APU__RING_CONTROL: s_ring_cfg_d[3] = apb4.pwdata;
|
||||||
|
`APB4_APU__RING_COALESCE: s_ring_cfg_d[4] = apb4.pwdata;
|
||||||
|
`APB4_APU__KWS_MODEL_ADDRESS: s_kws_model_cfg_d[0] = apb4.pwdata;
|
||||||
|
`APB4_APU__KWS_MODEL_SIZE: s_kws_model_cfg_d[1] = apb4.pwdata;
|
||||||
|
`APB4_APU__KWS_MODEL_EXPECTED_CRC: s_kws_model_cfg_d[2] = apb4.pwdata;
|
||||||
|
`APB4_APU__KWS_CONFIG: s_kws_cfg_d = s_merged_write[15:0];
|
||||||
|
`APB4_APU__PERF_CONTROL: begin
|
||||||
|
s_perf_en_d = s_merged_write[`APB4_APU__PERF_CONTROL_ENABLE];
|
||||||
|
if (s_merged_write[`APB4_APU__PERF_CONTROL_CLEAR]) begin
|
||||||
|
s_cnt_clear = 1'b1;
|
||||||
|
end
|
||||||
|
if (s_merged_write[`APB4_APU__PERF_CONTROL_SNAPSHOT]) begin
|
||||||
|
s_perf_snapshot_valid_d = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_cnt_clear) begin
|
||||||
|
s_perf_snapshot_valid_d = 1'b0;
|
||||||
|
end
|
||||||
|
if (s_req_accept && (apb4.pwrite ? s_write_err : s_read_err)) begin
|
||||||
|
s_irq_set[`APB4_APU__IRQ_FIRST_ERROR] = 1'b1;
|
||||||
|
if (!s_err_stat_q[`APB4_APU__ERROR_VALID]) begin
|
||||||
|
s_err_stat_d = 32'd1 |
|
||||||
|
(32'((apb4.pwrite && s_write_unsupported) ?
|
||||||
|
`APB4_APU__ERROR_CODE_UNSUPPORTED :
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG)
|
||||||
|
<< `APB4_APU__ERROR_CODE) |
|
||||||
|
(32'(`APB4_APU__ERROR_STAGE_APB) << `APB4_APU__ERROR_STAGE);
|
||||||
|
s_err_addr_d = apb4.paddr;
|
||||||
|
s_err_detail_d = apb4.pwrite ? apb4.pwdata : {20'd0, s_offset};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
s_irq_state_d = (s_irq_state_d & ~s_irq_clear) | s_irq_set;
|
||||||
|
|
||||||
|
if (s_soft_reset || resource_reset_i) begin
|
||||||
|
s_irq_state_d = 11'd0;
|
||||||
|
s_irq_en_d = 11'd0;
|
||||||
|
s_err_stat_d = 32'd0;
|
||||||
|
s_err_addr_d = 32'd0;
|
||||||
|
s_err_detail_d = 32'd0;
|
||||||
|
s_timeout_d[0] = TimeoutReset;
|
||||||
|
s_timeout_d[1] = TimeoutReset;
|
||||||
|
s_stream_route_d = 4'd0;
|
||||||
|
s_mc_cfg_d = '0;
|
||||||
|
s_job_cfg_d = '0;
|
||||||
|
s_ring_cfg_d = RingReset;
|
||||||
|
s_kws_model_cfg_d = '0;
|
||||||
|
s_kws_cfg_d = KwsConfigReset[15:0];
|
||||||
|
s_perf_en_d = 1'b0;
|
||||||
|
s_perf_snapshot_valid_d = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(1)
|
||||||
|
) u_ready_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_apb4_ready_d),
|
||||||
|
.dat_o (s_apb4_ready_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(1)
|
||||||
|
) u_resp_err_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_apb4_resp_err_d),
|
||||||
|
.dat_o (s_apb4_resp_err_q)
|
||||||
|
);
|
||||||
|
dffer #(
|
||||||
|
.DATA_WIDTH(32)
|
||||||
|
) u_rdata_dffer (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.en_i (s_req_accept && !apb4.pwrite),
|
||||||
|
.dat_i (s_read_data),
|
||||||
|
.dat_o (s_apb4_rdata_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(11)
|
||||||
|
) u_irq_state_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_irq_state_d),
|
||||||
|
.dat_o (s_irq_state_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(11)
|
||||||
|
) u_irq_enable_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_irq_en_d),
|
||||||
|
.dat_o (s_irq_en_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(32)
|
||||||
|
) u_error_status_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_err_stat_d),
|
||||||
|
.dat_o (s_err_stat_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(32)
|
||||||
|
) u_error_address_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_err_addr_d),
|
||||||
|
.dat_o (s_err_addr_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(32)
|
||||||
|
) u_error_detail_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_err_detail_d),
|
||||||
|
.dat_o (s_err_detail_q)
|
||||||
|
);
|
||||||
|
dffrc #(
|
||||||
|
.DATA_WIDTH(2 * 32),
|
||||||
|
.RESET_VAL ({TimeoutReset, TimeoutReset})
|
||||||
|
) u_timeout_dffrc (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_timeout_d),
|
||||||
|
.dat_o (s_timeout_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(4)
|
||||||
|
) u_stream_route_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_stream_route_d),
|
||||||
|
.dat_o (s_stream_route_q)
|
||||||
|
);
|
||||||
|
dffrc #(
|
||||||
|
.DATA_WIDTH(4 * 32),
|
||||||
|
.RESET_VAL (AclReset)
|
||||||
|
) u_acl_dffrc (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_acl_d),
|
||||||
|
.dat_o (s_acl_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(3 * 32)
|
||||||
|
) u_mc_cfg_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_mc_cfg_d),
|
||||||
|
.dat_o (s_mc_cfg_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(8 * 32)
|
||||||
|
) u_job_cfg_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_job_cfg_d),
|
||||||
|
.dat_o (s_job_cfg_q)
|
||||||
|
);
|
||||||
|
dffrc #(
|
||||||
|
.DATA_WIDTH(5 * 32),
|
||||||
|
.RESET_VAL (RingReset)
|
||||||
|
) u_ring_cfg_dffrc (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_ring_cfg_d),
|
||||||
|
.dat_o (s_ring_cfg_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(3 * 32)
|
||||||
|
) u_kws_model_cfg_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_kws_model_cfg_d),
|
||||||
|
.dat_o (s_kws_model_cfg_q)
|
||||||
|
);
|
||||||
|
dffrc #(
|
||||||
|
.DATA_WIDTH(16),
|
||||||
|
.RESET_VAL (KwsConfigReset[15:0])
|
||||||
|
) u_kws_cfg_dffrc (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_kws_cfg_d),
|
||||||
|
.dat_o (s_kws_cfg_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(1)
|
||||||
|
) u_perf_enable_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_perf_en_d),
|
||||||
|
.dat_o (s_perf_en_q)
|
||||||
|
);
|
||||||
|
dffr #(
|
||||||
|
.DATA_WIDTH(1)
|
||||||
|
) u_perf_snapshot_valid_dffr (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i(rst_n_i),
|
||||||
|
.dat_i (s_perf_snapshot_valid_d),
|
||||||
|
.dat_o (s_perf_snapshot_valid_q)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
@@ -421,9 +421,9 @@
|
|||||||
"symbol": "APB4_APU",
|
"symbol": "APB4_APU",
|
||||||
"base": "0x10013000",
|
"base": "0x10013000",
|
||||||
"size": "0x00001000",
|
"size": "0x00001000",
|
||||||
"route": "reserved",
|
"route": "apb4_periph",
|
||||||
"kind": "reserved",
|
"kind": "active",
|
||||||
"public": false,
|
"public": true,
|
||||||
"user_access": "none"
|
"user_access": "none"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,6 +125,8 @@
|
|||||||
/ip/multimedia/dvp_core.sv
|
/ip/multimedia/dvp_core.sv
|
||||||
/ip/multimedia/dvp_reg.sv
|
/ip/multimedia/dvp_reg.sv
|
||||||
/ip/multimedia/axi4s_dvp.sv
|
/ip/multimedia/axi4s_dvp.sv
|
||||||
|
/ip/multimedia/apu_reg.sv
|
||||||
|
/ip/multimedia/apb4_apu.sv
|
||||||
/ip/multimedia/jpeg_pkg.sv
|
/ip/multimedia/jpeg_pkg.sv
|
||||||
/ip/multimedia/jpeg_transform.sv
|
/ip/multimedia/jpeg_transform.sv
|
||||||
/ip/multimedia/jpeg_quantizer.sv
|
/ip/multimedia/jpeg_quantizer.sv
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ must appear exactly once. Disabled targets keep their slot and interface
|
|||||||
declaration but cannot own an address region. This list stays separate from
|
declaration but cannot own an address region. This list stays separate from
|
||||||
`apb4_system_targets`, which owns the `0x2000_0000` `apb4_system` island.
|
`apb4_system_targets`, which owns the `0x2000_0000` `apb4_system` island.
|
||||||
Slot 15 is the active SDIO0 management window; SDIO1 is appended at slot 18,
|
Slot 15 is the active SDIO0 management window; SDIO1 is appended at slot 18,
|
||||||
the management-only crypto controller at slot 19, and USB2 at slot 20, so the
|
the management-only crypto controller at slot 19, USB2 at slot 20, JPEG at
|
||||||
existing slots 0..17 remain stable.
|
slot 26, and the APU shell at slot 27, so the existing slots remain stable.
|
||||||
|
|
||||||
Each `gpio_alt_functions` entry defines both alternate modes for one GPIO pin.
|
Each `gpio_alt_functions` entry defines both alternate modes for one GPIO pin.
|
||||||
`inputs` are driven from the selected GPIO input, and `do` and `oe` define the
|
`inputs` are driven from the selected GPIO input, and `do` and `oe` define the
|
||||||
@@ -54,7 +54,8 @@ Existing allocated core IRQ bits retain their compatibility mapping; additions
|
|||||||
must use currently unallocated bits and preserve the existing entries. SDIO0
|
must use currently unallocated bits and preserve the existing entries. SDIO0
|
||||||
and SDIO1 use APB4 group bits 16 and 17 and core bits 10 and 21. Crypto uses
|
and SDIO1 use APB4 group bits 16 and 17 and core bits 10 and 21. Crypto uses
|
||||||
APB4 group bit 18 and core bit 23. USB2 uses APB4 group bit 19 and core bit 24.
|
APB4 group bit 18 and core bit 23. USB2 uses APB4 group bit 19 and core bit 24.
|
||||||
All four remain management-only in the
|
JPEG uses group bit 22 and core bit 30; APU uses group bit 23 and core bit 31.
|
||||||
|
All resource-owned sources remain management-only in the
|
||||||
generated user IRQ mask. Removing a source leaves its
|
generated user IRQ mask. Removing a source leaves its
|
||||||
core IRQ bit unallocated and driven low. Firmware does not
|
core IRQ bit unallocated and driven low. Firmware does not
|
||||||
expose a generic external interrupt API until the SoC includes a claim/complete
|
expose a generic external interrupt API until the SoC includes a claim/complete
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ COMPATIBILITY_IRQ_BINDINGS = (
|
|||||||
("watchdog_early_warning", "apb4_system", 3, 14, "u_wdg_if.irq_o"),
|
("watchdog_early_warning", "apb4_system", 3, 14, "u_wdg_if.irq_o"),
|
||||||
("rng", "apb4_system", 4, 16, "s_rng_irq"),
|
("rng", "apb4_system", 4, 16, "s_rng_irq"),
|
||||||
("resource_fault", "apb4_system", 7, 29, "s_resource_fault_irq"),
|
("resource_fault", "apb4_system", 7, 29, "s_resource_fault_irq"),
|
||||||
|
("apu", "apb4_periph", 23, 31, "resource_irq_lp_i[6]"),
|
||||||
("ws2812", "apb4_periph", 10, 17, "ws2812.irq_o"),
|
("ws2812", "apb4_periph", 10, 17, "ws2812.irq_o"),
|
||||||
("gpio", "apb4_periph", 11, 18, "gpio.irq_o"),
|
("gpio", "apb4_periph", 11, 18, "gpio.irq_o"),
|
||||||
("i2c1", "apb4_periph", 12, 19, "i2c1.irq_o"),
|
("i2c1", "apb4_periph", 12, 19, "i2c1.irq_o"),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"irq_groups": [
|
"irq_groups": [
|
||||||
{
|
{
|
||||||
"name": "apb4_periph",
|
"name": "apb4_periph",
|
||||||
"width": 23,
|
"width": 24,
|
||||||
"top_signal": "s_apb4_periph_irq"
|
"top_signal": "s_apb4_periph_irq"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -276,6 +276,15 @@
|
|||||||
"core_bit": 29,
|
"core_bit": 29,
|
||||||
"signal": "s_resource_fault_irq",
|
"signal": "s_resource_fault_irq",
|
||||||
"user_visible": false
|
"user_visible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "apu",
|
||||||
|
"description": "APU completion and error interrupt",
|
||||||
|
"group": "apb4_periph",
|
||||||
|
"group_bit": 23,
|
||||||
|
"core_bit": 31,
|
||||||
|
"signal": "resource_irq_lp_i[6]",
|
||||||
|
"user_visible": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"wake_sources": [
|
"wake_sources": [
|
||||||
@@ -600,6 +609,13 @@
|
|||||||
"timed_interface": "u_jpeg_apb4_if",
|
"timed_interface": "u_jpeg_apb4_if",
|
||||||
"pure_interface": "u_jpeg_apb4_pure_if",
|
"pure_interface": "u_jpeg_apb4_pure_if",
|
||||||
"region": "APB4_JPEG"
|
"region": "APB4_JPEG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"slot": 27,
|
||||||
|
"name": "apu",
|
||||||
|
"timed_interface": "u_apu_apb4_if",
|
||||||
|
"pure_interface": "u_apu_apb4_pure_if",
|
||||||
|
"region": "APB4_APU"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"apb4_system_targets": [
|
"apb4_system_targets": [
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ CRT_SRCS := $(ROOT_PATH)/crt/arch/riscv/startup.S \
|
|||||||
$(ROOT_PATH)/crt/src/hal/dma_math.c \
|
$(ROOT_PATH)/crt/src/hal/dma_math.c \
|
||||||
$(ROOT_PATH)/crt/src/hal/dma.c \
|
$(ROOT_PATH)/crt/src/hal/dma.c \
|
||||||
$(ROOT_PATH)/crt/src/hal/crypto.c \
|
$(ROOT_PATH)/crt/src/hal/crypto.c \
|
||||||
|
$(ROOT_PATH)/crt/src/hal/apu.c \
|
||||||
$(ROOT_PATH)/crt/src/hal/jpeg_math.c \
|
$(ROOT_PATH)/crt/src/hal/jpeg_math.c \
|
||||||
$(ROOT_PATH)/crt/src/hal/jpeg.c \
|
$(ROOT_PATH)/crt/src/hal/jpeg.c \
|
||||||
$(ROOT_PATH)/crt/src/hal/dvp.c \
|
$(ROOT_PATH)/crt/src/hal/dvp.c \
|
||||||
|
|||||||
+33
-14
@@ -23,8 +23,12 @@ module apb4_periph (
|
|||||||
input logic debug_halted_i,
|
input logic debug_halted_i,
|
||||||
input logic timebase_tick_i,
|
input logic timebase_tick_i,
|
||||||
input logic ext_h_hp_irq_i,
|
input logic ext_h_hp_irq_i,
|
||||||
input logic [5:0] resource_irq_lp_i,
|
input logic [6:0] resource_irq_lp_i,
|
||||||
input logic [5:0] resource_irq_hp_i,
|
input logic [6:0] resource_irq_hp_i,
|
||||||
|
input logic [1:0] apu_owner_i,
|
||||||
|
input logic apu_owner_lock_i,
|
||||||
|
input logic apu_quiesce_i,
|
||||||
|
input logic apu_reset_i,
|
||||||
input logic jpeg_quiesce_i,
|
input logic jpeg_quiesce_i,
|
||||||
input logic jpeg_reset_i,
|
input logic jpeg_reset_i,
|
||||||
axi4_if.slave cfg_axi4,
|
axi4_if.slave cfg_axi4,
|
||||||
@@ -67,8 +71,9 @@ module apb4_periph (
|
|||||||
output logic hp_software_irq_o,
|
output logic hp_software_irq_o,
|
||||||
output logic hp_machine_external_irq_o,
|
output logic hp_machine_external_irq_o,
|
||||||
output logic hp_supervisor_external_irq_o,
|
output logic hp_supervisor_external_irq_o,
|
||||||
|
output logic apu_idle_o,
|
||||||
output logic jpeg_idle_o,
|
output logic jpeg_idle_o,
|
||||||
output logic [5:0] resource_irq_raw_o,
|
output logic [6:0] resource_irq_raw_o,
|
||||||
output logic [`SOC_IRQ_APB4_PERIPH_WIDTH-1:0] irq_o
|
output logic [`SOC_IRQ_APB4_PERIPH_WIDTH-1:0] irq_o
|
||||||
// verilog_format: on
|
// verilog_format: on
|
||||||
);
|
);
|
||||||
@@ -151,6 +156,7 @@ axi4_stream_if #(
|
|||||||
logic s_dma_crypto_in_proc;
|
logic s_dma_crypto_in_proc;
|
||||||
logic s_dma_crypto_out_proc;
|
logic s_dma_crypto_out_proc;
|
||||||
logic s_crypto_irq;
|
logic s_crypto_irq;
|
||||||
|
logic s_apu_irq_raw;
|
||||||
logic s_jpeg_irq_raw;
|
logic s_jpeg_irq_raw;
|
||||||
logic s_usb2_irq;
|
logic s_usb2_irq;
|
||||||
logic s_tim0_irq, s_tim1_irq;
|
logic s_tim0_irq, s_tim1_irq;
|
||||||
@@ -210,7 +216,7 @@ axi4_stream_if #(
|
|||||||
assign hp_machine_external_irq_o = s_hp_plic_context_irq[0];
|
assign hp_machine_external_irq_o = s_hp_plic_context_irq[0];
|
||||||
assign hp_supervisor_external_irq_o = s_hp_plic_context_irq[1];
|
assign hp_supervisor_external_irq_o = s_hp_plic_context_irq[1];
|
||||||
assign resource_irq_raw_o = {
|
assign resource_irq_raw_o = {
|
||||||
s_jpeg_irq_raw, spisd.irq_o, sdio1.irq_o, sdio0.irq_o, s_usb2_irq, s_dma_irq
|
s_apu_irq_raw, s_jpeg_irq_raw, spisd.irq_o, sdio1.irq_o, sdio0.irq_o, s_usb2_irq, s_dma_irq
|
||||||
};
|
};
|
||||||
|
|
||||||
apb4_async_bridge u_psram_cfg_mem_cdc (
|
apb4_async_bridge u_psram_cfg_mem_cdc (
|
||||||
@@ -281,16 +287,17 @@ axi4_stream_if #(
|
|||||||
assign s_opipsram_irq_mem = u_opipsram_mem_if.irq_o;
|
assign s_opipsram_irq_mem = u_opipsram_mem_if.irq_o;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
s_hp_plic_source = '0;
|
s_hp_plic_source = '0;
|
||||||
s_hp_plic_source[1] = uart1.irq_o;
|
s_hp_plic_source[1] = uart1.irq_o;
|
||||||
s_hp_plic_source[2] = s_mailbox_hp_irq;
|
s_hp_plic_source[2] = s_mailbox_hp_irq;
|
||||||
s_hp_plic_source[3] = ext_h_hp_irq_i;
|
s_hp_plic_source[3] = ext_h_hp_irq_i;
|
||||||
s_hp_plic_source[4] = resource_irq_hp_i[0];
|
s_hp_plic_source[4] = resource_irq_hp_i[0];
|
||||||
s_hp_plic_source[5] = resource_irq_hp_i[1];
|
s_hp_plic_source[5] = resource_irq_hp_i[1];
|
||||||
s_hp_plic_source[6] = resource_irq_hp_i[2];
|
s_hp_plic_source[6] = resource_irq_hp_i[2];
|
||||||
s_hp_plic_source[7] = resource_irq_hp_i[3];
|
s_hp_plic_source[7] = resource_irq_hp_i[3];
|
||||||
s_hp_plic_source[8] = resource_irq_hp_i[4];
|
s_hp_plic_source[8] = resource_irq_hp_i[4];
|
||||||
s_hp_plic_source[9] = resource_irq_hp_i[5];
|
s_hp_plic_source[9] = resource_irq_hp_i[5];
|
||||||
|
s_hp_plic_source[10] = resource_irq_hp_i[6];
|
||||||
end
|
end
|
||||||
|
|
||||||
`include "apb4_periph_irq_bindings.svh"
|
`include "apb4_periph_irq_bindings.svh"
|
||||||
@@ -469,6 +476,18 @@ axi4_stream_if #(
|
|||||||
.irq_o (s_jpeg_irq_raw)
|
.irq_o (s_jpeg_irq_raw)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
apb4_apu u_apb4_apu (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.owner_i (apu_owner_i),
|
||||||
|
.owner_lock_i (apu_owner_lock_i),
|
||||||
|
.quiesce_i (apu_quiesce_i),
|
||||||
|
.resource_reset_i(apu_reset_i),
|
||||||
|
.apb4 (u_apu_apb4_if),
|
||||||
|
.idle_o (apu_idle_o),
|
||||||
|
.irq_o (s_apu_irq_raw)
|
||||||
|
);
|
||||||
|
|
||||||
apb4_sysctrl u_apb4_sysctrl (
|
apb4_sysctrl u_apb4_sysctrl (
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_n_i (rst_n_i),
|
.rst_n_i (rst_n_i),
|
||||||
|
|||||||
+30
-26
@@ -23,9 +23,9 @@ module apb4_system (
|
|||||||
input logic rst_aud_n_i,
|
input logic rst_aud_n_i,
|
||||||
input logic debug_halted_i,
|
input logic debug_halted_i,
|
||||||
input logic ext_h_data_idle_i,
|
input logic ext_h_data_idle_i,
|
||||||
input logic [6:0] resource_idle_i,
|
input logic [7:0] resource_idle_i,
|
||||||
input logic [6:0] resource_block_ack_i,
|
input logic [7:0] resource_block_ack_i,
|
||||||
input logic [5:0] resource_irq_i,
|
input logic [6:0] resource_irq_i,
|
||||||
input logic cache_request_i,
|
input logic cache_request_i,
|
||||||
axi4_if.slave axi4,
|
axi4_if.slave axi4,
|
||||||
axi4_if.master ext_h_axi4,
|
axi4_if.master ext_h_axi4,
|
||||||
@@ -45,11 +45,12 @@ module apb4_system (
|
|||||||
output logic ext_h_irq_raw_o,
|
output logic ext_h_irq_raw_o,
|
||||||
output logic [1:0] ext_h_owner_o,
|
output logic [1:0] ext_h_owner_o,
|
||||||
output logic cache_clean_o,
|
output logic cache_clean_o,
|
||||||
output logic [6:0][1:0] resource_owner_o,
|
output logic [7:0][1:0] resource_owner_o,
|
||||||
output logic [6:0] resource_quiesce_o,
|
output logic [7:0] resource_owner_lock_o,
|
||||||
output logic [6:0] resource_reset_o,
|
output logic [7:0] resource_quiesce_o,
|
||||||
output logic [5:0] resource_irq_lp_o,
|
output logic [7:0] resource_reset_o,
|
||||||
output logic [5:0] resource_irq_hp_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
|
output logic [`SOC_IRQ_APB4_SYSTEM_WIDTH-1:0] irq_o
|
||||||
// verilog_format: on
|
// verilog_format: on
|
||||||
);
|
);
|
||||||
@@ -97,12 +98,13 @@ module apb4_system (
|
|||||||
logic s_ext_h_irq;
|
logic s_ext_h_irq;
|
||||||
logic s_ext_h_irq_raw;
|
logic s_ext_h_irq_raw;
|
||||||
logic [ 1:0] unused_ext_h_owner;
|
logic [ 1:0] unused_ext_h_owner;
|
||||||
logic [ 6:0] s_resource_irq;
|
logic [ 7:0] s_resource_irq;
|
||||||
logic [ 6:0] s_resource_irq_lp;
|
logic [ 7:0] s_resource_irq_lp;
|
||||||
logic [ 6:0] s_resource_irq_hp;
|
logic [ 7:0] s_resource_irq_hp;
|
||||||
logic [ 6:0][1:0] s_resource_owner;
|
logic [ 7:0][1:0] s_resource_owner;
|
||||||
logic [ 6:0] s_resource_quiesce;
|
logic [ 7:0] s_resource_owner_lock;
|
||||||
logic [ 6:0] s_resource_reset;
|
logic [ 7:0] s_resource_quiesce;
|
||||||
|
logic [ 7:0] s_resource_reset;
|
||||||
logic s_resource_fault_irq;
|
logic s_resource_fault_irq;
|
||||||
logic s_cache_clean;
|
logic s_cache_clean;
|
||||||
logic s_unused_resource;
|
logic s_unused_resource;
|
||||||
@@ -110,16 +112,17 @@ module apb4_system (
|
|||||||
logic s_unused_product_input;
|
logic s_unused_product_input;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
assign s_resource_irq = {resource_irq_i[5], s_ext_h_irq_raw, resource_irq_i[4:0]};
|
assign s_resource_irq = {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 s_ext_h_irq = s_resource_irq_lp[5];
|
||||||
assign ext_h_irq_raw_o = s_ext_h_irq_raw;
|
assign ext_h_irq_raw_o = s_ext_h_irq_raw;
|
||||||
assign ext_h_owner_o = s_resource_owner[5];
|
assign ext_h_owner_o = s_resource_owner[5];
|
||||||
assign cache_clean_o = s_cache_clean;
|
assign cache_clean_o = s_cache_clean;
|
||||||
assign resource_owner_o = s_resource_owner;
|
assign resource_owner_o = s_resource_owner;
|
||||||
assign resource_quiesce_o = s_resource_quiesce;
|
assign resource_owner_lock_o = s_resource_owner_lock;
|
||||||
assign resource_reset_o = s_resource_reset;
|
assign resource_quiesce_o = s_resource_quiesce;
|
||||||
assign resource_irq_lp_o = {s_resource_irq_lp[6], s_resource_irq_lp[4:0]};
|
assign resource_reset_o = s_resource_reset;
|
||||||
assign resource_irq_hp_o = {s_resource_irq_hp[6], s_resource_irq_hp[4:0]};
|
assign resource_irq_lp_o = {s_resource_irq_lp[7:6], s_resource_irq_lp[4:0]};
|
||||||
|
assign resource_irq_hp_o = {s_resource_irq_hp[7:6], s_resource_irq_hp[4:0]};
|
||||||
|
|
||||||
`ifdef PDK_IHP130
|
`ifdef PDK_IHP130
|
||||||
localparam logic [31:0] ARCHINFO_TECHNOLOGY = 32'h0201_0082;
|
localparam logic [31:0] ARCHINFO_TECHNOLOGY = 32'h0201_0082;
|
||||||
@@ -231,7 +234,7 @@ module apb4_system (
|
|||||||
apb4_crc u_apb4_crc (.apb4(u_crc_apb4_if));
|
apb4_crc u_apb4_crc (.apb4(u_crc_apb4_if));
|
||||||
|
|
||||||
resource_controller #(
|
resource_controller #(
|
||||||
.ResourceCount(7)
|
.ResourceCount(8)
|
||||||
) u_resource_controller (
|
) u_resource_controller (
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_n_i (rst_n_i),
|
.rst_n_i (rst_n_i),
|
||||||
@@ -241,6 +244,7 @@ module apb4_system (
|
|||||||
.cache_request_i(cache_request_i),
|
.cache_request_i(cache_request_i),
|
||||||
.cache_clean_o (s_cache_clean),
|
.cache_clean_o (s_cache_clean),
|
||||||
.owner_o (s_resource_owner),
|
.owner_o (s_resource_owner),
|
||||||
|
.owner_lock_o (s_resource_owner_lock),
|
||||||
.quiesce_o (s_resource_quiesce),
|
.quiesce_o (s_resource_quiesce),
|
||||||
.reset_o (s_resource_reset),
|
.reset_o (s_resource_reset),
|
||||||
.irq_lp_o (s_resource_irq_lp),
|
.irq_lp_o (s_resource_irq_lp),
|
||||||
@@ -297,6 +301,6 @@ axi42apb4_system u_axi42apb4_system (
|
|||||||
.ext_h_timeout_o (ext_h_timeout_o)
|
.ext_h_timeout_o (ext_h_timeout_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign s_unused_resource = ^unused_ext_h_owner;
|
assign s_unused_resource = ^{unused_ext_h_owner, s_resource_irq_hp[5]};
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
@@ -433,6 +433,13 @@ module axi4_interconnect #(
|
|||||||
automatic logic [32:0] wrap_base = {1'b0, addr} & ~(burst_bytes - 1'b1);
|
automatic logic [32:0] wrap_base = {1'b0, addr} & ~(burst_bytes - 1'b1);
|
||||||
automatic
|
automatic
|
||||||
logic
|
logic
|
||||||
|
apu_lp_only =
|
||||||
|
`SOC_ADDR_IS_APB4_APU(addr)
|
||||||
|
&& (((addr[11:0] >= 12'h040) && (addr[11:0] <= 12'h04c)) ||
|
||||||
|
((addr[11:0] >= 12'h080) && (addr[11:0] <= 12'h088)) ||
|
||||||
|
((addr[11:0] >= 12'h200) && (addr[11:0] <= 12'h208)));
|
||||||
|
automatic
|
||||||
|
logic
|
||||||
burst_legal =
|
burst_legal =
|
||||||
(burst == `AXI4_BURST_TYPE_FIXED) ||
|
(burst == `AXI4_BURST_TYPE_FIXED) ||
|
||||||
(burst == `AXI4_BURST_TYPE_INCR) ||
|
(burst == `AXI4_BURST_TYPE_INCR) ||
|
||||||
@@ -465,7 +472,7 @@ module axi4_interconnect #(
|
|||||||
`SOC_ADDR_IS_APB4_EXT_H(addr)
|
`SOC_ADDR_IS_APB4_EXT_H(addr)
|
||||||
&& !
|
&& !
|
||||||
`SOC_ADDR_IS_APB4_RESOURCE_CTRL(addr)
|
`SOC_ADDR_IS_APB4_RESOURCE_CTRL(addr)
|
||||||
);
|
&& !apu_lp_only);
|
||||||
`else
|
`else
|
||||||
s_access_allowed[master] = (master != 1) || ((read_req &&
|
s_access_allowed[master] = (master != 1) || ((read_req &&
|
||||||
`SOC_USER_ADDR_READABLE(addr)
|
`SOC_USER_ADDR_READABLE(addr)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: MulanPSL-2.0
|
// SPDX-License-Identifier: MulanPSL-2.0
|
||||||
|
|
||||||
module resource_controller #(
|
module resource_controller #(
|
||||||
parameter int unsigned ResourceCount = 6
|
parameter int unsigned ResourceCount = 8
|
||||||
) (
|
) (
|
||||||
// verilog_format: off -- preserve the resource ownership boundary columns
|
// verilog_format: off -- preserve the resource ownership boundary columns
|
||||||
input logic clk_i,
|
input logic clk_i,
|
||||||
@@ -13,6 +13,7 @@ module resource_controller #(
|
|||||||
input logic cache_request_i,
|
input logic cache_request_i,
|
||||||
output logic cache_clean_o,
|
output logic cache_clean_o,
|
||||||
output logic [ResourceCount-1:0][1:0] owner_o,
|
output logic [ResourceCount-1:0][1:0] owner_o,
|
||||||
|
output logic [ResourceCount-1:0] owner_lock_o,
|
||||||
output logic [ResourceCount-1:0] quiesce_o,
|
output logic [ResourceCount-1:0] quiesce_o,
|
||||||
output logic [ResourceCount-1:0] reset_o,
|
output logic [ResourceCount-1:0] reset_o,
|
||||||
output logic [ResourceCount-1:0] irq_lp_o,
|
output logic [ResourceCount-1:0] irq_lp_o,
|
||||||
@@ -69,6 +70,7 @@ module resource_controller #(
|
|||||||
assign apb4.pslverr = s_resp_err_q;
|
assign apb4.pslverr = s_resp_err_q;
|
||||||
assign apb4.prdata = s_rdata_q;
|
assign apb4.prdata = s_rdata_q;
|
||||||
assign owner_o = s_owner_q;
|
assign owner_o = s_owner_q;
|
||||||
|
assign owner_lock_o = s_owner_lock_q;
|
||||||
assign quiesce_o = s_quiesce_q;
|
assign quiesce_o = s_quiesce_q;
|
||||||
assign reset_o = s_reset_q;
|
assign reset_o = s_reset_q;
|
||||||
assign cache_clean_o = s_cache_clean_q;
|
assign cache_clean_o = s_cache_clean_q;
|
||||||
|
|||||||
+57
-43
@@ -232,18 +232,21 @@ module retrosoc (
|
|||||||
logic [31:0] s_ext_h_timeout;
|
logic [31:0] s_ext_h_timeout;
|
||||||
logic s_ext_h_irq_raw;
|
logic s_ext_h_irq_raw;
|
||||||
logic [ 1:0] s_ext_h_owner;
|
logic [ 1:0] s_ext_h_owner;
|
||||||
logic [ 6:0][1:0] s_resource_owner;
|
logic [ 7:0][1:0] s_resource_owner;
|
||||||
logic [ 6:0] s_resource_quiesce;
|
logic [ 7:0] s_resource_owner_lock;
|
||||||
logic [ 6:0] s_resource_reset;
|
logic [ 7:0] s_resource_quiesce;
|
||||||
|
logic [ 7:0] s_resource_reset;
|
||||||
logic [ 6:0] s_resource_idle_hp;
|
logic [ 6:0] s_resource_idle_hp;
|
||||||
logic [ 6:0] s_resource_idle_pclk;
|
logic [ 6:0] s_resource_idle_pclk;
|
||||||
logic [ 6:0] s_resource_block_ack_hp;
|
logic [ 6:0] s_resource_block_ack_hp;
|
||||||
logic [ 6:0] s_resource_block_ack_pclk;
|
logic [ 6:0] s_resource_block_ack_pclk;
|
||||||
logic [ 5:0] s_resource_irq_raw;
|
logic [ 6:0] s_resource_irq_raw;
|
||||||
logic [ 5:0] s_resource_irq_lp;
|
logic [ 6:0] s_resource_irq_lp;
|
||||||
logic [ 5:0] s_resource_irq_hp;
|
logic [ 6:0] s_resource_irq_hp;
|
||||||
|
logic s_apu_idle;
|
||||||
logic s_jpeg_idle;
|
logic s_jpeg_idle;
|
||||||
logic [ 6:0] s_resource_idle_combined;
|
logic [ 7:0] s_resource_idle_combined;
|
||||||
|
logic [ 7:0] s_resource_block_ack_combined;
|
||||||
logic [31:0] s_fault_addr_mux;
|
logic [31:0] s_fault_addr_mux;
|
||||||
logic [ 3:0] s_fault_wstrb_mux;
|
logic [ 3:0] s_fault_wstrb_mux;
|
||||||
logic s_fault_reserved_mux;
|
logic s_fault_reserved_mux;
|
||||||
@@ -555,7 +558,7 @@ core_wrapper u_core_wrapper (
|
|||||||
.block_new_i (s_hp_block_hp),
|
.block_new_i (s_hp_block_hp),
|
||||||
.recovery_i (s_hp_recovery_hp),
|
.recovery_i (s_hp_recovery_hp),
|
||||||
.flush_i (s_hp_flush_hp),
|
.flush_i (s_hp_flush_hp),
|
||||||
.resource_block_i (s_resource_quiesce | s_resource_reset),
|
.resource_block_i (s_resource_quiesce[6:0] | s_resource_reset[6:0]),
|
||||||
.mem_pad_mode_i (s_mem_pad_mode_lp),
|
.mem_pad_mode_i (s_mem_pad_mode_lp),
|
||||||
.ext_h_block_i (s_ext_h_block),
|
.ext_h_block_i (s_ext_h_block),
|
||||||
.ext_h_read_base_i (s_ext_h_read_base),
|
.ext_h_read_base_i (s_ext_h_read_base),
|
||||||
@@ -797,6 +800,10 @@ core_wrapper u_core_wrapper (
|
|||||||
.ext_h_hp_irq_i ((s_ext_h_owner == 2'd1) ? s_ext_h_irq_raw : 1'b0),
|
.ext_h_hp_irq_i ((s_ext_h_owner == 2'd1) ? s_ext_h_irq_raw : 1'b0),
|
||||||
.resource_irq_lp_i (s_resource_irq_lp),
|
.resource_irq_lp_i (s_resource_irq_lp),
|
||||||
.resource_irq_hp_i (s_resource_irq_hp),
|
.resource_irq_hp_i (s_resource_irq_hp),
|
||||||
|
.apu_owner_i (s_resource_owner[7]),
|
||||||
|
.apu_owner_lock_i (s_resource_owner_lock[7]),
|
||||||
|
.apu_quiesce_i (s_resource_quiesce[7]),
|
||||||
|
.apu_reset_i (s_resource_reset[7]),
|
||||||
.jpeg_quiesce_i (s_resource_quiesce[6]),
|
.jpeg_quiesce_i (s_resource_quiesce[6]),
|
||||||
.jpeg_reset_i (s_resource_reset[6]),
|
.jpeg_reset_i (s_resource_reset[6]),
|
||||||
.cfg_axi4 (u_cfg_pclk_axi4_if),
|
.cfg_axi4 (u_cfg_pclk_axi4_if),
|
||||||
@@ -840,6 +847,7 @@ core_wrapper u_core_wrapper (
|
|||||||
.hp_machine_external_irq_o (s_hp_machine_external_irq),
|
.hp_machine_external_irq_o (s_hp_machine_external_irq),
|
||||||
.hp_supervisor_external_irq_o(s_hp_supervisor_external_irq),
|
.hp_supervisor_external_irq_o(s_hp_supervisor_external_irq),
|
||||||
.resource_irq_raw_o (s_resource_irq_raw),
|
.resource_irq_raw_o (s_resource_irq_raw),
|
||||||
|
.apu_idle_o (s_apu_idle),
|
||||||
.jpeg_idle_o (s_jpeg_idle),
|
.jpeg_idle_o (s_jpeg_idle),
|
||||||
.irq_o (s_apb4_periph_irq)
|
.irq_o (s_apb4_periph_irq)
|
||||||
);
|
);
|
||||||
@@ -853,49 +861,54 @@ core_wrapper u_core_wrapper (
|
|||||||
);
|
);
|
||||||
|
|
||||||
apb4_system u_apb4_system (
|
apb4_system u_apb4_system (
|
||||||
.clk_i (clk_pclk_i),
|
.clk_i (clk_pclk_i),
|
||||||
.rst_n_i (rst_pclk_n_i),
|
.rst_n_i (rst_pclk_n_i),
|
||||||
.clk_aud_i (clk_aud_i),
|
.clk_aud_i (clk_aud_i),
|
||||||
.rst_aud_n_i (rst_aud_n_i),
|
.rst_aud_n_i (rst_aud_n_i),
|
||||||
.debug_halted_i (s_mgmt_debug_halted),
|
.debug_halted_i (s_mgmt_debug_halted),
|
||||||
.ext_h_data_idle_i (s_ext_h_data_idle),
|
.ext_h_data_idle_i (s_ext_h_data_idle),
|
||||||
.resource_idle_i (s_resource_idle_combined),
|
.resource_idle_i (s_resource_idle_combined),
|
||||||
.resource_block_ack_i(s_resource_block_ack_pclk),
|
.resource_block_ack_i (s_resource_block_ack_combined),
|
||||||
.resource_irq_i (s_resource_irq_raw),
|
.resource_irq_i (s_resource_irq_raw),
|
||||||
.cache_request_i (s_hp_cache_req_pclk),
|
.cache_request_i (s_hp_cache_req_pclk),
|
||||||
.ext_h_axi4 (u_ext_h_wide_axi4_if),
|
.ext_h_axi4 (u_ext_h_wide_axi4_if),
|
||||||
.fabric_monitor (u_fabric_monitor_pclk_if),
|
.fabric_monitor (u_fabric_monitor_pclk_if),
|
||||||
.axi4 (u_system_pclk_axi4_if),
|
.axi4 (u_system_pclk_axi4_if),
|
||||||
.pwm (u_pwm_if),
|
.pwm (u_pwm_if),
|
||||||
.ps2 (u_ps2_if),
|
.ps2 (u_ps2_if),
|
||||||
.ip_sel_i (u_sysctrl_if.ip_sel_o),
|
.ip_sel_i (u_sysctrl_if.ip_sel_o),
|
||||||
.user_gpio (u_user_gpio_if),
|
.user_gpio (u_user_gpio_if),
|
||||||
.rtc_wake_o (s_rtc_wake),
|
.rtc_wake_o (s_rtc_wake),
|
||||||
.wdg_reset_req_o (wdg_reset_req_o),
|
.wdg_reset_req_o (wdg_reset_req_o),
|
||||||
.ext_h_block_o (s_ext_h_block),
|
.ext_h_block_o (s_ext_h_block),
|
||||||
.ext_h_read_base_o (s_ext_h_read_base),
|
.ext_h_read_base_o (s_ext_h_read_base),
|
||||||
.ext_h_read_limit_o (s_ext_h_read_limit),
|
.ext_h_read_limit_o (s_ext_h_read_limit),
|
||||||
.ext_h_write_base_o (s_ext_h_write_base),
|
.ext_h_write_base_o (s_ext_h_write_base),
|
||||||
.ext_h_write_limit_o (s_ext_h_write_limit),
|
.ext_h_write_limit_o (s_ext_h_write_limit),
|
||||||
.ext_h_timeout_o (s_ext_h_timeout),
|
.ext_h_timeout_o (s_ext_h_timeout),
|
||||||
.ext_h_irq_raw_o (s_ext_h_irq_raw),
|
.ext_h_irq_raw_o (s_ext_h_irq_raw),
|
||||||
.ext_h_owner_o (s_ext_h_owner),
|
.ext_h_owner_o (s_ext_h_owner),
|
||||||
.cache_clean_o (s_hp_cache_clean_pclk),
|
.cache_clean_o (s_hp_cache_clean_pclk),
|
||||||
.resource_owner_o (s_resource_owner),
|
.resource_owner_o (s_resource_owner),
|
||||||
.resource_quiesce_o (s_resource_quiesce),
|
.resource_owner_lock_o(s_resource_owner_lock),
|
||||||
.resource_reset_o (s_resource_reset),
|
.resource_quiesce_o (s_resource_quiesce),
|
||||||
.resource_irq_lp_o (s_resource_irq_lp),
|
.resource_reset_o (s_resource_reset),
|
||||||
.resource_irq_hp_o (s_resource_irq_hp),
|
.resource_irq_lp_o (s_resource_irq_lp),
|
||||||
.irq_o (s_apb4_system_irq)
|
.resource_irq_hp_o (s_resource_irq_hp),
|
||||||
|
.irq_o (s_apb4_system_irq)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign s_resource_idle_combined = {
|
assign s_resource_idle_combined = {
|
||||||
|
s_apu_idle,
|
||||||
s_jpeg_idle && s_resource_idle_pclk[6],
|
s_jpeg_idle && s_resource_idle_pclk[6],
|
||||||
s_ext_h_data_idle && s_resource_idle_pclk[5],
|
s_ext_h_data_idle && s_resource_idle_pclk[5],
|
||||||
s_resource_idle_pclk[4:0]
|
s_resource_idle_pclk[4:0]
|
||||||
};
|
};
|
||||||
|
assign s_resource_block_ack_combined = {
|
||||||
|
s_apu_idle && (s_resource_quiesce[7] || s_resource_reset[7]), s_resource_block_ack_pclk
|
||||||
|
};
|
||||||
|
|
||||||
logic [35:0] s_unused_domain_inputs;
|
logic [36:0] s_unused_domain_inputs;
|
||||||
assign s_unused_domain_inputs = {
|
assign s_unused_domain_inputs = {
|
||||||
clk_pclk_i,
|
clk_pclk_i,
|
||||||
rst_pclk_n_i,
|
rst_pclk_n_i,
|
||||||
@@ -910,6 +923,7 @@ core_wrapper u_core_wrapper (
|
|||||||
s_hp_lifecycle_draining,
|
s_hp_lifecycle_draining,
|
||||||
s_hp_lifecycle_fault,
|
s_hp_lifecycle_fault,
|
||||||
^s_resource_owner,
|
^s_resource_owner,
|
||||||
|
^s_resource_owner_lock,
|
||||||
^s_resource_quiesce,
|
^s_resource_quiesce,
|
||||||
^s_resource_reset,
|
^s_resource_reset,
|
||||||
^unused_cdc_clear_busy,
|
^unused_cdc_clear_busy,
|
||||||
|
|||||||
@@ -133,7 +133,10 @@
|
|||||||
"sdram_reg.sv"
|
"sdram_reg.sv"
|
||||||
],
|
],
|
||||||
"rtl/ip/multimedia": [
|
"rtl/ip/multimedia": [
|
||||||
|
"apb4_apu.sv",
|
||||||
"apb4_jpeg.sv",
|
"apb4_jpeg.sv",
|
||||||
|
"apu_define.svh",
|
||||||
|
"apu_reg.sv",
|
||||||
"axi4s_dvp.sv",
|
"axi4s_dvp.sv",
|
||||||
"dvp_core.sv",
|
"dvp_core.sv",
|
||||||
"dvp_define.svh",
|
"dvp_define.svh",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ TEST_SOURCES = (
|
|||||||
"crt/src/hal/i2s_math.c",
|
"crt/src/hal/i2s_math.c",
|
||||||
"crt/src/hal/dma_math.c",
|
"crt/src/hal/dma_math.c",
|
||||||
"crt/src/hal/jpeg_math.c",
|
"crt/src/hal/jpeg_math.c",
|
||||||
|
"crt/src/hal/apu.c",
|
||||||
"crt/src/hal/sysctrl.c",
|
"crt/src/hal/sysctrl.c",
|
||||||
"crt/src/hal/clock.c",
|
"crt/src/hal/clock.c",
|
||||||
"crt/src/hal/resource.c",
|
"crt/src/hal/resource.c",
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ tooling.
|
|||||||
APB4 simulations; `test_crypto_register_parity.py` checks the handwritten
|
APB4 simulations; `test_crypto_register_parity.py` checks the handwritten
|
||||||
RTL/C register ABI and `test_dma.py` covers DMA bursts, TCD fetch, CRC,
|
RTL/C register ABI and `test_dma.py` covers DMA bursts, TCD fetch, CRC,
|
||||||
tail-byte writes, and crypto endpoints.
|
tail-byte writes, and crypto endpoints.
|
||||||
|
- `test_apu.py` checks the complete fail-closed APU-P1 APB4 register matrix and
|
||||||
|
integrated LP/HP IRQ ownership topology; `test_apu_register_parity.py` keeps
|
||||||
|
its handwritten RTL/C ABI and matrix coverage synchronized.
|
||||||
- `test_user_ip_register_parity.py` keeps the integrated slot 1 timer and slot
|
- `test_user_ip_register_parity.py` keeps the integrated slot 1 timer and slot
|
||||||
2 GPIO register offsets synchronized with their application-owned C
|
2 GPIO register offsets synchronized with their application-owned C
|
||||||
definitions and checks their extension-manifest slot assignments.
|
definitions and checks their extension-manifest slot assignments.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <retrosoc/core/status.h>
|
#include <retrosoc/core/status.h>
|
||||||
#include <retrosoc/core/wait.h>
|
#include <retrosoc/core/wait.h>
|
||||||
|
#include <retrosoc/hal/apu.h>
|
||||||
#include <retrosoc/hal/gpio.h>
|
#include <retrosoc/hal/gpio.h>
|
||||||
#include <retrosoc/hal/clock.h>
|
#include <retrosoc/hal/clock.h>
|
||||||
#include <retrosoc/hal/extension.h>
|
#include <retrosoc/hal/extension.h>
|
||||||
@@ -864,6 +865,10 @@ static int test_resource_validation(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_apu_validation(void) {
|
||||||
|
return (rs_apu_probe(NULL) == RS_EINVAL) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_jpeg_validation(void) {
|
static int test_jpeg_validation(void) {
|
||||||
static _Alignas(RS_JPEG_DESCRIPTOR_ALIGNMENT) rs_jpeg_descriptor_t ring[2];
|
static _Alignas(RS_JPEG_DESCRIPTOR_ALIGNMENT) rs_jpeg_descriptor_t ring[2];
|
||||||
rs_jpeg_descriptor_t descriptor;
|
rs_jpeg_descriptor_t descriptor;
|
||||||
@@ -1016,6 +1021,7 @@ int main(void) {
|
|||||||
test_user_ip_validation(),
|
test_user_ip_validation(),
|
||||||
test_extension_validation(),
|
test_extension_validation(),
|
||||||
test_resource_validation(),
|
test_resource_validation(),
|
||||||
|
test_apu_validation(),
|
||||||
test_jpeg_validation(),
|
test_jpeg_validation(),
|
||||||
test_ps2_decoders(),
|
test_ps2_decoders(),
|
||||||
test_wav_parser(),
|
test_wav_parser(),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module apb4_topology_tb;
|
|||||||
begin
|
begin
|
||||||
s_decode_addr = address;
|
s_decode_addr = address;
|
||||||
#1;
|
#1;
|
||||||
if (s_psel_comb !== (20'd1 << slot)) begin
|
if (s_psel_comb !== (28'd1 << slot)) begin
|
||||||
$fatal(1, "unexpected APB4 target slot for %h: got %b", address, s_psel_comb);
|
$fatal(1, "unexpected APB4 target slot for %h: got %b", address, s_psel_comb);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -44,7 +44,7 @@ module apb4_topology_tb;
|
|||||||
expect_select(`SOC_ADDR_APB4_SDIO1_BASE, 18);
|
expect_select(`SOC_ADDR_APB4_SDIO1_BASE, 18);
|
||||||
expect_select(`SOC_ADDR_APB4_CRYPTO_BASE, 19);
|
expect_select(`SOC_ADDR_APB4_CRYPTO_BASE, 19);
|
||||||
expect_disabled(`SOC_ADDR_APB4_GA_BASE);
|
expect_disabled(`SOC_ADDR_APB4_GA_BASE);
|
||||||
expect_disabled(`SOC_ADDR_APB4_APU_BASE);
|
expect_select(`SOC_ADDR_APB4_APU_BASE, 27);
|
||||||
$display("SoC topology APB4 routing test passed");
|
$display("SoC topology APB4 routing test passed");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,271 @@
|
|||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
`include "apu_define.svh"
|
||||||
|
`include "soc_irq_config.svh"
|
||||||
|
|
||||||
|
module apu_irq_topology_tb;
|
||||||
|
localparam logic [31:0] ApuBase = 32'h1001_3000;
|
||||||
|
localparam logic [11:0] Resource7Owner = 12'h1e0;
|
||||||
|
localparam logic [11:0] Resource7Control = 12'h1e4;
|
||||||
|
localparam logic [11:0] Resource7Fault = 12'h1ec;
|
||||||
|
|
||||||
|
logic clk_i = 1'b0;
|
||||||
|
logic rst_n_i = 1'b0;
|
||||||
|
logic s_apu_idle;
|
||||||
|
logic s_apu_irq_raw;
|
||||||
|
logic [ 7:0] s_resource_idle;
|
||||||
|
logic [ 7:0] s_resource_block_ack;
|
||||||
|
logic [ 7:0] s_resource_irq_raw;
|
||||||
|
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_irq_lp;
|
||||||
|
logic [ 7:0] s_resource_irq_hp;
|
||||||
|
logic [ 6:0] s_resource_irq_lp_compact;
|
||||||
|
logic [ 6:0] s_resource_irq_hp_compact;
|
||||||
|
logic s_resource_fault_irq;
|
||||||
|
logic s_cache_clean;
|
||||||
|
logic [`SOC_IRQ_APB4_PERIPH_WIDTH-1:0] s_apb4_periph_irq;
|
||||||
|
logic [`SOC_IRQ_APB4_SYSTEM_WIDTH-1:0] s_apb4_system_irq;
|
||||||
|
logic [ `SOC_IRQ_VECTOR_WIDTH-1:0] s_irq;
|
||||||
|
logic [ 31:0] s_hp_plic_source;
|
||||||
|
logic [ 1:0] s_hp_plic_context_irq;
|
||||||
|
logic [ 31:0] s_value;
|
||||||
|
|
||||||
|
apb4_if u_apu_apb4_if (
|
||||||
|
.pclk (clk_i),
|
||||||
|
.presetn(rst_n_i)
|
||||||
|
);
|
||||||
|
apb4_if u_resource_apb4_if (
|
||||||
|
.pclk (clk_i),
|
||||||
|
.presetn(rst_n_i)
|
||||||
|
);
|
||||||
|
apb4_if u_plic_apb4_if (
|
||||||
|
.pclk (clk_i),
|
||||||
|
.presetn(rst_n_i)
|
||||||
|
);
|
||||||
|
|
||||||
|
always #5 clk_i = ~clk_i;
|
||||||
|
|
||||||
|
assign s_resource_idle = {s_apu_idle, 7'h7f};
|
||||||
|
assign s_resource_block_ack = {
|
||||||
|
s_apu_idle && (s_resource_quiesce[7] || s_resource_reset[7]), 7'd0
|
||||||
|
};
|
||||||
|
assign s_resource_irq_raw = {s_apu_irq_raw, 7'd0};
|
||||||
|
assign s_resource_irq_lp_compact = {s_resource_irq_lp[7:6], s_resource_irq_lp[4:0]};
|
||||||
|
assign s_resource_irq_hp_compact = {s_resource_irq_hp[7:6], s_resource_irq_hp[4:0]};
|
||||||
|
assign s_apb4_periph_irq = {s_resource_irq_lp_compact[6], 23'd0};
|
||||||
|
assign s_apb4_system_irq = '0;
|
||||||
|
assign s_hp_plic_source = {21'd0, s_resource_irq_hp_compact[6], 10'd0};
|
||||||
|
|
||||||
|
`include "soc_irq_wiring.svh"
|
||||||
|
|
||||||
|
apb4_apu u_apu (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.owner_i (s_resource_owner[7]),
|
||||||
|
.owner_lock_i (s_resource_owner_lock[7]),
|
||||||
|
.quiesce_i (s_resource_quiesce[7]),
|
||||||
|
.resource_reset_i(s_resource_reset[7]),
|
||||||
|
.apb4 (u_apu_apb4_if),
|
||||||
|
.idle_o (s_apu_idle),
|
||||||
|
.irq_o (s_apu_irq_raw)
|
||||||
|
);
|
||||||
|
|
||||||
|
resource_controller #(
|
||||||
|
.ResourceCount(8)
|
||||||
|
) u_resource_controller (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.idle_i (s_resource_idle),
|
||||||
|
.block_ack_i (s_resource_block_ack),
|
||||||
|
.irq_i (s_resource_irq_raw),
|
||||||
|
.cache_request_i(1'b0),
|
||||||
|
.cache_clean_o (s_cache_clean),
|
||||||
|
.owner_o (s_resource_owner),
|
||||||
|
.owner_lock_o (s_resource_owner_lock),
|
||||||
|
.quiesce_o (s_resource_quiesce),
|
||||||
|
.reset_o (s_resource_reset),
|
||||||
|
.irq_lp_o (s_resource_irq_lp),
|
||||||
|
.irq_hp_o (s_resource_irq_hp),
|
||||||
|
.fault_irq_o (s_resource_fault_irq),
|
||||||
|
.apb4 (u_resource_apb4_if)
|
||||||
|
);
|
||||||
|
|
||||||
|
apb4_plic u_hp_plic (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.source_i (s_hp_plic_source),
|
||||||
|
.apb4 (u_plic_apb4_if),
|
||||||
|
.context_irq_o(s_hp_plic_context_irq)
|
||||||
|
);
|
||||||
|
|
||||||
|
task automatic drive_apb_idle;
|
||||||
|
begin
|
||||||
|
u_apu_apb4_if.paddr = 32'd0;
|
||||||
|
u_apu_apb4_if.pprot = 3'd0;
|
||||||
|
u_apu_apb4_if.psel = 1'b0;
|
||||||
|
u_apu_apb4_if.penable = 1'b0;
|
||||||
|
u_apu_apb4_if.pwrite = 1'b0;
|
||||||
|
u_apu_apb4_if.pwdata = 32'd0;
|
||||||
|
u_apu_apb4_if.pstrb = 4'd0;
|
||||||
|
u_resource_apb4_if.paddr = 32'd0;
|
||||||
|
u_resource_apb4_if.pprot = 3'd0;
|
||||||
|
u_resource_apb4_if.psel = 1'b0;
|
||||||
|
u_resource_apb4_if.penable = 1'b0;
|
||||||
|
u_resource_apb4_if.pwrite = 1'b0;
|
||||||
|
u_resource_apb4_if.pwdata = 32'd0;
|
||||||
|
u_resource_apb4_if.pstrb = 4'd0;
|
||||||
|
u_plic_apb4_if.paddr = 32'd0;
|
||||||
|
u_plic_apb4_if.pprot = 3'd0;
|
||||||
|
u_plic_apb4_if.psel = 1'b0;
|
||||||
|
u_plic_apb4_if.penable = 1'b0;
|
||||||
|
u_plic_apb4_if.pwrite = 1'b0;
|
||||||
|
u_plic_apb4_if.pwdata = 32'd0;
|
||||||
|
u_plic_apb4_if.pstrb = 4'd0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic apu_write(input logic [11:0] offset_i, input logic [31:0] data_i);
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_apu_apb4_if.paddr = ApuBase + offset_i;
|
||||||
|
u_apu_apb4_if.pwdata = data_i;
|
||||||
|
u_apu_apb4_if.pstrb = 4'hf;
|
||||||
|
u_apu_apb4_if.pwrite = 1'b1;
|
||||||
|
u_apu_apb4_if.psel = 1'b1;
|
||||||
|
u_apu_apb4_if.penable = 1'b0;
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_apu_apb4_if.penable = 1'b1;
|
||||||
|
while (!u_apu_apb4_if.pready) @(negedge clk_i);
|
||||||
|
if (u_apu_apb4_if.pslverr) $fatal(1, "APU topology write failed at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_apu_apb4_if.psel = 1'b0;
|
||||||
|
u_apu_apb4_if.penable = 1'b0;
|
||||||
|
u_apu_apb4_if.pwrite = 1'b0;
|
||||||
|
u_apu_apb4_if.pstrb = 4'd0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic resource_write(input logic [11:0] offset_i, input logic [31:0] data_i,
|
||||||
|
input logic expected_err_i);
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_resource_apb4_if.paddr = {20'd0, offset_i};
|
||||||
|
u_resource_apb4_if.pwdata = data_i;
|
||||||
|
u_resource_apb4_if.pstrb = 4'hf;
|
||||||
|
u_resource_apb4_if.pwrite = 1'b1;
|
||||||
|
u_resource_apb4_if.psel = 1'b1;
|
||||||
|
u_resource_apb4_if.penable = 1'b0;
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_resource_apb4_if.penable = 1'b1;
|
||||||
|
while (!u_resource_apb4_if.pready) @(negedge clk_i);
|
||||||
|
if (u_resource_apb4_if.pslverr != expected_err_i) begin
|
||||||
|
$fatal(1, "Resource topology write response mismatch at %h", offset_i);
|
||||||
|
end
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_resource_apb4_if.psel = 1'b0;
|
||||||
|
u_resource_apb4_if.penable = 1'b0;
|
||||||
|
u_resource_apb4_if.pwrite = 1'b0;
|
||||||
|
u_resource_apb4_if.pstrb = 4'd0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic plic_write(input logic [25:0] offset_i, input logic [31:0] data_i);
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.paddr = {6'd0, offset_i};
|
||||||
|
u_plic_apb4_if.pwdata = data_i;
|
||||||
|
u_plic_apb4_if.pstrb = 4'hf;
|
||||||
|
u_plic_apb4_if.pwrite = 1'b1;
|
||||||
|
u_plic_apb4_if.psel = 1'b1;
|
||||||
|
u_plic_apb4_if.penable = 1'b0;
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.penable = 1'b1;
|
||||||
|
while (!u_plic_apb4_if.pready) @(negedge clk_i);
|
||||||
|
if (u_plic_apb4_if.pslverr) $fatal(1, "PLIC topology write failed at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.psel = 1'b0;
|
||||||
|
u_plic_apb4_if.penable = 1'b0;
|
||||||
|
u_plic_apb4_if.pwrite = 1'b0;
|
||||||
|
u_plic_apb4_if.pstrb = 4'd0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic plic_read(input logic [25:0] offset_i, output logic [31:0] data_o);
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.paddr = {6'd0, offset_i};
|
||||||
|
u_plic_apb4_if.pstrb = 4'd0;
|
||||||
|
u_plic_apb4_if.pwrite = 1'b0;
|
||||||
|
u_plic_apb4_if.psel = 1'b1;
|
||||||
|
u_plic_apb4_if.penable = 1'b0;
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.penable = 1'b1;
|
||||||
|
while (!u_plic_apb4_if.pready) @(negedge clk_i);
|
||||||
|
if (u_plic_apb4_if.pslverr) $fatal(1, "PLIC topology read failed at %h", offset_i);
|
||||||
|
data_o = u_plic_apb4_if.prdata;
|
||||||
|
@(negedge clk_i);
|
||||||
|
u_plic_apb4_if.psel = 1'b0;
|
||||||
|
u_plic_apb4_if.penable = 1'b0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
drive_apb_idle();
|
||||||
|
repeat (4) @(posedge clk_i);
|
||||||
|
rst_n_i = 1'b1;
|
||||||
|
|
||||||
|
plic_write(26'h000028, 32'd3);
|
||||||
|
plic_write(26'h002000, 32'h0000_0400);
|
||||||
|
plic_write(26'h200000, 32'd0);
|
||||||
|
apu_write(`APB4_APU__IRQ_ENABLE, 32'h0000_0001);
|
||||||
|
apu_write(`APB4_APU__IRQ_TEST, 32'h0000_0001);
|
||||||
|
repeat (2) @(posedge clk_i);
|
||||||
|
#1;
|
||||||
|
if ((s_resource_owner[7] != 2'd0) || !s_resource_irq_lp[7] || s_resource_irq_hp[7] ||
|
||||||
|
!s_apb4_periph_irq[23] || !s_irq[31] || s_hp_plic_source[10] ||
|
||||||
|
s_hp_plic_context_irq[0]) begin
|
||||||
|
$fatal(1, "APU event was not delivered exclusively to LP IRQ31");
|
||||||
|
end
|
||||||
|
|
||||||
|
resource_write(Resource7Control, 32'h0000_0001, 1'b0);
|
||||||
|
resource_write(Resource7Owner, 32'h0000_0101, 1'b0);
|
||||||
|
repeat (2) @(posedge clk_i);
|
||||||
|
#1;
|
||||||
|
if ((s_resource_owner[7] != 2'd1) || !s_resource_owner_lock[7] ||
|
||||||
|
s_resource_irq_lp[7] || !s_resource_irq_hp[7] || s_apb4_periph_irq[23] ||
|
||||||
|
s_irq[31] || !s_hp_plic_source[10] || !s_hp_plic_context_irq[0]) begin
|
||||||
|
$fatal(1, "APU event was not delivered exclusively to HP PLIC source 10");
|
||||||
|
end
|
||||||
|
plic_read(26'h200004, s_value);
|
||||||
|
if (s_value != 32'd10) $fatal(1, "HP PLIC did not claim APU source 10");
|
||||||
|
|
||||||
|
resource_write(Resource7Owner, 32'd0, 1'b1);
|
||||||
|
if ((s_resource_owner[7] != 2'd1) || !s_resource_owner_lock[7] || !s_resource_fault_irq) begin
|
||||||
|
$fatal(1, "APU owner lock did not preserve HP ownership");
|
||||||
|
end
|
||||||
|
resource_write(Resource7Fault, 32'h0000_0001, 1'b0);
|
||||||
|
if (s_resource_fault_irq) $fatal(1, "APU resource fault did not clear");
|
||||||
|
|
||||||
|
resource_write(Resource7Control, 32'h0000_0003, 1'b0);
|
||||||
|
repeat (2) @(posedge clk_i);
|
||||||
|
#1;
|
||||||
|
if (s_resource_irq_lp[7] || s_resource_irq_hp[7] || s_apb4_periph_irq[23] || s_irq[31] ||
|
||||||
|
s_hp_plic_source[10]) begin
|
||||||
|
$fatal(1, "APU resource reset did not mask both interrupt routes");
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_resource_fault_irq || s_cache_clean) begin
|
||||||
|
$fatal(1, "APU topology test left an unrelated controller output asserted");
|
||||||
|
end
|
||||||
|
$display("APU-P1 integrated IRQ ownership topology passed");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
repeat (1000) @(posedge clk_i);
|
||||||
|
$fatal(1, "APU-P1 IRQ ownership topology timed out");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,542 @@
|
|||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
`include "apu_define.svh"
|
||||||
|
|
||||||
|
module apu_reg_tb;
|
||||||
|
localparam logic [31:0] ApuBase = 32'h1001_3000;
|
||||||
|
localparam int unsigned RegisterCount = 95;
|
||||||
|
localparam logic [1:0] AccessRo = 2'd0;
|
||||||
|
localparam logic [1:0] AccessWo = 2'd1;
|
||||||
|
localparam logic [1:0] AccessRw = 2'd2;
|
||||||
|
|
||||||
|
logic clk_i = 1'b0;
|
||||||
|
logic rst_n_i = 1'b0;
|
||||||
|
logic [ 1:0] owner_i = 2'd0;
|
||||||
|
logic owner_lock_i = 1'b0;
|
||||||
|
logic quiesce_i = 1'b0;
|
||||||
|
logic resource_reset_i = 1'b0;
|
||||||
|
logic idle_o;
|
||||||
|
logic irq_o;
|
||||||
|
logic [31:0] s_value;
|
||||||
|
logic [11:0] s_reg_offset [RegisterCount];
|
||||||
|
logic [ 1:0] s_reg_access [RegisterCount];
|
||||||
|
logic [31:0] s_reg_reset [RegisterCount];
|
||||||
|
logic s_reg_full_strobe [RegisterCount];
|
||||||
|
int unsigned s_reg_count;
|
||||||
|
|
||||||
|
apb4_if apb4 (
|
||||||
|
.pclk (clk_i),
|
||||||
|
.presetn(rst_n_i)
|
||||||
|
);
|
||||||
|
|
||||||
|
always #5 clk_i = ~clk_i;
|
||||||
|
|
||||||
|
apb4_apu u_dut (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_n_i (rst_n_i),
|
||||||
|
.owner_i (owner_i),
|
||||||
|
.owner_lock_i (owner_lock_i),
|
||||||
|
.quiesce_i (quiesce_i),
|
||||||
|
.resource_reset_i(resource_reset_i),
|
||||||
|
.apb4 (apb4),
|
||||||
|
.idle_o (idle_o),
|
||||||
|
.irq_o (irq_o)
|
||||||
|
);
|
||||||
|
|
||||||
|
function automatic logic [31:0] legal_write_value(input logic [11:0] offset_i);
|
||||||
|
case (offset_i)
|
||||||
|
`APB4_APU__IRQ_STATE: legal_write_value = 32'h0000_07ff;
|
||||||
|
`APB4_APU__IRQ_ENABLE: legal_write_value = 32'h0000_0005;
|
||||||
|
`APB4_APU__ERROR_STATUS: legal_write_value = 32'h0000_0001;
|
||||||
|
`APB4_APU__SEQUENCER_TIMEOUT: legal_write_value = 32'h1234_5678;
|
||||||
|
`APB4_APU__STREAM_ROUTE: legal_write_value = 32'd0;
|
||||||
|
`APB4_APU__READ_BASE: legal_write_value = 32'h3000_0000;
|
||||||
|
`APB4_APU__READ_LIMIT: legal_write_value = 32'h3000_ffff;
|
||||||
|
`APB4_APU__WRITE_BASE: legal_write_value = 32'h3001_0000;
|
||||||
|
`APB4_APU__WRITE_LIMIT: legal_write_value = 32'h3001_ffff;
|
||||||
|
`APB4_APU__DMA_TIMEOUT: legal_write_value = 32'h8765_4321;
|
||||||
|
`APB4_APU__MC_IMAGE_ADDRESS: legal_write_value = 32'h3002_0000;
|
||||||
|
`APB4_APU__MC_IMAGE_SIZE: legal_write_value = 32'h0000_0040;
|
||||||
|
`APB4_APU__MC_EXPECTED_CRC: legal_write_value = 32'ha5a5_5a5a;
|
||||||
|
`APB4_APU__JOB_CONTROL: legal_write_value = 32'h0000_0121;
|
||||||
|
`APB4_APU__JOB_INPUT_ADDRESS: legal_write_value = 32'h3003_0000;
|
||||||
|
`APB4_APU__JOB_INPUT_LENGTH: legal_write_value = 32'h0000_0100;
|
||||||
|
`APB4_APU__JOB_OUTPUT_ADDRESS: legal_write_value = 32'h3003_1000;
|
||||||
|
`APB4_APU__JOB_OUTPUT_CAPACITY: legal_write_value = 32'h0000_1000;
|
||||||
|
`APB4_APU__JOB_INPUT_CONFIG: legal_write_value = 32'h0012_3456;
|
||||||
|
`APB4_APU__JOB_OUTPUT_CONFIG: legal_write_value = 32'h0001_2345;
|
||||||
|
`APB4_APU__JOB_FLAGS: legal_write_value = 32'h0000_0001;
|
||||||
|
`APB4_APU__RING_BASE: legal_write_value = 32'h3004_0000;
|
||||||
|
`APB4_APU__RING_SIZE: legal_write_value = 32'h0000_0008;
|
||||||
|
`APB4_APU__RING_TAIL: legal_write_value = 32'h0000_0003;
|
||||||
|
`APB4_APU__RING_CONTROL: legal_write_value = 32'h0000_0001;
|
||||||
|
`APB4_APU__RING_COALESCE: legal_write_value = 32'h0004_0002;
|
||||||
|
`APB4_APU__KWS_MODEL_ADDRESS: legal_write_value = 32'h3005_0000;
|
||||||
|
`APB4_APU__KWS_MODEL_SIZE: legal_write_value = 32'h0000_0100;
|
||||||
|
`APB4_APU__KWS_MODEL_EXPECTED_CRC: legal_write_value = 32'h5a5a_a5a5;
|
||||||
|
`APB4_APU__KWS_CONTROL: legal_write_value = 32'h0000_0004;
|
||||||
|
`APB4_APU__KWS_CONFIG: legal_write_value = 32'h0000_0590;
|
||||||
|
`APB4_APU__PERF_CONTROL: legal_write_value = 32'h0000_0001;
|
||||||
|
default: legal_write_value = 32'd0;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function automatic logic [31:0] legal_readback_value(input logic [11:0] offset_i);
|
||||||
|
case (offset_i)
|
||||||
|
`APB4_APU__IRQ_STATE, `APB4_APU__ERROR_STATUS, `APB4_APU__STREAM_ROUTE,
|
||||||
|
`APB4_APU__KWS_CONTROL:
|
||||||
|
legal_readback_value = 32'd0;
|
||||||
|
default: legal_readback_value = legal_write_value(offset_i);
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function automatic logic [31:0] reset_or_preserved_value(input logic [11:0] offset_i,
|
||||||
|
input logic [31:0] reset_i);
|
||||||
|
case (offset_i)
|
||||||
|
`APB4_APU__READ_BASE, `APB4_APU__READ_LIMIT, `APB4_APU__WRITE_BASE, `APB4_APU__WRITE_LIMIT:
|
||||||
|
reset_or_preserved_value = legal_write_value(offset_i);
|
||||||
|
default: reset_or_preserved_value = reset_i;
|
||||||
|
endcase
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task automatic add_register(input logic [11:0] offset_i, input logic [1:0] access_i,
|
||||||
|
input logic [31:0] reset_i, input logic full_strobe_i);
|
||||||
|
begin
|
||||||
|
if (s_reg_count >= RegisterCount) $fatal(1, "APU register table overflow");
|
||||||
|
s_reg_offset[s_reg_count] = offset_i;
|
||||||
|
s_reg_access[s_reg_count] = access_i;
|
||||||
|
s_reg_reset[s_reg_count] = reset_i;
|
||||||
|
s_reg_full_strobe[s_reg_count] = full_strobe_i;
|
||||||
|
s_reg_count++;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic initialize_register_table;
|
||||||
|
begin
|
||||||
|
s_reg_count = 0;
|
||||||
|
add_register(`APB4_APU__IP_ID, AccessRo, 32'h4150_5530, 1'b0);
|
||||||
|
add_register(`APB4_APU__IP_VERSION, AccessRo, 32'h0001_0000, 1'b0);
|
||||||
|
add_register(`APB4_APU__CAPABILITY0, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__CAPABILITY1, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__COMMAND, AccessWo, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__STATUS, AccessRo, 32'h0000_0100, 1'b0);
|
||||||
|
add_register(`APB4_APU__IRQ_STATE, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__IRQ_ENABLE, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__IRQ_TEST, AccessWo, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__ERROR_STATUS, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__ERROR_ADDRESS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__ERROR_DETAIL, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__SEQUENCER_TIMEOUT, AccessRw, 32'h0000_ffff, 1'b0);
|
||||||
|
add_register(`APB4_APU__STREAM_ROUTE, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__STREAM_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__OWNER_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__READ_BASE, AccessRw, 32'hffff_ffff, 1'b1);
|
||||||
|
add_register(`APB4_APU__READ_LIMIT, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__WRITE_BASE, AccessRw, 32'hffff_ffff, 1'b1);
|
||||||
|
add_register(`APB4_APU__WRITE_LIMIT, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__DMA_TIMEOUT, AccessRw, 32'h0000_ffff, 1'b0);
|
||||||
|
add_register(`APB4_APU__ABI_DIGEST, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__SEQUENCER_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__SEQUENCER_RETIRED, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_IMAGE_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__MC_IMAGE_SIZE, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__MC_EXPECTED_CRC, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__MC_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_ABI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_BUILD_ID_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_BUILD_ID_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_LOCK, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_ACTUAL_CRC, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__MC_LOAD_COUNT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_CONTROL, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_INPUT_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__JOB_INPUT_LENGTH, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__JOB_OUTPUT_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__JOB_OUTPUT_CAPACITY, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__JOB_INPUT_CONFIG, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_OUTPUT_CONFIG, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_FLAGS, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_INPUT_USED, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_OUTPUT_BYTES, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_FRAMES, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_SOURCE_INFO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_CYCLES, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__JOB_DETAIL, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__RING_BASE, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__RING_SIZE, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__RING_HEAD, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__RING_TAIL, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__RING_CONTROL, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__RING_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__RING_COMPLETED, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__RING_COALESCE, AccessRw, 32'h0001_0001, 1'b1);
|
||||||
|
add_register(`APB4_APU__RING_DOORBELL, AccessWo, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__KWS_MODEL_ADDRESS, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__KWS_MODEL_SIZE, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__KWS_MODEL_EXPECTED_CRC, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__KWS_CONTROL, AccessRw, 32'd0, 1'b1);
|
||||||
|
add_register(`APB4_APU__KWS_CONFIG, AccessRw, 32'h0000_0380, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_RESULT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_TIMESTAMP_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_TIMESTAMP_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_FRAME_COUNT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_INFERENCE_COUNT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_HIT_COUNT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_OVERRUN_COUNT, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_MODEL_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__KWS_MODEL_ACTUAL_CRC, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_CONTROL, AccessRw, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_STATUS, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_ACTIVE_CYCLES_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_ACTIVE_CYCLES_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_INPUT_BYTES_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_INPUT_BYTES_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_OUTPUT_BYTES_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_OUTPUT_BYTES_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DECODED_FRAMES_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DECODED_FRAMES_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DMA_READ_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DMA_READ_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DMA_WRITE_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_DMA_WRITE_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_STREAM_STALLS_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_STREAM_STALLS_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_SEQUENCER_INSTR_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_SEQUENCER_INSTR_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_KWS_CYCLES_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_KWS_CYCLES_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_FAULTS_LO, AccessRo, 32'd0, 1'b0);
|
||||||
|
add_register(`APB4_APU__PERF_FAULTS_HI, AccessRo, 32'd0, 1'b0);
|
||||||
|
if (s_reg_count != RegisterCount) begin
|
||||||
|
$fatal(1, "APU register table has %0d entries, expected %0d", s_reg_count, RegisterCount);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic drive_apb_idle;
|
||||||
|
begin
|
||||||
|
apb4.paddr = 32'd0;
|
||||||
|
apb4.pprot = 3'd0;
|
||||||
|
apb4.psel = 1'b0;
|
||||||
|
apb4.penable = 1'b0;
|
||||||
|
apb4.pwrite = 1'b0;
|
||||||
|
apb4.pwdata = 32'd0;
|
||||||
|
apb4.pstrb = 4'd0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic hard_reset;
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
drive_apb_idle();
|
||||||
|
owner_i = 2'd0;
|
||||||
|
owner_lock_i = 1'b0;
|
||||||
|
quiesce_i = 1'b0;
|
||||||
|
resource_reset_i = 1'b0;
|
||||||
|
rst_n_i = 1'b0;
|
||||||
|
repeat (2) @(posedge clk_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
rst_n_i = 1'b1;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic apb_write(input logic [11:0] offset_i, input logic [31:0] data_i,
|
||||||
|
input logic [3:0] strobe_i, input logic expected_err_i);
|
||||||
|
int unsigned s_wait_cycles;
|
||||||
|
logic s_response_err;
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
apb4.paddr = ApuBase + offset_i;
|
||||||
|
apb4.pwdata = data_i;
|
||||||
|
apb4.pstrb = strobe_i;
|
||||||
|
apb4.pwrite = 1'b1;
|
||||||
|
apb4.psel = 1'b1;
|
||||||
|
apb4.penable = 1'b0;
|
||||||
|
#1;
|
||||||
|
if (apb4.pready) $fatal(1, "APU PREADY asserted during write setup at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
apb4.penable = 1'b1;
|
||||||
|
s_wait_cycles = 0;
|
||||||
|
#1;
|
||||||
|
while (!apb4.pready) begin
|
||||||
|
s_wait_cycles++;
|
||||||
|
if (s_wait_cycles > 4) $fatal(1, "APU write wait timeout at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
#1;
|
||||||
|
end
|
||||||
|
if (s_wait_cycles != 1) begin
|
||||||
|
$fatal(1, "APU write wait count mismatch at %h: %0d", offset_i, s_wait_cycles);
|
||||||
|
end
|
||||||
|
if (apb4.pslverr != expected_err_i) $fatal(1, "APU write response mismatch at %h", offset_i);
|
||||||
|
s_response_err = apb4.pslverr;
|
||||||
|
#2;
|
||||||
|
if (!apb4.pready || (apb4.pslverr != s_response_err)) begin
|
||||||
|
$fatal(1, "APU write response was not retained through completion at %h", offset_i);
|
||||||
|
end
|
||||||
|
@(negedge clk_i);
|
||||||
|
drive_apb_idle();
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic apb_read(input logic [11:0] offset_i, output logic [31:0] data_o,
|
||||||
|
input logic expected_err_i);
|
||||||
|
int unsigned s_wait_cycles;
|
||||||
|
logic [31:0] s_response_data;
|
||||||
|
logic s_response_err;
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
apb4.paddr = ApuBase + offset_i;
|
||||||
|
apb4.pstrb = 4'd0;
|
||||||
|
apb4.pwrite = 1'b0;
|
||||||
|
apb4.psel = 1'b1;
|
||||||
|
apb4.penable = 1'b0;
|
||||||
|
#1;
|
||||||
|
if (apb4.pready) $fatal(1, "APU PREADY asserted during read setup at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
apb4.penable = 1'b1;
|
||||||
|
s_wait_cycles = 0;
|
||||||
|
#1;
|
||||||
|
while (!apb4.pready) begin
|
||||||
|
s_wait_cycles++;
|
||||||
|
if (s_wait_cycles > 4) $fatal(1, "APU read wait timeout at %h", offset_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
#1;
|
||||||
|
end
|
||||||
|
if (s_wait_cycles != 1) begin
|
||||||
|
$fatal(1, "APU read wait count mismatch at %h: %0d", offset_i, s_wait_cycles);
|
||||||
|
end
|
||||||
|
if (apb4.pslverr != expected_err_i) $fatal(1, "APU read response mismatch at %h", offset_i);
|
||||||
|
s_response_data = apb4.prdata;
|
||||||
|
s_response_err = apb4.pslverr;
|
||||||
|
#2;
|
||||||
|
if (!apb4.pready || (apb4.prdata != s_response_data) ||
|
||||||
|
(apb4.pslverr != s_response_err)) begin
|
||||||
|
$fatal(1, "APU read response was not retained through completion at %h", offset_i);
|
||||||
|
end
|
||||||
|
data_o = s_response_data;
|
||||||
|
@(negedge clk_i);
|
||||||
|
drive_apb_idle();
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic expect_read(input logic [11:0] offset_i, input logic [31:0] expected_i);
|
||||||
|
begin
|
||||||
|
apb_read(offset_i, s_value, 1'b0);
|
||||||
|
if (s_value != expected_i) begin
|
||||||
|
$fatal(1, "APU read mismatch at %h: got %h expected %h", offset_i, s_value, expected_i);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic program_rw_registers;
|
||||||
|
begin
|
||||||
|
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||||
|
if (s_reg_access[register_index] == AccessRw) begin
|
||||||
|
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||||
|
4'hf, 1'b0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic check_reset_state(input logic preserve_acl_i);
|
||||||
|
logic [31:0] s_expected;
|
||||||
|
begin
|
||||||
|
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||||
|
if (s_reg_access[register_index] != AccessWo) begin
|
||||||
|
s_expected = preserve_acl_i ?
|
||||||
|
reset_or_preserved_value(s_reg_offset[register_index], s_reg_reset[register_index]) :
|
||||||
|
s_reg_reset[register_index];
|
||||||
|
expect_read(s_reg_offset[register_index], s_expected);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task automatic check_rejected_write(input logic [11:0] offset_i,
|
||||||
|
input logic [31:0] rejected_value_i,
|
||||||
|
input logic [5:0] error_code_i);
|
||||||
|
logic [31:0] s_before;
|
||||||
|
begin
|
||||||
|
hard_reset();
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||||
|
if ((offset_i != `APB4_APU__COMMAND) && (offset_i != `APB4_APU__IRQ_TEST) &&
|
||||||
|
(offset_i != `APB4_APU__RING_DOORBELL)) begin
|
||||||
|
apb_read(offset_i, s_before, 1'b0);
|
||||||
|
end else begin
|
||||||
|
s_before = 32'd0;
|
||||||
|
end
|
||||||
|
apb_write(offset_i, rejected_value_i, 4'hf, 1'b1);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||||
|
expect_read(`APB4_APU__ERROR_STATUS, 32'd1 | (32'(error_code_i) << 1));
|
||||||
|
expect_read(`APB4_APU__ERROR_ADDRESS, ApuBase + offset_i);
|
||||||
|
if ((offset_i != `APB4_APU__COMMAND) && (offset_i != `APB4_APU__IRQ_TEST) &&
|
||||||
|
(offset_i != `APB4_APU__RING_DOORBELL) && (offset_i != `APB4_APU__IRQ_STATE) &&
|
||||||
|
(offset_i != `APB4_APU__ERROR_STATUS) && (offset_i != `APB4_APU__ERROR_ADDRESS) &&
|
||||||
|
(offset_i != `APB4_APU__ERROR_DETAIL)) begin
|
||||||
|
expect_read(offset_i, s_before);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
initialize_register_table();
|
||||||
|
drive_apb_idle();
|
||||||
|
hard_reset();
|
||||||
|
if (!idle_o || irq_o) $fatal(1, "APU reset lifecycle outputs mismatch");
|
||||||
|
|
||||||
|
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||||
|
hard_reset();
|
||||||
|
if (s_reg_access[register_index] == AccessWo) begin
|
||||||
|
apb_read(s_reg_offset[register_index], s_value, 1'b1);
|
||||||
|
end else begin
|
||||||
|
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||||
|
hard_reset();
|
||||||
|
case (s_reg_access[register_index])
|
||||||
|
AccessRo: begin
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||||
|
apb_write(s_reg_offset[register_index], 32'd0, 4'hf, 1'b1);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||||
|
if ((s_reg_offset[register_index] != `APB4_APU__ERROR_ADDRESS) &&
|
||||||
|
(s_reg_offset[register_index] != `APB4_APU__ERROR_DETAIL)) begin
|
||||||
|
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
AccessWo: begin
|
||||||
|
apb_read(s_reg_offset[register_index], s_value, 1'b1);
|
||||||
|
hard_reset();
|
||||||
|
if (s_reg_offset[register_index] == `APB4_APU__COMMAND) begin
|
||||||
|
apb_write(s_reg_offset[register_index], 32'h0000_0004, 4'hf, 1'b0);
|
||||||
|
end else if (s_reg_offset[register_index] == `APB4_APU__IRQ_TEST) begin
|
||||||
|
apb_write(s_reg_offset[register_index], 32'd0, 4'hf, 1'b0);
|
||||||
|
end else begin
|
||||||
|
apb_write(s_reg_offset[register_index], 32'h0000_0001, 4'hf, 1'b1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
AccessRw: begin
|
||||||
|
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||||
|
4'hf, 1'b0);
|
||||||
|
expect_read(s_reg_offset[register_index], legal_readback_value(
|
||||||
|
s_reg_offset[register_index]));
|
||||||
|
end
|
||||||
|
default: $fatal(1, "APU register table has invalid access class");
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
hard_reset();
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_00aa, 4'h1, 1'b0);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_ffaa);
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_bb00, 4'h2, 1'b0);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h0000_bbaa);
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h00cc_0000, 4'h4, 1'b0);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h00cc_bbaa);
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'hdd00_0000, 4'h8, 1'b0);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'hddcc_bbaa);
|
||||||
|
|
||||||
|
for (int unsigned register_index = 0; register_index < RegisterCount; register_index++) begin
|
||||||
|
if (s_reg_full_strobe[register_index]) begin
|
||||||
|
hard_reset();
|
||||||
|
apb_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678, 4'hf, 1'b0);
|
||||||
|
apb_write(s_reg_offset[register_index], legal_write_value(s_reg_offset[register_index]),
|
||||||
|
4'h7, 1'b1);
|
||||||
|
expect_read(`APB4_APU__SEQUENCER_TIMEOUT, 32'h1234_5678);
|
||||||
|
if (s_reg_access[register_index] == AccessRw) begin
|
||||||
|
expect_read(s_reg_offset[register_index], s_reg_reset[register_index]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
check_rejected_write(`APB4_APU__COMMAND, 32'h0000_0080, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
for (int bit_index = 0; bit_index < 6; bit_index++) begin
|
||||||
|
if ((bit_index != `APB4_APU__COMMAND_SOFT_RESET) &&
|
||||||
|
(bit_index != `APB4_APU__COMMAND_CLEAR_COUNTERS)) begin
|
||||||
|
check_rejected_write(`APB4_APU__COMMAND, 32'd1 << bit_index,
|
||||||
|
`APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
check_rejected_write(`APB4_APU__IRQ_STATE, 32'h0000_0800, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__IRQ_ENABLE, 32'h0000_0800,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__IRQ_TEST, 32'h0000_0800, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__ERROR_STATUS, 32'h0000_0002,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__SEQUENCER_TIMEOUT, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__STREAM_ROUTE, 32'h0000_0001, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
check_rejected_write(`APB4_APU__STREAM_ROUTE, 32'h0000_0004, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
check_rejected_write(`APB4_APU__DMA_TIMEOUT, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__MC_IMAGE_ADDRESS, 32'h3002_0001,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__MC_IMAGE_SIZE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__JOB_CONTROL, 32'h8000_0000,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__JOB_INPUT_CONFIG, 32'h8000_0000,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__JOB_OUTPUT_CONFIG, 32'h8000_0000,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__JOB_FLAGS, 32'h0000_0002, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_BASE, 32'h3004_0001, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_SIZE, 32'h0000_0003, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_TAIL, 32'h0000_0100, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_CONTROL, 32'h0000_0004,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_COALESCE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__RING_DOORBELL, 32'h0000_0001,
|
||||||
|
`APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_MODEL_ADDRESS, 32'h3005_0001,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_MODEL_SIZE, 32'd0, `APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0001, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0002, `APB4_APU__ERROR_CODE_UNSUPPORTED);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_CONTROL, 32'h0000_0008,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__KWS_CONFIG, 32'h0000_0080,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
check_rejected_write(`APB4_APU__PERF_CONTROL, 32'h0000_0008,
|
||||||
|
`APB4_APU__ERROR_CODE_INVALID_CONFIG);
|
||||||
|
|
||||||
|
hard_reset();
|
||||||
|
apb_write(`APB4_APU__IRQ_TEST, 32'h0000_0001, 4'hf, 1'b0);
|
||||||
|
force u_dut.u_apu_reg.s_irq_set = 11'h001;
|
||||||
|
apb_write(`APB4_APU__IRQ_STATE, 32'h0000_0001, 4'h1, 1'b0);
|
||||||
|
release u_dut.u_apu_reg.s_irq_set;
|
||||||
|
expect_read(`APB4_APU__IRQ_STATE, 32'h0000_0001);
|
||||||
|
apb_write(`APB4_APU__IRQ_STATE, 32'h0000_0001, 4'h1, 1'b0);
|
||||||
|
expect_read(`APB4_APU__IRQ_STATE, 32'd0);
|
||||||
|
|
||||||
|
hard_reset();
|
||||||
|
program_rw_registers();
|
||||||
|
apb_write(`APB4_APU__COMMAND, 32'h0000_0004, 4'hf, 1'b0);
|
||||||
|
check_reset_state(1'b1);
|
||||||
|
|
||||||
|
hard_reset();
|
||||||
|
program_rw_registers();
|
||||||
|
@(negedge clk_i);
|
||||||
|
resource_reset_i = 1'b1;
|
||||||
|
@(posedge clk_i);
|
||||||
|
@(negedge clk_i);
|
||||||
|
resource_reset_i = 1'b0;
|
||||||
|
check_reset_state(1'b1);
|
||||||
|
|
||||||
|
hard_reset();
|
||||||
|
owner_i = 2'd1;
|
||||||
|
owner_lock_i = 1'b1;
|
||||||
|
quiesce_i = 1'b1;
|
||||||
|
expect_read(`APB4_APU__OWNER_STATUS, 32'h0000_0301);
|
||||||
|
apb_read(12'h060, s_value, 1'b1);
|
||||||
|
apb_read(12'h001, s_value, 1'b1);
|
||||||
|
|
||||||
|
$display("APU-P1 complete APB register matrix passed");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
repeat (20000) @(posedge clk_i);
|
||||||
|
$fatal(1, "APU-P1 APB register matrix timed out");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
@@ -180,6 +180,41 @@ module axi4_interconnect_tb;
|
|||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
task automatic issue_hp_apu_write(input logic [31:0] address, input logic [1:0] expected_response,
|
||||||
|
input logic expected_access_fault);
|
||||||
|
begin
|
||||||
|
@(negedge clk_i);
|
||||||
|
masters[6].awaddr = address;
|
||||||
|
masters[6].awlen = 8'd0;
|
||||||
|
masters[6].awvalid = 1'b1;
|
||||||
|
do @(posedge clk_i); while (!masters[6].awready);
|
||||||
|
@(negedge clk_i);
|
||||||
|
masters[6].awvalid = 1'b0;
|
||||||
|
masters[6].wdata = 32'h1234_5678;
|
||||||
|
masters[6].wstrb = 4'hf;
|
||||||
|
masters[6].wlast = 1'b1;
|
||||||
|
masters[6].wvalid = 1'b1;
|
||||||
|
do @(posedge clk_i); while (!masters[6].wready);
|
||||||
|
@(negedge clk_i);
|
||||||
|
masters[6].wvalid = 1'b0;
|
||||||
|
masters[6].bready = 1'b1;
|
||||||
|
while (!masters[6].bvalid) @(negedge clk_i);
|
||||||
|
#1;
|
||||||
|
if ((masters[6].bresp != expected_response) ||
|
||||||
|
(fault_valid_o != expected_access_fault) ||
|
||||||
|
(expected_access_fault &&
|
||||||
|
(!fault_access_o || (fault_addr_o != address) || (fault_master_o != 3'd6) ||
|
||||||
|
(fault_code_o != `RIB_RESP_PROTERR)))) begin
|
||||||
|
$fatal(
|
||||||
|
1,
|
||||||
|
"HP APU access policy mismatch at %h: resp=%0d fault=%0d access=%0d master=%0d code=%0d",
|
||||||
|
address, masters[6].bresp, fault_valid_o, fault_access_o, fault_master_o, fault_code_o);
|
||||||
|
end
|
||||||
|
@(negedge clk_i);
|
||||||
|
masters[6].bready = 1'b0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
task automatic issue_management_with_idle_sdio;
|
task automatic issue_management_with_idle_sdio;
|
||||||
integer cycles;
|
integer cycles;
|
||||||
begin
|
begin
|
||||||
@@ -347,7 +382,12 @@ module axi4_interconnect_tb;
|
|||||||
issue_management_with_idle_sdio();
|
issue_management_with_idle_sdio();
|
||||||
issue_mgmt_error_read(32'hA000_0000, 8'd0, `AXI4_RESP_DECODE_ERROR, `RIB_RESP_DECERR);
|
issue_mgmt_error_read(32'hA000_0000, 8'd0, `AXI4_RESP_DECODE_ERROR, `RIB_RESP_DECERR);
|
||||||
issue_mgmt_error_read(32'h3000_0000, 8'd16, `AXI4_RESP_SLAVE_ERROR, `RIB_RESP_BURSTERR);
|
issue_mgmt_error_read(32'h3000_0000, 8'd16, `AXI4_RESP_SLAVE_ERROR, `RIB_RESP_BURSTERR);
|
||||||
|
`ifdef MINI_PRODUCT
|
||||||
|
issue_hp_apu_write(32'h1001_301C, `AXI4_RESP_OKAY, 1'b0);
|
||||||
|
issue_hp_apu_write(32'h1001_3040, `AXI4_RESP_SLAVE_ERROR, 1'b1);
|
||||||
|
`else
|
||||||
issue_denied_user_write(32'h1000_B000);
|
issue_denied_user_write(32'h1000_B000);
|
||||||
|
`endif
|
||||||
issue_contending_sdio_faults();
|
issue_contending_sdio_faults();
|
||||||
issue_hp_accesses();
|
issue_hp_accesses();
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,17 @@
|
|||||||
module resource_controller_tb;
|
module resource_controller_tb;
|
||||||
logic clk_i = 1'b0;
|
logic clk_i = 1'b0;
|
||||||
logic rst_n_i = 1'b0;
|
logic rst_n_i = 1'b0;
|
||||||
logic [ 5:0] idle_i = '0;
|
logic [ 7:0] idle_i = '0;
|
||||||
logic [ 5:0] block_ack_i = '0;
|
logic [ 7:0] block_ack_i = '0;
|
||||||
logic [ 5:0] irq_i = '0;
|
logic [ 7:0] irq_i = '0;
|
||||||
logic cache_request_i = 1'b0;
|
logic cache_request_i = 1'b0;
|
||||||
logic cache_clean_o;
|
logic cache_clean_o;
|
||||||
logic [ 5:0][1:0] owner_o;
|
logic [ 7:0][1:0] owner_o;
|
||||||
logic [ 5:0] quiesce_o;
|
logic [ 7:0] owner_lock_o;
|
||||||
logic [ 5:0] reset_o;
|
logic [ 7:0] quiesce_o;
|
||||||
logic [ 5:0] irq_lp_o;
|
logic [ 7:0] reset_o;
|
||||||
logic [ 5:0] irq_hp_o;
|
logic [ 7:0] irq_lp_o;
|
||||||
|
logic [ 7:0] irq_hp_o;
|
||||||
logic fault_irq_o;
|
logic fault_irq_o;
|
||||||
logic [31:0] read_data;
|
logic [31:0] read_data;
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ module resource_controller_tb;
|
|||||||
.cache_request_i(cache_request_i),
|
.cache_request_i(cache_request_i),
|
||||||
.cache_clean_o (cache_clean_o),
|
.cache_clean_o (cache_clean_o),
|
||||||
.owner_o (owner_o),
|
.owner_o (owner_o),
|
||||||
|
.owner_lock_o (owner_lock_o),
|
||||||
.quiesce_o (quiesce_o),
|
.quiesce_o (quiesce_o),
|
||||||
.reset_o (reset_o),
|
.reset_o (reset_o),
|
||||||
.irq_lp_o (irq_lp_o),
|
.irq_lp_o (irq_lp_o),
|
||||||
@@ -90,7 +92,7 @@ module resource_controller_tb;
|
|||||||
|
|
||||||
repeat (3) @(posedge clk_i);
|
repeat (3) @(posedge clk_i);
|
||||||
rst_n_i = 1'b1;
|
rst_n_i = 1'b1;
|
||||||
idle_i = 6'h3F;
|
idle_i = 8'hFF;
|
||||||
|
|
||||||
apb_read(12'h000, read_data);
|
apb_read(12'h000, read_data);
|
||||||
if (read_data != 32'h5253_4354) $fatal(1, "resource controller ID mismatch");
|
if (read_data != 32'h5253_4354) $fatal(1, "resource controller ID mismatch");
|
||||||
@@ -135,6 +137,16 @@ module resource_controller_tb;
|
|||||||
$fatal(1, "resource lifecycle controls did not update");
|
$fatal(1, "resource lifecycle controls did not update");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
irq_i[7] = 1'b1;
|
||||||
|
#1;
|
||||||
|
if (!irq_lp_o[7] || irq_hp_o[7]) $fatal(1, "APU reset owner routing mismatch");
|
||||||
|
block_ack_i[7] = 1'b1;
|
||||||
|
apb_write(12'h1E4, 32'h0000_0001, 1'b0);
|
||||||
|
apb_write(12'h1E0, 32'h0000_0101, 1'b0);
|
||||||
|
if ((owner_o[7] != 2'd1) || !owner_lock_o[7] || irq_lp_o[7] || !irq_hp_o[7]) begin
|
||||||
|
$fatal(1, "APU resource index 7 ownership or IRQ routing mismatch");
|
||||||
|
end
|
||||||
|
|
||||||
$display("Resource Controller ownership, IRQ, and cache handshake test passed");
|
$display("Resource Controller ownership, IRQ, and cache handshake test passed");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ module soc_irq_topology_tb;
|
|||||||
20: expect_irq(32'd1 << 25);
|
20: expect_irq(32'd1 << 25);
|
||||||
21: expect_irq(32'd1 << 26);
|
21: expect_irq(32'd1 << 26);
|
||||||
22: expect_irq(32'd1 << 30);
|
22: expect_irq(32'd1 << 30);
|
||||||
|
23: expect_irq(32'd1 << 31);
|
||||||
default: expect_irq(32'd1 << (bit_index + 7));
|
default: expect_irq(32'd1 << (bit_index + 7));
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
@@ -70,7 +71,7 @@ module soc_irq_topology_tb;
|
|||||||
$fatal(1, "SDIO core IRQ bits are not low when sources are low: IRQ10=%b IRQ21=%b",
|
$fatal(1, "SDIO core IRQ bits are not low when sources are low: IRQ10=%b IRQ21=%b",
|
||||||
s_irq[10], s_irq[21]);
|
s_irq[10], s_irq[21]);
|
||||||
end
|
end
|
||||||
if ((s_irq[31] !== 1'b0) || (s_irq[19:18] !== '0)) begin
|
if (s_irq[19:18] !== '0) begin
|
||||||
$fatal(1, "unallocated core IRQ bits are not low: %h", s_irq);
|
$fatal(1, "unallocated core IRQ bits are not low: %h", s_irq);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
"""Directed verification for the APU-P1 APB4 register shell."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
TOPOLOGY = ROOT / "rtl/mini/integration/soc_topology.json"
|
||||||
|
TOPOLOGY_GENERATOR = ROOT / "rtl/mini/integration/generate_soc_topology.py"
|
||||||
|
MEMORY_MAP = ROOT / "rtl/mini/address_map/memory_map.json"
|
||||||
|
|
||||||
|
|
||||||
|
def test_apu_p1_apb_register_shell(tmp_path: Path) -> None:
|
||||||
|
iverilog = shutil.which("iverilog")
|
||||||
|
vvp = shutil.which("vvp")
|
||||||
|
sv2v = shutil.which("sv2v")
|
||||||
|
if iverilog is None or vvp is None or sv2v is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
common = ROOT / "rtl/managed/clusterip/common/rtl"
|
||||||
|
multimedia = ROOT / "rtl/ip/multimedia"
|
||||||
|
source_list = tmp_path / "apu_reg.fl"
|
||||||
|
source_list.write_text(
|
||||||
|
"\n".join(
|
||||||
|
[
|
||||||
|
"+define+SV_ASSRT_DISABLE",
|
||||||
|
f"+incdir+{common}",
|
||||||
|
f"+incdir+{common / 'interface'}",
|
||||||
|
f"+incdir+{multimedia}",
|
||||||
|
str(common / "interface/apb4_if.sv"),
|
||||||
|
str(common / "utils/register.sv"),
|
||||||
|
str(multimedia / "apu_reg.sv"),
|
||||||
|
str(multimedia / "apb4_apu.sv"),
|
||||||
|
str(ROOT / "tests/rtl/apu_reg_tb.sv"),
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
converted = tmp_path / "apu_reg_tb.v"
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
|
||||||
|
"-f",
|
||||||
|
str(source_list),
|
||||||
|
"--output",
|
||||||
|
str(converted),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
simulation = tmp_path / "apu_reg_tb"
|
||||||
|
subprocess.run(
|
||||||
|
[iverilog, "-g2012", "-s", "apu_reg_tb", "-o", str(simulation), str(converted)],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
|
||||||
|
assert "APU-P1 complete APB register matrix passed" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def test_apu_p1_integrated_irq_ownership_topology(tmp_path: Path) -> None:
|
||||||
|
iverilog = shutil.which("iverilog")
|
||||||
|
vvp = shutil.which("vvp")
|
||||||
|
sv2v = shutil.which("sv2v")
|
||||||
|
if iverilog is None or vvp is None or sv2v is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
common = ROOT / "rtl/managed/clusterip/common/rtl"
|
||||||
|
multimedia = ROOT / "rtl/ip/multimedia"
|
||||||
|
peripheral = ROOT / "rtl/ip/peripheral"
|
||||||
|
topology_output = tmp_path / "topology"
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
str(TOPOLOGY_GENERATOR),
|
||||||
|
"--map",
|
||||||
|
str(TOPOLOGY),
|
||||||
|
"--memory-map",
|
||||||
|
str(MEMORY_MAP),
|
||||||
|
"--output-dir",
|
||||||
|
str(topology_output),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
source_list = tmp_path / "apu_irq_topology.fl"
|
||||||
|
source_list.write_text(
|
||||||
|
"\n".join(
|
||||||
|
[
|
||||||
|
"+define+SV_ASSRT_DISABLE",
|
||||||
|
f"+incdir+{topology_output / 'rtl'}",
|
||||||
|
f"+incdir+{common}",
|
||||||
|
f"+incdir+{common / 'interface'}",
|
||||||
|
f"+incdir+{multimedia}",
|
||||||
|
str(common / "interface/apb4_if.sv"),
|
||||||
|
str(common / "utils/register.sv"),
|
||||||
|
str(multimedia / "apu_reg.sv"),
|
||||||
|
str(multimedia / "apb4_apu.sv"),
|
||||||
|
str(ROOT / "rtl/mini/top/resource_controller.sv"),
|
||||||
|
str(peripheral / "apb4_plic.sv"),
|
||||||
|
str(ROOT / "tests/rtl/apu_irq_topology_tb.sv"),
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
converted = tmp_path / "apu_irq_topology_tb.v"
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
|
||||||
|
"-f",
|
||||||
|
str(source_list),
|
||||||
|
"--output",
|
||||||
|
str(converted),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
simulation = tmp_path / "apu_irq_topology_tb"
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
iverilog,
|
||||||
|
"-g2012",
|
||||||
|
"-s",
|
||||||
|
"apu_irq_topology_tb",
|
||||||
|
"-o",
|
||||||
|
str(simulation),
|
||||||
|
str(converted),
|
||||||
|
],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
|
||||||
|
assert "APU-P1 integrated IRQ ownership topology passed" in result.stdout
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
"""Keep the handwritten APU-P1 RTL and SDK register ABI synchronized."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
RTL_DEFINE = ROOT / "rtl/ip/multimedia/apu_define.svh"
|
||||||
|
C_HEADER = ROOT / "crt/include/retrosoc/hal/apu_regs.h"
|
||||||
|
REGISTER_TESTBENCH = ROOT / "tests/rtl/apu_reg_tb.sv"
|
||||||
|
|
||||||
|
|
||||||
|
def _rtl_values() -> dict[str, int]:
|
||||||
|
values: dict[str, int] = {}
|
||||||
|
pattern = re.compile(
|
||||||
|
r"^`define\s+APB4_APU__(\w+)\s+((?:\d+)'[hHdDbB][0-9a-fA-F_]+|\d+)\s*$"
|
||||||
|
)
|
||||||
|
for line in RTL_DEFINE.read_text(encoding="utf-8").splitlines():
|
||||||
|
match = pattern.match(line)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
name, literal = match.groups()
|
||||||
|
if "'" in literal:
|
||||||
|
_, value = literal.split("'", maxsplit=1)
|
||||||
|
radix = {"h": 16, "d": 10, "b": 2}[value[0].lower()]
|
||||||
|
values[name] = int(value[1:].replace("_", ""), radix)
|
||||||
|
else:
|
||||||
|
values[name] = int(literal, 10)
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
def _c_values() -> dict[str, int]:
|
||||||
|
values: dict[str, int] = {}
|
||||||
|
pattern = re.compile(
|
||||||
|
r"^#define\s+RS_APU_ABI_(\w+)\s+"
|
||||||
|
r"(?:UINT32_C\((0[xX][0-9a-fA-F]+)\)|(\d+)[uU]?)\s*$"
|
||||||
|
)
|
||||||
|
for line in C_HEADER.read_text(encoding="utf-8").splitlines():
|
||||||
|
match = pattern.match(line)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
name, hexadecimal, decimal = match.groups()
|
||||||
|
values[name] = int(hexadecimal, 16) if hexadecimal is not None else int(decimal, 10)
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
def test_apu_register_constants_match_expected_abi() -> None:
|
||||||
|
assert _c_values() == _rtl_values()
|
||||||
|
|
||||||
|
|
||||||
|
def test_apu_register_matrix_covers_each_offset_once() -> None:
|
||||||
|
offset_pattern = re.compile(
|
||||||
|
r"^`define\s+APB4_APU__(\w+)\s+12'[hH][0-9a-fA-F_]+\s*$"
|
||||||
|
)
|
||||||
|
table_pattern = re.compile(r"add_register\(`APB4_APU__(\w+),")
|
||||||
|
expected = [
|
||||||
|
match.group(1)
|
||||||
|
for line in RTL_DEFINE.read_text(encoding="utf-8").splitlines()
|
||||||
|
if (match := offset_pattern.match(line)) is not None
|
||||||
|
]
|
||||||
|
covered = table_pattern.findall(REGISTER_TESTBENCH.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
assert len(covered) == len(set(covered))
|
||||||
|
assert set(covered) == set(expected)
|
||||||
+5
-1
@@ -8,6 +8,8 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
@@ -173,8 +175,9 @@ def test_axi4_word_bridge_supports_bursts_backpressure_and_errors(tmp_path: Path
|
|||||||
assert "AXI4 word bridge test passed" in result.stdout
|
assert "AXI4 word bridge test passed" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("product_mode", [False, True])
|
||||||
def test_axi4_interconnect_classifies_decode_protocol_and_access_errors(
|
def test_axi4_interconnect_classifies_decode_protocol_and_access_errors(
|
||||||
tmp_path: Path,
|
tmp_path: Path, product_mode: bool
|
||||||
) -> None:
|
) -> None:
|
||||||
verilator = shutil.which("verilator")
|
verilator = shutil.which("verilator")
|
||||||
if verilator is None:
|
if verilator is None:
|
||||||
@@ -205,6 +208,7 @@ def test_axi4_interconnect_classifies_decode_protocol_and_access_errors(
|
|||||||
"-Wno-fatal",
|
"-Wno-fatal",
|
||||||
"--top-module",
|
"--top-module",
|
||||||
"axi4_interconnect_tb",
|
"axi4_interconnect_tb",
|
||||||
|
*(["-DMINI_PRODUCT"] if product_mode else []),
|
||||||
"-I" + str(memory_map / "rtl"),
|
"-I" + str(memory_map / "rtl"),
|
||||||
"-I" + str(ROOT / "rtl/mini/top"),
|
"-I" + str(ROOT / "rtl/mini/top"),
|
||||||
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl"),
|
"-I" + str(ROOT / "rtl/managed/clusterip/common/rtl"),
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ def test_booter_prints_every_public_active_mmio_region() -> None:
|
|||||||
assert "DMA(8CH)" in mmio_function
|
assert "DMA(8CH)" in mmio_function
|
||||||
assert "DMA(6CH)" not in mmio_function
|
assert "DMA(6CH)" not in mmio_function
|
||||||
assert "RS_SOC_APB4_GA_BASE" not in mmio_function
|
assert "RS_SOC_APB4_GA_BASE" not in mmio_function
|
||||||
assert "RS_SOC_APB4_APU_BASE" not in mmio_function
|
assert "RS_SOC_APB4_APU_BASE" in mmio_function
|
||||||
|
|
||||||
|
|
||||||
def test_sram_capacity_selects_one_consistent_hardware_software_window(tmp_path: Path) -> None:
|
def test_sram_capacity_selects_one_consistent_hardware_software_window(tmp_path: Path) -> None:
|
||||||
@@ -173,9 +173,11 @@ def test_user_ip_is_always_emitted_for_the_fixed_platform(tmp_path: Path) -> Non
|
|||||||
assert "`define SOC_ADDR_APB4_SDIO0_BASE 32'h1000F000" in rtl
|
assert "`define SOC_ADDR_APB4_SDIO0_BASE 32'h1000F000" in rtl
|
||||||
assert "`define SOC_ADDR_APB4_SDIO1_BASE 32'h10015000" in rtl
|
assert "`define SOC_ADDR_APB4_SDIO1_BASE 32'h10015000" in rtl
|
||||||
assert "`define SOC_ADDR_APB4_USB2_BASE 32'h10016000" in rtl
|
assert "`define SOC_ADDR_APB4_USB2_BASE 32'h10016000" in rtl
|
||||||
|
assert "`define SOC_ADDR_APB4_APU_BASE 32'h10013000" in rtl
|
||||||
assert "`define SOC_ADDR_APB4_CRYPTO_BASE 32'h1000C000" in rtl
|
assert "`define SOC_ADDR_APB4_CRYPTO_BASE 32'h1000C000" in rtl
|
||||||
assert "#define RS_SOC_APB4_CRYPTO_BASE UINT32_C(0x1000C000)" in header
|
assert "#define RS_SOC_APB4_CRYPTO_BASE UINT32_C(0x1000C000)" in header
|
||||||
assert "#define RS_SOC_APB4_USB2_BASE UINT32_C(0x10016000)" in header
|
assert "#define RS_SOC_APB4_USB2_BASE UINT32_C(0x10016000)" in header
|
||||||
|
assert "#define RS_SOC_APB4_APU_BASE UINT32_C(0x10013000)" in header
|
||||||
|
|
||||||
|
|
||||||
def test_bootstrap_assembly_uses_the_generated_gpio_admin_base() -> None:
|
def test_bootstrap_assembly_uses_the_generated_gpio_admin_base() -> None:
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
data_policy = (tmp_path / "rtl/soc_data_policy.svh").read_text(encoding="utf-8")
|
data_policy = (tmp_path / "rtl/soc_data_policy.svh").read_text(encoding="utf-8")
|
||||||
filelist = (tmp_path / "soc_topology.fl").read_text(encoding="utf-8")
|
filelist = (tmp_path / "soc_topology.fl").read_text(encoding="utf-8")
|
||||||
|
|
||||||
assert interfaces.count("apb4_if u_") == 25
|
assert interfaces.count("apb4_if u_") == 26
|
||||||
assert "nmi_if" not in interfaces
|
assert "nmi_if" not in interfaces
|
||||||
assert "soc_nmi" not in interfaces
|
assert "soc_nmi" not in interfaces
|
||||||
assert "assign s_psel_comb[17] = `SOC_ADDR_IS_APB4_I2C1(s_decode_addr);" in routes
|
assert "assign s_psel_comb[17] = `SOC_ADDR_IS_APB4_I2C1(s_decode_addr);" in routes
|
||||||
@@ -93,6 +93,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
assert "assign s_psel_comb[24] = `SOC_ADDR_IS_HP_ACLINT(s_decode_addr);" in routes
|
assert "assign s_psel_comb[24] = `SOC_ADDR_IS_HP_ACLINT(s_decode_addr);" in routes
|
||||||
assert "assign s_psel_comb[25] = `SOC_ADDR_IS_HP_PLIC(s_decode_addr);" in routes
|
assert "assign s_psel_comb[25] = `SOC_ADDR_IS_HP_PLIC(s_decode_addr);" in routes
|
||||||
assert "assign s_psel_comb[26] = `SOC_ADDR_IS_APB4_JPEG(s_decode_addr);" in routes
|
assert "assign s_psel_comb[26] = `SOC_ADDR_IS_APB4_JPEG(s_decode_addr);" in routes
|
||||||
|
assert "assign s_psel_comb[27] = `SOC_ADDR_IS_APB4_APU(s_decode_addr);" in routes
|
||||||
assert gpio.count("// GPIO") == 64
|
assert gpio.count("// GPIO") == 64
|
||||||
assert "u_uart1_if" not in gpio
|
assert "u_uart1_if" not in gpio
|
||||||
assert "assign u_uart0_if.cts_n_i = u_gpio_if.di_i[0];" in gpio
|
assert "assign u_uart0_if.cts_n_i = u_gpio_if.di_i[0];" in gpio
|
||||||
@@ -141,7 +142,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
assert ".usb2_axi4(u_usb2_axi4_if)" in apb_periph_fabric
|
assert ".usb2_axi4(u_usb2_axi4_if)" in apb_periph_fabric
|
||||||
assert "`define SOC_IRQ_VECTOR_WIDTH 32" in irq_config
|
assert "`define SOC_IRQ_VECTOR_WIDTH 32" in irq_config
|
||||||
assert "`define SOC_USER_IRQ_MASK 32'h004EFBFC" in irq_config
|
assert "`define SOC_USER_IRQ_MASK 32'h004EFBFC" in irq_config
|
||||||
assert "`define SOC_IRQ_APB4_PERIPH_WIDTH 23" in irq_config
|
assert "`define SOC_IRQ_APB4_PERIPH_WIDTH 24" in irq_config
|
||||||
assert "`define SOC_IRQ_APB4_SYSTEM_WIDTH 8" in irq_config
|
assert "`define SOC_IRQ_APB4_SYSTEM_WIDTH 8" in irq_config
|
||||||
assert "assign irq_o[0] = u_clint_if.software_irq_o[0];" in rib_irq
|
assert "assign irq_o[0] = u_clint_if.software_irq_o[0];" in rib_irq
|
||||||
assert "assign irq_o[10] = ws2812.irq_o;" in rib_irq
|
assert "assign irq_o[10] = ws2812.irq_o;" in rib_irq
|
||||||
@@ -155,6 +156,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
assert "assign irq_o[18] = s_crypto_irq;" in rib_irq
|
assert "assign irq_o[18] = s_crypto_irq;" in rib_irq
|
||||||
assert "assign irq_o[19] = resource_irq_lp_i[1];" in rib_irq
|
assert "assign irq_o[19] = resource_irq_lp_i[1];" in rib_irq
|
||||||
assert "assign irq_o[22] = resource_irq_lp_i[5];" in rib_irq
|
assert "assign irq_o[22] = resource_irq_lp_i[5];" in rib_irq
|
||||||
|
assert "assign irq_o[23] = resource_irq_lp_i[6];" in rib_irq
|
||||||
assert "assign irq_o[0] = pwm.irq_o;" in apb_irq
|
assert "assign irq_o[0] = pwm.irq_o;" in apb_irq
|
||||||
assert "assign irq_o[4] = s_rng_irq;" in apb_irq
|
assert "assign irq_o[4] = s_rng_irq;" in apb_irq
|
||||||
assert "assign irq_o[5] = s_ext_l_irq;" in apb_irq
|
assert "assign irq_o[5] = s_ext_l_irq;" in apb_irq
|
||||||
@@ -172,6 +174,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
assert "s_irq[28] = s_apb4_system_irq[6];" in irq_wiring
|
assert "s_irq[28] = s_apb4_system_irq[6];" in irq_wiring
|
||||||
assert "s_irq[29] = s_apb4_system_irq[7];" in irq_wiring
|
assert "s_irq[29] = s_apb4_system_irq[7];" in irq_wiring
|
||||||
assert "s_irq[30] = s_apb4_periph_irq[22];" in irq_wiring
|
assert "s_irq[30] = s_apb4_periph_irq[22];" in irq_wiring
|
||||||
|
assert "s_irq[31] = s_apb4_periph_irq[23];" in irq_wiring
|
||||||
assert "irq_i[10] == apb4_periph_irq_i[16]" in irq_sva
|
assert "irq_i[10] == apb4_periph_irq_i[16]" in irq_sva
|
||||||
assert "irq_i[15] == apb4_periph_irq_i[13]" in irq_sva
|
assert "irq_i[15] == apb4_periph_irq_i[13]" in irq_sva
|
||||||
assert "irq_i[20] == apb4_periph_irq_i[14]" in irq_sva
|
assert "irq_i[20] == apb4_periph_irq_i[14]" in irq_sva
|
||||||
@@ -180,7 +183,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
|||||||
assert "irq_i[23] == apb4_periph_irq_i[18]" in irq_sva
|
assert "irq_i[23] == apb4_periph_irq_i[18]" in irq_sva
|
||||||
assert "irq_i[24] == apb4_periph_irq_i[19]" in irq_sva
|
assert "irq_i[24] == apb4_periph_irq_i[19]" in irq_sva
|
||||||
assert "irq_i[30] == apb4_periph_irq_i[22]" in irq_sva
|
assert "irq_i[30] == apb4_periph_irq_i[22]" in irq_sva
|
||||||
assert "irq_i[31] == 1'b0" in irq_sva
|
assert "irq_i[31] == apb4_periph_irq_i[23]" in irq_sva
|
||||||
assert "bind retrosoc soc_irq_topology_sva" in irq_sva
|
assert "bind retrosoc soc_irq_topology_sva" in irq_sva
|
||||||
assert ".clk_i(clk_lp_i)" in irq_sva
|
assert ".clk_i(clk_lp_i)" in irq_sva
|
||||||
assert ".rst_n_i(rst_lp_n_i)" in irq_sva
|
assert ".rst_n_i(rst_lp_n_i)" in irq_sva
|
||||||
@@ -236,9 +239,28 @@ def test_topology_preserves_default_irq_compatibility_mapping() -> None:
|
|||||||
("extension_h", "apb4_system", 6, 28, "s_ext_h_irq"),
|
("extension_h", "apb4_system", 6, 28, "s_ext_h_irq"),
|
||||||
("jpeg", "apb4_periph", 22, 30, "resource_irq_lp_i[5]"),
|
("jpeg", "apb4_periph", 22, 30, "resource_irq_lp_i[5]"),
|
||||||
("resource_fault", "apb4_system", 7, 29, "s_resource_fault_irq"),
|
("resource_fault", "apb4_system", 7, 29, "s_resource_fault_irq"),
|
||||||
|
("apu", "apb4_periph", 23, 31, "resource_irq_lp_i[6]"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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")
|
||||||
|
top = (ROOT / "rtl/mini/top/retrosoc.sv").read_text(encoding="utf-8")
|
||||||
|
resource_header = (ROOT / "crt/include/retrosoc/hal/resource.h").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 ".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
|
||||||
|
|
||||||
|
|
||||||
def test_topology_always_adds_the_user_apb_target(tmp_path: Path) -> None:
|
def test_topology_always_adds_the_user_apb_target(tmp_path: Path) -> None:
|
||||||
generate(tmp_path)
|
generate(tmp_path)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user