Commit 4bb81b94 authored by Roberto Hexsel's avatar Roberto Hexsel

fixed: VHDL for reading cop0 registers was not combinational; cleared...

fixed: VHDL for reading cop0 registers was not combinational; cleared interrupt hazards on all cop0 events
parent 8ec97abe
......@@ -308,10 +308,9 @@ _excp_0180ret:
.ent _excp_0200
_excp_0200:
mfc0 $k0, c0_cause
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
mfc0 $k1, c0_status
andi $k0, $k0, M_CauseIM # Keep only IP bits from Cause
and $k0, $k0, $k1 # and mask with IM bits
srl $k0, $k0, 10 # keep only 3 MS bits of IP (irq7..5)
lui $k1, %hi(handlers_tbl) # plus displacement in j-table of 8 bytes
ori $k1, $k1, %lo(handlers_tbl)
......@@ -322,7 +321,7 @@ _excp_0200:
## the code for each handler must contain an exception return
## sequence shown below in excp_0200ret.
## such as the sequence shown below, in excp_0200ret.
handlers_tbl:
j dismiss # no request: 000
nop
......
......@@ -191,7 +191,7 @@ _mtc0: mtc0 $6, c0_status # this MUST NOT be cancelled by the interrupt
nop
nop
lw $7, 0(COUNT) # was the IRQ taken? If so,
la $4, (numCy+4) # value in count must be 4 (b31b30=00)
la $4, (numCy+4) # value in count must be 0xc000.0004
nop
nop
bne $4, $7, _err2 # error if COUNTER != 4
......
the quick brown fox jumps over the lazy dog
......@@ -341,7 +341,7 @@ architecture rtl of core is
signal selB,EX_selB: std_logic;
signal oper,EX_oper: t_alu_fun;
signal EX_postn, shamt,EX_shamt: reg5;
signal regs_A,EX_A,MM_A,WB_A, regs_B,EX_B,MM_B:reg32;
signal regs_A,EX_A,MM_A,WB_A, regs_B,EX_B,MM_B: reg32;
signal displ32,EX_displ32: reg32;
signal result,MM_result,WB_result,WB_C, EX_addr,MM_addr: reg32;
signal pc_p8,EX_pc_p8,MM_pc_p8,WB_pc_p8 : reg32;
......@@ -1325,8 +1325,8 @@ begin
i_A := EX_A;
end if;
alu_inp_A <= i_A;
-- assert false report -- DEBUG
-- "FWD_A: alu_A="&SLV32HEX(alu_inp_A)&" alu_B="&SLV32HEX(alu_fwd_B);
assert TRUE report -- DEBUG
"FWD_A: alu_A="&SLV32HEX(alu_inp_A)&" alu_B="&SLV32HEX(alu_fwd_B);
FORWARD_B:
......@@ -1344,8 +1344,8 @@ begin
i_B := EX_B;
end if;
alu_fwd_B <= i_B;
-- assert false report -- DEBUG
-- "FWD_B: alu_A="&SLV32HEX(alu_inp_A)&" alu_B="&SLV32HEX(alu_fwd_B);
assert TRUE report -- DEBUG
"FWD_B: alu_A="&SLV32HEX(alu_inp_A)&" alu_B="&SLV32HEX(alu_fwd_B);
end process EX_FORWARDING_ALU;
alu_inp_B <= alu_fwd_B when (EX_selB = '0') else EX_displ32;
......@@ -1813,14 +1813,19 @@ begin
-- Also, delay the interrupt requests to avoid hazards while
-- the interrupt-enable bit is changed in the STATUS register.
dly_i0 <= '1' when ( (EX_exception = exERET) or -- forward progress
(EX_exception = exEI) or -- interrupt hazard
(EX_exception = exDI) or -- interrupt hazard
(EX_exception = exEHB) or -- interrupt hazard
(EX_exception = exMTC0 -- interrupt hazard
and EX_cop0_reg = cop0reg_STATUS) ) else
'0';
-- dly_i0 <= '1' when ( (EX_exception = exERET) or -- forward progress
-- (EX_exception = exEI) or -- interrupt hazard
-- (EX_exception = exDI) or -- interrupt hazard
-- (EX_exception = exEHB) or -- interrupt hazard
-- (EX_exception = exMTC0 -- interrupt hazard
-- and EX_cop0_reg = cop0reg_STATUS) or
-- (EX_exception = exMFC0 -- interrupt hazard
-- and EX_cop0_reg = cop0reg_STATUS) ) else
-- '0';
dly_i0 <= '1' when ( EX_exception /= exNOP ) else '0';
U_DLY_INT1: FFD port map (clk, rst, '1',dly_i0, dly_i1);
U_DLY_INT2: FFD port map (clk, rst, '1',dly_i1, dly_i2);
dly_interr <= dly_i0 or dly_i1 or dly_i2;
......@@ -1869,18 +1874,16 @@ begin
EX_is_exception, is_exception);
-- exception_dec <= exception_type'pos(is_exception); -- debugging only
-- STATUS -- pg 79 -- cop0_12 --------------------
COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS:
process (MM_a_rt, is_exception, cop0_inp,
MM_cop0_reg, MM_cop0_sel,
RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot,
rom_stall,ram_stall, MM_is_mfc0,
INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED,
EntryHi, COUNT, COMPARE, STATUS, CAUSE, EPC, BadVAddr)
rom_stall,ram_stall, STATUS)
variable newSTATUS, i_COP0_rd : reg32;
variable newSTATUS : reg32;
variable i_update,i_epc_update,i_stall : std_logic;
variable i_nullify: boolean;
variable i_update_r : reg5;
......@@ -1893,7 +1896,6 @@ begin
i_epc_source := EPC_src_PC;
i_update := '0';
i_update_r := b"00000";
i_COP0_rd := x"00000000";
i_stall := '0';
i_nullify := FALSE;
......@@ -1937,42 +1939,17 @@ begin
newSTATUS(STATUS_IE) := '1';
i_update := '1';
i_update_r := cop0reg_STATUS;
i_COP0_rd := STATUS;
i_stall := '0';
when exDI => -- disable interrupts
newSTATUS(STATUS_IE) := '0';
i_update := '1';
i_update_r := cop0reg_STATUS;
i_COP0_rd := STATUS;
i_stall := '0';
when exMFC0 => -- move from COP-0
i_stall := '0';
case MM_cop0_reg is
when cop0reg_Index => i_COP0_rd := INDEX;
when cop0reg_Random => i_COP0_rd := RANDOM;
when cop0reg_EntryLo0 => i_COP0_rd := EntryLo0;
when cop0reg_EntryLo1 => i_COP0_rd := EntryLo1;
when cop0reg_Context => i_COP0_rd := CONTEXT;
when cop0reg_PageMask => i_COP0_rd := PAGEMASK;
when cop0reg_Wired => i_COP0_rd := WIRED;
when cop0reg_EntryHi => i_COP0_rd := EntryHi;
when cop0reg_COUNT => i_COP0_rd := COUNT;
when cop0reg_COMPARE => i_COP0_rd := COMPARE;
when cop0reg_STATUS => i_COP0_rd := STATUS;
when cop0reg_CAUSE => i_COP0_rd := CAUSE;
when cop0reg_EPC => i_COP0_rd := EPC;
when cop0reg_BadVAddr => i_COP0_rd := BadVAddr;
when cop0reg_CONFIG =>
if MM_cop0_sel = b"000" then
i_COP0_rd := CONFIG0;
else
i_COP0_rd := CONFIG1;
end if;
when others => i_COP0_rd := (others => 'X');
end case;
i_stall := '0'; -- register selection below
when exERET => -- EXCEPTION RETURN
newSTATUS(STATUS_EXL) := '0'; -- leave exception level
i_update := '1';
......@@ -2033,7 +2010,7 @@ begin
when exRESV_INSTR => -- reserved instruction ABORT SIMULATION
assert true -- invalid opcode
assert FALSE -- invalid opcode
report LF & "invalid opcode (resv instr) at PC="& SLV32HEX(EX_PC)
severity failure;
......@@ -2060,11 +2037,11 @@ begin
exception_taken <= '1';
i_update := '1';
i_update_r := cop0reg_STATUS;
ExcCode <= cop0code_AdEL;
i_nullify := TRUE; -- nullify instructions in IF,RF,EX
i_epc_source := EPC_src_MM; -- bad address is in EXCP_MM_PC
ExcCode <= cop0code_AdEL;
i_nullify := TRUE; -- nullify instructions in IF,RF,EX
i_epc_source := EPC_src_MM; -- bad address is in EXCP_MM_PC
i_epc_update := '0';
is_delayslot <= MM_is_delayslot;
is_delayslot <= MM_is_delayslot;
when MMaddressErrorLD | MMaddressErrorST =>
......@@ -2189,7 +2166,7 @@ begin
when exInterr => -- normal interrupt
if (rom_stall = '0') and (ram_stall = '0') then
-- assert false report "interrupt PC="&SLV32HEX(PC) severity note;
assert TRUE report "interrupt PC="&SLV32HEX(PC) severity note;
interrupt_taken <= '1';
newSTATUS(STATUS_UM) := '0'; -- enter kernel mode
newSTATUS(STATUS_EXL) := '1'; -- at exception level
......@@ -2239,7 +2216,6 @@ begin
end case;
STATUSinp <= newSTATUS;
MM_cop0_val <= i_COP0_rd;
update <= i_update;
update_reg <= i_update_r;
......@@ -2256,6 +2232,55 @@ begin
end process COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS;
-- Select value to be read by instruction MFC0 --------------------
COP0_READ: process (is_exception, MM_cop0_reg, MM_cop0_sel,
INDEX, RANDOM, EntryLo0, EntryLo1,
CONTEXT, PAGEMASK, WIRED, EntryHi,
COUNT, COMPARE, STATUS, CAUSE, EPC, BadVAddr)
variable i_COP0_rd : reg32;
begin
case is_exception is
when exEI | exDI => -- enable/disable interrupts
i_COP0_rd := STATUS;
when exMFC0 => -- move from COP-0
case MM_cop0_reg is
when cop0reg_Index => i_COP0_rd := INDEX;
when cop0reg_Random => i_COP0_rd := RANDOM;
when cop0reg_EntryLo0 => i_COP0_rd := EntryLo0;
when cop0reg_EntryLo1 => i_COP0_rd := EntryLo1;
when cop0reg_Context => i_COP0_rd := CONTEXT;
when cop0reg_PageMask => i_COP0_rd := PAGEMASK;
when cop0reg_Wired => i_COP0_rd := WIRED;
when cop0reg_EntryHi => i_COP0_rd := EntryHi;
when cop0reg_COUNT => i_COP0_rd := COUNT;
when cop0reg_COMPARE => i_COP0_rd := COMPARE;
when cop0reg_STATUS => i_COP0_rd := STATUS;
when cop0reg_CAUSE => i_COP0_rd := CAUSE;
when cop0reg_EPC => i_COP0_rd := EPC;
when cop0reg_BadVAddr => i_COP0_rd := BadVAddr;
when cop0reg_CONFIG =>
if MM_cop0_sel = b"000" then
i_COP0_rd := CONFIG0; -- constant
else
i_COP0_rd := CONFIG1; -- constant
end if;
when others =>
i_COP0_rd := STATUS;
end case;
when others =>
i_COP0_rd := STATUS;
end case;
MM_cop0_val <= i_COP0_rd;
end process COP0_READ;
-- Select input to PC on an exception --------------------
COP0_SEL_EPC: process (is_exception, STATUS, CAUSE, MM_trapped)
variable i_excp_PCsel : reg3;
......
......@@ -1038,11 +1038,11 @@ begin
rx_run <= '0';
rx_next_st <= st_idle;
if ((recv /= x"0a") and (recv /= x"04")) then
if ((recv /= x"0a") and (recv /= x"04") and (recv /= x"00")) then
write ( msg, character'val(to_integer(unsigned(recv))) );
end if;
if ((recv = x"0a") or (recv = x"04")) then
if ((recv = x"0a") or (recv = x"04") or (recv = x"00")) then
writeline( output_stream, msg );
end if;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment