blob: 5e64a8509f16b6330c33552a730b168805184641 [file] [log] [blame]
// 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('.', '__')
# TODO #15754: Pass this parameter through the tlgen script instead of hardcoding
%>\
% if block.node_type.name == "ASYNC_FIFO":
tlul_fifo_async #(
.ReqDepth (1),
.RspDepth (1)
) 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 != 1:
.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 != 1:
.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 != 1:
.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 != 1:
.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