mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-22 10:21:17 +00:00
commit
f181bf31e2
6
Makefile
6
Makefile
@ -3,7 +3,7 @@ GHDLFLAGS=--std=08 -Psim-unisim
|
||||
CFLAGS=-O2 -Wall
|
||||
|
||||
all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb \
|
||||
rotator_tb
|
||||
rotator_tb countzero_tb
|
||||
|
||||
# XXX
|
||||
# loadstore_tb fetch_tb
|
||||
@ -19,6 +19,7 @@ core_tb.o: common.o wishbone_types.o core.o soc.o sim_jtag.o
|
||||
core.o: common.o wishbone_types.o fetch1.o fetch2.o icache.o decode1.o decode2.o register_file.o cr_file.o execute1.o execute2.o loadstore1.o loadstore2.o multiply.o writeback.o core_debug.o divider.o
|
||||
core_debug.o: common.o
|
||||
countzero.o:
|
||||
countzero_tb.o: common.o glibc_random.o countzero.o
|
||||
cr_file.o: common.o
|
||||
crhelpers.o: common.o
|
||||
decode1.o: common.o decode_types.o
|
||||
@ -95,6 +96,9 @@ divider_tb: divider_tb.o
|
||||
rotator_tb: rotator_tb.o
|
||||
$(GHDL) -e $(GHDLFLAGS) $@
|
||||
|
||||
countzero_tb: countzero_tb.o
|
||||
$(GHDL) -e $(GHDLFLAGS) $@
|
||||
|
||||
simple_ram_tb: simple_ram_tb.o
|
||||
$(GHDL) -e $(GHDLFLAGS) $@
|
||||
|
||||
|
||||
171
countzero.vhdl
171
countzero.vhdl
@ -14,97 +14,100 @@ entity zero_counter is
|
||||
end entity zero_counter;
|
||||
|
||||
architecture behaviour of zero_counter is
|
||||
signal y, z : std_ulogic_vector(3 downto 0);
|
||||
signal v16 : std_ulogic_vector(15 downto 0);
|
||||
signal v4 : std_ulogic_vector(3 downto 0);
|
||||
signal sel : std_ulogic_vector(5 downto 0);
|
||||
|
||||
-- Return the index of the leftmost or rightmost 1 in a set of 4 bits.
|
||||
-- Assumes v is not "0000"; if it is, return (right ? "11" : "00").
|
||||
function encoder(v: std_ulogic_vector(3 downto 0); right: std_ulogic) return std_ulogic_vector is
|
||||
begin
|
||||
if right = '0' then
|
||||
if v(3) = '1' then
|
||||
return "11";
|
||||
elsif v(2) = '1' then
|
||||
return "10";
|
||||
elsif v(1) = '1' then
|
||||
return "01";
|
||||
else
|
||||
return "00";
|
||||
end if;
|
||||
else
|
||||
if v(0) = '1' then
|
||||
return "00";
|
||||
elsif v(1) = '1' then
|
||||
return "01";
|
||||
elsif v(2) = '1' then
|
||||
return "10";
|
||||
else
|
||||
return "11";
|
||||
end if;
|
||||
end if;
|
||||
end;
|
||||
|
||||
begin
|
||||
zerocounter0: process(all)
|
||||
variable l32, r32 : std_ulogic;
|
||||
variable v32 : std_ulogic_vector(31 downto 0);
|
||||
variable v16 : std_ulogic_vector(15 downto 0);
|
||||
variable v8 : std_ulogic_vector(7 downto 0);
|
||||
variable v4 : std_ulogic_vector(3 downto 0);
|
||||
variable sel : std_ulogic_vector(5 downto 0);
|
||||
begin
|
||||
l32 := '0';
|
||||
r32 := '0';
|
||||
v32 := (others => '0');
|
||||
v16 := (others => '0');
|
||||
v8 := (others => '0');
|
||||
v4 := (others => '0');
|
||||
sel := (others => '0');
|
||||
-- Test 4 groups of 16 bits each.
|
||||
-- The top 2 groups are considered to be zero in 32-bit mode.
|
||||
z(0) <= or (rs(15 downto 0));
|
||||
z(1) <= or (rs(31 downto 16));
|
||||
z(2) <= or (rs(47 downto 32));
|
||||
z(3) <= or (rs(63 downto 48));
|
||||
if is_32bit = '0' then
|
||||
sel(5 downto 4) <= encoder(z, count_right);
|
||||
else
|
||||
sel(5) <= '0';
|
||||
if count_right = '0' then
|
||||
sel(4) <= z(1);
|
||||
else
|
||||
sel(4) <= not z(0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
l32 := or (rs(63 downto 32));
|
||||
r32 := or (rs(31 downto 0));
|
||||
if (l32 = '0' or is_32bit = '1') and r32 = '0' then
|
||||
-- Select the leftmost/rightmost non-zero group of 16 bits
|
||||
case sel(5 downto 4) is
|
||||
when "00" =>
|
||||
v16 <= rs(15 downto 0);
|
||||
when "01" =>
|
||||
v16 <= rs(31 downto 16);
|
||||
when "10" =>
|
||||
v16 <= rs(47 downto 32);
|
||||
when others =>
|
||||
v16 <= rs(63 downto 48);
|
||||
end case;
|
||||
|
||||
-- Test 4 groups of 4 bits
|
||||
y(0) <= or (v16(3 downto 0));
|
||||
y(1) <= or (v16(7 downto 4));
|
||||
y(2) <= or (v16(11 downto 8));
|
||||
y(3) <= or (v16(15 downto 12));
|
||||
sel(3 downto 2) <= encoder(y, count_right);
|
||||
|
||||
-- Select the leftmost/rightmost non-zero group of 4 bits
|
||||
case sel(3 downto 2) is
|
||||
when "00" =>
|
||||
v4 <= v16(3 downto 0);
|
||||
when "01" =>
|
||||
v4 <= v16(7 downto 4);
|
||||
when "10" =>
|
||||
v4 <= v16(11 downto 8);
|
||||
when others =>
|
||||
v4 <= v16(15 downto 12);
|
||||
end case;
|
||||
|
||||
sel(1 downto 0) <= encoder(v4, count_right);
|
||||
|
||||
-- sel is now the index of the leftmost/rightmost 1 bit in rs
|
||||
if v4 = "0000" then
|
||||
-- operand is zero, return 32 for 32-bit, else 64
|
||||
result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
|
||||
elsif count_right = '0' then
|
||||
-- return (63 - sel), trimmed to 5 bits in 32-bit mode
|
||||
result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
|
||||
else
|
||||
|
||||
if count_right = '0' then
|
||||
sel(5) := l32 and (not is_32bit);
|
||||
else
|
||||
sel(5) := (not r32) and (not is_32bit);
|
||||
end if;
|
||||
if sel(5) = '1' then
|
||||
v32 := rs(63 downto 32);
|
||||
else
|
||||
v32 := rs(31 downto 0);
|
||||
end if;
|
||||
|
||||
if count_right = '0' then
|
||||
sel(4) := or (v32(31 downto 16));
|
||||
else
|
||||
sel(4) := not (or (v32(15 downto 0)));
|
||||
end if;
|
||||
if sel(4) = '1' then
|
||||
v16 := v32(31 downto 16);
|
||||
else
|
||||
v16 := v32(15 downto 0);
|
||||
end if;
|
||||
|
||||
if count_right = '0' then
|
||||
sel(3) := or (v16(15 downto 8));
|
||||
else
|
||||
sel(3) := not (or (v16(7 downto 0)));
|
||||
end if;
|
||||
if sel(3) = '1' then
|
||||
v8 := v16(15 downto 8);
|
||||
else
|
||||
v8 := v16(7 downto 0);
|
||||
end if;
|
||||
|
||||
if count_right = '0' then
|
||||
sel(2) := or (v8(7 downto 4));
|
||||
else
|
||||
sel(2) := not (or (v8(3 downto 0)));
|
||||
end if;
|
||||
if sel(2) = '1' then
|
||||
v4 := v8(7 downto 4);
|
||||
else
|
||||
v4 := v8(3 downto 0);
|
||||
end if;
|
||||
|
||||
if count_right = '0' then
|
||||
if v4(3) = '1' then
|
||||
sel(1 downto 0) := "11";
|
||||
elsif v4(2) = '1' then
|
||||
sel(1 downto 0) := "10";
|
||||
elsif v4(1) = '1' then
|
||||
sel(1 downto 0) := "01";
|
||||
else
|
||||
sel(1 downto 0) := "00";
|
||||
end if;
|
||||
result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
|
||||
else
|
||||
if v4(0) = '1' then
|
||||
sel(1 downto 0) := "00";
|
||||
elsif v4(1) = '1' then
|
||||
sel(1 downto 0) := "01";
|
||||
elsif v4(2) = '1' then
|
||||
sel(1 downto 0) := "10";
|
||||
else
|
||||
sel(1 downto 0) := "11";
|
||||
end if;
|
||||
result <= x"00000000000000" & "00" & sel;
|
||||
end if;
|
||||
result <= x"00000000000000" & "00" & sel;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
105
countzero_tb.vhdl
Normal file
105
countzero_tb.vhdl
Normal file
@ -0,0 +1,105 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.common.all;
|
||||
use work.glibc_random.all;
|
||||
|
||||
entity countzero_tb is
|
||||
end countzero_tb;
|
||||
|
||||
architecture behave of countzero_tb is
|
||||
constant clk_period: time := 10 ns;
|
||||
signal rs: std_ulogic_vector(63 downto 0);
|
||||
signal is_32bit, count_right: std_ulogic := '0';
|
||||
signal result: std_ulogic_vector(63 downto 0);
|
||||
signal randno: std_ulogic_vector(63 downto 0);
|
||||
|
||||
begin
|
||||
zerocounter_0: entity work.zero_counter
|
||||
port map (
|
||||
rs => rs,
|
||||
result => result,
|
||||
count_right => count_right,
|
||||
is_32bit => is_32bit
|
||||
);
|
||||
|
||||
stim_process: process
|
||||
variable r: std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
-- test with input = 0
|
||||
report "test zero input";
|
||||
rs <= (others => '0');
|
||||
is_32bit <= '0';
|
||||
count_right <= '0';
|
||||
wait for clk_period;
|
||||
assert result = x"0000000000000040"
|
||||
report "bad cntlzd 0 = " & to_hstring(result);
|
||||
count_right <= '1';
|
||||
wait for clk_period;
|
||||
assert result = x"0000000000000040"
|
||||
report "bad cnttzd 0 = " & to_hstring(result);
|
||||
is_32bit <= '1';
|
||||
count_right <= '0';
|
||||
wait for clk_period;
|
||||
assert result = x"0000000000000020"
|
||||
report "bad cntlzw 0 = " & to_hstring(result);
|
||||
count_right <= '1';
|
||||
wait for clk_period;
|
||||
assert result = x"0000000000000020"
|
||||
report "bad cnttzw 0 = " & to_hstring(result);
|
||||
|
||||
report "test cntlzd/w";
|
||||
count_right <= '0';
|
||||
for j in 0 to 100 loop
|
||||
r := pseudorand(64);
|
||||
r(63) := '1';
|
||||
for i in 0 to 63 loop
|
||||
rs <= r;
|
||||
is_32bit <= '0';
|
||||
wait for clk_period;
|
||||
assert to_integer(unsigned(result)) = i
|
||||
report "bad cntlzd " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
rs <= r(31 downto 0) & r(63 downto 32);
|
||||
is_32bit <= '1';
|
||||
wait for clk_period;
|
||||
if i < 32 then
|
||||
assert to_integer(unsigned(result)) = i
|
||||
report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
else
|
||||
assert to_integer(unsigned(result)) = 32
|
||||
report "bad cntlzw " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
end if;
|
||||
r := '0' & r(63 downto 1);
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
report "test cnttzd/w";
|
||||
count_right <= '1';
|
||||
for j in 0 to 100 loop
|
||||
r := pseudorand(64);
|
||||
r(0) := '1';
|
||||
for i in 0 to 63 loop
|
||||
rs <= r;
|
||||
is_32bit <= '0';
|
||||
wait for clk_period;
|
||||
assert to_integer(unsigned(result)) = i
|
||||
report "bad cnttzd " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
is_32bit <= '1';
|
||||
wait for clk_period;
|
||||
if i < 32 then
|
||||
assert to_integer(unsigned(result)) = i
|
||||
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
else
|
||||
assert to_integer(unsigned(result)) = 32
|
||||
report "bad cnttzw " & to_hstring(rs) & " -> " & to_hstring(result);
|
||||
end if;
|
||||
r := r(62 downto 0) & '0';
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
assert false report "end of test" severity failure;
|
||||
wait;
|
||||
end process;
|
||||
end behave;
|
||||
Loading…
x
Reference in New Issue
Block a user