diff --git a/src/backend/tpl/idma_backend.sv.tpl b/src/backend/tpl/idma_backend.sv.tpl index c5a2e164..8e414f5b 100644 --- a/src/backend/tpl/idma_backend.sv.tpl +++ b/src/backend/tpl/idma_backend.sv.tpl @@ -127,13 +127,13 @@ module idma_backend_${name_uniqueifier} #( % if database[protocol]['read_slave'] == 'true': _read\ % endif -_req_t ${protocol}_read_req_i, +_req_t ${mh_format['ar'][protocol]}${protocol}_read_req_i, % else: output ${protocol}\ % if database[protocol]['read_slave'] == 'true': _read\ % endif -_req_t ${protocol}_read_req_o, +_req_t ${mh_format['ar'][protocol]}${protocol}_read_req_o, % endif /// ${database[protocol]['full_name']} read response % if database[protocol]['passive_req'] == 'true': @@ -141,13 +141,13 @@ _req_t ${protocol}_read_req_o, % if database[protocol]['read_slave'] == 'true': _read\ % endif -_rsp_t ${protocol}_read_rsp_o, +_rsp_t ${mh_format['ar'][protocol]}${protocol}_read_rsp_o, % else: input ${protocol}\ % if database[protocol]['read_slave'] == 'true': _read\ % endif -_rsp_t ${protocol}_read_rsp_i, +_rsp_t ${mh_format['ar'][protocol]}${protocol}_read_rsp_i, % endif % endfor % for protocol in used_write_protocols: @@ -157,13 +157,13 @@ _rsp_t ${protocol}_read_rsp_i, % if database[protocol]['read_slave'] == 'true': _write\ % endif -_req_t ${protocol}_write_req_o, +_req_t ${mh_format['aw'][protocol]}${protocol}_write_req_o, /// ${database[protocol]['full_name']} write response input ${protocol}\ % if database[protocol]['read_slave'] == 'true': _write\ % endif -_rsp_t ${protocol}_write_rsp_i, +_rsp_t ${mh_format['aw'][protocol]}${protocol}_write_rsp_i, % endfor /// iDMA busy flags @@ -198,12 +198,13 @@ _rsp_t ${protocol}_write_rsp_i, /// - `decouple_aw`: If the transfer has the AW decoupled from the R /// - `is_single`: Is this transfer just one beat long? `(len == 0)` typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; + idma_pkg::protocol_e src_protocol; + idma_pkg::multihead_t src_head; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; } r_dp_req_t; /// The datapath read response type provides feedback from the read part of the datapath: @@ -225,12 +226,13 @@ _rsp_t ${protocol}_write_rsp_i, /// - `num_beats`: The number of beats this burst consist of /// - `is_single`: Is this transfer just one beat long? `(len == 0)` typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; + idma_pkg::protocol_e dst_protocol; + idma_pkg::multihead_t dst_head; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; } w_dp_req_t; /// The datapath write response type provides feedback from the write part of the datapath: @@ -248,8 +250,9 @@ _rsp_t ${protocol}_write_rsp_i, } idma_r_req_t; % if not one_read_port: typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; + idma_pkg::protocol_e src_protocol; + idma_pkg::multihead_t src_head; + read_meta_channel_t ar_req; } read_meta_channel_tagged_t; % endif @@ -268,8 +271,9 @@ _rsp_t ${protocol}_write_rsp_i, } idma_w_req_t; % if not one_write_port: typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; + idma_pkg::protocol_e dst_protocol; + idma_pkg::multihead_t dst_head; + write_meta_channel_t aw_req; } write_meta_channel_tagged_t; % endif @@ -278,6 +282,8 @@ _rsp_t ${protocol}_write_rsp_i, typedef struct packed { idma_pkg::protocol_e src_protocol; idma_pkg::protocol_e dst_protocol; + idma_pkg::multihead_t src_head; + idma_pkg::multihead_t dst_head; offset_t read_shift; offset_t write_shift; logic decouple_rw; @@ -469,21 +475,23 @@ _rsp_t ${protocol}_write_rsp_i, // assemble read datapath request assign r_req.r_dp_req = '{ src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 + src_head: idma_req_i.opt.src_head, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 }; // assemble write datapath request assign w_req.w_dp_req = '{ dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 + dst_head: idma_req_i.opt.src_head, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 }; // if the legalizer is bypassed; every burst is the last of the 1D transfer @@ -632,6 +640,7 @@ _rsp_t ${protocol}_write_rsp_i, % if not one_read_port: always_comb begin : assign_r_meta_req r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; + r_meta_req_tagged.src_head = r_req.r_dp_req.src_head; r_meta_req_tagged.ar_req = r_req.ar_req; end % endif @@ -780,6 +789,7 @@ _rsp_t ${protocol}_write_rsp_i, % if not one_write_port: always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; + w_meta_req_tagged.dst_head = w_req.w_dp_req.dst_head; w_meta_req_tagged.aw_req = w_req.aw_req; end % endif diff --git a/src/backend/tpl/idma_backend_synth.sv.tpl b/src/backend/tpl/idma_backend_synth.sv.tpl index 9ea38735..1fce76b6 100644 --- a/src/backend/tpl/idma_backend_synth.sv.tpl +++ b/src/backend/tpl/idma_backend_synth.sv.tpl @@ -95,6 +95,8 @@ module idma_backend_synth_${name_uniqueifier} #( input addr_t req_dst_addr_i, input idma_pkg::protocol_e req_src_protocol_i, input idma_pkg::protocol_e req_dst_protocol_i, + input idma_pkg::multihead_t req_src_head_i, + input idma_pkg::multihead_t req_dst_head_i, input id_t req_axi_id_i, input axi_pkg::burst_t req_src_burst_i, input axi_pkg::cache_t req_src_cache_i, @@ -364,6 +366,8 @@ ${p}_${database[p]['write_meta_channel']}_width\ assign idma_req.length = req_length_i; assign idma_req.opt.src_protocol = req_src_protocol_i; assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.src_head = req_src_head_i; + assign idma_req.opt.dst_head = req_dst_head_i; assign idma_req.opt.axi_id = req_axi_id_i; assign idma_req.opt.dst.cache = req_dst_cache_i; assign idma_req.opt.dst.burst = req_dst_burst_i; diff --git a/src/backend/tpl/idma_legalizer.sv.tpl b/src/backend/tpl/idma_legalizer.sv.tpl index 777ee1bc..47441be9 100644 --- a/src/backend/tpl/idma_legalizer.sv.tpl +++ b/src/backend/tpl/idma_legalizer.sv.tpl @@ -476,6 +476,8 @@ w_num_bytes_to_pb = w_page_num_bytes_to_pb; opt_tf_d = '{ src_protocol: req_i.opt.src_protocol, dst_protocol: req_i.opt.dst_protocol, + src_head: req_i.opt.src_head, + dst_head: req_i.opt.dst_head, read_shift: '0, write_shift: '0, decouple_rw: req_i.opt.beo.decouple_rw, @@ -529,6 +531,7 @@ ${database[protocol]['legalizer_read_meta_channel']} // assign the signals needed to set-up the read data path assign r_req_o.r_dp_req = '{ src_protocol: opt_tf_q.src_protocol, + src_head: opt_tf_q.src_head, offset: r_addr_offset, tailer: OffsetWidth'(r_num_bytes + r_addr_offset), shift: opt_tf_q.read_shift, @@ -545,6 +548,7 @@ ${database[used_write_protocols[0]]['legalizer_write_data_path']} % else: w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, + dst_head: opt_tf_q.dst_head, offset: w_addr_offset, tailer: OffsetWidth'(w_num_bytes + w_addr_offset), shift: opt_tf_q.write_shift, @@ -579,6 +583,7 @@ ${database[protocol]['legalizer_write_data_path']} default: w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, + dst_head: opt_tf_q.dst_head, offset: w_addr_offset, tailer: OffsetWidth'(w_num_bytes + w_addr_offset), shift: opt_tf_q.write_shift, diff --git a/src/backend/tpl/idma_transport_layer.sv.tpl b/src/backend/tpl/idma_transport_layer.sv.tpl index 91d27131..16815110 100644 --- a/src/backend/tpl/idma_transport_layer.sv.tpl +++ b/src/backend/tpl/idma_transport_layer.sv.tpl @@ -80,13 +80,13 @@ module idma_transport_layer_${name_uniqueifier} #( % if database[protocol]['read_slave'] == 'true': _read\ % endif -_req_t ${protocol}_read_req_i, +_req_t ${mh_format['ar'][protocol]}${protocol}_read_req_i, % else: output ${protocol}\ % if database[protocol]['read_slave'] == 'true': _read\ % endif -_req_t ${protocol}_read_req_o, +_req_t ${mh_format['ar'][protocol]}${protocol}_read_req_o, % endif /// ${database[protocol]['full_name']} read response % if database[protocol]['passive_req'] == 'true': @@ -94,13 +94,13 @@ _req_t ${protocol}_read_req_o, % if database[protocol]['read_slave'] == 'true': _read\ % endif -_rsp_t ${protocol}_read_rsp_o, +_rsp_t ${mh_format['ar'][protocol]}${protocol}_read_rsp_o, % else: input ${protocol}\ % if database[protocol]['read_slave'] == 'true': _read\ % endif -_rsp_t ${protocol}_read_rsp_i, +_rsp_t ${mh_format['ar'][protocol]}${protocol}_read_rsp_i, % endif % endfor % for protocol in used_write_protocols: @@ -110,13 +110,13 @@ _rsp_t ${protocol}_read_rsp_i, % if database[protocol]['read_slave'] == 'true': _write\ % endif -_req_t ${protocol}_write_req_o, +_req_t ${mh_format['aw'][protocol]}${protocol}_write_req_o, /// ${database[protocol]['full_name']} write response input ${protocol}\ % if database[protocol]['read_slave'] == 'true': _write\ % endif -_rsp_t ${protocol}_write_rsp_i, +_rsp_t ${mh_format['aw'][protocol]}${protocol}_write_rsp_i, % endfor /// Read datapath request @@ -195,149 +195,63 @@ _rsp_t ${protocol}_write_rsp_i, typedef logic [7:0] byte_t; // inbound control signals to the read buffer: controlled by the read process - strb_t\ % if not one_read_port: % for p in used_read_protocols: - ${p}_buffer_in_valid,\ + strb_t ${mh_format['ar'][p]}${p}_buffer_in_valid; % endfor % endif - buffer_in_valid; - + strb_t buffer_in_valid; strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t\ + strb_t buffer_out_valid; + strb_t buffer_out_valid_shifted; % if not one_write_port: % for p in used_write_protocols: - ${p}_buffer_out_ready,\ + strb_t ${mh_format['aw'][p]}${p}_buffer_out_ready; % endfor % endif - - buffer_out_ready, buffer_out_ready_shifted; + strb_t buffer_out_ready; + strb_t buffer_out_ready_shifted; // shifted data flowing into the buffer - byte_t [2*StrbWidth-1:0] buffer_in_tmp; - byte_t [StrbWidth-1:0]\ % if not one_read_port: % for p in used_read_protocols: - ${p}_buffer_in,\ + byte_t [StrbWidth-1:0] ${mh_format['ar'][p]}${p}_buffer_in; % endfor % endif + byte_t [StrbWidth-1:0] buffer_in; + byte_t [StrbWidth-1:0] buffer_in_shifted; + // Introduce this temporary signal to ease tool compatibility + byte_t [2*StrbWidth-1:0] buffer_in_tmp; - buffer_in, buffer_in_shifted; // aligned and coalesced data leaving the buffer byte_t [2*StrbWidth-1:0] buffer_out_tmp; - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; -% if not one_read_port: + byte_t [StrbWidth-1:0] buffer_out; + byte_t [StrbWidth-1:0] buffer_out_shifted; +% if not one_read_port: // Read multiplexed signals - logic\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_r_chan_valid\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor - logic\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_r_chan_ready\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor - logic\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_r_dp_valid\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor - logic\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_r_dp_ready\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor - r_dp_rsp_t\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_r_dp_rsp\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor + % for protocol in used_read_protocols: + logic ${mh_format['ar'][protocol]}${protocol}_r_chan_valid; + logic ${mh_format['ar'][protocol]}${protocol}_r_chan_ready; + logic ${mh_format['ar'][protocol]}${protocol}_r_dp_valid; + logic ${mh_format['ar'][protocol]}${protocol}_r_dp_ready; + r_dp_rsp_t ${mh_format['ar'][protocol]}${protocol}_r_dp_rsp; + logic ${mh_format['ar'][protocol]}${protocol}_ar_ready; - logic\ - % for index, protocol in enumerate(used_read_protocols): - ${protocol}_ar_ready\ - % if index == len(used_read_protocols)-1: -; - % else: -,\ - % endif - %endfor + % endfor % endif % if not one_write_port: - // Write multiplexed signals - logic\ - % for index, protocol in enumerate(used_write_protocols): - ${protocol}_w_dp_rsp_valid\ - % if index == len(used_write_protocols)-1: -; - % else: -,\ - % endif - %endfor - logic\ - % for index, protocol in enumerate(used_write_protocols): - ${protocol}_w_dp_rsp_ready\ - % if index == len(used_write_protocols)-1: -; - % else: -,\ - % endif - %endfor - logic\ - % for index, protocol in enumerate(used_write_protocols): - ${protocol}_w_dp_ready\ - % if index == len(used_write_protocols)-1: -; - % else: -,\ - % endif - %endfor - w_dp_rsp_t\ - % for index, protocol in enumerate(used_write_protocols): - ${protocol}_w_dp_rsp\ - % if index == len(used_write_protocols)-1: -; - % else: -,\ - % endif - %endfor + % for protocol in used_write_protocols: + logic ${mh_format['aw'][protocol]}${protocol}_w_dp_rsp_valid; + logic ${mh_format['aw'][protocol]}${protocol}_w_dp_rsp_ready; + logic ${mh_format['aw'][protocol]}${protocol}_w_dp_ready; + w_dp_rsp_t ${mh_format['aw'][protocol]}${protocol}_w_dp_rsp; + logic ${mh_format['aw'][protocol]}${protocol}_aw_ready; - logic\ - % for index, protocol in enumerate(used_write_protocols): - ${protocol}_aw_ready\ - % if index == len(used_write_protocols)-1: -; - % else: -,\ - % endif %endfor -% endif -% if not one_write_port: logic w_dp_req_valid, w_dp_req_ready; logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; logic w_dp_rsp_valid, w_dp_rsp_ready; @@ -346,6 +260,9 @@ _rsp_t ${protocol}_write_rsp_i, // Write Response FIFO signals logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; idma_pkg::protocol_e w_resp_fifo_out_protocol; +% if any_mh['aw']: + idma_pkg::multihead_t w_resp_fifo_out_head; +% endif logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; % endif @@ -365,7 +282,11 @@ ${rendered_read_ports[read_port]} always_comb begin : gen_read_meta_channel_multiplexer case(ar_req_i.src_protocol) % for rp in used_read_protocols: + % if mh_format['ar'][rp] == '': idma_pkg::${database[rp]['protocol_enum']}: ar_ready_o = ${rp}_ar_ready; + % else: + idma_pkg::${database[rp]['protocol_enum']}: ar_ready_o = ${rp}_ar_ready [ar_req_i.src_head]; + % endif % endfor default: ar_ready_o = 1'b0; endcase @@ -375,6 +296,7 @@ ${rendered_read_ports[read_port]} if (r_dp_valid_i) begin case(r_dp_req_i.src_protocol) % for rp in used_read_protocols: + % if mh_format['ar'][rp] == '': idma_pkg::${database[rp]['protocol_enum']}: begin r_chan_valid_o = ${rp}_r_chan_valid; r_chan_ready_o = ${rp}_r_chan_ready; @@ -386,6 +308,19 @@ ${rendered_read_ports[read_port]} buffer_in = ${rp}_buffer_in; buffer_in_valid = ${rp}_buffer_in_valid; end + % else: + idma_pkg::${database[rp]['protocol_enum']}: begin + r_chan_valid_o = ${rp}_r_chan_valid [r_dp_req_i.src_head]; + r_chan_ready_o = ${rp}_r_chan_ready [r_dp_req_i.src_head]; + + r_dp_ready_o = ${rp}_r_dp_ready [r_dp_req_i.src_head]; + r_dp_rsp_o = ${rp}_r_dp_rsp [r_dp_req_i.src_head]; + r_dp_valid_o = ${rp}_r_dp_valid [r_dp_req_i.src_head]; + + buffer_in = ${rp}_buffer_in [r_dp_req_i.src_head]; + buffer_in_valid = ${rp}_buffer_in_valid [r_dp_req_i.src_head]; + end + % endif % endfor default: begin r_chan_valid_o = 1'b0; @@ -473,8 +408,13 @@ ${rendered_read_ports[read_port]} case(w_dp_req_i.dst_protocol) % for wp in used_write_protocols: idma_pkg::${database[wp]['protocol_enum']}: begin + % if mh_format['aw'][wp] == '': w_dp_req_ready = ${wp}_w_dp_ready; buffer_out_ready = ${wp}_buffer_out_ready; + % else: + w_dp_req_ready = ${wp}_w_dp_ready [w_dp_req_i.dst_head]; + buffer_out_ready = ${wp}_buffer_out_ready [w_dp_req_i.dst_head]; + % endif end % endfor default: begin @@ -488,7 +428,11 @@ ${rendered_read_ports[read_port]} always_comb begin : gen_write_meta_channel_multiplexer case(aw_req_i.dst_protocol) % for wp in used_write_protocols: + % if mh_format['aw'][wp] == '': idma_pkg::${database[wp]['protocol_enum']}: aw_ready_o = ${wp}_aw_ready; + % else: + idma_pkg::${database[wp]['protocol_enum']}: aw_ready_o = ${wp}_aw_ready [aw_req_i.dst_head]; + % endif % endfor default: aw_ready_o = 1'b0; endcase @@ -507,7 +451,7 @@ ${rendered_write_ports[write_port]} //-------------------------------------- // Write Response FIFO //-------------------------------------- - // Needed to be able to route the write reponses properly + // Needed to be able to route the write responses properly // Insert when data write happens // Remove when write response comes @@ -529,6 +473,26 @@ ${rendered_write_ports[write_port]} .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) ); +% if not mh_format['aw'][wp] == '': + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( idma_pkg::multihead_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_write_response_fifo_multihead ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_dp_req_i.dst_head ), + .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), + .ready_o ( /* NOT CONNECTED */ ), + .data_o ( w_resp_fifo_out_multihead ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) + ); + +% endif //-------------------------------------- // Write Request Demultiplexer //-------------------------------------- @@ -538,15 +502,25 @@ ${rendered_write_ports[write_port]} w_dp_rsp_mux = '0; w_dp_rsp_mux_valid = 1'b0; % for wp in used_write_protocols: + % if mh_format['aw'][wp] == '': ${wp}_w_dp_rsp_ready = 1'b0; + % else: + ${wp}_w_dp_rsp_ready = '0; + % endif % endfor if ( w_resp_fifo_out_valid ) begin case(w_resp_fifo_out_protocol) % for wp in used_write_protocols: idma_pkg::${database[wp]['protocol_enum']}: begin + % if mh_format['aw'][wp] == '': w_dp_rsp_mux_valid = ${wp}_w_dp_rsp_valid; w_dp_rsp_mux = ${wp}_w_dp_rsp; ${wp}_w_dp_rsp_ready = w_dp_rsp_mux_ready; + % else: + w_dp_rsp_mux_valid = ${wp}_w_dp_rsp_valid [w_resp_fifo_out_multihead]; + w_dp_rsp_mux = ${wp}_w_dp_rsp [w_resp_fifo_out_multihead]; + ${wp}_w_dp_rsp_ready [w_resp_fifo_out_multihead] = w_dp_rsp_mux_ready; + % endif end % endfor default: begin diff --git a/src/db/idma_axi.yml b/src/db/idma_axi.yml index 02c7f884..267ce4b2 100644 --- a/src/db/idma_axi.yml +++ b/src/db/idma_axi.yml @@ -62,6 +62,7 @@ legalizer_write_meta_channel: | legalizer_write_data_path: | w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, + dst_head: opt_tf_q.dst_head, offset: w_addr_offset, tailer: OffsetWidth'(w_num_bytes + w_addr_offset), shift: opt_tf_q.write_shift, @@ -78,7 +79,7 @@ read_template: | .ar_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_axi_read ( + ) i_idma_axi_read${mh} ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .r_dp_req_i ( r_dp_req_i ), @@ -110,7 +111,7 @@ write_template: | .aw_chan_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_axi_write ( + ) i_idma_axi_write${mh} ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .w_dp_req_i ( w_dp_req_i ), diff --git a/src/db/idma_axi_lite.yml b/src/db/idma_axi_lite.yml index edb5637a..5f21d559 100644 --- a/src/db/idma_axi_lite.yml +++ b/src/db/idma_axi_lite.yml @@ -65,7 +65,7 @@ read_template: | .ar_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_axil_read ( + ) i_idma_axil_read${mh} ( .r_dp_req_i ( r_dp_req_i ), .r_dp_valid_i ( ${r_dp_valid_i} ), .r_dp_ready_o ( ${r_dp_ready_o} ), @@ -95,7 +95,7 @@ write_template: | .aw_chan_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_axil_write ( + ) i_idma_axil_write${mh} ( .w_dp_req_i ( w_dp_req_i ), .w_dp_valid_i ( ${w_dp_valid_i} ), .w_dp_ready_o ( ${w_dp_ready_o} ), diff --git a/src/db/idma_axi_stream.yml b/src/db/idma_axi_stream.yml index ac639ff3..4ffa09c8 100644 --- a/src/db/idma_axi_stream.yml +++ b/src/db/idma_axi_stream.yml @@ -228,7 +228,7 @@ read_template: | .read_meta_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_axis_read ( + ) i_idma_axis_read${mh} ( .r_dp_req_i ( r_dp_req_i ), .r_dp_req_valid_i ( ${r_dp_valid_i} ), .r_dp_req_ready_o ( ${r_dp_ready_o} ), @@ -258,7 +258,7 @@ write_template: | .write_meta_channel_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_axis_write ( + ) i_idma_axis_write${mh} ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .w_dp_req_i ( w_dp_req_i ), diff --git a/src/db/idma_init.yml b/src/db/idma_init.yml index 35e40911..d4210a43 100644 --- a/src/db/idma_init.yml +++ b/src/db/idma_init.yml @@ -86,7 +86,7 @@ read_template: | .read_meta_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_init_read ( + ) i_idma_init_read${mh} ( .r_dp_req_i ( r_dp_req_i ), .r_dp_valid_i ( ${r_dp_valid_i} ), .r_dp_ready_o ( ${r_dp_ready_o} ), @@ -115,7 +115,7 @@ write_template: | .write_meta_channel_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_init_write ( + ) i_idma_init_write${mh} ( .w_dp_req_i ( w_dp_req_i ), .w_dp_valid_i ( ${w_dp_valid_i} ), .w_dp_ready_o ( ${w_dp_ready_o} ), diff --git a/src/db/idma_obi.yml b/src/db/idma_obi.yml index e4664735..be95b11b 100644 --- a/src/db/idma_obi.yml +++ b/src/db/idma_obi.yml @@ -72,7 +72,7 @@ read_template: | .read_meta_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_obi_read ( + ) i_idma_obi_read${mh} ( .r_dp_req_i ( r_dp_req_i ), .r_dp_valid_i ( ${r_dp_valid_i} ), .r_dp_ready_o ( ${r_dp_ready_o} ), @@ -102,7 +102,7 @@ write_template: | .write_meta_channel_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_obi_write ( + ) i_idma_obi_write${mh} ( .w_dp_req_i ( w_dp_req_i ), .w_dp_valid_i ( ${w_dp_valid_i} ), .w_dp_ready_o ( ${w_dp_ready_o} ), diff --git a/src/db/idma_tilelink.yml b/src/db/idma_tilelink.yml index 652a6caf..15e97eb0 100644 --- a/src/db/idma_tilelink.yml +++ b/src/db/idma_tilelink.yml @@ -80,6 +80,7 @@ legalizer_write_meta_channel: | legalizer_write_data_path: | w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, + dst_head: opt_tf_q.dst_head, offset: w_addr_offset, tailer: OffsetWidth'(w_num_bytes + w_addr_offset), shift: opt_tf_q.write_shift, @@ -97,7 +98,7 @@ read_template: | .read_meta_chan_t ( read_meta_channel_t ), .read_req_t ( ${req_t} ), .read_rsp_t ( ${rsp_t} ) - ) i_idma_tilelink_read ( + ) i_idma_tilelink_read${mh} ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .r_dp_req_i ( r_dp_req_i ), @@ -135,7 +136,7 @@ write_template: | .write_meta_chan_t ( write_meta_channel_t ), .write_req_t ( ${req_t} ), .write_rsp_t ( ${rsp_t} ) - ) i_idma_tilelink_write ( + ) i_idma_tilelink_write${mh} ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .w_dp_req_i ( w_dp_req_i ), diff --git a/src/idma_pkg.sv b/src/idma_pkg.sv index f3023499..c78e6196 100644 --- a/src/idma_pkg.sv +++ b/src/idma_pkg.sv @@ -97,6 +97,9 @@ package idma_pkg; AXI_STREAM = 'd5 } protocol_e; + /// Multihead channel selection type + typedef logic[7:0] multihead_t; + /// Supported Protocols type typedef logic[1:0] protocol_t; diff --git a/src/include/idma/typedef.svh b/src/include/idma/typedef.svh index d250ec10..841200a1 100644 --- a/src/include/idma/typedef.svh +++ b/src/include/idma/typedef.svh @@ -22,6 +22,8 @@ typedef struct packed { \ idma_pkg::protocol_e src_protocol; \ idma_pkg::protocol_e dst_protocol; \ + idma_pkg::multihead_t src_head; \ + idma_pkg::multihead_t dst_head; \ axi_id_t axi_id; \ idma_pkg::axi_options_t src; \ idma_pkg::axi_options_t dst; \ diff --git a/test/frontend/tb_idma_desc64_bench.sv b/test/frontend/tb_idma_desc64_bench.sv index 872a70ac..b3eeefe7 100644 --- a/test/frontend/tb_idma_desc64_bench.sv +++ b/test/frontend/tb_idma_desc64_bench.sv @@ -462,6 +462,8 @@ module tb_idma_desc64_bench // overwrite protocols current_stimulus.burst.opt.src_protocol = idma_pkg::AXI; current_stimulus.burst.opt.dst_protocol = idma_pkg::AXI; + current_stimulus.burst.opt.src_head = '0; + current_stimulus.burst.opt.dst_head = '0; current_stimulus.burst.user = '0; current_stimulus.base = base_current; @@ -503,6 +505,8 @@ module tb_idma_desc64_bench // overwrite protocols current_stimulus.burst.opt.src_protocol = idma_pkg::AXI; current_stimulus.burst.opt.dst_protocol = idma_pkg::AXI; + current_stimulus.burst.opt.src_head = '0; + current_stimulus.burst.opt.dst_head = '0; current_stimulus.burst.user = '0; current_stimulus.base = base_current; diff --git a/test/frontend/tb_idma_desc64_top.sv b/test/frontend/tb_idma_desc64_top.sv index 6ad784bb..4b4ab0af 100644 --- a/test/frontend/tb_idma_desc64_top.sv +++ b/test/frontend/tb_idma_desc64_top.sv @@ -271,6 +271,8 @@ module tb_idma_desc64_top // overwrite protocols current_stimulus.burst.opt.src_protocol = idma_pkg::AXI; current_stimulus.burst.opt.dst_protocol = idma_pkg::AXI; + current_stimulus.burst.opt.src_head = '0; + current_stimulus.burst.opt.dst_head = '0; current_stimulus.burst.user = '0; current_stimuli_group.push_back(current_stimulus); @@ -303,6 +305,8 @@ module tb_idma_desc64_top // overwrite protocols current_stimulus.burst.opt.src_protocol = idma_pkg::AXI; current_stimulus.burst.opt.dst_protocol = idma_pkg::AXI; + current_stimulus.burst.opt.src_head = '0; + current_stimulus.burst.opt.dst_head = '0; current_stimulus.burst.user = '0; // chain descriptor diff --git a/test/idma_test.sv b/test/idma_test.sv index ece009f6..2842d4bf 100644 --- a/test/idma_test.sv +++ b/test/idma_test.sv @@ -695,6 +695,8 @@ package idma_test; idma.req.dst_addr <= #TA dst_addr; idma.req.opt.src_protocol <= #TA src_protocol; idma.req.opt.dst_protocol <= #TA dst_protocol; + idma.req.opt.src_head <= #TA '0; + idma.req.opt.dst_head <= #TA '0; idma.req.opt.axi_id <= #TA id; idma.req.opt.beo.decouple_aw <= #TA decouple_aw; idma.req.opt.beo.decouple_rw <= #TA decouple_rw; @@ -709,8 +711,11 @@ package idma_test; idma.req.length <= #TA '0; idma.req.src_addr <= #TA '0; idma.req.dst_addr <= #TA '0; + idma.req.opt.src_protocol <= #TA idma_pkg::AXI; + idma.req.opt.dst_protocol <= #TA idma_pkg::AXI; + idma.req.opt.src_head <= #TA '0; + idma.req.opt.dst_head <= #TA '0; idma.req.opt.axi_id <= #TA '0; - idma.req.opt.dst.prot <= #TA '0; idma.req.opt.beo.decouple_aw <= #TA '0; idma.req.opt.beo.decouple_rw <= #TA '0; idma.req.opt.beo.src_max_llen <= #TA '0; @@ -862,6 +867,8 @@ package idma_test; nd_idma.req.burst_req.dst_addr <= #TA dst_addr; nd_idma.req.burst_req.opt.src_protocol <= #TA src_protocol; nd_idma.req.burst_req.opt.dst_protocol <= #TA dst_protocol; + nd_idma.req.burst_req.opt.src_head <= #TA '0; + nd_idma.req.burst_req.opt.dst_head <= #TA '0; nd_idma.req.burst_req.opt.beo.decouple_aw <= #TA decouple_aw; nd_idma.req.burst_req.opt.beo.decouple_rw <= #TA decouple_rw; nd_idma.req.burst_req.opt.beo.src_max_llen <= #TA src_max_llen; @@ -877,6 +884,10 @@ package idma_test; nd_idma.req.burst_req.length <= #TA '0; nd_idma.req.burst_req.src_addr <= #TA '0; nd_idma.req.burst_req.dst_addr <= #TA '0; + nd_idma.req.burst_req.opt.src_protocol <= #TA idma_pkg::AXI; + nd_idma.req.burst_req.opt.dst_protocol <= #TA idma_pkg::AXI; + nd_idma.req.burst_req.opt.src_head <= #TA '0; + nd_idma.req.burst_req.opt.dst_head <= #TA '0; nd_idma.req.burst_req.opt.beo.decouple_aw <= #TA '0; nd_idma.req.burst_req.opt.beo.decouple_rw <= #TA '0; nd_idma.req.burst_req.opt.beo.src_max_llen <= #TA '0; diff --git a/util/mario/backend.py b/util/mario/backend.py index 22a21dfd..6554a146 100644 --- a/util/mario/backend.py +++ b/util/mario/backend.py @@ -22,6 +22,16 @@ def render_backend(prot_ids: dict, db: dict, tpl_file: str) -> str: # render for every is for prot_id in prot_ids: + # format multi head bus + mh_format = {'ar': {}, 'aw': {}} + for dir in ['r', 'w']: + for mhp in prot_ids[prot_id]['multihead'][dir]: + num_heads = prot_ids[prot_id]['multihead'][dir][mhp] + if (num_heads == 1): + mh_format['a' + dir][mhp] = '' + else: + mh_format['a' + dir][mhp] = f'[{num_heads-1}:0] ' + # get ports used used_read_prots = prot_ids[prot_id]['ar'] used_write_prots = prot_ids[prot_id]['aw'] @@ -42,7 +52,8 @@ def render_backend(prot_ids: dict, db: dict, tpl_file: str) -> str: 'used_non_bursting_write_protocols': prot_key(used_write_prots, 'bursts', 'not_supported', db), 'combined_aw_and_w': - eval_key(used_write_prots, 'combined_aw_and_w', 'true', db) + eval_key(used_write_prots, 'combined_aw_and_w', 'true', db), + 'mh_format': mh_format } # render diff --git a/util/mario/transport_layer.py b/util/mario/transport_layer.py index 17a23a36..38ef9203 100644 --- a/util/mario/transport_layer.py +++ b/util/mario/transport_layer.py @@ -22,79 +22,125 @@ def render_read_mgr_inst(prot_id: str, prot_ids: dict, db: dict) -> dict: # Render read ports for rp in prot_ids[prot_id]['ar']: + res[rp] = '' + + # prepare multihead snippets + num_heads = prot_ids[prot_id]['multihead']['r'][rp] + + # treat multi head config as multi protocol config + srp &= num_heads == 1 + # template cleanup db[rp]['read_template'] = ' ' + db[rp]['read_template'].replace('\n', '\n ') db[rp]['read_template'] = db[rp]['read_template'][:-5] - if db[rp]['read_slave'] == 'true': - read_req_str = f'{rp}_read_req_t' - read_rsp_str = f'{rp}_read_rsp_t' - else: - read_req_str = f'{rp}_req_t' - read_rsp_str = f'{rp}_rsp_t' - - if db[rp]['passive_req'] == 'true': - read_port_dir_req_str = 'i' - read_port_dir_rsp_str = 'o' - else: - read_port_dir_req_str = 'o' - read_port_dir_rsp_str = 'i' - - if srp: - read_dp_valid_in = 'r_dp_valid_i' - read_dp_ready_out = 'r_dp_ready_o' - read_dp_response = 'r_dp_rsp_o' - read_dp_valid_out = 'r_dp_valid_o' - read_dp_ready_in = 'r_dp_ready_i' - read_meta_request = 'ar_req_i' - read_meta_valid = 'ar_valid_i' - read_meta_ready = 'ar_ready_o' - r_chan_valid = 'r_chan_valid_o' - r_chan_ready = 'r_chan_ready_o' - buffer_in = 'buffer_in' - buffer_in_valid = 'buffer_in_valid' - else: - read_dp_valid_in = f'''\ -(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & r_dp_valid_i\ + # iterate over heads + for curr_head in range(0, num_heads): + + if num_heads == 1: + mh = '' + mh_bus = '' + else: + mh = f'_{curr_head}' + mh_bus = f' [{curr_head}]' + + if db[rp]['read_slave'] == 'true': + read_req_str = f'{rp}_read_req_t' + read_rsp_str = f'{rp}_read_rsp_t' + else: + read_req_str = f'{rp}_req_t' + read_rsp_str = f'{rp}_rsp_t' + + if db[rp]['passive_req'] == 'true': + read_port_dir_req_str = 'i' + read_port_dir_rsp_str = 'o' + else: + read_port_dir_req_str = 'o' + read_port_dir_rsp_str = 'i' + + if srp: + read_dp_valid_in = 'r_dp_valid_i' + read_dp_ready_out = 'r_dp_ready_o' + read_dp_response = 'r_dp_rsp_o' + read_dp_valid_out = 'r_dp_valid_o' + read_dp_ready_in = 'r_dp_ready_i' + read_meta_request = 'ar_req_i' + read_meta_valid = 'ar_valid_i' + read_meta_ready = 'ar_ready_o' + r_chan_valid = 'r_chan_valid_o' + r_chan_ready = 'r_chan_ready_o' + buffer_in = 'buffer_in' + buffer_in_valid = 'buffer_in_valid' + else: + if num_heads == 1: + read_dp_valid_in = f'''\ +(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +r_dp_valid_i\ ''' - read_dp_ready_out = f'{rp}_r_dp_ready' - read_dp_response = f'{rp}_r_dp_rsp' - read_dp_valid_out = f'{rp}_r_dp_valid' - read_dp_ready_in = f'''\ -(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & r_dp_ready_i\ + else: + read_dp_valid_in = f'''\ +(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +(r_dp_req_i.src_head == {curr_head}) & \ +r_dp_valid_i\ ''' - read_meta_request = 'ar_req_i.ar_req' - read_meta_valid = f'''\ -(ar_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & ar_valid_i\ + read_dp_ready_out = f'{rp}_r_dp_ready{mh_bus}' + read_dp_response = f'{rp}_r_dp_rsp{mh_bus}' + read_dp_valid_out = f'{rp}_r_dp_valid{mh_bus}' + if num_heads == 1: + read_dp_ready_in = f'''\ +(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +r_dp_ready_i\ ''' - read_meta_ready = f'{rp}_ar_ready' - r_chan_valid = f'{rp}_r_chan_valid' - r_chan_ready = f'{rp}_r_chan_ready' - buffer_in = f'{rp}_buffer_in' - buffer_in_valid = f'{rp}_buffer_in_valid' - - read_port_context = { - 'database': db, - 'req_t': read_req_str, - 'rsp_t': read_rsp_str, - 'r_dp_valid_i': read_dp_valid_in, - 'r_dp_ready_o': read_dp_ready_out, - 'r_dp_rsp_o': read_dp_response, - 'r_dp_valid_o': read_dp_valid_out, - 'r_dp_ready_i': read_dp_ready_in, - 'read_meta_request': read_meta_request, - 'read_meta_valid': read_meta_valid, - 'read_meta_ready': read_meta_ready, - 'read_request': f'{rp}_read_req_{read_port_dir_req_str}', - 'read_response': f'{rp}_read_rsp_{read_port_dir_rsp_str}', - 'r_chan_valid': r_chan_valid, - 'r_chan_ready': r_chan_ready, - 'buffer_in': buffer_in, - 'buffer_in_valid': buffer_in_valid - } - - # render - res[rp] = Template(db[rp]['read_template']).render(**read_port_context) + else: + read_dp_ready_in = f'''\ +(r_dp_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +(r_dp_req_i.src_head == {curr_head}) & \ +r_dp_ready_i\ +''' + read_meta_request = 'ar_req_i.ar_req' + if num_heads == 1: + read_meta_valid = f'''\ +(ar_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +ar_valid_i\ +''' + else: + read_meta_valid = f'''\ +(ar_req_i.src_protocol == idma_pkg::{db[rp]["protocol_enum"]}) & \ +(r_dp_req_i.src_head == {curr_head}) & \ +ar_valid_i\ +''' + read_meta_ready = f'{rp}_ar_ready{mh_bus}' + r_chan_valid = f'{rp}_r_chan_valid{mh_bus}' + r_chan_ready = f'{rp}_r_chan_ready{mh_bus}' + buffer_in = f'{rp}_buffer_in{mh_bus}' + buffer_in_valid = f'{rp}_buffer_in_valid{mh_bus}' + + read_port_context = { + 'database': db, + 'req_t': read_req_str, + 'rsp_t': read_rsp_str, + 'r_dp_valid_i': read_dp_valid_in, + 'r_dp_ready_o': read_dp_ready_out, + 'r_dp_rsp_o': read_dp_response, + 'r_dp_valid_o': read_dp_valid_out, + 'r_dp_ready_i': read_dp_ready_in, + 'read_meta_request': read_meta_request, + 'read_meta_valid': read_meta_valid, + 'read_meta_ready': read_meta_ready, + 'read_request': f'{rp}_read_req_{read_port_dir_req_str}', + 'read_response': f'{rp}_read_rsp_{read_port_dir_rsp_str}', + 'r_chan_valid': r_chan_valid, + 'r_chan_ready': r_chan_ready, + 'buffer_in': buffer_in, + 'buffer_in_valid': buffer_in_valid, + 'mh': mh + } + + if curr_head > 0: + res[rp] += '\n\n' + + # render + res[rp] += Template(db[rp]['read_template']).render(**read_port_context) return res @@ -110,61 +156,99 @@ def render_write_mgr_inst(prot_id: str, prot_ids: dict, db: dict) -> dict: # Render read ports for wp in prot_ids[prot_id]['aw']: + res[wp] = '' + + # prepare multihead snippets + num_heads = prot_ids[prot_id]['multihead']['w'][wp] + + # treat multi head config as multi protocol config + swp &= num_heads == 1 + # template cleanup db[wp]['write_template'] = ' ' + db[wp]['write_template'].replace('\n', '\n ') db[wp]['write_template'] = db[wp]['write_template'][:-5] - if db[wp]['read_slave'] == 'true': - write_req_str = f'{wp}_write_req_t' - write_rsp_str = f'{wp}_write_rsp_t' - else: - write_req_str = f'{wp}_req_t' - write_rsp_str = f'{wp}_rsp_t' - - if swp: - write_dp_valid_in = 'w_dp_valid_i' - write_dp_ready_out = 'w_dp_ready_o' - write_dp_response = 'w_dp_rsp_o' - write_dp_valid_out = 'w_dp_valid_o' - write_dp_ready_in = 'w_dp_ready_i' - write_meta_request = 'aw_req_i' - write_meta_valid = 'aw_valid_i' - write_meta_ready = 'aw_ready_o' - buffer_out_ready = 'buffer_out_ready' - else: - write_dp_valid_in = f'''\ -(w_dp_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & w_dp_req_valid\ + # iterate over heads + for curr_head in range(0, num_heads): + + if num_heads == 1: + mh = '' + mh_bus = '' + else: + mh = f'_{curr_head}' + mh_bus = f' [{curr_head}]' + + if db[wp]['read_slave'] == 'true': + write_req_str = f'{wp}_write_req_t' + write_rsp_str = f'{wp}_write_rsp_t' + else: + write_req_str = f'{wp}_req_t' + write_rsp_str = f'{wp}_rsp_t' + + if swp: + write_dp_valid_in = 'w_dp_valid_i' + write_dp_ready_out = 'w_dp_ready_o' + write_dp_response = 'w_dp_rsp_o' + write_dp_valid_out = 'w_dp_valid_o' + write_dp_ready_in = 'w_dp_ready_i' + write_meta_request = 'aw_req_i' + write_meta_valid = 'aw_valid_i' + write_meta_ready = 'aw_ready_o' + buffer_out_ready = 'buffer_out_ready' + else: + if num_heads == 1: + write_dp_valid_in = f'''\ +(w_dp_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & \ +w_dp_req_valid\ ''' - write_dp_ready_out = f'{wp}_w_dp_ready' - write_dp_response = f'{wp}_w_dp_rsp' - write_dp_valid_out = f'{wp}_w_dp_rsp_valid' - write_dp_ready_in = f'{wp}_w_dp_rsp_ready' - write_meta_request = 'aw_req_i.aw_req' - write_meta_valid = f'''\ -(aw_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & aw_valid_i\ + else: + write_dp_valid_in = f'''\ +(w_dp_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & \ +(r_dp_req_i.dst_head == {curr_head}) & \ +w_dp_req_valid\ ''' - write_meta_ready = f'{wp}_aw_ready' - buffer_out_ready = f'{wp}_buffer_out_ready' - - write_port_context = { - 'database': db, - 'req_t': write_req_str, - 'rsp_t': write_rsp_str, - 'w_dp_valid_i': write_dp_valid_in, - 'w_dp_ready_o': write_dp_ready_out, - 'w_dp_rsp_o': write_dp_response, - 'w_dp_valid_o': write_dp_valid_out, - 'w_dp_ready_i': write_dp_ready_in, - 'write_meta_request': write_meta_request, - 'write_meta_valid': write_meta_valid, - 'write_meta_ready': write_meta_ready, - 'write_request': f'{wp}_write_req_o', - 'write_response': f'{wp}_write_rsp_i', - 'buffer_out_ready': buffer_out_ready - } - - # render - res[wp] = Template(db[wp]['write_template']).render(**write_port_context) + write_dp_ready_out = f'{wp}_w_dp_ready{mh_bus}' + write_dp_response = f'{wp}_w_dp_rsp{mh_bus}' + write_dp_valid_out = f'{wp}_w_dp_rsp_valid{mh_bus}' + write_dp_ready_in = f'{wp}_w_dp_rsp_ready{mh_bus}' + write_meta_request = 'aw_req_i.aw_req' + if num_heads == 1: + write_meta_valid = f'''\ +(aw_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & \ +aw_valid_i\ +''' + else: + write_meta_valid = f'''\ +(aw_req_i.dst_protocol == idma_pkg::{db[wp]["protocol_enum"]}) & \ +(r_dp_req_i.dst_head == {curr_head}) & \ +aw_valid_i\ +''' + write_meta_ready = f'{wp}_aw_ready{mh_bus}' + buffer_out_ready = f'{wp}_buffer_out_ready{mh_bus}' + + write_port_context = { + 'database': db, + 'req_t': write_req_str, + 'rsp_t': write_rsp_str, + 'w_dp_valid_i': write_dp_valid_in, + 'w_dp_ready_o': write_dp_ready_out, + 'w_dp_rsp_o': write_dp_response, + 'w_dp_valid_o': write_dp_valid_out, + 'w_dp_ready_i': write_dp_ready_in, + 'write_meta_request': write_meta_request, + 'write_meta_valid': write_meta_valid, + 'write_meta_ready': write_meta_ready, + 'write_request': f'{wp}_write_req_o', + 'write_response': f'{wp}_write_rsp_i', + 'buffer_out_ready': buffer_out_ready, + 'mh': mh + } + + if curr_head > 0: + res[wp] += '\n\n' + + # render + res[wp] += Template(db[wp]['write_template']).render(**write_port_context) return res @@ -179,6 +263,18 @@ def render_transport_layer(prot_ids: dict, db: dict, tpl_file: str) -> str: # render for every is for prot_id in prot_ids: + # format multi head bus + any_mh = {'ar': False, 'aw': False} + mh_format = {'ar': {}, 'aw': {}} + for dir in ['r', 'w']: + for mhp in prot_ids[prot_id]['multihead'][dir]: + num_heads = prot_ids[prot_id]['multihead'][dir][mhp] + if (num_heads == 1): + mh_format['a' + dir][mhp] = '' + else: + any_mh['a' + dir] |= True + mh_format['a' + dir][mhp] = f'[{num_heads-1}:0] ' + # Render Transport Layer context = { 'name_uniqueifier': prot_id, @@ -186,8 +282,10 @@ def render_transport_layer(prot_ids: dict, db: dict, tpl_file: str) -> str: 'used_read_protocols': prot_ids[prot_id]['ar'], 'used_write_protocols': prot_ids[prot_id]['aw'], 'used_protocols': prot_ids[prot_id]['used'], - 'one_read_port': len(prot_ids[prot_id]['ar']) == 1, - 'one_write_port': len(prot_ids[prot_id]['aw']) == 1, + 'one_read_port': len(prot_ids[prot_id]['ar']) == 1 and not any_mh['ar'], + 'one_write_port': len(prot_ids[prot_id]['aw']) == 1 and not any_mh['aw'], + 'mh_format': mh_format, + 'any_mh': any_mh, 'rendered_read_ports': render_read_mgr_inst(prot_id, prot_ids, db), 'rendered_write_ports': render_write_mgr_inst(prot_id, prot_ids, db) } diff --git a/util/mario/util.py b/util/mario/util.py index 74376c58..8cc2d492 100644 --- a/util/mario/util.py +++ b/util/mario/util.py @@ -58,27 +58,49 @@ def prepare_ids(id_strs: list) -> dict: # check specifier ordering specifiers = id[::2] + specifiers = [''.join(i for i in s if not i.isdigit()) for s in specifiers] + if not specifiers == sorted(specifiers): - print(f'[MARIO] Specifier order not corrected in {id_str}', file=sys.stderr) + print(f'[MARIO] Specifier order not correct in {id_str}', file=sys.stderr) sys.exit(1) # get protocols r_prots = [] w_prots = [] rw_prots = [] + multihead = {'r': {}, 'w': {}} for idx in range(0, len(id), 2): - if id[idx] == 'r': + # check if we have a multi head config + num_char_idx = 0 + for c in id[idx]: + if c.isdigit(): + num_char_idx += 1 + + current_id = id[idx][num_char_idx:] + num_channels = id[idx][:num_char_idx] + if num_channels != '': + num_channels = int(num_channels) + if num_channels < 2: + print(f'[MARIO] Multi head specifier not correct in {id_str}', file=sys.stderr) + sys.exit(1) + else: + num_channels = 1 + + if current_id == 'r': r_prots.append(id[idx + 1]) - elif id[idx] == 'w': + multihead['r'][id[idx + 1]] = num_channels + elif current_id == 'w': w_prots.append(id[idx + 1]) - elif id[idx] == 'rw': + multihead['w'][id[idx + 1]] = num_channels + elif current_id == 'rw': rw_prots.append(id[idx + 1]) + multihead['r'][id[idx + 1]] = num_channels + multihead['w'][id[idx + 1]] = num_channels else: print(f'[MARIO] {id[idx]} is non-supported specifier', file=sys.stderr) sys.exit(1) # check protocol ordering - specifiers = id[::2] if not r_prots == sorted(r_prots): print('[MARIO] Read protocols order not correct', file=sys.stderr) sys.exit(1) @@ -91,6 +113,13 @@ def prepare_ids(id_strs: list) -> dict: print('[MARIO] Bidir protocols order not correct', file=sys.stderr) sys.exit(1) + # check if a rw_prot is declared as one read and write prot + for rp in r_prots: + if rp in w_prots: + if multihead['r'][rp] == multihead['w'][rp]: + print('[MARIO] Use rw specifier instead of r and w separately', file=sys.stderr) + sys.exit(1) + # create all_read and all_write ar_prots = [] [ar_prots.append(rp) for rp in r_prots] @@ -116,7 +145,7 @@ def prepare_ids(id_strs: list) -> dict: # append protocols res[id_str] = {'r': r_prots, 'w': w_prots, 'rw': rw_prots, 'ar': sorted(ar_prots), - 'aw': sorted(aw_prots), 'used': sorted(list(set(used_prots)))} + 'aw': sorted(aw_prots), 'used': sorted(list(set(used_prots))), 'multihead': multihead} return res