Skip to content
Snippets Groups Projects
Commit 31f64b66 authored by Wesley W. Terpstra's avatar Wesley W. Terpstra
Browse files

crossbar: eliminate code duplication

parent dff14433
Branches
Tags
No related merge requests found
......@@ -47,60 +47,8 @@ architecture rtl of xwb_sdb_crossbar is
constant c_sdb_bytes : natural := c_sdb_device_length / 8;
constant c_rom_bytes : natural := c_rom_entries * c_sdb_bytes;
type t_sizes is record
bus_last : unsigned(63 downto 0);
msi_last : unsigned(63 downto 0);
end record t_sizes;
-- Step 2. Find the size of the bus
function f_sizes return t_sizes is
variable result : t_sizes;
variable typ : std_logic_vector(7 downto 0);
variable last : unsigned(63 downto 0);
constant zero : t_wishbone_address := (others => '0');
begin
-- The SDB block must be aligned
assert (g_sdb_addr and std_logic_vector(to_unsigned(c_rom_bytes - 1, c_wishbone_address_width))) = zero
report "SDB address is not aligned (" & f_bits2string(g_sdb_addr) & "). This is not supported by the crossbar."
severity Failure;
-- The ROM will be an addressed slave as well
result.bus_last := (others => '0');
result.bus_last(g_sdb_addr'range) := unsigned(g_sdb_addr);
result.bus_last := result.bus_last + to_unsigned(c_rom_bytes, 64) - 1;
-- There are no MSI targets by default
result.msi_last := (others => '0');
for i in c_layout'range loop
typ := c_layout(i)(7 downto 0);
last := unsigned(f_sdb_extract_component(c_layout(i)(447 downto 8)).addr_last);
case typ is
when x"01" => if last > result.bus_last then result.bus_last := last; end if;
when x"02" => if last > result.bus_last then result.bus_last := last; end if;
when x"03" => if last > result.msi_last then result.msi_last := last; end if;
when others => null;
end case;
end loop;
-- round result up to a power of two -1
for i in 62 downto 0 loop
result.bus_last(i) := result.bus_last(i) or result.bus_last(i+1);
result.msi_last(i) := result.msi_last(i) or result.msi_last(i+1);
end loop;
-- Not a wraparound bus? Ignore all that hard work.
if not g_wraparound then
result.bus_last := (others => '0');
for i in 0 to c_wishbone_address_width-1 loop
result.bus_last(i) := '1';
end loop;
end if;
return result;
end f_sizes;
constant c_sizes : t_sizes := f_sizes;
constant c_bus_last : unsigned := f_sdb_bus_end(g_wraparound, g_layout, g_sdb_addr, false);
constant c_msi_last : unsigned := f_sdb_bus_end(g_wraparound, g_layout, g_sdb_addr, true);
type t_addresses is record
bus_address : t_wishbone_address_array(g_num_slaves -1 downto 0);
......@@ -162,7 +110,7 @@ architecture rtl of xwb_sdb_crossbar is
report "Too many device and bridge records found in g_layout"
severity Failure;
size := c_sizes.bus_last - size;
size := c_bus_last - size;
result.bus_address(bus_index) := address;
result.bus_mask (bus_index) := std_logic_vector(size(address'range));
bus_index := bus_index + 1;
......@@ -172,7 +120,7 @@ architecture rtl of xwb_sdb_crossbar is
report "Too many msi records found in g_layout"
severity Failure;
size := c_sizes.msi_last - size;
size := c_msi_last - size;
result.msi_address(msi_index) := address;
result.msi_mask (msi_index) := std_logic_vector(size(address'range));
msi_index := msi_index + 1;
......@@ -213,7 +161,7 @@ architecture rtl of xwb_sdb_crossbar is
-- Figure out the mask for the SDB slave
constant c_rom_mask : unsigned(63 downto 0) :=
c_sizes.bus_last - to_unsigned(c_rom_bytes-1, 64);
c_bus_last - to_unsigned(c_rom_bytes-1, 64);
constant c_sdb_mask : t_wishbone_address :=
std_logic_vector(c_rom_mask(c_wishbone_address_width-1 downto 0));
......@@ -237,7 +185,7 @@ begin
generic map(
g_layout => c_layout,
g_masters => g_num_masters,
g_bus_end => c_sizes.bus_last)
g_bus_end => c_bus_last)
port map(
clk_sys_i => clk_sys_i,
master_i => sdb_sel,
......
......@@ -207,6 +207,7 @@ package wishbone_pkg is
function f_sdb_auto_sdb (slaves : t_sdb_record_array; masters : t_sdb_record_array) return t_wishbone_address;
-- For internal use by the crossbar
function f_sdb_bus_end(g_wraparound : boolean; g_layout : t_sdb_record_array; g_sdb_addr : t_wishbone_address; msi : boolean) return unsigned;
function f_sdb_embed_product(product : t_sdb_product) return std_logic_vector; -- (319 downto 8)
function f_sdb_embed_component(sdb_component : t_sdb_component; address : t_wishbone_address) return std_logic_vector; -- (447 downto 8)
function f_sdb_extract_product(sdb_record : std_logic_vector(319 downto 8)) return t_sdb_product;
......@@ -346,8 +347,11 @@ package wishbone_pkg is
g_layout : t_sdb_record_array;
g_sdb_addr : t_wishbone_address) return t_sdb_bridge;
function f_xwb_msi_manual_sdb( -- take a manual bus size
g_size : t_wishbone_address) return t_sdb_msi;
function f_xwb_msi_layout_sdb( -- determine MSI size from layout
g_layout : t_sdb_record_array) return t_sdb_bridge;
g_layout : t_sdb_record_array) return t_sdb_msi;
component xwb_sdb_crossbar
generic (
......@@ -1744,33 +1748,11 @@ package body wishbone_pkg is
-- END MAT's NEW FUNCTIONS FROM 18th Oct 2013
------------------------------------------------------------------------------------------------------------------------------
function f_xwb_bridge_manual_sdb(
g_size : t_wishbone_address;
g_sdb_addr : t_wishbone_address) return t_sdb_bridge
is
variable result : t_sdb_bridge;
begin
result.sdb_child := (others => '0');
result.sdb_child(c_wishbone_address_width-1 downto 0) := g_sdb_addr;
result.sdb_component.addr_first := (others => '0');
result.sdb_component.addr_last := (others => '0');
result.sdb_component.addr_last(c_wishbone_address_width-1 downto 0) := g_size;
result.sdb_component.product.vendor_id := x"0000000000000651"; -- GSI
result.sdb_component.product.device_id := x"eef0b198";
result.sdb_component.product.version := x"00000001";
result.sdb_component.product.date := x"20120511";
result.sdb_component.product.name := "WB4-Bridge-GSI ";
return result;
end f_xwb_bridge_manual_sdb;
function f_xwb_bridge_layout_sdb_helper(
g_wraparound : boolean := true;
function f_sdb_bus_end(
g_wraparound : boolean;
g_layout : t_sdb_record_array;
g_sdb_addr : t_wishbone_address;
msi : boolean) return t_sdb_bridge
msi : boolean) return unsigned
is
alias c_layout : t_sdb_record_array(g_layout'length-1 downto 0) is g_layout;
......@@ -1814,23 +1796,71 @@ package body wishbone_pkg is
end loop;
end if;
return f_xwb_bridge_manual_sdb(std_logic_vector(result(c_wishbone_address_width-1 downto 0)), g_sdb_addr);
end f_xwb_bridge_layout_sdb_helper;
return result;
end f_sdb_bus_end;
function f_xwb_bridge_manual_sdb(
g_size : t_wishbone_address;
g_sdb_addr : t_wishbone_address) return t_sdb_bridge
is
variable result : t_sdb_bridge;
begin
result.sdb_child := (others => '0');
result.sdb_child(c_wishbone_address_width-1 downto 0) := g_sdb_addr;
result.sdb_component.addr_first := (others => '0');
result.sdb_component.addr_last := (others => '0');
result.sdb_component.addr_last(c_wishbone_address_width-1 downto 0) := g_size;
result.sdb_component.product.vendor_id := x"0000000000000651"; -- GSI
result.sdb_component.product.device_id := x"eef0b198";
result.sdb_component.product.version := x"00000001";
result.sdb_component.product.date := x"20120511";
result.sdb_component.product.name := "WB4-Bridge-GSI ";
return result;
end f_xwb_bridge_manual_sdb;
function f_xwb_bridge_layout_sdb( -- determine bus size from layout
g_wraparound : boolean := true;
g_layout : t_sdb_record_array;
g_sdb_addr : t_wishbone_address) return t_sdb_bridge
is begin
return f_xwb_bridge_layout_sdb_helper(g_wraparound, g_layout, g_sdb_addr, false);
is
variable address : t_wishbone_address;
begin
address := std_logic_vector(f_sdb_bus_end(g_wraparound, g_layout, g_sdb_addr, false)(address'range));
return f_xwb_bridge_manual_sdb(address, g_sdb_addr);
end f_xwb_bridge_layout_sdb;
function f_xwb_msi_manual_sdb(
g_size : t_wishbone_address) return t_sdb_msi
is
variable result : t_sdb_msi;
begin
result.wbd_endian := '0';
result.wbd_width := x"7";
result.sdb_component.addr_first := (others => '0');
result.sdb_component.addr_last := (others => '0');
result.sdb_component.addr_last(c_wishbone_address_width-1 downto 0) := g_size;
result.sdb_component.product.vendor_id := x"0000000000000651"; -- GSI
result.sdb_component.product.device_id := x"aa7bfb3c";
result.sdb_component.product.version := x"00000001";
result.sdb_component.product.date := x"20160422";
result.sdb_component.product.name := "WB4-MSI-Bridge-GSI ";
return result;
end f_xwb_msi_manual_sdb;
function f_xwb_msi_layout_sdb( -- determine MSI size from layout
g_layout : t_sdb_record_array) return t_sdb_bridge
g_layout : t_sdb_record_array) return t_sdb_msi
is
constant zero : t_wishbone_address := (others => '0');
variable address : t_wishbone_address;
begin
return f_xwb_bridge_layout_sdb_helper(false, g_layout, zero, true);
address := std_logic_vector(f_sdb_bus_end(true, g_layout, zero, true)(address'range));
return f_xwb_msi_manual_sdb(address);
end f_xwb_msi_layout_sdb;
function f_xwb_dpram(g_size : natural) return t_sdb_device
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment