Initial load of files
This commit is contained in:
1125
src_Core/ISA/ISA_Decls.bsv
Normal file
1125
src_Core/ISA/ISA_Decls.bsv
Normal file
File diff suppressed because it is too large
Load Diff
179
src_Core/ISA/ISA_Decls_C.bsv
Normal file
179
src_Core/ISA/ISA_Decls_C.bsv
Normal file
@@ -0,0 +1,179 @@
|
||||
// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
|
||||
|
||||
// ================================================================
|
||||
// This is an 'include' file, not a separate BSV package
|
||||
//
|
||||
// Contains RISC-V ISA defs for the 'C' ("compressed") extension
|
||||
// i.e., 16-bit instructions
|
||||
//
|
||||
// ================================================================
|
||||
// Instruction field encodings
|
||||
|
||||
typedef Bit #(16) Instr_C;
|
||||
|
||||
Bit #(2) opcode_C0 = 2'b00;
|
||||
Bit #(2) opcode_C1 = 2'b01;
|
||||
Bit #(2) opcode_C2 = 2'b10;
|
||||
|
||||
Bit #(3) funct3_C_LWSP = 3'b_010;
|
||||
Bit #(3) funct3_C_LDSP = 3'b_011; // RV64 and RV128
|
||||
Bit #(3) funct3_C_LQSP = 3'b_001; // RV128
|
||||
Bit #(3) funct3_C_FLWSP = 3'b_011; // RV32FC
|
||||
Bit #(3) funct3_C_FLDSP = 3'b_001; // RV32DC, RV64DC
|
||||
|
||||
Bit #(3) funct3_C_SWSP = 3'b_110;
|
||||
|
||||
Bit #(3) funct3_C_SQSP = 3'b_101; // RV128
|
||||
Bit #(3) funct3_C_FSDSP = 3'b_101; // RV32DC, RV64DC
|
||||
|
||||
Bit #(3) funct3_C_SDSP = 3'b_111; // RV64 and RV128
|
||||
Bit #(3) funct3_C_FSWSP = 3'b_111; // RV32FC
|
||||
|
||||
Bit #(3) funct3_C_LQ = 3'b_001; // RV128
|
||||
Bit #(3) funct3_C_FLD = 3'b_001; // RV32DC, RV64DC
|
||||
|
||||
Bit #(3) funct3_C_LW = 3'b_010;
|
||||
|
||||
Bit #(3) funct3_C_LD = 3'b_011; // RV64 and RV128
|
||||
Bit #(3) funct3_C_FLW = 3'b_011; // RV32FC
|
||||
|
||||
Bit #(3) funct3_C_FSD = 3'b_101; // RV32DC, RV64DC
|
||||
Bit #(3) funct3_C_SQ = 3'b_101; // RV128
|
||||
|
||||
Bit #(3) funct3_C_SW = 3'b_110;
|
||||
|
||||
Bit #(3) funct3_C_SD = 3'b_111; // RV64 and RV128
|
||||
Bit #(3) funct3_C_FSW = 3'b_111; // RV32FC
|
||||
|
||||
Bit #(3) funct3_C_JAL = 3'b_001; // RV32
|
||||
Bit #(3) funct3_C_J = 3'b_101;
|
||||
Bit #(3) funct3_C_BEQZ = 3'b_110;
|
||||
Bit #(3) funct3_C_BNEZ = 3'b_111;
|
||||
|
||||
Bit #(4) funct4_C_JR = 4'b_1000;
|
||||
Bit #(4) funct4_C_JALR = 4'b_1001;
|
||||
|
||||
Bit #(3) funct3_C_LI = 3'b_010;
|
||||
Bit #(3) funct3_C_LUI = 3'b_011; // RV64 and RV128
|
||||
|
||||
Bit #(3) funct3_C_NOP = 3'b_000;
|
||||
Bit #(3) funct3_C_ADDI = 3'b_000;
|
||||
Bit #(3) funct3_C_ADDIW = 3'b_001;
|
||||
Bit #(3) funct3_C_ADDI16SP = 3'b_011;
|
||||
Bit #(3) funct3_C_ADDI4SPN = 3'b_000;
|
||||
Bit #(3) funct3_C_SLLI = 3'b_000;
|
||||
|
||||
Bit #(3) funct3_C_SRLI = 3'b_100;
|
||||
Bit #(2) funct2_C_SRLI = 2'b_00;
|
||||
|
||||
Bit #(3) funct3_C_SRAI = 3'b_100;
|
||||
Bit #(2) funct2_C_SRAI = 2'b_01;
|
||||
|
||||
Bit #(3) funct3_C_ANDI = 3'b_100;
|
||||
Bit #(2) funct2_C_ANDI = 2'b_10;
|
||||
|
||||
Bit #(4) funct4_C_MV = 4'b_1000;
|
||||
Bit #(4) funct4_C_ADD = 4'b_1001;
|
||||
|
||||
Bit #(6) funct6_C_AND = 6'b_100_0_11;
|
||||
Bit #(2) funct2_C_AND = 2'b_11;
|
||||
|
||||
Bit #(6) funct6_C_OR = 6'b_100_0_11;
|
||||
Bit #(2) funct2_C_OR = 2'b_10;
|
||||
|
||||
Bit #(6) funct6_C_XOR = 6'b_100_0_11;
|
||||
Bit #(2) funct2_C_XOR = 2'b_01;
|
||||
|
||||
Bit #(6) funct6_C_SUB = 6'b_100_0_11;
|
||||
Bit #(2) funct2_C_SUB = 2'b_00;
|
||||
|
||||
Bit #(6) funct6_C_ADDW = 6'b_100_1_11;
|
||||
Bit #(2) funct2_C_ADDW = 2'b_01;
|
||||
|
||||
Bit #(6) funct6_C_SUBW = 6'b_100_1_11;
|
||||
Bit #(2) funct2_C_SUBW = 2'b_00;
|
||||
|
||||
Bit #(4) funct4_C_EBREAK = 4'b_1001;
|
||||
|
||||
// ================================================================
|
||||
// Functions to extract instruction fields from 'C' (compressed) instructions
|
||||
|
||||
function Tuple4 #(Bit #(4), RegName, RegName, Bit #(2)) fv_ifields_CR_type (Instr_C instr);
|
||||
let funct4 = instr [15:12];
|
||||
let rd_rs1 = instr [11: 7];
|
||||
let rs2 = instr [ 6: 2];
|
||||
let op = instr [ 1: 0];
|
||||
return tuple4 (funct4, rd_rs1, rs2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple5 #(Bit #(3), Bit #(1), Bit #(5), Bit #(5), Bit #(2)) fv_ifields_CI_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12 = instr [12:12];
|
||||
let rd_rs1 = instr [11: 7];
|
||||
let imm_at_6_2 = instr [ 6: 2];
|
||||
let op = instr [ 1: 0];
|
||||
return tuple5 (funct3, imm_at_12, rd_rs1, imm_at_6_2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple4 #(Bit #(3), Bit #(6), RegName, Bit #(2)) fv_ifields_CSS_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_7 = instr [12: 7];
|
||||
let rs2 = instr [ 6: 2];
|
||||
let op = instr [ 1: 0];
|
||||
return tuple4 (funct3, imm_at_12_7, rs2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple4 #(Bit #(3), Bit #(8), RegName, Bit #(2)) fv_ifields_CIW_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_5 = instr [12: 5];
|
||||
let rd = {2'b01, instr [4:2]};
|
||||
let op = instr [ 1: 0];
|
||||
return tuple4 (funct3, imm_at_12_5, rd, op);
|
||||
endfunction
|
||||
|
||||
function Tuple6 #(Bit #(3), Bit #(3), RegName, Bit #(2), RegName, Bit #(2)) fv_ifields_CL_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_10 = instr [12:10];
|
||||
let rs1 = {2'b01, instr [9:7]};
|
||||
let imm_at_6_5 = instr [ 6: 5];
|
||||
let rd = {2'b01, instr [4:2]};
|
||||
let op = instr [ 1: 0];
|
||||
return tuple6 (funct3, imm_at_12_10, rs1, imm_at_6_5, rd, op);
|
||||
endfunction
|
||||
|
||||
function Tuple6 #(Bit #(3), Bit #(3), RegName, Bit #(2), RegName, Bit #(2)) fv_ifields_CS_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_10 = instr [12:10];
|
||||
let rs1 = {2'b01, instr [9:7]};
|
||||
let imm_at_6_5 = instr [ 6: 5];
|
||||
let rs2 = {2'b01, instr [4:2]};
|
||||
let op = instr [ 1: 0];
|
||||
return tuple6 (funct3, imm_at_12_10, rs1, imm_at_6_5, rs2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple5 #(Bit #(6), RegName, Bit #(2), RegName, Bit #(2)) fv_ifields_CA_type (Instr_C instr);
|
||||
let funct6 = instr [15:10];
|
||||
let rd_rs1 = {2'b01, instr [9:7]};
|
||||
let funct2 = instr [ 6: 5];
|
||||
let rs2 = {2'b01, instr [4:2]};
|
||||
let op = instr [ 1: 0];
|
||||
return tuple5 (funct6, rd_rs1, funct2, rs2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple5 #(Bit #(3), Bit #(3), RegName, Bit #(5), Bit #(2)) fv_ifields_CB_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_10 = instr [12:10];
|
||||
let rs1 = {2'b01, instr [9:7]};
|
||||
let imm_at_6_2 = instr [ 6: 2];
|
||||
let op = instr [ 1: 0];
|
||||
return tuple5 (funct3, imm_at_12_10, rs1, imm_at_6_2, op);
|
||||
endfunction
|
||||
|
||||
function Tuple3 #(Bit #(3), Bit #(11), Bit #(2)) fv_ifields_CJ_type (Instr_C instr);
|
||||
let funct3 = instr [15:13];
|
||||
let imm_at_12_2 = instr [12: 2];
|
||||
let op = instr [ 1: 0];
|
||||
return tuple3 (funct3, imm_at_12_2, op);
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
716
src_Core/ISA/ISA_Decls_Priv_M.bsv
Normal file
716
src_Core/ISA/ISA_Decls_Priv_M.bsv
Normal file
@@ -0,0 +1,716 @@
|
||||
// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
|
||||
|
||||
// ================================================================
|
||||
// This is an 'include' file, not a separate BSV package
|
||||
//
|
||||
// Contains RISC-V Machine-Level ISA defs
|
||||
//
|
||||
// ================================================================
|
||||
|
||||
// ================================================================
|
||||
// Utility functions
|
||||
|
||||
// In these functions, 'bitpos' is Bit #(6) which is enough to index
|
||||
// 64-bit words in RV64.
|
||||
|
||||
function Bit #(n) fv_assign_bit (Bit #(n) x, Bit #(6) bitpos, Bit #(1) b)
|
||||
provisos (Add #(a__, 1, n));
|
||||
Bit #(n) mask = (1 << bitpos);
|
||||
Bit #(n) val = (extend (b) << bitpos);
|
||||
return ((x & (~ mask)) | val);
|
||||
endfunction
|
||||
|
||||
function Bit #(n) fv_assign_bits (Bit #(n) x, Bit #(6) bitpos, Bit #(w) bs)
|
||||
provisos (Add #(a__, w, n));
|
||||
Bit #(n) mask = (((1 << valueOf (w)) - 1) << bitpos);
|
||||
Bit #(n) val = (extend (bs) << bitpos);
|
||||
return ((x & (~ mask)) | val);
|
||||
endfunction
|
||||
|
||||
function Bit #(w) fv_get_bits (Bit #(n) x, Bit #(6) bitpos)
|
||||
provisos (Add #(a__, w, n));
|
||||
Bit #(n) mask = ((1 << valueOf (w)) - 1);
|
||||
return truncate ((x >> bitpos) & mask);
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Machine-level CSRs
|
||||
|
||||
CSR_Addr csr_addr_mvendorid = 12'hF11; // Vendor ID
|
||||
CSR_Addr csr_addr_marchid = 12'hF12; // Architecture ID
|
||||
CSR_Addr csr_addr_mimpid = 12'hF13; // Implementation ID
|
||||
CSR_Addr csr_addr_mhartid = 12'hF14; // Hardware thread ID
|
||||
|
||||
CSR_Addr csr_addr_mstatus = 12'h300; // Machine status
|
||||
CSR_Addr csr_addr_misa = 12'h301; // ISA and extensions
|
||||
CSR_Addr csr_addr_medeleg = 12'h302; // Machine exception delegation
|
||||
CSR_Addr csr_addr_mideleg = 12'h303; // Machine interrupt delegation
|
||||
CSR_Addr csr_addr_mie = 12'h304; // Machine interrupt-enable
|
||||
CSR_Addr csr_addr_mtvec = 12'h305; // Machine trap handler base address
|
||||
CSR_Addr csr_addr_mcounteren = 12'h306; // Machine counter enable
|
||||
|
||||
CSR_Addr csr_addr_mscratch = 12'h340; // Scratch reg for machine trap handlers
|
||||
CSR_Addr csr_addr_mepc = 12'h341; // Machine exception program counter
|
||||
CSR_Addr csr_addr_mcause = 12'h342; // Machine trap cause
|
||||
CSR_Addr csr_addr_mtval = 12'h343; // Machine bad address
|
||||
CSR_Addr csr_addr_mip = 12'h344; // Machine interrupt pending
|
||||
|
||||
CSR_Addr csr_addr_pmpcfg0 = 12'h3A0; // PMP Config
|
||||
CSR_Addr csr_addr_pmpcfg1 = 12'h3A1; // PMP Config
|
||||
CSR_Addr csr_addr_pmpcfg2 = 12'h3A2; // PMP Config
|
||||
CSR_Addr csr_addr_pmpcfg3 = 12'h3A3; // PMP Config
|
||||
CSR_Addr csr_addr_pmpaddr0 = 12'h3B0; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr1 = 12'h3B1; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr2 = 12'h3B2; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr3 = 12'h3B3; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr4 = 12'h3B4; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr5 = 12'h3B5; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr6 = 12'h3B6; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr7 = 12'h3B7; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr8 = 12'h3B8; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr9 = 12'h3B9; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr10 = 12'h3BA; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr11 = 12'h3BB; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr12 = 12'h3BC; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr13 = 12'h3BD; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr14 = 12'h3BE; // PMP address register
|
||||
CSR_Addr csr_addr_pmpaddr15 = 12'h3BF; // PMP address register
|
||||
|
||||
CSR_Addr csr_addr_mcycle = 12'hB00; // Machine cycle counter
|
||||
CSR_Addr csr_addr_minstret = 12'hB02; // Machine Instructions retired counter
|
||||
|
||||
CSR_Addr csr_addr_mhpmcounter3 = 12'hB03; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter4 = 12'hB04; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter5 = 12'hB05; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter6 = 12'hB06; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter7 = 12'hB07; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter8 = 12'hB08; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter9 = 12'hB09; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter10 = 12'hB0A; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter11 = 12'hB0B; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter12 = 12'hB0C; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter13 = 12'hB0D; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter14 = 12'hB0E; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter15 = 12'hB0F; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter16 = 12'hB10; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter17 = 12'hB11; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter18 = 12'hB12; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter19 = 12'hB13; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter20 = 12'hB14; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter21 = 12'hB15; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter22 = 12'hB16; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter23 = 12'hB17; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter24 = 12'hB18; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter25 = 12'hB19; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter26 = 12'hB1A; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter27 = 12'hB1B; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter28 = 12'hB1C; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter29 = 12'hB1D; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter30 = 12'hB1E; // Machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter31 = 12'hB1F; // Machine performance-monitoring counter
|
||||
|
||||
CSR_Addr csr_addr_mcycleh = 12'hB80; // Upper 32 bits of csr_mcycle (RV32I only)
|
||||
CSR_Addr csr_addr_minstreth = 12'hB82; // Upper 32 bits of csr_minstret (RV32I only)
|
||||
|
||||
CSR_Addr csr_addr_mhpmcounter3h = 12'hB83; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter4h = 12'hB84; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter5h = 12'hB85; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter6h = 12'hB86; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter7h = 12'hB87; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter8h = 12'hB88; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter9h = 12'hB89; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter10h = 12'hB8A; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter11h = 12'hB8B; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter12h = 12'hB8C; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter13h = 12'hB8D; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter14h = 12'hB8E; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter15h = 12'hB8F; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter16h = 12'hB90; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter17h = 12'hB91; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter18h = 12'hB92; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter19h = 12'hB93; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter20h = 12'hB94; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter21h = 12'hB95; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter22h = 12'hB96; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter23h = 12'hB97; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter24h = 12'hB98; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter25h = 12'hB99; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter26h = 12'hB9A; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter27h = 12'hB9B; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter28h = 12'hB9C; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter29h = 12'hB9D; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter30h = 12'hB9E; // Upper 32 bits of machine performance-monitoring counter
|
||||
CSR_Addr csr_addr_mhpmcounter31h = 12'hB9F; // Upper 32 bits of machine performance-monitoring counter
|
||||
|
||||
CSR_Addr csr_addr_mhpmevent3 = 12'h323; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent4 = 12'h324; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent5 = 12'h325; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent6 = 12'h326; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent7 = 12'h327; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent8 = 12'h328; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent9 = 12'h329; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent10 = 12'h32A; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent11 = 12'h32B; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent12 = 12'h32C; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent13 = 12'h32D; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent14 = 12'h32E; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent15 = 12'h32F; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent16 = 12'h330; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent17 = 12'h331; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent18 = 12'h332; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent19 = 12'h333; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent20 = 12'h334; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent21 = 12'h335; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent22 = 12'h336; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent23 = 12'h337; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent24 = 12'h338; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent25 = 12'h339; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent26 = 12'h33A; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent27 = 12'h33B; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent28 = 12'h33C; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent29 = 12'h33D; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent30 = 12'h33E; // Machine performance-monitoring event selector
|
||||
CSR_Addr csr_addr_mhpmevent31 = 12'h33F; // Machine performance-monitoring event selector
|
||||
|
||||
CSR_Addr csr_addr_tselect = 12'h7A0; // Debug/Trace trigger register select
|
||||
CSR_Addr csr_addr_tdata1 = 12'h7A1; // First Debug/Trace trigger data
|
||||
CSR_Addr csr_addr_tdata2 = 12'h7A2; // Secont Debug/Trace trigger data
|
||||
CSR_Addr csr_addr_tdata3 = 12'h7A3; // Third Debug/Trace trigger data
|
||||
|
||||
CSR_Addr csr_addr_dcsr = 12'h7B0; // Debug control and status
|
||||
CSR_Addr csr_addr_dpc = 12'h7B1; // Debug PC
|
||||
CSR_Addr csr_addr_dscratch0 = 12'h7B2; // Debug scratch0
|
||||
CSR_Addr csr_addr_dscratch1 = 12'h7B3; // Debug scratch1
|
||||
|
||||
// ================================================================
|
||||
// MISA
|
||||
|
||||
typedef struct {
|
||||
Bit #(2) mxl;
|
||||
Bit #(1) z; Bit #(1) y;
|
||||
Bit #(1) x; Bit #(1) w; Bit #(1) v; Bit #(1) u; Bit #(1) t; Bit #(1) s; Bit #(1) r; Bit #(1) q;
|
||||
Bit #(1) p; Bit #(1) o; Bit #(1) n; Bit #(1) m; Bit #(1) l; Bit #(1) k; Bit #(1) j; Bit #(1) i;
|
||||
Bit #(1) h; Bit #(1) g; Bit #(1) f; Bit #(1) e; Bit #(1) d; Bit #(1) c; Bit #(1) b; Bit #(1) a;
|
||||
} MISA
|
||||
deriving (Bits);
|
||||
|
||||
Bit #(2) misa_mxl_zero = 0;
|
||||
Bit #(2) misa_mxl_32 = 1;
|
||||
Bit #(2) misa_mxl_64 = 2;
|
||||
Bit #(2) misa_mxl_128 = 3;
|
||||
|
||||
function WordXL misa_to_word (MISA ms);
|
||||
return {ms.mxl,
|
||||
0, // expands appropriately for RV32 and RV64
|
||||
ms.z, ms.y,
|
||||
ms.x, ms.w, ms.v, ms.u, ms.t, ms.s, ms.r, ms.q,
|
||||
ms.p, ms.o, ms.n, ms.m, ms.l, ms.k, ms.j, ms.i,
|
||||
ms.h, ms.g, ms.f, ms.e, ms.d, ms.c, ms.b, ms.a};
|
||||
endfunction
|
||||
|
||||
function MISA word_to_misa (WordXL x);
|
||||
return MISA {mxl: x [xlen-1:xlen-2],
|
||||
z: x [25], y: x [24],
|
||||
x: x [23], w: x [22], v: x [21], u: x [20], t: x [19], s: x [18], r: x [17], q: x [16],
|
||||
p: x [15], o: x [14], n: x [13], m: x [12], l: x [11], k: x [10], j: x [9], i: x [8],
|
||||
h: x [7], g: x [6], f: x [5], e: x [4], d: x [3], c: x [2], b: x [1], a: x [0]};
|
||||
endfunction
|
||||
|
||||
instance FShow #(MISA);
|
||||
function Fmt fshow (MISA misa);
|
||||
let fmt_mxl = case (misa.mxl)
|
||||
1: $format ("mxl 32");
|
||||
2: $format ("mxl 64");
|
||||
3: $format ("mxl 128");
|
||||
default: $format ("mxl unknown %0d", misa.mxl);
|
||||
endcase;
|
||||
return ( fmt_mxl
|
||||
+ $format ((misa.z == 1'b1) ? "Z" : "")
|
||||
+ $format ((misa.y == 1'b1) ? "Y" : "")
|
||||
+ $format ((misa.x == 1'b1) ? "X" : "")
|
||||
+ $format ((misa.w == 1'b1) ? "W" : "")
|
||||
+ $format ((misa.v == 1'b1) ? "V" : "")
|
||||
+ $format ((misa.u == 1'b1) ? "U" : "")
|
||||
+ $format ((misa.t == 1'b1) ? "T" : "")
|
||||
+ $format ((misa.s == 1'b1) ? "S" : "")
|
||||
+ $format ((misa.r == 1'b1) ? "R" : "")
|
||||
+ $format ((misa.q == 1'b1) ? "Q" : "")
|
||||
+ $format ((misa.p == 1'b1) ? "P" : "")
|
||||
+ $format ((misa.o == 1'b1) ? "O" : "")
|
||||
+ $format ((misa.n == 1'b1) ? "N" : "")
|
||||
+ $format ((misa.m == 1'b1) ? "M" : "")
|
||||
+ $format ((misa.l == 1'b1) ? "L" : "")
|
||||
+ $format ((misa.k == 1'b1) ? "K" : "")
|
||||
+ $format ((misa.j == 1'b1) ? "J" : "")
|
||||
+ $format ((misa.i == 1'b1) ? "I" : "")
|
||||
+ $format ((misa.h == 1'b1) ? "H" : "")
|
||||
+ $format ((misa.g == 1'b1) ? "G" : "")
|
||||
+ $format ((misa.f == 1'b1) ? "F" : "")
|
||||
+ $format ((misa.d == 1'b1) ? "E" : "")
|
||||
+ $format ((misa.d == 1'b1) ? "D" : "")
|
||||
+ $format ((misa.c == 1'b1) ? "C" : "")
|
||||
+ $format ((misa.b == 1'b1) ? "B" : "")
|
||||
+ $format ((misa.a == 1'b1) ? "A" : ""));
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
// ================================================================
|
||||
// MSTATUS
|
||||
|
||||
Integer mstatus_sd_bitpos = xlen - 1;
|
||||
|
||||
Integer mstatus_sxl_bitpos = 34;
|
||||
Integer mstatus_uxl_bitpos = 32;
|
||||
|
||||
Integer mstatus_tsr_bitpos = 22;
|
||||
Integer mstatus_tw_bitpos = 21;
|
||||
Integer mstatus_tvm_bitpos = 20;
|
||||
|
||||
Integer mstatus_mxr_bitpos = 19;
|
||||
Integer mstatus_sum_bitpos = 18;
|
||||
Integer mstatus_mprv_bitpos = 17;
|
||||
|
||||
Integer mstatus_xs_bitpos = 15;
|
||||
Integer mstatus_fs_bitpos = 13;
|
||||
|
||||
Integer mstatus_mpp_bitpos = 11;
|
||||
Integer mstatus_WPRI_9_bitpos = 9;
|
||||
Integer mstatus_spp_bitpos = 8;
|
||||
|
||||
Integer mstatus_mpie_bitpos = 7;
|
||||
Integer mstatus_WPRI_6_bitpos = 6;
|
||||
Integer mstatus_spie_bitpos = 5;
|
||||
Integer mstatus_upie_bitpos = 4;
|
||||
|
||||
Integer mstatus_mie_bitpos = 3;
|
||||
Integer mstatus_WPRI_2_bitpos = 2;
|
||||
Integer mstatus_sie_bitpos = 1;
|
||||
Integer mstatus_uie_bitpos = 0;
|
||||
|
||||
// Values for FS and XS
|
||||
|
||||
Bit #(2) fs_xs_off = 2'h0;
|
||||
Bit #(2) fs_xs_initial = 2'h1;
|
||||
Bit #(2) fs_xs_clean = 2'h2;
|
||||
Bit #(2) fs_xs_dirty = 2'h3;
|
||||
|
||||
// Extract MSTATUS.FS field
|
||||
function Bit #(2) fv_mstatus_fs (WordXL mstatus);
|
||||
return (fv_get_bits (mstatus, fromInteger (mstatus_fs_bitpos)));
|
||||
endfunction
|
||||
|
||||
// Virtual field SD is computed from FS and XS
|
||||
function Bit #(1) fv_mstatus_sd (WordXL mstatus);
|
||||
Bit #(2) xs = fv_get_bits (mstatus, fromInteger (mstatus_xs_bitpos));
|
||||
Bit #(2) fs = fv_get_bits (mstatus, fromInteger (mstatus_fs_bitpos));
|
||||
return (((fs == fs_xs_dirty) || (xs == fs_xs_dirty)) ? 1 : 0);
|
||||
endfunction
|
||||
|
||||
function Fmt fshow_mstatus (MISA misa, WordXL mstatus);
|
||||
Bit #(2) sxl = ((misa.mxl == misa_mxl_64) ? fv_get_bits (mstatus, fromInteger (mstatus_sxl_bitpos)) : 0);
|
||||
Bit #(2) uxl = ((misa.mxl == misa_mxl_64) ? fv_get_bits (mstatus, fromInteger (mstatus_uxl_bitpos)) : 0);
|
||||
Bit #(2) xs = fv_get_bits (mstatus, fromInteger (mstatus_xs_bitpos));
|
||||
Bit #(2) fs = fv_get_bits (mstatus, fromInteger (mstatus_fs_bitpos));
|
||||
Bit #(2) mpp = fv_get_bits (mstatus, fromInteger (mstatus_mpp_bitpos));
|
||||
|
||||
return ( $format ("MStatus{")
|
||||
+ $format ("sd:%0d", fv_mstatus_sd (mstatus))
|
||||
|
||||
+ ((misa.mxl == misa_mxl_64) ? $format (" sxl:%0d uxl:%0d", sxl, uxl) : $format (""))
|
||||
|
||||
+ $format (" tsr:%0d", mstatus [mstatus_tsr_bitpos])
|
||||
+ $format (" tw:%0d", mstatus [mstatus_tw_bitpos])
|
||||
+ $format (" tvm:%0d", mstatus [mstatus_tvm_bitpos])
|
||||
+ $format (" mxr:%0d", mstatus [mstatus_mxr_bitpos])
|
||||
+ $format (" sum:%0d", mstatus [mstatus_sum_bitpos])
|
||||
+ $format (" mprv:%0d", mstatus [mstatus_mprv_bitpos])
|
||||
|
||||
+ $format (" xs:%0d", xs)
|
||||
+ $format (" fs:%0d", fs)
|
||||
|
||||
+ $format (" mpp:%0d", mpp)
|
||||
+ $format (" spp:%0d", mstatus [mstatus_spp_bitpos])
|
||||
|
||||
+ $format (" pies:%0d_%0d%0d",
|
||||
mstatus [mstatus_mpie_bitpos], mstatus [mstatus_spie_bitpos], mstatus [mstatus_upie_bitpos])
|
||||
|
||||
+ $format (" ies:%0d_%0d%0d",
|
||||
mstatus [mstatus_mie_bitpos], mstatus [mstatus_sie_bitpos], mstatus [mstatus_uie_bitpos])
|
||||
+ $format ("}")
|
||||
);
|
||||
endfunction
|
||||
|
||||
// ----------------
|
||||
// Help functions to manipulate mstatus on traps and trap-returns
|
||||
|
||||
function Priv_Mode fv_new_priv_on_exception (MISA misa,
|
||||
Priv_Mode from_priv,
|
||||
Bool interrupt,
|
||||
Exc_Code exc_code,
|
||||
Bit #(16) medeleg,
|
||||
Bit #(12) mideleg,
|
||||
Bit #(16) sedeleg,
|
||||
Bit #(12) sideleg);
|
||||
Priv_Mode to_priv = m_Priv_Mode;
|
||||
Bit #(1) deleg_bit = 1'b0;
|
||||
|
||||
// If the current priv mode is M, it cannot be delegated.
|
||||
if (from_priv < m_Priv_Mode) begin
|
||||
// If S is supported
|
||||
if (misa.s == 1'b1) begin
|
||||
// Look in medeleg/mideleg for the cause bit; if set, delegate.
|
||||
if (interrupt)
|
||||
deleg_bit = mideleg [exc_code];
|
||||
else
|
||||
deleg_bit = medeleg [exc_code];
|
||||
if (deleg_bit == 1'b1) begin
|
||||
// If the current priv mode is S, then delegate to S.
|
||||
to_priv = s_Priv_Mode;
|
||||
// If the current priv mode is U, and user mode traps are supported,
|
||||
// then consult sedeleg/sideleg to determine if delegated to U mode.
|
||||
if ((from_priv == u_Priv_Mode) && (misa.n == 1'b1)) begin
|
||||
if (interrupt)
|
||||
deleg_bit = sideleg [exc_code];
|
||||
else
|
||||
deleg_bit = sedeleg [exc_code];
|
||||
if (deleg_bit == 1'b1)
|
||||
to_priv = u_Priv_Mode;
|
||||
end
|
||||
end
|
||||
end
|
||||
else begin
|
||||
// S is not supported
|
||||
// If user mode traps are supported,
|
||||
// then consult medele/mideleg to determine if delegated to U mode.
|
||||
if (misa.n == 1'b1) begin
|
||||
// Look in medeleg/mideleg for the cause bit; if set, delegate.
|
||||
if (interrupt)
|
||||
deleg_bit = mideleg [exc_code];
|
||||
else
|
||||
deleg_bit = medeleg [exc_code];
|
||||
if (deleg_bit == 1'b1)
|
||||
to_priv = u_Priv_Mode;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return to_priv;
|
||||
endfunction
|
||||
|
||||
function WordXL fv_new_mstatus_on_exception (WordXL mstatus, Priv_Mode from_y, Priv_Mode to_x);
|
||||
Bit #(6) ie_to_x = extend (to_x);
|
||||
Bit #(6) pie_to_x = fromInteger (mstatus_upie_bitpos) + extend (to_x);
|
||||
// xPIE = xIE
|
||||
mstatus = fv_assign_bit (mstatus, pie_to_x, mstatus [ie_to_x]);
|
||||
// xIE = 0
|
||||
mstatus = fv_assign_bit (mstatus, ie_to_x, 1'b0);
|
||||
|
||||
// xPP = y Assert: (to_x == m_Priv_Mode) || (to_x == s_Priv_Mode)
|
||||
mstatus = ( (to_x == m_Priv_Mode)
|
||||
? fv_assign_bits (mstatus, fromInteger (mstatus_mpp_bitpos), from_y)
|
||||
: fv_assign_bit (mstatus, fromInteger (mstatus_spp_bitpos), from_y [0]));
|
||||
return mstatus;
|
||||
endfunction
|
||||
|
||||
function Tuple2 #(WordXL, Priv_Mode) fv_new_mstatus_on_ret (MISA misa,
|
||||
WordXL mstatus,
|
||||
Priv_Mode from_x);
|
||||
Bit #(6) ie_from_x = extend (from_x);
|
||||
Bit #(6) pie_from_x = fromInteger (mstatus_upie_bitpos) + extend (from_x);
|
||||
|
||||
// Pop the interrupt-enable stack
|
||||
// (set xIE = xPIE)
|
||||
mstatus = fv_assign_bit (mstatus, ie_from_x, mstatus [pie_from_x]);
|
||||
|
||||
// Enable interrupt at from_x
|
||||
// (set xPIE = 1)
|
||||
mstatus = fv_assign_bit (mstatus, pie_from_x, 1'b1);
|
||||
|
||||
// Pop the previous privilege mode
|
||||
// which empties the one-element stack, revealing the default value
|
||||
// (set xPP to U -- or M if U is not supported)
|
||||
Priv_Mode to_y;
|
||||
Priv_Mode default_pp = ((misa.u == 1'b1) ? u_Priv_Mode : m_Priv_Mode);
|
||||
if (from_x == m_Priv_Mode) begin
|
||||
to_y = fv_get_bits (mstatus, fromInteger (mstatus_mpp_bitpos));
|
||||
mstatus = fv_assign_bits (mstatus, fromInteger (mstatus_mpp_bitpos), default_pp);
|
||||
end
|
||||
else begin //if (from_x == s_Priv_Mode)
|
||||
to_y = {1'b0, mstatus [mstatus_spp_bitpos]};
|
||||
mstatus = fv_assign_bit (mstatus, fromInteger (mstatus_spp_bitpos), default_pp [0]);
|
||||
end
|
||||
|
||||
return tuple2 (mstatus, to_y);
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Logical view of csr_mtvec register
|
||||
|
||||
typedef enum {DIRECT, VECTORED} MTVEC_Mode
|
||||
deriving (Bits, Eq, FShow);
|
||||
|
||||
typedef struct {
|
||||
Bit #(XLEN_MINUS_2) base;
|
||||
MTVEC_Mode mode;
|
||||
} MTVec
|
||||
deriving (Bits, FShow);
|
||||
|
||||
function WordXL mtvec_to_word (MTVec mv);
|
||||
return {mv.base,
|
||||
1'b0,
|
||||
pack (mv.mode)};
|
||||
endfunction
|
||||
|
||||
function MTVec word_to_mtvec (WordXL x);
|
||||
return MTVec {base: truncate (x >> 2),
|
||||
mode: unpack (x[0])};
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Logical view of csr_mcounteren register
|
||||
typedef struct {
|
||||
Bit#(1) ir;
|
||||
Bit#(1) tm;
|
||||
Bit#(1) cy;
|
||||
} MCounteren
|
||||
deriving (Bits, FShow);
|
||||
|
||||
function WordXL mcounteren_to_word (MCounteren mc);
|
||||
return {0,
|
||||
mc.ir,
|
||||
mc.tm,
|
||||
mc.cy};
|
||||
endfunction
|
||||
|
||||
function MCounteren word_to_mcounteren (WordXL x);
|
||||
return MCounteren {ir: x[2],
|
||||
tm: x[1],
|
||||
cy: x[0]};
|
||||
endfunction
|
||||
|
||||
function MCounteren mcounteren_reset_value;
|
||||
return MCounteren {ir: 1'b0,
|
||||
tm: 1'b0,
|
||||
cy: 1'b0};
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// MIP and MIE fields (interrupt pending, interrupt enable)
|
||||
|
||||
Integer mip_usip_bitpos = 0;
|
||||
Integer mip_ssip_bitpos = 1;
|
||||
Integer mip_msip_bitpos = 3;
|
||||
|
||||
Integer mip_utip_bitpos = 4;
|
||||
Integer mip_stip_bitpos = 5;
|
||||
Integer mip_mtip_bitpos = 7;
|
||||
|
||||
Integer mip_ueip_bitpos = 8;
|
||||
Integer mip_seip_bitpos = 9;
|
||||
Integer mip_meip_bitpos = 11;
|
||||
|
||||
// ================================================================
|
||||
// MCAUSE (reason for exception)
|
||||
|
||||
typedef struct {
|
||||
Bit #(1) interrupt;
|
||||
Exc_Code exc_code;
|
||||
} MCause
|
||||
deriving (Bits);
|
||||
|
||||
instance FShow #(MCause);
|
||||
function Fmt fshow (MCause mc);
|
||||
if (mc.interrupt == 1)
|
||||
return fshow_interrupt_Exc_Code (mc.exc_code);
|
||||
else
|
||||
return fshow_trap_Exc_Code (mc.exc_code);
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
function WordXL mcause_to_word (MCause mc);
|
||||
return {mc.interrupt, 0, mc.exc_code};
|
||||
endfunction
|
||||
|
||||
function MCause word_to_mcause (WordXL x);
|
||||
return MCause {interrupt: msb (x),
|
||||
exc_code: truncate (x)};
|
||||
endfunction
|
||||
|
||||
// Exception Codes in mcause
|
||||
|
||||
typedef Bit #(4) Exc_Code;
|
||||
|
||||
// When Interrupt = 1 (interrupt)
|
||||
|
||||
Exc_Code exc_code_USER_SW_INTERRUPT = 0;
|
||||
Exc_Code exc_code_SUPERVISOR_SW_INTERRUPT = 1;
|
||||
Exc_Code exc_code_HYPERVISOR_SW_INTERRUPT = 2;
|
||||
Exc_Code exc_code_MACHINE_SW_INTERRUPT = 3;
|
||||
|
||||
Exc_Code exc_code_USER_TIMER_INTERRUPT = 4;
|
||||
Exc_Code exc_code_SUPERVISOR_TIMER_INTERRUPT = 5;
|
||||
Exc_Code exc_code_HYPERVISOR_TIMER_INTERRUPT = 6;
|
||||
Exc_Code exc_code_MACHINE_TIMER_INTERRUPT = 7;
|
||||
|
||||
Exc_Code exc_code_USER_EXTERNAL_INTERRUPT = 8;
|
||||
Exc_Code exc_code_SUPERVISOR_EXTERNAL_INTERRUPT = 9;
|
||||
Exc_Code exc_code_HYPERVISOR_EXTERNAL_INTERRUPT = 10;
|
||||
Exc_Code exc_code_MACHINE_EXTERNAL_INTERRUPT = 11;
|
||||
|
||||
// When Interrupt = 0 (trap)
|
||||
|
||||
Exc_Code exc_code_INSTR_ADDR_MISALIGNED = 0;
|
||||
Exc_Code exc_code_INSTR_ACCESS_FAULT = 1;
|
||||
Exc_Code exc_code_ILLEGAL_INSTRUCTION = 2;
|
||||
Exc_Code exc_code_BREAKPOINT = 3;
|
||||
|
||||
Exc_Code exc_code_LOAD_ADDR_MISALIGNED = 4;
|
||||
Exc_Code exc_code_LOAD_ACCESS_FAULT = 5;
|
||||
|
||||
Exc_Code exc_code_STORE_AMO_ADDR_MISALIGNED = 6;
|
||||
Exc_Code exc_code_STORE_AMO_ACCESS_FAULT = 7;
|
||||
|
||||
Exc_Code exc_code_ECALL_FROM_U = 8;
|
||||
Exc_Code exc_code_ECALL_FROM_S = 9;
|
||||
Exc_Code exc_code_RESERVED_10 = 10;
|
||||
Exc_Code exc_code_ECALL_FROM_M = 11;
|
||||
|
||||
Exc_Code exc_code_INSTR_PAGE_FAULT = 12;
|
||||
Exc_Code exc_code_LOAD_PAGE_FAULT = 13;
|
||||
Exc_Code exc_code_RESERVED_14 = 14;
|
||||
Exc_Code exc_code_STORE_AMO_PAGE_FAULT = 15;
|
||||
|
||||
|
||||
function Fmt fshow_interrupt_Exc_Code (Exc_Code exc_code);
|
||||
return case (exc_code)
|
||||
exc_code_USER_SW_INTERRUPT: $format ("USER_SW_INTERRUPT");
|
||||
exc_code_SUPERVISOR_SW_INTERRUPT: $format ("SUPERVISOR_SW_INTERRUPT");
|
||||
exc_code_HYPERVISOR_SW_INTERRUPT: $format ("HYPERVISOR_SW_INTERRUPT");
|
||||
exc_code_MACHINE_SW_INTERRUPT: $format ("MACHINE_SW_INTERRUPT");
|
||||
|
||||
exc_code_USER_TIMER_INTERRUPT: $format ("USER_TIMER_INTERRUPT");
|
||||
exc_code_SUPERVISOR_TIMER_INTERRUPT: $format ("SUPERVISOR_TIMER_INTERRUPT");
|
||||
exc_code_HYPERVISOR_TIMER_INTERRUPT: $format ("HYPERVISOR_TIMER_INTERRUPT");
|
||||
exc_code_MACHINE_TIMER_INTERRUPT: $format ("MACHINE_TIMER_INTERRUPT");
|
||||
|
||||
exc_code_USER_EXTERNAL_INTERRUPT: $format ("USER_EXTERNAL_INTERRUPT");
|
||||
exc_code_SUPERVISOR_EXTERNAL_INTERRUPT: $format ("SUPERVISOR_EXTERNAL_INTERRUPT");
|
||||
exc_code_HYPERVISOR_EXTERNAL_INTERRUPT: $format ("HYPERVISOR_EXTERNAL_INTERRUPT");
|
||||
exc_code_MACHINE_EXTERNAL_INTERRUPT: $format ("MACHINE_EXTERNAL_INTERRUPT");
|
||||
default: $format ("unknown interrupt Exc_Code %d", exc_code);
|
||||
endcase;
|
||||
endfunction
|
||||
|
||||
function Fmt fshow_trap_Exc_Code (Exc_Code exc_code);
|
||||
return case (exc_code)
|
||||
exc_code_INSTR_ADDR_MISALIGNED: $format ("INSTRUCTION_ADDR_MISALIGNED");
|
||||
exc_code_INSTR_ACCESS_FAULT: $format ("INSTRUCTION_ACCESS_FAULT");
|
||||
exc_code_ILLEGAL_INSTRUCTION: $format ("ILLEGAL_INSTRUCTION");
|
||||
exc_code_BREAKPOINT: $format ("BREAKPOINT");
|
||||
|
||||
exc_code_LOAD_ADDR_MISALIGNED: $format ("LOAD_ADDR_MISALIGNED");
|
||||
exc_code_LOAD_ACCESS_FAULT: $format ("LOAD_ACCESS_FAULT");
|
||||
|
||||
exc_code_STORE_AMO_ADDR_MISALIGNED: $format ("STORE_AMO_ADDR_MISALIGNED");
|
||||
exc_code_STORE_AMO_ACCESS_FAULT: $format ("STORE_AMO_ACCESS_FAULT");
|
||||
|
||||
exc_code_ECALL_FROM_U: $format ("ECALL_FROM_U");
|
||||
exc_code_ECALL_FROM_S: $format ("ECALL_FROM_S");
|
||||
exc_code_ECALL_FROM_M: $format ("ECALL_FROM_M");
|
||||
|
||||
exc_code_INSTR_PAGE_FAULT: $format ("INSTRUCTION_PAGE_FAULT");
|
||||
exc_code_LOAD_PAGE_FAULT: $format ("LOAD_PAGE_FAULT");
|
||||
exc_code_STORE_AMO_PAGE_FAULT: $format ("STORE_AMO_PAGE_FAULT");
|
||||
|
||||
default: $format ("unknown trap Exc_Code %d", exc_code);
|
||||
endcase;
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Function from various CSRs and current privilege to:
|
||||
// whether or not an interrupt is pending,
|
||||
// and if so, corresponding exception code
|
||||
|
||||
function Maybe #(Exc_Code) fv_interrupt_pending (MISA misa,
|
||||
WordXL mstatus,
|
||||
WordXL mip,
|
||||
WordXL mie,
|
||||
Bit #(12) mideleg,
|
||||
Bit #(12) sideleg,
|
||||
Priv_Mode cur_priv);
|
||||
|
||||
function Maybe #(Exc_Code) fv_interrupt_i_pending (Exc_Code i);
|
||||
Bool intr_pending = ((mip [i] == 1) && (mie [i] == 1));
|
||||
Priv_Mode handler_priv;
|
||||
if (mideleg [i] == 1)
|
||||
if (misa.u == 1)
|
||||
if (misa.s == 1)
|
||||
// System with M, S, U
|
||||
if (sideleg [i] == 1)
|
||||
if (misa.n == 1)
|
||||
// M->S->U delegation
|
||||
handler_priv = u_Priv_Mode;
|
||||
else
|
||||
// Error: SIDELEG [i] should not be 1 if MISA.N is 0
|
||||
handler_priv = m_Priv_Mode;
|
||||
else
|
||||
// M->S delegation
|
||||
handler_priv = s_Priv_Mode;
|
||||
else
|
||||
// System with M, U
|
||||
if (misa.n == 1)
|
||||
// M->U delegation
|
||||
handler_priv = u_Priv_Mode;
|
||||
else
|
||||
// Error: MIDELEG [i] should not be 1 if MISA.N is 0
|
||||
handler_priv = m_Priv_Mode;
|
||||
else
|
||||
// Error: System with M only; MIDELEG [i] should not be 1
|
||||
handler_priv = m_Priv_Mode;
|
||||
else
|
||||
// no delegation
|
||||
handler_priv = m_Priv_Mode;
|
||||
|
||||
Bool xie;
|
||||
if (cur_priv == u_Priv_Mode)
|
||||
xie = (mstatus [mstatus_uie_bitpos] == 1);
|
||||
else if (cur_priv == s_Priv_Mode)
|
||||
xie = (mstatus [mstatus_sie_bitpos] == 1);
|
||||
else if (cur_priv == m_Priv_Mode)
|
||||
xie = (mstatus [mstatus_mie_bitpos] == 1);
|
||||
else
|
||||
// Error: unexpected mode
|
||||
xie = False;
|
||||
|
||||
Bool glob_enabled = ( (cur_priv < handler_priv)
|
||||
|| ((cur_priv == handler_priv) && xie));
|
||||
|
||||
return ((intr_pending && glob_enabled) ? (tagged Valid i) : (tagged Invalid));
|
||||
endfunction
|
||||
|
||||
// Check all interrupts in the following decreasing priority order
|
||||
Maybe #(Exc_Code) m_ec;
|
||||
m_ec = fv_interrupt_i_pending (exc_code_MACHINE_EXTERNAL_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_MACHINE_SW_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_MACHINE_TIMER_INTERRUPT);
|
||||
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_SUPERVISOR_EXTERNAL_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_SUPERVISOR_SW_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_SUPERVISOR_TIMER_INTERRUPT);
|
||||
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_USER_EXTERNAL_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_USER_SW_INTERRUPT);
|
||||
if (m_ec matches tagged Invalid)
|
||||
m_ec = fv_interrupt_i_pending (exc_code_USER_TIMER_INTERRUPT);
|
||||
|
||||
return m_ec;
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
421
src_Core/ISA/ISA_Decls_Priv_S.bsv
Normal file
421
src_Core/ISA/ISA_Decls_Priv_S.bsv
Normal file
@@ -0,0 +1,421 @@
|
||||
// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
|
||||
|
||||
// ================================================================
|
||||
// WARNING: this is an 'include' file, not a separate BSV package!
|
||||
//
|
||||
// Contains RISC-V Supervisor-Level ISA defs, based on:
|
||||
// The RISC-V Instruction Set Manual"
|
||||
// Volume II: Privileged Architecture
|
||||
// Privileged Architecture Version 1.10
|
||||
// Document Version 1.10
|
||||
// May 7, 2017
|
||||
//
|
||||
// ================================================================
|
||||
|
||||
// Invariants on ifdefs:
|
||||
// - If RV32 is defined, we assume Sv32 for the VM system
|
||||
// - If RV64 is defined, one of SV39 or SV48 must also be defined for the VM system
|
||||
|
||||
// ================================================================
|
||||
// Supervisor-level CSRs
|
||||
|
||||
CSR_Addr csr_addr_sstatus = 12'h100; // Supervisor status
|
||||
CSR_Addr csr_addr_sedeleg = 12'h102; // Supervisor exception delegation
|
||||
CSR_Addr csr_addr_sideleg = 12'h103; // Supervisor interrupt delegation
|
||||
CSR_Addr csr_addr_sie = 12'h104; // Supervisor interrupt enable
|
||||
CSR_Addr csr_addr_stvec = 12'h105; // Supervisor trap handler base address
|
||||
CSR_Addr csr_addr_scounteren = 12'h106; // Supervisor counter enable
|
||||
|
||||
CSR_Addr csr_addr_sscratch = 12'h140; // Scratch reg for supervisor trap handlers
|
||||
CSR_Addr csr_addr_sepc = 12'h141; // Supervisor exception program counter
|
||||
CSR_Addr csr_addr_scause = 12'h142; // Supervisor trap cause
|
||||
CSR_Addr csr_addr_stval = 12'h143; // Supervisor bad address or instruction
|
||||
CSR_Addr csr_addr_sip = 12'h144; // Supervisor interrupt pending
|
||||
|
||||
CSR_Addr csr_addr_satp = 12'h180; // Supervisor address translation and protection
|
||||
|
||||
// ================================================================
|
||||
// SSTATUS
|
||||
|
||||
function Bit #(1) fn_sstatus_sd (WordXL sstatus_val); return sstatus_val [xlen-1]; endfunction
|
||||
|
||||
`ifdef RV64
|
||||
function Bit #(2) fn_sstatus_UXL (WordXL sstatus_val); return sstatus_val [33:32]; endfunction
|
||||
`endif
|
||||
|
||||
function Bit #(1) fn_sstatus_SUM (WordXL sstatus_val); return sstatus_val [19]; endfunction
|
||||
function Bit #(1) fn_sstatus_MXR (WordXL sstatus_val); return sstatus_val [18]; endfunction
|
||||
|
||||
function Bit #(2) fn_sstatus_xs (WordXL sstatus_val); return sstatus_val [16:15]; endfunction
|
||||
function Bit #(2) fn_sstatus_fs (WordXL sstatus_val); return sstatus_val [14:13]; endfunction
|
||||
|
||||
function Bit #(1) fn_sstatus_spp (WordXL sstatus_val); return sstatus_val [8]; endfunction
|
||||
|
||||
function Bit #(1) fn_sstatus_spie (WordXL sstatus_val); return sstatus_val [5]; endfunction
|
||||
function Bit #(1) fn_sstatus_upie (WordXL sstatus_val); return sstatus_val [4]; endfunction
|
||||
|
||||
function Bit #(1) fn_sstatus_sie (WordXL sstatus_val); return sstatus_val [1]; endfunction
|
||||
function Bit #(1) fn_sstatus_uie (WordXL sstatus_val); return sstatus_val [0]; endfunction
|
||||
|
||||
// ----------------
|
||||
// SCAUSE (reason for exception)
|
||||
|
||||
function Bit #(1) scause_interrupt (WordXL scause_val); return scause_val [xlen-1]; endfunction
|
||||
function Bit #(TSub #(XLEN,1)) scause_exception_code (WordXL scause_val); return scause_val [xlen-2:0]; endfunction
|
||||
|
||||
// ================================================================
|
||||
|
||||
`ifdef ISA_PRIV_S
|
||||
// ================================================================
|
||||
// SATP (supervisor address translation and protection)
|
||||
|
||||
// ----------------
|
||||
`ifdef RV32
|
||||
|
||||
typedef Bit #(1) VM_Mode;
|
||||
typedef Bit #(9) ASID;
|
||||
|
||||
function WordXL fn_mk_satp_val (VM_Mode mode, ASID asid, PA pa) = { mode, asid, pa [33:12] };
|
||||
function VM_Mode fn_satp_to_VM_Mode (Bit #(32) satp_val); return satp_val [31]; endfunction
|
||||
function ASID fn_satp_to_ASID (Bit #(32) satp_val); return satp_val [30:22]; endfunction
|
||||
function PPN fn_satp_to_PPN (Bit #(32) satp_val); return satp_val [21: 0]; endfunction
|
||||
|
||||
Bit #(1) satp_mode_RV32_bare = 1'h_0;
|
||||
Bit #(1) satp_mode_RV32_sv32 = 1'h_1;
|
||||
|
||||
`elsif RV64
|
||||
|
||||
typedef Bit #(4) VM_Mode;
|
||||
typedef Bit #(16) ASID;
|
||||
|
||||
function WordXL fn_mk_satp_val (VM_Mode mode, ASID asid, PA pa) = { mode, asid, pa [55:12] };
|
||||
function VM_Mode fn_satp_to_VM_Mode (Bit #(64) satp_val); return satp_val [63:60]; endfunction
|
||||
function ASID fn_satp_to_ASID (Bit #(64) satp_val); return satp_val [59:44]; endfunction
|
||||
function PPN fn_satp_to_PPN (Bit #(64) satp_val); return satp_val [43: 0]; endfunction
|
||||
|
||||
Bit #(4) satp_mode_RV64_bare = 4'd__0;
|
||||
Bit #(4) satp_mode_RV64_sv39 = 4'd__8;
|
||||
Bit #(4) satp_mode_RV64_sv48 = 4'd__9;
|
||||
Bit #(4) satp_mode_RV64_sv57 = 4'd_10;
|
||||
Bit #(4) satp_mode_RV64_sv64 = 4'd_11;
|
||||
|
||||
`endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Virtual and Physical addresses, page numbers, offsets
|
||||
// Page table (PT) fields and entries (PTEs)
|
||||
// For Sv32 and Sv39
|
||||
|
||||
|
||||
// ----------------
|
||||
// RV32.Sv32
|
||||
|
||||
`ifdef RV32
|
||||
|
||||
// Virtual addrs
|
||||
typedef 32 VA_sz;
|
||||
typedef 20 VPN_sz;
|
||||
typedef 10 VPN_J_sz;
|
||||
|
||||
// Physical addrs
|
||||
typedef 34 PA_sz;
|
||||
typedef 22 PPN_sz;
|
||||
typedef 12 PPN_1_sz;
|
||||
typedef 10 PPN_0_sz;
|
||||
|
||||
// Offsets within a page
|
||||
typedef 12 Offset_sz;
|
||||
|
||||
// PTNodes (nodes in the page-table tree)
|
||||
typedef 1024 PTNode_sz; // # of PTEs in a PTNode
|
||||
|
||||
// VAs, VPN selectors
|
||||
function VA fn_mkVA (VPN_J vpn1, VPN_J vpn0, Bit #(Offset_sz) offset) = { vpn1, vpn0, offset };
|
||||
function VPN fn_Addr_to_VPN (Bit #(n) addr) = addr [31:12];
|
||||
function VPN_J fn_Addr_to_VPN_1 (Bit #(n) addr) = addr [31:22];
|
||||
function VPN_J fn_Addr_to_VPN_0 (Bit #(n) addr) = addr [21:12];
|
||||
|
||||
// ----------------
|
||||
// RV64.Sv39
|
||||
|
||||
// ifdef RV32
|
||||
`elsif RV64
|
||||
|
||||
// ----------------
|
||||
// RV64.Sv39
|
||||
|
||||
// ifdef RV32 .. elsif RV64
|
||||
`ifdef SV39
|
||||
|
||||
// Virtual addrs
|
||||
typedef 39 VA_sz;
|
||||
typedef 27 VPN_sz;
|
||||
typedef 9 VPN_J_sz;
|
||||
|
||||
// Physical addrs
|
||||
typedef 64 PA_sz; // need 56b in Sv39 mode and 64b in Bare mode
|
||||
typedef 44 PPN_sz;
|
||||
typedef 26 PPN_2_sz;
|
||||
typedef 9 PPN_1_sz;
|
||||
typedef 9 PPN_0_sz;
|
||||
|
||||
// Offsets within a page
|
||||
typedef 12 Offset_sz;
|
||||
|
||||
// PTNodes (nodes in the page-table tree)
|
||||
typedef 512 PTNode_sz; // # of PTEs in a PTNode
|
||||
|
||||
// VAs, VPN selectors
|
||||
function VA fn_mkVA (VPN_J vpn2, VPN_J vpn1, VPN_J vpn0, Bit #(Offset_sz) offset) = { vpn2, vpn1, vpn0, offset };
|
||||
function VPN fn_Addr_to_VPN (Bit #(n) addr) = addr [38:12];
|
||||
function VPN_J fn_Addr_to_VPN_2 (Bit #(n) addr) = addr [38:30];
|
||||
function VPN_J fn_Addr_to_VPN_1 (Bit #(n) addr) = addr [29:21];
|
||||
function VPN_J fn_Addr_to_VPN_0 (Bit #(n) addr) = addr [20:12];
|
||||
|
||||
// ifdef RV32 .. elsif RV64 / ifdef SV39
|
||||
`else
|
||||
|
||||
// TODO: RV64.SV48 definitions
|
||||
|
||||
// ifdef RV32 .. elsif RV64 / ifdef SV39 .. else
|
||||
`endif
|
||||
|
||||
// ifdef RV32 .. elsif RV64
|
||||
`endif
|
||||
|
||||
// ----------------
|
||||
// Derived types and values
|
||||
|
||||
// Physical addrs
|
||||
Integer pa_sz = valueOf (PA_sz); typedef Bit #(PA_sz) PA;
|
||||
|
||||
function PA fn_WordXL_to_PA (WordXL eaddr);
|
||||
`ifdef RV32
|
||||
return extend (eaddr);
|
||||
`elsif RV64
|
||||
return truncate (eaddr);
|
||||
`endif
|
||||
endfunction
|
||||
|
||||
// Virtual addrs -- derived types and values
|
||||
Integer va_sz = valueOf (VA_sz); typedef Bit #(VA_sz) VA;
|
||||
|
||||
function VA fn_WordXL_to_VA (WordXL eaddr);
|
||||
`ifdef RV32
|
||||
return eaddr;
|
||||
`elsif RV64
|
||||
return truncate (eaddr);
|
||||
`endif
|
||||
endfunction
|
||||
|
||||
// Page offsets
|
||||
function Offset fn_Addr_to_Offset (Bit #(n) addr);
|
||||
return addr [offset_sz - 1: 0];
|
||||
endfunction
|
||||
|
||||
// VPNs
|
||||
Integer vpn_sz = valueOf (VPN_sz); typedef Bit #(VPN_sz) VPN;
|
||||
Integer vpn_j_sz = valueOf (VPN_J_sz); typedef Bit #(VPN_J_sz) VPN_J;
|
||||
Integer offset_sz = valueOf (Offset_sz); typedef Bit #(Offset_sz) Offset;
|
||||
|
||||
// PPNs
|
||||
Integer ppn_sz = valueOf (PPN_sz); typedef Bit #(PPN_sz) PPN;
|
||||
`ifdef RV64
|
||||
Integer ppn_2_sz = valueOf (PPN_2_sz); typedef Bit #(PPN_2_sz) PPN_2;
|
||||
`endif
|
||||
Integer ppn_1_sz = valueOf (PPN_1_sz); typedef Bit #(PPN_1_sz) PPN_1;
|
||||
Integer ppn_0_sz = valueOf (PPN_0_sz); typedef Bit #(PPN_0_sz) PPN_0;
|
||||
|
||||
`ifdef RV32
|
||||
typedef Bit #(PPN_1_sz) PPN_MEGA;
|
||||
`elsif RV64
|
||||
typedef Bit #(TAdd #(PPN_2_sz, PPN_1_sz)) PPN_MEGA;
|
||||
typedef Bit #(PPN_2_sz) PPN_GIGA;
|
||||
`endif
|
||||
|
||||
function PPN fn_PA_to_PPN (PA pa);
|
||||
return pa [ppn_sz + offset_sz - 1: offset_sz];
|
||||
endfunction
|
||||
|
||||
function PA fn_PPN_and_Offset_to_PA (PPN ppn, Offset offset);
|
||||
`ifdef RV32
|
||||
return {ppn, offset};
|
||||
`elsif RV64
|
||||
return zeroExtend ({ppn, offset});
|
||||
`endif
|
||||
endfunction
|
||||
|
||||
// ----------------
|
||||
// PTNodes (nodes in the page-table tree)
|
||||
|
||||
Integer ptnode_sz = valueOf (PTNode_sz); // # of PTEs in a PTNode
|
||||
typedef TLog #(PTNode_sz) PTNode_Index_sz;
|
||||
typedef Bit #(PTNode_Index_sz) PTNode_Index;
|
||||
Integer ptnode_index_sz = valueOf (PTNode_Index_sz);
|
||||
|
||||
// ----------------
|
||||
// PTEs (Page Table Entries in PTNodes)
|
||||
|
||||
typedef WordXL PTE;
|
||||
|
||||
Integer pte_V_offset = 0; // Valid
|
||||
Integer pte_R_offset = 1; // Read permission
|
||||
Integer pte_W_offset = 2; // Write permission
|
||||
Integer pte_X_offset = 3; // Execute permission
|
||||
Integer pte_U_offset = 4; // Accessible-to-user-mode
|
||||
Integer pte_G_offset = 5; // Global mapping
|
||||
Integer pte_A_offset = 6; // Accessed
|
||||
Integer pte_D_offset = 7; // Dirty
|
||||
Integer pte_RSW_offset = 8; // Reserved for supervisor SW
|
||||
|
||||
`ifdef RV32
|
||||
Integer pte_PPN_0_offset = 10;
|
||||
Integer pte_PPN_1_offset = 20;
|
||||
`elsif RV64
|
||||
Integer pte_PPN_0_offset = 10;
|
||||
Integer pte_PPN_1_offset = 19;
|
||||
Integer pte_PPN_2_offset = 28;
|
||||
`endif
|
||||
|
||||
function Bit #(1) fn_PTE_to_V (PTE pte);
|
||||
return pte [pte_V_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_R (PTE pte);
|
||||
return pte [pte_R_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_W (PTE pte);
|
||||
return pte [pte_W_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_X (PTE pte);
|
||||
return pte [pte_X_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_U (PTE pte);
|
||||
return pte [pte_U_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_G (PTE pte);
|
||||
return pte [pte_G_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_A (PTE pte);
|
||||
return pte [pte_A_offset];
|
||||
endfunction
|
||||
|
||||
function Bit #(1) fn_PTE_to_D (PTE pte);
|
||||
return pte [pte_D_offset];
|
||||
endfunction
|
||||
|
||||
function PPN fn_PTE_to_PPN (PTE pte);
|
||||
return pte [ppn_sz + pte_PPN_0_offset - 1 : pte_PPN_0_offset];
|
||||
endfunction
|
||||
|
||||
function PPN_MEGA fn_PTE_to_PPN_mega (PTE pte);
|
||||
return pte [ppn_sz + pte_PPN_0_offset - 1 : pte_PPN_1_offset];
|
||||
endfunction
|
||||
|
||||
`ifdef RV64
|
||||
function PPN_GIGA fn_PTE_to_PPN_giga (PTE pte);
|
||||
return pte [ppn_sz + pte_PPN_0_offset - 1 : pte_PPN_2_offset];
|
||||
endfunction
|
||||
`endif
|
||||
|
||||
function PPN_0 fn_PTE_to_PPN_0 (PTE pte);
|
||||
return pte [pte_PPN_1_offset - 1 : pte_PPN_0_offset];
|
||||
endfunction
|
||||
|
||||
function PPN_1 fn_PTE_to_PPN_1 (PTE pte);
|
||||
return pte [ppn_1_sz + pte_PPN_1_offset - 1 : pte_PPN_1_offset];
|
||||
endfunction
|
||||
|
||||
`ifdef RV64
|
||||
function PPN_2 fn_PTE_to_PPN_2 (PTE pte);
|
||||
return pte [ppn_2_sz + pte_PPN_2_offset - 1 : pte_PPN_2_offset];
|
||||
endfunction
|
||||
`endif
|
||||
|
||||
// ----------------
|
||||
// Check if a PTE is invalid (V bit clear, or improper R/W bits)
|
||||
|
||||
function Bool is_invalid_pte (PTE pte);
|
||||
return ( (fn_PTE_to_V (pte) == 0)
|
||||
|| ( (fn_PTE_to_R (pte) == 0)
|
||||
&& (fn_PTE_to_W (pte) == 1)));
|
||||
endfunction
|
||||
|
||||
// ----------------
|
||||
// Check if PTE bits deny a virtual-mem access
|
||||
|
||||
function Bool is_pte_denial (Bool dmem_not_imem, // load-store or fetch?
|
||||
Bool read_not_write,
|
||||
Priv_Mode priv,
|
||||
Bit #(1) sstatus_SUM,
|
||||
Bit #(1) mstatus_MXR,
|
||||
PTE pte);
|
||||
|
||||
let pte_u = fn_PTE_to_U (pte);
|
||||
let pte_x = fn_PTE_to_X (pte);
|
||||
let pte_w = fn_PTE_to_W (pte);
|
||||
let pte_r = fn_PTE_to_R (pte);
|
||||
|
||||
Bool priv_deny = ( ((priv == u_Priv_Mode) && (pte_u == 1'b0))
|
||||
|| ((priv == s_Priv_Mode) && (pte_u == 1'b1) && (sstatus_SUM == 1'b0)));
|
||||
|
||||
Bool access_fetch = ((! dmem_not_imem) && read_not_write);
|
||||
Bool access_load = (dmem_not_imem && read_not_write);
|
||||
Bool access_store = (dmem_not_imem && (! read_not_write));
|
||||
|
||||
let pte_r_mxr = (pte_r | (mstatus_MXR & pte_x));
|
||||
|
||||
Bool access_ok = ( (access_fetch && (pte_x == 1'b1))
|
||||
|| (access_load && (pte_r_mxr == 1'b1))
|
||||
|| (access_store && (pte_w == 1'b1)));
|
||||
|
||||
|
||||
return (priv_deny || (! access_ok));
|
||||
endfunction
|
||||
|
||||
// ----------------
|
||||
// Check PTE A and D bits
|
||||
|
||||
function Bool is_pte_A_D_fault (Bool read_not_write, PTE pte);
|
||||
return ( (fn_PTE_to_A (pte) == 0)
|
||||
|| ((! read_not_write) && (fn_PTE_to_D (pte) == 0)));
|
||||
endfunction
|
||||
|
||||
// ----------------
|
||||
// Choose particular kind of page fault
|
||||
|
||||
function Exc_Code fn_page_fault_exc_code (Bool dmem_not_imem, Bool read_not_write);
|
||||
return ((! dmem_not_imem) ? exc_code_INSTR_PAGE_FAULT
|
||||
:(read_not_write ? exc_code_LOAD_PAGE_FAULT
|
||||
: exc_code_STORE_AMO_PAGE_FAULT));
|
||||
endfunction
|
||||
|
||||
`else // ifdef ISA_PRIV_S
|
||||
// The below definitions are valid for cases where there is no VM
|
||||
// Physical addrs -- without VM, PA is same as WordXL
|
||||
typedef XLEN PA_sz;
|
||||
|
||||
// Physical addrs
|
||||
Integer pa_sz = valueOf (PA_sz); typedef Bit #(PA_sz) PA;
|
||||
|
||||
function PA fn_WordXL_to_PA (WordXL eaddr);
|
||||
return eaddr;
|
||||
endfunction
|
||||
|
||||
`endif // else-ifdef ISA_PRIV_S
|
||||
|
||||
// ----------------
|
||||
// Choose particular kind of access fault
|
||||
|
||||
function Exc_Code fn_access_exc_code (Bool dmem_not_imem, Bool read_not_write);
|
||||
return ((! dmem_not_imem) ? exc_code_INSTR_ACCESS_FAULT
|
||||
:(read_not_write ? exc_code_LOAD_ACCESS_FAULT
|
||||
: exc_code_STORE_AMO_ACCESS_FAULT));
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
362
src_Core/ISA/TV_Info.bsv
Normal file
362
src_Core/ISA/TV_Info.bsv
Normal file
@@ -0,0 +1,362 @@
|
||||
// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved
|
||||
|
||||
// ================================================================
|
||||
// Definition of Tandem Verifier Packets.
|
||||
// The CPU sends out such a packet for each instruction retired.
|
||||
// A Tandem Verifier contains a "golden model" simulator of the RISC-V
|
||||
// ISA, and verifies that the information in the packet is correct,
|
||||
// instruction by instruction.
|
||||
|
||||
// ================================================================
|
||||
|
||||
package TV_Info;
|
||||
|
||||
// ================================================================
|
||||
// Bluespec library imports
|
||||
|
||||
import DefaultValue :: *;
|
||||
import Vector :: *;
|
||||
|
||||
// ================================================================
|
||||
// Project imports
|
||||
|
||||
import ISA_Decls :: *;
|
||||
|
||||
// ================================================================
|
||||
|
||||
typedef enum {// These are not from instruction flow and do not have a PC or instruction
|
||||
TRACE_RESET,
|
||||
TRACE_GPR_WRITE,
|
||||
TRACE_FPR_WRITE,
|
||||
TRACE_CSR_WRITE,
|
||||
TRACE_MEM_WRITE,
|
||||
|
||||
// These are from instruction flow and have a PC and instruction
|
||||
TRACE_OTHER,
|
||||
TRACE_I_RD, TRACE_F_RD,
|
||||
TRACE_I_LOAD, TRACE_F_LOAD,
|
||||
TRACE_STORE,
|
||||
TRACE_AMO,
|
||||
TRACE_TRAP,
|
||||
TRACE_RET,
|
||||
TRACE_CSRRX,
|
||||
|
||||
// These are from an interrupt and has a PC but no instruction
|
||||
TRACE_INTR
|
||||
} Trace_Op
|
||||
deriving (Bits, Eq, FShow);
|
||||
|
||||
typedef struct {
|
||||
Trace_Op op;
|
||||
WordXL pc;
|
||||
ISize instr_sz;
|
||||
Bit #(32) instr;
|
||||
RegName rd;
|
||||
WordXL word1;
|
||||
WordXL word2;
|
||||
Bit #(64) word3; // Wider than WordXL because can contain paddr (in RV32, paddr can be 34 bits)
|
||||
WordXL word4;
|
||||
} Trace_Data
|
||||
deriving (Bits);
|
||||
|
||||
// RESET
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x
|
||||
function Trace_Data mkTrace_RESET ();
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_RESET;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// GPR_WRITE
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x rdval
|
||||
function Trace_Data mkTrace_GPR_WRITE (RegName rd, WordXL rdval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_GPR_WRITE;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// FPR_WRITE
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x rdval
|
||||
function Trace_Data mkTrace_FPR_WRITE (RegName rd, WordXL rdval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_FPR_WRITE;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// CSR_WRITE
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x csraddr csrval
|
||||
function Trace_Data mkTrace_CSR_WRITE (CSR_Addr csraddr, WordXL csrval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_CSR_WRITE;
|
||||
td.word3 = zeroExtend (csraddr);
|
||||
td.word4 = csrval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// MEM_WRITE
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x sz stval paddr
|
||||
function Trace_Data mkTrace_MEM_WRITE (MemReqSize sz, WordXL stval, Bit #(64) paddr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_MEM_WRITE;
|
||||
td.word1 = zeroExtend (sz);
|
||||
td.word2 = stval;
|
||||
td.word3 = paddr;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// OTHER
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x
|
||||
function Trace_Data mkTrace_OTHER (WordXL pc, ISize isize, Bit #(32) instr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_OTHER;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// I_RD
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval
|
||||
function Trace_Data mkTrace_I_RD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_I_RD;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// F_RD
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval
|
||||
function Trace_Data mkTrace_F_RD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_F_RD;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// I_LOAD
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval eaddr
|
||||
function Trace_Data mkTrace_I_LOAD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval, WordXL eaddr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_I_LOAD;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
td.word3 = zeroExtend (eaddr);
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// F_LOAD
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval eaddr
|
||||
function Trace_Data mkTrace_F_LOAD (WordXL pc, ISize isize, Bit #(32) instr, RegName rd, WordXL rdval, WordXL eaddr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_F_LOAD;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
td.word3 = zeroExtend (eaddr);
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// STORE
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x stval eaddr
|
||||
function Trace_Data mkTrace_STORE (WordXL pc, ISize isize, Bit #(32) instr, WordXL stval, WordXL eaddr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_STORE;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.word2 = stval;
|
||||
td.word3 = zeroExtend (eaddr);
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// AMO
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval stval eaddr
|
||||
function Trace_Data mkTrace_AMO (WordXL pc, ISize isize, Bit #(32) instr,
|
||||
RegName rd, WordXL rdval, WordXL stval, WordXL eaddr);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_AMO;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
td.word2 = stval;
|
||||
td.word3 = zeroExtend (eaddr);
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// TRAP
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x priv mstatus mcause mepc mtval
|
||||
function Trace_Data mkTrace_TRAP (WordXL pc, ISize isize, Bit #(32) instr,
|
||||
Priv_Mode priv, WordXL mstatus, WordXL mcause, WordXL mepc, WordXL mtval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_TRAP;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = zeroExtend (priv);
|
||||
td.word1 = mstatus;
|
||||
td.word2 = mcause;
|
||||
td.word3 = zeroExtend (mepc);
|
||||
td.word4 = mtval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// RET
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x priv mstatus
|
||||
function Trace_Data mkTrace_RET (WordXL pc, ISize isize, Bit #(32) instr, Priv_Mode priv, WordXL mstatus);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_RET;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = zeroExtend (priv);
|
||||
td.word1 = mstatus;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// CSRRX
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x x x x rdval csrvalid csraddr csrval
|
||||
function Trace_Data mkTrace_CSRRX (WordXL pc, ISize isize, Bit #(32) instr,
|
||||
RegName rd, WordXL rdval, Bool csrvalid, CSR_Addr csraddr, WordXL csrval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_CSRRX;
|
||||
td.pc = pc;
|
||||
td.instr_sz = isize;
|
||||
td.instr = instr;
|
||||
td.rd = rd;
|
||||
td.word1 = rdval;
|
||||
td.word2 = (csrvalid ? 1 : 0);
|
||||
td.word3 = zeroExtend (csraddr);
|
||||
td.word4 = csrval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// INTR
|
||||
// op pc instr_sz instr rd word1 word2 word3 word4
|
||||
// x x priv mstatus mcause mepc mtval
|
||||
function Trace_Data mkTrace_INTR (WordXL pc,
|
||||
Priv_Mode priv, WordXL mstatus, WordXL mcause, WordXL mepc, WordXL mtval);
|
||||
Trace_Data td = ?;
|
||||
td.op = TRACE_INTR;
|
||||
td.pc = pc;
|
||||
td.rd = zeroExtend (priv);
|
||||
td.word1 = mstatus;
|
||||
td.word2 = mcause;
|
||||
td.word3 = zeroExtend (mepc);
|
||||
td.word4 = mtval;
|
||||
return td;
|
||||
endfunction
|
||||
|
||||
// ================================================================
|
||||
// Display of Trace_Data for debugging
|
||||
|
||||
instance FShow #(Trace_Data);
|
||||
function Fmt fshow (Trace_Data td);
|
||||
Fmt fmt = $format ("Trace_Data{", fshow (td.op));
|
||||
|
||||
if (td.op == TRACE_RESET) begin
|
||||
end
|
||||
|
||||
else if ((td.op == TRACE_GPR_WRITE) || (td.op == TRACE_FPR_WRITE))
|
||||
fmt = fmt + $format (" rd %0d rdval %0h", td.rd, td.word1);
|
||||
|
||||
else if (td.op == TRACE_CSR_WRITE)
|
||||
fmt = fmt + $format (" csraddr %0h csrval %0h", td.word3, td.word4);
|
||||
|
||||
else if (td.op == TRACE_MEM_WRITE)
|
||||
fmt = fmt + $format (" sz %0d stval %0h paddr %0h", td.word1, td.word2, td.word3);
|
||||
|
||||
else begin
|
||||
fmt = fmt + $format (" pc %0h", td.pc);
|
||||
|
||||
if (td.op != TRACE_INTR)
|
||||
fmt = fmt + $format (" instr.%0d %0h:", pack (td.instr_sz), td.instr);
|
||||
|
||||
if ((td.op == TRACE_I_RD) || (td.op == TRACE_F_RD))
|
||||
fmt = fmt + $format (" rd %0d rdval %0h", td.rd, td.word1);
|
||||
|
||||
else if ((td.op == TRACE_I_LOAD) || (td.op == TRACE_F_LOAD))
|
||||
fmt = fmt + $format (" rd %0d rdval %0h eaddr %0h",
|
||||
td.rd, td.word1, td.word3);
|
||||
|
||||
else if (td.op == TRACE_STORE)
|
||||
fmt = fmt + $format (" stval %0h eaddr %0h", td.word2, td.word3);
|
||||
|
||||
else if (td.op == TRACE_AMO)
|
||||
fmt = fmt + $format (" rd %0d rdval %0h stval %0h eaddr %0h",
|
||||
td.rd, td.word1, td.word2, td.word3);
|
||||
|
||||
else if (td.op == TRACE_CSRRX)
|
||||
fmt = fmt + $format (" rd %0d rdval %0h csraddr %0h csrval %0h",
|
||||
td.rd, td.word1, td.word3, td.word4);
|
||||
|
||||
else if ((td.op == TRACE_TRAP) || (td.op == TRACE_INTR))
|
||||
fmt = fmt + $format (" priv %0d mstatus %0h mcause %0h mepc %0h mtval %0h",
|
||||
td.rd, td.word1, td.word2, td.word3, td.word4);
|
||||
|
||||
else if (td.op == TRACE_RET)
|
||||
fmt = fmt + $format (" priv %0d mstatus %0h", td.rd, td.word1);
|
||||
end
|
||||
|
||||
fmt = fmt + $format ("}");
|
||||
return fmt;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
// ================================================================
|
||||
// Trace_Data is encoded in module mkTV_Encode into vectors of bytes,
|
||||
// which are eventually streamed out to an on-line tandem verifier/
|
||||
// analyzer (or to a file for off-line tandem-verification/analysis).
|
||||
|
||||
// Various 'transactions' produce a Trace_Data struct (e.g., reset,
|
||||
// each instruction retirement, each GDB write to registers or memory,
|
||||
// etc.). Each struct is encoded into a vector of bytes; the number
|
||||
// of bytes depends on the kind of transaction and various encoding
|
||||
// choices.
|
||||
|
||||
typedef 72 TV_VB_SIZE; // max bytes needed for each transaction
|
||||
typedef Vector #(TV_VB_SIZE, Byte) TV_Vec_Bytes;
|
||||
|
||||
// ================================================================
|
||||
|
||||
typedef struct {
|
||||
Bit #(32) num_bytes;
|
||||
TV_Vec_Bytes vec_bytes;
|
||||
} Info_CPU_to_Verifier deriving (Bits, FShow);
|
||||
|
||||
// ================================================================
|
||||
|
||||
endpackage
|
||||
Reference in New Issue
Block a user