Commit 180ec3e9 authored by Tristan Gingold's avatar Tristan Gingold

urv: handle irq using v1.10 spec.

parent e2859cda
......@@ -70,7 +70,7 @@
`define FUNC_REM 3'b110
`define FUNC_REMU 3'b111
`define RD_SOURCE_ALU 3'b000
`define RD_SOURCE_ALU 3'b000
`define RD_SOURCE_SHIFTER 3'b010
`define RD_SOURCE_MULTIPLY 3'b001
`define RD_SOURCE_DIVIDE 3'b100
......@@ -78,9 +78,9 @@
`define RD_SOURCE_MULH 3'b111
`define CSR_ID_CYCLESH 12'hc80
`define CSR_ID_CYCLESL 12'hc00
`define CSR_ID_CYCLESL 12'hc00
`define CSR_ID_TIMEH 12'hc81
`define CSR_ID_TIMEL 12'hc01
`define CSR_ID_TIMEL 12'hc01
`define CSR_ID_MSCRATCH 12'h340
`define CSR_ID_MEPC 12'h341
`define CSR_ID_MSTATUS 12'h300
......@@ -106,9 +106,9 @@
`define URV_RESET_VECTOR 32'h00000000
`define URV_TRAP_VECTOR 32'h00000008
// Bits in mie/mip for user mode
`define EXCEPT_TIMER 4
`define EXCEPT_IRQ 8
// Bits in mie/mip for machine mode
`define EXCEPT_TIMER 7
`define EXCEPT_IRQ 11
// Cause
`define CAUSE_ILLEGAL_INSN 2
......@@ -116,6 +116,9 @@
`define CAUSE_UNALIGNED_LOAD 4
`define CAUSE_UNALIGNED_STORE 6
`define CAUSE_MACHINE_IRQ 11
`define CAUSE_MACHINE_TIMER 7
`define OP_SEL_BYPASS_X 0
`define OP_SEL_BYPASS_W 1
`define OP_SEL_DIRECT 2
......
......@@ -44,15 +44,14 @@ module urv_exceptions
input exp_irq_i,
input exp_tick_i,
input exp_breakpoint_i,
input exp_unaligned_load_i,
input exp_unaligned_store_i,
input exp_invalid_insn_i,
output exp_ei_pending_o,
output exp_ti_pending_o,
input [31:0] x_csr_write_value_i,
input x_exception_i,
input [3:0] x_exception_cause_i,
input x_interrupt_i,
input [31:0] x_exception_pc_i,
output [31:0] x_exception_pc_o,
......@@ -64,61 +63,50 @@ module urv_exceptions
output [31:0] csr_mcause_o
);
reg [31:0] csr_mepc;
reg [31:0] csr_mie;
reg csr_ie;
reg [3:0] csr_mcause;
reg [5:0] except_vec_masked;
reg csr_status_mie;
reg [3:0] csr_mcause_code;
reg csr_mcause_interrupt;
assign csr_mcause_o = {28'h0, csr_mcause};
assign csr_mcause_o = {csr_mcause_interrupt, 27'h0, csr_mcause_code};
assign csr_mepc_o = csr_mepc;
assign csr_mie_o = csr_mie;
assign csr_mstatus_o[0] = csr_ie;
assign csr_mstatus_o[31:1] = 0;
assign csr_mstatus_o[3] = csr_status_mie;
assign csr_mstatus_o[31:4] = 0;
assign csr_mstatus_o[2:0] = 0;
assign csr_mip_o = 0;
always@(posedge clk_i)
if (rst_i)
except_vec_masked <= 0;
else begin
if(!x_stall_i && !x_kill_i && d_is_csr_i && d_csr_sel_i == `CSR_ID_MIP)
begin
except_vec_masked[4] <= x_csr_write_value_i [`EXCEPT_TIMER];
except_vec_masked[5] <= x_csr_write_value_i [`EXCEPT_IRQ];
end
else begin
if ( exp_tick_i )
except_vec_masked[4] <= csr_mie[`EXCEPT_TIMER] & csr_ie;
if( exp_irq_i )
except_vec_masked[5] <= csr_mie[`EXCEPT_IRQ] & csr_ie;
end
end
assign exp_ei_pending_o = exp_irq_i & csr_mie[`EXCEPT_IRQ] & csr_status_mie;
assign exp_ti_pending_o = exp_tick_i & csr_mie[`EXCEPT_TIMER] & csr_status_mie;
always@(posedge clk_i)
if(rst_i)
begin
csr_mcause <= 0;
csr_mcause_code <= 0;
csr_mcause_interrupt <= 0;
csr_mepc <= 0;
csr_mie <= 0;
csr_ie <= 0;
csr_status_mie <= 0;
end
else
begin
if (x_exception_i)
begin
csr_mepc <= x_exception_pc_i;
csr_mcause <= x_exception_cause_i;
csr_mcause_code <= x_exception_cause_i;
csr_mcause_interrupt <= x_interrupt_i;
// Mask interrupts when taken.
if (x_interrupt_i)
csr_status_mie <= 0;
end
if (!x_stall_i && !x_kill_i && d_is_csr_i)
case (d_csr_sel_i)
`CSR_ID_MSTATUS:
csr_ie <= x_csr_write_value_i[0];
csr_status_mie <= x_csr_write_value_i[3];
`CSR_ID_MEPC:
csr_mepc <= x_csr_write_value_i;
`CSR_ID_MIE:
......
......@@ -130,6 +130,7 @@ module urv_exec
reg x_exception;
reg [3:0] x_exception_cause;
reg x_interrupt;
reg branch_take;
reg branch_condition_met;
......@@ -154,8 +155,9 @@ module urv_exec
wire [31:0] csr_mie, csr_mip, csr_mepc, csr_mstatus,csr_mcause;
wire [31:0] csr_write_value;
wire [31:0] exception_address;
wire [31:0] exception_pc;
wire irq_pending;
wire timer_pending;
urv_csr
#(
......@@ -210,13 +212,12 @@ module urv_exec
.exp_irq_i(irq_i),
.exp_tick_i(timer_tick_i),
.exp_breakpoint_i(1'b0),
.exp_unaligned_load_i(1'b0),
.exp_unaligned_store_i(1'b0),
.exp_invalid_insn_i(d_is_undef_i && !x_stall_i && !x_kill_i && d_valid_i),
.exp_ei_pending_o(irq_pending),
.exp_ti_pending_o(timer_pending),
.x_exception_i(x_exception),
.x_exception_cause_i(x_exception_cause),
.x_interrupt_i(x_interrupt),
.x_exception_pc_i(exception_pc),
.x_exception_pc_o(exception_address),
......@@ -388,35 +389,48 @@ module urv_exec
// x_exception: exception due to execution
always@*
if (x_stall_i || x_kill_i || !d_valid_i)
begin
// If the current instruction is not valid, there is no exception.
x_exception <= 0;
x_exception_cause <= 4'hx;
end
else if (d_is_undef_i)
begin
x_exception <= 1;
x_exception_cause <= `CAUSE_ILLEGAL_INSN;
end
else
case (d_opcode_i)
`OPC_LOAD:
begin
x_exception <= unaligned_addr;
x_exception_cause <= `CAUSE_UNALIGNED_LOAD;
end
`OPC_STORE:
begin
x_exception <= unaligned_addr;
x_exception_cause <= `CAUSE_UNALIGNED_STORE;
end
default:
begin
x_exception <= 0;
x_exception_cause <= 4'hx;
end
endcase
begin
x_exception <= 0;
x_interrupt <= 0;
x_exception_cause <= 4'hx;
if (x_stall_i || x_kill_i || !d_valid_i)
begin
// If the current instruction is not valid, there is no exception.
end
else if (d_is_undef_i)
begin
x_exception <= 1;
x_interrupt <= 0;
x_exception_cause <= `CAUSE_ILLEGAL_INSN;
end
else if (unaligned_addr
&& (d_opcode_i == `OPC_LOAD || d_opcode_i == `OPC_STORE))
begin
x_exception <= 1;
x_interrupt <= 0;
case (d_opcode_i)
`OPC_LOAD:
x_exception_cause <= `CAUSE_UNALIGNED_LOAD;
`OPC_STORE:
x_exception_cause <= `CAUSE_UNALIGNED_STORE;
default:
x_exception_cause <= 4'hx;
endcase // case (d_opcode_i)
end
else if (timer_pending)
begin
x_exception <= 1;
x_interrupt <= 1;
x_exception_cause <= `CAUSE_MACHINE_TIMER;
end
else if (irq_pending)
begin
x_exception <= 1;
x_interrupt <= 1;
x_exception_cause <= `CAUSE_MACHINE_IRQ;
end
end
// generate store value/select
always@*
......
......@@ -48,35 +48,19 @@ trap_entry:
sw t0,144(sp)
mv a0,sp
la t0, jump_table
sll t3, t3, 2
add t0, t0, t3
lw t0, 0(t0)
la ra, jump_table_return
jr t0
bgez t3, .Lexcept
jal irq_handler
j .Lret
jump_table:
.word undefined_handler
.word undefined_handler
.word undefined_insn_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
jump_table_return:
mv a0,sp
.Lexcept:
la t0, jump_table
sll t3, t3, 2
add t0, t0, t3
lw t0, 0(t0)
jalr t0
.Lret:
mv a0,sp
lw t1,128(a0)
lw t2,132(a0)
addi sp,sp,320
......@@ -115,10 +99,31 @@ jump_table_return:
lw a0,40(a0)
mret
.weak undefined_handler
.text
.weak undefined_handler
undefined_handler:
j undefined_handler
.weak undefined_insn_handler
.weak undefined_insn_handler
undefined_insn_handler:
j undefined_insn_handler
j undefined_insn_handler
.data
jump_table:
.word undefined_handler # 0: Insn address misaligned
.word undefined_handler
.word undefined_insn_handler # 2: Illegal insn
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
.word undefined_handler
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