Merge pull request #99 from paulusmack/logical

Logical
pull/103/head
Anton Blanchard 5 years ago committed by GitHub
commit f181bf31e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,7 +3,7 @@ GHDLFLAGS=--std=08 -Psim-unisim
CFLAGS=-O2 -Wall CFLAGS=-O2 -Wall


all = core_tb simple_ram_behavioural_tb soc_reset_tb icache_tb multiply_tb dmi_dtm_tb divider_tb \ 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 # XXX
# loadstore_tb fetch_tb # 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.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 core_debug.o: common.o
countzero.o: countzero.o:
countzero_tb.o: common.o glibc_random.o countzero.o
cr_file.o: common.o cr_file.o: common.o
crhelpers.o: common.o crhelpers.o: common.o
decode1.o: common.o decode_types.o decode1.o: common.o decode_types.o
@ -95,6 +96,9 @@ divider_tb: divider_tb.o
rotator_tb: rotator_tb.o rotator_tb: rotator_tb.o
$(GHDL) -e $(GHDLFLAGS) $@ $(GHDL) -e $(GHDLFLAGS) $@


countzero_tb: countzero_tb.o
$(GHDL) -e $(GHDLFLAGS) $@

simple_ram_tb: simple_ram_tb.o simple_ram_tb: simple_ram_tb.o
$(GHDL) -e $(GHDLFLAGS) $@ $(GHDL) -e $(GHDLFLAGS) $@



@ -14,97 +14,100 @@ entity zero_counter is
end entity zero_counter; end entity zero_counter;


architecture behaviour of zero_counter is architecture behaviour of zero_counter is
begin signal y, z : std_ulogic_vector(3 downto 0);
zerocounter0: process(all) signal v16 : std_ulogic_vector(15 downto 0);
variable l32, r32 : std_ulogic; signal v4 : std_ulogic_vector(3 downto 0);
variable v32 : std_ulogic_vector(31 downto 0); signal sel : std_ulogic_vector(5 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');

l32 := or (rs(63 downto 32));
r32 := or (rs(31 downto 0));
if (l32 = '0' or is_32bit = '1') and r32 = '0' then
-- operand is zero, return 32 for 32-bit, else 64
result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
else


if count_right = '0' then -- Return the index of the leftmost or rightmost 1 in a set of 4 bits.
sel(5) := l32 and (not is_32bit); -- 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 else
sel(5) := (not r32) and (not is_32bit); return "00";
end if; end if;
if sel(5) = '1' then else
v32 := rs(63 downto 32); if v(0) = '1' then
return "00";
elsif v(1) = '1' then
return "01";
elsif v(2) = '1' then
return "10";
else else
v32 := rs(31 downto 0); return "11";
end if; end if;
end if;
end;


if count_right = '0' then begin
sel(4) := or (v32(31 downto 16)); zerocounter0: process(all)
else begin
sel(4) := not (or (v32(15 downto 0))); -- Test 4 groups of 16 bits each.
end if; -- The top 2 groups are considered to be zero in 32-bit mode.
if sel(4) = '1' then z(0) <= or (rs(15 downto 0));
v16 := v32(31 downto 16); z(1) <= or (rs(31 downto 16));
else z(2) <= or (rs(47 downto 32));
v16 := v32(15 downto 0); z(3) <= or (rs(63 downto 48));
end if; 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;


if count_right = '0' then -- Select the leftmost/rightmost non-zero group of 16 bits
sel(3) := or (v16(15 downto 8)); case sel(5 downto 4) is
else when "00" =>
sel(3) := not (or (v16(7 downto 0))); v16 <= rs(15 downto 0);
end if; when "01" =>
if sel(3) = '1' then v16 <= rs(31 downto 16);
v8 := v16(15 downto 8); when "10" =>
else v16 <= rs(47 downto 32);
v8 := v16(7 downto 0); when others =>
end if; v16 <= rs(63 downto 48);
end case;


if count_right = '0' then -- Test 4 groups of 4 bits
sel(2) := or (v8(7 downto 4)); y(0) <= or (v16(3 downto 0));
else y(1) <= or (v16(7 downto 4));
sel(2) := not (or (v8(3 downto 0))); y(2) <= or (v16(11 downto 8));
end if; y(3) <= or (v16(15 downto 12));
if sel(2) = '1' then sel(3 downto 2) <= encoder(y, count_right);
v4 := v8(7 downto 4);
else
v4 := v8(3 downto 0);
end if;


if count_right = '0' then -- Select the leftmost/rightmost non-zero group of 4 bits
if v4(3) = '1' then case sel(3 downto 2) is
sel(1 downto 0) := "11"; when "00" =>
elsif v4(2) = '1' then v4 <= v16(3 downto 0);
sel(1 downto 0) := "10"; when "01" =>
elsif v4(1) = '1' then v4 <= v16(7 downto 4);
sel(1 downto 0) := "01"; when "10" =>
else v4 <= v16(11 downto 8);
sel(1 downto 0) := "00"; when others =>
end if; v4 <= v16(15 downto 12);
result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0); end case;
else
if v4(0) = '1' then sel(1 downto 0) <= encoder(v4, count_right);
sel(1 downto 0) := "00";
elsif v4(1) = '1' then -- sel is now the index of the leftmost/rightmost 1 bit in rs
sel(1 downto 0) := "01"; if v4 = "0000" then
elsif v4(2) = '1' then -- operand is zero, return 32 for 32-bit, else 64
sel(1 downto 0) := "10"; result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
else elsif count_right = '0' then
sel(1 downto 0) := "11"; -- return (63 - sel), trimmed to 5 bits in 32-bit mode
end if; result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
result <= x"00000000000000" & "00" & sel; else
end if; result <= x"00000000000000" & "00" & sel;
end if; end if;


end process; end process;

@ -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…
Cancel
Save