diff --git a/hdl/boa32_cpu.sv b/hdl/boa32_cpu.sv index 62407ba..cea5f8a 100644 --- a/hdl/boa32_cpu.sv +++ b/hdl/boa32_cpu.sv @@ -44,11 +44,13 @@ module boa32_cpu#( parameter entrypoint = 32'h4000_0000, // CPU-local memory-mapped I/O address. parameter cpummio = 32'hff00_0000, - // CSR mhartid value. + // CSR mhartid value (CPU number). parameter hartid = 32'h0000_0000, // Print debug messages about CPU state. parameter debug = 0, - // Support RVC instructions. + // Support M (multiply/divide) instructions. + parameter has_m = 1, + // Support C (compressed) instructions. parameter has_c = 1 )( // CPU clock. @@ -479,7 +481,7 @@ module boa32_cpu#( // Data hazard avoicance. fw_stall_if ); - boa_stage_id#(.debug(debug), .has_c(has_c)) st_id( + boa_stage_id#(.debug(debug), .has_m(has_m), .has_c(has_c)) st_id( clk, rst, clear_id, // Pipeline input. if_id_valid && !fw_stall_if, if_id_pc, if_id_insn, if_id_trap && !fw_stall_if, if_id_cause, @@ -492,7 +494,7 @@ module boa32_cpu#( // Data hazard avoidance. fw_stall_id, use_rs1_bt, fw_rs1_bt, fw_in_bt ); - boa_stage_ex st_ex( + boa_stage_ex#(.has_m(has_m)) st_ex ( clk, rst, clear_ex, // Pipeline input. id_ex_valid && !fw_stall_id, id_ex_pc, id_ex_insn, id_ex_ilen, id_ex_use_rd, fw_rs1_ex ? fw_in_rs1_ex : id_ex_rs1_val, fw_rs2_ex ? fw_in_rs2_ex : id_ex_rs2_val, id_ex_branch, id_ex_branch_predict, id_ex_trap && !fw_stall_id, id_ex_cause, diff --git a/hdl/stages/boa_stage_ex.sv b/hdl/stages/boa_stage_ex.sv index 6b01872..ed6ff8c 100644 --- a/hdl/stages/boa_stage_ex.sv +++ b/hdl/stages/boa_stage_ex.sv @@ -9,7 +9,10 @@ // Boa³² pipline stage: EX (ALU and address calculation). module boa_stage_ex#( // Divider latency, 0 to 33. - parameter div_latency = 2 + // Only applicable if has_m is 1. + parameter div_latency = 2, + // Support M (multiply/divide) instructions. + parameter has_m = 1 )( // CPU clock. input logic clk, @@ -158,22 +161,29 @@ module boa_stage_ex#( logic[31:0] div_res; logic[31:0] mod_res; logic[31:0] shx_res; - boa_mul_simple mul(mul_u_lhs, mul_u_rhs, r_rs1_val, r_rs2_val, mul_res); generate - if (div_latency == 0) begin: l0 + if (has_m) begin: mul + boa_mul_simple mul(mul_u_lhs, mul_u_rhs, r_rs1_val, r_rs2_val, mul_res); + end else begin: nomul + assign mul_res = 'bx; + end + if (has_m && div_latency == 0) begin: l0div boa_div_simple div( div_u, r_rs1_val, r_rs2_val, div_res, mod_res ); - end else begin: l1 + end else if (has_m) begin: l1div boa_div_pipelined#(.latency(div_latency)) div( clk, div_u, r_rs1_val, r_rs2_val, div_res, mod_res ); + end else begin: nodiv + assign div_res = 'bx; + assign mod_res = 'bx; end endgenerate boa_shift_simple shift(shr_arith, shr, r_rs1_val, op_rhs_mux, shx_res); // Computation delay module. - wire is_divmod = d_valid && d_insn[6:2] == `RV_OP_OP && d_insn[25] && d_insn[14]; + wire is_divmod = has_m && d_valid && d_insn[6:2] == `RV_OP_OP && d_insn[25] && d_insn[14]; boa_delay_comp#(div_latency) div_delay(clk, is_divmod, stall_req); // Adder mode. @@ -226,7 +236,7 @@ module boa_stage_ex#( logic[31:0] out_mux; always @(*) begin if (is_op) begin - if (muldiv_en) begin + if (has_m && muldiv_en) begin // MULDIV instructions. casez (r_insn[14:12]) 3'b000: out_mux = mul_res[31:0]; diff --git a/hdl/stages/boa_stage_id.sv b/hdl/stages/boa_stage_id.sv index 35b01a0..5d51dd2 100644 --- a/hdl/stages/boa_stage_id.sv +++ b/hdl/stages/boa_stage_id.sv @@ -10,7 +10,9 @@ module boa_stage_id#( // Print debug messages about CPU state. parameter debug = 0, - // Support RVC instructions. + // Support M (multiply/divide) instructions. + parameter has_m = 1, + // Support C (compressed) instructions. parameter has_c = 1 )( // CPU clock. diff --git a/sim/riscv-tests/bench.cpp b/sim/riscv-tests/bench.cpp index d2d137a..69a5bba 100644 --- a/sim/riscv-tests/bench.cpp +++ b/sim/riscv-tests/bench.cpp @@ -28,6 +28,8 @@ int main(int argc, char **argv) { // Add exit handlers. atexit(atexit_func); + bool catch_ebreak = getenv("CATCH_EBREAK"); + // Set UART to nonblocking. stdin_orig_flags = fcntl(0, F_GETFL); fcntl(fileno(stdin), F_SETFL, stdin_orig_flags | O_NONBLOCK); @@ -55,6 +57,12 @@ int main(int argc, char **argv) { trace->dump(i * 10); top->clk ^= 1; + if (top->is_ebreak && top->clk && catch_ebreak) { + printf("Trace / breakpoint trap\n"); + printf("PC = 0x%08x\n", top->epc << 1); + ec = -3; + break; + } if (top->is_ecall && top->clk) { int a0 = top->regs[10]; int a7 = top->regs[17]; diff --git a/sim/riscv-tests/hdl/top.sv b/sim/riscv-tests/hdl/top.sv index afb6241..aa0b8b3 100644 --- a/sim/riscv-tests/hdl/top.sv +++ b/sim/riscv-tests/hdl/top.sv @@ -6,13 +6,17 @@ module top( input logic clk, output logic is_ecall, - output logic[31:0] regs[31:0] + output logic is_ebreak, + output logic[31:0] regs[31:0], + output logic[31:1] epc ); `include "boa_fileio.svh" `include "boa_defines.svh" // To host time. assign is_ecall = cpu.csr_ex.ex_trap && cpu.csr_ex.ex_cause == `RV_ECAUSE_M_ECALL; + assign is_ebreak = cpu.csr_ex.ex_trap && cpu.csr_ex.ex_cause == `RV_ECAUSE_EBREAK; + assign epc = cpu.csr_ex.ex_epc; assign regs[0] = 0; assign regs[31:1] = cpu.st_id.regfile.storage; @@ -46,7 +50,11 @@ module top( end // The boa CPU core. - boa32_cpu#(32'h8000_0000) cpu( + boa32_cpu#( + .entrypoint(32'h8000_0000), + .has_c(1), + .has_m(1) + ) cpu ( clk, clk, rst, pbus, dbus, 0 ); endmodule