Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
msfschaffner committed Jan 7, 2019
1 parent a3044db commit a956c81
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 60 deletions.
47 changes: 16 additions & 31 deletions include/riscv_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ----------------------
Expand Down Expand Up @@ -330,6 +312,7 @@ package riscv;
localparam logic [63:0] S_EXT_INTERRUPT = (1 << 63) | IRQ_S_EXT;
localparam logic [63:0] M_EXT_INTERRUPT = (1 << 63) | IRQ_M_EXT;

localparam int unsigned NUM_AUX_PERF_CNT = 14;
// -----
// CSRs
// -----
Expand Down Expand Up @@ -389,19 +372,21 @@ package riscv;
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
// Performance counters (make sure this is in line with NUM_AUX_PERF_CNT above)
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;
Expand Down
2 changes: 1 addition & 1 deletion src/ariane.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
9 changes: 5 additions & 4 deletions src/csr_regfile.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
44 changes: 20 additions & 24 deletions src/perf_counters.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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

Expand Down

0 comments on commit a956c81

Please sign in to comment.