diff --git a/Bender.lock b/Bender.lock index caa3519b..018ea78a 100644 --- a/Bender.lock +++ b/Bender.lock @@ -7,8 +7,8 @@ packages: dependencies: - common_cells axi: - revision: a256a3b86394fedf19e361047fccfdd7f6ef83e4 - version: 0.39.9 + revision: a8c53cee2520d328d390c507c88818e8ac144c8c + version: 0.39.10 source: Git: https://github.com/pulp-platform/axi.git dependencies: @@ -23,8 +23,8 @@ packages: dependencies: - common_cells common_cells: - revision: 9ca8a7655f741e7dd5736669a20a301325194c28 - version: 1.39.0 + revision: 1281545696eb3fcba50ec5b4275993476a3c710e + version: 1.40.0 source: Git: https://github.com/pulp-platform/common_cells.git dependencies: @@ -44,19 +44,9 @@ packages: dependencies: - common_cells - common_verification - register_interface: - revision: d6e1d4cdaab7870f4faf3f88a1c788eaf5ac129d - version: 0.4.7 - source: - Git: https://github.com/pulp-platform/register_interface.git - dependencies: - - apb - - axi - - common_cells - - common_verification tech_cells_generic: - revision: 7968dd6e6180df2c644636bc6d2908a49f2190cf - version: 0.2.13 + revision: 3a3de73632a06826b1bd9c65a0a2e92b32016845 + version: 0.2.14 source: Git: https://github.com/pulp-platform/tech_cells_generic.git dependencies: diff --git a/Bender.yml b/Bender.yml index 2049f69e..e5ff5e8d 100644 --- a/Bender.yml +++ b/Bender.yml @@ -18,7 +18,6 @@ dependencies: axi_stream: { git: "https://github.com/pulp-platform/axi_stream.git", version: 0.1.1 } common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.39.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.5 } - register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.7 } apb: { git: "https://github.com/pulp-platform/apb.git", version: 0.2.4 } obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.7 } diff --git a/idma.mk b/idma.mk index 879be491..8e6bb18f 100644 --- a/idma.mk +++ b/idma.mk @@ -119,7 +119,7 @@ IDMA_RTL_FILES := $(IDMA_RTL_DIR)/idma_transport_layer \ IDMA_VSIM_DIR := $(IDMA_ROOT)/target/sim/vsim define idma_gen - $(PYTHON) $(IDMA_GEN) --entity $1 --tpl $2 --db $3 --ids $4 --fids $5 $(if $7,--compute-ids $7) > $6 + $(PYTHON) $(IDMA_GEN) --entity $1 --tpl $2 --db $3 --ids $4 --fids $5 $(if $7,--compute-ids $7) $(if $8,--cpuif $8) > $6 endef # Force an RTL regen when IDMA_VIDMA_IDS changes; rewritten only on change @@ -182,6 +182,10 @@ IDMA_FE_DIR := $(IDMA_ROOT)/src/frontend IDMA_FE_REGS := desc64 IDMA_FE_REGS += $(IDMA_FE_IDS) +# Config-bus CPUIF for the register frontend: PeakRDL regblock --cpuif + matching wrapper +# packing. apb4-flat (default, industry standard); also obi-flat / passthrough / axi4-lite-flat. +IDMA_REG_CPUIF ?= apb4-flat + regwidth = $(word 1,$(subst _, ,$1)) dimension = $(word 2,$(subst _, ,$1)) @@ -189,7 +193,7 @@ log2dimension = $(shell echo $$(( $$( echo "obase=2;$$(($(1)-1))" | bc | wc -c ) $(IDMA_RTL_DIR)/idma_reg%d_reg_pkg.sv $(IDMA_RTL_DIR)/idma_reg%d_reg_top.sv $(IDMA_RTL_DIR)/idma_reg%d_addrmap_pkg.sv: $(PEAKRDL) regblock $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $(IDMA_RTL_DIR) \ - --default-reset arst_n --cpuif apb4-flat \ + --default-reset arst_n --cpuif $(IDMA_REG_CPUIF) \ --module-name idma_reg$*d_reg_top \ --package idma_reg$*d_reg_pkg \ -P SysAddrWidth=$(call regwidth,$*) \ @@ -205,6 +209,8 @@ $(IDMA_RTL_DIR)/idma_reg%d_reg_pkg.sv $(IDMA_RTL_DIR)/idma_reg%d_reg_top.sv $(ID -P Log2NumDims=$(call log2dimension,$(call dimension,$*)) $(IDMA_RTL_DIR)/idma_desc64_reg_pkg.sv $(IDMA_RTL_DIR)/idma_desc64_reg_top.sv $(IDMA_RTL_DIR)/idma_desc64_addrmap_pkg.sv: + # desc64 has static, hand-written APB reg wrappers (idma_desc64_reg_wrapper.sv); it is + # APB-native and not part of the CPUIF selector — keep its reg_top apb4-flat. $(PEAKRDL) regblock $(IDMA_FE_DIR)/desc64/idma_desc64_reg.rdl -o $(IDMA_RTL_DIR) \ --default-reset arst_n --cpuif apb4-flat \ --module-name idma_desc64_reg_top \ @@ -216,7 +222,7 @@ $(IDMA_RTL_DIR)/idma_desc64_reg_pkg.sv $(IDMA_RTL_DIR)/idma_desc64_reg_top.sv $( --license_str="Copyright 2025 ETH Zurich and University of Bologna.\nSolderpad Hardware License, Version 0.51, see LICENSE for details.\nSPDX-License-Identifier: SHL-0.51" $(IDMA_RTL_DIR)/idma_%_top.sv: $(IDMA_GEN) $(IDMA_FE_DIR)/reg/tpl/idma_reg.sv.tpl - $(call idma_gen,reg_top,$(IDMA_FE_DIR)/reg/tpl/idma_reg.sv.tpl,,,$*,$@) + $(call idma_gen,reg_top,$(IDMA_FE_DIR)/reg/tpl/idma_reg.sv.tpl,,,$*,$@,,$(if $(filter desc64,$*),apb4-flat,$(IDMA_REG_CPUIF))) $(IDMA_HTML_DIR)/regs/idma_reg%d_reg/index.html: $(PEAKRDL) html $(IDMA_FE_DIR)/reg/idma_reg.rdl -o $(IDMA_HTML_DIR)/regs/idma_reg$*d_reg \ diff --git a/src/frontend/reg/tpl/idma_reg.sv.tpl b/src/frontend/reg/tpl/idma_reg.sv.tpl index 7c00f349..a1ea9175 100644 --- a/src/frontend/reg/tpl/idma_reg.sv.tpl +++ b/src/frontend/reg/tpl/idma_reg.sv.tpl @@ -6,7 +6,26 @@ // - Michael Rogenmoser // - Thomas Benz +<% + # Config-bus CPUIF family, derived from --cpuif (idma.mk IDMA_REG_CPUIF). The wrapper packs + # the PeakRDL reg_top's flat CPUIF signals into the matching req/rsp struct; the reg_top is + # generated with the same --cpuif so its port set matches the branch selected here. + if cpuif.startswith('apb'): + _fam = 'apb' + elif cpuif.startswith('obi'): + _fam = 'obi' + elif cpuif.startswith('axi4-lite'): + _fam = 'axil' + else: + raise Exception("idma_reg.sv.tpl: unsupported register CPUIF '%s' (add a branch)" % cpuif) +%>\ +% if _fam == 'apb': `include "apb/typedef.svh" +% elif _fam == 'obi': +`include "obi/typedef.svh" +% elif _fam == 'axil': +`include "axi/typedef.svh" +% endif /// Description: Register-based front-end for iDMA module idma_${identifier} #( @@ -18,10 +37,22 @@ module idma_${identifier} #( parameter int unsigned IdCounterWidth = 32'd32, /// Dependent parameter: Stream Idx parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), - /// Register_interface request type - parameter type reg_req_t = logic, - /// Register_interface response type - parameter type reg_rsp_t = logic, +% if _fam == 'apb': + /// APB4 request type + parameter type apb_req_t = logic, + /// APB4 response type + parameter type apb_rsp_t = logic, +% elif _fam == 'obi': + /// OBI request type + parameter type obi_req_t = logic, + /// OBI response type + parameter type obi_rsp_t = logic, +% elif _fam == 'axil': + /// AXI4-Lite request type + parameter type axi_lite_req_t = logic, + /// AXI4-Lite response type + parameter type axi_lite_rsp_t = logic, +% endif /// DMA 1d or ND burst request type parameter type dma_req_t = logic, /// Dependent type for IdCounterWidth @@ -31,9 +62,17 @@ module idma_${identifier} #( ) ( input logic clk_i, input logic rst_ni, - /// Register interface control slave - input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, - output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, + /// Configuration control slave (${cpuif}) +% if _fam == 'apb': + input apb_req_t [NumRegs-1:0] dma_ctrl_req_i, + output apb_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, +% elif _fam == 'obi': + input obi_req_t [NumRegs-1:0] dma_ctrl_req_i, + output obi_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, +% elif _fam == 'axil': + input axi_lite_req_t [NumRegs-1:0] dma_ctrl_req_i, + output axi_lite_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, +% endif /// Request signals output dma_req_t dma_req_o, output logic req_valid_o, @@ -51,11 +90,6 @@ module idma_${identifier} #( localparam int unsigned MaxNumStreams = 32'd16; localparam int unsigned RegAddrWidth = idma_${identifier}_reg_pkg::IDMA_${identifier.upper()}_REG_TOP_MIN_ADDR_WIDTH; - `APB_TYPEDEF_ALL(apb, logic[31:0], logic[31:0], logic[3:0]) - apb_req_t [NumRegs-1:0] apb_req; - apb_resp_t [NumRegs-1:0] apb_rsp; - - // register connections idma_${identifier}_reg_pkg::idma_reg__out_t dma_reg2hw [NumRegs-1:0]; idma_${identifier}_reg_pkg::idma_reg__in_t dma_hw2reg [NumRegs-1:0]; @@ -65,9 +99,6 @@ module idma_${identifier} #( logic [NumRegs-1:0] arb_valid; logic [NumRegs-1:0] arb_ready; - // register signals - reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; - always_comb begin stream_idx_o = '0; for (int r = 0; r < NumRegs; r++) begin @@ -83,48 +114,70 @@ module idma_${identifier} #( for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs - reg_to_apb #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ), - .apb_req_t ( apb_req_t ), - .apb_rsp_t ( apb_resp_t ) - ) chs_regs_reg_to_apb ( - .clk_i, - .rst_ni, - .reg_req_i ( dma_ctrl_req_i [i] ), - .reg_rsp_o ( dma_ctrl_rsp [i] ), - .apb_req_o ( apb_req [i] ), - .apb_rsp_i ( apb_rsp [i] ) - ); - +% if _fam == 'obi': + // override the reg_top ID width so s_obi_aid/s_obi_rid match the OBI bus id width + idma_${identifier}_reg_top #( + .ID_WIDTH ( $bits(dma_ctrl_req_i[i].a.aid) ) + ) i_idma_${identifier}_reg_top ( +% else: idma_${identifier}_reg_top i_idma_${identifier}_reg_top ( +% endif .clk ( clk_i ), .arst_n ( rst_ni ), - .s_apb_psel (apb_req[i].psel), - .s_apb_penable (apb_req[i].penable), - .s_apb_pwrite (apb_req[i].pwrite), - .s_apb_pprot (apb_req[i].pprot), - .s_apb_paddr (apb_req[i].paddr[RegAddrWidth-1:0]), - .s_apb_pwdata (apb_req[i].pwdata), - .s_apb_pstrb (apb_req[i].pstrb), - .s_apb_pready (apb_rsp[i].pready), - .s_apb_prdata (apb_rsp[i].prdata), - .s_apb_pslverr (apb_rsp[i].pslverr), +% if _fam == 'apb': + .s_apb_psel ( dma_ctrl_req_i[i].psel ), + .s_apb_penable ( dma_ctrl_req_i[i].penable ), + .s_apb_pwrite ( dma_ctrl_req_i[i].pwrite ), + .s_apb_pprot ( dma_ctrl_req_i[i].pprot ), + .s_apb_paddr ( dma_ctrl_req_i[i].paddr[RegAddrWidth-1:0] ), + .s_apb_pwdata ( dma_ctrl_req_i[i].pwdata ), + .s_apb_pstrb ( dma_ctrl_req_i[i].pstrb ), + .s_apb_pready ( dma_ctrl_rsp_o[i].pready ), + .s_apb_prdata ( dma_ctrl_rsp_o[i].prdata ), + .s_apb_pslverr ( dma_ctrl_rsp_o[i].pslverr ), +% elif _fam == 'obi': + .s_obi_req ( dma_ctrl_req_i[i].req ), + .s_obi_gnt ( dma_ctrl_rsp_o[i].gnt ), + .s_obi_addr ( dma_ctrl_req_i[i].a.addr[RegAddrWidth-1:0] ), + .s_obi_we ( dma_ctrl_req_i[i].a.we ), + .s_obi_be ( dma_ctrl_req_i[i].a.be ), + .s_obi_wdata ( dma_ctrl_req_i[i].a.wdata ), + .s_obi_aid ( dma_ctrl_req_i[i].a.aid ), + .s_obi_rvalid ( dma_ctrl_rsp_o[i].rvalid ), + .s_obi_rready ( dma_ctrl_req_i[i].rready ), + .s_obi_rdata ( dma_ctrl_rsp_o[i].r.rdata ), + .s_obi_err ( dma_ctrl_rsp_o[i].r.err ), + .s_obi_rid ( dma_ctrl_rsp_o[i].r.rid ), +% elif _fam == 'axil': + .s_axil_awvalid ( dma_ctrl_req_i[i].aw_valid ), + .s_axil_awready ( dma_ctrl_rsp_o[i].aw_ready ), + .s_axil_awaddr ( dma_ctrl_req_i[i].aw.addr[RegAddrWidth-1:0] ), + .s_axil_awprot ( dma_ctrl_req_i[i].aw.prot ), + .s_axil_wvalid ( dma_ctrl_req_i[i].w_valid ), + .s_axil_wready ( dma_ctrl_rsp_o[i].w_ready ), + .s_axil_wdata ( dma_ctrl_req_i[i].w.data ), + .s_axil_wstrb ( dma_ctrl_req_i[i].w.strb ), + .s_axil_bvalid ( dma_ctrl_rsp_o[i].b_valid ), + .s_axil_bready ( dma_ctrl_req_i[i].b_ready ), + .s_axil_bresp ( dma_ctrl_rsp_o[i].b.resp ), + .s_axil_arvalid ( dma_ctrl_req_i[i].ar_valid ), + .s_axil_arready ( dma_ctrl_rsp_o[i].ar_ready ), + .s_axil_araddr ( dma_ctrl_req_i[i].ar.addr[RegAddrWidth-1:0] ), + .s_axil_arprot ( dma_ctrl_req_i[i].ar.prot ), + .s_axil_rvalid ( dma_ctrl_rsp_o[i].r_valid ), + .s_axil_rready ( dma_ctrl_req_i[i].r_ready ), + .s_axil_rdata ( dma_ctrl_rsp_o[i].r.data ), + .s_axil_rresp ( dma_ctrl_rsp_o[i].r.resp ), +% endif .hwif_out ( dma_reg2hw [i] ), .hwif_in ( dma_hw2reg [i] ) ); logic read_happens; - // DMA backpressure - always_comb begin : proc_dma_backpressure - // ready signal - dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; - end - - // valid signals + // launch-stall: hold the reg read-ack until the arbiter accepts the request + // (protocol-agnostic — driven into hwif rd_ack below, see gen_hw2reg_connections) always_comb begin : proc_launch read_happens = 1'b0; diff --git a/util/gen_idma.py b/util/gen_idma.py index 537b9adb..c2a319ba 100644 --- a/util/gen_idma.py +++ b/util/gen_idma.py @@ -49,6 +49,8 @@ def main(): parser.add_argument('--fids', dest='fids', nargs='*', help='frontend IDs') parser.add_argument('--db', dest='db', nargs='*', help='Database files') parser.add_argument('--tpl', dest='tpl', required=True, help='Template file') + parser.add_argument('--cpuif', dest='cpuif', default='apb4-flat', + help='Register-frontend config-bus CPUIF (must match the PeakRDL regblock --cpuif)') args = parser.parse_args() # prepare database and ids @@ -73,7 +75,7 @@ def main(): elif args.entity == 'reg_hjson': print(render_reg_hjson(frontend_ids, args.tpl)) elif args.entity == 'reg_top': - print(render_reg_top(frontend_ids, args.tpl)) + print(render_reg_top(frontend_ids, args.tpl, args.cpuif)) elif args.entity == 'tracer': print(render_tracer(protocol_ids, protocol_db, args.tpl)) else: diff --git a/util/mario/frontend.py b/util/mario/frontend.py index a252f880..6d8d41a8 100644 --- a/util/mario/frontend.py +++ b/util/mario/frontend.py @@ -142,7 +142,7 @@ def render_reg_hjson(fe_ids: dict, tpl_file: str) -> str: return reg_hjson_rendered -def render_reg_top(fe_ids: dict, tpl_file: str) -> str: +def render_reg_top(fe_ids: dict, tpl_file: str, cpuif: str = 'apb4-flat') -> str: """Generate register top""" reg_top_rendered = '' @@ -162,7 +162,8 @@ def render_reg_top(fe_ids: dict, tpl_file: str) -> str: 'identifier': fe_id, 'num_dim': int(fe_ids[fe_id][1]), 'sep': sep, - 'bit_width': fe_ids[fe_id][0] + 'bit_width': fe_ids[fe_id][0], + 'cpuif': cpuif } # render