mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-28 18:51:53 +00:00
execute1: Implement trace interrupts
Trace interrupts occur when the MSR[TE] field is non-zero and an instruction other than rfid has been successfully completed. A trace interrupt occurs before the next instruction is executed or any asynchronous interrupt is taken. Since the trace interrupt is defined to set SRR1 bits depending on whether the traced instruction is a load or an instruction treated as a load, or a store or an instruction treated as a store, we need to make sure the treated-as-a-load instructions (icbi, icbt, dcbt, dcbst, dcbf) and the treated-as-a-store instructions (dcbtst, dcbz) have the correct opcodes in decode1. Several of them were previously marked as OP_NOP. We don't yet implement the SIAR or SDAR registers, which should be set by trace interrupts. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -13,6 +13,8 @@ package common is
|
||||
constant MSR_SF : integer := (63 - 0); -- Sixty-Four bit mode
|
||||
constant MSR_EE : integer := (63 - 48); -- External interrupt Enable
|
||||
constant MSR_PR : integer := (63 - 49); -- PRoblem state
|
||||
constant MSR_SE : integer := (63 - 53); -- Single-step bit of TE field
|
||||
constant MSR_BE : integer := (63 - 54); -- Branch trace bit of TE field
|
||||
constant MSR_IR : integer := (63 - 58); -- Instruction Relocation
|
||||
constant MSR_DR : integer := (63 - 59); -- Data Relocation
|
||||
constant MSR_RI : integer := (63 - 62); -- Recoverable Interrupt
|
||||
|
||||
10
decode1.vhdl
10
decode1.vhdl
@@ -201,10 +201,10 @@ architecture behaviour of decode1 is
|
||||
2#1000111010# => (ALU, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- cnttzd
|
||||
2#1000011010# => (ALU, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- cnttzw
|
||||
2#1011110011# => (ALU, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- darn
|
||||
2#0001010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf
|
||||
2#0000110110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst
|
||||
2#0100010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt
|
||||
2#0011110110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbtst
|
||||
2#0001010110# => (ALU, OP_DCBF, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf
|
||||
2#0000110110# => (ALU, OP_DCBST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst
|
||||
2#0100010110# => (ALU, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt
|
||||
2#0011110110# => (ALU, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbtst
|
||||
2#1111110110# => (LDST, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- dcbz
|
||||
2#0110001001# => (ALU, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- divdeu
|
||||
2#1110001001# => (ALU, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- divdeuo
|
||||
@@ -230,7 +230,7 @@ architecture behaviour of decode1 is
|
||||
2#1101111010# => (ALU, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extswsli
|
||||
2#1101111011# => (ALU, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extswsli
|
||||
2#1111010110# => (ALU, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbi
|
||||
2#0000010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt
|
||||
2#0000010110# => (ALU, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt
|
||||
2#0000001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel
|
||||
2#0000101111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- isel
|
||||
2#0001001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- isel
|
||||
|
||||
@@ -53,6 +53,8 @@ architecture behaviour of execute1 is
|
||||
f : Execute1ToFetch1Type;
|
||||
busy: std_ulogic;
|
||||
terminate: std_ulogic;
|
||||
trace_next : std_ulogic;
|
||||
prev_op : insn_type_t;
|
||||
lr_update : std_ulogic;
|
||||
next_lr : std_ulogic_vector(63 downto 0);
|
||||
mul_in_progress : std_ulogic;
|
||||
@@ -69,7 +71,7 @@ architecture behaviour of execute1 is
|
||||
end record;
|
||||
constant reg_type_init : reg_type :=
|
||||
(e => Execute1ToWritebackInit, f => Execute1ToFetch1Init,
|
||||
busy => '0', lr_update => '0', terminate => '0',
|
||||
busy => '0', lr_update => '0', terminate => '0', trace_next => '0', prev_op => OP_ILLEGAL,
|
||||
mul_in_progress => '0', mul_finish => '0', div_in_progress => '0', cntz_in_progress => '0',
|
||||
slow_op_insn => OP_ILLEGAL, slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init,
|
||||
next_lr => (others => '0'), last_nia => (others => '0'), others => (others => '0'));
|
||||
@@ -330,6 +332,7 @@ begin
|
||||
variable abs_branch : std_ulogic;
|
||||
variable spr_val : std_ulogic_vector(63 downto 0);
|
||||
variable addend : std_ulogic_vector(127 downto 0);
|
||||
variable do_trace : std_ulogic;
|
||||
begin
|
||||
result := (others => '0');
|
||||
sum_with_carry := (others => '0');
|
||||
@@ -525,6 +528,11 @@ begin
|
||||
|
||||
v.e.mode_32bit := not ctrl.msr(MSR_SF);
|
||||
|
||||
do_trace := valid_in and ctrl.msr(MSR_SE);
|
||||
if valid_in = '1' then
|
||||
v.prev_op := e_in.insn_type;
|
||||
end if;
|
||||
|
||||
if ctrl.irq_state = WRITE_SRR1 then
|
||||
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
|
||||
v.e.exc_write_data := ctrl.srr1;
|
||||
@@ -532,13 +540,29 @@ begin
|
||||
ctrl_tmp.msr(MSR_SF) <= '1';
|
||||
ctrl_tmp.msr(MSR_EE) <= '0';
|
||||
ctrl_tmp.msr(MSR_PR) <= '0';
|
||||
ctrl_tmp.msr(MSR_SE) <= '0';
|
||||
ctrl_tmp.msr(MSR_BE) <= '0';
|
||||
ctrl_tmp.msr(MSR_IR) <= '0';
|
||||
ctrl_tmp.msr(MSR_DR) <= '0';
|
||||
ctrl_tmp.msr(MSR_RI) <= '0';
|
||||
ctrl_tmp.msr(MSR_LE) <= '1';
|
||||
v.e.valid := '1';
|
||||
v.trace_next := '0';
|
||||
report "Writing SRR1: " & to_hstring(ctrl.srr1);
|
||||
|
||||
elsif r.trace_next = '1' and valid_in = '1' then
|
||||
-- Generate a trace interrupt rather than executing the next instruction
|
||||
-- or taking any asynchronous interrupt
|
||||
v.f.redirect_nia := std_logic_vector(to_unsigned(16#d00#, 64));
|
||||
ctrl_tmp.srr1(63 - 33) <= '1';
|
||||
if r.prev_op = OP_LOAD or r.prev_op = OP_ICBI or r.prev_op = OP_ICBT or
|
||||
r.prev_op = OP_DCBT or r.prev_op = OP_DCBST or r.prev_op = OP_DCBF then
|
||||
ctrl_tmp.srr1(63 - 35) <= '1';
|
||||
elsif r.prev_op = OP_STORE or r.prev_op = OP_DCBZ or r.prev_op = OP_DCBTST then
|
||||
ctrl_tmp.srr1(63 - 36) <= '1';
|
||||
end if;
|
||||
exception := '1';
|
||||
|
||||
elsif irq_valid = '1' and valid_in = '1' then
|
||||
-- we need two cycles to write srr0 and 1
|
||||
-- will need more when we have to write HEIR
|
||||
@@ -594,7 +618,7 @@ begin
|
||||
else
|
||||
illegal := '1';
|
||||
end if;
|
||||
when OP_NOP =>
|
||||
when OP_NOP | OP_DCBF | OP_DCBST | OP_DCBT | OP_DCBTST | OP_ICBT =>
|
||||
-- Do nothing
|
||||
when OP_ADD | OP_CMP | OP_TRAP =>
|
||||
result := sum_with_carry(63 downto 0);
|
||||
@@ -715,6 +739,9 @@ begin
|
||||
is_branch := '1';
|
||||
taken_branch := '1';
|
||||
abs_branch := insn_aa(e_in.insn);
|
||||
if ctrl.msr(MSR_BE) = '1' then
|
||||
do_trace := '1';
|
||||
end if;
|
||||
when OP_BC =>
|
||||
-- read_data1 is CTR
|
||||
bo := insn_bo(e_in.insn);
|
||||
@@ -727,6 +754,9 @@ begin
|
||||
is_branch := '1';
|
||||
taken_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
|
||||
abs_branch := insn_aa(e_in.insn);
|
||||
if ctrl.msr(MSR_BE) = '1' then
|
||||
do_trace := '1';
|
||||
end if;
|
||||
when OP_BCREG =>
|
||||
-- read_data1 is CTR
|
||||
-- read_data2 is target register (CTR, LR or TAR)
|
||||
@@ -740,6 +770,9 @@ begin
|
||||
is_branch := '1';
|
||||
taken_branch := ppc_bc_taken(bo, bi, cr_in, a_in);
|
||||
abs_branch := '1';
|
||||
if ctrl.msr(MSR_BE) = '1' then
|
||||
do_trace := '1';
|
||||
end if;
|
||||
|
||||
when OP_RFID =>
|
||||
v.f.virt_mode := a_in(MSR_IR) or a_in(MSR_PR);
|
||||
@@ -760,6 +793,7 @@ begin
|
||||
is_branch := '1';
|
||||
taken_branch := '1';
|
||||
abs_branch := '1';
|
||||
do_trace := '0';
|
||||
|
||||
when OP_CNTZ =>
|
||||
v.e.valid := '0';
|
||||
@@ -1135,6 +1169,10 @@ begin
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if do_trace = '1' then
|
||||
v.trace_next := '1';
|
||||
end if;
|
||||
|
||||
v.e.write_data := result;
|
||||
v.e.write_enable := result_en and not exception;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user