Merge pull request #452 from paulusmack/master

SPR and interrupt bug fixes, implement LPCR[EVIRT], plus logic/timing improvements
pull/453/head
Paul Mackerras 1 week ago committed by GitHub
commit fabe9a4feb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -249,6 +249,7 @@ package common is
-- LPCR bit numbers
constant LPCR_HAIL : integer := 63 - 37;
constant LPCR_UPRT : integer := 63 - 41;
constant LPCR_EVIRT : integer := 63 - 42;
constant LPCR_HR : integer := 63 - 43;
constant LPCR_LD : integer := 63 - 46;
constant LPCR_HEIC : integer := 63 - 59;
@ -322,6 +323,7 @@ package common is
hdexcr_hyp: aspect_bits_t;
hdexcr_enf: aspect_bits_t;
lpcr_hail: std_ulogic;
lpcr_evirt: std_ulogic;
lpcr_ld: std_ulogic;
lpcr_heic: std_ulogic;
lpcr_lpes: std_ulogic;
@ -333,7 +335,7 @@ package common is
dscr => (others => '0'),
dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init,
hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init,
lpcr_hail => '0', lpcr_ld => '1', lpcr_heic => '0',
lpcr_hail => '0', lpcr_evirt => '0', lpcr_ld => '1', lpcr_heic => '0',
lpcr_lpes => '0', lpcr_hvice => '0',
others => (others => '0'));

@ -420,9 +422,11 @@ package common is

type bypass_data_t is record
tag : instr_tag_t;
reg : gspr_index_t;
data : std_ulogic_vector(63 downto 0);
end record;
constant bypass_data_init : bypass_data_t := (tag => instr_tag_init, data => (others => '0'));
constant bypass_data_init : bypass_data_t :=
(tag => instr_tag_init, reg => (others => '0'), data => (others => '0'));

type cr_bypass_data_t is record
tag : instr_tag_t;

@ -32,9 +32,10 @@ entity control is
gpr_c_read_valid_in : in std_ulogic;
gpr_c_read_in : in gspr_index_t;

execute_next_tag : in instr_tag_t;
execute_next_bypass : in bypass_data_t;
execute2_next_bypass : in bypass_data_t;
writeback_bypass : in bypass_data_t;
execute_next_cr_tag : in instr_tag_t;
execute2_next_tag : in instr_tag_t;
execute2_next_cr_tag : in instr_tag_t;

cr_read_in : in std_ulogic;
@ -166,56 +167,78 @@ begin
begin
tag_a := instr_tag_init;
for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_a_read_in then
if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_a_read_in and gpr_a_read_valid_in = '1' then
tag_a.valid := '1';
tag_a.tag := i;
if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_a)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_a)) or
tag_match(complete_in, tag_a) then
tag_a.valid := '0';
end if;
end loop;
tag_b := instr_tag_init;
for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_b_read_in then
tag_b.valid := '1';
tag_b.tag := i;
end if;
end loop;
tag_c := instr_tag_init;
for i in tag_number_t loop
if tag_regs(i).wr_gpr = '1' and tag_regs(i).recent = '1' and tag_regs(i).reg = gpr_c_read_in then
tag_c.valid := '1';
tag_c.tag := i;
end if;
end loop;

byp_a := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_a) then
if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
execute_next_bypass.reg = gpr_a_read_in then
byp_a(1) := '1';
end if;
if EX1_BYPASS and tag_match(execute2_next_tag, tag_a) then
elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
execute2_next_bypass.reg = gpr_a_read_in then
byp_a(2) := '1';
end if;
if tag_match(complete_in, tag_a) then
elsif writeback_bypass.tag.valid = '1' and
writeback_bypass.reg = gpr_a_read_in then
byp_a(3) := '1';
end if;
byp_a(0) := gpr_a_read_valid_in and (byp_a(1) or byp_a(2) or byp_a(3));

tag_b := instr_tag_init;
for i in tag_number_t loop
if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_b_read_in and gpr_b_read_valid_in = '1' then
tag_b.valid := '1';
tag_b.tag := i;
if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_b)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_b)) or
tag_match(complete_in, tag_b) then
tag_b.valid := '0';
end if;
end if;
end loop;
byp_b := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_b) then
if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
execute_next_bypass.reg = gpr_b_read_in then
byp_b(1) := '1';
end if;
if EX1_BYPASS and tag_match(execute2_next_tag, tag_b) then
elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
execute2_next_bypass.reg = gpr_b_read_in then
byp_b(2) := '1';
end if;
if tag_match(complete_in, tag_b) then
elsif writeback_bypass.tag.valid = '1' and
writeback_bypass.reg = gpr_b_read_in then
byp_b(3) := '1';
end if;
byp_b(0) := gpr_b_read_valid_in and (byp_b(1) or byp_b(2) or byp_b(3));

tag_c := instr_tag_init;
for i in tag_number_t loop
if tag_regs(i).valid = '1' and tag_regs(i).recent = '1' and
tag_regs(i).reg = gpr_c_read_in and gpr_c_read_valid_in = '1' then
tag_c.valid := '1';
tag_c.tag := i;
if (EX1_BYPASS and tag_match(execute_next_bypass.tag, tag_c)) or
(EX1_BYPASS and tag_match(execute2_next_bypass.tag, tag_c)) or
tag_match(complete_in, tag_c) then
tag_c.valid := '0';
end if;
end if;
end loop;
byp_c := "0000";
if EX1_BYPASS and tag_match(execute_next_tag, tag_c) then
if EX1_BYPASS and execute_next_bypass.tag.valid = '1' and
execute_next_bypass.reg = gpr_c_read_in then
byp_c(1) := '1';
end if;
if EX1_BYPASS and tag_match(execute2_next_tag, tag_c) then
elsif EX1_BYPASS and execute2_next_bypass.tag.valid = '1' and
execute2_next_bypass.reg = gpr_c_read_in then
byp_c(2) := '1';
end if;
if tag_match(complete_in, tag_c) then
elsif writeback_bypass.tag.valid = '1' and
writeback_bypass.reg = gpr_c_read_in then
byp_c(3) := '1';
end if;
byp_c(0) := gpr_c_read_valid_in and (byp_c(1) or byp_c(2) or byp_c(3));
@ -224,9 +247,7 @@ begin
gpr_bypass_b <= byp_b;
gpr_bypass_c <= byp_c;

gpr_tag_stall <= (tag_a.valid and gpr_a_read_valid_in and not byp_a(0)) or
(tag_b.valid and gpr_b_read_valid_in and not byp_b(0)) or
(tag_c.valid and gpr_c_read_valid_in and not byp_c(0));
gpr_tag_stall <= tag_a.valid or tag_b.valid or tag_c.valid;

incr_tag := curr_tag;
instr_tag.tag <= curr_tag;

@ -279,10 +279,11 @@ begin
gpr_c_read_valid_in => gpr_c_read_valid,
gpr_c_read_in => gpr_c_read,

execute_next_tag => execute_bypass.tag,
execute_next_bypass => execute_bypass,
execute_next_cr_tag => execute_cr_bypass.tag,
execute2_next_tag => execute2_bypass.tag,
execute2_next_bypass => execute2_bypass,
execute2_next_cr_tag => execute2_cr_bypass.tag,
writeback_bypass => writeback_bypass,

cr_read_in => cr_read_valid,
cr_write_in => cr_write_valid,

@ -106,7 +106,6 @@ architecture behaviour of execute1 is
scv_trap : std_ulogic;
write_tbl : std_ulogic;
write_tbu : std_ulogic;
noop_spr_read : std_ulogic;
send_hmsg : std_ulogic_vector(NCPUS-1 downto 0);
clr_hmsg : std_ulogic;
end record;
@ -426,6 +425,7 @@ architecture behaviour of execute1 is
begin
ret := (others => '0');
ret(LPCR_HAIL) := c.lpcr_hail;
ret(LPCR_EVIRT) := c.lpcr_evirt;
ret(LPCR_UPRT) := '1';
ret(LPCR_HR) := '1';
ret(LPCR_LD) := c.lpcr_ld;
@ -1216,6 +1216,7 @@ begin
variable owait : std_ulogic;
variable srr1 : std_ulogic_vector(63 downto 0);
variable c32, c64 : std_ulogic;
variable sprnum : spr_num_t;
begin
v := actions_type_init;
v.e.write_data := alu_result;
@ -1224,7 +1225,7 @@ begin
v.e.rc := e_in.rc;
v.e.write_cr_data := write_cr_data;
v.e.write_cr_mask := write_cr_mask;
v.e.write_cr_enable := e_in.output_cr;
v.e.write_cr_enable := e_in.output_cr or e_in.rc;
v.e.write_xerc_enable := e_in.output_xer;
v.e.xerc := xerc_in;
v.new_msr := ex1.msr;
@ -1424,17 +1425,20 @@ begin
when OP_DARN =>
when OP_MFMSR =>
when OP_MFSPR =>
sprnum := decode_spr_num(e_in.insn);
if e_in.spr_is_ram = '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(sprnum) &
"=" & to_hstring(alu_result);
end if;
elsif e_in.spr_select.valid = '1' and e_in.spr_select.wonly = '0' 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(sprnum);
end if;
slow_op := '1';
v.se.noop_spr_read := e_in.spr_select.noop;
if e_in.spr_select.noop = '1' then
v.e.write_enable := '0';
end if;
if e_in.spr_select.ispmu = '0' then
case e_in.spr_select.sel is
when SPRSEL_LOGR =>
@ -1449,14 +1453,15 @@ begin
end if;
else
-- mfspr from unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
-- supervisor mode and a program or HEAI interrupt for user mode
-- LPCR[EVIRT] = 1 makes it HEAI in privileged mode
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)) &
" invalid";
report "MFSPR to SPR " & integer'image(sprnum) & " invalid";
end if;
slow_op := '1';
v.se.noop_spr_read := '1';
if ex1.msr(MSR_PR) = '1' then
v.e.write_enable := '0';
if ex1.msr(MSR_PR) = '1' or ctrl.lpcr_evirt = '1' or
sprnum = 0 or sprnum = 4 or sprnum = 5 or sprnum = 6 then
illegal := '1';
end if;
end if;
@ -1502,8 +1507,9 @@ begin
end if;
end if;
when OP_MTSPR =>
sprnum := decode_spr_num(e_in.insn);
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(sprnum) &
"=" & to_hstring(c_in);
end if;
v.se.write_pmuspr := e_in.spr_select.ispmu;
@ -1543,8 +1549,10 @@ begin
end if;
if e_in.spr_select.valid = '0' and e_in.spr_is_ram = '0' then
-- mtspr to unimplemented SPRs should be a nop in
-- supervisor mode and a program interrupt for user mode
if ex1.msr(MSR_PR) = '1' then
-- supervisor mode and a program interrupt or HEAI for user mode
-- LPCR[EVIRT] = 1 makes it HEAI in privileged mode
if ex1.msr(MSR_PR) = '1' or ctrl.lpcr_evirt = '1' or
sprnum = 0 or sprnum = 4 or sprnum = 5 or sprnum = 6 then
illegal := '1';
end if;
end if;
@ -1746,6 +1754,8 @@ begin
if valid_in = '1' then
v.prev_op := e_in.insn_type;
v.prev_prefixed := e_in.prefixed;
v.se.set_heir := actions.se.set_heir;
v.se.write_ic := actions.se.write_ic;
end if;

-- Determine if there is any interrupt to be taken
@ -1935,8 +1945,9 @@ begin
v.fp_exception_next := '0';
end if;

bypass_data.tag.valid <= e_in.write_reg_enable and bypass_valid;
bypass_data.tag.tag <= e_in.instr_tag.tag;
bypass_data.tag.valid <= v.e.write_enable and bypass_valid;
bypass_data.tag.tag <= v.e.instr_tag.tag;
bypass_data.reg <= v.e.write_reg;
bypass_data.data <= alu_result;

bypass_cr_data.tag.valid <= e_in.output_cr and bypass_valid;
@ -2047,16 +2058,22 @@ begin
-- Next insn adder used in a couple of places
next_nia <= std_ulogic_vector(unsigned(ex1.e.last_nia) + 4);

v := ex2;
if stage2_stall = '0' then
v.log_addr_spr := ex2.log_addr_spr;

v.e := ex1.e;
v.se := ex1.se;
v.ext_interrupt := ex1.ext_interrupt;
v.taken_branch_event := ex1.taken_branch_event;
v.br_mispredict := ex1.br_mispredict;
if ex1.advance_nia = '1' then
v.ext_interrupt := ex1.ext_interrupt and not stage2_stall;
v.taken_branch_event := ex1.taken_branch_event and not stage2_stall;
v.br_mispredict := ex1.br_mispredict and not stage2_stall;
if stage2_stall = '1' then
v.e.last_nia := ex2.e.last_nia;
elsif ex1.advance_nia = '1' then
v.e.last_nia := next_nia;
end if;
if stage2_stall = '1' then
v.e.valid := '0';
v.e.interrupt := '0';
v.se := side_effect_init;
end if;

if ex1.se.mult_32s = '1' and ex1.oe = '1' then
@ -2110,9 +2127,7 @@ begin
else
rcresult := countbits_result;
end if;
if ex1.se.noop_spr_read = '1' then
sprres := ex1.spr_write_data;
elsif ex1.res2_sel(0) = '0' then
if ex1.res2_sel(0) = '0' then
sprres := spr_result;
else
sprres := pmu_to_x.spr_val;
@ -2144,14 +2159,11 @@ begin
cr_mask(7) := '1';
end if;

if stage2_stall = '0' then
v.e.write_data := ex_result;
v.e.write_cr_data := cr_res;
v.e.write_cr_mask := cr_mask;
if ex1.e.rc = '1' and ex1.e.write_enable = '1' and v.e.valid = '1' then
v.e.write_cr_enable := '1';
end if;

if stage2_stall = '0' then
if ex1.se.write_msr = '1' then
ctrl_tmp.msr <= ex1.msr;
end if;
@ -2183,6 +2195,7 @@ begin
end if;
if ex1.se.write_lpcr = '1' then
ctrl_tmp.lpcr_hail <= ex1.spr_write_data(LPCR_HAIL);
ctrl_tmp.lpcr_evirt <= ex1.spr_write_data(LPCR_EVIRT);
ctrl_tmp.lpcr_ld <= ex1.spr_write_data(LPCR_LD);
ctrl_tmp.lpcr_heic <= ex1.spr_write_data(LPCR_HEIC);
ctrl_tmp.lpcr_lpes <= ex1.spr_write_data(LPCR_LPES);
@ -2240,13 +2253,15 @@ begin
end if;
end if;

bypass_valid := ex1.e.valid;
if stage2_stall = '1' and ex1.res2_sel(1) = '1' then
bypass_valid := '0';
end if;
-- Don't bypass the result from mfspr to slow SPRs or PMU SPRs,
-- because we don't want to send the value while stalled because it
-- might change, and we don't want bypass_valid to depend on
-- stage2_stall for timing reasons.
bypass_valid := ex1.e.valid and not ex1.res2_sel(1);

bypass2_data.tag.valid <= ex1.e.write_enable and bypass_valid;
bypass2_data.tag.tag <= ex1.e.instr_tag.tag;
bypass2_data.reg <= ex1.e.write_reg;
bypass2_data.data <= ex_result;

bypass2_cr_data.tag.valid <= (ex1.e.write_cr_enable or (ex1.e.rc and ex1.e.write_enable))

@ -1795,6 +1795,49 @@ int fpu_test_26(void)
return trapit(0, test26);
}

/* Check for enabled invalid exception suppressing write of result */
int test27(long arg)
{
unsigned long operands[4];
unsigned long result;

operands[0] = 0xabcd1234ef895670;
operands[1] = 0xbff0000000000000;
operands[2] = 0xef895670abcd1234;
operands[3] = 0;
set_fpscr(FPS_VE);
asm("lfd 3,0(%0); isync; lfd 4,8(%0); lfd 3,16(%0); fsqrt 3,4; stfd 3,0(%1)"
: : "b" (&operands), "b" (&result) : "memory");
if (result != 0xef895670abcd1234) {
if (result == 0x7ffc000000000000)
return 1;
if (result == 0xabcd1234ef895670)
return 2;
print_hex(result, 16, " ");
return 3;
}

set_fpscr(FPS_ZE);
asm("lfd 3,0(%0); isync; lfd 4,8(%0); lfd 5,24(%0); lfd 3,16(%0); fdiv 3,4,5; stfd 3,0(%1)"
: : "b" (&operands), "b" (&result) : "memory");
if (result != 0xef895670abcd1234) {
if (result == 0x7ffc000000000000)
return 4;
if (result == 0xabcd1234ef895670)
return 5;
print_hex(result, 16, " ");
return 6;
}

return 0;
}

int fpu_test_27(void)
{
enable_fp();
return trapit(0, test27);
}

int fail = 0;

void do_test(int num, int (*test)(void))
@ -1846,6 +1889,7 @@ int main(void)
do_test(24, fpu_test_24);
do_test(25, fpu_test_25);
do_test(26, fpu_test_26);
do_test(27, fpu_test_27);

return fail;
}

@ -7,6 +7,8 @@
#define MSR_LE 0x1
#define MSR_DR 0x10
#define MSR_IR 0x20
#define MSR_PR 0x4000
#define MSR_EE 0x8000
#define MSR_SF 0x8000000000000000ul

extern unsigned long callit(unsigned long arg1, unsigned long arg2,
@ -27,6 +29,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs)

#define DSISR 18
#define DAR 19
#define DEC 22
#define SRR0 26
#define SRR1 27
#define PID 48
@ -35,6 +38,7 @@ static inline void do_tlbie(unsigned long rb, unsigned long rs)
#define SPRG3 275
#define HSRR0 314
#define HSRR1 315
#define HEIR 339
#define PTCR 464

static inline unsigned long mfspr(int sprnum)
@ -464,6 +468,39 @@ int mode_test_8(void)
return 0;
}

int test_9_mf(void)
{
mfspr(2);
return 0;
}

int test_9_mt(unsigned long arg)
{
mtspr(2, arg);
return 0;
}

int mode_test_9(void)
{
unsigned long ret, msr;

/*
* Test that mfspr/mtspr to unimplemented SPRs in user mode
* causes an HEAI and sets HEIR.
*/
msr = MSR_SF | MSR_LE | MSR_PR | MSR_EE | MSR_IR | MSR_DR;
mtspr(DEC, 0x7fffffff);
ret = callit(0, 0, (unsigned long) test_9_mf, msr);
if (ret != 0xe40 ||
(mfspr(HEIR) & 0xfc1fffff) != ((31ul << 26) | (2 << 16) | (339 << 1)))
return 1;
ret = callit(0, 0, (unsigned long) test_9_mt, msr);
if (ret != 0xe40 ||
(mfspr(HEIR) & 0xfc1fffff) != ((31ul << 26) | (2 << 16) | (467 << 1)))
return 2;
return 0;
}

int fail = 0;

void do_test(int num, int (*test)(void))
@ -510,6 +547,7 @@ int main(void)
do_test(6, mode_test_6);
do_test(7, mode_test_7);
do_test(8, mode_test_8);
do_test(9, mode_test_9);

return fail;
}

@ -44,3 +44,91 @@ boot_entry:
bctrl
attn // terminate on exit
b .

.globl read_sprn
read_sprn:
nop
nop
mr %r0,%r3
mr %r3,%r4
cmpdi %r0,0
beq 0f
cmpdi %r0,1
beq 1f
cmpdi %r0,4
beq 4f
cmpdi %r0,5
beq 5f
cmpdi %r0,6
beq 6f
mfspr %r3,179
blr
0: mfspr %r3,0
blr
1: mfspr %r3,1
blr
4: mfspr %r3,4
blr
5: mfspr %r3,5
blr
6: mfspr %r3,6
blr

.globl write_sprn
write_sprn:
nop
nop
mr %r0,%r3
li %r3,0
cmpdi %r0,0
beq 0f
cmpdi %r0,1
beq 1f
cmpdi %r0,4
beq 4f
cmpdi %r0,5
beq 5f
cmpdi %r0,6
beq 6f
mtspr 179,%r3
blr
0: mtspr 0,%r3
blr
1: mtspr 1,%r3
blr
4: mtspr 4,%r3
blr
5: mtspr 5,%r3
blr
6: mtspr 6,%r3
blr

#define EXCEPTION(nr) \
.= nr ;\
li %r3,nr ;\
blr

EXCEPTION(0x300)
EXCEPTION(0x380)
EXCEPTION(0x400)
EXCEPTION(0x480)
EXCEPTION(0x500)
EXCEPTION(0x600)
EXCEPTION(0x700)
EXCEPTION(0x800)
EXCEPTION(0x900)
EXCEPTION(0x980)
EXCEPTION(0xa00)
EXCEPTION(0xb00)
EXCEPTION(0xc00)
EXCEPTION(0xd00)
EXCEPTION(0xe00)
EXCEPTION(0xe20)
EXCEPTION(0xe40)
EXCEPTION(0xe60)
EXCEPTION(0xe80)
EXCEPTION(0xf00)
EXCEPTION(0xf20)
EXCEPTION(0xf40)
EXCEPTION(0xf60)
EXCEPTION(0xf80)

@ -8,6 +8,9 @@
#define PASS "PASS\n"
#define FAIL "FAIL\n"

extern long read_sprn(long, long);
extern long write_sprn(long);

// i < 100
void print_test(char *str)
{
@ -44,9 +47,24 @@ void print_test(char *str)
#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)

void print_hex(unsigned long val, int ndigits, const char *str)
{
int i, x;

for (i = (ndigits - 1) * 4; i >= 0; i -= 4) {
x = (val >> i) & 0xf;
if (x >= 10)
putchar(x + 'a' - 10);
else
putchar(x + '0');
}
puts(str);
}

int main(void)
{
unsigned long tmp;
unsigned long tmp, r;
int fail = 0;

console_init();

@ -86,7 +104,47 @@ int main(void)
DO_ONE(SPR_PTCR);
DO_ONE(SPR_PVR);

/*
* Test no-op behaviour of reserved no-op SPRs,
* and of accesses to undefined SPRs in privileged mode.
*/
print_test("reserved no-op");
__asm__ __volatile__("mtspr 811,%0" : : "r" (7838));
__asm__ __volatile__("li %0,%1; mfspr %0,811" : "=r" (tmp) : "i" (2398));
if (tmp == 2398) {
puts(PASS);
} else {
puts(FAIL);
fail = 1;
}

print_test("undefined SPR");
r = write_sprn(179);
tmp = read_sprn(179, 2498);
if (r == 0 && tmp == 2498) {
puts(PASS);
} else {
puts(FAIL);
fail = 1;
}

print_test("read SPR 0/4/5/6");
if (read_sprn(0, 1234) == 0xe40 && read_sprn(2, 1234) == 1234 &&
read_sprn(4, 1234) == 0xe40 && read_sprn(5, 1234) == 0xe40 &&
read_sprn(6, 1234) == 0xe40 &&
write_sprn(0) == 0xe40 && write_sprn(2) == 0 &&
write_sprn(4) == 0xe40 && write_sprn(5) == 0xe40 &&
write_sprn(6) == 0xe40) {
puts(PASS);
} else {
puts(FAIL);
fail = 1;
}

if (!fail)
puts(PASS);
else
puts(FAIL);

return 0;
return fail;
}

Binary file not shown.

@ -24,3 +24,4 @@ test 23:PASS
test 24:PASS
test 25:PASS
test 26:PASS
test 27:PASS

Binary file not shown.

@ -6,3 +6,4 @@ test 05:PASS
test 06:PASS
test 07:PASS
test 08:PASS
test 09:PASS

Binary file not shown.

@ -22,4 +22,7 @@ Test SPR_HSPRG1:PASS
Test SPR_PID:PASS
Test SPR_PTCR:PASS
Test SPR_PVR:PASS
Test reserved no-op:PASS
Test undefined SPR:PASS
Test read SPR 0/4/5/6:PASS
PASS

@ -203,6 +203,7 @@ begin
-- Register write data bypass to decode2
wb_bypass.tag.tag <= complete_out.tag;
wb_bypass.tag.valid <= complete_out.valid and w_out.write_enable;
wb_bypass.reg <= w_out.write_reg;
wb_bypass.data <= w_out.write_data;

end process;

Loading…
Cancel
Save