mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
✨ Implement privileged part of F-Extension
This commit is contained in:
parent
3a9a0b7a58
commit
c762c5817a
8 changed files with 100 additions and 34 deletions
|
@ -32,6 +32,13 @@ package riscv;
|
|||
XLEN_128 = 2'b11
|
||||
} xlen_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
Off = 2'b00,
|
||||
Initial = 2'b01,
|
||||
Clean = 2'b10,
|
||||
Dirty = 2'b11
|
||||
} xs_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic sd; // signal dirty - read-only - hardwired zero
|
||||
logic [62:36] wpri4; // writes preserved reads ignored
|
||||
|
@ -44,8 +51,8 @@ package riscv;
|
|||
logic mxr; // make executable readable
|
||||
logic sum; // permit supervisor user memory access
|
||||
logic mprv; // modify privilege - privilege level for ld/st
|
||||
logic [1:0] xs; // extension register - hardwired to zero
|
||||
logic [1:0] fs; // extension register - hardwired to zero
|
||||
xs_t xs; // extension register - hardwired to zero
|
||||
xs_t fs; // floating point extension register
|
||||
priv_lvl_t mpp; // holds the previous privilege mode up to machine
|
||||
logic [1:0] wpri2; // writes preserved reads ignored
|
||||
logic spp; // holds the previous privilege mode up to supervisor
|
||||
|
|
|
@ -135,6 +135,7 @@ module ariane #(
|
|||
// --------------
|
||||
// CSR Commit
|
||||
logic csr_commit_commit_ex;
|
||||
logic dirty_fp_state;
|
||||
// LSU Commit
|
||||
logic lsu_commit_commit_ex;
|
||||
logic lsu_commit_ready_ex_commit;
|
||||
|
@ -154,6 +155,7 @@ module ariane #(
|
|||
// CSR <-> *
|
||||
// --------------
|
||||
logic [4:0] fflags_csr_commit;
|
||||
riscv::xs_t fs;
|
||||
logic [2:0] frm_csr_id_issue_ex;
|
||||
logic enable_translation_csr_ex;
|
||||
logic en_ld_st_translation_csr_ex;
|
||||
|
@ -255,6 +257,7 @@ module ariane #(
|
|||
.issue_instr_ack_i ( issue_instr_issue_id ),
|
||||
|
||||
.priv_lvl_i ( priv_lvl ),
|
||||
.fs_i ( fs ),
|
||||
.frm_i ( frm_csr_id_issue_ex ),
|
||||
.debug_mode_i ( debug_mode_csr_id ),
|
||||
.tvm_i ( tvm_csr_id ),
|
||||
|
@ -415,8 +418,9 @@ module ariane #(
|
|||
// ---------
|
||||
commit_stage commit_stage_i (
|
||||
.halt_i ( halt_ctrl ),
|
||||
.flush_dcache_i ( dcache_flush_ctrl_cache ),
|
||||
.flush_dcache_i ( dcache_flush_ctrl_cache ),
|
||||
.exception_o ( ex_commit ),
|
||||
.dirty_fp_state_o ( dirty_fp_state ),
|
||||
.debug_mode_i ( debug_mode_csr_id ),
|
||||
.debug_req_i ( debug_req_i ),
|
||||
.single_step_i ( single_step_csr_commit ),
|
||||
|
@ -455,6 +459,7 @@ module ariane #(
|
|||
.ex_i ( ex_commit ),
|
||||
.csr_op_i ( csr_op_commit_csr ),
|
||||
.csr_write_fflags_i ( csr_write_fflags_commit_cs ),
|
||||
.dirty_fp_state_i ( dirty_fp_state ),
|
||||
.csr_addr_i ( csr_addr_ex_csr ),
|
||||
.csr_wdata_i ( csr_wdata_commit_csr ),
|
||||
.csr_rdata_o ( csr_rdata_csr_commit ),
|
||||
|
@ -465,6 +470,7 @@ module ariane #(
|
|||
.set_debug_pc_o ( set_debug_pc ),
|
||||
.trap_vector_base_o ( trap_vector_base_commit_pcgen ),
|
||||
.priv_lvl_o ( priv_lvl ),
|
||||
.fs_o ( fs ),
|
||||
.fflags_o ( fflags_csr_commit ),
|
||||
.frm_o ( frm_csr_id_issue_ex ),
|
||||
.ld_st_priv_lvl_o ( ld_st_priv_lvl_csr_ex ),
|
||||
|
|
|
@ -21,6 +21,7 @@ module commit_stage #(
|
|||
input logic halt_i, // request to halt the core
|
||||
input logic flush_dcache_i, // request to flush dcache -> also flush the pipeline
|
||||
output exception_t exception_o, // take exception to controller
|
||||
output logic dirty_fp_state_o, // mark the F state as dirty
|
||||
input logic debug_mode_i, // we are in debug mode
|
||||
input logic debug_req_i, // debug unit is requesting to enter debug mode
|
||||
input logic single_step_i, // we are in single step debug mode
|
||||
|
@ -55,6 +56,7 @@ module commit_stage #(
|
|||
assign waddr_o[1] = commit_instr_i[1].rd[4:0];
|
||||
|
||||
assign pc_o = commit_instr_i[0].pc;
|
||||
assign dirty_fp_state_o = |we_fpr_o;
|
||||
|
||||
// -------------------
|
||||
// Commit Instruction
|
||||
|
@ -69,7 +71,6 @@ module commit_stage #(
|
|||
we_gpr_o[0] = 1'b0;
|
||||
we_gpr_o[1] = 1'b0;
|
||||
we_fpr_o = '{default: 1'b0};
|
||||
|
||||
commit_lsu_o = 1'b0;
|
||||
commit_csr_o = 1'b0;
|
||||
wdata_o[0] = commit_instr_i[0].result;
|
||||
|
|
|
@ -21,7 +21,6 @@ module csr_regfile #(
|
|||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic time_irq_i, // Timer threw a interrupt
|
||||
|
||||
// send a flush request out if a CSR with a side effect has changed (e.g. written)
|
||||
output logic flush_o,
|
||||
output logic halt_csr_o, // halt requested
|
||||
|
@ -39,6 +38,7 @@ module csr_regfile #(
|
|||
input logic [11:0] csr_addr_i, // Address of the register to read/write
|
||||
input logic [63:0] csr_wdata_i, // Write data in
|
||||
output logic [63:0] csr_rdata_o, // Read data out
|
||||
input logic dirty_fp_state_i, // Mark the FP sate as dirty
|
||||
input logic csr_write_fflags_i, // Write fflags register e.g.: we are retiring a floating point instruction
|
||||
input logic [63:0] pc_i, // PC of instruction accessing the CSR
|
||||
output exception_t csr_exception_o, // attempts to access a CSR without appropriate privilege
|
||||
|
@ -50,6 +50,7 @@ module csr_regfile #(
|
|||
output logic [63:0] trap_vector_base_o, // Output base of exception vector, correct CSR is output (mtvec, stvec)
|
||||
output riscv::priv_lvl_t priv_lvl_o, // Current privilege level the CPU is in
|
||||
// FPU
|
||||
output riscv::xs_t fs_o, // Floating point extension status
|
||||
output logic [4:0] fflags_o, // Floating-Point Accured Exceptions
|
||||
output logic [2:0] frm_o, // Floating-Point Dynamic Rounding Mode
|
||||
// MMU
|
||||
|
@ -91,12 +92,14 @@ module csr_regfile #(
|
|||
logic mret; // return from M-mode exception
|
||||
logic sret; // return from S-mode exception
|
||||
logic dret; // return from debug mode
|
||||
|
||||
// CSR write causes us to mark the FPU state as dirty
|
||||
logic dirty_fp_state_csr;
|
||||
riscv::csr_t csr_addr;
|
||||
// ----------------
|
||||
// Assignments
|
||||
// ----------------
|
||||
assign csr_addr = riscv::csr_t'(csr_addr_i);
|
||||
assign fs_o = mstatus_q.fs;
|
||||
// ----------------
|
||||
// CSR Registers
|
||||
// ----------------
|
||||
|
@ -153,9 +156,27 @@ module csr_regfile #(
|
|||
|
||||
if (csr_read) begin
|
||||
case (csr_addr.address)
|
||||
riscv::CSR_FFLAGS: csr_rdata = {59'b0, fcsr_q.fflags};
|
||||
riscv::CSR_FRM: csr_rdata = {61'b0, fcsr_q.frm};
|
||||
riscv::CSR_FCSR: csr_rdata = {32'b0, fcsr_q};
|
||||
riscv::CSR_FFLAGS: begin
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
read_access_exception = 1'b1;
|
||||
end else begin
|
||||
csr_rdata = {59'b0, fcsr_q.fflags};
|
||||
end
|
||||
end
|
||||
riscv::CSR_FRM: begin
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
read_access_exception = 1'b1;
|
||||
end else begin
|
||||
csr_rdata = {61'b0, fcsr_q.frm};
|
||||
end
|
||||
end
|
||||
riscv::CSR_FCSR: begin
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
read_access_exception = 1'b1;
|
||||
end else begin
|
||||
csr_rdata = {32'b0, fcsr_q};
|
||||
end
|
||||
end
|
||||
// debug registers
|
||||
riscv::CSR_DCSR: csr_rdata = {32'b0, dcsr_q};
|
||||
riscv::CSR_DPC: csr_rdata = dpc_q;
|
||||
|
@ -287,25 +308,40 @@ module csr_regfile #(
|
|||
stval_d = stval_q;
|
||||
satp_d = satp_q;
|
||||
en_ld_st_translation_d = en_ld_st_translation_q;
|
||||
|
||||
dirty_fp_state_csr = 1'b0;
|
||||
// check for correct access rights and that we are writing
|
||||
if (csr_we) begin
|
||||
case (csr_addr.address)
|
||||
// Floating-Point
|
||||
riscv::CSR_FFLAGS: begin
|
||||
fcsr_d.fflags = csr_wdata[4:0];
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
update_access_exception = 1'b1;
|
||||
end else begin
|
||||
dirty_fp_state_csr = 1'b1;
|
||||
fcsr_d.fflags = csr_wdata[4:0];
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
end
|
||||
end
|
||||
riscv::CSR_FRM: begin
|
||||
fcsr_d.frm = csr_wdata[2:0];
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
update_access_exception = 1'b1;
|
||||
end else begin
|
||||
dirty_fp_state_csr = 1'b1;
|
||||
fcsr_d.frm = csr_wdata[2:0];
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
end
|
||||
end
|
||||
riscv::CSR_FCSR: begin
|
||||
fcsr_d[7:0] = csr_wdata[7:0]; // ignore writes to reserved space
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
update_access_exception = 1'b1;
|
||||
end else begin
|
||||
dirty_fp_state_csr = 1'b1;
|
||||
fcsr_d[7:0] = csr_wdata[7:0]; // ignore writes to reserved space
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
end
|
||||
end
|
||||
// debug CSR
|
||||
riscv::CSR_DCSR: begin
|
||||
|
@ -330,10 +366,13 @@ module csr_regfile #(
|
|||
// also hardwire the registers for sstatus
|
||||
mstatus_d.sxl = riscv::XLEN_64;
|
||||
mstatus_d.uxl = riscv::XLEN_64;
|
||||
// hardwired zero registers
|
||||
mstatus_d.sd = 1'b0;
|
||||
mstatus_d.xs = 2'b0;
|
||||
mstatus_d.fs = 2'b0;
|
||||
// hardwired extension registers
|
||||
mstatus_d.sd = (&mstatus_q.xs) | (&mstatus_q.fs);
|
||||
mstatus_d.xs = riscv::Off;
|
||||
// hardwire to zero if floating point extension is not present
|
||||
if (!FP_PRESENT) begin
|
||||
mstatus_d.fs = riscv::Off;
|
||||
end
|
||||
mstatus_d.upie = 1'b0;
|
||||
mstatus_d.uie = 1'b0;
|
||||
// not all fields of mstatus can be written
|
||||
|
@ -390,9 +429,11 @@ module csr_regfile #(
|
|||
mstatus_d.sxl = riscv::XLEN_64;
|
||||
mstatus_d.uxl = riscv::XLEN_64;
|
||||
// hardwired zero registers
|
||||
mstatus_d.sd = 1'b0;
|
||||
mstatus_d.xs = 2'b0;
|
||||
mstatus_d.fs = 2'b0;
|
||||
mstatus_d.sd = (&mstatus_q.xs) | (&mstatus_q.fs);
|
||||
mstatus_d.xs = riscv::Off;
|
||||
if (!FP_PRESENT) begin
|
||||
mstatus_d.fs = riscv::Off;
|
||||
end
|
||||
mstatus_d.upie = 1'b0;
|
||||
mstatus_d.uie = 1'b0;
|
||||
// this register has side-effects on other registers, flush the pipeline
|
||||
|
@ -451,6 +492,11 @@ module csr_regfile #(
|
|||
endcase
|
||||
end
|
||||
|
||||
// mark the floating point extension register as dirty
|
||||
if (FP_PRESENT && (dirty_fp_state_csr || dirty_fp_state_i)) begin
|
||||
mstatus_d.fs = riscv::Dirty;
|
||||
end
|
||||
|
||||
// write the floating point status register
|
||||
if (csr_write_fflags_i)
|
||||
fcsr_d.fflags = csr_wdata_i[4:0] | fcsr_q.fflags;
|
||||
|
|
|
@ -30,6 +30,7 @@ module decoder (
|
|||
// From CSR
|
||||
input riscv::priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input logic debug_mode_i, // we are in debug mode
|
||||
input riscv::xs_t fs_i, // floating point extension status
|
||||
input logic [2:0] frm_i, // floating-point dynamic rounding mode
|
||||
input logic tvm_i, // trap virtual memory
|
||||
input logic tw_i, // timeout wait
|
||||
|
@ -244,7 +245,8 @@ module decoder (
|
|||
// Vectorial Floating-Point Reg-Reg Operations
|
||||
// --------------------------------------------
|
||||
if (instr.rvftype.funct2 == 2'b10) begin // Prefix 10 for all Xfvec ops
|
||||
if (FP_PRESENT & XFVEC) begin // only generate decoder if FP extensions are enabled (static)
|
||||
// only generate decoder if FP extensions are enabled (static)
|
||||
if (FP_PRESENT && XFVEC && fs_i != riscv::Off) begin
|
||||
automatic logic allow_replication; // control honoring of replication flag
|
||||
|
||||
instruction_o.fu = FPU_VEC; // Same unit, but sets 'vectorial' signal
|
||||
|
@ -618,7 +620,7 @@ module decoder (
|
|||
// Floating-Point Load/store
|
||||
// --------------------------------
|
||||
riscv::OpcodeStoreFp: begin
|
||||
if (FP_PRESENT) begin // only generate decoder if FP extensions are enabled (static)
|
||||
if (FP_PRESENT && fs_i != riscv::Off) begin // only generate decoder if FP extensions are enabled (static)
|
||||
instruction_o.fu = STORE;
|
||||
imm_select = SIMM;
|
||||
instruction_o.rs1 = instr.stype.rs1;
|
||||
|
@ -641,7 +643,7 @@ module decoder (
|
|||
end
|
||||
|
||||
riscv::OpcodeLoadFp: begin
|
||||
if (FP_PRESENT) begin // only generate decoder if FP extensions are enabled (static)
|
||||
if (FP_PRESENT && fs_i != riscv::Off) begin // only generate decoder if FP extensions are enabled (static)
|
||||
instruction_o.fu = LOAD;
|
||||
imm_select = IIMM;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
|
@ -670,7 +672,7 @@ module decoder (
|
|||
riscv::OpcodeMsub,
|
||||
riscv::OpcodeNmsub,
|
||||
riscv::OpcodeNmadd: begin
|
||||
if (FP_PRESENT) begin // only generate decoder if FP extensions are enabled (static)
|
||||
if (FP_PRESENT && fs_i != riscv::Off) begin // only generate decoder if FP extensions are enabled (static)
|
||||
instruction_o.fu = FPU;
|
||||
instruction_o.rs1 = instr.r4type.rs1;
|
||||
instruction_o.rs2 = instr.r4type.rs2;
|
||||
|
@ -723,7 +725,7 @@ module decoder (
|
|||
end
|
||||
|
||||
riscv::OpcodeOpFp: begin
|
||||
if (FP_PRESENT) begin // only generate decoder if FP extensions are enabled (static)
|
||||
if (FP_PRESENT && fs_i != riscv::Off) begin // only generate decoder if FP extensions are enabled (static)
|
||||
instruction_o.fu = FPU;
|
||||
instruction_o.rs1 = instr.rftype.rs1;
|
||||
instruction_o.rs2 = instr.rftype.rs2;
|
||||
|
|
|
@ -122,7 +122,8 @@ module ex_stage #(
|
|||
// Branch Engine
|
||||
// --------------------
|
||||
branch_unit branch_unit_i (
|
||||
.fu_valid_i ( alu_valid_i || lsu_valid_i || csr_valid_i || mult_valid_i), // any functional unit is valid, check that there is no accidental mis-predict
|
||||
// any functional unit is valid, check that there is no accidental mis-predict
|
||||
.fu_valid_i ( alu_valid_i || lsu_valid_i || csr_valid_i || mult_valid_i || fpu_valid_i ),
|
||||
.branch_comp_res_i ( alu_branch_res ),
|
||||
.*
|
||||
);
|
||||
|
@ -139,7 +140,7 @@ module ex_stage #(
|
|||
// FPU
|
||||
// ----------------
|
||||
generate
|
||||
if( FP_PRESENT ) begin : fpu_gen
|
||||
if (FP_PRESENT) begin : fpu_gen
|
||||
fpu_wrap fpu_i (
|
||||
.operand_c_i ( imm_i ),
|
||||
.result_o ( fpu_result_o ),
|
||||
|
|
|
@ -32,6 +32,7 @@ module id_stage (
|
|||
input logic issue_instr_ack_i, // issue stage acknowledged sampling of instructions
|
||||
// from CSR file
|
||||
input riscv::priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input riscv::xs_t fs_i, // floating point extension status
|
||||
input logic [2:0] frm_i, // floating-point dynamic rounding mode
|
||||
|
||||
input logic debug_mode_i, // we are in debug mode
|
||||
|
@ -92,6 +93,8 @@ module id_stage (
|
|||
.ex_i ( fetch_entry.ex ),
|
||||
.instruction_o ( decoded_instruction ),
|
||||
.is_control_flow_instr_o ( is_control_flow_instr ),
|
||||
.fs_i,
|
||||
.frm_i,
|
||||
.*
|
||||
);
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ module issue_read_operands #(
|
|||
// use the zimm as operand a
|
||||
if (issue_instr_i.use_zimm) begin
|
||||
// zero extend operand a
|
||||
operand_a_n = {52'b0, issue_instr_i.rs1};
|
||||
operand_a_n = {52'b0, issue_instr_i.rs1[4:0]};
|
||||
end
|
||||
// or is it an immediate (including PC), this is not the case for a store and control flow instructions
|
||||
if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE) && (issue_instr_i.fu != CTRL_FLOW)) begin
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue