| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 | // | 
 | // xbar_${xbar.name} module generated by `tlgen.py` tool | 
 | // all reset signals should be generated from one reset signal to not make any deadlock | 
 | // | 
 | // Interconnect | 
 | <% | 
 |   import tlgen.lib as lib | 
 | %>\ | 
 | % for host in xbar.hosts: | 
 | ${xbar.repr_tree(host, 0)} | 
 | % endfor | 
 |  | 
 | module xbar_${xbar.name} ( | 
 | % for c in xbar.clocks: | 
 |   input ${c}, | 
 | % endfor | 
 | % for r in xbar.resets: | 
 |   input ${r}, | 
 | % endfor | 
 |  | 
 |   // Host interfaces | 
 | % for node in xbar.hosts: | 
 |   input  tlul_pkg::tl_h2d_t tl_${node.name.replace('.', '__')}_i, | 
 |   output tlul_pkg::tl_d2h_t tl_${node.name.replace('.', '__')}_o, | 
 | % endfor | 
 |  | 
 |   // Device interfaces | 
 | % for node in xbar.devices: | 
 |   output tlul_pkg::tl_h2d_t tl_${node.name.replace('.', '__')}_o, | 
 |   input  tlul_pkg::tl_d2h_t tl_${node.name.replace('.', '__')}_i, | 
 | % endfor | 
 |  | 
 |   input prim_mubi_pkg::mubi4_t scanmode_i | 
 | ); | 
 |  | 
 |   import tlul_pkg::*; | 
 |   import tl_${xbar.name}_pkg::*; | 
 |  | 
 |   // scanmode_i is currently not used, but provisioned for future use | 
 |   // this assignment prevents lint warnings | 
 |   logic unused_scanmode; | 
 |   assign unused_scanmode = ^scanmode_i; | 
 |  | 
 | % for block in xbar.nodes: | 
 |   ## Create enum type for Upstream and Downstream ports connection | 
 |   % if block.node_type.name   == "ASYNC_FIFO": | 
 |     ## One US, one DS | 
 |   tl_h2d_t tl_${block.name}_us_h2d ; | 
 |   tl_d2h_t tl_${block.name}_us_d2h ; | 
 |   tl_h2d_t tl_${block.name}_ds_h2d ; | 
 |   tl_d2h_t tl_${block.name}_ds_d2h ; | 
 |  | 
 |   % elif block.node_type.name == "SOCKET_1N": | 
 |     ## One US, multiple DS | 
 |   tl_h2d_t tl_${block.name}_us_h2d ; | 
 |   tl_d2h_t tl_${block.name}_us_d2h ; | 
 |  | 
 |   ##typedef enum int { | 
 |   ##  % for port in block.ds: | 
 |   ##    % if loop.last: | 
 |   ##    % else: | 
 |   ##    % endif | 
 |   ##  % endfor | 
 |   ##} socket_${block.name}_ds_e; | 
 |  | 
 |   tl_h2d_t tl_${block.name}_ds_h2d [${len(block.ds)}]; | 
 |   tl_d2h_t tl_${block.name}_ds_d2h [${len(block.ds)}]; | 
 |  | 
 |   // Create steering signal | 
 |   logic [${len(block.ds).bit_length()-1}:0] dev_sel_${block.name}; | 
 |  | 
 |   % elif block.node_type.name == "SOCKET_M1": | 
 |     ## Multiple US, one DS | 
 |     ## typedef enum int { | 
 |     ##   % for port in block.us: | 
 |     ##     % if loop.last: | 
 |     ##     % else: | 
 |     ##     % endif | 
 |     ##   % endfor | 
 |     ## } socket_${block.name}_us_e; | 
 |  | 
 |   tl_h2d_t tl_${block.name}_us_h2d [${len(block.us)}]; | 
 |   tl_d2h_t tl_${block.name}_us_d2h [${len(block.us)}]; | 
 |  | 
 |   tl_h2d_t tl_${block.name}_ds_h2d ; | 
 |   tl_d2h_t tl_${block.name}_ds_d2h ; | 
 |  | 
 |   % else: | 
 |     ## block is either HOST or DEVICE. Ignore | 
 |   % endif | 
 | % endfor | 
 |  | 
 | % for conn in xbar.edges: | 
 |   ## sweep each entry of edges and find each end (us, ds) then connect between | 
 |   ## Connect upstream | 
 | <% | 
 |     ds_name = conn.ds.name.replace('.', '__') | 
 |     us_name = conn.us.name.replace('.', '__') | 
 |  | 
 |     if conn.ds.node_type.name == "ASYNC_FIFO": | 
 |       ds_h2d_name = 'tl_' + ds_name + '_us_h2d' | 
 |       ds_d2h_name = 'tl_' + ds_name + '_us_d2h' | 
 |       ds_index = -1 | 
 |     elif conn.ds.node_type.name == "SOCKET_1N": | 
 |       ds_h2d_name = 'tl_' + ds_name + '_us_h2d' | 
 |       ds_d2h_name = 'tl_' + ds_name + '_us_d2h' | 
 |       ds_index = -1 | 
 |     elif conn.ds.node_type.name == "SOCKET_M1": | 
 |       ds_h2d_name = 'tl_' + ds_name + '_us_h2d' | 
 |       ds_d2h_name = 'tl_' + ds_name + '_us_d2h' | 
 |       ds_index = conn.ds.us.index(conn) | 
 |     elif conn.ds.node_type.name == "DEVICE": | 
 |       ds_h2d_name = 'tl_' + ds_name + '_o' | 
 |       ds_d2h_name = 'tl_' + ds_name + '_i' | 
 |       ds_index = -1 | 
 |  | 
 |     if conn.us.node_type.name == "ASYNC_FIFO": | 
 |       us_h2d_name = 'tl_' + us_name + '_ds_h2d' | 
 |       us_d2h_name = 'tl_' + us_name + '_ds_d2h' | 
 |       us_index = -1 | 
 |     elif conn.us.node_type.name == "SOCKET_1N": | 
 |       us_h2d_name = 'tl_' + us_name + '_ds_h2d' | 
 |       us_d2h_name = 'tl_' + us_name + '_ds_d2h' | 
 |       us_index = conn.us.ds.index(conn) | 
 |     elif conn.us.node_type.name == "SOCKET_M1": | 
 |       us_h2d_name = 'tl_' + us_name + '_ds_h2d' | 
 |       us_d2h_name = 'tl_' + us_name + '_ds_d2h' | 
 |       us_index = -1 | 
 |     elif conn.us.node_type.name == "HOST": | 
 |       us_h2d_name = 'tl_' + us_name + '_i' | 
 |       us_d2h_name = 'tl_' + us_name + '_o' | 
 |       us_index = -1 | 
 | %>\ | 
 |  | 
 | % if us_index == -1 and ds_index == -1: | 
 |   assign ${ds_h2d_name} = ${us_h2d_name}; | 
 |   assign ${us_d2h_name} = ${ds_d2h_name}; | 
 | % elif us_index == -1 and ds_index != -1: | 
 |   assign ${ds_h2d_name}[${ds_index}] = ${us_h2d_name}; | 
 |   assign ${us_d2h_name} = ${ds_d2h_name}[${ds_index}]; | 
 | % elif us_index != -1 and ds_index == -1: | 
 |   assign ${ds_h2d_name} = ${us_h2d_name}[${us_index}]; | 
 |   assign ${us_d2h_name}[${us_index}] = ${ds_d2h_name}; | 
 | % else: | 
 |   assign ${ds_h2d_name}[${ds_index}] = ${us_h2d_name}[${us_index}]; | 
 |   assign ${us_d2h_name}[${us_index}] = ${ds_d2h_name}[${ds_index}]; | 
 | % endif | 
 | % endfor | 
 |  | 
 | % for block in xbar.socket_1ns: | 
 | <% | 
 |   addr_sig = "tl_" + block.name + "_us_h2d.a_address" | 
 |   sel_len = len(block.ds).bit_length() | 
 | %>\ | 
 |   always_comb begin | 
 |     // default steering to generate error response if address is not within the range | 
 |     dev_sel_${block.name} = ${"%d'd%d" % (sel_len, len(block.ds))}; | 
 | % for i in block.ds: | 
 | <% | 
 |   leaf = xbar.get_leaf_from_s1n(block, loop.index); | 
 |   leaf_name = leaf.name.upper().replace('.', '__') | 
 |  | 
 |   name_space = "ADDR_SPACE_" + leaf_name; | 
 |   name_mask  = "ADDR_MASK_" + leaf_name; | 
 |   prefix = "if (" if loop.first else "end else if (" | 
 | %>\ | 
 |   % if len(leaf.addr_range) == 1: | 
 |       % if lib.is_pow2((leaf.addr_range[0][1]-leaf.addr_range[0][0])+1): | 
 |     ${prefix}(${addr_sig} & | 
 |     ${" " * len(prefix)} ~(${name_mask})) == ${name_space}) begin | 
 |       % else: | 
 |     ${prefix}((${addr_sig} <= (${name_mask} + ${name_space})) && | 
 |        (${addr_sig} >= ${name_space}))) begin | 
 |       % endif | 
 |       dev_sel_${block.name} = ${"%d'd%d" % (sel_len, loop.index)}; | 
 | ${"end" if loop.last else ""} | 
 |   % else: | 
 |     ## Xbar device port | 
 | <% | 
 |   num_range = len(leaf.addr_range) | 
 | %>\ | 
 |     ${prefix} | 
 |     % for i in range(num_range): | 
 |       % if lib.is_pow2(leaf.addr_range[i][1]-leaf.addr_range[0][0]+1): | 
 |       ((${addr_sig} & ~(${name_mask}[${i}])) == ${name_space}[${i}])${" ||" if not loop.last else ""} | 
 |       % else: | 
 |       ((${addr_sig} <= (${name_mask}[${i}] + ${name_space}[${i}])) && | 
 |        (${addr_sig} >= ${name_space}[${i}]))${" ||" if not loop.last else ""} | 
 |       % endif | 
 |     % endfor | 
 |     ) begin | 
 |       dev_sel_${block.name} = ${"%d'd%d" % (sel_len, loop.index)}; | 
 | ${"end" if loop.last else ""} | 
 |   % endif | 
 | % endfor | 
 |   end | 
 |  | 
 | % endfor | 
 |  | 
 |   // Instantiation phase | 
 | % for block in xbar.nodes: | 
 | <% | 
 |   stripped_name = block.name.replace('.', '__') | 
 | %>\ | 
 |   % if block.node_type.name   == "ASYNC_FIFO": | 
 |   tlul_fifo_async #( | 
 |     .ReqDepth        (4),// At least 4 to make async work | 
 |     .RspDepth        (4) // At least 4 to make async work | 
 |   ) u_${stripped_name} ( | 
 |     .clk_h_i      (${block.clocks[0]}), | 
 |     .rst_h_ni     (${block.resets[0]}), | 
 |     .clk_d_i      (${block.clocks[1]}), | 
 |     .rst_d_ni     (${block.resets[1]}), | 
 |     .tl_h_i       (tl_${stripped_name}_us_h2d), | 
 |     .tl_h_o       (tl_${stripped_name}_us_d2h), | 
 |     .tl_d_o       (tl_${stripped_name}_ds_h2d), | 
 |     .tl_d_i       (tl_${stripped_name}_ds_d2h) | 
 |   ); | 
 |   % elif block.node_type.name == "SOCKET_1N": | 
 |   tlul_socket_1n #( | 
 |     % if block.hreq_pass != 1: | 
 |     .HReqPass  (1'b${block.hreq_pass}), | 
 |     % endif | 
 |     % if block.hrsp_pass != 1: | 
 |     .HRspPass  (1'b${block.hrsp_pass}), | 
 |     % endif | 
 |     % if block.hdepth != 2: | 
 |     .HReqDepth (4'h${block.hdepth}), | 
 |     .HRspDepth (4'h${block.hdepth}), | 
 |     % endif | 
 |     % if block.dreq_pass != 2**(len(block.ds)) -1: | 
 |     .DReqPass  (${len(block.ds)}'h${"%x" % block.dreq_pass}), | 
 |     % endif | 
 |     % if block.drsp_pass != 2**(len(block.ds)) -1: | 
 |     .DRspPass  (${len(block.ds)}'h${"%x" % block.drsp_pass}), | 
 |     % endif | 
 |     % if block.ddepth != 2: | 
 |     .DReqDepth (${len(block.ds)*4}'h${"%x" % block.ddepth}), | 
 |     .DRspDepth (${len(block.ds)*4}'h${"%x" % block.ddepth}), | 
 |     % endif | 
 |     .N         (${len(block.ds)}) | 
 |   ) u_${stripped_name} ( | 
 |     .clk_i        (${block.clocks[0]}), | 
 |     .rst_ni       (${block.resets[0]}), | 
 |     .tl_h_i       (tl_${stripped_name}_us_h2d), | 
 |     .tl_h_o       (tl_${stripped_name}_us_d2h), | 
 |     .tl_d_o       (tl_${stripped_name}_ds_h2d), | 
 |     .tl_d_i       (tl_${stripped_name}_ds_d2h), | 
 |     .dev_select_i (dev_sel_${stripped_name}) | 
 |   ); | 
 |   % elif block.node_type.name == "SOCKET_M1": | 
 |   tlul_socket_m1 #( | 
 |     % if block.hreq_pass != 2**(len(block.us)) - 1: | 
 |     .HReqPass  (${len(block.us)}'h${"%x" % block.hreq_pass}), | 
 |     % endif | 
 |     % if block.hrsp_pass != 2**(len(block.us)) - 1: | 
 |     .HRspPass  (${len(block.us)}'h${"%x" % block.hrsp_pass}), | 
 |     % endif | 
 |     % if block.hdepth != 2: | 
 |     .HReqDepth (${len(block.us)*4}'h${"%x" % block.hdepth}), | 
 |     .HRspDepth (${len(block.us)*4}'h${"%x" % block.hdepth}), | 
 |     % endif | 
 |     % if block.dreq_pass != 1: | 
 |     .DReqPass  (1'b${block.dreq_pass}), | 
 |     % endif | 
 |     % if block.drsp_pass != 1: | 
 |     .DRspPass  (1'b${block.drsp_pass}), | 
 |     % endif | 
 |     % if block.ddepth != 2: | 
 |     .DReqDepth (4'h${block.ddepth}), | 
 |     .DRspDepth (4'h${block.ddepth}), | 
 |     % endif | 
 |     .M         (${len(block.us)}) | 
 |   ) u_${stripped_name} ( | 
 |     .clk_i        (${block.clocks[0]}), | 
 |     .rst_ni       (${block.resets[0]}), | 
 |     .tl_h_i       (tl_${stripped_name}_us_h2d), | 
 |     .tl_h_o       (tl_${stripped_name}_us_d2h), | 
 |     .tl_d_o       (tl_${stripped_name}_ds_h2d), | 
 |     .tl_d_i       (tl_${stripped_name}_ds_d2h) | 
 |   ); | 
 |   % endif | 
 | % endfor | 
 |  | 
 | endmodule |