From 91c42e0f27dfc5e72bd09a7dfd3db8dfcd6b9f2d Mon Sep 17 00:00:00 2001
From: "Wesley W. Terpstra" <w.terpstra@gsi.de>
Date: Thu, 21 Apr 2016 17:18:36 +0200
Subject: [PATCH] sdb: modify ROM handle active master flag

---
 modules/wishbone/wb_crossbar/sdb_rom.vhd      | 115 ++++++++++--------
 .../wishbone/wb_crossbar/xwb_sdb_crossbar.vhd |  13 +-
 modules/wishbone/wishbone_pkg.vhd             |  10 +-
 3 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/modules/wishbone/wb_crossbar/sdb_rom.vhd b/modules/wishbone/wb_crossbar/sdb_rom.vhd
index 37acd3b1..d0b65b11 100644
--- a/modules/wishbone/wb_crossbar/sdb_rom.vhd
+++ b/modules/wishbone/wb_crossbar/sdb_rom.vhd
@@ -5,28 +5,72 @@ use work.wishbone_pkg.all;
 
 entity sdb_rom is
   generic(
-    g_slaves      : t_sdb_record_array;
-    g_masters     : t_sdb_record_array;
-    g_bus_end     : unsigned(63 downto 0));
+    g_layout  : t_sdb_record_array;
+    g_masters : natural;
+    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);
+    clk_sys_i  : in  std_logic;
+    master_i   : in  std_logic_vector(g_masters-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_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;
+  alias c_layout : t_sdb_record_array(g_layout'length downto 1) is g_layout;
 
   -- The ROM must describe all slaves, the crossbar itself and the optional information records
-  constant c_used_entries   : natural := c_slaves'high + 1;
+  constant c_used_entries   : natural := c_layout'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;
   constant c_rom_depth      : natural := f_ceil_log2(c_rom_words);
   constant c_rom_lowbits    : natural := f_ceil_log2(c_wishbone_data_width / 8);
   
+  -- Index of the MSI entry in SDB
+  type t_nat_array is array(g_masters-1 downto 0) of natural;
+  function f_master_positions return t_nat_array is
+    variable result : t_nat_array;
+    variable master : natural := 0;
+  begin
+    for rec in c_layout'low to c_layout'high loop
+      if c_layout(rec)(7 downto 0) = x"03" then
+        assert master < g_masters
+        report "Too many msi records found"
+        severity failure;
+        
+        result(master) := rec;
+        master := master + 1;
+      end if;
+    end loop;
+    
+    if master = 0 then
+      result := (others => g_masters);
+    else
+      assert master = g_masters
+      report "Insufficient msi records found"
+      severity failure;
+    end if;
+    return result;
+  end f_master_positions;
+  
+  constant c_master_positions : t_nat_array := f_master_positions;
+  constant c_msi              : boolean     := c_master_positions(0) /= g_masters;
+  
+  function f_msi_flag_index(y : std_logic_vector) return std_logic_vector is
+    variable offset : unsigned(c_rom_depth-1 downto 0) := (others => '0');
+    variable result : std_logic_vector(c_rom_depth-1 downto 0) := (others => '0');
+  begin
+    for i in c_master_positions'range loop
+      if c_msi then
+        offset := to_unsigned(c_master_positions(i)*16, offset'length);
+      end if;
+      for b in result'range loop
+        result(b) := result(b) or (offset(b) and y(i));
+      end loop;
+    end loop;
+    return result;
+  end f_msi_flag_index;
+  
   type t_rom is array(c_rom_words-1 downto 0) of t_wishbone_data;
 
   function f_build_rom
@@ -45,17 +89,10 @@ 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
-    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_component.product.device_id := x"e6a542c9";
+    sdb_component.product.version   := x"00000003";
+    sdb_component.product.date      := x"20120511";
+    sdb_component.product.name      := "WB4-Crossbar-GSI   ";
     sdb_device(447 downto   8) := f_sdb_embed_component(sdb_component, (others => '0'));
     
     for i in 0 to c_sdb_words-1 loop
@@ -63,46 +100,18 @@ architecture rtl of sdb_rom is
         sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
     end loop;
     
-    for master in c_masters'range loop
-      sdb_device(511 downto 0) := c_masters(master);
+    for idx in c_layout'range loop
+      sdb_device(511 downto 0) := c_layout(idx);
       
       for i in 0 to c_sdb_words-1 loop
-        res((master+1)*c_sdb_words-1-i) := 
+        res((idx+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) := 
-          sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
-      end loop;
-    end loop;
-
     return res;
   end 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);
@@ -119,7 +128,7 @@ begin
   slave_o.int   <= '0'; -- Tom sucks! This should not be here.
 
   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';
+  s_flag(s_flag'high) <= '1' when adr_reg = sel_reg and c_msi else '0';
   slave_o.dat <= s_rom or s_flag;
   
   slave_clk : process(clk_sys_i)
diff --git a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
index fd7ceb61..c237a721 100644
--- a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
@@ -214,11 +214,9 @@ architecture rtl of xwb_sdb_crossbar is
   constant c_mask : t_wishbone_address_array(g_num_slaves downto 0) :=
     c_sdb_mask & c_addresses.bus_mask;
   
-  -- !!! to remove
-  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);
+  signal sdb_sel    : std_logic_vector(g_num_masters-1 downto 0);
 
 begin
 
@@ -228,12 +226,12 @@ begin
   
   rom : sdb_rom
     generic map(
-      g_slaves   => c_layout,
-      g_masters  => c_null,
+      g_layout   => c_layout,
+      g_masters  => g_num_masters,
       g_bus_end  => c_sizes.bus_last)
     port map(
       clk_sys_i => clk_sys_i,
-      master_i  => (others => '0'),
+      master_i  => sdb_sel,
       slave_i   => master_o_1(g_num_slaves),
       slave_o   => master_i_1(g_num_slaves));
   
@@ -250,6 +248,7 @@ begin
       slave_i       => slave_i, 
       slave_o       => slave_o, 
       master_i      => master_i_1, 
-      master_o      => master_o_1);
+      master_o      => master_o_1,
+      sdb_sel_o     => sdb_sel);
 
 end rtl;
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index 35564c73..ea085890 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -361,12 +361,12 @@ package wishbone_pkg is
 
   component sdb_rom is
     generic(
-      g_slaves      : t_sdb_record_array;
-      g_masters     : t_sdb_record_array;
-      g_bus_end     : unsigned(63 downto 0));
+      g_layout  : t_sdb_record_array;
+      g_masters : natural;
+      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);
+      master_i  : in  std_logic_vector(g_masters-1 downto 0);
       slave_i   : in  t_wishbone_slave_in;
       slave_o   : out t_wishbone_slave_out);
   end component;
@@ -1389,7 +1389,7 @@ package body wishbone_pkg 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');
+    v_empty(7 downto 0) := (others => '1'); -- !!! fuck
     if enable then
       return f_sdb_embed_msi(msi, c_zero);
     else
-- 
GitLab