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)))
|
SRC_MODULE=$(filter-out %_top.sv,$(filter-out %_tb.sv,$(SRC_ALL)))
|
||||||
DEF_MODULE=$(wildcard src/*.svh)
|
DEF_MODULE=$(wildcard src/*.svh)
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -15,12 +15,6 @@ SECTIONS {
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
. = 0x20000;
|
|
||||||
|
|
||||||
.vectors : {
|
|
||||||
*(.text.vectors)
|
|
||||||
}
|
|
||||||
|
|
||||||
. = 0x20000000;
|
. = 0x20000000;
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
@@ -32,4 +26,8 @@ SECTIONS {
|
|||||||
.bss : {
|
.bss : {
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. = 0x20400000;
|
||||||
|
|
||||||
|
.end : {}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -4,19 +4,32 @@
|
|||||||
.option push
|
.option push
|
||||||
.option norvc
|
.option norvc
|
||||||
__entry:
|
__entry:
|
||||||
|
__reset: j fw_entry
|
||||||
|
__exception: j fw_exception_entry
|
||||||
|
|
||||||
|
fw_entry:
|
||||||
la sp, stack_top
|
la sp, stack_top
|
||||||
jal {firmware_main}
|
jal {firmware_main}
|
||||||
|
fw_exception_entry:
|
||||||
|
mv tp, sp
|
||||||
|
la sp, exception_stack_top
|
||||||
|
jal {firmware_exception}
|
||||||
|
j .
|
||||||
|
|
||||||
.option pop
|
.option pop
|
||||||
.popsection // .text.entry
|
.popsection // .text.entry
|
||||||
|
|
||||||
.pushsection .text.vectors
|
.pushsection .text.vectors, "ax"
|
||||||
|
.global __vector
|
||||||
__vector:
|
__vector:
|
||||||
j .
|
j .
|
||||||
.popsection // .text.vectors
|
.popsection // .text.vectors
|
||||||
|
|
||||||
.pushsection .bss
|
.pushsection .bss
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
.skip 2048
|
.skip 65536
|
||||||
stack_top:
|
stack_top:
|
||||||
|
exception_stack_bottom:
|
||||||
|
.skip 65536
|
||||||
|
exception_stack_top:
|
||||||
.popsection // .bss
|
.popsection // .bss
|
||||||
|
|||||||
+12
-2
@@ -35,8 +35,18 @@ unsafe extern "C" fn firmware_main() -> ! {
|
|||||||
loop {
|
loop {
|
||||||
// TODO pause/system/fence instruction not implemented
|
// TODO pause/system/fence instruction not implemented
|
||||||
// core::hint::spin_loop();
|
// 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_instruction_decode;
|
||||||
wire fault_unsupported_size;
|
wire fault_unsupported_size;
|
||||||
wire fault_address_align;
|
wire fault_address_align;
|
||||||
|
wire raise_ecall;
|
||||||
|
wire raise_ebreak;
|
||||||
|
|
||||||
// Control
|
// Control
|
||||||
|
|
||||||
@@ -112,6 +114,8 @@ module rvx0_core #(
|
|||||||
rvx0_decoder decoder (
|
rvx0_decoder decoder (
|
||||||
.instruction_i (instruction),
|
.instruction_i (instruction),
|
||||||
|
|
||||||
|
.instruction_fault_o (fault_instruction_decode),
|
||||||
|
|
||||||
.v1src_o (v1src),
|
.v1src_o (v1src),
|
||||||
.v2src_o (v2src),
|
.v2src_o (v2src),
|
||||||
.vdsrc_o (vdsrc),
|
.vdsrc_o (vdsrc),
|
||||||
@@ -123,8 +127,10 @@ module rvx0_core #(
|
|||||||
.write_mem_o (need_memory_write),
|
.write_mem_o (need_memory_write),
|
||||||
.write_pc_o (write_pc),
|
.write_pc_o (write_pc),
|
||||||
.funct3_o (funct3),
|
.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 (
|
rvx0_regfile regfile (
|
||||||
@@ -204,6 +210,8 @@ module rvx0_core #(
|
|||||||
fault_instruction ||
|
fault_instruction ||
|
||||||
fault_memory_align ||
|
fault_memory_align ||
|
||||||
fault_memory_access ||
|
fault_memory_access ||
|
||||||
|
raise_ecall ||
|
||||||
|
raise_ebreak ||
|
||||||
intr_ext_i;
|
intr_ext_i;
|
||||||
|
|
||||||
assign fault_instruction = fault_instruction_decode || (fault_unsupported_size && (need_memory_read || need_memory_write));
|
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
|
end else if (fault_instruction) begin
|
||||||
mcause_write_value = MCAUSE_ILLEGAL_INSTRUCTION;
|
mcause_write_value = MCAUSE_ILLEGAL_INSTRUCTION;
|
||||||
mtval_write_value = 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
|
end else if (~need_memory_write && fault_memory_align) begin
|
||||||
mcause_write_value = MCAUSE_LOAD_ADDRESS_MISALIGNED;
|
mcause_write_value = MCAUSE_LOAD_ADDRESS_MISALIGNED;
|
||||||
mtval_write_value = alu_output;
|
mtval_write_value = alu_output;
|
||||||
@@ -271,6 +281,8 @@ module rvx0_core #(
|
|||||||
// been incremented
|
// been incremented
|
||||||
mepc_write_value = pc_value - 4;
|
mepc_write_value = pc_value - 4;
|
||||||
mtval_write_value = alu_output;
|
mtval_write_value = alu_output;
|
||||||
|
end else if (raise_ecall) begin
|
||||||
|
mcause_write_value = MCAUSE_ECALL_MMODE;
|
||||||
end else if (intr_ext_i) begin
|
end else if (intr_ext_i) begin
|
||||||
mcause_write_value = MCAUSE_INTR_EXT_MMODE | MCAUSE_INTERRUPT;
|
mcause_write_value = MCAUSE_INTR_EXT_MMODE | MCAUSE_INTERRUPT;
|
||||||
end
|
end
|
||||||
@@ -284,8 +296,11 @@ module rvx0_core #(
|
|||||||
|
|
||||||
if (fault) begin
|
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("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;
|
regfile.dump_state;
|
||||||
$finish;
|
$finish;
|
||||||
|
`endif
|
||||||
exec_stall = 1;
|
exec_stall = 1;
|
||||||
end else begin
|
end else begin
|
||||||
`ifdef RVX0_DEBUGGING
|
`ifdef RVX0_DEBUGGING
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ module rvx0_csr (
|
|||||||
always @(posedge clk_i) begin
|
always @(posedge clk_i) begin
|
||||||
if (rst_i) begin
|
if (rst_i) begin
|
||||||
// TODO set from CPU
|
// TODO set from CPU
|
||||||
mtvec_o = 'h00020000;
|
mtvec_o = 'h00001004;
|
||||||
mepc_o = 0;
|
mepc_o = 0;
|
||||||
mstatus_o = 0;
|
mstatus_o = 0;
|
||||||
mstatush_o = 0;
|
mstatush_o = 0;
|
||||||
|
|||||||
+78
-13
@@ -8,7 +8,13 @@ module rvx0_decoder (
|
|||||||
output logic write_mem_o,
|
output logic write_mem_o,
|
||||||
output logic conditional_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 instruction_fault_o,
|
||||||
|
output logic [6:0] opcode_o,
|
||||||
output wire [31:0] imm_o,
|
output wire [31:0] imm_o,
|
||||||
output wire v1src_o,
|
output wire v1src_o,
|
||||||
output wire [1:0] v2src_o,
|
output wire [1:0] v2src_o,
|
||||||
@@ -20,15 +26,13 @@ module rvx0_decoder (
|
|||||||
output wire [4:0] rs2_o,
|
output wire [4:0] rs2_o,
|
||||||
output wire [4:0] rd_o
|
output wire [4:0] rd_o
|
||||||
);
|
);
|
||||||
wire [6:0] opcode;
|
|
||||||
|
|
||||||
wire signed [11:0] imm_i_type;
|
wire signed [11:0] imm_i_type;
|
||||||
wire signed [11:0] imm_s_type;
|
wire signed [11:0] imm_s_type;
|
||||||
wire signed [12:0] imm_b_type;
|
wire signed [12:0] imm_b_type;
|
||||||
wire [19:0] imm_u_type;
|
wire [19:0] imm_u_type;
|
||||||
wire signed [20:0] imm_j_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 funct3_o = instruction_i[14:12];
|
||||||
assign funct7_o = instruction_i[31:25];
|
assign funct7_o = instruction_i[31:25];
|
||||||
|
|
||||||
@@ -42,10 +46,24 @@ module rvx0_decoder (
|
|||||||
assign rs2_o = instruction_i[24:20];
|
assign rs2_o = instruction_i[24:20];
|
||||||
assign rd_o = instruction_i[11:7];
|
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 (
|
rvx0_decoder_i decoder_i (
|
||||||
.instruction_i (instruction_i),
|
.instruction_i (instruction_i),
|
||||||
|
|
||||||
.opcode (opcode),
|
.opcode (opcode_o),
|
||||||
.funct3 (funct3_o),
|
.funct3 (funct3_o),
|
||||||
|
|
||||||
.imm_i_type (imm_i_type),
|
.imm_i_type (imm_i_type),
|
||||||
@@ -54,15 +72,62 @@ module rvx0_decoder (
|
|||||||
.imm_u_type (imm_u_type),
|
.imm_u_type (imm_u_type),
|
||||||
.imm_j_type (imm_j_type),
|
.imm_j_type (imm_j_type),
|
||||||
|
|
||||||
.write_pc_o (write_pc_o),
|
.write_pc_o (base_write_pc),
|
||||||
.write_mem_o (write_mem_o),
|
.write_mem_o (base_write_mem),
|
||||||
.conditional_o (conditional_o),
|
.conditional_o (base_conditional),
|
||||||
|
|
||||||
.instruction_fault_o (instruction_fault_o),
|
.instruction_fault_o (base_instruction_fault),
|
||||||
.imm_o (imm_o),
|
.imm_o (base_imm),
|
||||||
.v1src_o (v1src_o),
|
.v1src_o (base_v1src),
|
||||||
.v2src_o (v2src_o),
|
.v2src_o (base_v2src),
|
||||||
.vdsrc_o (vdsrc_o),
|
.vdsrc_o (base_vdsrc),
|
||||||
.aluop_o (aluop_o)
|
.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
|
endmodule
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Base rv32i instruction set decoder
|
// Base rv32i instruction set decoder minus fence/pause/ecall/ebreak
|
||||||
module rvx0_decoder_i (
|
module rvx0_decoder_i (
|
||||||
input wire [31:0] instruction_i,
|
input wire [31:0] instruction_i,
|
||||||
|
|
||||||
@@ -69,6 +69,10 @@ module rvx0_decoder_i (
|
|||||||
v2src_o = V2SRC_ZERO;
|
v2src_o = V2SRC_ZERO;
|
||||||
vdsrc_o = RDSRC_MEM;
|
vdsrc_o = RDSRC_MEM;
|
||||||
imm_o = 32'(signed'(imm_i_type));
|
imm_o = 32'(signed'(imm_i_type));
|
||||||
|
|
||||||
|
if (funct3[1:0] == 2'b11) begin
|
||||||
|
instruction_fault_o = 1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
7'b0100011: begin // store
|
7'b0100011: begin // store
|
||||||
v1src_o = V1SRC_RS1;
|
v1src_o = V1SRC_RS1;
|
||||||
@@ -76,6 +80,10 @@ module rvx0_decoder_i (
|
|||||||
vdsrc_o = RDSRC_NONE;
|
vdsrc_o = RDSRC_NONE;
|
||||||
write_mem_o = 1;
|
write_mem_o = 1;
|
||||||
imm_o = 32'(signed'(imm_s_type));
|
imm_o = 32'(signed'(imm_s_type));
|
||||||
|
|
||||||
|
if (funct3[1:0] == 2'b11) begin
|
||||||
|
instruction_fault_o = 1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
7'b0010011: begin // alu imm
|
7'b0010011: begin // alu imm
|
||||||
v1src_o = V1SRC_RS1;
|
v1src_o = V1SRC_RS1;
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ module rvx0_busmux (
|
|||||||
|
|
||||||
// RAM
|
// RAM
|
||||||
const logic [31:0] APB1_BASE = 'h20000000;
|
const logic [31:0] APB1_BASE = 'h20000000;
|
||||||
const logic [31:0] APB1_SIZE = 'h00001000;
|
const logic [31:0] APB1_SIZE = 'h00400000;
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
const logic [31:0] APB2_BASE = 'h10000000;
|
const logic [31:0] APB2_BASE = 'h10000000;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
`define __RVX0_DEFS_SVH
|
`define __RVX0_DEFS_SVH
|
||||||
|
|
||||||
`define RVX0_DEBUGGING 1
|
`define RVX0_DEBUGGING 1
|
||||||
|
// `define RVX0_CRASH_ON_EXCEPTION 1
|
||||||
|
|
||||||
const logic [1:0] RDSRC_ALU = 0;
|
const logic [1:0] RDSRC_ALU = 0;
|
||||||
const logic [1:0] RDSRC_MEM = 1;
|
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_INTR_EXT_MMODE = 11;
|
||||||
const logic [31:0] MCAUSE_INTERRUPT = 1 << 31;
|
const logic [31:0] MCAUSE_INTERRUPT = 1 << 31;
|
||||||
|
|
||||||
|
const logic IGROUP_RV32I = 0;
|
||||||
|
const logic IGROUP_SYSTEM = 1;
|
||||||
|
|
||||||
`endif // __RVX0_DEFS_SVH
|
`endif // __RVX0_DEFS_SVH
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module rvx0_simple_ram (
|
module rvx0_simple_ram (
|
||||||
rvx0_apb.slave apb_slave
|
rvx0_apb.slave apb_slave
|
||||||
);
|
);
|
||||||
reg [31:0] words [0:1023];
|
reg [31:0] words [0:1048576];
|
||||||
|
|
||||||
integer i;
|
integer i;
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@ module rvx0_simple_ram (
|
|||||||
if (apb_slave.prstn) begin
|
if (apb_slave.prstn) begin
|
||||||
if (apb_slave.penable) begin
|
if (apb_slave.penable) begin
|
||||||
if (apb_slave.pwrite) 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);
|
$display("RAM write [%x] <= %x", apb_slave.paddr, apb_slave.pwdata);
|
||||||
end else begin
|
end else begin
|
||||||
apb_slave.prdata <= words[apb_slave.paddr[11:2]];
|
apb_slave.prdata <= words[apb_slave.paddr[22:2]];
|
||||||
$display("RAM read %x <= [%x]", words[apb_slave.paddr[11:2]], apb_slave.paddr);
|
$display("RAM read %x <= [%x]", words[apb_slave.paddr[22:2]], apb_slave.paddr);
|
||||||
end
|
end
|
||||||
|
|
||||||
apb_slave.pready <= 1;
|
apb_slave.pready <= 1;
|
||||||
@@ -21,10 +21,8 @@ module rvx0_simple_ram (
|
|||||||
apb_slave.pready <= 0;
|
apb_slave.pready <= 0;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
// for (i = 0; i < 1024; ++i)
|
for (i = 0; i < 1024; ++i)
|
||||||
// words[i] <= 0;
|
words[i] <= 0;
|
||||||
|
|
||||||
words[0] <= 'h11223344;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
Reference in New Issue
Block a user