♻️ Re-factor packages and add debug pkg

This commit is contained in:
Florian Zaruba 2018-06-30 16:51:54 -07:00
parent f2cca400af
commit e942c2052b
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
14 changed files with 404 additions and 440 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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