mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
Fix #158
This commit is contained in:
parent
a3044dbfce
commit
be3c614f71
4 changed files with 40 additions and 59 deletions
|
@ -255,24 +255,6 @@ package riscv;
|
|||
localparam OpcodeC2Swsp = 3'b110;
|
||||
localparam OpcodeC2Sdsp = 3'b111;
|
||||
|
||||
// ----------------------
|
||||
// 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
|
||||
localparam logic [11:0] PERF_SB_FULL = 12'hC; // Scoreboard full
|
||||
localparam logic [11:0] PERF_IF_EMPTY = 12'hD; // instruction fetch queue empty
|
||||
|
||||
// ----------------------
|
||||
// Virtual Memory
|
||||
// ----------------------
|
||||
|
@ -390,18 +372,20 @@ package riscv;
|
|||
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_L1_ICACHE_MISS = 12'hC03, // L1 Instr Cache Miss
|
||||
CSR_L1_DCACHE_MISS = 12'hC04, // L1 Data Cache Miss
|
||||
CSR_ITLB_MISS = 12'hC05, // ITLB Miss
|
||||
CSR_DTLB_MISS = 12'hC06, // DTLB Miss
|
||||
CSR_LOAD = 12'hC07, // Loads
|
||||
CSR_STORE = 12'hC08, // Stores
|
||||
CSR_EXCEPTION = 12'hC09, // Taken exceptions
|
||||
CSR_EXCEPTION_RET = 12'hC0A, // Exception return
|
||||
CSR_BRANCH_JUMP = 12'hC0B, // Software change of PC
|
||||
CSR_CALL = 12'hC0C, // Procedure call
|
||||
CSR_RET = 12'hC0D, // Procedure Return
|
||||
CSR_MIS_PREDICT = 12'hC0E, // Branch mis-predicted
|
||||
CSR_SB_FULL = 12'hC0F, // Scoreboard full
|
||||
CSR_IF_EMPTY = 12'hC10 // instruction fetch queue empty
|
||||
} csr_reg_t;
|
||||
|
||||
localparam logic [63:0] SSTATUS_UIE = 64'h00000001;
|
||||
|
|
|
@ -187,7 +187,7 @@ module ariane #(
|
|||
// ----------------------------
|
||||
// Performance Counters <-> *
|
||||
// ----------------------------
|
||||
logic [11:0] addr_csr_perf;
|
||||
logic [4:0] addr_csr_perf;
|
||||
logic [63:0] data_csr_perf, data_perf_csr;
|
||||
logic we_csr_perf;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ module csr_regfile #(
|
|||
output logic icache_en_o, // L1 ICache Enable
|
||||
output logic dcache_en_o, // L1 DCache Enable
|
||||
// Performance Counter
|
||||
output logic [11:0] perf_addr_o, // address to performance counter module
|
||||
output logic [4:0] perf_addr_o, // read/write address to performance counter module (up to 29 aux counters possible in riscv encoding.h)
|
||||
output logic [63:0] perf_data_o, // write data to performance counter module
|
||||
input logic [63:0] perf_data_i, // read data from performance counter module
|
||||
output logic perf_we_o
|
||||
|
@ -149,8 +149,7 @@ module csr_regfile #(
|
|||
// a read access exception can only occur if we attempt to read a CSR which does not exist
|
||||
read_access_exception = 1'b0;
|
||||
csr_rdata = 64'b0;
|
||||
// feed through address of performance counter
|
||||
perf_addr_o = csr_addr.address;
|
||||
perf_addr_o = csr_addr.address[4:0];;
|
||||
|
||||
if (csr_read) begin
|
||||
unique case (csr_addr.address)
|
||||
|
@ -249,7 +248,9 @@ module csr_regfile #(
|
|||
riscv::CSR_BRANCH_JUMP,
|
||||
riscv::CSR_CALL,
|
||||
riscv::CSR_RET,
|
||||
riscv::CSR_MIS_PREDICT: csr_rdata = perf_data_i;
|
||||
riscv::CSR_MIS_PREDICT,
|
||||
riscv::CSR_SB_FULL,
|
||||
riscv::CSR_IF_EMPTY: csr_rdata = perf_data_i;
|
||||
default: read_access_exception = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ module perf_counters #(
|
|||
input logic rst_ni,
|
||||
input logic debug_mode_i, // debug mode
|
||||
// SRAM like interface
|
||||
input logic [11:0] addr_i, // read/write address
|
||||
input logic [4:0] addr_i, // read/write address (up to 29 aux counters possible in riscv encoding.h)
|
||||
input logic we_i, // write enable
|
||||
input logic [63:0] data_i, // data to write
|
||||
output logic [63:0] data_o, // data to read
|
||||
|
@ -45,7 +45,7 @@ module perf_counters #(
|
|||
input branchpredict_t resolved_branch_i
|
||||
);
|
||||
|
||||
logic [13:0][63:0] perf_counter_d, perf_counter_q;
|
||||
logic [riscv::CSR_IF_EMPTY[4:0] : riscv::CSR_L1_ICACHE_MISS[4:0]][63:0] perf_counter_d, perf_counter_q;
|
||||
|
||||
always_comb begin : perf_counters
|
||||
perf_counter_d = perf_counter_q;
|
||||
|
@ -57,66 +57,62 @@ module perf_counters #(
|
|||
// Update Performance Counters
|
||||
// ------------------------------
|
||||
if (l1_icache_miss_i)
|
||||
perf_counter_d[riscv::PERF_L1_ICACHE_MISS] = perf_counter_q[riscv::PERF_L1_ICACHE_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_L1_ICACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_L1_ICACHE_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (l1_dcache_miss_i)
|
||||
perf_counter_d[riscv::PERF_L1_DCACHE_MISS] = perf_counter_q[riscv::PERF_L1_DCACHE_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_L1_DCACHE_MISS[4:0]] = perf_counter_q[riscv::CSR_L1_DCACHE_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (itlb_miss_i)
|
||||
perf_counter_d[riscv::PERF_ITLB_MISS] = perf_counter_q[riscv::PERF_ITLB_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_ITLB_MISS[4:0]] = perf_counter_q[riscv::CSR_ITLB_MISS[4:0]] + 1'b1;
|
||||
|
||||
if (dtlb_miss_i)
|
||||
perf_counter_d[riscv::PERF_DTLB_MISS] = perf_counter_q[riscv::PERF_DTLB_MISS] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_DTLB_MISS[4:0]] = perf_counter_q[riscv::CSR_DTLB_MISS[4:0]] + 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[riscv::PERF_LOAD] = perf_counter_q[riscv::PERF_LOAD] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_LOAD[4:0]] = perf_counter_q[riscv::CSR_LOAD[4:0]] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == STORE)
|
||||
perf_counter_d[riscv::PERF_STORE] = perf_counter_q[riscv::PERF_STORE] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_STORE[4:0]] = perf_counter_q[riscv::CSR_STORE[4:0]] + 1'b1;
|
||||
|
||||
if (commit_instr_i[i].fu == CTRL_FLOW)
|
||||
perf_counter_d[riscv::PERF_BRANCH_JUMP] = perf_counter_q[riscv::PERF_BRANCH_JUMP] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_BRANCH_JUMP[4:0]] = perf_counter_q[riscv::CSR_BRANCH_JUMP[4:0]] + 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[riscv::PERF_CALL] = perf_counter_q[riscv::PERF_CALL] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_CALL[4:0]] = perf_counter_q[riscv::CSR_CALL[4:0]] + 1'b1;
|
||||
|
||||
// Return from call
|
||||
if (commit_instr_i[i].op == JALR && commit_instr_i[i].rs1 == 'b1)
|
||||
perf_counter_d[riscv::PERF_RET] = perf_counter_q[riscv::PERF_RET] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_RET[4:0]] = perf_counter_q[riscv::CSR_RET[4:0]] + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if (ex_i.valid)
|
||||
perf_counter_d[riscv::PERF_EXCEPTION] = perf_counter_q[riscv::PERF_EXCEPTION] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_EXCEPTION[4:0]] = perf_counter_q[riscv::CSR_EXCEPTION[4:0]] + 1'b1;
|
||||
|
||||
if (eret_i)
|
||||
perf_counter_d[riscv::PERF_EXCEPTION_RET] = perf_counter_q[riscv::PERF_EXCEPTION_RET] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_EXCEPTION_RET[4:0]] = perf_counter_q[riscv::CSR_EXCEPTION_RET[4:0]] + 1'b1;
|
||||
|
||||
if (resolved_branch_i.valid && resolved_branch_i.is_mispredict)
|
||||
perf_counter_d[riscv::PERF_MIS_PREDICT] = perf_counter_q[riscv::PERF_MIS_PREDICT] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_MIS_PREDICT[4:0]] = perf_counter_q[riscv::CSR_MIS_PREDICT[4:0]] + 1'b1;
|
||||
|
||||
if (sb_full_i) begin
|
||||
perf_counter_d[riscv::PERF_SB_FULL] = perf_counter_q[riscv::PERF_SB_FULL] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_SB_FULL[4:0]] = perf_counter_q[riscv::CSR_SB_FULL[4:0]] + 1'b1;
|
||||
end
|
||||
|
||||
if (if_empty_i) begin
|
||||
perf_counter_d[riscv::PERF_IF_EMPTY] = perf_counter_q[riscv::PERF_IF_EMPTY] + 1'b1;
|
||||
perf_counter_d[riscv::CSR_IF_EMPTY[4:0]] = perf_counter_q[riscv::CSR_IF_EMPTY[4:0]] + 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Read Port
|
||||
if (!we_i) begin
|
||||
data_o = perf_counter_q[addr_i[2:0]];
|
||||
// write port
|
||||
end else begin
|
||||
// on a write also output the current value
|
||||
data_o = perf_counter_q[addr_i[2:0]];
|
||||
perf_counter_d[addr_i[2:0]] = data_i;
|
||||
// write after read
|
||||
data_o = perf_counter_q[addr_i];
|
||||
if (we_i) begin
|
||||
perf_counter_d[addr_i] = data_i;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue