diff --git a/Bender.yml b/Bender.yml index b2b62ee9c..ddf3a281e 100644 --- a/Bender.yml +++ b/Bender.yml @@ -128,6 +128,7 @@ sources: - test/midend/tb_idma_nd_midend_b2b.sv - test/midend/tb_idma_rt_midend.sv - test/midend/tb_idma_transpose_midend.sv + - test/midend/tb_idma_mp_midend.sv # Level 2 - test/future/idma_obi2axi_bridge.sv - test/future/idma_tilelink2axi_bridge.sv diff --git a/doc/site/src/content/docs/architecture/frontend/snitch.md b/doc/site/src/content/docs/architecture/frontend/snitch.md index e2d46f3eb..d3f77cc46 100644 --- a/doc/site/src/content/docs/architecture/frontend/snitch.md +++ b/doc/site/src/content/docs/architecture/frontend/snitch.md @@ -38,6 +38,19 @@ All DMA instructions that return a value write to `rd` (destination register). T - Bit 1: Enable 2D mode (use previously set strides/reps). If 2D mode is enabled but `DMSTR`/`DMREP` were not called since the last transfer, the previously set stride and repetition values are reused. On reset, these default to zero - Bits 4:2: Channel select - `$clog2(NumChannels)` bits wide, remaining upper bits are zero-extended. For the common single-channel case (`NumChannels=1`), these bits are unused and only bit 1 (2D enable) matters +### In-network collectives + +`DMUSER` is how a Snitch core reaches an interconnect that resolves collectives in the +network, such as FlooNoC's multicast and reduction. The user word carries the destination +mask and the collective opcode; iDMA forwards it to `aw.user` and interprets none of it. + +Participating cores must issue transfers that the legalizer decomposes identically. A +reduction join matches incoming flits on destination and mask, so two participants that +produce different burst counts for the same logical transfer will never join and the +network stalls. The legalizer splits on the page boundary and the source offset, so equal +lengths are not sufficient: give every participant the same source alignment relative to +the page size, or the same `src_max_llen` with `src_reduce_len` set. + ## Parameters For most Snitch cluster integrations, `NumChannels=1` and `NumAxInFlight=3` are standard. Increase `NumChannels` only if you need independent DMA channels on separate address spaces. @@ -51,6 +64,7 @@ For most Snitch cluster integrations, `NumChannels=1` and `NumAxInFlight=3` are | `NumAxInFlight` | Number of in-flight AXI transactions (default: 3) | | `DMAReqFifoDepth` | Depth of the request FIFO between frontend and midend (default: 3) | | `NumChannels` | Number of independent DMA channels, each with its own backend + ND midend (default: 1) | +| `NumDim` | Number of ND dimensions handed to the ND midend (default: 2). `idma_transpose_midend` requires at least 4 | | `DMATracing` | Enable DMA trace file generation for debugging | ## Programming Sequence diff --git a/idma.mk b/idma.mk index 7c2ac0f8e..50438216e 100644 --- a/idma.mk +++ b/idma.mk @@ -512,6 +512,13 @@ idma_sim_tb_idma_transpose_midend: $(IDMA_VSIM_DIR)/compile.tcl cd $(IDMA_VSIM_DIR); $(VSIM) -c -t 1ps -voptargs=+acc -gDataWidth=64 tb_idma_transpose_midend -do "run -all; quit" cd $(IDMA_VSIM_DIR); $(VSIM) -c -t 1ps -voptargs=+acc -gDataWidth=512 tb_idma_transpose_midend -do "run -all; quit" +.PHONY: idma_sim_tb_idma_mp_midend +idma_sim_tb_idma_mp_midend: $(IDMA_VSIM_DIR)/compile.tcl + cd $(IDMA_VSIM_DIR); $(VSIM) -c -do "source compile.tcl; quit" + # the TB derives its geometry from the parameters; one run per topology + cd $(IDMA_VSIM_DIR); $(VSIM) -c -t 1ps -voptargs=+acc -gNumBEs=4 -gRegionWidth=4096 tb_idma_mp_midend -do "run -all; quit" + cd $(IDMA_VSIM_DIR); $(VSIM) -c -t 1ps -voptargs=+acc -gNumBEs=8 -gRegionWidth=1024 tb_idma_mp_midend -do "run -all; quit" + .PHONY: idma_sim_tb_idma_rt_midend idma_sim_tb_idma_rt_midend: $(IDMA_VSIM_DIR)/compile.tcl diff --git a/jobs/jobs.json b/jobs/jobs.json index d9607dd9a..da056c9ec 100644 --- a/jobs/jobs.json +++ b/jobs/jobs.json @@ -1,592 +1,872 @@ { - "rw_axi" : { - "jobs" : { - "simple" : "backend_rw_axi/simple.txt", - "same_dst" : "backend_rw_axi/same_dst.txt", - "linear" : "backend_rw_axi/linear.txt", - "huge" : "backend_rw_axi/huge.txt", - "large" : "backend_rw_axi/large.txt", - "medium" : "backend_rw_axi/medium.txt", - "mixed" : "backend_rw_axi/mixed.txt", - "small" : "backend_rw_axi/small.txt", - "tiny" : "backend_rw_axi/tiny.txt", - "error_simple" : "backend_rw_axi/error_simple.txt", - "error_mixed" : "backend_rw_axi/error_mixed.txt", - "zero_transfer" : "backend_rw_axi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 1, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 1 - }, - "proc_id" : "rw_axi", - "testbench": "tb_idma_backend_rw_axi", - "synth_top": "idma_backend_synth_rw_axi" - }, - "rw_axi_stall" : { - "jobs" : { - "simple" : "backend_rw_axi/simple.txt", - "same_dst" : "backend_rw_axi/same_dst.txt", - "linear" : "backend_rw_axi/linear.txt", - "huge" : "backend_rw_axi/huge.txt", - "large" : "backend_rw_axi/large.txt", - "medium" : "backend_rw_axi/medium.txt", - "mixed" : "backend_rw_axi/mixed.txt", - "small" : "backend_rw_axi/small.txt", - "tiny" : "backend_rw_axi/tiny.txt", - "error_simple" : "backend_rw_axi/error_simple.txt", - "error_mixed" : "backend_rw_axi/error_mixed.txt", - "zero_transfer" : "backend_rw_axi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 8, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 1, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 1 - }, - "tb_params" : { - "AXI_IdealMemory" : 0, - "AXI_MemNumReqOutst" : 2, - "AXI_MemLatency" : 8, - "WatchDogNumCycles" : 5000 - }, - "proc_id" : "rw_axi", - "testbench": "tb_idma_backend_rw_axi", - "synth_top": "idma_backend_synth_rw_axi" - }, - "r_axi_w_obi" : { - "jobs" : { - "simple" : "backend_r_axi_w_obi/simple.txt", - "same_dst" : "backend_r_axi_w_obi/same_dst.txt", - "linear" : "backend_r_axi_w_obi/linear.txt", - "huge" : "backend_r_axi_w_obi/huge.txt", - "large" : "backend_r_axi_w_obi/large.txt", - "medium" : "backend_r_axi_w_obi/medium.txt", - "mixed" : "backend_r_axi_w_obi/mixed.txt", - "small" : "backend_r_axi_w_obi/small.txt", - "tiny" : "backend_r_axi_w_obi/tiny.txt", - "zero_transfer" : "backend_r_axi_w_obi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 0, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "r_axi_w_obi", - "testbench": "tb_idma_backend_r_axi_w_obi", - "synth_top": "idma_backend_synth_r_axi_w_obi" - }, - "r_obi_w_axi" : { - "jobs" : { - "simple" : "backend_r_obi_w_axi/simple.txt", - "same_dst" : "backend_r_obi_w_axi/same_dst.txt", - "linear" : "backend_r_obi_w_axi/linear.txt", - "huge" : "backend_r_obi_w_axi/huge.txt", - "large" : "backend_r_obi_w_axi/large.txt", - "medium" : "backend_r_obi_w_axi/medium.txt", - "mixed" : "backend_r_obi_w_axi/mixed.txt", - "small" : "backend_r_obi_w_axi/small.txt", - "tiny" : "backend_r_obi_w_axi/tiny.txt", - "zero_transfer" : "backend_r_obi_w_axi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 0, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "r_obi_w_axi", - "testbench": "tb_idma_backend_r_obi_w_axi", - "synth_top": "idma_backend_synth_r_obi_w_axi" - }, - "snitch_read" : { - "jobs" : { - "simple" : "backend_r_axi_rw_init_rw_obi/simple.txt", - "same_dst" : "backend_r_axi_rw_init_rw_obi/same_dst.txt", - "linear" : "backend_r_axi_rw_init_rw_obi/linear.txt", - "huge" : "backend_r_axi_rw_init_rw_obi/huge.txt", - "large" : "backend_r_axi_rw_init_rw_obi/large.txt", - "medium" : "backend_r_axi_rw_init_rw_obi/medium.txt", - "mixed" : "backend_r_axi_rw_init_rw_obi/mixed.txt", - "small" : "backend_r_axi_rw_init_rw_obi/small.txt", - "tiny" : "backend_r_axi_rw_init_rw_obi/tiny.txt", - "zero_transfer" : "backend_r_axi_rw_init_rw_obi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "r_axi_rw_init_rw_obi", - "testbench": "tb_idma_backend_r_axi_rw_init_rw_obi", - "synth_top": "idma_backend_synth_r_axi_rw_init_rw_obi" - }, - "snitch_init_read" : { - "jobs" : { - "simple" : "backend_r_init_rw_axi_rw_obi/simple.txt", - "same_dst" : "backend_r_init_rw_axi_rw_obi/same_dst.txt", - "linear" : "backend_r_init_rw_axi_rw_obi/linear.txt", - "huge" : "backend_r_init_rw_axi_rw_obi/huge.txt", - "large" : "backend_r_init_rw_axi_rw_obi/large.txt", - "medium" : "backend_r_init_rw_axi_rw_obi/medium.txt", - "mixed" : "backend_r_init_rw_axi_rw_obi/mixed.txt", - "small" : "backend_r_init_rw_axi_rw_obi/small.txt", - "tiny" : "backend_r_init_rw_axi_rw_obi/tiny.txt", - "zero_transfer" : "backend_r_init_rw_axi_rw_obi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "r_init_rw_axi_rw_obi", - "testbench": "tb_idma_backend_r_init_rw_axi_rw_obi", - "synth_top": "idma_backend_synth_r_init_rw_axi_rw_obi" - }, - "snitch_write" : { - "jobs" : { - "simple" : "backend_r_obi_rw_init_w_axi/simple.txt", - "same_dst" : "backend_r_obi_rw_init_w_axi/same_dst.txt", - "linear" : "backend_r_obi_rw_init_w_axi/linear.txt", - "huge" : "backend_r_obi_rw_init_w_axi/huge.txt", - "large" : "backend_r_obi_rw_init_w_axi/large.txt", - "medium" : "backend_r_obi_rw_init_w_axi/medium.txt", - "mixed" : "backend_r_obi_rw_init_w_axi/mixed.txt", - "small" : "backend_r_obi_rw_init_w_axi/small.txt", - "tiny" : "backend_r_obi_rw_init_w_axi/tiny.txt", - "zero_transfer" : "backend_r_obi_rw_init_w_axi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "r_obi_rw_init_w_axi", - "testbench": "tb_idma_backend_r_obi_rw_init_w_axi", - "synth_top": "idma_backend_synth_r_obi_rw_init_w_axi" - }, - "snitch_read_write" : { - "jobs" : { - "simple" : "backend_rw_axi_rw_init_rw_obi/simple.txt", - "same_dst" : "backend_rw_axi_rw_init_rw_obi/same_dst.txt", - "linear" : "backend_rw_axi_rw_init_rw_obi/linear.txt", - "huge" : "backend_rw_axi_rw_init_rw_obi/huge.txt", - "large" : "backend_rw_axi_rw_init_rw_obi/large.txt", - "medium" : "backend_rw_axi_rw_init_rw_obi/medium.txt", - "mixed" : "backend_rw_axi_rw_init_rw_obi/mixed.txt", - "small" : "backend_rw_axi_rw_init_rw_obi/small.txt", - "tiny" : "backend_rw_axi_rw_init_rw_obi/tiny.txt", - "zero_transfer" : "backend_rw_axi_rw_init_rw_obi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 1, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "rw_axi_rw_init_rw_obi", - "testbench": "tb_idma_backend_rw_axi_rw_init_rw_obi", - "synth_top": "idma_backend_synth_rw_axi_rw_init_rw_obi" - }, - "rw_axi_rw_axis": { - "jobs" : { - "simple" : "backend_rw_axi_rw_axis/simple.txt", - "same_dst" : "backend_rw_axi_rw_axis/same_dst.txt", - "linear" : "backend_rw_axi_rw_axis/linear.txt", - "huge" : "backend_rw_axi_rw_axis/huge.txt", - "large" : "backend_rw_axi_rw_axis/large.txt", - "medium" : "backend_rw_axi_rw_axis/medium.txt", - "mixed" : "backend_rw_axi_rw_axis/mixed.txt", - "small" : "backend_rw_axi_rw_axis/small.txt", - "tiny" : "backend_rw_axi_rw_axis/tiny.txt", - "zero_transfer" : "backend_rw_axi_rw_axis/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 0, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "rw_axi_rw_axis", - "testbench" : "tb_idma_backend_rw_axi_rw_axis", - "synth_top" : "idma_backend_synth_rw_axi_rw_axis" - }, - "rw_obi": { - "jobs" : { - "simple" : "backend_rw_obi/simple.txt", - "same_dst" : "backend_rw_obi/same_dst.txt", - "linear" : "backend_rw_obi/linear.txt", - "huge" : "backend_rw_obi/huge.txt", - "large" : "backend_rw_obi/large.txt", - "medium" : "backend_rw_obi/medium.txt", - "mixed" : "backend_rw_obi/mixed.txt", - "small" : "backend_rw_obi/small.txt", - "tiny" : "backend_rw_obi/tiny.txt", - "zero_transfer" : "backend_rw_obi/zero_transfer.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "CombinedShifter" : 0, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 0, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "rw_obi", - "testbench" : "tb_idma_backend_rw_obi", - "synth_top" : "idma_backend_synth_rw_obi" - }, - "4d_extension" : { - "jobs" : { - "simple" : "4d_extension/simple.txt", - "linear_2d" : "4d_extension/linear_2D.txt" - }, - "params" : { - "DataWidth" : 32, - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "NumAxInFlight" : 3, - "BufferDepth" : 3, - "TFLenWidth" : 32, - "MemSysDepth" : 0, - "NumDim" : 4, - "RepWidth" : 32, - "StrideWidth" : 32, - "CombinedShifter" : 0, - "MaskInvalidData" : 1, - "RAWCouplingAvail" : 1, - "HardwareLegalizer" : 1, - "RejectZeroTransfers" : 1, - "ErrorHandling" : 0 - }, - "proc_id" : "rw_axi", - "testbench": "tb_idma_nd_midend", - "synth_top": "idma_nd_midend_synth" + "rw_axi": { + "jobs": { + "simple": "backend_rw_axi/simple.txt", + "same_dst": "backend_rw_axi/same_dst.txt", + "linear": "backend_rw_axi/linear.txt", + "huge": "backend_rw_axi/huge.txt", + "large": "backend_rw_axi/large.txt", + "medium": "backend_rw_axi/medium.txt", + "mixed": "backend_rw_axi/mixed.txt", + "small": "backend_rw_axi/small.txt", + "tiny": "backend_rw_axi/tiny.txt", + "error_simple": "backend_rw_axi/error_simple.txt", + "error_mixed": "backend_rw_axi/error_mixed.txt", + "zero_transfer": "backend_rw_axi/zero_transfer.txt" }, - "desc64": { - "jobs" : { - "simple" : "jobs.json" - }, - "params" : { - }, - "proc_id" : "none", - "testbench" : "tb_idma_desc64_top", - "synth_top" : "idma_desc64_synth" + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 1, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 1 }, - "desc64_dma": { - "jobs" : { - "simple" : "jobs.json" - }, - "params" : { - }, - "proc_id" : "none", - "testbench" : "tb_idma_desc64_bench", - "synth_top" : "idma_desc64_synth" + "proc_id": "rw_axi", + "testbench": "tb_idma_backend_rw_axi", + "synth_top": "idma_backend_synth_rw_axi" + }, + "rw_axi_stall": { + "jobs": { + "simple": "backend_rw_axi/simple.txt", + "same_dst": "backend_rw_axi/same_dst.txt", + "linear": "backend_rw_axi/linear.txt", + "huge": "backend_rw_axi/huge.txt", + "large": "backend_rw_axi/large.txt", + "medium": "backend_rw_axi/medium.txt", + "mixed": "backend_rw_axi/mixed.txt", + "small": "backend_rw_axi/small.txt", + "tiny": "backend_rw_axi/tiny.txt", + "error_simple": "backend_rw_axi/error_simple.txt", + "error_mixed": "backend_rw_axi/error_mixed.txt", + "zero_transfer": "backend_rw_axi/zero_transfer.txt" }, - "rt_midend": { - "jobs" : { - "simple" : "jobs.json" - }, - "params" : { - }, - "proc_id" : "none", - "testbench" : "tb_idma_rt_midend", - "synth_top" : "idma_rt_midend_synth" + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 8, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 1, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 1 }, - "mp_midend": { - "jobs" : { - "simple" : "jobs.json" - }, - "params" : { - }, - "proc_id" : "none", - "testbench" : "idma_mp_midend_synth", - "synth_top" : "idma_mp_midend_synth" + "tb_params": { + "AXI_IdealMemory": 0, + "AXI_MemNumReqOutst": 2, + "AXI_MemLatency": 8, + "WatchDogNumCycles": 5000 }, - "mxquant" : { - "jobs" : { - }, - "params" : { - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "TFLenWidth" : 32 - }, - "testbench" : "tb_idma_mxquant", - "verify" : { - "dpi" : "idma_mxquant_dpi", - "token" : "[MXQ] ALL PASS", - "legs" : [ - { "tag" : "mxquant_32", "params" : { "DataWidth" : 32 } }, - { "tag" : "mxquant_64", "params" : { "DataWidth" : 64 } }, - { "tag" : "mxquant_256", "params" : { "DataWidth" : 256 } }, - { "tag" : "mxquant_512", "params" : { "DataWidth" : 512 } }, - { "tag" : "mxquant_1024", "params" : { "DataWidth" : 1024 } } - ] - } + "proc_id": "rw_axi", + "testbench": "tb_idma_backend_rw_axi", + "synth_top": "idma_backend_synth_rw_axi" + }, + "r_axi_w_obi": { + "jobs": { + "simple": "backend_r_axi_w_obi/simple.txt", + "same_dst": "backend_r_axi_w_obi/same_dst.txt", + "linear": "backend_r_axi_w_obi/linear.txt", + "huge": "backend_r_axi_w_obi/huge.txt", + "large": "backend_r_axi_w_obi/large.txt", + "medium": "backend_r_axi_w_obi/medium.txt", + "mixed": "backend_r_axi_w_obi/mixed.txt", + "small": "backend_r_axi_w_obi/small.txt", + "tiny": "backend_r_axi_w_obi/tiny.txt", + "zero_transfer": "backend_r_axi_w_obi/zero_transfer.txt" }, - "mxroundtrip" : { - "jobs" : { - }, - "params" : { - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "TFLenWidth" : 32 - }, - "testbench" : "tb_idma_mxroundtrip", - "verify" : { - "dpi" : "idma_mxquant_dpi", - "token" : "[MXRT] ALL PASS", - "legs" : [ - { "tag" : "mxroundtrip_32", "params" : { "DataWidth" : 32 } }, - { "tag" : "mxroundtrip_64", "params" : { "DataWidth" : 64 } }, - { "tag" : "mxroundtrip_256", "params" : { "DataWidth" : 256 } } - ], - "exclude" : [ - { "values" : [512, 1024], "why" : "heap abort during model construction, see #196" } - ] + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 0, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "r_axi_w_obi", + "testbench": "tb_idma_backend_r_axi_w_obi", + "synth_top": "idma_backend_synth_r_axi_w_obi" + }, + "r_obi_w_axi": { + "jobs": { + "simple": "backend_r_obi_w_axi/simple.txt", + "same_dst": "backend_r_obi_w_axi/same_dst.txt", + "linear": "backend_r_obi_w_axi/linear.txt", + "huge": "backend_r_obi_w_axi/huge.txt", + "large": "backend_r_obi_w_axi/large.txt", + "medium": "backend_r_obi_w_axi/medium.txt", + "mixed": "backend_r_obi_w_axi/mixed.txt", + "small": "backend_r_obi_w_axi/small.txt", + "tiny": "backend_r_obi_w_axi/tiny.txt", + "zero_transfer": "backend_r_obi_w_axi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 0, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "r_obi_w_axi", + "testbench": "tb_idma_backend_r_obi_w_axi", + "synth_top": "idma_backend_synth_r_obi_w_axi" + }, + "snitch_read": { + "jobs": { + "simple": "backend_r_axi_rw_init_rw_obi/simple.txt", + "same_dst": "backend_r_axi_rw_init_rw_obi/same_dst.txt", + "linear": "backend_r_axi_rw_init_rw_obi/linear.txt", + "huge": "backend_r_axi_rw_init_rw_obi/huge.txt", + "large": "backend_r_axi_rw_init_rw_obi/large.txt", + "medium": "backend_r_axi_rw_init_rw_obi/medium.txt", + "mixed": "backend_r_axi_rw_init_rw_obi/mixed.txt", + "small": "backend_r_axi_rw_init_rw_obi/small.txt", + "tiny": "backend_r_axi_rw_init_rw_obi/tiny.txt", + "zero_transfer": "backend_r_axi_rw_init_rw_obi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "r_axi_rw_init_rw_obi", + "testbench": "tb_idma_backend_r_axi_rw_init_rw_obi", + "synth_top": "idma_backend_synth_r_axi_rw_init_rw_obi" + }, + "snitch_init_read": { + "jobs": { + "simple": "backend_r_init_rw_axi_rw_obi/simple.txt", + "same_dst": "backend_r_init_rw_axi_rw_obi/same_dst.txt", + "linear": "backend_r_init_rw_axi_rw_obi/linear.txt", + "huge": "backend_r_init_rw_axi_rw_obi/huge.txt", + "large": "backend_r_init_rw_axi_rw_obi/large.txt", + "medium": "backend_r_init_rw_axi_rw_obi/medium.txt", + "mixed": "backend_r_init_rw_axi_rw_obi/mixed.txt", + "small": "backend_r_init_rw_axi_rw_obi/small.txt", + "tiny": "backend_r_init_rw_axi_rw_obi/tiny.txt", + "zero_transfer": "backend_r_init_rw_axi_rw_obi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "r_init_rw_axi_rw_obi", + "testbench": "tb_idma_backend_r_init_rw_axi_rw_obi", + "synth_top": "idma_backend_synth_r_init_rw_axi_rw_obi" + }, + "snitch_write": { + "jobs": { + "simple": "backend_r_obi_rw_init_w_axi/simple.txt", + "same_dst": "backend_r_obi_rw_init_w_axi/same_dst.txt", + "linear": "backend_r_obi_rw_init_w_axi/linear.txt", + "huge": "backend_r_obi_rw_init_w_axi/huge.txt", + "large": "backend_r_obi_rw_init_w_axi/large.txt", + "medium": "backend_r_obi_rw_init_w_axi/medium.txt", + "mixed": "backend_r_obi_rw_init_w_axi/mixed.txt", + "small": "backend_r_obi_rw_init_w_axi/small.txt", + "tiny": "backend_r_obi_rw_init_w_axi/tiny.txt", + "zero_transfer": "backend_r_obi_rw_init_w_axi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "r_obi_rw_init_w_axi", + "testbench": "tb_idma_backend_r_obi_rw_init_w_axi", + "synth_top": "idma_backend_synth_r_obi_rw_init_w_axi" + }, + "snitch_read_write": { + "jobs": { + "simple": "backend_rw_axi_rw_init_rw_obi/simple.txt", + "same_dst": "backend_rw_axi_rw_init_rw_obi/same_dst.txt", + "linear": "backend_rw_axi_rw_init_rw_obi/linear.txt", + "huge": "backend_rw_axi_rw_init_rw_obi/huge.txt", + "large": "backend_rw_axi_rw_init_rw_obi/large.txt", + "medium": "backend_rw_axi_rw_init_rw_obi/medium.txt", + "mixed": "backend_rw_axi_rw_init_rw_obi/mixed.txt", + "small": "backend_rw_axi_rw_init_rw_obi/small.txt", + "tiny": "backend_rw_axi_rw_init_rw_obi/tiny.txt", + "zero_transfer": "backend_rw_axi_rw_init_rw_obi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 1, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "rw_axi_rw_init_rw_obi", + "testbench": "tb_idma_backend_rw_axi_rw_init_rw_obi", + "synth_top": "idma_backend_synth_rw_axi_rw_init_rw_obi" + }, + "rw_axi_rw_axis": { + "jobs": { + "simple": "backend_rw_axi_rw_axis/simple.txt", + "same_dst": "backend_rw_axi_rw_axis/same_dst.txt", + "linear": "backend_rw_axi_rw_axis/linear.txt", + "huge": "backend_rw_axi_rw_axis/huge.txt", + "large": "backend_rw_axi_rw_axis/large.txt", + "medium": "backend_rw_axi_rw_axis/medium.txt", + "mixed": "backend_rw_axi_rw_axis/mixed.txt", + "small": "backend_rw_axi_rw_axis/small.txt", + "tiny": "backend_rw_axi_rw_axis/tiny.txt", + "zero_transfer": "backend_rw_axi_rw_axis/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 0, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "rw_axi_rw_axis", + "testbench": "tb_idma_backend_rw_axi_rw_axis", + "synth_top": "idma_backend_synth_rw_axi_rw_axis" + }, + "rw_obi": { + "jobs": { + "simple": "backend_rw_obi/simple.txt", + "same_dst": "backend_rw_obi/same_dst.txt", + "linear": "backend_rw_obi/linear.txt", + "huge": "backend_rw_obi/huge.txt", + "large": "backend_rw_obi/large.txt", + "medium": "backend_rw_obi/medium.txt", + "mixed": "backend_rw_obi/mixed.txt", + "small": "backend_rw_obi/small.txt", + "tiny": "backend_rw_obi/tiny.txt", + "zero_transfer": "backend_rw_obi/zero_transfer.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "CombinedShifter": 0, + "MaskInvalidData": 1, + "RAWCouplingAvail": 0, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "rw_obi", + "testbench": "tb_idma_backend_rw_obi", + "synth_top": "idma_backend_synth_rw_obi" + }, + "4d_extension": { + "jobs": { + "simple": "4d_extension/simple.txt", + "linear_2d": "4d_extension/linear_2D.txt" + }, + "params": { + "DataWidth": 32, + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "NumAxInFlight": 3, + "BufferDepth": 3, + "TFLenWidth": 32, + "MemSysDepth": 0, + "NumDim": 4, + "RepWidth": 32, + "StrideWidth": 32, + "CombinedShifter": 0, + "MaskInvalidData": 1, + "RAWCouplingAvail": 1, + "HardwareLegalizer": 1, + "RejectZeroTransfers": 1, + "ErrorHandling": 0 + }, + "proc_id": "rw_axi", + "testbench": "tb_idma_nd_midend", + "synth_top": "idma_nd_midend_synth" + }, + "desc64": { + "jobs": { + "simple": "jobs.json" + }, + "params": {}, + "proc_id": "none", + "testbench": "tb_idma_desc64_top", + "synth_top": "idma_desc64_synth" + }, + "desc64_dma": { + "jobs": { + "simple": "jobs.json" + }, + "params": {}, + "proc_id": "none", + "testbench": "tb_idma_desc64_bench", + "synth_top": "idma_desc64_synth" + }, + "rt_midend": { + "jobs": { + "simple": "jobs.json" + }, + "params": {}, + "proc_id": "none", + "testbench": "tb_idma_rt_midend", + "synth_top": "idma_rt_midend_synth" + }, + "mp_midend": { + "jobs": { + "simple": "jobs.json" + }, + "params": {}, + "proc_id": "none", + "testbench": "tb_idma_mp_midend", + "synth_top": "idma_mp_midend_synth", + "verify": { + "token": "[MID] ALL PASS", + "legs": [ + { + "tag": "mp_midend_4x4k", + "params": { + "NumBEs": 4, + "RegionWidth": 4096 + } + }, + { + "tag": "mp_midend_8x1k", + "params": { + "NumBEs": 8, + "RegionWidth": 1024 + } } + ] + } + }, + "mxquant": { + "jobs": {}, + "params": { + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "TFLenWidth": 32 }, - "transpose" : { - "jobs" : { - }, - "params" : { - }, - "testbench" : "tb_idma_otf_transpose", - "verify" : { - "dpi" : "idma_transpose_dpi", - "token" : "[TB] ALL PASS", - "legs" : [ - { "tag" : "otf_transpose", "params" : { "StrbWidth" : 8, "FullDuplex" : 1 } }, - { "tag" : "otf_transpose_bp", "params" : { "StrbWidth" : 8, "FullDuplex" : 1 }, "plusargs" : ["+BP"] }, - { "tag" : "otf_transpose_8_0", "params" : { "StrbWidth" : 8, "FullDuplex" : 0 }, "plusargs" : ["+BP"] }, - { "tag" : "otf_transpose_64_1", "params" : { "StrbWidth" : 64, "FullDuplex" : 1 }, "plusargs" : ["+BP"] }, - { "tag" : "otf_transpose_64_0", "params" : { "StrbWidth" : 64, "FullDuplex" : 0 }, "plusargs" : ["+BP"] } - ] + "testbench": "tb_idma_mxquant", + "verify": { + "dpi": "idma_mxquant_dpi", + "token": "[MXQ] ALL PASS", + "legs": [ + { + "tag": "mxquant_32", + "params": { + "DataWidth": 32 + } + }, + { + "tag": "mxquant_64", + "params": { + "DataWidth": 64 + } + }, + { + "tag": "mxquant_256", + "params": { + "DataWidth": 256 + } + }, + { + "tag": "mxquant_512", + "params": { + "DataWidth": 512 + } + }, + { + "tag": "mxquant_1024", + "params": { + "DataWidth": 1024 + } } + ] + } + }, + "mxroundtrip": { + "jobs": {}, + "params": { + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "TFLenWidth": 32 }, - "transpose_midend" : { - "jobs" : { - }, - "params" : { - "AddrWidth" : 64 - }, - "testbench" : "tb_idma_transpose_midend", - "verify" : { - "dpi" : "idma_transpose_dpi", - "token" : "[MID] ALL PASS", - "legs" : [ - { "tag" : "transpose_midend_64", "params" : { "DataWidth" : 64 } }, - { "tag" : "transpose_midend_512", "params" : { "DataWidth" : 512 } } - ] + "testbench": "tb_idma_mxroundtrip", + "verify": { + "dpi": "idma_mxquant_dpi", + "token": "[MXRT] ALL PASS", + "legs": [ + { + "tag": "mxroundtrip_32", + "params": { + "DataWidth": 32 + } + }, + { + "tag": "mxroundtrip_64", + "params": { + "DataWidth": 64 + } + }, + { + "tag": "mxroundtrip_256", + "params": { + "DataWidth": 256 + } + } + ], + "exclude": [ + { + "values": [ + 512, + 1024 + ], + "why": "heap abort during model construction, see #196" } + ] + } + }, + "transpose": { + "jobs": {}, + "params": {}, + "testbench": "tb_idma_otf_transpose", + "verify": { + "dpi": "idma_transpose_dpi", + "token": "[TB] ALL PASS", + "legs": [ + { + "tag": "otf_transpose", + "params": { + "StrbWidth": 8, + "FullDuplex": 1 + } + }, + { + "tag": "otf_transpose_bp", + "params": { + "StrbWidth": 8, + "FullDuplex": 1 + }, + "plusargs": [ + "+BP" + ] + }, + { + "tag": "otf_transpose_8_0", + "params": { + "StrbWidth": 8, + "FullDuplex": 0 + }, + "plusargs": [ + "+BP" + ] + }, + { + "tag": "otf_transpose_64_1", + "params": { + "StrbWidth": 64, + "FullDuplex": 1 + }, + "plusargs": [ + "+BP" + ] + }, + { + "tag": "otf_transpose_64_0", + "params": { + "StrbWidth": 64, + "FullDuplex": 0 + }, + "plusargs": [ + "+BP" + ] + } + ] + } + }, + "transpose_midend": { + "jobs": {}, + "params": { + "AddrWidth": 64 }, - "mxclear" : { - "jobs" : { - }, - "params" : { - "StrbWidth" : 8 - }, - "testbench" : "tb_idma_mxclear", - "verify" : { - "expect" : "fail", - "defines" : ["INC_ASSERT"], - "token" : "clear with in-flight state", - "legs" : [ - { "tag" : "mxclear_1", "params" : { "Quant" : 1 } }, - { "tag" : "mxclear_0", "params" : { "Quant" : 0 } } - ] + "testbench": "tb_idma_transpose_midend", + "verify": { + "dpi": "idma_transpose_dpi", + "token": "[MID] ALL PASS", + "legs": [ + { + "tag": "transpose_midend_64", + "params": { + "DataWidth": 64 + } + }, + { + "tag": "transpose_midend_512", + "params": { + "DataWidth": 512 + } } + ] + } + }, + "mxclear": { + "jobs": {}, + "params": { + "StrbWidth": 8 }, - "mxneg" : { - "jobs" : { - }, - "params" : { - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "TFLenWidth" : 32 - }, - "testbench" : "tb_idma_mxneg", - "verify" : { - "dpi" : "idma_mxquant_dpi", - "expect" : "fail", - "defines" : ["INC_ASSERT"], - "legs" : [ - { "tag" : "mxneg_1", "params" : { "NegCase" : 1, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeSizeAligned" }, - { "tag" : "mxneg_2", "params" : { "NegCase" : 2, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeSrcAligned" }, - { "tag" : "mxneg_3", "params" : { "NegCase" : 3, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeDstAligned" }, - { "tag" : "mxneg_5", "params" : { "NegCase" : 5, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeMxdequantBeatAligned" }, - { "tag" : "mxneg_6", "params" : { "NegCase" : 6, "DataWidth" : 64, "EnDequant" : 0, "EnFp16" : 1 }, "token" : "ComputeOpUnsupported" }, - { "tag" : "mxneg_7", "params" : { "NegCase" : 7, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeMxSrcProtocol" }, - { "tag" : "mxneg_8", "params" : { "NegCase" : 8, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeMxDstProtocol" }, - { "tag" : "mxneg_10", "params" : { "NegCase" : 10, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 1 }, "token" : "ComputeTransposeSingleBeat" }, - { "tag" : "mxneg_13", "params" : { "NegCase" : 13, "DataWidth" : 64, "EnDequant" : 1, "EnFp16" : 0 }, "token" : "ComputeOpUnsupported" } - ], - "exclude" : [ - { "case" : 4, "why" : "DataWidth 1024 SIGSEGVs on verilator 5.020; passes on 5.046" }, - { "case" : 11, "why" : "the request is never accepted, so the guard is never sampled" }, - { "case" : 12, "why" : "DataWidth 1024 SIGSEGVs on verilator 5.020; passes on 5.046" } - ] + "testbench": "tb_idma_mxclear", + "verify": { + "expect": "fail", + "defines": [ + "INC_ASSERT" + ], + "token": "clear with in-flight state", + "legs": [ + { + "tag": "mxclear_1", + "params": { + "Quant": 1 + } + }, + { + "tag": "mxclear_0", + "params": { + "Quant": 0 + } } + ] + } + }, + "mxneg": { + "jobs": {}, + "params": { + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "TFLenWidth": 32 }, - "mxperf" : { - "jobs" : { - }, - "params" : { - "AddrWidth" : 32, - "UserWidth" : 1, - "AxiIdWidth" : 12, - "TFLenWidth" : 32 - }, - "testbench" : "tb_idma_mxperf", - "verify" : { - "token" : "[MXPF] ALL PASS", - "legs" : [ - { "tag" : "mxperf_32", "params" : { "DataWidth" : 32 } }, - { "tag" : "mxperf_64", "params" : { "DataWidth" : 64 } } - ] + "testbench": "tb_idma_mxneg", + "verify": { + "dpi": "idma_mxquant_dpi", + "expect": "fail", + "defines": [ + "INC_ASSERT" + ], + "legs": [ + { + "tag": "mxneg_1", + "params": { + "NegCase": 1, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeSizeAligned" + }, + { + "tag": "mxneg_2", + "params": { + "NegCase": 2, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeSrcAligned" + }, + { + "tag": "mxneg_3", + "params": { + "NegCase": 3, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeDstAligned" + }, + { + "tag": "mxneg_5", + "params": { + "NegCase": 5, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeMxdequantBeatAligned" + }, + { + "tag": "mxneg_6", + "params": { + "NegCase": 6, + "DataWidth": 64, + "EnDequant": 0, + "EnFp16": 1 + }, + "token": "ComputeOpUnsupported" + }, + { + "tag": "mxneg_7", + "params": { + "NegCase": 7, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeMxSrcProtocol" + }, + { + "tag": "mxneg_8", + "params": { + "NegCase": 8, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeMxDstProtocol" + }, + { + "tag": "mxneg_10", + "params": { + "NegCase": 10, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 1 + }, + "token": "ComputeTransposeSingleBeat" + }, + { + "tag": "mxneg_13", + "params": { + "NegCase": 13, + "DataWidth": 64, + "EnDequant": 1, + "EnFp16": 0 + }, + "token": "ComputeOpUnsupported" + } + ], + "exclude": [ + { + "case": 4, + "why": "DataWidth 1024 SIGSEGVs on verilator 5.020; passes on 5.046" + }, + { + "case": 11, + "why": "the request is never accepted, so the guard is never sampled" + }, + { + "case": 12, + "why": "DataWidth 1024 SIGSEGVs on verilator 5.020; passes on 5.046" } + ] + } + }, + "mxperf": { + "jobs": {}, + "params": { + "AddrWidth": 32, + "UserWidth": 1, + "AxiIdWidth": 12, + "TFLenWidth": 32 }, - "_verify" : { - "elab_widths" : [32, 64, 512, 1024], - "elab_compute" : [ - { "width" : 64, "ops" : 15, "tuning" : 1 }, - { "width" : 512, "ops" : 15, "tuning" : 1 }, - { "width" : 64, "ops" : 8, "tuning" : 0 }, - { "width" : 64, "ops" : 6, "tuning" : 1 } - ], - "elab_shared_tops" : [ - "idma_desc64_synth", "idma_nd_midend_synth", - "idma_mp_midend_synth", "idma_rt_midend_synth" - ], - "multihead_ids" : ["2r_axi_w_axi", "2rw_axi"], - "reg_variants" : [ - { "variant" : 3, "module" : "idma_reg32_3d" }, - { "variant" : 2, "module" : "idma_reg64_2d" }, - { "variant" : 1, "module" : "idma_reg64_1d" } - ], - "elab_covered_elsewhere" : ["tb_idma_reg_frontend"], - "guards_untested" : [ - { "guard" : "ComputeMxFp16Width", "why" : "only reachable from the excluded 1024 cases" }, - { "guard" : "ComputeMxdequantLengthFits", "why" : "case 11 is never accepted" }, - { "guard" : "ComputeDstTilelink", "why" : "no TileLink backend variant exists" } - ], - "tops_untested" : [ - { "top" : "tb_idma_nd_midend_b2b", "why" : "hangs ([B2B] timeout); latent reset/LFSR race" }, - { "top" : "tb_idma_transpose_nd", - "why" : "verilator only: the ND response never fires once the first case drains" }, - { "top" : "tb_idma_transpose_b2b", - "why" : "verilator only: the first geometry never completes, watchdog trip" }, - { "top" : "tb_idma_mxrand", - "why" : "verilator only: transfer 1 never completes, even at NumXfers=1 StallPct=0" }, - { "top" : "tb_idma_rt_midend", "why" : "fails under --assert on cc_rr_arb_tree lock" }, - { "top" : "the directed backend job runs", "why" : "verilator cannot drive the class-based stimulus" } - ] + "testbench": "tb_idma_mxperf", + "verify": { + "token": "[MXPF] ALL PASS", + "legs": [ + { + "tag": "mxperf_32", + "params": { + "DataWidth": 32 + } + }, + { + "tag": "mxperf_64", + "params": { + "DataWidth": 64 + } + } + ] } + }, + "_verify": { + "elab_widths": [ + 32, + 64, + 512, + 1024 + ], + "elab_compute": [ + { + "width": 64, + "ops": 15, + "tuning": 1 + }, + { + "width": 512, + "ops": 15, + "tuning": 1 + }, + { + "width": 64, + "ops": 8, + "tuning": 0 + }, + { + "width": 64, + "ops": 6, + "tuning": 1 + } + ], + "elab_shared_tops": [ + "idma_desc64_synth", + "idma_nd_midend_synth", + "idma_mp_midend_synth", + "idma_rt_midend_synth" + ], + "multihead_ids": [ + "2r_axi_w_axi", + "2rw_axi" + ], + "reg_variants": [ + { + "variant": 3, + "module": "idma_reg32_3d" + }, + { + "variant": 2, + "module": "idma_reg64_2d" + }, + { + "variant": 1, + "module": "idma_reg64_1d" + } + ], + "elab_covered_elsewhere": [ + "tb_idma_reg_frontend" + ], + "guards_untested": [ + { + "guard": "ComputeMxFp16Width", + "why": "only reachable from the excluded 1024 cases" + }, + { + "guard": "ComputeMxdequantLengthFits", + "why": "case 11 is never accepted" + }, + { + "guard": "ComputeDstTilelink", + "why": "no TileLink backend variant exists" + } + ], + "tops_untested": [ + { + "top": "tb_idma_nd_midend_b2b", + "why": "hangs ([B2B] timeout); latent reset/LFSR race" + }, + { + "top": "tb_idma_transpose_nd", + "why": "verilator only: the ND response never fires once the first case drains" + }, + { + "top": "tb_idma_transpose_b2b", + "why": "verilator only: the first geometry never completes, watchdog trip" + }, + { + "top": "tb_idma_mxrand", + "why": "verilator only: transfer 1 never completes, even at NumXfers=1 StallPct=0" + }, + { + "top": "tb_idma_rt_midend", + "why": "fails under --assert on cc_rr_arb_tree lock" + }, + { + "top": "the directed backend job runs", + "why": "verilator cannot drive the class-based stimulus" + } + ] + } } diff --git a/src/backend/tpl/idma_legalizer.sv.tpl b/src/backend/tpl/idma_legalizer.sv.tpl index 4806a3209..e2be53ecd 100644 --- a/src/backend/tpl/idma_legalizer.sv.tpl +++ b/src/backend/tpl/idma_legalizer.sv.tpl @@ -170,7 +170,9 @@ ${database[p]['max_beats_per_burst']} * StrbWidth > ${database[p]['page_size']}\ % endif % endfor page_len_t w_num_bytes_to_pb; +% if not always_decoupled: page_len_t c_num_bytes_to_pb; +% endif // read process page_len_t r_num_bytes_possible; @@ -351,16 +353,23 @@ w_num_bytes_to_pb = w_page_num_bytes_to_pb; //-------------------------------------- // page boundary check //-------------------------------------- +% if not always_decoupled: // how many transfers are remaining when concerning both r/w pages? // take the boundary that is closer assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? w_num_bytes_to_pb : r_num_bytes_to_pb; +% endif //-------------------------------------- // Synchronized R/W process //-------------------------------------- always_comb begin : proc_num_bytes_possible +% if always_decoupled: + // Every protocol here forces decoupling: never coupled + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; +% else: // Default: Coupled r_num_bytes_possible = c_num_bytes_to_pb; w_num_bytes_possible = c_num_bytes_to_pb; @@ -392,6 +401,7 @@ w_num_bytes_to_pb = w_page_num_bytes_to_pb; r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end +% endif end assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; @@ -644,6 +654,14 @@ ${database[protocol]['legalizer_write_data_path']} // * rw_decoupled: either machine advances always_comb begin : proc_legalizer_flow_control +% if always_decoupled: + // Every protocol here forces decoupling: never coupled + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; +% else: if ( opt_tf_q.decouple_rw\ % if len(used_non_bursting_or_force_decouple_read_protocols) != 0: @@ -680,6 +698,7 @@ ${database[protocol]['legalizer_write_data_path']} r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; end +% endif end // load next idma request: if both machines are done! diff --git a/src/frontend/inst64/idma_inst64_top.sv b/src/frontend/inst64/idma_inst64_top.sv index 1edfe626a..1479db7a4 100644 --- a/src/frontend/inst64/idma_inst64_top.sv +++ b/src/frontend/inst64/idma_inst64_top.sv @@ -20,6 +20,8 @@ module idma_inst64_top #( parameter int unsigned NumAxInFlight = 32'd3, parameter int unsigned DMAReqFifoDepth = 32'd3, parameter int unsigned NumChannels = 32'd1, + /// Number of ND dimensions; the transpose midend needs at least 4 + parameter int unsigned NumDim = 32'd2, parameter bit TCDMAliasEnable = 1'b0, parameter int unsigned DMATracing = 32'd0, parameter type axi_ar_chan_t = logic, @@ -69,7 +71,6 @@ module idma_inst64_top #( localparam int unsigned TfIdWidth = 32'd32; localparam int unsigned TFLenWidth = AxiAddrWidth; localparam int unsigned RepWidth = 32'd32; - localparam int unsigned NumDim = 32'd2; localparam int unsigned BufferDepth = 32'd3; localparam int unsigned NumRules = 32'd5; localparam int unsigned AwInFlightCntWidth = diff --git a/src/include/idma/typedef.svh b/src/include/idma/typedef.svh index 642923f09..f1836f808 100644 --- a/src/include/idma/typedef.svh +++ b/src/include/idma/typedef.svh @@ -58,11 +58,11 @@ // iDMA Full Request and Response Structs // // Usage Example: -// `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t) +// `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t[, user_t]) // `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, axi_addr_t) -`define IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t) \ +`define IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, axi_id_t, axi_addr_t, tf_len_t, user_t = logic) \ `IDMA_TYPEDEF_OPTIONS_T(options_t, axi_id_t) \ - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, axi_addr_t, options_t) + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, axi_addr_t, options_t, user_t) `define IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, axi_addr_t) \ `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, axi_addr_t) \ `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) diff --git a/src/midend/idma_mp_dist_midend.sv b/src/midend/idma_mp_dist_midend.sv index 99b34c04e..40ee1bb96 100644 --- a/src/midend/idma_mp_dist_midend.sv +++ b/src/midend/idma_mp_dist_midend.sv @@ -160,11 +160,9 @@ module idma_mp_dist_midend #( if (($unsigned(idma_req_i.src_addr) >= RegionStart) && ($unsigned(idma_req_i.src_addr) < RegionEnd )) begin idma_req_o[i].src_addr[FullRegionAddressBits-1:0] = i*RegionWidth; - idma_req_o[i].dst_addr = idma_req_i.dst_addr + i*RegionWidth - - start_addr[DmaRegionAddressBits-1:0]; + idma_req_o[i].dst_addr = idma_req_i.dst_addr + i*RegionWidth - start_addr; end else begin - idma_req_o[i].src_addr = idma_req_i.src_addr + i*RegionWidth - - start_addr[DmaRegionAddressBits-1:0]; + idma_req_o[i].src_addr = idma_req_i.src_addr + i*RegionWidth - start_addr; idma_req_o[i].dst_addr[FullRegionAddressBits-1:0] = i*RegionWidth; end if ($unsigned(end_addr) >= (i+1)*RegionWidth) begin diff --git a/test/midend/tb_idma_mp_midend.sv b/test/midend/tb_idma_mp_midend.sv new file mode 100644 index 000000000..d5acedc21 --- /dev/null +++ b/test/midend/tb_idma_mp_midend.sv @@ -0,0 +1,176 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Daniel Keller + +`include "idma/typedef.svh" + +/// Unit check for idma_mp_dist_midend: every slice must carry the region-local +/// address on the distributed side and the correctly rebased address on the +/// counterpart side. Covers transfers starting in a non-zero region, which is +/// where truncating the start address silently mis-rebases every slice after +/// the first. +module tb_idma_mp_midend #( + parameter int unsigned NumBEs = 32'd4, + parameter int unsigned RegionWidth = 32'h1000, + parameter int unsigned AddrWidth = 32'd32, + parameter int unsigned UserWidth = 32'd36 +); + + localparam int unsigned RegionStart = 32'h0000_0000; + localparam int unsigned RegionEnd = RegionStart + NumBEs * RegionWidth; + localparam int unsigned NotInvolvedLen = 32'd1; + + typedef logic [UserWidth-1:0] user_t; + typedef logic [AddrWidth-1:0] addr_t; + typedef logic [ 31:0] tf_len_t; + typedef logic [ 2:0] id_t; + + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t, user_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) + + // recognisable pattern, wider than 32 bits to prove the type is carried + localparam user_t UserTag = user_t'(36'h9_ABCD_EF12); + + logic clk, rst_n; + + idma_req_t req_in; + idma_req_t [NumBEs-1:0] req_out; + logic [NumBEs-1:0] req_valid_out, req_ready_in, rsp_valid_in, rsp_ready_out; + idma_rsp_t [NumBEs-1:0] rsp_in; + idma_pkg::idma_busy_t [NumBEs-1:0] busy_in; + + assign req_ready_in = '1; + assign rsp_valid_in = '0; + assign rsp_in = '0; + assign busy_in = '0; + + idma_mp_dist_midend #( + .NumBEs ( NumBEs ), + .RegionWidth ( RegionWidth ), + .RegionStart ( RegionStart ), + .RegionEnd ( RegionEnd ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ) + ) i_dut ( + .clk_i ( clk ), + .rst_ni ( rst_n ), + .idma_req_i ( req_in ), + .idma_req_valid_i ( 1'b0 ), + .idma_req_ready_o ( ), + .idma_rsp_o ( ), + .idma_rsp_valid_o ( ), + .idma_rsp_ready_i ( 1'b1 ), + .idma_busy_o ( ), + .idma_req_o ( req_out ), + .idma_req_valid_o ( req_valid_out ), + .idma_req_ready_i ( req_ready_in ), + .idma_rsp_i ( rsp_in ), + .idma_rsp_valid_i ( rsp_valid_in ), + .idma_rsp_ready_o ( rsp_ready_out ), + .idma_busy_i ( busy_in ) + ); + + initial begin + clk = 1'b0; + forever #0.5ns clk = ~clk; + end + + int errs = 0; + + task automatic chk(input string name, input logic [63:0] got, input logic [63:0] exp); + if (got !== exp) begin + errs++; + $display("[MID] %s: got 0x%0h exp 0x%0h", name, got, exp); + end + endtask + + /// Check one slice of a transfer whose distributed side is `src`. + task automatic chk_slice(input string name, + input int unsigned i, + input logic [63:0] exp_src, + input logic [63:0] exp_dst, + input logic [63:0] exp_len); + chk($sformatf("%s be%0d src", name, i), req_out[i].src_addr, exp_src); + chk($sformatf("%s be%0d dst", name, i), req_out[i].dst_addr, exp_dst); + chk($sformatf("%s be%0d len", name, i), req_out[i].length, exp_len); + // metadata, the user field included, is forwarded untouched + chk($sformatf("%s be%0d user", name, i), 64'(req_out[i].user), 64'(UserTag)); + endtask + + /// A back-end outside the transfer emits the tie-off request, not a slice. + task automatic chk_idle(input string name, input int unsigned i); + chk($sformatf("%s be%0d len", name, i), req_out[i].length, NotInvolvedLen); + chk($sformatf("%s be%0d src", name, i), req_out[i].src_addr, '0); + chk($sformatf("%s be%0d dst", name, i), req_out[i].dst_addr, '0); + endtask + + task automatic drive(input logic [63:0] src, input logic [63:0] dst, input logic [63:0] len); + req_in = '0; + req_in.src_addr = addr_t'(src); + req_in.dst_addr = addr_t'(dst); + req_in.length = tf_len_t'(len); + req_in.user = UserTag; + #1ns; + endtask + + // Counterpart base, well clear of the distributed region. + localparam longint unsigned CpBase = 64'h0010_0000; + localparam longint unsigned RW = 64'(RegionWidth); + localparam longint unsigned Half = RW / 2; + + /// Every back-end outside [lo, hi] must carry the tie-off request. + task automatic chk_idle_outside(input string name, input int unsigned lo, input int unsigned hi); + for (int unsigned i = 0; i < NumBEs; i++) begin + if (i < lo || i > hi) chk_idle(name, i); + end + endtask + + initial begin + req_in = '0; + rst_n = 1'b0; + #5ns; + rst_n = 1'b1; + #5ns; + + // --- Start half way into region 1 and run one region long, so the transfer + // --- ends half way into region 2. Slice 2 is rebased, and its counterpart + // --- address is only right if the whole start address is subtracted. + drive(RW + Half, CpBase, RW); + chk_slice("r1span", 1, RW + Half, CpBase, RW - Half); + chk_slice("r1span", 2, 2*RW, CpBase + Half, Half); + chk_idle_outside("r1span", 1, 2); + + // --- The same shape starting in region 0, where truncating the start + // --- address is a no-op. Guards the fix against over-correcting. + drive(Half, CpBase, RW); + chk_slice("r0span", 0, Half, CpBase, RW - Half); + chk_slice("r0span", 1, RW, CpBase + RW - Half, Half); + chk_idle_outside("r0span", 0, 1); + + // --- Distributed side on the destination; the source is the counterpart. + drive(CpBase, RW + Half, RW); + chk_slice("dstdist", 1, CpBase, RW + Half, RW - Half); + chk_slice("dstdist", 2, CpBase + Half, 2*RW, Half); + chk_idle_outside("dstdist", 1, 2); + + // --- Wholly inside one region: a single slice carries the full length. + drive(RW + Half, CpBase, Half / 2); + chk_slice("single", 1, RW + Half, CpBase, Half / 2); + chk_idle_outside("single", 1, 1); + + // --- Full span: every back-end takes exactly one region. + drive(64'd0, CpBase, 64'(NumBEs) * RW); + for (int unsigned i = 0; i < NumBEs; i++) begin + chk_slice("fullspan", i, 64'(i) * RW, CpBase + 64'(i) * RW, RW); + end + + if (errs == 0) $display("[MID] ALL PASS (NumBEs=%0d RegionWidth=0x%0h)", NumBEs, RegionWidth); + else $fatal(1, "[MID] FAIL: %0d mismatches", errs); + $finish; + end + +endmodule diff --git a/util/mario/legalizer.py b/util/mario/legalizer.py index 517e1885d..52ec98fb7 100644 --- a/util/mario/legalizer.py +++ b/util/mario/legalizer.py @@ -62,6 +62,12 @@ def render_legalizer(prot_ids: dict, db: dict, tpl_file: str) -> str: has_page_write_bursting = eval_key(used_write_prots, 'bursts', 'split_at_page_boundary', db) has_pow2_write_bursting = eval_key(used_write_prots, 'bursts', 'only_pow2', db) has_write_bursting = has_page_write_bursting or has_pow2_write_bursting + # A port whose every protocol forces decoupling can never run coupled, so the + # runtime protocol test collapses to a constant. + all_read_force_decouple = len(used_read_prots) != 0 and \ + set(prot_force_decouple(used_read_prots, db)) == set(used_read_prots) + all_write_force_decouple = len(used_write_prots) != 0 and \ + set(prot_force_decouple(used_write_prots, db)) == set(used_write_prots) # assemble context context = { 'name_uniqueifier': prot_id, @@ -91,7 +97,9 @@ def render_legalizer(prot_ids: dict, db: dict, tpl_file: str) -> str: 'used_non_bursting_or_force_decouple_read_protocols': prot_force_decouple(used_read_prots, db), 'used_non_bursting_or_force_decouple_write_protocols': - prot_force_decouple(used_write_prots, db) + prot_force_decouple(used_write_prots, db), + 'always_decoupled': + all_read_force_decouple or all_write_force_decouple } # render