Skip to content

Commit

Permalink
Change: Convert ASM testsuite to use RISCV tests unit testing framework
Browse files Browse the repository at this point in the history
New: Put in place a first trap handling in control:
- misaligned address (data and instruction)
- CSR read-only register write
- decoding error
New: Replaced enable IO pin by IRQ
  • Loading branch information
dpretet committed Sep 7, 2021
1 parent c68ac60 commit 2bff838
Show file tree
Hide file tree
Showing 53 changed files with 1,439 additions and 2,036 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,7 @@ obj_dir
.DS_Store
tags
test/*/*.txt
data.v
*.gtkw
*.v
*.elf
*.asm
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
FRISCV is a SystemVerilog implementation of [RISCV ISA](https://riscv.org):

- Support RV32I & RV32E instruction sets
- 2-stage pipeline
- 3-stage pipeline
- In-order execution
- Instruction cache
- AXI4-lite instruction and data interfaces
- Machine-mode only
- Interrupt (CLIC)
- Timer
- [RISCV compliant](./test/riscv-tests/README.md)

<p align="center">
<!--img width="100" height="100" src=""-->
Expand All @@ -20,16 +23,15 @@ FRISCV is a SystemVerilog implementation of [RISCV ISA](https://riscv.org):

To be implemented next:

- Supervisor & user mode
- New ISA extensions (mult/div, FP, ...)
- Interrupt
- Timer
- Privileged instruction
- Data cache stage
- 64 bits architecture
- JTAG interface for debugging purpose
- ... and many more :)

The core is verified with SystemVerilog and Assembler, two testsuites are
present in [test](./test) folder:
The core is verified with Assembler, two testsuites are present in
[test](./test) folder:
- [In-house Assembler Testsuite](./test/asm_testsuite/README.md)
- [RISCV Compliance Testsuite](./test/riscv-tests/README.md)

Expand Down
109 changes: 95 additions & 14 deletions rtl/friscv_control.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ module friscv_control
input logic aclk,
input logic aresetn,
input logic srst,
output logic [4 -1:0] traps,
input logic irq,
output logic [5 -1:0] traps,
// Flush control
output logic flush_req,
input logic flush_ack,
Expand Down Expand Up @@ -163,6 +164,13 @@ module friscv_control
logic [XLEN -1:0] sb_mstatus;

logic [XLEN -1:0] mstatus_for_mret;
logic csr_ro_wr;
logic inst_addr_misaligned;
logic [XLEN -1:0] mcause_code;
logic [XLEN -1:0] data_addr;
logic load_misaligned;
logic store_misaligned;
logic trap_occuring;

// Logger setup
svlogger log;
Expand Down Expand Up @@ -210,7 +218,7 @@ module friscv_control
///////////////////////////////////////////////////////////////////////////
// CSR Shared bus extraction
///////////////////////////////////////////////////////////////////////////

assign sb_mtvec = csr_sb[`MTVEC+:XLEN];
assign sb_mstatus = csr_sb[`MSTATUS+:XLEN];
assign sb_mepc = csr_sb[`MEPC+:XLEN];
Expand Down Expand Up @@ -341,8 +349,8 @@ module friscv_control
//
///////////////////////////////////////////////////////////////////////////

// increment counter by 4 because we index bytes
assign pc_plus4 = pc_reg + {{(XLEN-3){1'b0}},3'b100};
// Increment counter by 4 because we index bytes
assign pc_plus4 = pc_reg + ILEN/8;

// AUIPC: Add Upper Immediate into Program Counter
assign pc_auipc = $signed(pc_reg) + $signed({imm20,12'b0});
Expand All @@ -356,7 +364,7 @@ module friscv_control
// For all branching instruction
assign pc_branching = $signed(pc_reg) + $signed({{19{imm12[11]}}, imm12, 1'b0});

// program counter switching logic
// Program counter switching logic
assign pc = (cfsm==BOOT) ? pc_reg :
// FENCE (0) or FENCE.I (1)
(|fence) ? pc_plus4 :
Expand Down Expand Up @@ -401,7 +409,7 @@ module friscv_control
// BGE: branch if greater (unsigned)
assign bgeu = (ctrl_rs1_val >= ctrl_rs2_val) ? 1'b1 : 1'b0;

// activate branching only if valid FUNCT3 received
// Activate branching only if valid FUNCT3 received
assign goto_branch = ((funct3 == `BEQ && beq) ||
(funct3 == `BNE && bne) ||
(funct3 == `BLT && blt) ||
Expand All @@ -426,7 +434,7 @@ module friscv_control
pc_reg <= {(XLEN){1'b0}};
pc_jal_saved <= {(XLEN){1'b0}};
pc_auipc_saved <= {(XLEN){1'b0}};
traps <= 4'b0;
traps <= 5'b0;
flush_fifo <= 1'b0;
arid <= {AXI_ID_W{1'b0}};
flush_req <= 1'b0;
Expand All @@ -443,7 +451,7 @@ module friscv_control
pc_reg <= {(XLEN){1'b0}};
pc_jal_saved <= {(XLEN){1'b0}};
pc_auipc_saved <= {(XLEN){1'b0}};
traps <= 4'b0;
traps <= 5'b0;
flush_fifo <= 1'b0;
arid <= {AXI_ID_W{1'b0}};
flush_req <= 1'b0;
Expand Down Expand Up @@ -480,7 +488,7 @@ module friscv_control
// and can branch and CSR are ready, stop the addr
// issuer and load it with correct address to use
//
if (~fifo_empty &&
if (~fifo_empty &&
(jump_branch || sys[`IS_ECALL] || sys[`IS_MRET] || fence[`IS_FENCEI]) &&
~cant_branch_now && csr_ready) begin
// ECALL
Expand All @@ -499,7 +507,7 @@ module friscv_control
// Manages the PC vs the different instructions to execute
if (~fifo_empty) begin

// Stop the execution when an supported instruction or
// Stop the execution when a unsupported instruction or
// a decoding error has been issued
if (inst_error) begin
log.error("Decoding error, received an unsupported instruction");
Expand All @@ -513,7 +521,7 @@ module friscv_control
mepc_wr <= 1'b1;
mepc <= pc_reg;
mcause_wr <= 1'b1;
mcause <= {{XLEN-2{1'b0}}, 2'h2};
mcause <= mcause_code;
cfsm <= RELOAD;
end

Expand Down Expand Up @@ -606,7 +614,7 @@ module friscv_control
// reboot the cache and continue to fetch the addresses from
// a new origin
RELOAD: begin
traps <= 2'b0;
traps <= 5'b0;
mepc_wr <= 1'b0;
mstatus_wr <= 1'b0;
mcause_wr <= 1'b0;
Expand All @@ -633,7 +641,7 @@ module friscv_control
// EBREAK completly stops the processor and wait for a reboot
// TODO: Understand how to manage EBREAK when software needs
EBREAK: begin
traps <= 2'b0;
traps <= 5'b0;
arvalid <= 1'b0;
flush_fifo <= 1'b0;
cfsm <= EBREAK;
Expand Down Expand Up @@ -685,7 +693,7 @@ module friscv_control

///////////////////////////////////////////////////////////////////////////
//
// Prepare CSR registers content to store during exceptions and trap
// Prepare CSR registers content to store during exceptions and traps
//
///////////////////////////////////////////////////////////////////////////

Expand All @@ -703,6 +711,79 @@ module friscv_control
1'b0, // SIE
1'b0}; // UIE

///////////////////////////////////////////////////////////////////////////
// Mause Register management, indicating to software the trap in
// machine-mode
///////////////////////////////////////////////////////////////////////////

// The access tries to modify a read-only register
assign csr_ro_wr = (csr[11:10]==2'b11 &&
// only rs1=x0 and these opcodes can be legal, else
// it modifies the targeted CSR
((rs1!=5'b0 &&
(funct3==`CSRRS || funct3==`CSRRC ||
funct3==`CSRRSI || funct3==`CSRRCI)) &&
// Any RW opcode is illegal
(funct3==`CSRRW && funct3==`CSRRWI))
) ? 1'b1 : 1'b0;

// PC is not aligned with 32 bits
assign inst_addr_misaligned = (pc[1:0] != 2'b0) ? 1'b1 : 1'b0;

// The address to access during a LOAD or a STORE
assign data_addr = $signed({{(XLEN-12){imm12[11]}}, imm12}) + $signed(ctrl_rs1_val);

// LOAD is not boundary aligned
assign load_misaligned = (opcode==`LOAD && funct3==`LH && data_addr[1:0]==2'h3) ? 1'b1 :
(opcode==`LOAD && funct3==`LHU && data_addr[1:0]==2'h3) ? 1'b1 :
(opcode==`LOAD && funct3==`LW && data_addr[1:0]!=2'b0) ? 1'b1 :
1'b0 ;

// STORE is not boundary aligned
assign store_misaligned = (opcode==`STORE && funct3==`SH && ^data_addr[1:0]==2'h3) ? 1'b1 :
1'b0 ;

///////////////////////////////////////////////////////////////////////////
//
// Synchronous exception priority in decreasing priority order:
//
// Priority | Exception Code | Description
// ----------|------------------|------------------------------------------
// Highest | 3 | Instruction address breakpoint
// | 12 | Instruction page fault
// | 1 | Instruction access fault
// | 2 | Illegal instruction
// | 0 | Instruction address misaligned
// | 8,9,11 | Environment call (U/S/M modes)
// | 3 | Environment break
// | 3 | Load/Store/AMO address breakpoint
// | 6 | Store/AMO address misaligned
// | 4 | Load address misaligned
// | 15 | Store/AMO page fault
// | 13 | Load page fault
// | 7 | Store/AMO access fault
// Lowest | 5 | Load access fault
//
///////////////////////////////////////////////////////////////////////////

// MCAUSE switching logic based on priority
assign mcause_code = (inst_addr_misaligned) ? {XLEN{1'b0}} :
(csr_ro_wr) ? {{XLEN-4{1'b0}}, 4'h1} :
(inst_error) ? {{XLEN-4{1'b0}}, 4'h2} :
(sys[`IS_ECALL]) ? {{XLEN-4{1'b0}}, 4'hB} :
(sys[`IS_EBREAK]) ? {{XLEN-4{1'b0}}, 4'h3} :
(store_misaligned) ? {{XLEN-4{1'b0}}, 4'h6} :
(load_misaligned) ? {{XLEN-4{1'b0}}, 4'h4} :
{XLEN{1'b0}};

// Triggers the trap execution
assign trap_occuring = csr_ro_wr |
inst_addr_misaligned |
load_misaligned |
store_misaligned |
inst_error;


endmodule

`resetall
45 changes: 12 additions & 33 deletions rtl/friscv_csr.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ module friscv_csr
input logic [XLEN -1:0] ctrl_mstatus,
input logic ctrl_mcause_wr,
input logic [XLEN -1:0] ctrl_mcause,
// status of the processor
output logic ro_trap,
// CSR shared bus
output logic [`CSR_SB_W -1:0] csr_sb
);
Expand Down Expand Up @@ -66,19 +64,17 @@ module friscv_csr
logic [`ZIMM_W -1:0] zimm;
logic [`CSR_W -1:0] csr;

logic csr_wren;
logic csr_rden;
logic [XLEN-1:0] oldval;
logic [XLEN-1:0] newval;
logic [XLEN-1:0] csrs [2**12-1:0];
logic csr_wren;
logic csr_rden;
logic [XLEN -1:0] oldval;
logic [XLEN -1:0] newval;

logic [`FUNCT3_W -1:0] funct3_r;
logic [`CSR_W -1:0] csr_r;
logic [`ZIMM_W -1:0] zimm_r;
logic [5 -1:0] rs1_addr_r;
logic [XLEN -1:0] rs1_val_r;

logic ro_write_access;

// -------------------
// Machine-level CSRs:
Expand Down Expand Up @@ -149,15 +145,6 @@ module friscv_csr

assign rs1_addr = rs1;

// Flags an access which will try to modify a read-only register
assign ro_write_access = (csr[11:10]==2'b11 &&
// only rs1=x0 and these opcodes will be legal
((rs1!=5'b0 &&
(funct3==`CSRRS || funct3==`CSRRC ||
funct3==`CSRRSI || funct3==`CSRRCI)) &&
// Any RW opcode is illegal
(funct3==`CSRRW && funct3==`CSRRWI))
) ? 1'b1 : 1'b0;

// ------------------------------------------------------------------------
// CSR execution machine
Expand All @@ -176,7 +163,6 @@ module friscv_csr
rs1_addr_r <= 5'b0;
rs1_val_r <= {XLEN{1'b0}};
rd_wr_addr <= 5'b0;
ro_trap <= 1'b0;
cfsm <= IDLE;
end else if (srst) begin
rd_wr_en <= 1'b0;
Expand All @@ -190,7 +176,6 @@ module friscv_csr
rs1_addr_r <= 5'b0;
rs1_val_r <= {XLEN{1'b0}};
rd_wr_addr <= 5'b0;
ro_trap <= 1'b0;
cfsm <= IDLE;
end else begin

Expand All @@ -204,20 +189,14 @@ module friscv_csr
ready <= 1'b1;

if (valid) begin
if (~ro_write_access) begin
ready <= 1'b0;
funct3_r <= funct3;
csr_r <= csr;
zimm_r <= zimm;
rs1_addr_r <= rs1;
rs1_val_r <= rs1_val;
rd_wr_addr <= rd;
ro_trap <= 1'b0;
cfsm <= COMPUTE;
end else begin
log.error("Try to write into read-only register");
ro_trap <= 1'b1;
end
ready <= 1'b0;
funct3_r <= funct3;
csr_r <= csr;
zimm_r <= zimm;
rs1_addr_r <= rs1;
rs1_val_r <= rs1_val;
rd_wr_addr <= rd;
cfsm <= COMPUTE;
end
end

Expand Down
Loading

0 comments on commit 2bff838

Please sign in to comment.