plru: Add a simple PLRU module
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 2 Oct 2019 09:06:53 +0000 (19:06 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 8 Oct 2019 03:46:46 +0000 (14:46 +1100)
Tested in sim only for now

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Makefile
microwatt.core
plru.vhdl [new file with mode: 0644]
plru_tb.vhdl [new file with mode: 0644]

index 7b28b31bf4dce62ede92bb1e3e0e3aa2a90a347f..c95c04a7a3de2fdaa368ef2c247f9def936636bd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,8 @@ writeback.o: common.o
 dmi_dtm_tb.o: dmi_dtm_xilinx.o wishbone_debug_master.o
 dmi_dtm_xilinx.o: wishbone_types.o sim-unisim/unisim_vcomponents.o
 wishbone_debug_master.o: wishbone_types.o
+plru.o:
+plru_tb.o: plru.o
 
 UNISIM_BITS = sim-unisim/unisim_vcomponents.vhdl sim-unisim/BSCANE2.vhdl sim-unisim/BUFG.vhdl
 sim-unisim/unisim_vcomponents.o: $(UNISIM_BITS)
@@ -75,6 +77,9 @@ fetch_tb: fetch_tb.o
 icache_tb: icache_tb.o
        $(GHDL) -e $(GHDLFLAGS) -Wl,simple_ram_behavioural_helpers_c.o $@
 
+plru_tb: plru_tb.o
+       $(GHDL) -e $(GHDLFLAGS) $@
+
 loadstore_tb: loadstore_tb.o
        $(GHDL) -e $(GHDLFLAGS) $@
 
index 6143f504af084b300b40f6779d5d1761e2416f65..94d909ecdfcfe27631b5bbe2a86f31cc4beb6c44 100644 (file)
@@ -29,6 +29,7 @@ filesets:
       - insn_helpers.vhdl
       - core.vhdl
       - icache.vhdl
+      - plru.vhdl
       - core_debug.vhdl
     file_type : vhdlSource-2008
 
diff --git a/plru.vhdl b/plru.vhdl
new file mode 100644 (file)
index 0000000..936f85e
--- /dev/null
+++ b/plru.vhdl
@@ -0,0 +1,77 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use ieee.math_real.all;
+
+entity plru is
+    generic (
+       BITS : positive := 2
+       )
+       ;
+    port (
+       clk    : in std_ulogic;
+       rst    : in std_ulogic;
+
+       acc    : in std_ulogic_vector(BITS-1 downto 0);
+       acc_en : in std_ulogic;
+       lru    : out std_ulogic_vector(BITS-1 downto 0)
+       );
+end entity plru;
+
+architecture rtl of plru is
+    constant count : positive := 2 ** BITS - 1;
+    subtype node_t is integer range 0 to count;
+    type tree_t is array(node_t) of std_ulogic;
+
+    signal tree: tree_t;
+begin
+
+    -- XXX Check if we can turn that into a little ROM instead that
+    -- takes the tree bit vector and returns the LRU. See if it's better
+    -- in term of FPGA resouces usage...
+    get_lru: process(all)
+       variable node : node_t;
+    begin
+       node := 0;
+       for i in 0 to BITS-1 loop
+           report "GET: i:" & integer'image(i) & " node:" & integer'image(node) & " val:" & std_ulogic'image(tree(node));
+           lru(BITS-1-i) <= tree(node);
+           if i /= BITS-1 then
+               node := node * 2;
+               if tree(node) = '1' then
+                   node := node + 2;
+               else
+                   node := node + 1;
+               end if;
+           end if;
+       end loop;
+    end process;
+
+    update_lru: process(clk)
+       variable node : node_t;
+       variable abit : std_ulogic;
+    begin
+       if rising_edge(clk) then
+           if rst = '1' then
+               tree <= (others => '0');
+           elsif acc_en = '1' then
+               node := 0;
+               for i in 0 to BITS-1 loop
+                   abit := acc(BITS-1-i);
+                   tree(node) <= not abit;
+                   report "UPD: i:" & integer'image(i) & " node:" & integer'image(node) & " val" & std_ulogic'image(not abit);
+                   if i /= BITS-1 then
+                       node := node * 2;
+                       if abit = '1' then
+                           node := node + 2;
+                       else
+                           node := node + 1;
+                       end if;
+                   end if;
+               end loop;
+           end if;         
+       end if;
+    end process;
+end;
+
+
diff --git a/plru_tb.vhdl b/plru_tb.vhdl
new file mode 100644 (file)
index 0000000..18512e4
--- /dev/null
@@ -0,0 +1,109 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+library work;
+use work.common.all;
+use work.wishbone_types.all;
+
+entity plru_tb is
+end plru_tb;
+
+architecture behave of plru_tb is
+    signal clk          : std_ulogic;
+    signal rst          : std_ulogic;
+
+    constant clk_period : time := 10 ns;
+
+    signal acc_en : std_ulogic;
+    signal acc : std_ulogic_vector(2 downto 0);
+    signal lru : std_ulogic_vector(2 downto 0);
+
+begin
+    plru0: entity work.plru
+        generic map(
+            BITS => 3
+            )
+        port map(
+            clk => clk,
+            rst => rst,
+
+           acc => acc,
+           acc_en => acc_en,
+           lru => lru
+            );
+
+    clk_process: process
+    begin
+        clk <= '0';
+        wait for clk_period/2;
+        clk <= '1';
+        wait for clk_period/2;
+    end process;
+
+    rst_process: process
+    begin
+        rst <= '1';
+        wait for 2*clk_period;
+        rst <= '0';
+        wait;
+    end process;
+
+    stim: process
+    begin
+       wait for 4*clk_period;
+
+       report "accessing 1:";
+       acc <= "001";
+       acc_en <= '1';
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 2:";
+       acc <= "010";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 7:";
+       acc <= "111";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 4:";
+       acc <= "100";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 3:";
+       acc <= "011";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 5:";
+       acc <= "101";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 3:";
+       acc <= "011";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 5:";
+       acc <= "101";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 6:";
+       acc <= "110";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+       report "accessing 0:";
+       acc <= "000";
+       wait for clk_period;
+       report "lru:" & to_hstring(lru);
+
+        assert false report "end of test" severity failure;
+        wait;
+    end process;
+end;