Add ecall/ebreak

This commit is contained in:
2025-09-03 17:22:00 +03:00
parent 3087975833
commit ee55a07e0a
11 changed files with 148 additions and 37 deletions
+17 -2
View File
@@ -40,6 +40,8 @@ module rvx0_core #(
wire fault_instruction_decode;
wire fault_unsupported_size;
wire fault_address_align;
wire raise_ecall;
wire raise_ebreak;
// Control
@@ -112,6 +114,8 @@ module rvx0_core #(
rvx0_decoder decoder (
.instruction_i (instruction),
.instruction_fault_o (fault_instruction_decode),
.v1src_o (v1src),
.v2src_o (v2src),
.vdsrc_o (vdsrc),
@@ -123,8 +127,10 @@ module rvx0_core #(
.write_mem_o (need_memory_write),
.write_pc_o (write_pc),
.funct3_o (funct3),
.instruction_fault_o (fault_instruction_decode),
.conditional_o (conditional)
.conditional_o (conditional),
.raise_ecall_o (raise_ecall),
.raise_ebreak_o (raise_ebreak)
);
rvx0_regfile regfile (
@@ -204,6 +210,8 @@ module rvx0_core #(
fault_instruction ||
fault_memory_align ||
fault_memory_access ||
raise_ecall ||
raise_ebreak ||
intr_ext_i;
assign fault_instruction = fault_instruction_decode || (fault_unsupported_size && (need_memory_read || need_memory_write));
@@ -257,6 +265,8 @@ module rvx0_core #(
end else if (fault_instruction) begin
mcause_write_value = MCAUSE_ILLEGAL_INSTRUCTION;
mtval_write_value = instruction;
end else if (raise_ebreak) begin
mcause_write_value = MCAUSE_BREAKPOINT;
end else if (~need_memory_write && fault_memory_align) begin
mcause_write_value = MCAUSE_LOAD_ADDRESS_MISALIGNED;
mtval_write_value = alu_output;
@@ -271,6 +281,8 @@ module rvx0_core #(
// been incremented
mepc_write_value = pc_value - 4;
mtval_write_value = alu_output;
end else if (raise_ecall) begin
mcause_write_value = MCAUSE_ECALL_MMODE;
end else if (intr_ext_i) begin
mcause_write_value = MCAUSE_INTR_EXT_MMODE | MCAUSE_INTERRUPT;
end
@@ -284,8 +296,11 @@ module rvx0_core #(
if (fault) begin
$display("Take exception mcause=%x, mepc=%x, mtval=%x to %x", mcause_write_value, mepc_write_value, mtval_write_value, csr_mtvec);
$display("Instruction: %x", instruction);
`ifdef RVX0_CRASH_ON_EXCEPTION
regfile.dump_state;
$finish;
`endif
exec_stall = 1;
end else begin
`ifdef RVX0_DEBUGGING
+1 -1
View File
@@ -33,7 +33,7 @@ module rvx0_csr (
always @(posedge clk_i) begin
if (rst_i) begin
// TODO set from CPU
mtvec_o = 'h00020000;
mtvec_o = 'h00001004;
mepc_o = 0;
mstatus_o = 0;
mstatush_o = 0;
+78 -13
View File
@@ -8,7 +8,13 @@ module rvx0_decoder (
output logic write_mem_o,
output logic conditional_o,
output logic is_system_o,
output logic raise_ecall_o,
output logic raise_ebreak_o,
output logic instruction_fault_o,
output logic [6:0] opcode_o,
output wire [31:0] imm_o,
output wire v1src_o,
output wire [1:0] v2src_o,
@@ -20,15 +26,13 @@ module rvx0_decoder (
output wire [4:0] rs2_o,
output wire [4:0] rd_o
);
wire [6:0] opcode;
wire signed [11:0] imm_i_type;
wire signed [11:0] imm_s_type;
wire signed [12:0] imm_b_type;
wire [19:0] imm_u_type;
wire signed [20:0] imm_j_type;
assign opcode = instruction_i[6:0];
assign opcode_o = instruction_i[6:0];
assign funct3_o = instruction_i[14:12];
assign funct7_o = instruction_i[31:25];
@@ -42,10 +46,24 @@ module rvx0_decoder (
assign rs2_o = instruction_i[24:20];
assign rd_o = instruction_i[11:7];
// Decode select
// Base ISA
wire base_instruction_fault;
wire base_write_pc;
wire base_write_mem;
wire base_v1src;
wire [1:0] base_v2src;
wire [1:0] base_vdsrc;
wire base_conditional;
wire [3:0] base_aluop;
wire [31:0] base_imm;
rvx0_decoder_i decoder_i (
.instruction_i (instruction_i),
.opcode (opcode),
.opcode (opcode_o),
.funct3 (funct3_o),
.imm_i_type (imm_i_type),
@@ -54,15 +72,62 @@ module rvx0_decoder (
.imm_u_type (imm_u_type),
.imm_j_type (imm_j_type),
.write_pc_o (write_pc_o),
.write_mem_o (write_mem_o),
.conditional_o (conditional_o),
.write_pc_o (base_write_pc),
.write_mem_o (base_write_mem),
.conditional_o (base_conditional),
.instruction_fault_o (instruction_fault_o),
.imm_o (imm_o),
.v1src_o (v1src_o),
.v2src_o (v2src_o),
.vdsrc_o (vdsrc_o),
.aluop_o (aluop_o)
.instruction_fault_o (base_instruction_fault),
.imm_o (base_imm),
.v1src_o (base_v1src),
.v2src_o (base_v2src),
.vdsrc_o (base_vdsrc),
.aluop_o (base_aluop)
);
always_comb begin
is_system_o = 0;
case (opcode_o)
'b0001111: is_system_o = 1;
'b1110011: is_system_o = 1;
endcase
raise_ecall_o = 0;
raise_ebreak_o = 0;
write_pc_o = 0;
write_mem_o = 0;
conditional_o = 0;
instruction_fault_o = 0;
imm_o = 0;
v1src_o = V1SRC_ZERO;
v2src_o = V2SRC_ZERO;
vdsrc_o = RDSRC_NONE;
aluop_o = ALUOP_ADD;
if (rs1_o == 0 && funct3_o == 0 && rd_o == 0 && opcode_o == 'b1110011) begin
case (instruction_i[31:20])
0: raise_ecall_o = 1;
1: raise_ebreak_o = 1;
default: instruction_fault_o = 1;
endcase
end else if (rs1_o == 0 && funct3_o == 0 && opcode_o == 'b0001111) begin
// Nice
end else begin
instruction_fault_o = base_instruction_fault;
if (~base_instruction_fault) begin
write_pc_o = base_write_pc;
write_mem_o = base_write_mem;
conditional_o = base_conditional;
imm_o = base_imm;
v1src_o = base_v1src;
v2src_o = base_v2src;
vdsrc_o = base_vdsrc;
aluop_o = base_aluop;
end
end
end
endmodule
+9 -1
View File
@@ -1,4 +1,4 @@
// Base rv32i instruction set decoder
// Base rv32i instruction set decoder minus fence/pause/ecall/ebreak
module rvx0_decoder_i (
input wire [31:0] instruction_i,
@@ -69,6 +69,10 @@ module rvx0_decoder_i (
v2src_o = V2SRC_ZERO;
vdsrc_o = RDSRC_MEM;
imm_o = 32'(signed'(imm_i_type));
if (funct3[1:0] == 2'b11) begin
instruction_fault_o = 1;
end
end
7'b0100011: begin // store
v1src_o = V1SRC_RS1;
@@ -76,6 +80,10 @@ module rvx0_decoder_i (
vdsrc_o = RDSRC_NONE;
write_mem_o = 1;
imm_o = 32'(signed'(imm_s_type));
if (funct3[1:0] == 2'b11) begin
instruction_fault_o = 1;
end
end
7'b0010011: begin // alu imm
v1src_o = V1SRC_RS1;
+1 -1
View File
@@ -14,7 +14,7 @@ module rvx0_busmux (
// RAM
const logic [31:0] APB1_BASE = 'h20000000;
const logic [31:0] APB1_SIZE = 'h00001000;
const logic [31:0] APB1_SIZE = 'h00400000;
// Debug
const logic [31:0] APB2_BASE = 'h10000000;
+4
View File
@@ -2,6 +2,7 @@
`define __RVX0_DEFS_SVH
`define RVX0_DEBUGGING 1
// `define RVX0_CRASH_ON_EXCEPTION 1
const logic [1:0] RDSRC_ALU = 0;
const logic [1:0] RDSRC_MEM = 1;
@@ -58,4 +59,7 @@ const logic [31:0] MCAUSE_STORE_PAGE_FAULT = 15;
const logic [31:0] MCAUSE_INTR_EXT_MMODE = 11;
const logic [31:0] MCAUSE_INTERRUPT = 1 << 31;
const logic IGROUP_RV32I = 0;
const logic IGROUP_SYSTEM = 1;
`endif // __RVX0_DEFS_SVH
+6 -8
View File
@@ -1,7 +1,7 @@
module rvx0_simple_ram (
rvx0_apb.slave apb_slave
);
reg [31:0] words [0:1023];
reg [31:0] words [0:1048576];
integer i;
@@ -9,11 +9,11 @@ module rvx0_simple_ram (
if (apb_slave.prstn) begin
if (apb_slave.penable) begin
if (apb_slave.pwrite) begin
words[apb_slave.paddr[11:2]] <= apb_slave.pwdata;
words[apb_slave.paddr[22:2]] <= apb_slave.pwdata;
$display("RAM write [%x] <= %x", apb_slave.paddr, apb_slave.pwdata);
end else begin
apb_slave.prdata <= words[apb_slave.paddr[11:2]];
$display("RAM read %x <= [%x]", words[apb_slave.paddr[11:2]], apb_slave.paddr);
apb_slave.prdata <= words[apb_slave.paddr[22:2]];
$display("RAM read %x <= [%x]", words[apb_slave.paddr[22:2]], apb_slave.paddr);
end
apb_slave.pready <= 1;
@@ -21,10 +21,8 @@ module rvx0_simple_ram (
apb_slave.pready <= 0;
end
end else begin
// for (i = 0; i < 1024; ++i)
// words[i] <= 0;
words[0] <= 'h11223344;
for (i = 0; i < 1024; ++i)
words[i] <= 0;
end
end
endmodule