mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 21:57:11 -04:00
♻️ Re-factor packages and add debug pkg
This commit is contained in:
parent
f2cca400af
commit
e942c2052b
14 changed files with 404 additions and 440 deletions
2
Makefile
2
Makefile
|
@ -19,7 +19,7 @@ verilator ?= verilator
|
|||
riscv-test ?= rv64ui-p-add
|
||||
# Sources
|
||||
# Ariane PKG
|
||||
ariane_pkg := include/ariane_pkg.sv include/nbdcache_pkg.sv
|
||||
ariane_pkg := include/ariane_pkg.sv include/nbdcache_pkg.sv src/debug/dm_pkg.sv include/riscv_pkg.sv
|
||||
# utility modules
|
||||
util := $(wildcard src/util/*.svh) src/util/instruction_tracer_pkg.sv src/util/instruction_tracer_if.sv \
|
||||
src/util/generic_fifo.sv src/util/cluster_clock_gating.sv src/util/behav_sram.sv
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* File: ariane_pkg.svh
|
||||
* File: ariane_pkg.sv
|
||||
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
* Date: 8.4.2017
|
||||
*
|
||||
|
@ -214,71 +214,6 @@ package ariane_pkg;
|
|||
// we want jump accordingly e.g.: +4, +2
|
||||
} scoreboard_entry_t;
|
||||
|
||||
// --------------------
|
||||
// Instruction Types
|
||||
// --------------------
|
||||
typedef struct packed {
|
||||
logic [31:25] funct7;
|
||||
logic [24:20] rs2;
|
||||
logic [19:15] rs1;
|
||||
logic [14:12] funct3;
|
||||
logic [11:7] rd;
|
||||
logic [6:0] opcode;
|
||||
} rtype_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:20] imm;
|
||||
logic [19:15] rs1;
|
||||
logic [14:12] funct3;
|
||||
logic [11:7] rd;
|
||||
logic [6:0] opcode;
|
||||
} itype_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:25] imm;
|
||||
logic [24:20] rs2;
|
||||
logic [19:15] rs1;
|
||||
logic [14:12] funct3;
|
||||
logic [11:7] imm0;
|
||||
logic [6:0] opcode;
|
||||
} stype_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:12] funct3;
|
||||
logic [11:7] rd;
|
||||
logic [6:0] opcode;
|
||||
} utype_t;
|
||||
|
||||
typedef union packed {
|
||||
logic [31:0] instr;
|
||||
rtype_t rtype;
|
||||
itype_t itype;
|
||||
stype_t stype;
|
||||
utype_t utype;
|
||||
} instruction_t;
|
||||
|
||||
// --------------------
|
||||
// Opcodes
|
||||
// --------------------
|
||||
localparam OPCODE_SYSTEM = 7'h73;
|
||||
localparam OPCODE_FENCE = 7'h0f;
|
||||
localparam OPCODE_OP = 7'h33;
|
||||
localparam OPCODE_OP32 = 7'h3B;
|
||||
localparam OPCODE_OPIMM = 7'h13;
|
||||
localparam OPCODE_OPIMM32 = 7'h1B;
|
||||
localparam OPCODE_STORE = 7'h23;
|
||||
localparam OPCODE_LOAD = 7'h03;
|
||||
localparam OPCODE_BRANCH = 7'h63;
|
||||
localparam OPCODE_JALR = 7'h67;
|
||||
localparam OPCODE_JAL = 7'h6f;
|
||||
localparam OPCODE_AUIPC = 7'h17;
|
||||
localparam OPCODE_LUI = 7'h37;
|
||||
localparam OPCODE_AMO = 7'h2F;
|
||||
|
||||
localparam OPCODE_C_J = 3'b101;
|
||||
localparam OPCODE_C_BEQZ = 3'b110;
|
||||
localparam OPCODE_C_BNEZ = 3'b111;
|
||||
|
||||
// --------------------
|
||||
// Atomics
|
||||
// --------------------
|
||||
|
@ -286,15 +221,6 @@ package ariane_pkg;
|
|||
AMO_NONE, AMO_LR, AMO_SC, AMO_SWAP, AMO_ADD, AMO_AND, AMO_OR, AMO_XOR, AMO_MAX, AMO_MAXU, AMO_MIN, AMO_MINU
|
||||
} amo_t;
|
||||
|
||||
// --------------------
|
||||
// Privilege Spec
|
||||
// --------------------
|
||||
typedef enum logic[1:0] {
|
||||
PRIV_LVL_M = 2'b11,
|
||||
PRIV_LVL_S = 2'b01,
|
||||
PRIV_LVL_U = 2'b00
|
||||
} priv_lvl_t;
|
||||
|
||||
// memory management, pte
|
||||
typedef struct packed {
|
||||
logic [9:0] reserved;
|
||||
|
@ -351,104 +277,6 @@ package ariane_pkg;
|
|||
localparam logic [63:0] S_EXT_INTERRUPT = (1 << 63) | 9;
|
||||
localparam logic [63:0] M_EXT_INTERRUPT = (1 << 63) | 11;
|
||||
|
||||
// ----------------------
|
||||
// Performance Counters
|
||||
// ----------------------
|
||||
localparam logic [11:0] PERF_L1_ICACHE_MISS = 12'h0; // L1 Instr Cache Miss
|
||||
localparam logic [11:0] PERF_L1_DCACHE_MISS = 12'h1; // L1 Data Cache Miss
|
||||
localparam logic [11:0] PERF_ITLB_MISS = 12'h2; // ITLB Miss
|
||||
localparam logic [11:0] PERF_DTLB_MISS = 12'h3; // DTLB Miss
|
||||
localparam logic [11:0] PERF_LOAD = 12'h4; // Loads
|
||||
localparam logic [11:0] PERF_STORE = 12'h5; // Stores
|
||||
localparam logic [11:0] PERF_EXCEPTION = 12'h6; // Taken exceptions
|
||||
localparam logic [11:0] PERF_EXCEPTION_RET = 12'h7; // Exception return
|
||||
localparam logic [11:0] PERF_BRANCH_JUMP = 12'h8; // Software change of PC
|
||||
localparam logic [11:0] PERF_CALL = 12'h9; // Procedure call
|
||||
localparam logic [11:0] PERF_RET = 12'hA; // Procedure Return
|
||||
localparam logic [11:0] PERF_MIS_PREDICT = 12'hB; // Branch mis-predicted
|
||||
|
||||
// -----
|
||||
// CSRs
|
||||
// -----
|
||||
typedef enum logic [11:0] {
|
||||
// Supervisor Mode CSRs
|
||||
CSR_SSTATUS = 12'h100,
|
||||
CSR_SIE = 12'h104,
|
||||
CSR_STVEC = 12'h105,
|
||||
CSR_SCOUNTEREN = 12'h106,
|
||||
CSR_SSCRATCH = 12'h140,
|
||||
CSR_SEPC = 12'h141,
|
||||
CSR_SCAUSE = 12'h142,
|
||||
CSR_STVAL = 12'h143,
|
||||
CSR_SIP = 12'h144,
|
||||
CSR_SATP = 12'h180,
|
||||
// Machine Mode CSRs
|
||||
CSR_MSTATUS = 12'h300,
|
||||
CSR_MISA = 12'h301,
|
||||
CSR_MEDELEG = 12'h302,
|
||||
CSR_MIDELEG = 12'h303,
|
||||
CSR_MIE = 12'h304,
|
||||
CSR_MTVEC = 12'h305,
|
||||
CSR_MCOUNTEREN = 12'h306,
|
||||
CSR_MSCRATCH = 12'h340,
|
||||
CSR_MEPC = 12'h341,
|
||||
CSR_MCAUSE = 12'h342,
|
||||
CSR_MTVAL = 12'h343,
|
||||
CSR_MIP = 12'h344,
|
||||
CSR_PMPCFG0 = 12'h3A0,
|
||||
CSR_PMPADDR0 = 12'h3B0,
|
||||
CSR_MVENDORID = 12'hF11,
|
||||
CSR_MARCHID = 12'hF12,
|
||||
CSR_MIMPID = 12'hF13,
|
||||
CSR_MHARTID = 12'hF14,
|
||||
CSR_MCYCLE = 12'hB00,
|
||||
CSR_MINSTRET = 12'hB02,
|
||||
CSR_DCACHE = 12'h701,
|
||||
CSR_ICACHE = 12'h700,
|
||||
// Debug CSR
|
||||
CSR_DCSR = 12'h7b0,
|
||||
CSR_DPC = 12'h7b1,
|
||||
CSR_DSCRATCH0 = 12'h7b2, // optional
|
||||
CSR_DSCRATCH1 = 12'h7b3, // optional
|
||||
// Counters and Timers
|
||||
CSR_CYCLE = 12'hC00,
|
||||
CSR_TIME = 12'hC01,
|
||||
CSR_INSTRET = 12'hC02,
|
||||
// Performance counters
|
||||
CSR_L1_ICACHE_MISS = PERF_L1_ICACHE_MISS + 12'hC03,
|
||||
CSR_L1_DCACHE_MISS = PERF_L1_DCACHE_MISS + 12'hC03,
|
||||
CSR_ITLB_MISS = PERF_ITLB_MISS + 12'hC03,
|
||||
CSR_DTLB_MISS = PERF_DTLB_MISS + 12'hC03,
|
||||
CSR_LOAD = PERF_LOAD + 12'hC03,
|
||||
CSR_STORE = PERF_STORE + 12'hC03,
|
||||
CSR_EXCEPTION = PERF_EXCEPTION + 12'hC03,
|
||||
CSR_EXCEPTION_RET = PERF_EXCEPTION_RET + 12'hC03,
|
||||
CSR_BRANCH_JUMP = PERF_BRANCH_JUMP + 12'hC03,
|
||||
CSR_CALL = PERF_CALL + 12'hC03,
|
||||
CSR_RET = PERF_RET + 12'hC03,
|
||||
CSR_MIS_PREDICT = PERF_MIS_PREDICT + 12'hC03
|
||||
} csr_reg_t;
|
||||
|
||||
// decoded CSR address
|
||||
typedef struct packed {
|
||||
logic [1:0] rw;
|
||||
priv_lvl_t priv_lvl;
|
||||
logic [7:0] address;
|
||||
} csr_addr_t;
|
||||
|
||||
typedef union packed {
|
||||
csr_reg_t address;
|
||||
csr_addr_t csr_decode;
|
||||
} csr_t;
|
||||
|
||||
// ----------------------
|
||||
// Debug
|
||||
// ----------------------
|
||||
localparam logic [2:0] DBG_CAUSE_BREAKPOINT = 3'h1;
|
||||
localparam logic [2:0] DBG_CAUSE_TRIGGER = 3'h2;
|
||||
localparam logic [2:0] DBG_CAUSE_REQUEST = 3'h3;
|
||||
localparam logic [2:0] DBG_CAUSE_SINGLE_STEP = 3'h4;
|
||||
|
||||
// ----------------------
|
||||
// Arithmetic Functions
|
||||
// ----------------------
|
||||
|
|
|
@ -54,7 +54,7 @@ module ariane #(
|
|||
// Global Signals
|
||||
// Signals connecting more than one module
|
||||
// ------------------------------------------
|
||||
priv_lvl_t priv_lvl;
|
||||
riscv::priv_lvl_t priv_lvl;
|
||||
exception_t ex_commit; // exception from commit stage
|
||||
branchpredict_t resolved_branch;
|
||||
logic [63:0] pc_commit;
|
||||
|
@ -170,7 +170,7 @@ module ariane #(
|
|||
// --------------
|
||||
logic enable_translation_csr_ex;
|
||||
logic en_ld_st_translation_csr_ex;
|
||||
priv_lvl_t ld_st_priv_lvl_csr_ex;
|
||||
riscv::priv_lvl_t ld_st_priv_lvl_csr_ex;
|
||||
logic sum_csr_ex;
|
||||
logic mxr_csr_ex;
|
||||
logic [43:0] satp_ppn_csr_ex;
|
||||
|
|
|
@ -42,29 +42,29 @@ module compressed_decoder
|
|||
unique case (instr_i[15:13])
|
||||
3'b000: begin
|
||||
// c.addi4spn -> addi rd', x2, imm
|
||||
instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], OPCODE_OPIMM};
|
||||
instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], riscv::OpcodeOpimm};
|
||||
if (instr_i[12:5] == 8'b0) illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// c.lw -> lw rd', imm(rs1')
|
||||
instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], OPCODE_LOAD};
|
||||
instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], riscv::OpcodeLoad};
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.ld -> ld rd', imm(rs1')
|
||||
// | imm[11:0] | rs1 | funct3 | rd | opcode |
|
||||
instr_o = {4'b0, instr_i[6:5], instr_i[12:10], 3'b000, 2'b01, instr_i[9:7], 3'b011, 2'b01, instr_i[4:2], OPCODE_LOAD};
|
||||
// | imm[11:0] | rs1 | funct3 | rd | opcode|
|
||||
instr_o = {4'b0, instr_i[6:5], instr_i[12:10], 3'b000, 2'b01, instr_i[9:7], 3'b011, 2'b01, instr_i[4:2], riscv::OpcodeLoad};
|
||||
end
|
||||
|
||||
3'b110: begin
|
||||
// c.sw -> sw rs2', imm(rs1')
|
||||
instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, OPCODE_STORE};
|
||||
instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, riscv::OpcodeStore};
|
||||
end
|
||||
|
||||
3'b111: begin
|
||||
// c.sd -> sd rs2', imm(rs1')
|
||||
instr_o = {4'b0, instr_i[6:5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b011, instr_i[11:10], 3'b000, OPCODE_STORE};
|
||||
instr_o = {4'b0, instr_i[6:5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b011, instr_i[11:10], 3'b000, riscv::OpcodeStore};
|
||||
end
|
||||
|
||||
default: begin
|
||||
|
@ -79,35 +79,35 @@ module compressed_decoder
|
|||
3'b000: begin
|
||||
// c.addi -> addi rd, rd, nzimm
|
||||
// c.nop -> addi 0, 0, 0
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OPIMM};
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], riscv::OpcodeOpimm};
|
||||
end
|
||||
|
||||
// c.addiw -> addiw rd, rd, nzimm for RV64
|
||||
3'b001: begin
|
||||
if (instr_i[11:7] != 5'h0) // only valid if the destination is not r0
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OPIMM32};
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], riscv::OpcodeOpimm32};
|
||||
else
|
||||
illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
OPCODE_C_J: begin
|
||||
riscv::OpcodeCJ: begin
|
||||
// 101: c.j -> jal x0, imm
|
||||
instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], OPCODE_JAL};
|
||||
instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], riscv::OpcodeJal};
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// c.li -> addi rd, x0, nzimm
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], OPCODE_OPIMM};
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], riscv::OpcodeOpimm};
|
||||
if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.lui -> lui rd, imm
|
||||
instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], OPCODE_LUI};
|
||||
instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], riscv::OpcodeLui};
|
||||
|
||||
if (instr_i[11:7] == 5'h02) begin
|
||||
// c.addi16sp -> addi x2, x2, nzimm
|
||||
instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, OPCODE_OPIMM};
|
||||
instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, riscv::OpcodeOpimm};
|
||||
end else if (instr_i[11:7] == 5'b0) begin
|
||||
illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
@ -121,45 +121,45 @@ module compressed_decoder
|
|||
2'b01: begin
|
||||
// 00: c.srli -> srli rd, rd, shamt
|
||||
// 01: c.srai -> srai rd, rd, shamt
|
||||
instr_o = {1'b0, instr_i[10], 4'b0, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], OPCODE_OPIMM};
|
||||
instr_o = {1'b0, instr_i[10], 4'b0, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], riscv::OpcodeOpimm};
|
||||
// shamt field must be non-zero
|
||||
if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
2'b10: begin
|
||||
// c.andi -> andi rd, rd, imm
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OPIMM};
|
||||
instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], riscv::OpcodeOpimm};
|
||||
end
|
||||
|
||||
2'b11: begin
|
||||
unique case ({instr_i[12], instr_i[6:5]})
|
||||
3'b000: begin
|
||||
// c.sub -> sub rd', rd', rs2'
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], OPCODE_OP};
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], riscv::OpcodeOp};
|
||||
end
|
||||
|
||||
3'b001: begin
|
||||
// c.xor -> xor rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], OPCODE_OP};
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], riscv::OpcodeOp};
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// c.or -> or rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], OPCODE_OP};
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], riscv::OpcodeOp};
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.and -> and rd', rd', rs2'
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OP};
|
||||
instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], riscv::OpcodeOp};
|
||||
end
|
||||
|
||||
3'b100: begin
|
||||
// c.subw -> subw rd', rd', rs2'
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], OPCODE_OP32};
|
||||
instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], riscv::OpcodeOp32};
|
||||
end
|
||||
3'b101: begin
|
||||
// c.addw -> addw rd', rd', rs2'
|
||||
instr_o = {2'b00, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], OPCODE_OP32};
|
||||
instr_o = {2'b00, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], riscv::OpcodeOp32};
|
||||
end
|
||||
|
||||
3'b110,
|
||||
|
@ -174,10 +174,10 @@ module compressed_decoder
|
|||
endcase
|
||||
end
|
||||
|
||||
OPCODE_C_BEQZ, OPCODE_C_BNEZ: begin
|
||||
riscv::OpcodeCBeqz, riscv::OpcodeCBnez: begin
|
||||
// 0: c.beqz -> beq rs1', x0, imm
|
||||
// 1: c.bnez -> bne rs1', x0, imm
|
||||
instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], OPCODE_BRANCH};
|
||||
instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], riscv::OpcodeBranch};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
@ -187,37 +187,37 @@ module compressed_decoder
|
|||
unique case (instr_i[15:13])
|
||||
3'b000: begin
|
||||
// c.slli -> slli rd, rd, shamt
|
||||
instr_o = {6'b0, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], OPCODE_OPIMM};
|
||||
instr_o = {6'b0, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], riscv::OpcodeOpimm};
|
||||
if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; // register not x0
|
||||
if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1; // shift amount must be non zero
|
||||
end
|
||||
|
||||
3'b010: begin
|
||||
// c.lwsp -> lw rd, imm(x2)
|
||||
instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], OPCODE_LOAD};
|
||||
instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], riscv::OpcodeLoad};
|
||||
if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b011: begin
|
||||
// c.ldsp -> ld rd, imm(x2)
|
||||
instr_o = {3'b0, instr_i[4:2], instr_i[12], instr_i[6:5], 3'b000, 5'h02, 3'b011, instr_i[11:7], OPCODE_LOAD};
|
||||
instr_o = {3'b0, instr_i[4:2], instr_i[12], instr_i[6:5], 3'b000, 5'h02, 3'b011, instr_i[11:7], riscv::OpcodeLoad};
|
||||
if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b100: begin
|
||||
if (instr_i[12] == 1'b0) begin
|
||||
// c.mv -> add rd/rs1, x0, rs2
|
||||
instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], OPCODE_OP};
|
||||
instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], riscv::OpcodeOp};
|
||||
|
||||
if (instr_i[6:2] == 5'b0) begin
|
||||
// c.jr -> jalr x0, rd/rs1, 0
|
||||
instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, OPCODE_JALR};
|
||||
instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, riscv::OpcodeJalr};
|
||||
// rs1 != 0
|
||||
illegal_instr_o = (instr_i[11:7] != '0) ? 1'b0 : 1'b1;
|
||||
end
|
||||
end else begin
|
||||
// c.add -> add rd, rd, rs2
|
||||
instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OP};
|
||||
instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], riscv::OpcodeOp};
|
||||
|
||||
if (instr_i[11:7] == 5'b0) begin
|
||||
// c.ebreak -> ebreak
|
||||
|
@ -226,19 +226,19 @@ module compressed_decoder
|
|||
illegal_instr_o = 1'b1;
|
||||
end else if (instr_i[6:2] == 5'b0) begin
|
||||
// c.jalr -> jalr x1, rs1, 0
|
||||
instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, OPCODE_JALR};
|
||||
instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, riscv::OpcodeJalr};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
3'b110: begin
|
||||
// c.swsp -> sw rs2, imm(x2)
|
||||
instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, OPCODE_STORE};
|
||||
instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, riscv::OpcodeStore};
|
||||
end
|
||||
|
||||
3'b111: begin
|
||||
// c.sdsp -> sd rs2, imm(x2)
|
||||
instr_o = {3'b0, instr_i[9:7], instr_i[12], instr_i[6:2], 5'h02, 3'b011, instr_i[11:10], 3'b000, OPCODE_STORE};
|
||||
instr_o = {3'b0, instr_i[9:7], instr_i[12], instr_i[6:2], 5'h02, 3'b011, instr_i[11:10], 3'b000, riscv::OpcodeStore};
|
||||
end
|
||||
|
||||
default: begin
|
||||
|
|
|
@ -48,11 +48,11 @@ module csr_regfile #(
|
|||
output logic [63:0] epc_o, // Output the exception PC to PC Gen, the correct CSR (mepc, sepc) is set accordingly
|
||||
output logic eret_o, // Return from exception, set the PC of epc_o
|
||||
output logic [63:0] trap_vector_base_o, // Output base of exception vector, correct CSR is output (mtvec, stvec)
|
||||
output priv_lvl_t priv_lvl_o, // Current privilege level the CPU is in
|
||||
output riscv::priv_lvl_t priv_lvl_o, // Current privilege level the CPU is in
|
||||
// MMU
|
||||
output logic en_translation_o, // enable VA translation
|
||||
output logic en_ld_st_translation_o, // enable VA translation for load and stores
|
||||
output priv_lvl_t ld_st_priv_lvl_o, // Privilege level at which load and stores should happen
|
||||
output riscv::priv_lvl_t ld_st_priv_lvl_o, // Privilege level at which load and stores should happen
|
||||
output logic sum_o,
|
||||
output logic mxr_o,
|
||||
output logic [43:0] satp_ppn_o,
|
||||
|
@ -81,7 +81,7 @@ module csr_regfile #(
|
|||
logic read_access_exception, update_access_exception;
|
||||
logic csr_we, csr_read;
|
||||
logic [63:0] csr_wdata, csr_rdata;
|
||||
priv_lvl_t trap_to_priv_lvl;
|
||||
riscv::priv_lvl_t trap_to_priv_lvl;
|
||||
// register for enabling load store address translation, this is critical, hence the register
|
||||
logic en_ld_st_translation_d, en_ld_st_translation_q;
|
||||
logic mprv;
|
||||
|
@ -89,68 +89,25 @@ module csr_regfile #(
|
|||
logic sret; // return from S-mode exception
|
||||
logic dret; // return from debug mode
|
||||
|
||||
csr_t csr_addr;
|
||||
riscv::csr_t csr_addr;
|
||||
// ----------------
|
||||
// Assignments
|
||||
// ----------------
|
||||
assign csr_addr = csr_t'(csr_addr_i);
|
||||
assign csr_addr = riscv::csr_t'(csr_addr_i);
|
||||
// ----------------
|
||||
// CSR Registers
|
||||
// ----------------
|
||||
// privilege level register
|
||||
priv_lvl_t priv_lvl_d, priv_lvl_q;
|
||||
riscv::priv_lvl_t priv_lvl_d, priv_lvl_q;
|
||||
// we are in debug
|
||||
logic debug_mode_q, debug_mode_d;
|
||||
logic next_pc;
|
||||
|
||||
typedef struct packed {
|
||||
logic sd; // signal dirty - read-only - hardwired zero
|
||||
logic [62:36] wpri4; // writes preserved reads ignored
|
||||
logic [1:0] sxl; // variable supervisor mode xlen - hardwired to zero
|
||||
logic [1:0] uxl; // variable user mode xlen - hardwired to zero
|
||||
logic [8:0] wpri3; // writes preserved reads ignored
|
||||
logic tsr; // trap sret
|
||||
logic tw; // time wait
|
||||
logic tvm; // trap virtual memory
|
||||
logic mxr; // make executable readable
|
||||
logic sum; // permit supervisor user memory access
|
||||
logic mprv; // modify privilege - privilege level for ld/st
|
||||
logic [1:0] xs; // extension register - hardwired to zero
|
||||
logic [1:0] fs; // extension register - hardwired to zero
|
||||
priv_lvl_t mpp; // holds the previous privilege mode up to machine
|
||||
logic [1:0] wpri2; // writes preserved reads ignored
|
||||
logic spp; // holds the previous privilege mode up to supervisor
|
||||
logic mpie; // machine interrupts enable bit active prior to trap
|
||||
logic wpri1; // writes preserved reads ignored
|
||||
logic spie; // supervisor interrupts enable bit active prior to trap
|
||||
logic upie; // user interrupts enable bit active prior to trap - hardwired to zero
|
||||
logic mie; // machine interrupts enable
|
||||
logic wpri0; // writes preserved reads ignored
|
||||
logic sie; // supervisor interrupts enable
|
||||
logic uie; // user interrupts enable - hardwired to zero
|
||||
} status_t;
|
||||
riscv::status_rv64_t mstatus_q, mstatus_d;
|
||||
riscv::satp_t satp_q, satp_d;
|
||||
dm::dcsr_t dcsr_q, dcsr_d;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:28] xdebugver;
|
||||
logic [27:16] zero2;
|
||||
logic ebreakm;
|
||||
logic zero1;
|
||||
logic ebreaks;
|
||||
logic ebreaku;
|
||||
logic stepie;
|
||||
logic stopcount;
|
||||
logic stoptime;
|
||||
logic [8:6] cause;
|
||||
logic zero0;
|
||||
logic mprven;
|
||||
logic nmip;
|
||||
logic step;
|
||||
logic prv;
|
||||
} dcsr_t;
|
||||
|
||||
dcsr_t dcsr_q, dcsr_d;
|
||||
logic [63:0] dpc_q, dpc_d;
|
||||
status_t mstatus_q, mstatus_d;
|
||||
logic [63:0] mtvec_q, mtvec_d;
|
||||
logic [63:0] medeleg_q, medeleg_d;
|
||||
logic [63:0] mideleg_q, mideleg_d;
|
||||
|
@ -176,14 +133,6 @@ module csr_regfile #(
|
|||
logic [63:0] cycle_q, cycle_d;
|
||||
logic [63:0] instret_q, instret_d;
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] mode;
|
||||
logic [15:0] asid;
|
||||
logic [43:0] ppn;
|
||||
} satp_t;
|
||||
|
||||
satp_t satp_q, satp_d;
|
||||
|
||||
// ----------------
|
||||
// CSR Read logic
|
||||
// ----------------
|
||||
|
@ -196,65 +145,65 @@ module csr_regfile #(
|
|||
|
||||
if (csr_read) begin
|
||||
case (csr_addr.address)
|
||||
CSR_DCSR: csr_rdata = {31'b0, dcsr_q};
|
||||
CSR_DPC: csr_rdata = dpc_q;
|
||||
riscv::CSR_DCSR: csr_rdata = {31'b0, dcsr_q};
|
||||
riscv::CSR_DPC: csr_rdata = dpc_q;
|
||||
|
||||
CSR_SSTATUS: csr_rdata = mstatus_q & 64'h3fffe1fee;
|
||||
CSR_SIE: csr_rdata = mie_q & mideleg_q;
|
||||
CSR_SIP: csr_rdata = mip_q & mideleg_q;
|
||||
CSR_STVEC: csr_rdata = stvec_q;
|
||||
CSR_SCOUNTEREN: csr_rdata = 64'b0; // not implemented
|
||||
CSR_SSCRATCH: csr_rdata = sscratch_q;
|
||||
CSR_SEPC: csr_rdata = sepc_q;
|
||||
CSR_SCAUSE: csr_rdata = scause_q;
|
||||
CSR_STVAL: csr_rdata = stval_q;
|
||||
CSR_SATP: begin
|
||||
riscv::CSR_SSTATUS: csr_rdata = mstatus_q & 64'h3fffe1fee;
|
||||
riscv::CSR_SIE: csr_rdata = mie_q & mideleg_q;
|
||||
riscv::CSR_SIP: csr_rdata = mip_q & mideleg_q;
|
||||
riscv::CSR_STVEC: csr_rdata = stvec_q;
|
||||
riscv::CSR_SCOUNTEREN: csr_rdata = 64'b0; // not implemented
|
||||
riscv::CSR_SSCRATCH: csr_rdata = sscratch_q;
|
||||
riscv::CSR_SEPC: csr_rdata = sepc_q;
|
||||
riscv::CSR_SCAUSE: csr_rdata = scause_q;
|
||||
riscv::CSR_STVAL: csr_rdata = stval_q;
|
||||
riscv::CSR_SATP: begin
|
||||
// intercept reads to SATP if in S-Mode and TVM is enabled
|
||||
if (priv_lvl_o == PRIV_LVL_S && mstatus_q.tvm)
|
||||
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm)
|
||||
read_access_exception = 1'b1;
|
||||
else
|
||||
csr_rdata = satp_q;
|
||||
end
|
||||
|
||||
CSR_MSTATUS: csr_rdata = mstatus_q;
|
||||
CSR_MISA: csr_rdata = ISA_CODE;
|
||||
CSR_MEDELEG: csr_rdata = medeleg_q;
|
||||
CSR_MIDELEG: csr_rdata = mideleg_q;
|
||||
CSR_MIE: csr_rdata = mie_q;
|
||||
CSR_MTVEC: csr_rdata = mtvec_q;
|
||||
CSR_MCOUNTEREN: csr_rdata = 64'b0; // not implemented
|
||||
CSR_MSCRATCH: csr_rdata = mscratch_q;
|
||||
CSR_MEPC: csr_rdata = mepc_q;
|
||||
CSR_MCAUSE: csr_rdata = mcause_q;
|
||||
CSR_MTVAL: csr_rdata = mtval_q;
|
||||
CSR_MIP: csr_rdata = mip_q;
|
||||
riscv::CSR_MSTATUS: csr_rdata = mstatus_q;
|
||||
riscv::CSR_MISA: csr_rdata = ISA_CODE;
|
||||
riscv::CSR_MEDELEG: csr_rdata = medeleg_q;
|
||||
riscv::CSR_MIDELEG: csr_rdata = mideleg_q;
|
||||
riscv::CSR_MIE: csr_rdata = mie_q;
|
||||
riscv::CSR_MTVEC: csr_rdata = mtvec_q;
|
||||
riscv::CSR_MCOUNTEREN: csr_rdata = 64'b0; // not implemented
|
||||
riscv::CSR_MSCRATCH: csr_rdata = mscratch_q;
|
||||
riscv::CSR_MEPC: csr_rdata = mepc_q;
|
||||
riscv::CSR_MCAUSE: csr_rdata = mcause_q;
|
||||
riscv::CSR_MTVAL: csr_rdata = mtval_q;
|
||||
riscv::CSR_MIP: csr_rdata = mip_q;
|
||||
// Placeholders for M-mode protection
|
||||
CSR_PMPCFG0: csr_rdata = pmpcfg0_q;
|
||||
CSR_PMPADDR0: csr_rdata = pmpaddr0_q;
|
||||
CSR_MVENDORID: csr_rdata = 64'b0; // not implemented
|
||||
CSR_MARCHID: csr_rdata = 64'b0; // PULP, anonymous source (no allocated ID yet)
|
||||
CSR_MIMPID: csr_rdata = 64'b0; // not implemented
|
||||
CSR_MHARTID: csr_rdata = {53'b0, cluster_id_i[5:0], 1'b0, core_id_i[3:0]};
|
||||
CSR_MCYCLE: csr_rdata = cycle_q;
|
||||
CSR_MINSTRET: csr_rdata = instret_q;
|
||||
CSR_DCACHE: csr_rdata = dcache_q;
|
||||
CSR_ICACHE: csr_rdata = icache_q;
|
||||
riscv::CSR_PMPCFG0: csr_rdata = pmpcfg0_q;
|
||||
riscv::CSR_PMPADDR0: csr_rdata = pmpaddr0_q;
|
||||
riscv::CSR_MVENDORID: csr_rdata = 64'b0; // not implemented
|
||||
riscv::CSR_MARCHID: csr_rdata = 64'b0; // PULP, anonymous source (no allocated ID yet)
|
||||
riscv::CSR_MIMPID: csr_rdata = 64'b0; // not implemented
|
||||
riscv::CSR_MHARTID: csr_rdata = {53'b0, cluster_id_i[5:0], 1'b0, core_id_i[3:0]};
|
||||
riscv::CSR_MCYCLE: csr_rdata = cycle_q;
|
||||
riscv::CSR_MINSTRET: csr_rdata = instret_q;
|
||||
riscv::CSR_DCACHE: csr_rdata = dcache_q;
|
||||
riscv::CSR_ICACHE: csr_rdata = icache_q;
|
||||
// Counters and Timers
|
||||
CSR_CYCLE: csr_rdata = cycle_q;
|
||||
CSR_TIME: csr_rdata = time_i;
|
||||
CSR_INSTRET: csr_rdata = instret_q;
|
||||
CSR_L1_ICACHE_MISS,
|
||||
CSR_L1_DCACHE_MISS,
|
||||
CSR_ITLB_MISS,
|
||||
CSR_DTLB_MISS,
|
||||
CSR_LOAD,
|
||||
CSR_STORE,
|
||||
CSR_EXCEPTION,
|
||||
CSR_EXCEPTION_RET,
|
||||
CSR_BRANCH_JUMP,
|
||||
CSR_CALL,
|
||||
CSR_RET,
|
||||
CSR_MIS_PREDICT: csr_rdata = perf_data_i;
|
||||
riscv::CSR_CYCLE: csr_rdata = cycle_q;
|
||||
riscv::CSR_TIME: csr_rdata = time_i;
|
||||
riscv::CSR_INSTRET: csr_rdata = instret_q;
|
||||
riscv::CSR_L1_ICACHE_MISS,
|
||||
riscv::CSR_L1_DCACHE_MISS,
|
||||
riscv::CSR_ITLB_MISS,
|
||||
riscv::CSR_DTLB_MISS,
|
||||
riscv::CSR_LOAD,
|
||||
riscv::CSR_STORE,
|
||||
riscv::CSR_EXCEPTION,
|
||||
riscv::CSR_EXCEPTION_RET,
|
||||
riscv::CSR_BRANCH_JUMP,
|
||||
riscv::CSR_CALL,
|
||||
riscv::CSR_RET,
|
||||
riscv::CSR_MIS_PREDICT: csr_rdata = perf_data_i;
|
||||
default: read_access_exception = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
@ -263,7 +212,7 @@ module csr_regfile #(
|
|||
// CSR Write and update logic
|
||||
// ---------------------------
|
||||
always_comb begin : csr_update
|
||||
automatic satp_t sapt;
|
||||
automatic riscv::satp_t sapt;
|
||||
automatic logic [63:0] mip;
|
||||
automatic logic [63:0] instret;
|
||||
|
||||
|
@ -310,7 +259,7 @@ module csr_regfile #(
|
|||
if (csr_we) begin
|
||||
case (csr_addr.address)
|
||||
// debug CSR
|
||||
CSR_DCSR: begin
|
||||
riscv::CSR_DCSR: begin
|
||||
dcsr_d = csr_wdata[31:0];
|
||||
// debug is implemented
|
||||
dcsr_d.xdebugver = 4'h4;
|
||||
|
@ -319,16 +268,16 @@ module csr_regfile #(
|
|||
dcsr_d.stopcount = 1'b0;
|
||||
dcsr_d.stoptime = 1'b0;
|
||||
end
|
||||
CSR_DPC: dpc_d = csr_wdata;
|
||||
riscv::CSR_DPC: dpc_d = csr_wdata;
|
||||
// sstatus is a subset of mstatus - mask it accordingly
|
||||
CSR_SSTATUS: begin
|
||||
riscv::CSR_SSTATUS: begin
|
||||
mstatus_d = csr_wdata & 64'h3fffe1fee;
|
||||
// this instruction has side-effects
|
||||
flush_o = 1'b1;
|
||||
end
|
||||
// even machine mode interrupts can be visible and set-able to supervisor
|
||||
// if the corresponding bit in mideleg is set
|
||||
CSR_SIE: begin
|
||||
riscv::CSR_SIE: begin
|
||||
// the mideleg makes sure only delegate-able register (and therefore also only implemented registers)
|
||||
// are written
|
||||
for (int unsigned i = 0; i < 64; i++)
|
||||
|
@ -336,25 +285,25 @@ module csr_regfile #(
|
|||
mie_d[i] = csr_wdata[i];
|
||||
end
|
||||
|
||||
CSR_SIP: begin
|
||||
riscv::CSR_SIP: begin
|
||||
for (int unsigned i = 0; i < 64; i++)
|
||||
if (mideleg_q[i])
|
||||
mip_d[i] = mip[i];
|
||||
end
|
||||
|
||||
CSR_SCOUNTEREN:;
|
||||
CSR_STVEC: stvec_d = {csr_wdata[63:2], 1'b0, csr_wdata[0]};
|
||||
CSR_SSCRATCH: sscratch_d = csr_wdata;
|
||||
CSR_SEPC: sepc_d = {csr_wdata[63:1], 1'b0};
|
||||
CSR_SCAUSE: scause_d = csr_wdata;
|
||||
CSR_STVAL: stval_d = csr_wdata;
|
||||
riscv::CSR_SCOUNTEREN:;
|
||||
riscv::CSR_STVEC: stvec_d = {csr_wdata[63:2], 1'b0, csr_wdata[0]};
|
||||
riscv::CSR_SSCRATCH: sscratch_d = csr_wdata;
|
||||
riscv::CSR_SEPC: sepc_d = {csr_wdata[63:1], 1'b0};
|
||||
riscv::CSR_SCAUSE: scause_d = csr_wdata;
|
||||
riscv::CSR_STVAL: stval_d = csr_wdata;
|
||||
// supervisor address translation and protection
|
||||
CSR_SATP: begin
|
||||
riscv::CSR_SATP: begin
|
||||
// intercept SATP writes if in S-Mode and TVM is enabled
|
||||
if (priv_lvl_o == PRIV_LVL_S && mstatus_q.tvm)
|
||||
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm)
|
||||
update_access_exception = 1'b1;
|
||||
else begin
|
||||
sapt = satp_t'(csr_wdata);
|
||||
sapt = riscv::satp_t'(csr_wdata);
|
||||
// only make ASID_LEN - 1 bit stick, that way software can figure out how many ASID bits are supported
|
||||
sapt.asid = sapt.asid & {{(16-ASID_WIDTH){1'b0}}, {ASID_WIDTH{1'b1}}};
|
||||
satp_d = sapt;
|
||||
|
@ -364,7 +313,7 @@ module csr_regfile #(
|
|||
flush_o = 1'b1;
|
||||
end
|
||||
|
||||
CSR_MSTATUS: begin
|
||||
riscv::CSR_MSTATUS: begin
|
||||
mstatus_d = csr_wdata;
|
||||
mstatus_d.sxl = 2'b10;
|
||||
mstatus_d.uxl = 2'b10;
|
||||
|
@ -378,51 +327,51 @@ module csr_regfile #(
|
|||
flush_o = 1'b1;
|
||||
end
|
||||
// MISA is WARL (Write Any Value, Reads Legal Value)
|
||||
CSR_MISA:;
|
||||
riscv::CSR_MISA:;
|
||||
// machine exception delegation register
|
||||
// 0 - 15 exceptions supported
|
||||
CSR_MEDELEG: medeleg_d = csr_wdata & 64'hF7FF;
|
||||
riscv::CSR_MEDELEG: medeleg_d = csr_wdata & 64'hF7FF;
|
||||
// machine interrupt delegation register
|
||||
// we do not support user interrupt delegation
|
||||
CSR_MIDELEG: mideleg_d = csr_wdata & 64'hBBB;
|
||||
riscv::CSR_MIDELEG: mideleg_d = csr_wdata & 64'hBBB;
|
||||
|
||||
// mask the register so that unsupported interrupts can never be set
|
||||
CSR_MIE: mie_d = csr_wdata & 64'hBBB; // we only support supervisor and m-mode interrupts
|
||||
riscv::CSR_MIE: mie_d = csr_wdata & 64'hBBB; // we only support supervisor and m-mode interrupts
|
||||
|
||||
CSR_MTVEC: begin
|
||||
riscv::CSR_MTVEC: begin
|
||||
mtvec_d = {csr_wdata[63:2], 1'b0, csr_wdata[0]};
|
||||
// we are in vector mode, this implementation requires the additional
|
||||
// alignment constraint of 64 * 4 bytes
|
||||
if (csr_wdata[0])
|
||||
mtvec_d = {csr_wdata[63:8], 7'b0, csr_wdata[0]};
|
||||
end
|
||||
CSR_MCOUNTEREN:;
|
||||
riscv::CSR_MCOUNTEREN:;
|
||||
|
||||
CSR_MSCRATCH: mscratch_d = csr_wdata;
|
||||
CSR_MEPC: mepc_d = {csr_wdata[63:1], 1'b0};
|
||||
CSR_MCAUSE: mcause_d = csr_wdata;
|
||||
CSR_MTVAL: mtval_d = csr_wdata;
|
||||
CSR_MIP: mip_d = mip;
|
||||
riscv::CSR_MSCRATCH: mscratch_d = csr_wdata;
|
||||
riscv::CSR_MEPC: mepc_d = {csr_wdata[63:1], 1'b0};
|
||||
riscv::CSR_MCAUSE: mcause_d = csr_wdata;
|
||||
riscv::CSR_MTVAL: mtval_d = csr_wdata;
|
||||
riscv::CSR_MIP: mip_d = mip;
|
||||
// Placeholders for M-mode protection
|
||||
CSR_PMPCFG0: pmpcfg0_d = csr_wdata;
|
||||
CSR_PMPADDR0: pmpaddr0_d = csr_wdata;
|
||||
riscv::CSR_PMPCFG0: pmpcfg0_d = csr_wdata;
|
||||
riscv::CSR_PMPADDR0: pmpaddr0_d = csr_wdata;
|
||||
|
||||
CSR_MCYCLE: cycle_d = csr_wdata;
|
||||
CSR_MINSTRET: instret = csr_wdata;
|
||||
CSR_DCACHE: dcache_d = csr_wdata[0]; // enable bit
|
||||
CSR_ICACHE: icache_d = csr_wdata[0]; // enable bit
|
||||
CSR_L1_ICACHE_MISS,
|
||||
CSR_L1_DCACHE_MISS,
|
||||
CSR_ITLB_MISS,
|
||||
CSR_DTLB_MISS,
|
||||
CSR_LOAD,
|
||||
CSR_STORE,
|
||||
CSR_EXCEPTION,
|
||||
CSR_EXCEPTION_RET,
|
||||
CSR_BRANCH_JUMP,
|
||||
CSR_CALL,
|
||||
CSR_RET,
|
||||
CSR_MIS_PREDICT: begin
|
||||
riscv::CSR_MCYCLE: cycle_d = csr_wdata;
|
||||
riscv::CSR_MINSTRET: instret = csr_wdata;
|
||||
riscv::CSR_DCACHE: dcache_d = csr_wdata[0]; // enable bit
|
||||
riscv::CSR_ICACHE: icache_d = csr_wdata[0]; // enable bit
|
||||
riscv::CSR_L1_ICACHE_MISS,
|
||||
riscv::CSR_L1_DCACHE_MISS,
|
||||
riscv::CSR_ITLB_MISS,
|
||||
riscv::CSR_DTLB_MISS,
|
||||
riscv::CSR_LOAD,
|
||||
riscv::CSR_STORE,
|
||||
riscv::CSR_EXCEPTION,
|
||||
riscv::CSR_EXCEPTION_RET,
|
||||
riscv::CSR_BRANCH_JUMP,
|
||||
riscv::CSR_CALL,
|
||||
riscv::CSR_RET,
|
||||
riscv::CSR_MIS_PREDICT: begin
|
||||
perf_data_o = csr_wdata;
|
||||
perf_we_o = 1'b1;
|
||||
end
|
||||
|
@ -445,7 +394,7 @@ module csr_regfile #(
|
|||
// -----------------------
|
||||
// update exception CSRs
|
||||
// we got an exception update cause, pc and stval register
|
||||
trap_to_priv_lvl = PRIV_LVL_M;
|
||||
trap_to_priv_lvl = riscv::PRIV_LVL_M;
|
||||
// Exception is taken and we are not in debug mode
|
||||
// exceptions in debug mode don't update any fields
|
||||
if (!debug_mode_q && ex_i.valid) begin
|
||||
|
@ -459,11 +408,11 @@ module csr_regfile #(
|
|||
(~ex_i.cause[63] && medeleg_q[ex_i.cause[5:0]])) begin
|
||||
// traps never transition from a more-privileged mode to a less privileged mode
|
||||
// so if we are already in M mode, stay there
|
||||
trap_to_priv_lvl = (priv_lvl_o == PRIV_LVL_M) ? PRIV_LVL_M : PRIV_LVL_S;
|
||||
trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S;
|
||||
end
|
||||
|
||||
// trap to supervisor mode
|
||||
if (trap_to_priv_lvl == PRIV_LVL_S) begin
|
||||
if (trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
|
||||
// update sstatus
|
||||
mstatus_d.sie = 1'b0;
|
||||
mstatus_d.spie = mstatus_q.sie;
|
||||
|
@ -511,15 +460,15 @@ module csr_regfile #(
|
|||
if (ex_i.valid && ex_i.cause == BREAKPOINT) begin
|
||||
// check that we actually want to enter debug depending on the privilege level we are currently in
|
||||
unique case (priv_lvl_o)
|
||||
PRIV_LVL_M: begin
|
||||
riscv::PRIV_LVL_M: begin
|
||||
debug_mode_d = dcsr_q.ebreakm;
|
||||
set_debug_pc_o = dcsr_q.ebreakm;
|
||||
end
|
||||
PRIV_LVL_S: begin
|
||||
riscv::PRIV_LVL_S: begin
|
||||
debug_mode_d = dcsr_q.ebreaks;
|
||||
set_debug_pc_o = dcsr_q.ebreaks;
|
||||
end
|
||||
PRIV_LVL_U: begin
|
||||
riscv::PRIV_LVL_U: begin
|
||||
debug_mode_d = dcsr_q.ebreaku;
|
||||
set_debug_pc_o = dcsr_q.ebreaku;
|
||||
end
|
||||
|
@ -527,7 +476,7 @@ module csr_regfile #(
|
|||
endcase
|
||||
// save PC of next this instruction e.g.: the next one to be executed
|
||||
dpc_d = pc_i;
|
||||
dcsr_d.cause = DBG_CAUSE_BREAKPOINT;
|
||||
dcsr_d.cause = dm::CauseBreakpoint;
|
||||
end
|
||||
|
||||
// we've got a debug request (and we have an instruction which we can associate it to)
|
||||
|
@ -535,7 +484,7 @@ module csr_regfile #(
|
|||
dpc_d = next_pc;
|
||||
debug_mode_d = 1'b1;
|
||||
set_debug_pc_o = 1'b1;
|
||||
dcsr_d.cause = DBG_CAUSE_REQUEST;
|
||||
dcsr_d.cause = dm::CauseRequest;
|
||||
end
|
||||
|
||||
// single step enable and we just retired an instruction
|
||||
|
@ -543,7 +492,7 @@ module csr_regfile #(
|
|||
dpc_d = next_pc;
|
||||
debug_mode_d = 1'b1;
|
||||
set_debug_pc_o = 1'b1;
|
||||
dcsr_d.cause = DBG_CAUSE_SINGLE_STEP;
|
||||
dcsr_d.cause = dm::CauseSingleStep;
|
||||
end
|
||||
end
|
||||
// go in halt-state again when we encounter an exception
|
||||
|
@ -556,7 +505,7 @@ module csr_regfile #(
|
|||
// ------------------------------
|
||||
// Set the address translation at which the load and stores should occur
|
||||
// we can use the previous values since changing the address translation will always involve a pipeline flush
|
||||
if (mprv && satp_q.mode == MODE_SV39 && (mstatus_q.mpp != PRIV_LVL_M))
|
||||
if (mprv && satp_q.mode == MODE_SV39 && (mstatus_q.mpp != riscv::PRIV_LVL_M))
|
||||
en_ld_st_translation_d = 1'b1;
|
||||
else // otherwise we go with the regular settings
|
||||
en_ld_st_translation_d = en_translation_o;
|
||||
|
@ -577,7 +526,7 @@ module csr_regfile #(
|
|||
// restore the previous privilege level
|
||||
priv_lvl_d = mstatus_q.mpp;
|
||||
// set mpp to user mode
|
||||
mstatus_d.mpp = PRIV_LVL_U;
|
||||
mstatus_d.mpp = riscv::PRIV_LVL_U;
|
||||
// set mpie to 1
|
||||
mstatus_d.mpie = 1'b1;
|
||||
end
|
||||
|
@ -588,9 +537,9 @@ module csr_regfile #(
|
|||
// return the previous supervisor interrupt enable flag
|
||||
mstatus_d.sie = mstatus_d.spie;
|
||||
// restore the previous privilege level
|
||||
priv_lvl_d = priv_lvl_t'({1'b0, mstatus_d.spp});
|
||||
priv_lvl_d = riscv::priv_lvl_t'({1'b0, mstatus_d.spp});
|
||||
// set spp to user mode
|
||||
mstatus_d.spp = logic'(PRIV_LVL_U);
|
||||
mstatus_d.spp = logic'(riscv::PRIV_LVL_U);
|
||||
// set spie to 1
|
||||
mstatus_d.spie = 1'b1;
|
||||
end
|
||||
|
@ -600,7 +549,7 @@ module csr_regfile #(
|
|||
// return from exception, IF doesn't care from where we are returning
|
||||
eret_o = 1'b1;
|
||||
// restore the previous privilege level
|
||||
priv_lvl_d = priv_lvl_t'(dcsr_q.prv);
|
||||
priv_lvl_d = riscv::priv_lvl_t'(dcsr_q.prv);
|
||||
// actually return from debug mode
|
||||
debug_mode_d = 1'b0;
|
||||
end
|
||||
|
@ -711,8 +660,8 @@ module csr_regfile #(
|
|||
interrupt_global_enable = (~debug_mode_q)
|
||||
// interrupts are enabled during single step or we are not stepping
|
||||
& (~dcsr_q.step | dcsr_q.stepie)
|
||||
& ((mstatus_q.mie & (priv_lvl_o == PRIV_LVL_M))
|
||||
| (priv_lvl_o != PRIV_LVL_M));
|
||||
& ((mstatus_q.mie & (priv_lvl_o == riscv::PRIV_LVL_M))
|
||||
| (priv_lvl_o != riscv::PRIV_LVL_M));
|
||||
|
||||
if (interrupt_cause[63] && interrupt_global_enable) begin
|
||||
// we can set the cause here
|
||||
|
@ -721,7 +670,7 @@ module csr_regfile #(
|
|||
// mode equals the delegated privilege mode (S or U) and that mode’s interrupt enable bit
|
||||
// (SIE or UIE in mstatus) is set, or if the current privilege mode is less than the delegated privilege mode.
|
||||
if (mideleg_q[interrupt_cause[5:0]]) begin
|
||||
if ((mstatus_q.sie && priv_lvl_o == PRIV_LVL_S) || priv_lvl_o == PRIV_LVL_U)
|
||||
if ((mstatus_q.sie && priv_lvl_o == riscv::PRIV_LVL_S) || priv_lvl_o == riscv::PRIV_LVL_U)
|
||||
csr_exception_o.valid = 1'b1;
|
||||
end else begin
|
||||
csr_exception_o.valid = 1'b1;
|
||||
|
@ -733,7 +682,7 @@ module csr_regfile #(
|
|||
// -----------------
|
||||
// if we are reading or writing, check for the correct privilege level
|
||||
if (csr_we || csr_read) begin
|
||||
if ((priv_lvl_t'(priv_lvl_o & csr_addr.csr_decode.priv_lvl) != csr_addr.csr_decode.priv_lvl)) begin
|
||||
if ((riscv::priv_lvl_t'(priv_lvl_o & csr_addr.csr_decode.priv_lvl) != csr_addr.csr_decode.priv_lvl)) begin
|
||||
csr_exception_o.cause = ILLEGAL_INSTR;
|
||||
csr_exception_o.valid = 1'b1;
|
||||
end
|
||||
|
@ -767,7 +716,7 @@ module csr_regfile #(
|
|||
always_comb begin : priv_output
|
||||
trap_vector_base_o = {mtvec_q[63:2], 2'b0};
|
||||
// output user mode stvec
|
||||
if (trap_to_priv_lvl == PRIV_LVL_S) begin
|
||||
if (trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
|
||||
trap_vector_base_o = {stvec_q[63:2], 2'b0};
|
||||
end
|
||||
|
||||
|
@ -819,13 +768,13 @@ module csr_regfile #(
|
|||
// -------------------
|
||||
assign csr_rdata_o = csr_rdata;
|
||||
// in debug mode we execute with privilege level M
|
||||
assign priv_lvl_o = (debug_mode_q) ? PRIV_LVL_M : priv_lvl_q;
|
||||
assign priv_lvl_o = (debug_mode_q) ? riscv::PRIV_LVL_M : priv_lvl_q;
|
||||
// MMU outputs
|
||||
assign satp_ppn_o = satp_q.ppn;
|
||||
assign asid_o = satp_q.asid[ASID_WIDTH-1:0];
|
||||
assign sum_o = mstatus_q.sum;
|
||||
// we support bare memory addressing and SV39
|
||||
assign en_translation_o = (satp_q.mode == 4'h8 && priv_lvl_o != PRIV_LVL_M) ? 1'b1 : 1'b0;
|
||||
assign en_translation_o = (satp_q.mode == 4'h8 && priv_lvl_o != riscv::PRIV_LVL_M) ? 1'b1 : 1'b0;
|
||||
assign mxr_o = mstatus_q.mxr;
|
||||
assign tvm_o = mstatus_q.tvm;
|
||||
assign tw_o = mstatus_q.tw;
|
||||
|
@ -841,7 +790,7 @@ module csr_regfile #(
|
|||
// sequential process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
priv_lvl_q <= PRIV_LVL_M;
|
||||
priv_lvl_q <= riscv::PRIV_LVL_M;
|
||||
// debug signals
|
||||
debug_mode_q <= 1'b0;
|
||||
dcsr_q <= '0;
|
||||
|
|
38
src/debug/axi_riscv_dm.sv
Normal file
38
src/debug/axi_riscv_dm.sv
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Copyright 2018 ETH Zurich and University of Bologna.
|
||||
* Copyright and related rights are licensed under the Solderpad Hardware
|
||||
* License, Version 0.51 (the “License”); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
* or agreed to in writing, software, hardware and materials distributed under
|
||||
* this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* File: axi_riscv_debug_module.sv
|
||||
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
* Date: 30.6.2018
|
||||
*
|
||||
* Description: Top-level of debug module (DM). This is an AXI-Slave.
|
||||
* DTM protocol is equal to SiFives debug protocol to leverage
|
||||
* SW infrastructure re-use.
|
||||
*/
|
||||
|
||||
module axi_riscv_dm (
|
||||
input logic clk_i, // clock
|
||||
input logic rst_ni, // asynchronous reset active low
|
||||
output logic ndmreset_o, // non-debug module reset
|
||||
AXI_BUS.Slave axi_slave // bus slave
|
||||
// Connection to DTM - compatible to RocketChip Debug Module
|
||||
input logic debug_req_valid,
|
||||
output logic debug_req_ready,
|
||||
input logic [ 6:0] debug_req_bits_addr,
|
||||
input logic [ 1:0] debug_req_bits_op, // 0 = nop, 1 = read, 2 = write
|
||||
input logic [31:0] debug_req_bits_data,
|
||||
|
||||
output logic debug_resp_valid,
|
||||
input logic debug_resp_ready,
|
||||
output logic [ 1:0] debug_resp_bits_resp,
|
||||
output logic [31:0] debug_resp_bits_data
|
||||
);
|
||||
|
||||
endmodule
|
149
src/debug/dm_pkg.sv
Normal file
149
src/debug/dm_pkg.sv
Normal file
|
@ -0,0 +1,149 @@
|
|||
/* Copyright 2018 ETH Zurich and University of Bologna.
|
||||
* Copyright and related rights are licensed under the Solderpad Hardware
|
||||
* License, Version 0.51 (the “License”); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
* or agreed to in writing, software, hardware and materials distributed under
|
||||
* this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* File: axi_riscv_debug_module.sv
|
||||
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
* Date: 30.6.2018
|
||||
*
|
||||
* Description: Debug-module package, contains common system definitions.
|
||||
*
|
||||
*/
|
||||
|
||||
package dm;
|
||||
// debug registers
|
||||
localparam logic [7:0] Data0 = 8'h04;
|
||||
// up to Data11
|
||||
localparam logic [7:0] DMControl = 8'h10;
|
||||
localparam logic [7:0] DMStatus = 8'h11; // r/o
|
||||
localparam logic [7:0] Hartinfo = 8'h12;
|
||||
localparam logic [7:0] HaltSum1 = 8'h13;
|
||||
localparam logic [7:0] HAWindowSel = 8'h14;
|
||||
localparam logic [7:0] HAWindow = 8'h15;
|
||||
localparam logic [7:0] AbstractCS = 8'h16;
|
||||
localparam logic [7:0] Command = 8'h17;
|
||||
localparam logic [7:0] AbstractAuto = 8'h18;
|
||||
localparam logic [7:0] DevTreeAddr0 = 8'h19;
|
||||
localparam logic [7:0] DevTreeAddr1 = 8'h1A;
|
||||
localparam logic [7:0] DevTreeAddr2 = 8'h1B;
|
||||
localparam logic [7:0] DevTreeAddr3 = 8'h1C;
|
||||
localparam logic [7:0] NextDM = 8'h1D;
|
||||
localparam logic [7:0] ProgBuf0 = 8'h20;
|
||||
// up to ProgBuf15
|
||||
localparam logic [7:0] AuthData = 8'h30;
|
||||
localparam logic [7:0] HaltSum2 = 8'h34;
|
||||
localparam logic [7:0] HaltSum3 = 8'h35;
|
||||
localparam logic [7:0] SBAddress3 = 8'h37;
|
||||
localparam logic [7:0] SBCS = 8'h38;
|
||||
localparam logic [7:0] SBAddress0 = 8'h39;
|
||||
localparam logic [7:0] SBAddress1 = 8'h3A;
|
||||
localparam logic [7:0] SBAddress2 = 8'h3B;
|
||||
localparam logic [7:0] SBData0 = 8'h3C;
|
||||
localparam logic [7:0] SBData1 = 8'h3D;
|
||||
localparam logic [7:0] SBData2 = 8'h3E;
|
||||
localparam logic [7:0] SBData3 = 8'h3F;
|
||||
localparam logic [7:0] HaltSum0 = 8'h40;
|
||||
|
||||
// address to which a hart should jump when it was requested to halt
|
||||
localparam logic [63:0] HaltAddress = 64'h1000;
|
||||
// debug causes
|
||||
localparam logic [2:0] CauseBreakpoint = 3'h1;
|
||||
localparam logic [2:0] CauseTrigger = 3'h2;
|
||||
localparam logic [2:0] CauseRequest = 3'h3;
|
||||
localparam logic [2:0] CauseSingleStep = 3'h4;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:23] zero1;
|
||||
logic impebreak;
|
||||
logic [21:0] zero0;
|
||||
logic allhavereset;
|
||||
logic anyhavereset;
|
||||
logic allresumeack;
|
||||
logic anyresumeack;
|
||||
logic allnonexistent;
|
||||
logic anynonexistent;
|
||||
logic allunavail;
|
||||
logic anyunavail;
|
||||
logic allrunning;
|
||||
logic anyrunning;
|
||||
logic allhalted;
|
||||
logic anyhalted;
|
||||
logic authenticated;
|
||||
logic authbusy;
|
||||
logic hasresethaltreq;
|
||||
logic devtreevalid;
|
||||
logic version;
|
||||
} dmstatus_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic haltreq;
|
||||
logic resumereq;
|
||||
logic hartreset;
|
||||
logic ackhavereset;
|
||||
logic zero1;
|
||||
logic hasel;
|
||||
logic [25:16] hartsello;
|
||||
logic [15:6] hartselhi;
|
||||
logic [5:4] zero0;
|
||||
logic setresethaltreq;
|
||||
logic clrresethaltreq;
|
||||
logic ndmreset;
|
||||
logic dmactive;
|
||||
} dmcontrol_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:24] zero1;
|
||||
logic [23:20] nscratch;
|
||||
logic [19:17] zero0;
|
||||
logic dataaccess;
|
||||
logic [15:12] datasize;
|
||||
logic [11:0] dataaddr;
|
||||
} hartinfo_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:29] zero3;
|
||||
logic [28:24] progbufsize;
|
||||
logic [23:12] zero2;
|
||||
logic busy;
|
||||
logic zero1;
|
||||
logic [10:8] cmderr;
|
||||
logic [7:4] zero0;
|
||||
logic [3:0] datacount;
|
||||
} abstractcs_t;
|
||||
|
||||
typedef enum logic [7:0] {
|
||||
AccessRegister = 8'h0,
|
||||
QuickAccess = 8'h1,
|
||||
AccessMemory = 8'h2
|
||||
} cmd_t;
|
||||
|
||||
typedef struct packed {
|
||||
cmd_t cmdtype;
|
||||
logic [23:0] control;
|
||||
} command_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:28] xdebugver;
|
||||
logic [27:16] zero2;
|
||||
logic ebreakm;
|
||||
logic zero1;
|
||||
logic ebreaks;
|
||||
logic ebreaku;
|
||||
logic stepie;
|
||||
logic stopcount;
|
||||
logic stoptime;
|
||||
logic [8:6] cause;
|
||||
logic zero0;
|
||||
logic mprven;
|
||||
logic nmip;
|
||||
logic step;
|
||||
logic prv;
|
||||
} dcsr_t;
|
||||
|
||||
endpackage
|
|
@ -28,7 +28,7 @@ module decoder (
|
|||
input branchpredict_sbe_t branch_predict_i,
|
||||
input exception_t ex_i, // if an exception occured in if
|
||||
// From CSR
|
||||
input priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input riscv::priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input logic debug_mode_i, // we are in debug mode
|
||||
input logic tvm_i, // trap virtual memory
|
||||
input logic tw_i, // timeout wait
|
||||
|
@ -41,8 +41,8 @@ module decoder (
|
|||
logic ecall;
|
||||
// this instruction is a software break-point
|
||||
logic ebreak;
|
||||
instruction_t instr;
|
||||
assign instr = instruction_t'(instruction_i);
|
||||
riscv::instruction_t instr;
|
||||
assign instr = riscv::instruction_t'(instruction_i);
|
||||
// --------------------
|
||||
// Immediate select
|
||||
// --------------------
|
||||
|
@ -79,7 +79,7 @@ module decoder (
|
|||
|
||||
if (~ex_i.valid) begin
|
||||
case (instr.rtype.opcode)
|
||||
OPCODE_SYSTEM: begin
|
||||
riscv::OpcodeSystem: begin
|
||||
instruction_o.fu = CSR;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
instruction_o.rd = instr.itype.rd;
|
||||
|
@ -100,13 +100,13 @@ module decoder (
|
|||
instruction_o.op = SRET;
|
||||
// check privilege level, SRET can only be executed in S and M mode
|
||||
// we'll just decode an illegal instruction if we are in the wrong privilege level
|
||||
if (priv_lvl_i == PRIV_LVL_U) begin
|
||||
if (priv_lvl_i == riscv::PRIV_LVL_U) begin
|
||||
illegal_instr = 1'b1;
|
||||
// do not change privilege level if this is an illegal instruction
|
||||
instruction_o.op = ADD;
|
||||
end
|
||||
// if we are in S-Mode and Trap SRET (tsr) is set -> trap on illegal instruction
|
||||
if (priv_lvl_i == PRIV_LVL_S && tsr_i) begin
|
||||
if (priv_lvl_i == riscv::PRIV_LVL_S && tsr_i) begin
|
||||
illegal_instr = 1'b1;
|
||||
// do not change privilege level if this is an illegal instruction
|
||||
instruction_o.op = ADD;
|
||||
|
@ -117,7 +117,7 @@ module decoder (
|
|||
instruction_o.op = MRET;
|
||||
// check privilege level, MRET can only be executed in M mode
|
||||
// otherwise we decode an illegal instruction
|
||||
if (priv_lvl_i inside {PRIV_LVL_U, PRIV_LVL_S})
|
||||
if (priv_lvl_i inside {riscv::PRIV_LVL_U, riscv::PRIV_LVL_S})
|
||||
illegal_instr = 1'b1;
|
||||
end
|
||||
// DRET
|
||||
|
@ -131,12 +131,12 @@ module decoder (
|
|||
instruction_o.op = WFI;
|
||||
// if timeout wait is set, trap on an illegal instruction in S Mode
|
||||
// (after 0 cycles timeout)
|
||||
if (priv_lvl_i == PRIV_LVL_S && tw_i) begin
|
||||
if (priv_lvl_i == riscv::PRIV_LVL_S && tw_i) begin
|
||||
illegal_instr = 1'b1;
|
||||
instruction_o.op = ADD;
|
||||
end
|
||||
// we don't support U mode interrupts so WFI is illegal in this context
|
||||
if (priv_lvl_i == PRIV_LVL_U) begin
|
||||
if (priv_lvl_i == riscv::PRIV_LVL_U) begin
|
||||
illegal_instr = 1'b1;
|
||||
instruction_o.op = ADD;
|
||||
end
|
||||
|
@ -149,7 +149,7 @@ module decoder (
|
|||
illegal_instr = 1'b0;
|
||||
instruction_o.op = SFENCE_VMA;
|
||||
// check TVM flag and intercept SFENCE.VMA call if necessary
|
||||
if (priv_lvl_i == PRIV_LVL_S && tvm_i)
|
||||
if (priv_lvl_i == riscv::PRIV_LVL_S && tvm_i)
|
||||
illegal_instr = 1'b1;
|
||||
end
|
||||
end
|
||||
|
@ -209,7 +209,7 @@ module decoder (
|
|||
endcase
|
||||
end
|
||||
// Memory ordering instructions
|
||||
OPCODE_FENCE: begin
|
||||
riscv::OpcodeFence: begin
|
||||
instruction_o.fu = CSR;
|
||||
instruction_o.rs1 = '0;
|
||||
instruction_o.rs2 = '0;
|
||||
|
@ -235,7 +235,7 @@ module decoder (
|
|||
// --------------------------
|
||||
// Reg-Reg Operations
|
||||
// --------------------------
|
||||
OPCODE_OP: begin
|
||||
riscv::OpcodeOp: begin
|
||||
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
|
||||
instruction_o.rs1 = instr.rtype.rs1;
|
||||
instruction_o.rs2 = instr.rtype.rs2;
|
||||
|
@ -270,7 +270,7 @@ module decoder (
|
|||
// --------------------------
|
||||
// 32bit Reg-Reg Operations
|
||||
// --------------------------
|
||||
OPCODE_OP32: begin
|
||||
riscv::OpcodeOp32: begin
|
||||
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
|
||||
instruction_o.rs1 = instr.rtype.rs1;
|
||||
instruction_o.rs2 = instr.rtype.rs2;
|
||||
|
@ -294,7 +294,7 @@ module decoder (
|
|||
// --------------------------------
|
||||
// Reg-Immediate Operations
|
||||
// --------------------------------
|
||||
OPCODE_OPIMM: begin
|
||||
riscv::OpcodeOpimm: begin
|
||||
instruction_o.fu = ALU;
|
||||
imm_select = IIMM;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
|
@ -328,7 +328,7 @@ module decoder (
|
|||
// --------------------------------
|
||||
// 32 bit Reg-Immediate Operations
|
||||
// --------------------------------
|
||||
OPCODE_OPIMM32: begin
|
||||
riscv::OpcodeOpimm32: begin
|
||||
instruction_o.fu = ALU;
|
||||
imm_select = IIMM;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
|
@ -358,7 +358,7 @@ module decoder (
|
|||
// --------------------------------
|
||||
// LSU
|
||||
// --------------------------------
|
||||
OPCODE_STORE: begin
|
||||
riscv::OpcodeStore: begin
|
||||
instruction_o.fu = STORE;
|
||||
imm_select = SIMM;
|
||||
instruction_o.rs1 = instr.stype.rs1;
|
||||
|
@ -373,7 +373,7 @@ module decoder (
|
|||
endcase
|
||||
end
|
||||
|
||||
OPCODE_LOAD: begin
|
||||
riscv::OpcodeLoad: begin
|
||||
instruction_o.fu = LOAD;
|
||||
imm_select = IIMM;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
|
@ -392,7 +392,7 @@ module decoder (
|
|||
end
|
||||
|
||||
`ifdef ENABLE_ATOMICS
|
||||
OPCODE_AMO: begin
|
||||
riscv::OpcodeAmo: begin
|
||||
// we are going to use the load unit for AMOs
|
||||
instruction_o.fu = LOAD;
|
||||
instruction_o.rd = instr.stype.imm0;
|
||||
|
@ -438,7 +438,7 @@ module decoder (
|
|||
// --------------------------------
|
||||
// Control Flow Instructions
|
||||
// --------------------------------
|
||||
OPCODE_BRANCH: begin
|
||||
riscv::OpcodeBranch: begin
|
||||
imm_select = SBIMM;
|
||||
instruction_o.fu = CTRL_FLOW;
|
||||
instruction_o.rs1 = instr.stype.rs1;
|
||||
|
@ -460,7 +460,7 @@ module decoder (
|
|||
endcase
|
||||
end
|
||||
// Jump and link register
|
||||
OPCODE_JALR: begin
|
||||
riscv::OpcodeJalr: begin
|
||||
instruction_o.fu = CTRL_FLOW;
|
||||
instruction_o.op = JALR;
|
||||
instruction_o.rs1 = instr.itype.rs1;
|
||||
|
@ -472,21 +472,21 @@ module decoder (
|
|||
illegal_instr = 1'b1;
|
||||
end
|
||||
// Jump and link
|
||||
OPCODE_JAL: begin
|
||||
riscv::OpcodeJal: begin
|
||||
instruction_o.fu = CTRL_FLOW;
|
||||
imm_select = JIMM;
|
||||
instruction_o.rd = instr.utype.rd;
|
||||
is_control_flow_instr_o = 1'b1;
|
||||
end
|
||||
|
||||
OPCODE_AUIPC: begin
|
||||
riscv::OpcodeAuipc: begin
|
||||
instruction_o.fu = ALU;
|
||||
imm_select = UIMM;
|
||||
instruction_o.use_pc = 1'b1;
|
||||
instruction_o.rd = instr.utype.rd;
|
||||
end
|
||||
|
||||
OPCODE_LUI: begin
|
||||
riscv::OpcodeLui: begin
|
||||
imm_select = UIMM;
|
||||
instruction_o.fu = ALU;
|
||||
instruction_o.rd = instr.utype.rd;
|
||||
|
@ -575,9 +575,9 @@ module decoder (
|
|||
instruction_o.ex.valid = 1'b1;
|
||||
// depending on the privilege mode, set the appropriate cause
|
||||
case (priv_lvl_i)
|
||||
PRIV_LVL_M: instruction_o.ex.cause = ENV_CALL_MMODE;
|
||||
PRIV_LVL_S: instruction_o.ex.cause = ENV_CALL_SMODE;
|
||||
PRIV_LVL_U: instruction_o.ex.cause = ENV_CALL_UMODE;
|
||||
riscv::PRIV_LVL_M: instruction_o.ex.cause = ENV_CALL_MMODE;
|
||||
riscv::PRIV_LVL_S: instruction_o.ex.cause = ENV_CALL_SMODE;
|
||||
riscv::PRIV_LVL_U: instruction_o.ex.cause = ENV_CALL_UMODE;
|
||||
default:; // this should not happen
|
||||
endcase
|
||||
end else if (ebreak) begin
|
||||
|
|
|
@ -87,8 +87,8 @@ module ex_stage #(
|
|||
output logic fetch_valid_o,
|
||||
output logic [63:0] fetch_paddr_o,
|
||||
output exception_t fetch_exception_o,
|
||||
input priv_lvl_t priv_lvl_i,
|
||||
input priv_lvl_t ld_st_priv_lvl_i,
|
||||
input riscv::priv_lvl_t priv_lvl_i,
|
||||
input riscv::priv_lvl_t ld_st_priv_lvl_i,
|
||||
input logic sum_i,
|
||||
input logic mxr_i,
|
||||
input logic [43:0] satp_ppn_i,
|
||||
|
|
|
@ -364,7 +364,7 @@ module frontend #(
|
|||
// -------------------------------
|
||||
// enter debug on a hard-coded base-address
|
||||
if (set_debug_pc_i) begin
|
||||
npc_d = 64'h1000;
|
||||
npc_d = dm::HaltAddress;
|
||||
end
|
||||
fetch_vaddr = fetch_address;
|
||||
end
|
||||
|
@ -510,13 +510,13 @@ module instr_scan (
|
|||
assign rvi_call_o = (rvi_jalr_o | rvi_jump_o) & instr_i[7]; // TODO: check that this captures calls
|
||||
// differentiates between JAL and BRANCH opcode, JALR comes from BHT
|
||||
assign rvi_imm_o = (instr_i[3]) ? uj_imm(instr_i) : sb_imm(instr_i);
|
||||
assign rvi_branch_o = (instr_i[6:0] == OPCODE_BRANCH) ? 1'b1 : 1'b0;
|
||||
assign rvi_jalr_o = (instr_i[6:0] == OPCODE_JALR) ? 1'b1 : 1'b0;
|
||||
assign rvi_jump_o = (instr_i[6:0] == OPCODE_JAL) ? 1'b1 : 1'b0;
|
||||
assign rvi_branch_o = (instr_i[6:0] == riscv::OpcodeBranch) ? 1'b1 : 1'b0;
|
||||
assign rvi_jalr_o = (instr_i[6:0] == riscv::OpcodeJalr) ? 1'b1 : 1'b0;
|
||||
assign rvi_jump_o = (instr_i[6:0] == riscv::OpcodeJal) ? 1'b1 : 1'b0;
|
||||
// opcode JAL
|
||||
assign rvc_jump_o = (instr_i[15:13] == OPCODE_C_J) & is_rvc_o & (instr_i[1:0] == 2'b01);
|
||||
assign rvc_jump_o = (instr_i[15:13] == riscv::OpcodeCJ) & is_rvc_o & (instr_i[1:0] == 2'b01);
|
||||
assign rvc_jr_o = (instr_i[15:12] == 4'b1000) & (instr_i[6:2] == 5'b00000) & is_rvc_o & (instr_i[1:0] == 2'b10);
|
||||
assign rvc_branch_o = ((instr_i[15:13] == OPCODE_C_BEQZ) | (instr_i[15:13] == OPCODE_C_BNEZ)) & is_rvc_o & (instr_i[1:0] == 2'b01);
|
||||
assign rvc_branch_o = ((instr_i[15:13] == riscv::OpcodeCBeqz) | (instr_i[15:13] == riscv::OpcodeCBnez)) & is_rvc_o & (instr_i[1:0] == 2'b01);
|
||||
// check that rs1 is x1 or x5
|
||||
assign rvc_return_o = rvc_jr_o & ~instr_i[11] & ~instr_i[10] & ~instr_i[8] & instr_i[7];
|
||||
assign rvc_jalr_o = (instr_i[15:12] == 4'b1001) & (instr_i[6:2] == 5'b00000) & is_rvc_o;
|
||||
|
|
|
@ -31,7 +31,7 @@ module id_stage (
|
|||
output logic is_ctrl_flow_o, // the instruction we issue is a ctrl flow instructions
|
||||
input logic issue_instr_ack_i, // issue stage acknowledged sampling of instructions
|
||||
// from CSR file
|
||||
input priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input riscv::priv_lvl_t priv_lvl_i, // current privilege level
|
||||
input logic debug_mode_i, // we are in debug mode
|
||||
input logic tvm_i,
|
||||
input logic tw_i,
|
||||
|
|
|
@ -48,8 +48,8 @@ module lsu #(
|
|||
output logic [63:0] fetch_paddr_o, // Instruction fetch interface
|
||||
output exception_t fetch_exception_o, // Instruction fetch interface
|
||||
|
||||
input priv_lvl_t priv_lvl_i, // From CSR register file
|
||||
input priv_lvl_t ld_st_priv_lvl_i, // From CSR register file
|
||||
input riscv::priv_lvl_t priv_lvl_i, // From CSR register file
|
||||
input riscv::priv_lvl_t ld_st_priv_lvl_i, // From CSR register file
|
||||
input logic sum_i, // From CSR register file
|
||||
input logic mxr_i, // From CSR register file
|
||||
input logic [43:0] satp_ppn_i, // From CSR register file
|
||||
|
|
12
src/mmu.sv
12
src/mmu.sv
|
@ -49,8 +49,8 @@ module mmu #(
|
|||
output logic [63:0] lsu_paddr_o, // translated address
|
||||
output exception_t lsu_exception_o, // address translation threw an exception
|
||||
// General control signals
|
||||
input priv_lvl_t priv_lvl_i,
|
||||
input priv_lvl_t ld_st_priv_lvl_i,
|
||||
input riscv::priv_lvl_t priv_lvl_i,
|
||||
input riscv::priv_lvl_t ld_st_priv_lvl_i,
|
||||
input logic sum_i,
|
||||
input logic mxr_i,
|
||||
// input logic flag_mprv_i,
|
||||
|
@ -182,8 +182,8 @@ module mmu #(
|
|||
// 2. We got an access error because of insufficient permissions -> throw an access exception
|
||||
fetch_exception_o = '0;
|
||||
// Check whether we are allowed to access this memory region from a fetch perspective
|
||||
iaccess_err = fetch_req_i && (((priv_lvl_i == PRIV_LVL_U) && ~itlb_content.u)
|
||||
|| ((priv_lvl_i == PRIV_LVL_S) && itlb_content.u));
|
||||
iaccess_err = fetch_req_i && (((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u)
|
||||
|| ((priv_lvl_i == riscv::PRIV_LVL_S) && itlb_content.u));
|
||||
|
||||
// check that the upper-most bits (63-39) are the same, otherwise throw a page fault exception...
|
||||
if (fetch_req_i && !((&fetch_vaddr_i[63:39]) == 1'b1 || (|fetch_vaddr_i[63:39]) == 1'b0)) begin
|
||||
|
@ -265,8 +265,8 @@ module mmu #(
|
|||
|
||||
// Check if the User flag is set, then we may only access it in supervisor mode
|
||||
// if SUM is enabled
|
||||
daccess_err = (ld_st_priv_lvl_i == PRIV_LVL_S && !sum_i && dtlb_pte_q.u) || // SUM is not set and we are trying to access a user page in supervisor mode
|
||||
(ld_st_priv_lvl_i == PRIV_LVL_U && !dtlb_pte_q.u); // this is not a user page but we are in user mode and trying to access it
|
||||
daccess_err = (ld_st_priv_lvl_i == riscv::PRIV_LVL_S && !sum_i && dtlb_pte_q.u) || // SUM is not set and we are trying to access a user page in supervisor mode
|
||||
(ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u); // this is not a user page but we are in user mode and trying to access it
|
||||
// translation is enabled and no misaligned exception occurred
|
||||
if (en_ld_st_translation_i && !misaligned_ex_q.valid) begin
|
||||
lsu_valid_o = 1'b0;
|
||||
|
|
|
@ -50,48 +50,48 @@ module perf_counters #(
|
|||
// Update Performance Counters
|
||||
// ------------------------------
|
||||
if (l1_icache_miss_i)
|
||||
perf_counter_d[PERF_L1_ICACHE_MISS] = perf_counter_q[PERF_L1_ICACHE_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_L1_ICACHE_MISS] = perf_counter_q[riscv::PERF_L1_ICACHE_MISS] + 1'b1;
|
||||
|
||||
if (l1_dcache_miss_i)
|
||||
perf_counter_d[PERF_L1_DCACHE_MISS] = perf_counter_q[PERF_L1_DCACHE_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_L1_DCACHE_MISS] = perf_counter_q[riscv::PERF_L1_DCACHE_MISS] + 1'b1;
|
||||
|
||||
if (itlb_miss_i)
|
||||
perf_counter_d[PERF_ITLB_MISS] = perf_counter_q[PERF_ITLB_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_ITLB_MISS] = perf_counter_q[riscv::PERF_ITLB_MISS] + 1'b1;
|
||||
|
||||
if (dtlb_miss_i)
|
||||
perf_counter_d[PERF_DTLB_MISS] = perf_counter_q[PERF_DTLB_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_DTLB_MISS] = perf_counter_q[riscv::PERF_DTLB_MISS] + 1'b1;
|
||||
|
||||
// instruction related perf counters
|
||||
for (int unsigned i = 0; i < NR_COMMIT_PORTS-1; i++) begin
|
||||
if (commit_ack_i[i]) begin
|
||||
if (commit_instr_i[i].fu == LOAD)
|
||||
perf_counter_d[PERF_LOAD] = perf_counter_q[PERF_LOAD] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_LOAD] = perf_counter_q[riscv::PERF_LOAD] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == STORE)
|
||||
perf_counter_d[PERF_STORE] = perf_counter_q[PERF_STORE] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_STORE] = perf_counter_q[riscv::PERF_STORE] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == CTRL_FLOW)
|
||||
perf_counter_d[PERF_BRANCH_JUMP] = perf_counter_q[PERF_BRANCH_JUMP] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_BRANCH_JUMP] = perf_counter_q[riscv::PERF_BRANCH_JUMP] + 1'b1;
|
||||
|
||||
// The standard software calling convention uses register x1 to hold the return address on a call
|
||||
// the unconditional jump is decoded as ADD op
|
||||
if (commit_instr_i[i].fu == CTRL_FLOW && commit_instr_i[i].op == '0 && commit_instr_i[i].rd == 'b1)
|
||||
perf_counter_d[PERF_CALL] = perf_counter_q[PERF_CALL] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_CALL] = perf_counter_q[riscv::PERF_CALL] + 1'b1;
|
||||
|
||||
// Return from call
|
||||
if (commit_instr_i[i].op == JALR && commit_instr_i[i].rs1 == 'b1)
|
||||
perf_counter_d[PERF_RET] = perf_counter_q[PERF_RET] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_RET] = perf_counter_q[riscv::PERF_RET] + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (ex_i.valid)
|
||||
perf_counter_d[PERF_EXCEPTION] = perf_counter_q[PERF_EXCEPTION] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_EXCEPTION] = perf_counter_q[riscv::PERF_EXCEPTION] + 1'b1;
|
||||
|
||||
if (eret_i)
|
||||
perf_counter_d[PERF_EXCEPTION_RET] = perf_counter_q[PERF_EXCEPTION_RET] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_EXCEPTION_RET] = perf_counter_q[riscv::PERF_EXCEPTION_RET] + 1'b1;
|
||||
|
||||
if (resolved_branch_i.valid && resolved_branch_i.is_mispredict)
|
||||
perf_counter_d[PERF_MIS_PREDICT] = perf_counter_q[PERF_MIS_PREDICT] + 1'b1;
|
||||
perf_counter_d[riscv::PERF_MIS_PREDICT] = perf_counter_q[riscv::PERF_MIS_PREDICT] + 1'b1;
|
||||
|
||||
// Read Port
|
||||
if (!we_i) begin
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue