Merge pull request #378 from mikey/ux-cleanup

Metavalue cleanup
fix-sdcard
Paul Mackerras 2 years ago committed by GitHub
commit de8fd492c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -115,28 +115,29 @@ package common is


-- Some SPRs are stored in a pair of small RAMs in execute1 -- Some SPRs are stored in a pair of small RAMs in execute1
-- Even half: -- Even half:
subtype ramspr_index is natural range 0 to 7; subtype ramspr_index_range is natural range 0 to 7;
constant RAMSPR_SRR0 : ramspr_index := 0; subtype ramspr_index is unsigned(2 downto 0);
constant RAMSPR_HSRR0 : ramspr_index := 1; constant RAMSPR_SRR0 : ramspr_index := to_unsigned(0,3);
constant RAMSPR_SPRG0 : ramspr_index := 2; constant RAMSPR_HSRR0 : ramspr_index := to_unsigned(1,3);
constant RAMSPR_SPRG2 : ramspr_index := 3; constant RAMSPR_SPRG0 : ramspr_index := to_unsigned(2,3);
constant RAMSPR_HSPRG0 : ramspr_index := 4; constant RAMSPR_SPRG2 : ramspr_index := to_unsigned(3,3);
constant RAMSPR_LR : ramspr_index := 5; -- must equal RAMSPR_CTR constant RAMSPR_HSPRG0 : ramspr_index := to_unsigned(4,3);
constant RAMSPR_TAR : ramspr_index := 6; constant RAMSPR_LR : ramspr_index := to_unsigned(5,3); -- must equal RAMSPR_CTR
constant RAMSPR_TAR : ramspr_index := to_unsigned(6,3);
-- Odd half: -- Odd half:
constant RAMSPR_SRR1 : ramspr_index := 0; constant RAMSPR_SRR1 : ramspr_index := to_unsigned(0,3);
constant RAMSPR_HSRR1 : ramspr_index := 1; constant RAMSPR_HSRR1 : ramspr_index := to_unsigned(1,3);
constant RAMSPR_SPRG1 : ramspr_index := 2; constant RAMSPR_SPRG1 : ramspr_index := to_unsigned(2,3);
constant RAMSPR_SPRG3 : ramspr_index := 3; constant RAMSPR_SPRG3 : ramspr_index := to_unsigned(3,3);
constant RAMSPR_HSPRG1 : ramspr_index := 4; constant RAMSPR_HSPRG1 : ramspr_index := to_unsigned(4,3);
constant RAMSPR_CTR : ramspr_index := 5; -- must equal RAMSPR_LR constant RAMSPR_CTR : ramspr_index := to_unsigned(5,3); -- must equal RAMSPR_LR


type ram_spr_info is record type ram_spr_info is record
index : ramspr_index; index : ramspr_index;
isodd : std_ulogic; isodd : std_ulogic;
valid : std_ulogic; valid : std_ulogic;
end record; end record;
constant ram_spr_info_init: ram_spr_info := (index => 0, others => '0'); constant ram_spr_info_init: ram_spr_info := (index => to_unsigned(0,3), others => '0');


subtype spr_selector is std_ulogic_vector(2 downto 0); subtype spr_selector is std_ulogic_vector(2 downto 0);
type spr_id is record type spr_id is record
@ -366,8 +367,8 @@ package common is
result_sel => "000", sub_select => "000", result_sel => "000", sub_select => "000",
repeat => '0', second => '0', spr_select => spr_id_init, repeat => '0', second => '0', spr_select => spr_id_init,
spr_is_ram => '0', spr_is_ram => '0',
ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0', ramspr_even_rdaddr => (others => '0'), ramspr_odd_rdaddr => (others => '0'), ramspr_rd_odd => '0',
ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0', ramspr_wraddr => (others => '0'), ramspr_write_even => '0', ramspr_write_odd => '0',
dbg_spr_access => '0', dbg_spr_access => '0',
dec_ctr => '0', dec_ctr => '0',
others => (others => '0')); others => (others => '0'));

@ -273,7 +273,7 @@ begin
valid := '1'; valid := '1';
sel := "000"; sel := "000";
isram := '1'; isram := '1';
raddr := 0; raddr := (others => '0');
odd := '0'; odd := '0';
case gspr_index(4 downto 0) is case gspr_index(4 downto 0) is
when 5x"00" => when 5x"00" =>
@ -304,7 +304,7 @@ begin
when others => when others =>
valid := '0'; valid := '0';
end case; end case;
dbg_spr_addr <= isram & sel & std_ulogic_vector(to_unsigned(raddr, 3)) & odd; dbg_spr_addr <= isram & sel & std_ulogic_vector(raddr) & odd;
spr_index_valid <= valid; spr_index_valid <= valid;
end if; end if;
end process; end process;

@ -36,6 +36,8 @@ architecture behaviour of decode1 is


constant illegal_inst : decode_rom_t := constant illegal_inst : decode_rom_t :=
(NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE);
constant x_inst : decode_rom_t :=
(NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, 'X', 'X', 'X', 'X', ZERO, 'X', NONE, 'X', 'X', 'X', 'X', 'X', 'X', NONE, 'X', 'X', NONE);


-- If we have an FPU, then it is used for integer divisions, -- If we have an FPU, then it is used for integer divisions,
-- otherwise a dedicated divider in the ALU is used. -- otherwise a dedicated divider in the ALU is used.
@ -530,7 +532,7 @@ architecture behaviour of decode1 is
function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is
variable ret : ram_spr_info; variable ret : ram_spr_info;
begin begin
ret := (index => 0, isodd => '0', valid => '1'); ret := (index => (others => '0'), isodd => '0', valid => '1');
case sprn is case sprn is
when SPR_LR => when SPR_LR =>
ret.index := RAMSPR_LR; ret.index := RAMSPR_LR;
@ -664,14 +666,23 @@ begin
br_offset := (others => '0'); br_offset := (others => '0');


majorop := unsigned(f_in.insn(31 downto 26)); majorop := unsigned(f_in.insn(31 downto 26));
v.decode := major_decode_rom_array(to_integer(majorop)); if is_X(majorop) then

v.decode := x_inst;
sprn := decode_spr_num(f_in.insn); else
v.spr_info := map_spr(sprn); v.decode := major_decode_rom_array(to_integer(majorop));
v.ram_spr := decode_ram_spr(sprn); end if;


case to_integer(unsigned(majorop)) is if is_X(f_in.insn) then
when 4 => v.spr_info := (sel => "XXX", others => 'X');
v.ram_spr := (index => (others => 'X'), others => 'X');
else
sprn := decode_spr_num(f_in.insn);
v.spr_info := map_spr(sprn);
v.ram_spr := decode_ram_spr(sprn);
end if;

case unsigned(majorop) is
when "000100" => -- 4
-- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*)
minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6); minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6);
vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op))); vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op)));
@ -679,13 +690,17 @@ begin
in3rc := '1'; in3rc := '1';
may_read_rb := '1'; may_read_rb := '1';


when 23 => when "010111" => -- 23
-- rlwnm[.] -- rlwnm[.]
may_read_rb := '1'; may_read_rb := '1';


when 31 => when "011111" => -- 31
-- major opcode 31, lots of things -- major opcode 31, lots of things
v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1)))); if is_X(f_in.insn) then
v.decode := x_inst;
else
v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1))));
end if;
may_read_rb := '1'; may_read_rb := '1';


if std_match(f_in.insn(10 downto 1), "01-1010011") then if std_match(f_in.insn(10 downto 1), "01-1010011") then
@ -705,28 +720,43 @@ begin
end if; end if;
when others => when others =>
end case; end case;
-- FIXME: This is a bit fragile doing this here but sprn depends
-- on f_in.insn
if is_X(f_in.insn) then
vi.override_decode.unit := NONE;
vi.override_unit := 'X';
vi.force_single := 'X';
end if;
end if; end if;
if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then
-- lower half of column 23 has FP loads and stores -- lower half of column 23 has FP loads and stores
fprs := '1'; fprs := '1';
end if; end if;


when 16 => when "010000" => -- 16
-- Predict backward branches as taken, forward as untaken -- Predict backward branches as taken, forward as untaken
v.br_pred := f_in.insn(15); v.br_pred := f_in.insn(15);
br_offset := resize(signed(f_in.insn(15 downto 2)), 24); br_offset := resize(signed(f_in.insn(15 downto 2)), 24);


when 18 => when "010010" => -- 18
-- Unconditional branches are always taken -- Unconditional branches are always taken
v.br_pred := '1'; v.br_pred := '1';
br_offset := signed(f_in.insn(25 downto 2)); br_offset := signed(f_in.insn(25 downto 2));


when 19 => when "010011" => -- 19
vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6)))); if is_X(f_in.insn) then
vi.override := 'X';
else
vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6))));
end if;
op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2); op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2);
v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits))); if is_X(op_19_bits) then
v.decode := x_inst;
else
v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits)));
end if;


when 24 => when "011000" => -- 24
-- ori, special-case the standard NOP -- ori, special-case the standard NOP
if std_match(f_in.insn, "01100000000000000000000000000000") then if std_match(f_in.insn, "01100000000000000000000000000000") then
report "PPC_nop"; report "PPC_nop";
@ -734,23 +764,35 @@ begin
vi.override_decode := nop_instr; vi.override_decode := nop_instr;
end if; end if;


when 30 => when "011110" => -- 30
v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); if is_X(f_in.insn) then
v.decode := x_inst;
else
v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1))));
end if;
may_read_rb := f_in.insn(4); may_read_rb := f_in.insn(4);


when 52 | 53 | 54 | 55 => when "110100" | "110101" | "110110" | "110111" => -- 52, 53, 54, 55
-- stfd[u] and stfs[u] -- stfd[u] and stfs[u]
if HAS_FPU then if HAS_FPU then
fprs := '1'; fprs := '1';
end if; end if;


when 58 => when "111010" => -- 58
v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0)))); if is_X(f_in.insn) then
v.decode := x_inst;
else
v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0))));
end if;


when 59 => when "111011" => -- 59
if HAS_FPU then if HAS_FPU then
-- floating point operations, mostly single-precision -- floating point operations, mostly single-precision
v.decode := decode_op_59_array(to_integer(unsigned(f_in.insn(5 downto 1)))); if is_X(f_in.insn) then
v.decode := x_inst;
else
v.decode := decode_op_59_array(to_integer(unsigned(f_in.insn(5 downto 1))));
end if;
if f_in.insn(5) = '0' and not std_match(f_in.insn(10 downto 1), "11-1001110") then if f_in.insn(5) = '0' and not std_match(f_in.insn(10 downto 1), "11-1001110") then
vi.override := '1'; vi.override := '1';
end if; end if;
@ -760,13 +802,19 @@ begin
may_read_rb := '1'; may_read_rb := '1';
end if; end if;


when 62 => when "111110" => -- 62
v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0)))); if is_X(f_in.insn) then
v.decode := x_inst;
else
v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0))));
end if;


when 63 => when "111111" => -- 63
if HAS_FPU then if HAS_FPU then
-- floating point operations, general and double-precision -- floating point operations, general and double-precision
if f_in.insn(5) = '0' then if is_X(f_in.insn) then
v.decode := x_inst;
elsif f_in.insn(5) = '0' then
v.decode := decode_op_63l_array(to_integer(unsigned(f_in.insn(4 downto 1) & f_in.insn(10 downto 6)))); v.decode := decode_op_63l_array(to_integer(unsigned(f_in.insn(4 downto 1) & f_in.insn(10 downto 6))));
else else
v.decode := decode_op_63h_array(to_integer(unsigned(f_in.insn(4 downto 1)))); v.decode := decode_op_63h_array(to_integer(unsigned(f_in.insn(4 downto 1))));

@ -671,8 +671,8 @@ begin


v.e.dbg_spr_access := dbg_spr_req and not v.read_rspr; v.e.dbg_spr_access := dbg_spr_req and not v.read_rspr;
if v.e.dbg_spr_access = '1' then if v.e.dbg_spr_access = '1' then
v.e.ramspr_even_rdaddr := to_integer(unsigned(dbg_spr_addr(3 downto 1))); v.e.ramspr_even_rdaddr := unsigned(dbg_spr_addr(3 downto 1));
v.e.ramspr_odd_rdaddr := to_integer(unsigned(dbg_spr_addr(3 downto 1))); v.e.ramspr_odd_rdaddr := unsigned(dbg_spr_addr(3 downto 1));
v.e.ramspr_rd_odd := dbg_spr_addr(0); v.e.ramspr_rd_odd := dbg_spr_addr(0);
end if; end if;



@ -147,7 +147,7 @@ architecture behaviour of execute1 is
taken_branch_event => '0', br_mispredict => '0', taken_branch_event => '0', br_mispredict => '0',
msr => 64x"0", msr => 64x"0",
xerc => xerc_init, xerc_valid => '0', xerc => xerc_init, xerc_valid => '0',
ramspr_wraddr => 0, ramspr_odd_data => 64x"0"); ramspr_wraddr => (others => '0'), ramspr_odd_data => 64x"0");


type reg_stage2_type is record type reg_stage2_type is record
e : Execute1ToWritebackType; e : Execute1ToWritebackType;
@ -221,7 +221,7 @@ architecture behaviour of execute1 is
signal irq_valid_log : std_ulogic; signal irq_valid_log : std_ulogic;


-- SPR-related signals -- SPR-related signals
type ramspr_half_t is array(ramspr_index) of std_ulogic_vector(63 downto 0); type ramspr_half_t is array(ramspr_index_range) of std_ulogic_vector(63 downto 0);
signal even_sprs : ramspr_half_t := (others => (others => '0')); signal even_sprs : ramspr_half_t := (others => (others => '0'));
signal odd_sprs : ramspr_half_t := (others => (others => '0')); signal odd_sprs : ramspr_half_t := (others => (others => '0'));
signal ramspr_even : std_ulogic_vector(63 downto 0); signal ramspr_even : std_ulogic_vector(63 downto 0);
@ -510,8 +510,16 @@ begin
variable doit : std_ulogic; variable doit : std_ulogic;
begin begin
-- Read address mux and async RAM reading -- Read address mux and async RAM reading
even_rd_data := even_sprs(e_in.ramspr_even_rdaddr); if is_X(e_in.ramspr_even_rdaddr) then
odd_rd_data := odd_sprs(e_in.ramspr_odd_rdaddr); even_rd_data := (others => 'X');
else
even_rd_data := even_sprs(to_integer(e_in.ramspr_even_rdaddr));
end if;
if is_X(e_in.ramspr_even_rdaddr) then
odd_rd_data := (others => 'X');
else
odd_rd_data := odd_sprs(to_integer(e_in.ramspr_odd_rdaddr));
end if;


-- Write address and data muxes -- Write address and data muxes
doit := ex1.e.valid and not stage2_stall and not flush_in; doit := ex1.e.valid and not stage2_stall and not flush_in;
@ -559,13 +567,15 @@ begin
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if ramspr_even_wr_enab = '1' then if ramspr_even_wr_enab = '1' then
even_sprs(ramspr_wr_addr) <= ramspr_even_wr_data; assert not is_X(ramspr_wr_addr) report "Writing to unknown address" severity FAILURE;
report "writing even spr " & integer'image(ramspr_wr_addr) & " data=" & even_sprs(to_integer(ramspr_wr_addr)) <= ramspr_even_wr_data;
report "writing even spr " & integer'image(to_integer(ramspr_wr_addr)) & " data=" &
to_hstring(ramspr_even_wr_data); to_hstring(ramspr_even_wr_data);
end if; end if;
if ramspr_odd_wr_enab = '1' then if ramspr_odd_wr_enab = '1' then
odd_sprs(ramspr_wr_addr) <= ramspr_odd_wr_data; assert not is_X(ramspr_wr_addr) report "Writing to unknown address" severity FAILURE;
report "writing odd spr " & integer'image(ramspr_wr_addr) & " data=" & odd_sprs(to_integer(ramspr_wr_addr)) <= ramspr_odd_wr_data;
report "writing odd spr " & integer'image(to_integer(ramspr_wr_addr)) & " data=" &
to_hstring(ramspr_odd_wr_data); to_hstring(ramspr_odd_wr_data);
end if; end if;
end if; end if;
@ -1160,12 +1170,12 @@ begin
when OP_MFMSR => when OP_MFMSR =>
when OP_MFSPR => when OP_MFSPR =>
if e_in.spr_is_ram = '1' then if e_in.spr_is_ram = '1' then
if e_in.valid = '1' then if e_in.valid = '1' and not is_X(e_in.insn) then
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(alu_result); "=" & to_hstring(alu_result);
end if; end if;
elsif e_in.spr_select.valid = '1' then elsif e_in.spr_select.valid = '1' then
if e_in.valid = '1' then if e_in.valid = '1' and not is_X(e_in.insn) then
report "MFSPR to slow SPR " & integer'image(decode_spr_num(e_in.insn)); report "MFSPR to slow SPR " & integer'image(decode_spr_num(e_in.insn));
end if; end if;
slow_op := '1'; slow_op := '1';
@ -1182,7 +1192,7 @@ begin
else else
-- mfspr from unimplemented SPRs should be a nop in -- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode -- supervisor mode and a program interrupt for user mode
if e_in.valid = '1' then if e_in.valid = '1' and not is_X(e_in.insn) then
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
" invalid"; " invalid";
end if; end if;
@ -1219,7 +1229,7 @@ begin
end if; end if;
end if; end if;
when OP_MTSPR => when OP_MTSPR =>
if e_in.valid = '1' then if e_in.valid = '1' and not is_X(e_in.insn) then
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) & report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(c_in); "=" & to_hstring(c_in);
end if; end if;
@ -1773,8 +1783,8 @@ begin
variable xer : std_ulogic_vector(63 downto 0); variable xer : std_ulogic_vector(63 downto 0);
begin begin
if sim_dump = '1' then if sim_dump = '1' then
report "LR " & to_hstring(even_sprs(RAMSPR_LR)); report "LR " & to_hstring(even_sprs(to_integer(RAMSPR_LR)));
report "CTR " & to_hstring(odd_sprs(RAMSPR_CTR)); report "CTR " & to_hstring(odd_sprs(to_integer(RAMSPR_CTR)));
sim_dump_done <= '1'; sim_dump_done <= '1';
else else
sim_dump_done <= '0'; sim_dump_done <= '0';

@ -123,15 +123,22 @@ begin
raddr := unsigned(r.nia(BTC_ADDR_BITS + 1 downto 2)) + raddr := unsigned(r.nia(BTC_ADDR_BITS + 1 downto 2)) +
to_unsigned(2, BTC_ADDR_BITS); to_unsigned(2, BTC_ADDR_BITS);
if advance_nia = '1' then if advance_nia = '1' then
btc_rd_data <= btc_memory(to_integer(raddr)); if is_X(raddr) then
btc_rd_valid <= btc_valids(to_integer(raddr)); btc_rd_data <= (others => 'X');
btc_rd_valid <= 'X';
else
btc_rd_data <= btc_memory(to_integer(raddr));
btc_rd_valid <= btc_valids(to_integer(raddr));
end if;
end if; end if;
if btc_wr = '1' then if btc_wr = '1' then
assert not is_X(btc_wr_addr) report "Writing to unknown address" severity FAILURE;
btc_memory(to_integer(unsigned(btc_wr_addr))) <= btc_wr_data; btc_memory(to_integer(unsigned(btc_wr_addr))) <= btc_wr_data;
end if; end if;
if inval_btc = '1' or rst = '1' then if inval_btc = '1' or rst = '1' then
btc_valids <= (others => '0'); btc_valids <= (others => '0');
elsif btc_wr = '1' then elsif btc_wr = '1' then
assert not is_X(btc_wr_addr) report "Writing to unknown address" severity FAILURE;
btc_valids(to_integer(unsigned(btc_wr_addr))) <= '1'; btc_valids(to_integer(unsigned(btc_wr_addr))) <= '1';
end if; end if;
end if; end if;

@ -440,6 +440,10 @@ architecture behaviour of fpu is
variable result: std_ulogic_vector(63 downto 0); variable result: std_ulogic_vector(63 downto 0);
begin begin
result := (others => '0'); result := (others => '0');
if is_X(shift) then
result := (others => 'X');
return result;
end if;
for i in 0 to 63 loop for i in 0 to 63 loop
if i >= shift then if i >= shift then
result(63 - i) := '1'; result(63 - i) := '1';
@ -643,7 +647,11 @@ begin
addrhi := "00"; addrhi := "00";
end if; end if;
addr := addrhi & r.b.mantissa(UNIT_BIT - 1 downto UNIT_BIT - 8); addr := addrhi & r.b.mantissa(UNIT_BIT - 1 downto UNIT_BIT - 8);
inverse_est <= '1' & inverse_table(to_integer(unsigned(addr))); if is_X(addr) then
inverse_est <= (others => 'X');
else
inverse_est <= '1' & inverse_table(to_integer(unsigned(addr)));
end if;
end if; end if;
end process; end process;


@ -841,10 +849,14 @@ begin
new_exp := r.result_exp - r.shift; new_exp := r.result_exp - r.shift;
exp_tiny := '0'; exp_tiny := '0';
exp_huge := '0'; exp_huge := '0';
if new_exp < min_exp then if is_X(new_exp) or is_X(min_exp) then
exp_tiny := 'X';
elsif new_exp < min_exp then
exp_tiny := '1'; exp_tiny := '1';
end if; end if;
if new_exp > max_exp then if is_X(new_exp) or is_X(min_exp) then
exp_huge := 'X';
elsif new_exp > max_exp then
exp_huge := '1'; exp_huge := '1';
end if; end if;


@ -855,7 +867,9 @@ begin
pcmpb_eq := '1'; pcmpb_eq := '1';
end if; end if;
pcmpb_lt := '0'; pcmpb_lt := '0';
if unsigned(r.p(59 downto 4)) < unsigned(r.b.mantissa(UNIT_BIT + 1 downto DP_RBIT)) then if is_X(r.p(59 downto 4)) or is_X(r.b.mantissa(55 downto 0)) then
pcmpb_lt := 'X';
elsif unsigned(r.p(59 downto 4)) < unsigned(r.b.mantissa(UNIT_BIT + 1 downto DP_RBIT)) then
pcmpb_lt := '1'; pcmpb_lt := '1';
end if; end if;
pcmpc_eq := '0'; pcmpc_eq := '0';
@ -863,7 +877,9 @@ begin
pcmpc_eq := '1'; pcmpc_eq := '1';
end if; end if;
pcmpc_lt := '0'; pcmpc_lt := '0';
if unsigned(r.p) < unsigned(r.c.mantissa) then if is_X(r.p) or is_X(r.c.mantissa) then
pcmpc_lt := 'X';
elsif unsigned(r.p) < unsigned(r.c.mantissa) then
pcmpc_lt := '1'; pcmpc_lt := '1';
end if; end if;


@ -3014,7 +3030,9 @@ begin
else else
mshift := r.shift; mshift := r.shift;
end if; end if;
if mshift < to_signed(-64, EXP_BITS) then if is_X(mshift) then
mask := (others => 'X');
elsif mshift < to_signed(-64, EXP_BITS) then
mask := (others => '1'); mask := (others => '1');
elsif mshift >= to_signed(0, EXP_BITS) then elsif mshift >= to_signed(0, EXP_BITS) then
mask := (others => '0'); mask := (others => '0');
@ -3060,7 +3078,9 @@ begin
in_b0 := not in_b0; in_b0 := not in_b0;
end if; end if;
in_b <= in_b0; in_b <= in_b0;
if r.shift >= to_signed(-64, EXP_BITS) and r.shift <= to_signed(63, EXP_BITS) then if is_X(r.shift) then
shift_res := (others => 'X');
elsif r.shift >= to_signed(-64, EXP_BITS) and r.shift <= to_signed(63, EXP_BITS) then
shift_res := shifter_64(r.r(63 downto 1) & (shiftin0 or r.r(0)) & shift_res := shifter_64(r.r(63 downto 1) & (shiftin0 or r.r(0)) &
(shiftin or r.s(55)) & r.s(54 downto 0), (shiftin or r.s(55)) & r.s(54 downto 0),
std_ulogic_vector(r.shift(6 downto 0))); std_ulogic_vector(r.shift(6 downto 0)));
@ -3224,7 +3244,9 @@ begin
v.cr_mask := num_to_fxm(0); v.cr_mask := num_to_fxm(0);
elsif r.is_cmp = '0' then elsif r.is_cmp = '0' then
v.cr_mask := num_to_fxm(1); v.cr_mask := num_to_fxm(1);
else elsif is_X(insn_bf(r.insn)) then
v.cr_mask := (others => 'X');
else
v.cr_mask := num_to_fxm(to_integer(unsigned(insn_bf(r.insn)))); v.cr_mask := num_to_fxm(to_integer(unsigned(insn_bf(r.insn))));
end if; end if;
v.writing_cr := r.is_cmp or r.rc; v.writing_cr := r.is_cmp or r.rc;

@ -162,7 +162,9 @@ package body helpers is


function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
begin begin
if to_integer(unsigned(reg)) = 0 then if is_X(reg) then
return x"XXXXXXXXXXXXXXXX";
elsif to_integer(unsigned(reg)) = 0 then
return x"0000000000000000"; return x"0000000000000000";
else else
return ra; return ra;

@ -207,7 +207,6 @@ architecture rtl of icache is
signal req_is_miss : std_ulogic; signal req_is_miss : std_ulogic;
signal req_raddr : real_addr_t; signal req_raddr : real_addr_t;


signal tlb_req_index : tlb_index_t;
signal real_addr : real_addr_t; signal real_addr : real_addr_t;
signal ra_valid : std_ulogic; signal ra_valid : std_ulogic;
signal priv_fault : std_ulogic; signal priv_fault : std_ulogic;
@ -317,14 +316,15 @@ architecture rtl of icache is
end; end;


-- Simple hash for direct-mapped TLB index -- Simple hash for direct-mapped TLB index
function hash_ea(addr: std_ulogic_vector(63 downto 0)) return tlb_index_t is function hash_ea(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
variable hash : std_ulogic_vector(TLB_BITS - 1 downto 0); variable hash : std_ulogic_vector(TLB_BITS - 1 downto 0);
begin begin
hash := addr(TLB_LG_PGSZ + TLB_BITS - 1 downto TLB_LG_PGSZ) hash := addr(TLB_LG_PGSZ + TLB_BITS - 1 downto TLB_LG_PGSZ)
xor addr(TLB_LG_PGSZ + 2 * TLB_BITS - 1 downto TLB_LG_PGSZ + TLB_BITS) xor addr(TLB_LG_PGSZ + 2 * TLB_BITS - 1 downto TLB_LG_PGSZ + TLB_BITS)
xor addr(TLB_LG_PGSZ + 3 * TLB_BITS - 1 downto TLB_LG_PGSZ + 2 * TLB_BITS); xor addr(TLB_LG_PGSZ + 3 * TLB_BITS - 1 downto TLB_LG_PGSZ + 2 * TLB_BITS);
return to_integer(unsigned(hash)); return hash;
end; end;

begin begin


assert LINE_SIZE mod ROW_SIZE = 0; assert LINE_SIZE mod ROW_SIZE = 0;
@ -435,7 +435,9 @@ begin
process(all) process(all)
begin begin
-- PLRU interface -- PLRU interface
if get_index(r.hit_nia) = i then if is_X(r.hit_nia) then
plru_acc_en <= 'X';
elsif get_index(r.hit_nia) = i then
plru_acc_en <= r.hit_valid; plru_acc_en <= r.hit_valid;
else else
plru_acc_en <= '0'; plru_acc_en <= '0';
@ -450,15 +452,25 @@ begin
itlb_lookup : process(all) itlb_lookup : process(all)
variable pte : tlb_pte_t; variable pte : tlb_pte_t;
variable ttag : tlb_tag_t; variable ttag : tlb_tag_t;
variable tlb_req_index : std_ulogic_vector(TLB_BITS - 1 downto 0);
begin begin
tlb_req_index <= hash_ea(i_in.nia); tlb_req_index := hash_ea(i_in.nia);
pte := itlb_ptes(tlb_req_index); if is_X(tlb_req_index) then
ttag := itlb_tags(tlb_req_index); pte := (others => 'X');
ttag := (others => 'X');
else
pte := itlb_ptes(to_integer(unsigned(tlb_req_index)));
ttag := itlb_tags(to_integer(unsigned(tlb_req_index)));
end if;
if i_in.virt_mode = '1' then if i_in.virt_mode = '1' then
real_addr <= pte(REAL_ADDR_BITS - 1 downto TLB_LG_PGSZ) & real_addr <= pte(REAL_ADDR_BITS - 1 downto TLB_LG_PGSZ) &
i_in.nia(TLB_LG_PGSZ - 1 downto 0); i_in.nia(TLB_LG_PGSZ - 1 downto 0);
if ttag = i_in.nia(63 downto TLB_LG_PGSZ + TLB_BITS) then if ttag = i_in.nia(63 downto TLB_LG_PGSZ + TLB_BITS) then
ra_valid <= itlb_valids(tlb_req_index); if is_X(tlb_req_index) then
ra_valid <= 'X';
else
ra_valid <= itlb_valids(to_integer(unsigned(tlb_req_index)));
end if;
else else
ra_valid <= '0'; ra_valid <= '0';
end if; end if;
@ -476,7 +488,7 @@ begin


-- iTLB update -- iTLB update
itlb_update: process(clk) itlb_update: process(clk)
variable wr_index : tlb_index_t; variable wr_index : std_ulogic_vector(TLB_BITS - 1 downto 0);
begin begin
if rising_edge(clk) then if rising_edge(clk) then
wr_index := hash_ea(m_in.addr); wr_index := hash_ea(m_in.addr);
@ -486,12 +498,14 @@ begin
itlb_valids(i) <= '0'; itlb_valids(i) <= '0';
end loop; end loop;
elsif m_in.tlbie = '1' then elsif m_in.tlbie = '1' then
assert not is_X(wr_index) report "icache index invalid on write" severity FAILURE;
-- clear entry regardless of hit or miss -- clear entry regardless of hit or miss
itlb_valids(wr_index) <= '0'; itlb_valids(to_integer(unsigned(wr_index))) <= '0';
elsif m_in.tlbld = '1' then elsif m_in.tlbld = '1' then
itlb_tags(wr_index) <= m_in.addr(63 downto TLB_LG_PGSZ + TLB_BITS); assert not is_X(wr_index) report "icache index invalid on write" severity FAILURE;
itlb_ptes(wr_index) <= m_in.pte; itlb_tags(to_integer(unsigned(wr_index))) <= m_in.addr(63 downto TLB_LG_PGSZ + TLB_BITS);
itlb_valids(wr_index) <= '1'; itlb_ptes(to_integer(unsigned(wr_index))) <= m_in.pte;
itlb_valids(to_integer(unsigned(wr_index))) <= '1';
end if; end if;
ev.itlb_miss_resolved <= m_in.tlbld and not rst; ev.itlb_miss_resolved <= m_in.tlbld and not rst;
end if; end if;
@ -503,9 +517,11 @@ begin
variable hit_way : way_t; variable hit_way : way_t;
begin begin
-- Extract line, row and tag from request -- Extract line, row and tag from request
req_index <= get_index(i_in.nia); if not is_X(i_in.nia) then
req_row <= get_row(i_in.nia); req_index <= get_index(i_in.nia);
req_tag <= get_tag(real_addr, i_in.big_endian); req_row <= get_row(i_in.nia);
end if;
req_tag <= get_tag(real_addr, i_in.big_endian);


-- Calculate address of beginning of cache row, will be -- Calculate address of beginning of cache row, will be
-- used for cache miss processing if needed -- used for cache miss processing if needed
@ -517,7 +533,11 @@ begin
hit_way := 0; hit_way := 0;
is_hit := '0'; is_hit := '0';
for i in way_t loop for i in way_t loop
if i_in.req = '1' and if is_X(i_in.nia) then
-- FIXME: This is fragile
-- req_index or req_row could be a metavalue
is_hit := 'X';
elsif i_in.req = '1' and
(cache_valids(req_index)(i) = '1' or (cache_valids(req_index)(i) = '1' or
(r.state = WAIT_ACK and (r.state = WAIT_ACK and
req_index = r.store_index and req_index = r.store_index and
@ -556,7 +576,7 @@ begin
-- some of the cache geometry information. -- some of the cache geometry information.
-- --
if r.hit_valid = '1' then if r.hit_valid = '1' then
i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way)); i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way));
else else
i_out.insn <= (others => '0'); i_out.insn <= (others => '0');
end if; end if;
@ -592,6 +612,8 @@ begin
r.hit_valid <= req_is_hit; r.hit_valid <= req_is_hit;
if req_is_hit = '1' then if req_is_hit = '1' then
r.hit_way <= req_hit_way; r.hit_way <= req_hit_way;
-- this is a bit fragile but better than propogating bad values
assert not is_X(i_in.nia) report "metavalue in NIA" severity FAILURE;


report "cache hit nia:" & to_hstring(i_in.nia) & report "cache hit nia:" & to_hstring(i_in.nia) &
" IR:" & std_ulogic'image(i_in.virt_mode) & " IR:" & std_ulogic'image(i_in.virt_mode) &
@ -648,6 +670,9 @@ begin
snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr)); snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr));
snoop_index <= get_index(snoop_addr); snoop_index <= get_index(snoop_addr);
snoop_cache_tags := cache_tags(get_index(snoop_addr)); snoop_cache_tags := cache_tags(get_index(snoop_addr));
if snoop_valid = '1' and is_X(snoop_addr) then
report "metavalue in snoop_addr" severity FAILURE;
end if;
snoop_tag := get_tag(snoop_addr, '0'); snoop_tag := get_tag(snoop_addr, '0');
snoop_hits <= (others => '0'); snoop_hits <= (others => '0');
for i in way_t loop for i in way_t loop

@ -625,8 +625,12 @@ begin
byte_offset := unsigned(r1.addr0(2 downto 0)); byte_offset := unsigned(r1.addr0(2 downto 0));
for i in 0 to 7 loop for i in 0 to 7 loop
k := (to_unsigned(i, 3) - byte_offset) xor r1.req.brev_mask; k := (to_unsigned(i, 3) - byte_offset) xor r1.req.brev_mask;
j := to_integer(k) * 8; if is_X(k) then
store_data(i * 8 + 7 downto i * 8) <= r1.req.store_data(j + 7 downto j); store_data(i * 8 + 7 downto i * 8) <= (others => 'X');
else
j := to_integer(k) * 8;
store_data(i * 8 + 7 downto i * 8) <= r1.req.store_data(j + 7 downto j);
end if;
end loop; end loop;


dbg_spr_rd := dbg_spr_req and not (r1.req.valid and r1.req.read_spr); dbg_spr_rd := dbg_spr_req and not (r1.req.valid and r1.req.read_spr);
@ -757,8 +761,12 @@ begin
-- load data formatting -- load data formatting
-- shift and byte-reverse data bytes -- shift and byte-reverse data bytes
for i in 0 to 7 loop for i in 0 to 7 loop
j := to_integer(r2.byte_index(i)) * 8; if is_X(r2.byte_index(i)) then
data_permuted(i * 8 + 7 downto i * 8) := d_in.data(j + 7 downto j); data_permuted(i * 8 + 7 downto i * 8) := (others => 'X');
else
j := to_integer(r2.byte_index(i)) * 8;
data_permuted(i * 8 + 7 downto i * 8) := d_in.data(j + 7 downto j);
end if;
end loop; end loop;


-- Work out the sign bit for sign extension. -- Work out the sign bit for sign extension.
@ -779,7 +787,9 @@ begin


-- trim and sign-extend -- trim and sign-extend
for i in 0 to 7 loop for i in 0 to 7 loop
if i < to_integer(unsigned(r2.req.length)) then if is_X(r2.req.length) then
trim_ctl(i) := "XX";
elsif i < to_integer(unsigned(r2.req.length)) then
if r2.req.dword_index = '1' then if r2.req.dword_index = '1' then
trim_ctl(i) := '1' & not r2.use_second(i); trim_ctl(i) := '1' & not r2.use_second(i);
else else

@ -163,11 +163,15 @@ begin
begin begin
-- mask_count has to be >= 5 -- mask_count has to be >= 5
m := x"001f"; m := x"001f";
for i in 5 to 15 loop if is_X(r.mask_size) then
if i < to_integer(r.mask_size) then m := (others => 'X');
m(i) := '1'; else
end if; for i in 5 to 15 loop
end loop; if i < to_integer(r.mask_size) then
m(i) := '1';
end if;
end loop;
end if;
mask <= m; mask <= m;
end process; end process;


@ -178,7 +182,9 @@ begin
begin begin
m := (others => '0'); m := (others => '0');
for i in 0 to 43 loop for i in 0 to 43 loop
if i < to_integer(r.shift) then if is_X(r.shift) then
m(i) := 'X';
elsif i < to_integer(r.shift) then
m(i) := '1'; m(i) := '1';
end if; end if;
end loop; end loop;

@ -217,7 +217,11 @@ begin


-- Check for timebase events -- Check for timebase events
tbdiff := p_in.tbbits and not prev_tb; tbdiff := p_in.tbbits and not prev_tb;
tbbit := tbdiff(3 - to_integer(unsigned(mmcr0(MMCR0_TBSEL + 1 downto MMCR0_TBSEL)))); if is_X(mmcr0) then
tbbit := 'X';
else
tbbit := tbdiff(3 - to_integer(unsigned(mmcr0(MMCR0_TBSEL + 1 downto MMCR0_TBSEL))));
end if;
if tbbit = '1' and mmcr0(MMCR0_TBEE) = '1' then if tbbit = '1' and mmcr0(MMCR0_TBEE) = '1' then
event := '1'; event := '1';
end if; end if;

@ -120,9 +120,21 @@ begin
b_addr(5) := '0'; b_addr(5) := '0';
c_addr(5) := '0'; c_addr(5) := '0';
end if; end if;
data_1 <= registers(to_integer(unsigned(a_addr))); if is_X(a_addr) then
data_2 <= registers(to_integer(unsigned(b_addr))); data_1 <= (others => 'X');
data_3 <= registers(to_integer(unsigned(c_addr))); else
data_1 <= registers(to_integer(unsigned(a_addr)));
end if;
if is_X(b_addr) then
data_2 <= (others => 'X');
else
data_2 <= registers(to_integer(unsigned(b_addr)));
end if;
if is_X(c_addr) then
data_3 <= (others => 'X');
else
data_3 <= registers(to_integer(unsigned(c_addr)));
end if;


prev_write_data <= w_in.write_data; prev_write_data <= w_in.write_data;
end if; end if;

@ -34,6 +34,10 @@ architecture behaviour of rotator is
variable ret: std_ulogic_vector(63 downto 0); variable ret: std_ulogic_vector(63 downto 0);
begin begin
ret := (others => '0'); ret := (others => '0');
if is_X(mask_begin) then
ret := (others => 'X');
return ret;
end if;
for i in 0 to 63 loop for i in 0 to 63 loop
if i >= to_integer(unsigned(mask_begin)) then if i >= to_integer(unsigned(mask_begin)) then
ret(63 - i) := '1'; ret(63 - i) := '1';

@ -25,9 +25,6 @@ ${MICROWATT_DIR}/core_tb | sed 's/.*: //' | egrep '^(GPR[0-9]|LR |CTR |XER |CR [


grep -v "^$" ${MICROWATT_DIR}/tests/${TEST}.out | sort | grep -v GPR31 > exp.out grep -v "^$" ${MICROWATT_DIR}/tests/${TEST}.out | sort | grep -v GPR31 > exp.out


cp test.out /tmp
cp exp.out /tmp

diff -q test.out exp.out && echo "$TEST PASS" && exit 0 diff -q test.out exp.out && echo "$TEST PASS" && exit 0


echo "$TEST FAIL ********" echo "$TEST FAIL ********"

@ -3,7 +3,7 @@
# Runs a test and checks the console output against known good output # Runs a test and checks the console output against known good output


if [ $# -ne 1 ]; then if [ $# -ne 1 ]; then
echo "Usage: run_test.sh <test>" echo "Usage: run_test_console.sh <test>"
exit 1 exit 1
fi fi


@ -23,16 +23,21 @@ cd $TMPDIR


cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin cp ${MICROWATT_DIR}/tests/${TEST}.bin main_ram.bin


${MICROWATT_DIR}/core_tb > /dev/null 2> test1.out || true ${MICROWATT_DIR}/core_tb > console.out 2> test1.out || true

# check metavalues aren't increasing
COUNT=$(grep -c 'metavalue' console.out)
EXP=$(cat ${MICROWATT_DIR}/tests/${TEST}.metavalue)
if [[ $COUNT -gt $EXP ]] ; then
echo "$TEST FAIL ******** metavalues increased from $EXP to $COUNT"
exit 1
fi


grep -v "Failed to bind debug socket" test1.out > test.out grep -v "Failed to bind debug socket" test1.out > test.out


cp ${MICROWATT_DIR}/tests/${TEST}.console_out exp.out cp ${MICROWATT_DIR}/tests/${TEST}.console_out exp.out


cp test.out /tmp
cp exp.out /tmp

diff -q test.out exp.out && echo "$TEST PASS" && exit 0 diff -q test.out exp.out && echo "$TEST PASS" && exit 0


echo "$TEST FAIL ********" echo "$TEST FAIL ******** Console output changed"
exit 1 exit 1

Binary file not shown.

@ -21,3 +21,5 @@ test 20:PASS
test 21:PASS test 21:PASS
test 22:PASS test 22:PASS
test 23:PASS test 23:PASS
test 24:PASS
test 25:PASS

@ -9,6 +9,7 @@ for i in sc illegal decrementer xics privileged mmu misc modes pmu reservation t
cd - cd -
cp $i/$i.bin test_$i.bin cp $i/$i.bin test_$i.bin
ln -s test_$i.bin main_ram.bin ln -s test_$i.bin main_ram.bin
../core_tb > /dev/null 2> test_$i.console_out ../core_tb > test_$i.log_out 2> test_$i.console_out
rm main_ram.bin grep -c metavalue test_$i.log_out > test_$i.metavalue
rm main_ram.bin test_$i.log_out
done done

Loading…
Cancel
Save