From 9c503b540a2e88ec01c23a9b948b8e06f32e0e49 Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Mon, 7 Jan 2019 20:49:36 +0100 Subject: [PATCH] Fix #158 --- include/riscv_pkg.sv | 44 ++++++++++++++------------------------------ src/ariane.sv | 2 +- src/csr_regfile.sv | 9 +++++---- src/perf_counters.sv | 44 ++++++++++++++++++++------------------------ 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/include/riscv_pkg.sv b/include/riscv_pkg.sv index b9a94c315a..4640862f0f 100644 --- a/include/riscv_pkg.sv +++ b/include/riscv_pkg.sv @@ -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; diff --git a/src/ariane.sv b/src/ariane.sv index 4927f205be..8b2c8def4c 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -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; diff --git a/src/csr_regfile.sv b/src/csr_regfile.sv index ce6b00175e..f960d93cea 100644 --- a/src/csr_regfile.sv +++ b/src/csr_regfile.sv @@ -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 diff --git a/src/perf_counters.sv b/src/perf_counters.sv index 381ff105ff..2b010cbcb9 100644 --- a/src/perf_counters.sv +++ b/src/perf_counters.sv @@ -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