From 004eb074c904c2aec489cf55610c00b4bf8aeab9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 2 Oct 2019 19:06:53 +1000 Subject: [PATCH] plru: Add a simple PLRU module Tested in sim only for now Signed-off-by: Benjamin Herrenschmidt --- Makefile | 5 +++ microwatt.core | 1 + plru.vhdl | 77 ++++++++++++++++++++++++++++++++++ plru_tb.vhdl | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 plru.vhdl create mode 100644 plru_tb.vhdl diff --git a/Makefile b/Makefile index 7b28b31..c95c04a 100644 --- 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) $@ diff --git a/microwatt.core b/microwatt.core index 6143f50..94d909e 100644 --- a/microwatt.core +++ b/microwatt.core @@ -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 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 index 0000000..18512e4 --- /dev/null +++ b/plru_tb.vhdl @@ -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;