From 31f64b66a770816f86c7d783cde6c2b80e8ead1c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" <w.terpstra@gsi.de> Date: Fri, 22 Apr 2016 16:14:18 +0200 Subject: [PATCH] crossbar: eliminate code duplication --- .../wishbone/wb_crossbar/xwb_sdb_crossbar.vhd | 64 ++----------- modules/wishbone/wishbone_pkg.vhd | 94 ++++++++++++------- 2 files changed, 68 insertions(+), 90 deletions(-) diff --git a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd index 361b52f0..8cec9681 100644 --- a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd +++ b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd @@ -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, diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd index 0cec2cb7..a0e62806 100644 --- a/modules/wishbone/wishbone_pkg.vhd +++ b/modules/wishbone/wishbone_pkg.vhd @@ -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 -- GitLab