Add ecall/ebreak
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
SRC_ALL=$(wildcard src/**/*.sv)
|
||||
SRC_ALL=$(wildcard src/**/*.sv src/*.sv)
|
||||
SRC_MODULE=$(filter-out %_top.sv,$(filter-out %_tb.sv,$(SRC_ALL)))
|
||||
DEF_MODULE=$(wildcard src/*.svh)
|
||||
|
||||
|
||||
+4
-6
@@ -15,12 +15,6 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
. = 0x20000;
|
||||
|
||||
.vectors : {
|
||||
*(.text.vectors)
|
||||
}
|
||||
|
||||
. = 0x20000000;
|
||||
|
||||
.data : {
|
||||
@@ -32,4 +26,8 @@ SECTIONS {
|
||||
.bss : {
|
||||
*(.bss*)
|
||||
}
|
||||
|
||||
. = 0x20400000;
|
||||
|
||||
.end : {}
|
||||
}
|
||||
|
||||
+15
-2
@@ -4,19 +4,32 @@
|
||||
.option push
|
||||
.option norvc
|
||||
__entry:
|
||||
__reset: j fw_entry
|
||||
__exception: j fw_exception_entry
|
||||
|
||||
fw_entry:
|
||||
la sp, stack_top
|
||||
jal {firmware_main}
|
||||
fw_exception_entry:
|
||||
mv tp, sp
|
||||
la sp, exception_stack_top
|
||||
jal {firmware_exception}
|
||||
j .
|
||||
|
||||
.option pop
|
||||
.popsection // .text.entry
|
||||
|
||||
.pushsection .text.vectors
|
||||
.pushsection .text.vectors, "ax"
|
||||
.global __vector
|
||||
__vector:
|
||||
j .
|
||||
.popsection // .text.vectors
|
||||
|
||||
.pushsection .bss
|
||||
stack_bottom:
|
||||
.skip 2048
|
||||
.skip 65536
|
||||
stack_top:
|
||||
exception_stack_bottom:
|
||||
.skip 65536
|
||||
exception_stack_top:
|
||||
.popsection // .bss
|
||||
|
||||
+12
-2
@@ -35,8 +35,18 @@ unsafe extern "C" fn firmware_main() -> ! {
|
||||
loop {
|
||||
// TODO pause/system/fence instruction not implemented
|
||||
// core::hint::spin_loop();
|
||||
core::arch::asm!("nop");
|
||||
core::arch::asm!("ebreak");
|
||||
}
|
||||
}
|
||||
|
||||
global_asm!(include_str!("entry.S"), firmware_main = sym firmware_main);
|
||||
unsafe extern "C" fn firmware_exception() {
|
||||
use fmt::Write;
|
||||
let mut d = D;
|
||||
writeln!(d, "In exception handler").ok();
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
include_str!("entry.S"),
|
||||
firmware_main = sym firmware_main,
|
||||
firmware_exception = sym firmware_exception
|
||||
);
|
||||
|
||||
+17
-2
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user