1152 lines
40 KiB
Plaintext
1152 lines
40 KiB
Plaintext
// Copyright (c) 2013-2020 Bluespec, Inc. All Rights Reserved
|
|
//-
|
|
// RVFI_DII + CHERI modifications:
|
|
// Copyright (c) 2020 Jonathan Woodruff
|
|
// All rights reserved.
|
|
//
|
|
// This software was developed by SRI International and the University of
|
|
// Cambridge Computer Laboratory (Department of Computer Science and
|
|
// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
|
|
// DARPA SSITH research programme.
|
|
//
|
|
// This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet").
|
|
//-
|
|
|
|
// ================================================================
|
|
// ISA defs for UC Berkeley RISC V
|
|
//
|
|
// References (from riscv.org):
|
|
// The RISC-V Instruction Set Manual
|
|
// Volume I: Unprivileged ISA
|
|
// Document Version 20181106-Base-Ratification
|
|
// November 6, 2018
|
|
//
|
|
// The RISC-V Instruction Set Manual
|
|
// Volume II: Privileged Architecture
|
|
// Document Version 20181203-Base-Ratification
|
|
// December 3, 2018
|
|
//
|
|
// ================================================================
|
|
|
|
package ISA_Decls;
|
|
|
|
// ================================================================
|
|
// BSV library imports
|
|
|
|
import DefaultValue :: *;
|
|
import Vector :: *;
|
|
import BuildVector :: *;
|
|
|
|
// ================================================================
|
|
// BSV project imports
|
|
|
|
// None
|
|
|
|
// ================================================================
|
|
|
|
typedef 3 NO_OF_PRIVMODES;
|
|
|
|
// ================================================================
|
|
// XLEN and related constants
|
|
|
|
`ifdef RV32
|
|
|
|
typedef 32 XLEN;
|
|
|
|
`elsif RV64
|
|
|
|
typedef 64 XLEN;
|
|
|
|
`endif
|
|
|
|
typedef TMul #(2, XLEN) XLEN_2; // Double-width for multiplications
|
|
typedef TSub #(XLEN, 2) XLEN_MINUS_2;// XLEN-2 for MTVEC base width
|
|
|
|
Integer xlen = valueOf (XLEN);
|
|
|
|
typedef enum { RV32, RV64 } RV_Version deriving (Eq, Bits);
|
|
|
|
RV_Version rv_version = ( (valueOf (XLEN) == 32) ? RV32 : RV64 );
|
|
|
|
// ----------------
|
|
// We're evolving the code to use WordXL/IntXL instead of Word/Word_S
|
|
// because of the widespread and inconsistent use of 'word' in the field.
|
|
// All existing uses of 'Word/Word_S' should migrate towards WordXL/IntXL.
|
|
// All new code should only use WordXL/IntXL
|
|
// Eventually, we should remove Word and Word_S
|
|
|
|
typedef Bit #(XLEN) WordXL; // Raw (unsigned) register data
|
|
typedef Int #(XLEN) IntXL; // Signed register data
|
|
|
|
typedef Bit #(XLEN) Word; // Raw (unsigned) register data // OLD: migrate to WordXL
|
|
typedef Int #(XLEN) Word_S; // Signed register data // OLD: migrate to IntXL
|
|
|
|
typedef WordXL Addr; // addresses/pointers
|
|
|
|
// ----------------
|
|
|
|
typedef 8 Bits_per_Byte;
|
|
typedef Bit #(Bits_per_Byte) Byte;
|
|
|
|
typedef XLEN Bits_per_Word; // REDUNDANT to XLEN
|
|
|
|
typedef TDiv #(Bits_per_Word, Bits_per_Byte) Bytes_per_Word; // OLD ('WordXL')
|
|
typedef TLog #(Bytes_per_Word) Bits_per_Byte_in_Word; // OLD ('WordXL')
|
|
typedef Bit #(Bits_per_Byte_in_Word) Byte_in_Word; // OLD ('WordXL')
|
|
typedef Vector #(Bytes_per_Word, Byte) Word_B; // OLD ('WordXL')
|
|
|
|
typedef TDiv #(XLEN, Bits_per_Byte) Bytes_per_WordXL;
|
|
typedef TLog #(Bytes_per_WordXL) Bits_per_Byte_in_WordXL;
|
|
typedef Bit #(Bits_per_Byte_in_WordXL) Byte_in_WordXL;
|
|
typedef Vector #(Bytes_per_WordXL, Byte) WordXL_B;
|
|
|
|
typedef XLEN Bits_per_Addr;
|
|
typedef TDiv #(Bits_per_Addr, Bits_per_Byte) Bytes_per_Addr;
|
|
|
|
Integer bits_per_byte = valueOf (Bits_per_Byte);
|
|
|
|
Integer bytes_per_wordxl = valueOf (Bytes_per_WordXL);
|
|
Integer bits_per_byte_in_wordxl = valueOf (Bits_per_Byte_in_WordXL);
|
|
|
|
Integer addr_lo_byte_in_wordxl = 0;
|
|
Integer addr_hi_byte_in_wordxl = addr_lo_byte_in_wordxl + bits_per_byte_in_wordxl - 1;
|
|
|
|
function Byte_in_Word fn_addr_to_byte_in_wordxl (Addr a);
|
|
return a [addr_hi_byte_in_wordxl : addr_lo_byte_in_wordxl ];
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// FLEN and related constants, for floating point data
|
|
// Can have one or two fpu sizes (should they be merged sooner than later ?).
|
|
|
|
// Cannot define ISA_D unless ISA_F is also defined
|
|
// ISA_F - 32 bit FPU
|
|
// ISA_D - 64 bit FPU
|
|
|
|
`ifdef ISA_F
|
|
|
|
`ifdef ISA_D // ISA_D precludes ISA_F
|
|
typedef 64 FLEN;
|
|
Bool hasFpu32 = False;
|
|
Bool hasFpu64 = True;
|
|
`else
|
|
typedef 32 FLEN;
|
|
Bool hasFpu32 = True;
|
|
Bool hasFpu64 = False;
|
|
`endif
|
|
|
|
typedef Bit #(FLEN) FP_Value;
|
|
typedef Bit #(FLEN) WordFL; // Floating point data
|
|
|
|
typedef TDiv #(FLEN, Bits_per_Byte) Bytes_per_WordFL;
|
|
typedef TLog #(Bytes_per_WordFL) Bits_per_Byte_in_WordFL;
|
|
typedef Bit #(Bits_per_Byte_in_WordFL) Byte_in_WordFL;
|
|
typedef Vector #(Bytes_per_WordFL, Byte) WordFL_B;
|
|
|
|
`endif
|
|
|
|
`ifdef ISA_F
|
|
`ifdef ISA_D
|
|
`define ISA_F_AND_D
|
|
`endif
|
|
`endif
|
|
|
|
// ================================================================
|
|
// Tokens are used for signalling/synchronization, and have no payload
|
|
|
|
typedef Bit #(0) Token;
|
|
|
|
// ================================================================
|
|
// Instruction fields
|
|
|
|
// This is used for encoding Tandem Verifier traces
|
|
typedef enum { ISIZE16BIT, ISIZE32BIT
|
|
} ISize deriving (Bits, Eq, FShow);
|
|
|
|
typedef Bit #(32) Instr;
|
|
typedef Bit #(7) Opcode;
|
|
typedef Bit #(5) RegName; // 32 registers, 0..31
|
|
typedef 32 NumRegs;
|
|
Integer numRegs = valueOf (NumRegs);
|
|
|
|
Instr illegal_instr = 32'h0000_0000;
|
|
|
|
function Opcode instr_opcode (Instr x); return x [6:0]; endfunction
|
|
|
|
function Bit #(2) instr_funct2 (Instr x); return x [26:25]; endfunction
|
|
function Bit #(3) instr_funct3 (Instr x); return x [14:12]; endfunction
|
|
function Bit #(5) instr_funct5 (Instr x); return x [31:27]; endfunction
|
|
function Bit #(7) instr_funct7 (Instr x); return x [31:25]; endfunction
|
|
function Bit #(10) instr_funct10 (Instr x); return { x [31:25], x [14:12] }; endfunction
|
|
function Bit #(2) instr_fmt (Instr x); return x [26:25]; endfunction
|
|
|
|
function RegName instr_rd (Instr x); return x [11:7]; endfunction
|
|
function RegName instr_rs1 (Instr x); return x [19:15]; endfunction
|
|
function RegName instr_rs2 (Instr x); return x [24:20]; endfunction
|
|
function RegName instr_rs3 (Instr x); return x [31:27]; endfunction
|
|
function CSR_Addr instr_csr (Instr x); return unpack(x [31:20]); endfunction
|
|
|
|
function Bit #(12) instr_I_imm12 (Instr x);
|
|
return x [31:20];
|
|
endfunction
|
|
|
|
function Bit #(12) instr_S_imm12 (Instr x);
|
|
return { x [31:25], x [11:7] };
|
|
endfunction
|
|
|
|
function Bit #(13) instr_SB_imm13 (Instr x);
|
|
return { x [31], x [7], x [30:25], x [11:8], 1'b0 };
|
|
endfunction
|
|
|
|
function Bit #(20) instr_U_imm20 (Instr x);
|
|
return x [31:12];
|
|
endfunction
|
|
|
|
function Bit #(21) instr_UJ_imm21 (Instr x);
|
|
return { x [31], x [19:12], x [20], x [30:21], 1'b0 };
|
|
endfunction
|
|
|
|
// For FENCE decode
|
|
function Bit #(4) instr_pred (Instr x); return x [27:24]; endfunction
|
|
function Bit #(4) instr_succ (Instr x); return x [23:20]; endfunction
|
|
|
|
// For AMO decode
|
|
function Bit #(2) instr_aqrl (Instr x); return x [26:25]; endfunction
|
|
|
|
// ----------------
|
|
// Decoded instructions
|
|
|
|
typedef struct {
|
|
Opcode opcode;
|
|
|
|
RegName rd;
|
|
RegName rs1;
|
|
RegName rs2;
|
|
RegName rs3;
|
|
CSR_Addr csr;
|
|
|
|
Bit #(3) funct3;
|
|
Bit #(5) funct5;
|
|
Bit #(7) funct7;
|
|
Bit #(10) funct10;
|
|
|
|
Bit #(12) imm12_I;
|
|
Bit #(12) imm12_S;
|
|
Bit #(13) imm13_SB;
|
|
Bit #(20) imm20_U;
|
|
Bit #(21) imm21_UJ;
|
|
|
|
Bit #(4) pred;
|
|
Bit #(4) succ;
|
|
|
|
Bit #(2) aqrl;
|
|
} Decoded_Instr
|
|
deriving (FShow, Bits);
|
|
|
|
function Decoded_Instr fv_decode (Instr instr);
|
|
return Decoded_Instr {opcode: instr_opcode (instr),
|
|
|
|
rd: instr_rd (instr),
|
|
rs1: instr_rs1 (instr),
|
|
rs2: instr_rs2 (instr),
|
|
rs3: instr_rs3 (instr),
|
|
csr: instr_csr (instr),
|
|
|
|
funct3: instr_funct3 (instr),
|
|
funct5: instr_funct5 (instr),
|
|
funct7: instr_funct7 (instr),
|
|
funct10: instr_funct10 (instr),
|
|
|
|
imm12_I: instr_I_imm12 (instr),
|
|
imm12_S: instr_S_imm12 (instr),
|
|
imm13_SB: instr_SB_imm13 (instr),
|
|
imm20_U: instr_U_imm20 (instr),
|
|
imm21_UJ: instr_UJ_imm21 (instr),
|
|
|
|
pred: instr_pred (instr),
|
|
succ: instr_succ (instr),
|
|
|
|
aqrl: instr_aqrl (instr)
|
|
};
|
|
endfunction
|
|
|
|
// Decodes if we need to read the GPR register file. This step becomes necessary
|
|
// on integrating the FPU as certain instruction now do not require the GPR
|
|
// anymore
|
|
// IsFP, GPRRd
|
|
// function Tuple2# (Bool, Bool) fv_decode_gpr_read (Decoded_Instr di);
|
|
// `ifdef ISA_F
|
|
// // FP_LD and FP_ST are treated as non-FP operation as far as GPR reads
|
|
// // are concerned
|
|
// if (di.opcode != op_FP) begin
|
|
// return (tuple2 (False, True)); // Regular op with GPR read
|
|
// end
|
|
//
|
|
// // This is an FP operation. The following f5 values would work for F and
|
|
// // D subsets
|
|
// else begin
|
|
// if ( (di.funct5 == f5_FCVT_F_X)
|
|
// || (di.funct5 == f5_FMV_W_X))
|
|
// return (tuple2 (True, True)); // FP op with GPR read
|
|
// else
|
|
// return (tuple2 (True, False));// FP op with no GPR read
|
|
// end
|
|
// `else
|
|
// return (tuple2 (False, True)); // Regular op with GPR read
|
|
// `endif
|
|
// endfunction
|
|
|
|
// ================================================================
|
|
// Instruction constructors
|
|
// Used in 'C' decode to construct equivalent 32-bit instructions
|
|
|
|
// R-type
|
|
function Instr mkInstr_R_type (Bit #(7) funct7, RegName rs2, RegName rs1, Bit #(3) funct3, RegName rd, Bit #(7) opcode);
|
|
let instr = { funct7, rs2, rs1, funct3, rd, opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// I-type
|
|
function Instr mkInstr_I_type (Bit #(12) imm12, RegName rs1, Bit #(3) funct3, RegName rd, Bit #(7) opcode);
|
|
let instr = { imm12, rs1, funct3, rd, opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// S-type
|
|
|
|
function Instr mkInstr_S_type (Bit #(12) imm12, RegName rs2, RegName rs1, Bit #(3) funct3, Bit #(7) opcode);
|
|
let instr = { imm12 [11:5], rs2, rs1, funct3, imm12 [4:0], opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// B-type
|
|
function Instr mkInstr_B_type (Bit #(13) imm13, RegName rs2, RegName rs1, Bit #(3) funct3, Bit #(7) opcode);
|
|
let instr = { imm13 [12], imm13 [10:5], rs2, rs1, funct3, imm13 [4:1], imm13 [11], opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// U-type
|
|
function Instr mkInstr_U_type (Bit #(20) imm20, RegName rd, Bit #(7) opcode);
|
|
let instr = { imm20, rd, opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// J-type
|
|
function Instr mkInstr_J_type (Bit #(21) imm21, RegName rd, Bit #(7) opcode);
|
|
let instr = { imm21 [20], imm21 [10:1], imm21 [11], imm21 [19:12], rd, opcode };
|
|
return instr;
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// Symbolic register names
|
|
|
|
RegName x0 = 0; RegName x1 = 1; RegName x2 = 2; RegName x3 = 3;
|
|
RegName x4 = 4; RegName x5 = 5; RegName x6 = 6; RegName x7 = 7;
|
|
RegName x8 = 8; RegName x9 = 9; RegName x10 = 10; RegName x11 = 11;
|
|
RegName x12 = 12; RegName x13 = 13; RegName x14 = 14; RegName x15 = 15;
|
|
RegName x16 = 16; RegName x17 = 17; RegName x18 = 18; RegName x19 = 19;
|
|
RegName x20 = 20; RegName x21 = 21; RegName x22 = 22; RegName x23 = 23;
|
|
RegName x24 = 24; RegName x25 = 25; RegName x26 = 26; RegName x27 = 27;
|
|
RegName x28 = 28; RegName x29 = 29; RegName x30 = 30; RegName x31 = 31;
|
|
|
|
// Register names used in calling convention
|
|
|
|
RegName reg_zero = 0;
|
|
RegName reg_ra = 1;
|
|
RegName reg_sp = 2;
|
|
RegName reg_gp = 3;
|
|
RegName reg_tp = 4;
|
|
|
|
RegName reg_t0 = 5; RegName reg_t1 = 6; RegName reg_t2 = 7;
|
|
RegName reg_fp = 8;
|
|
RegName reg_s0 = 8; RegName reg_s1 = 9;
|
|
|
|
RegName reg_a0 = 10; RegName reg_a1 = 11;
|
|
RegName reg_v0 = 10; RegName reg_v1 = 11;
|
|
|
|
RegName reg_a2 = 12; RegName reg_a3 = 13; RegName reg_a4 = 14; RegName reg_a5 = 15;
|
|
RegName reg_a6 = 16; RegName reg_a7 = 17;
|
|
|
|
RegName reg_s2 = 18; RegName reg_s3 = 19; RegName reg_s4 = 20; RegName reg_s5 = 21;
|
|
RegName reg_s6 = 22; RegName reg_s7 = 23; RegName reg_s8 = 24; RegName reg_s9 = 25;
|
|
RegName reg_s10 = 26; RegName reg_s11 = 27;
|
|
|
|
RegName reg_t3 = 28; RegName reg_t4 = 29; RegName reg_t5 = 30; RegName reg_t6 = 31;
|
|
|
|
// ----------------
|
|
// Is 'r' a standard register for PC save/restore on call/return?
|
|
// This function is used in branch-predictors for managing the return-address stack.
|
|
|
|
function Bool fn_reg_is_link (RegName r);
|
|
return ((r == x1) || (r == x5));
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// Kinds of memory access (excluding AMOs)
|
|
|
|
typedef enum { Access_RWX_R, Access_RWX_W, Access_RWX_X } Access_RWX
|
|
deriving (Eq, Bits, FShow);
|
|
|
|
// ================================================================
|
|
// Data sizes for LOAD/STORE
|
|
|
|
typedef enum {BITS8,
|
|
BITS16,
|
|
BITS32,
|
|
BITS64 // Even in RV32, to allow for Double (floating point)
|
|
} Mem_Data_Size
|
|
deriving (Eq, Bits, FShow);
|
|
|
|
// ================================================================
|
|
// LOAD/STORE instructions
|
|
|
|
typedef Bit #(2) MemReqSize;
|
|
|
|
MemReqSize f3_SIZE_B = 2'b00;
|
|
MemReqSize f3_SIZE_H = 2'b01;
|
|
MemReqSize f3_SIZE_W = 2'b10;
|
|
MemReqSize f3_SIZE_D = 2'b11;
|
|
|
|
// ----------------
|
|
// Load instructions
|
|
|
|
Opcode op_LOAD = 7'b00_000_11;
|
|
|
|
Bit #(3) f3_LB = 3'b000;
|
|
Bit #(3) f3_LH = 3'b001;
|
|
Bit #(3) f3_LW = 3'b010;
|
|
Bit #(3) f3_LD = 3'b011;
|
|
Bit #(3) f3_LBU = 3'b100;
|
|
Bit #(3) f3_LHU = 3'b101;
|
|
Bit #(3) f3_LWU = 3'b110;
|
|
|
|
// ----------------
|
|
// Store instructions
|
|
|
|
Opcode op_STORE = 7'b01_000_11;
|
|
|
|
Bit #(3) f3_SB = 3'b000;
|
|
Bit #(3) f3_SH = 3'b001;
|
|
Bit #(3) f3_SW = 3'b010;
|
|
Bit #(3) f3_SD = 3'b011;
|
|
|
|
// ================================================================
|
|
// Memory Model
|
|
|
|
Opcode op_MISC_MEM = 7'b00_011_11;
|
|
|
|
Bit #(3) f3_FENCE = 3'b000;
|
|
Bit #(3) f3_FENCE_I = 3'b001;
|
|
|
|
typedef struct {
|
|
// Predecessors
|
|
Bool pi; // IO reads
|
|
Bool po; // IO writes
|
|
Bool pr; // Mem reads
|
|
Bool pw; // Mem writes
|
|
// Successors
|
|
Bool si;
|
|
Bool so;
|
|
Bool sr;
|
|
Bool sw;
|
|
} Fence_Ordering
|
|
deriving (FShow);
|
|
|
|
instance Bits #(Fence_Ordering, 8);
|
|
function Bit #(8) pack (Fence_Ordering fo);
|
|
return {pack (fo.pi),
|
|
pack (fo.po),
|
|
pack (fo.pr),
|
|
pack (fo.pw),
|
|
pack (fo.si),
|
|
pack (fo.so),
|
|
pack (fo.sr),
|
|
pack (fo.sw) };
|
|
endfunction
|
|
function Fence_Ordering unpack (Bit #(8) b8);
|
|
return Fence_Ordering {pi: unpack (b8 [7]),
|
|
po: unpack (b8 [6]),
|
|
pr: unpack (b8 [5]),
|
|
pw: unpack (b8 [4]),
|
|
si: unpack (b8 [3]),
|
|
so: unpack (b8 [2]),
|
|
sr: unpack (b8 [1]),
|
|
sw: unpack (b8 [0]) };
|
|
endfunction
|
|
endinstance
|
|
|
|
// ================================================================
|
|
// Atomic Memory Operation Instructions
|
|
|
|
Opcode op_AMO = 7'b01_011_11;
|
|
|
|
// NOTE: bit [4] for aq, and [3] for rl, are here set to zero
|
|
|
|
Bit #(3) f3_AMO_W = 3'b010;
|
|
Bit #(3) f3_AMO_D = 3'b011;
|
|
|
|
Bit #(5) f5_AMO_LR = 5'b00010;
|
|
Bit #(5) f5_AMO_SC = 5'b00011;
|
|
Bit #(5) f5_AMO_ADD = 5'b00000;
|
|
Bit #(5) f5_AMO_SWAP = 5'b00001;
|
|
Bit #(5) f5_AMO_XOR = 5'b00100;
|
|
Bit #(5) f5_AMO_AND = 5'b01100;
|
|
Bit #(5) f5_AMO_OR = 5'b01000;
|
|
Bit #(5) f5_AMO_MIN = 5'b10000;
|
|
Bit #(5) f5_AMO_MAX = 5'b10100;
|
|
Bit #(5) f5_AMO_MINU = 5'b11000;
|
|
Bit #(5) f5_AMO_MAXU = 5'b11100;
|
|
|
|
Bit #(10) f10_LR_W = 10'b00010_00_010;
|
|
Bit #(10) f10_SC_W = 10'b00011_00_010;
|
|
Bit #(10) f10_AMOADD_W = 10'b00000_00_010;
|
|
Bit #(10) f10_AMOSWAP_W = 10'b00001_00_010;
|
|
Bit #(10) f10_AMOXOR_W = 10'b00100_00_010;
|
|
Bit #(10) f10_AMOAND_W = 10'b01100_00_010;
|
|
Bit #(10) f10_AMOOR_W = 10'b01000_00_010;
|
|
Bit #(10) f10_AMOMIN_W = 10'b10000_00_010;
|
|
Bit #(10) f10_AMOMAX_W = 10'b10100_00_010;
|
|
Bit #(10) f10_AMOMINU_W = 10'b11000_00_010;
|
|
Bit #(10) f10_AMOMAXU_W = 10'b11100_00_010;
|
|
|
|
Bit #(10) f10_LR_D = 10'b00010_00_011;
|
|
Bit #(10) f10_SC_D = 10'b00011_00_011;
|
|
Bit #(10) f10_AMOADD_D = 10'b00000_00_011;
|
|
Bit #(10) f10_AMOSWAP_D = 10'b00001_00_011;
|
|
Bit #(10) f10_AMOXOR_D = 10'b00100_00_011;
|
|
Bit #(10) f10_AMOAND_D = 10'b01100_00_011;
|
|
Bit #(10) f10_AMOOR_D = 10'b01000_00_011;
|
|
Bit #(10) f10_AMOMIN_D = 10'b10000_00_011;
|
|
Bit #(10) f10_AMOMAX_D = 10'b10100_00_011;
|
|
Bit #(10) f10_AMOMINU_D = 10'b11000_00_011;
|
|
Bit #(10) f10_AMOMAXU_D = 10'b11100_00_011;
|
|
|
|
// ================================================================
|
|
// Integer Register-Immediate Instructions
|
|
|
|
Opcode op_OP_IMM = 7'b00_100_11;
|
|
|
|
Bit #(3) f3_ADDI = 3'b000;
|
|
Bit #(3) f3_SLLI = 3'b001;
|
|
Bit #(3) f3_SLTI = 3'b010;
|
|
Bit #(3) f3_SLTIU = 3'b011;
|
|
Bit #(3) f3_XORI = 3'b100;
|
|
Bit #(3) f3_SRxI = 3'b101; Bit #(3) f3_SRLI = 3'b101; Bit #(3) f3_SRAI = 3'b101;
|
|
Bit #(3) f3_ORI = 3'b110;
|
|
Bit #(3) f3_ANDI = 3'b111;
|
|
|
|
// ================================================================
|
|
// Integer Register-Immediate 32b Instructions for RV64
|
|
|
|
Opcode op_OP_IMM_32 = 7'b00_110_11;
|
|
|
|
Bit #(3) f3_ADDIW = 3'b000;
|
|
Bit #(3) f3_SLLIW = 3'b001;
|
|
Bit #(3) f3_SRxIW = 3'b101; Bit #(3) f3_SRLIW = 3'b101; Bit #(3) f3_SRAIW = 3'b101;
|
|
|
|
// OP_IMM.SLLI/SRLI/SRAI for RV32
|
|
Bit #(7) msbs7_SLLI = 7'b_000_0000;
|
|
Bit #(7) msbs7_SRLI = 7'b_000_0000;
|
|
Bit #(7) msbs7_SRAI = 7'b_010_0000;
|
|
|
|
// OP_IMM.SLLI/SRLI/SRAI for RV64
|
|
Bit #(6) msbs6_SLLI = 6'b_00_0000;
|
|
Bit #(6) msbs6_SRLI = 6'b_00_0000;
|
|
Bit #(6) msbs6_SRAI = 6'b_01_0000;
|
|
|
|
// ================================================================
|
|
// Integer Register-Register Instructions
|
|
|
|
Opcode op_OP = 7'b01_100_11;
|
|
|
|
Bit #(10) f10_ADD = 10'b000_0000_000;
|
|
Bit #(10) f10_SUB = 10'b010_0000_000;
|
|
Bit #(10) f10_SLL = 10'b000_0000_001;
|
|
Bit #(10) f10_SLT = 10'b000_0000_010;
|
|
Bit #(10) f10_SLTU = 10'b000_0000_011;
|
|
Bit #(10) f10_XOR = 10'b000_0000_100;
|
|
Bit #(10) f10_SRL = 10'b000_0000_101;
|
|
Bit #(10) f10_SRA = 10'b010_0000_101;
|
|
Bit #(10) f10_OR = 10'b000_0000_110;
|
|
Bit #(10) f10_AND = 10'b000_0000_111;
|
|
|
|
Bit #(7) funct7_ADD = 7'b_000_0000; Bit #(3) funct3_ADD = 3'b_000;
|
|
Bit #(7) funct7_SUB = 7'b_010_0000; Bit #(3) funct3_SUB = 3'b_000;
|
|
Bit #(7) funct7_XOR = 7'b_000_0000; Bit #(3) funct3_XOR = 3'b_100;
|
|
Bit #(7) funct7_OR = 7'b_000_0000; Bit #(3) funct3_OR = 3'b_110;
|
|
Bit #(7) funct7_AND = 7'b_000_0000; Bit #(3) funct3_AND = 3'b_111;
|
|
|
|
// ----------------
|
|
// MUL/DIV/REM family
|
|
|
|
Bit #(7) f7_MUL_DIV_REM = 7'b000_0001;
|
|
|
|
function Bool f7_is_OP_MUL_DIV_REM (Bit #(7) f7);
|
|
return (f7 == f7_MUL_DIV_REM);
|
|
endfunction
|
|
|
|
Bit #(3) f3_MUL = 3'b000;
|
|
Bit #(3) f3_MULH = 3'b001;
|
|
Bit #(3) f3_MULHSU = 3'b010;
|
|
Bit #(3) f3_MULHU = 3'b011;
|
|
Bit #(3) f3_DIV = 3'b100;
|
|
Bit #(3) f3_DIVU = 3'b101;
|
|
Bit #(3) f3_REM = 3'b110;
|
|
Bit #(3) f3_REMU = 3'b111;
|
|
|
|
Bit #(10) f10_MUL = 10'b000_0001_000;
|
|
Bit #(10) f10_MULH = 10'b000_0001_001;
|
|
Bit #(10) f10_MULHSU = 10'b000_0001_010;
|
|
Bit #(10) f10_MULHU = 10'b000_0001_011;
|
|
Bit #(10) f10_DIV = 10'b000_0001_100;
|
|
Bit #(10) f10_DIVU = 10'b000_0001_101;
|
|
Bit #(10) f10_REM = 10'b000_0001_110;
|
|
Bit #(10) f10_REMU = 10'b000_0001_111;
|
|
|
|
// ================================================================
|
|
// Integer Register-Register 32b Instructions for RV64
|
|
|
|
Opcode op_OP_32 = 7'b01_110_11;
|
|
|
|
Bit #(10) f10_ADDW = 10'b000_0000_000;
|
|
Bit #(10) f10_SUBW = 10'b010_0000_000;
|
|
Bit #(10) f10_SLLW = 10'b000_0000_001;
|
|
Bit #(10) f10_SRLW = 10'b000_0000_101;
|
|
Bit #(10) f10_SRAW = 10'b010_0000_101;
|
|
|
|
Bit #(7) funct7_ADDW = 7'b_000_0000; Bit #(3) funct3_ADDW = 3'b_000;
|
|
Bit #(7) funct7_SUBW = 7'b_010_0000; Bit #(3) funct3_SUBW = 3'b_000;
|
|
|
|
Bit #(10) f10_MULW = 10'b000_0001_000;
|
|
Bit #(10) f10_DIVW = 10'b000_0001_100;
|
|
Bit #(10) f10_DIVUW = 10'b000_0001_101;
|
|
Bit #(10) f10_REMW = 10'b000_0001_110;
|
|
Bit #(10) f10_REMUW = 10'b000_0001_111;
|
|
|
|
function Bool is_OP_32_MUL_DIV_REM (Bit #(10) f10);
|
|
return ( (f10 == f10_MULW)
|
|
|| (f10 == f10_DIVW)
|
|
|| (f10 == f10_DIVUW)
|
|
|| (f10 == f10_REMW)
|
|
|| (f10 == f10_REMUW));
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// LUI, AUIPC
|
|
|
|
Opcode op_LUI = 7'b01_101_11;
|
|
Opcode op_AUIPC = 7'b00_101_11;
|
|
|
|
// ================================================================
|
|
// Control transfer
|
|
|
|
Opcode op_BRANCH = 7'b11_000_11;
|
|
|
|
Bit #(3) f3_BEQ = 3'b000;
|
|
Bit #(3) f3_BNE = 3'b001;
|
|
Bit #(3) f3_BLT = 3'b100;
|
|
Bit #(3) f3_BGE = 3'b101;
|
|
Bit #(3) f3_BLTU = 3'b110;
|
|
Bit #(3) f3_BGEU = 3'b111;
|
|
|
|
Opcode op_JAL = 7'b11_011_11;
|
|
|
|
Opcode op_JALR = 7'b11_001_11;
|
|
Bit #(3) funct3_JALR = 3'b000;
|
|
|
|
`ifdef ISA_F
|
|
// ================================================================
|
|
// Floating Point Instructions
|
|
// TODO: these are implementation choices; should not be in ISA_Decls
|
|
// Enumeration of floating point opcodes for decode within the FPU
|
|
typedef enum {
|
|
FPAdd
|
|
, FPSub
|
|
, FPMul
|
|
, FPDiv
|
|
, FPSqrt
|
|
, FPMAdd
|
|
, FPMSub
|
|
, FPNMAdd
|
|
, FPNMSub } FpuOp deriving (Bits, Eq, FShow);
|
|
|
|
// Enumeration of rounding modes
|
|
typedef enum {
|
|
Rnd_Nearest_Even
|
|
, Rnd_Zero
|
|
, Rnd_Minus_Inf
|
|
, Rnd_Plus_Inf
|
|
, Rnd_Nearest_Max_Mag
|
|
} RoundMode deriving (Bits, Eq, FShow);
|
|
|
|
// Funct2 encoding
|
|
Bit #(2) f2_S = 2'b00;
|
|
Bit #(2) f2_D = 2'b01;
|
|
Bit #(2) f2_Q = 2'b11;
|
|
|
|
// Floating point Load-Store
|
|
Opcode op_LOAD_FP = 7'b_00_001_11;
|
|
Opcode op_STORE_FP = 7'b_01_001_11;
|
|
Bit #(3) f3_FSW = 3'b010;
|
|
Bit #(3) f3_FSD = 3'b011;
|
|
Bit #(3) f3_FLW = 3'b010;
|
|
Bit #(3) f3_FLD = 3'b011;
|
|
|
|
// Fused FP Multiply Add/Sub instructions
|
|
Opcode op_FMADD = 7'b10_00_011;
|
|
Opcode op_FMSUB = 7'b10_00_111;
|
|
Opcode op_FNMSUB = 7'b10_01_011;
|
|
Opcode op_FNMADD = 7'b10_01_111;
|
|
|
|
// All other FP intructions
|
|
Opcode op_FP = 7'b10_10_011;
|
|
|
|
Bit #(7) f7_FADD_D = 7'h1 ;
|
|
Bit #(7) f7_FSUB_D = 7'h5 ;
|
|
Bit #(7) f7_FMUL_D = 7'h9 ;
|
|
Bit #(7) f7_FDIV_D = 7'hD ;
|
|
Bit #(7) f7_FSQRT_D = 7'h2D;
|
|
Bit #(7) f7_FCMP_D = 7'h51;
|
|
Bit #(7) f7_FMIN_D = 7'h15;
|
|
Bit #(7) f7_FMAX_D = 7'h15;
|
|
Bit #(7) f7_FSGNJ_D = 7'h11;
|
|
|
|
Bit #(7) f7_FADD_S = 7'h0 ;
|
|
Bit #(7) f7_FSUB_S = 7'h4 ;
|
|
Bit #(7) f7_FMUL_S = 7'h8 ;
|
|
Bit #(7) f7_FDIV_S = 7'hC ;
|
|
Bit #(7) f7_FSQRT_S = 7'h2C;
|
|
Bit #(7) f7_FCMP_S = 7'h50;
|
|
Bit #(7) f7_FMIN_S = 7'h14;
|
|
Bit #(7) f7_FMAX_S = 7'h14;
|
|
Bit #(7) f7_FSGNJ_S = 7'h10;
|
|
|
|
Bit #(7) f7_FCVT_W_S = 7'h60;
|
|
Bit #(7) f7_FCVT_WU_S = 7'h60;
|
|
Bit #(7) f7_FCVT_S_W = 7'h68;
|
|
Bit #(7) f7_FCVT_S_WU = 7'h68;
|
|
|
|
Bit #(7) f7_FCVT_L_S = 7'h60;
|
|
Bit #(7) f7_FCVT_LU_S = 7'h60;
|
|
Bit #(7) f7_FCVT_S_L = 7'h68;
|
|
Bit #(7) f7_FCVT_S_LU = 7'h68;
|
|
|
|
Bit #(7) f7_FCVT_S_D = 7'h20;
|
|
Bit #(7) f7_FCVT_D_S = 7'h21;
|
|
Bit #(7) f7_FCVT_W_D = 7'h61;
|
|
Bit #(7) f7_FCVT_WU_D = 7'h61;
|
|
Bit #(7) f7_FCVT_D_W = 7'h69;
|
|
Bit #(7) f7_FCVT_D_WU = 7'h69;
|
|
|
|
Bit #(7) f7_FCVT_L_D = 7'h61;
|
|
Bit #(7) f7_FCVT_LU_D = 7'h61;
|
|
Bit #(7) f7_FCVT_D_L = 7'h69;
|
|
Bit #(7) f7_FCVT_D_LU = 7'h69;
|
|
|
|
Bit #(7) f7_FMV_X_D = 7'h71;
|
|
Bit #(7) f7_FMV_D_X = 7'h79;
|
|
Bit #(7) f7_FCLASS_D = 7'h71;
|
|
Bit #(7) f7_FMV_X_W = 7'h70;
|
|
Bit #(7) f7_FMV_W_X = 7'h78;
|
|
Bit #(7) f7_FCLASS_S = 7'h70;
|
|
|
|
// fv_is_rd_in_GPR: Checks if the request generates a result which
|
|
// should be written into the GPR
|
|
function Bool fv_is_rd_in_GPR (Bit #(7) funct7, RegName rs2);
|
|
|
|
`ifdef ISA_D
|
|
let is_FCVT_W_D = (funct7 == f7_FCVT_W_D)
|
|
&& (rs2 == 0);
|
|
let is_FCVT_WU_D = (funct7 == f7_FCVT_WU_D)
|
|
&& (rs2 == 1);
|
|
`ifdef RV64
|
|
let is_FCVT_L_D = (funct7 == f7_FCVT_L_D)
|
|
&& (rs2 == 2);
|
|
let is_FCVT_LU_D = (funct7 == f7_FCVT_LU_D)
|
|
&& (rs2 == 3);
|
|
|
|
`endif
|
|
// FCLASS.D also maps to this -- both write to GPR
|
|
let is_FMV_X_D = (funct7 == f7_FMV_X_D);
|
|
// FEQ.D, FLE.D, FLT.D map to this
|
|
let is_FCMP_D = (funct7 == f7_FCMP_D);
|
|
`endif
|
|
|
|
let is_FCVT_W_S = (funct7 == f7_FCVT_W_S)
|
|
&& (rs2 == 0);
|
|
let is_FCVT_WU_S = (funct7 == f7_FCVT_WU_S)
|
|
&& (rs2 == 1);
|
|
`ifdef RV64
|
|
let is_FCVT_L_S = (funct7 == f7_FCVT_L_S)
|
|
&& (rs2 == 2);
|
|
let is_FCVT_LU_S = (funct7 == f7_FCVT_LU_S)
|
|
&& (rs2 == 3);
|
|
`endif
|
|
|
|
// FCLASS.S also maps to this -- both write to GPR
|
|
let is_FMV_X_W = (funct7 == f7_FMV_X_W);
|
|
|
|
// FEQ.S, FLE.S, FLT.S map to this
|
|
let is_FCMP_S = (funct7 == f7_FCMP_S);
|
|
|
|
return (
|
|
False
|
|
`ifdef ISA_D
|
|
|| is_FCVT_W_D
|
|
|| is_FCVT_WU_D
|
|
`ifdef RV64
|
|
|| is_FCVT_L_D
|
|
|| is_FCVT_LU_D
|
|
`endif
|
|
|| is_FMV_X_D
|
|
|| is_FCMP_D
|
|
`endif
|
|
`ifdef RV64
|
|
|| is_FCVT_L_S
|
|
|| is_FCVT_LU_S
|
|
`endif
|
|
|| is_FCVT_W_S
|
|
|| is_FCVT_WU_S
|
|
|| is_FMV_X_W
|
|
|| is_FCMP_S
|
|
);
|
|
endfunction
|
|
|
|
// Check if a rounding mode value in the FCSR.FRM is valid
|
|
function Bool fv_fcsr_frm_valid (Bit #(3) frm);
|
|
return ( (frm != 3'b101)
|
|
&& (frm != 3'b110)
|
|
&& (frm != 3'b111)
|
|
);
|
|
endfunction
|
|
|
|
// Check if a rounding mode value in the instr is valid
|
|
function Bool fv_inst_frm_valid (Bit #(3) frm);
|
|
return ( (frm != 3'b101)
|
|
&& (frm != 3'b110)
|
|
);
|
|
endfunction
|
|
|
|
// fv_rounding_mode_check
|
|
// Returns the correct rounding mode considering the values in the
|
|
// FCSR and the instruction and checks legality
|
|
function Tuple2# (Bit #(3), Bool) fv_rmode_check (
|
|
Bit #(3) inst_frm, Bit #(3) fcsr_frm);
|
|
let rm = (inst_frm == 3'h7) ? fcsr_frm : inst_frm;
|
|
let rm_is_legal = (inst_frm == 3'h7) ? fv_fcsr_frm_valid (fcsr_frm)
|
|
: fv_inst_frm_valid (inst_frm);
|
|
return (tuple2 (rm, rm_is_legal));
|
|
endfunction
|
|
|
|
// A D instruction requires misa.f to be set as well as misa.d
|
|
function Bool fv_is_fp_instr_legal (
|
|
Bit #(7) f7, Bit #(3) rm, RegName rs2, Opcode fopc);
|
|
Bit #(2) f2 = f7[1:0];
|
|
Bool is_legal = True;
|
|
if ( (fopc == op_FMADD )
|
|
|| (fopc == op_FMSUB )
|
|
|| (fopc == op_FNMADD)
|
|
|| (fopc == op_FNMSUB))
|
|
`ifdef ISA_D
|
|
return ((f2 == f2_S) || (f2 == f2_D)); // Both SP and DP are legal
|
|
`else
|
|
return (f2 == f2_S); // Only SP is legal
|
|
`endif
|
|
else
|
|
if ( (f7 == f7_FADD_S)
|
|
|| (f7 == f7_FSUB_S)
|
|
|| (f7 == f7_FMUL_S)
|
|
`ifdef ISA_FD_DIV
|
|
|| (f7 == f7_FDIV_S)
|
|
|| (f7 == f7_FSQRT_S)
|
|
`endif
|
|
|| ((f7 == f7_FSGNJ_S) && ( rm == 0))
|
|
|| ((f7 == f7_FSGNJ_S) && ( rm == 1))
|
|
|| ((f7 == f7_FSGNJ_S) && ( rm == 2))
|
|
|| ((f7 == f7_FCVT_W_S) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_WU_S)&& (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_L_S) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_LU_S)&& (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FCVT_S_W) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_S_WU)&& (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_S_L) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_S_LU)&& (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FMIN_S) && ( rm == 0))
|
|
|| ((f7 == f7_FMAX_S) && ( rm == 1))
|
|
|| ((f7 == f7_FCMP_S) && ( rm == 0))
|
|
|| ((f7 == f7_FCMP_S) && ( rm == 1))
|
|
|| ((f7 == f7_FCMP_S) && ( rm == 2))
|
|
|| ((f7 == f7_FMV_X_W) && ( rm == 0))
|
|
|| ((f7 == f7_FMV_W_X) && ( rm == 0))
|
|
|| ((f7 == f7_FCLASS_S) && ( rm == 1))
|
|
`ifdef ISA_D
|
|
|| (f7 == f7_FADD_D)
|
|
|| (f7 == f7_FSUB_D)
|
|
|| (f7 == f7_FMUL_D)
|
|
`ifdef ISA_FD_DIV
|
|
|| (f7 == f7_FDIV_D)
|
|
|| (f7 == f7_FSQRT_D)
|
|
`endif
|
|
|| ((f7 == f7_FSGNJ_D) && ( rm == 0))
|
|
|| ((f7 == f7_FSGNJ_D) && ( rm == 1))
|
|
|| ((f7 == f7_FSGNJ_D) && ( rm == 2))
|
|
|| ((f7 == f7_FCVT_W_D) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_WU_D)&& (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_L_D) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_LU_D)&& (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FCVT_D_W) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_D_WU)&& (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_D_L) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_D_LU)&& (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FCVT_D_S) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_S_D) && (rs2 == 1))
|
|
|| ((f7 == f7_FMIN_D) && ( rm == 0))
|
|
|| ((f7 == f7_FMAX_D) && ( rm == 1))
|
|
|| ((f7 == f7_FCMP_D) && ( rm == 0))
|
|
|| ((f7 == f7_FCMP_D) && ( rm == 1))
|
|
|| ((f7 == f7_FCMP_D) && ( rm == 2))
|
|
|| ((f7 == f7_FMV_X_D) && ( rm == 0))
|
|
|| ((f7 == f7_FMV_D_X) && ( rm == 0))
|
|
|| ((f7 == f7_FCLASS_D) && ( rm == 1))
|
|
`endif
|
|
) return True;
|
|
else return False;
|
|
endfunction
|
|
|
|
// Returns True if the first operand (val1) should be taken from the GPR
|
|
// instead of the FPR for a FP opcode
|
|
function Bool fv_fp_val1_from_gpr (Opcode opcode, Bit#(7) f7, RegName rs2);
|
|
return (
|
|
(opcode == op_FP)
|
|
&& ( False
|
|
`ifdef ISA_D
|
|
|| ((f7 == f7_FCVT_D_W) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_D_WU) && (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_D_L) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_D_LU) && (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FMV_D_X))
|
|
`endif
|
|
|| ((f7 == f7_FCVT_S_W) && (rs2 == 0))
|
|
|| ((f7 == f7_FCVT_S_WU) && (rs2 == 1))
|
|
`ifdef RV64
|
|
|| ((f7 == f7_FCVT_S_L) && (rs2 == 2))
|
|
|| ((f7 == f7_FCVT_S_LU) && (rs2 == 3))
|
|
`endif
|
|
|| ((f7 == f7_FMV_W_X))
|
|
)
|
|
);
|
|
endfunction
|
|
`endif
|
|
|
|
// ================================================================
|
|
// System Instructions
|
|
Opcode op_SYSTEM = 7'b11_100_11;
|
|
|
|
// sub-opcodes: (in funct3 field)
|
|
Bit #(3) f3_PRIV = 3'b000;
|
|
Bit #(3) f3_CSRRW = 3'b001;
|
|
Bit #(3) f3_CSRRS = 3'b010;
|
|
Bit #(3) f3_CSRRC = 3'b011;
|
|
Bit #(3) f3_SYSTEM_ILLEGAL = 3'b100;
|
|
Bit #(3) f3_CSRRWI = 3'b101;
|
|
Bit #(3) f3_CSRRSI = 3'b110;
|
|
Bit #(3) f3_CSRRCI = 3'b111;
|
|
|
|
// sub-sub-opcodes for f3_PRIV
|
|
|
|
Bit #(12) f12_ECALL = 12'b_0000_0000_0000;
|
|
Bit #(12) f12_EBREAK = 12'b_0000_0000_0001;
|
|
|
|
Bit #(12) f12_URET = 12'b_0000_0000_0010;
|
|
Bit #(12) f12_SRET = 12'b_0001_0000_0010;
|
|
Bit #(12) f12_HRET = 12'b_0010_0000_0010;
|
|
Bit #(12) f12_MRET = 12'b_0011_0000_0010;
|
|
Bit #(12) f12_WFI = 12'b_0001_0000_0101;
|
|
|
|
// v1.10 sub-sub-opcode for SFENCE_VMA
|
|
Bit #(7) f7_SFENCE_VMA = 7'b_0001_001;
|
|
|
|
Instr break_instr = { f12_EBREAK, 5'b00000, 3'b000, 5'b00000, op_SYSTEM };
|
|
|
|
function Bool fn_instr_is_csrrx (Instr instr);
|
|
let decoded_instr = fv_decode (instr);
|
|
let opcode = decoded_instr.opcode;
|
|
let funct3 = decoded_instr.funct3;
|
|
let csr = decoded_instr.csr;
|
|
return ((opcode == op_SYSTEM) && f3_is_CSRR_any (funct3));
|
|
endfunction
|
|
|
|
function Bool f3_is_CSRR_any (Bit #(3) f3);
|
|
return (f3_is_CSRR_W (f3) || f3_is_CSRR_S_or_C (f3));
|
|
endfunction
|
|
|
|
function Bool f3_is_CSRR_W (Bit #(3) f3);
|
|
return ((f3 == f3_CSRRW) || (f3 == f3_CSRRWI));
|
|
endfunction
|
|
|
|
function Bool f3_is_CSRR_S_or_C (Bit #(3) f3);
|
|
return ((f3 == f3_CSRRS) || (f3 == f3_CSRRSI) ||
|
|
(f3 == f3_CSRRC) || (f3 == f3_CSRRCI));
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// Privilege Modes
|
|
|
|
typedef 4 Num_Priv_Modes;
|
|
|
|
typedef Bit #(2) Priv_Mode;
|
|
|
|
Priv_Mode u_Priv_Mode = 2'b00;
|
|
Priv_Mode s_Priv_Mode = 2'b01;
|
|
Priv_Mode reserved_Priv_Mode = 2'b10;
|
|
Priv_Mode m_Priv_Mode = 2'b11;
|
|
|
|
function Fmt fshow_Priv_Mode (Priv_Mode pm);
|
|
return case (pm)
|
|
u_Priv_Mode: $format ("U");
|
|
s_Priv_Mode: $format ("S");
|
|
m_Priv_Mode: $format ("M");
|
|
default: $format ("RESERVED");
|
|
endcase;
|
|
endfunction
|
|
|
|
// ================================================================
|
|
// Control/Status registers
|
|
|
|
typedef Bit #(12) CSR_Addr;
|
|
|
|
function Bool fn_csr_addr_can_write (CSR_Addr csr_addr);
|
|
return (csr_addr [11:10] != 2'b11);
|
|
endfunction
|
|
|
|
function Bool fn_csr_addr_priv_ok (CSR_Addr csr_addr, Priv_Mode priv_mode);
|
|
return (priv_mode >= csr_addr [9:8]);
|
|
endfunction
|
|
|
|
// ----------------
|
|
// User-level CSR addresses
|
|
|
|
CSR_Addr csr_addr_ustatus = 12'h000; // User status
|
|
CSR_Addr csr_addr_uie = 12'h004; // User interrupt-enable
|
|
CSR_Addr csr_addr_utvec = 12'h005; // User trap handler base address
|
|
|
|
CSR_Addr csr_addr_uscratch = 12'h040; // Scratch register for trap handlers
|
|
CSR_Addr csr_addr_uepc = 12'h041; // User exception program counter
|
|
CSR_Addr csr_addr_ucause = 12'h042; // User trap cause
|
|
CSR_Addr csr_addr_utval = 12'h043; // User bad address or instruction
|
|
CSR_Addr csr_addr_uip = 12'h044; // User interrupt pending
|
|
|
|
CSR_Addr csr_addr_fflags = 12'h001; // Floating-point accrued exceptions
|
|
CSR_Addr csr_addr_frm = 12'h002; // Floating-point Dynamic Rounding Mode
|
|
CSR_Addr csr_addr_fcsr = 12'h003; // Floating-point Control and Status Register (frm + fflags)
|
|
|
|
CSR_Addr csr_addr_cycle = 12'hC00; // Cycle counter for RDCYCLE
|
|
CSR_Addr csr_addr_time = 12'hC01; // Timer for RDTIME
|
|
CSR_Addr csr_addr_instret = 12'hC02; // Instructions retired counter for RDINSTRET
|
|
|
|
CSR_Addr csr_addr_hpmcounter3 = 12'hC03; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter4 = 12'hC04; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter5 = 12'hC05; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter6 = 12'hC06; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter7 = 12'hC07; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter8 = 12'hC08; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter9 = 12'hC09; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter10 = 12'hC0A; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter11 = 12'hC0B; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter12 = 12'hC0C; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter13 = 12'hC0D; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter14 = 12'hC0E; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter15 = 12'hC0F; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter16 = 12'hC10; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter17 = 12'hC11; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter18 = 12'hC12; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter19 = 12'hC13; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter20 = 12'hC14; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter21 = 12'hC15; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter22 = 12'hC16; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter23 = 12'hC17; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter24 = 12'hC18; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter25 = 12'hC19; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter26 = 12'hC1A; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter27 = 12'hC1B; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter28 = 12'hC1C; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter29 = 12'hC1D; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter30 = 12'hC1E; // Performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter31 = 12'hC1F; // Performance-monitoring counter
|
|
|
|
CSR_Addr csr_addr_cycleh = 12'hC80; // Upper 32 bits of csr_cycle (RV32I only)
|
|
CSR_Addr csr_addr_timeh = 12'hC81; // Upper 32 bits of csr_time (RV32I only)
|
|
CSR_Addr csr_addr_instreth = 12'hC82; // Upper 32 bits of csr_instret (RV32I only)
|
|
|
|
CSR_Addr csr_addr_hpmcounter3h = 12'hC83; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter4h = 12'hC84; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter5h = 12'hC85; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter6h = 12'hC86; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter7h = 12'hC87; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter8h = 12'hC88; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter9h = 12'hC89; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter10h = 12'hC8A; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter11h = 12'hC8B; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter12h = 12'hC8C; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter13h = 12'hC8D; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter14h = 12'hC8E; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter15h = 12'hC8F; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter16h = 12'hC90; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter17h = 12'hC91; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter18h = 12'hC92; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter19h = 12'hC93; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter20h = 12'hC94; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter21h = 12'hC95; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter22h = 12'hC96; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter23h = 12'hC97; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter24h = 12'hC98; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter25h = 12'hC99; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter26h = 12'hC9A; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter27h = 12'hC9B; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter28h = 12'hC9C; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter29h = 12'hC9D; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter30h = 12'hC9E; // Upper 32 bits of performance-monitoring counter
|
|
CSR_Addr csr_addr_hpmcounter31h = 12'hC9F; // Upper 32 bits of performance-monitoring counter
|
|
|
|
// Information from the CSR on a new trap.
|
|
typedef struct {
|
|
Addr pc;
|
|
WordXL mstatus;
|
|
WordXL mcause;
|
|
Priv_Mode priv;
|
|
} Trap_Info deriving (Bits, Eq, FShow);
|
|
|
|
// ================================================================
|
|
// 'C' Extension ("compressed" instructions)
|
|
|
|
`include "ISA_Decls_C.bsv"
|
|
|
|
// ================================================================
|
|
// Supervisor-Level ISA defs
|
|
|
|
`include "ISA_Decls_Priv_S.bsv"
|
|
|
|
// ================================================================
|
|
// Hypervisor-Level ISA defs
|
|
|
|
// `include "ISA_Decls_Priv_H.bsv"
|
|
|
|
// ================================================================
|
|
// Machine-Level ISA defs
|
|
|
|
`include "ISA_Decls_Priv_M.bsv"
|
|
|
|
// ================================================================
|
|
|
|
endpackage
|