From 219b2ad28fc36bbffbcdf94befdb0020591c8adf Mon Sep 17 00:00:00 2001
From: "Wesley W. Terpstra" <w.terpstra@gsi.de>
Date: Thu, 21 Apr 2016 14:24:48 +0200
Subject: [PATCH] sdb: new master-describing SDB record

---
 modules/wishbone/wb_crossbar/sdb_rom.vhd      | 70 +++++++++++++++----
 .../wishbone/wb_crossbar/xwb_sdb_crossbar.vhd |  6 +-
 modules/wishbone/wishbone_pkg.vhd             | 58 ++++++++++++++-
 3 files changed, 119 insertions(+), 15 deletions(-)

diff --git a/modules/wishbone/wb_crossbar/sdb_rom.vhd b/modules/wishbone/wb_crossbar/sdb_rom.vhd
index 1c47f753..37acd3b1 100644
--- a/modules/wishbone/wb_crossbar/sdb_rom.vhd
+++ b/modules/wishbone/wb_crossbar/sdb_rom.vhd
@@ -5,19 +5,22 @@ use work.wishbone_pkg.all;
 
 entity sdb_rom is
   generic(
-    g_layout      : t_sdb_record_array;
+    g_slaves      : t_sdb_record_array;
+    g_masters     : t_sdb_record_array;
     g_bus_end     : unsigned(63 downto 0));
   port(
     clk_sys_i     : in  std_logic;
+    master_i      : in  std_logic_vector(g_masters'length-1 downto 0);
     slave_i       : in  t_wishbone_slave_in;
     slave_o       : out t_wishbone_slave_out);
 end sdb_rom;
 
 architecture rtl of sdb_rom is
-  alias c_layout : t_sdb_record_array(g_layout'length downto 1) is g_layout;
+  alias c_masters : t_sdb_record_array(g_masters'length downto 1) is g_masters;
+  alias c_slaves  : t_sdb_record_array(g_slaves'length+c_masters'high downto c_masters'high+1) is g_slaves;
 
   -- The ROM must describe all slaves, the crossbar itself and the optional information records
-  constant c_used_entries   : natural := c_layout'length + 1;
+  constant c_used_entries   : natural := c_slaves'high + 1;
   constant c_rom_entries    : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
   constant c_sdb_words      : natural := c_sdb_device_length / c_wishbone_data_width;
   constant c_rom_words      : natural := c_rom_entries * c_sdb_words;
@@ -42,10 +45,17 @@ architecture rtl of sdb_rom is
     sdb_component.addr_first := (others => '0');
     sdb_component.addr_last  := std_logic_vector(g_bus_end);
     sdb_component.product.vendor_id := x"0000000000000651"; -- GSI
-    sdb_component.product.device_id := x"e6a542c9";
-    sdb_component.product.version   := x"00000002";
-    sdb_component.product.date      := x"20120511";
-    sdb_component.product.name      := "WB4-Crossbar-GSI   ";
+    if g_masters'length > 0 then
+      sdb_component.product.device_id := x"2b6e61b3";
+      sdb_component.product.version   := x"00000001";
+      sdb_component.product.date      := x"20160421";
+      sdb_component.product.name      := "MSI-Crossbar-GSI   ";
+    else
+      sdb_component.product.device_id := x"e6a542c9";
+      sdb_component.product.version   := x"00000002";
+      sdb_component.product.date      := x"20120511";
+      sdb_component.product.name      := "WB4-Crossbar-GSI   ";
+    end if;
     sdb_device(447 downto   8) := f_sdb_embed_component(sdb_component, (others => '0'));
     
     for i in 0 to c_sdb_words-1 loop
@@ -53,8 +63,17 @@ architecture rtl of sdb_rom is
         sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
     end loop;
     
-    for slave in 1 to c_used_entries-1 loop
-      sdb_device(511 downto 0) := c_layout(slave);
+    for master in c_masters'range loop
+      sdb_device(511 downto 0) := c_masters(master);
+      
+      for i in 0 to c_sdb_words-1 loop
+        res((master+1)*c_sdb_words-1-i) := 
+          sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
+      end loop;
+    end loop;
+    
+    for slave in c_slaves'range loop
+      sdb_device(511 downto 0) := c_slaves(slave);
       
       for i in 0 to c_sdb_words-1 loop
         res((slave+1)*c_sdb_words-1-i) := 
@@ -64,23 +83,50 @@ architecture rtl of sdb_rom is
 
     return res;
   end f_build_rom;
-   
-  signal rom : t_rom := f_build_rom;
+  
+  function f_msi_flag_index(y : std_logic_vector) return std_logic_vector is
+    -- Bump the indexes to start from 1 (0 is the SDB table header)
+    alias x : std_logic_vector(y'length downto 1) is y;
+    -- Result is the full width of the SDB word address
+    variable result : std_logic_vector(c_rom_depth-1 downto 0) := (others => '0');
+    variable step : natural := 1;
+  begin
+    -- Leave bits 0-3 as '0' (16 words per SDB record)
+    for i in 4 to result'high loop
+      for j in x'range loop
+        if (j / step) mod 2 = 1 then
+          result(i) := result(i) or x(j);
+        end if;
+      end loop;
+      step := step + step;
+    end loop;
+    return result;
+  end f_msi_flag_index;
+  
+  constant rom : t_rom := f_build_rom;
   signal adr_reg : unsigned(c_rom_depth-1 downto 0);
+  signal sel_reg : unsigned(c_rom_depth-1 downto 0);
+  
+  signal s_rom  : t_wishbone_data;
+  signal s_flag : t_wishbone_data := (others => '0');
 
 begin
+
   -- Simple ROM; ignore we/sel/dat
   slave_o.err   <= '0';
   slave_o.rty   <= '0';
   slave_o.stall <= '0';
   slave_o.int   <= '0'; -- Tom sucks! This should not be here.
 
-  slave_o.dat <= rom(to_integer(adr_reg));
+  s_rom <= rom(to_integer(adr_reg));
+  s_flag(s_flag'high) <= '1' when adr_reg = sel_reg and g_masters'length > 0 else '0';
+  slave_o.dat <= s_rom or s_flag;
   
   slave_clk : process(clk_sys_i)
   begin
     if (rising_edge(clk_sys_i)) then
       adr_reg <= unsigned(slave_i.adr(c_rom_depth+c_rom_lowbits-1 downto c_rom_lowbits));
+      sel_reg <= unsigned(f_msi_flag_index(master_i));
       slave_o.ack <= slave_i.cyc and slave_i.stb;
     end if;
   end process;
diff --git a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
index f03f03c3..dee02661 100644
--- a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
@@ -154,10 +154,10 @@ architecture rtl of xwb_sdb_crossbar is
   constant c_sdb_mask : t_wishbone_address := 
     std_logic_vector(c_rom_mask(c_wishbone_address_width-1 downto 0));
   constant c_address : t_wishbone_address_array(g_num_slaves downto 0) :=
-  
     g_sdb_addr & f_addresses;
   constant c_mask : t_wishbone_address_array(g_num_slaves downto 0) :=
     c_sdb_mask & f_masks;
+  constant c_null : t_sdb_record_array(0 downto 1) := (others => (others => '0'));
   
   signal master_i_1 :  t_wishbone_master_in_array(g_num_slaves downto 0);
   signal master_o_1 : t_wishbone_master_out_array(g_num_slaves downto 0);
@@ -167,10 +167,12 @@ begin
   
   rom : sdb_rom
     generic map(
-      g_layout   => c_layout,
+      g_slaves   => c_layout,
+      g_masters  => c_null,
       g_bus_end  => c_bus_end)
     port map(
       clk_sys_i => clk_sys_i,
+      master_i  => (others => '0'),
       slave_i   => master_o_1(g_num_slaves),
       slave_o   => master_i_1(g_num_slaves));
   
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index 72c8ac17..ddeed8e5 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -124,6 +124,12 @@ package wishbone_pkg is
     sdb_component : t_sdb_component;
   end record t_sdb_device;
 
+  type t_sdb_msi is record
+    wbd_endian    : std_logic;          -- 0 = big, 1 = little
+    wbd_width     : std_logic_vector(3 downto 0);  -- 3=64-bit, 2=32-bit, 1=16-bit, 0=8-bit
+    sdb_component : t_sdb_component;
+  end record t_sdb_msi;
+
   type t_sdb_bridge is record
     sdb_child     : std_logic_vector(63 downto 0);
     sdb_component : t_sdb_component;
@@ -165,12 +171,14 @@ package wishbone_pkg is
   -- Used to configure a device at a certain address
   function f_sdb_embed_device(device : t_sdb_device; address : t_wishbone_address) return t_sdb_record;
   function f_sdb_embed_bridge(bridge : t_sdb_bridge; address : t_wishbone_address) return t_sdb_record;
+  function f_sdb_embed_msi(msi : t_sdb_msi; address : t_wishbone_address) return t_sdb_record;
   function f_sdb_embed_integration(integr : t_sdb_integration) return t_sdb_record;
   function f_sdb_embed_repo_url(url : t_sdb_repo_url) return t_sdb_record;
   function f_sdb_embed_synthesis(syn : t_sdb_synthesis) return t_sdb_record;
 
   function f_sdb_extract_device(sdb_record : t_sdb_record) return t_sdb_device;
   function f_sdb_extract_bridge(sdb_record : t_sdb_record) return t_sdb_bridge;
+  function f_sdb_extract_msi(sdb_record : t_sdb_record) return t_sdb_msi;
   function f_sdb_extract_integration(sdb_record : t_sdb_record) return t_sdb_integration;
   function f_sdb_extract_repo_url(sdb_record : t_sdb_record) return t_sdb_repo_url;
   function f_sdb_extract_synthesis(sdb_record : t_sdb_record) return t_sdb_synthesis;
@@ -178,6 +186,7 @@ package wishbone_pkg is
   -- Automatic crossbar mapping functions
   function f_sdb_auto_device(device : t_sdb_device; enable : boolean := true) return t_sdb_record;
   function f_sdb_auto_bridge(bridge : t_sdb_bridge; enable : boolean := true) return t_sdb_record;
+  function f_sdb_auto_msi   (msi    : t_sdb_msi;    enable : boolean := true) return t_sdb_record;
   function f_sdb_auto_layout(records : t_sdb_record_array) return t_sdb_record_array;
   function f_sdb_auto_sdb   (records : t_sdb_record_array) return t_wishbone_address;
   
@@ -349,10 +358,12 @@ package wishbone_pkg is
 
   component sdb_rom is
     generic(
-      g_layout      : t_sdb_record_array;
+      g_slaves      : t_sdb_record_array;
+      g_masters     : t_sdb_record_array;
       g_bus_end     : unsigned(63 downto 0));
     port(
       clk_sys_i : in  std_logic;
+      master_i  : in  std_logic_vector(g_masters'length-1 downto 0);
       slave_i   : in  t_wishbone_slave_in;
       slave_o   : out t_wishbone_slave_out);
   end component;
@@ -1196,6 +1207,36 @@ package body wishbone_pkg is
     return result;
   end;
 
+  function f_sdb_embed_msi(msi : t_sdb_msi; address : t_wishbone_address)
+    return t_sdb_record
+  is
+    variable result : t_sdb_record;
+  begin
+    result(511 downto 456) := (others => '0');
+    result(455)            := msi.wbd_endian;
+    result(454 downto 452) := (others => '0');
+    result(451 downto 448) := msi.wbd_width;
+    result(447 downto 8)   := f_sdb_embed_component(msi.sdb_component, address);
+    result(7 downto 0)     := x"03";    -- msi
+    return result;
+  end;
+
+  function f_sdb_extract_msi(sdb_record : t_sdb_record)
+    return t_sdb_msi
+  is
+    variable result : t_sdb_msi;
+  begin
+    result.wbd_endian    := sdb_record(452);
+    result.wbd_width     := sdb_record(451 downto 448);
+    result.sdb_component := f_sdb_extract_component(sdb_record(447 downto 8));
+
+    assert sdb_record(7 downto 0) = x"03"
+      report "Cannot extract t_sdb_msi from record of type " & integer'image(to_integer(unsigned(sdb_record(7 downto 0)))) & "."
+      severity failure;
+    
+    return result;
+  end;
+
   function f_sdb_embed_integration(integr : t_sdb_integration)
     return t_sdb_record
   is
@@ -1339,6 +1380,20 @@ package body wishbone_pkg is
     end if;
   end f_sdb_auto_bridge;
   
+  function f_sdb_auto_msi(msi : t_sdb_msi; enable : boolean := true)
+    return t_sdb_record
+  is
+    constant c_zero  : t_wishbone_address := (others => '0');
+    variable v_empty : t_sdb_record := (others => '0');
+  begin
+    v_empty(7 downto 0) := (others => '1');
+    if enable then
+      return f_sdb_embed_msi(msi, c_zero);
+    else
+      return v_empty;
+    end if;
+  end f_sdb_auto_msi;
+  
   subtype t_usdb_address is unsigned(63 downto 0);
   type t_usdb_address_array is array(natural range <>) of t_usdb_address;
   
@@ -1843,6 +1898,7 @@ package body wishbone_pkg is
       return ret_v;
    end f_string_fix_len;
 
+   -- do not synthesize
    function f_hot_to_bin(x : std_logic_vector) return natural is
       variable rv : natural;
    begin
-- 
GitLab