Skip to content

Commit facd028

Browse files
committed
Fix case where exception exit and entry are requested simultaneously. Fix interaction between exception exit and pipe stall/flush.
1 parent ff3a811 commit facd028

3 files changed

Lines changed: 38 additions & 7 deletions

File tree

TODO.todo

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ Processor:
1010
☐ Compliant debug support (must run with upstream openocd)
1111
☐ Support for M extension
1212
✔ Create divide/multiply circuit @done (20-02-26 00:00)
13-
Integrate into pipeline, pass compliance tests
14-
Kill ongoing div/mul on IRQ raise
13+
Integrate into pipeline, pass compliance tests @done (20-02-28 21:05)
14+
Kill ongoing div/mul on IRQ raise @done (20-03-02 00:45)
1515
☐ Fuse MULH/MUL and DIV/REM sequences
16+
✔ Get riscv-formal M-extension checks passing with ALTOPS enabled @done (20-03-02 00:44)
17+
☐ Get all riscv-formal rv32imc checks passing with muldiv instantiated
18+
☐ Standalone formal test for mul/div results
1619
☐ Support two-bus-master variant
1720
☐ Write separate top levels for 1mst and 2mst
1821
☐ Bring up compliance tests on 2mst
1922
☐ Bring up riscv-formal on 2mst
2023
☐ Yosys synth check for through-paths between the two busmasters
24+
☐ Bring up riscv-formal CSR checks
2125
☐ Integrate riscv-formal into regressions, perhaps optionally.
2226
☐ Iterate on decode synths to try and pack gates down
2327
Still an open issue. Have investigated the instruction decompressor and it's no larger than the crazy hand-Espresso'd one in SWeRV. Rest of decode potentially still has some savings in the non-RV-specific parts.

hdl/hazard5/hazard5_cpu.v

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,8 @@ reg [W_MEMOP-1:0] xm_memop;
353353
// For JALR, the LSB of the result must be cleared by hardware
354354
wire [W_ADDR-1:0] x_taken_jump_target = dx_jump_is_regoffs ? x_alu_add & ~32'h1 : dx_jump_target;
355355
wire [W_ADDR-1:0] x_jump_target =
356+
x_trap_exit ? x_mepc : // Note precedence -- it's possible to have enter && exit, but in this case enter_rdy is false.
356357
x_trap_enter ? x_trap_addr :
357-
x_trap_exit ? x_mepc :
358358
dx_imm[31] && dx_branchcond != BCOND_ALWAYS ? dx_mispredict_addr :
359359
x_taken_jump_target;
360360

@@ -401,7 +401,7 @@ always @ (*) begin
401401
MEMOP_SH: ahb_hsize_d = HSIZE_HWORD;
402402
default: ahb_hsize_d = HSIZE_BYTE;
403403
endcase
404-
ahb_req_d = x_memop_vld && !x_stall_raw && !flush_d_x && !x_trap_enter;
404+
ahb_req_d = x_memop_vld && !(x_stall_raw || flush_d_x || x_trap_enter);
405405
end
406406

407407
// ALU operand muxes and bypass
@@ -441,11 +441,17 @@ end
441441
wire x_except_ecall = dx_except == EXCEPT_ECALL;
442442
wire x_except_breakpoint = dx_except == EXCEPT_EBREAK;
443443
wire x_except_invalid_instr = dx_except == EXCEPT_INSTR_ILLEGAL;
444-
wire x_trap_enter_rdy = !(x_stall || m_jump_req);
445-
assign x_trap_exit = dx_except == EXCEPT_MRET && x_trap_enter_rdy;
444+
assign x_trap_exit = dx_except == EXCEPT_MRET && !(x_stall || m_jump_req);
445+
wire x_trap_enter_rdy = !(x_stall || m_jump_req || x_trap_exit);
446+
wire x_trap_is_exception; // diagnostic
446447

447448
`ifdef FORMAL
448-
always @ (posedge clk) if (flush_d_x) assert(!x_trap_enter_rdy);
449+
always @ (posedge clk) begin
450+
if (flush_d_x)
451+
assert(!x_trap_enter_rdy);
452+
if (x_trap_exit)
453+
assert(!ahb_req_d);
454+
end
449455
`endif
450456

451457
wire [W_DATA-1:0] x_csr_wdata = dx_csr_w_imm ?
@@ -479,6 +485,7 @@ hazard5_csr #(
479485
.trap_enter_vld (x_trap_enter),
480486
.trap_enter_rdy (x_trap_enter_rdy),
481487
.trap_exit (x_trap_exit),
488+
.trap_is_exception (x_trap_is_exception),
482489
.mepc_in (dx_pc),
483490
.mepc_out (x_mepc),
484491
// IRQ and exception requests

hdl/hazard5/hazard5_csr.v

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ module hazard5_csr #(
7070
output wire trap_enter_vld,
7171
input wire trap_enter_rdy,
7272
input wire trap_exit,
73+
output wire trap_is_exception, // diagnostic
7374
output wire [XLEN-1:0] mepc_in,
7475
output wire [XLEN-1:0] mepc_out,
7576

@@ -742,8 +743,27 @@ wire [11:0] mtvec_offs = (exception_req_any ?
742743

743744
assign trap_addr = mtvec | mtvec_offs;
744745
assign trap_enter_vld = CSR_M_TRAP && (exception_req_any || irq_any);
746+
assign trap_is_exception = exception_req_any;
745747

746748
assign mcause_irq_next = !exception_req_any;
747749
assign mcause_code_next = exception_req_any ? exception_req_num : irq_num;
748750

751+
// ----------------------------------------------------------------------------
752+
753+
`ifdef RISCV_FORMAL
754+
always @ (posedge clk) begin
755+
// Something is screwed up if this happens
756+
if ($past(trap_enter_vld && trap_enter_rdy))
757+
assert(!wen);
758+
// Don't do this
759+
assert(!(trap_enter_vld && trap_enter_rdy && trap_exit));
760+
// Should be impossible to get into the trap and exit it so quickly:
761+
if (in_trap && !$past(in_trap))
762+
assert(!trap_exit);
763+
// Should be impossible to get to another mret so soon after exiting:
764+
assert(!(trap_exit && $past(trap_exit)));
765+
end
766+
767+
`endif
768+
749769
endmodule

0 commit comments

Comments
 (0)