Implement privileged part of F-Extension

This commit is contained in:
Florian Zaruba 2018-09-11 17:32:22 +02:00
parent 3a9a0b7a58
commit c762c5817a
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
8 changed files with 100 additions and 34 deletions

View file

@ -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

View file

@ -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 ),

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 ),

View file

@ -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,
.*
);

View file

@ -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