mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
Merge pull request #160 from msfschaffner/master
Fix for address offset issue (fix #158)
This commit is contained in:
commit
4fd90a3017
7 changed files with 119 additions and 82 deletions
|
@ -6,6 +6,7 @@ cache:
|
|||
directories:
|
||||
$RISCV
|
||||
$VERILATOR_ROOT
|
||||
timeout: 1000
|
||||
|
||||
# required packages to install
|
||||
addons:
|
||||
|
@ -56,16 +57,22 @@ before_install:
|
|||
- git submodule update --init --recursive
|
||||
|
||||
stages:
|
||||
- checkout
|
||||
- compile1
|
||||
- compile2
|
||||
- test
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: checkout
|
||||
name: checkout gcc
|
||||
script:
|
||||
- ci/build-riscv-gcc.sh 0
|
||||
- stage: compile1
|
||||
name: build gcc
|
||||
script:
|
||||
- ci/build-riscv-gcc.sh
|
||||
- ci/build-riscv-gcc.sh 1
|
||||
- rm -rf $RISCV/riscv-gnu-toolchain
|
||||
- stage: compile2
|
||||
name: build tools
|
||||
script:
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
#!/bin/bash
|
||||
# call with first argument = 0 to checkout only
|
||||
|
||||
set -e
|
||||
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
VERSION="691e4e826251c7ec59f883cab18440c87baf45e7"
|
||||
cd $ROOT/tmp
|
||||
|
||||
mkdir -p $RISCV
|
||||
|
||||
cd $RISCV
|
||||
|
||||
if [ -z ${NUM_JOBS} ]; then
|
||||
NUM_JOBS=1
|
||||
fi
|
||||
|
||||
|
||||
if ! [ -e $RISCV/bin ]; then
|
||||
[ -d $ROOT/tmp/riscv-gnu-toolchain ] || git clone https://github.com/riscv/riscv-gnu-toolchain.git
|
||||
if ! [ -e $RISCV/riscv-gnu-toolchain ]; then
|
||||
git clone https://github.com/riscv/riscv-gnu-toolchain.git
|
||||
fi
|
||||
|
||||
cd riscv-gnu-toolchain
|
||||
git checkout $VERSION
|
||||
git submodule update --init --recursive
|
||||
|
||||
mkdir -p $RISCV
|
||||
|
||||
echo "Compiling RISC-V Toolchain"
|
||||
./configure --prefix=$RISCV > /dev/null
|
||||
make -j${NUM_JOBS} > /dev/null
|
||||
echo "Compilation Finished"
|
||||
if [[ $1 -ne "0" || -z ${1} ]]; then
|
||||
echo "Compiling RISC-V Toolchain"
|
||||
./configure --prefix=$RISCV > /dev/null
|
||||
make -j${NUM_JOBS} > /dev/null
|
||||
echo "Compilation Finished"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,10 @@ module ariane_verilog_wrap #(
|
|||
serpent_cache_pkg::l15_req_t l15_req, l15_req_remapped;
|
||||
serpent_cache_pkg::l15_rtrn_t l15_rtrn;
|
||||
|
||||
/////////////////////////////
|
||||
// Debug module address translation
|
||||
/////////////////////////////
|
||||
|
||||
always_comb begin : p_remap
|
||||
l15_req_remapped = l15_req;
|
||||
if (l15_req.l15_address < 64'h1000) begin
|
||||
|
@ -72,6 +76,11 @@ module ariane_verilog_wrap #(
|
|||
assign l15_rtrn = l15_rtrn_i;
|
||||
`endif
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// Core wakeup mechanism
|
||||
/////////////////////////////
|
||||
|
||||
// // this is a workaround since interrupts are not fully supported yet.
|
||||
// // the logic below catches the initial wake up interrupt that enables the cores.
|
||||
// logic wake_up_d, wake_up_q;
|
||||
|
@ -112,21 +121,52 @@ module ariane_verilog_wrap #(
|
|||
// reset gate this
|
||||
assign rst_n = wake_up_cnt_q[$high(wake_up_cnt_q)] & reset_l;
|
||||
|
||||
// reset_synchronizer #(
|
||||
// .NUM_REGS(2)
|
||||
// ) i_sync (
|
||||
// .clk_i ( clk_i ),
|
||||
// .rst_ni ( rst_n ),
|
||||
// .tmode_i ( 1'b0 ),
|
||||
// .rst_no ( spc_grst_l )
|
||||
// );
|
||||
|
||||
/////////////////////////////
|
||||
// synchronizers
|
||||
/////////////////////////////
|
||||
|
||||
logic [1:0] irq;
|
||||
logic ipi, time_irq, debug_req;
|
||||
|
||||
// reset synchronization
|
||||
synchronizer i_sync (
|
||||
.clk ( clk_i ),
|
||||
.presyncdata ( rst_n ),
|
||||
.syncdata ( spc_grst_l )
|
||||
);
|
||||
|
||||
// interrupts
|
||||
for (genvar k=0; k<$size(irq_i); k++) begin
|
||||
synchronizer i_irq_sync (
|
||||
.clk ( clk_i ),
|
||||
.presyncdata ( irq_i[k] ),
|
||||
.syncdata ( irq[k] )
|
||||
);
|
||||
end
|
||||
|
||||
synchronizer i_ipi_sync (
|
||||
.clk ( clk_i ),
|
||||
.presyncdata ( ipi_i ),
|
||||
.syncdata ( ipi )
|
||||
);
|
||||
|
||||
synchronizer i_timer_sync (
|
||||
.clk ( clk_i ),
|
||||
.presyncdata ( time_irq_i ),
|
||||
.syncdata ( time_irq )
|
||||
);
|
||||
|
||||
synchronizer i_debug_sync (
|
||||
.clk ( clk_i ),
|
||||
.presyncdata ( debug_req_i ),
|
||||
.syncdata ( debug_req )
|
||||
);
|
||||
|
||||
/////////////////////////////
|
||||
// ariane instance
|
||||
/////////////////////////////
|
||||
|
||||
ariane #(
|
||||
.SwapEndianess ( SwapEndianess ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ),
|
||||
|
@ -134,12 +174,12 @@ module ariane_verilog_wrap #(
|
|||
) ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( spc_grst_l ),
|
||||
.boot_addr_i ,
|
||||
.hart_id_i ,
|
||||
.irq_i ,
|
||||
.ipi_i ,
|
||||
.time_irq_i ,
|
||||
.debug_req_i ,
|
||||
.boot_addr_i ,// constant
|
||||
.hart_id_i ,// constant
|
||||
.irq_i ( irq ),
|
||||
.ipi_i ( ipi ),
|
||||
.time_irq_i ( time_irq ),
|
||||
.debug_req_i ( debug_req ),
|
||||
`ifdef AXI64_CACHE_PORTS
|
||||
.axi_req_o ( axi_req ),
|
||||
.axi_resp_i ( axi_resp )
|
||||
|
|
|
@ -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