mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 12:17:19 -04:00
Merge branch 'master' into rgmii_eth
This commit is contained in:
commit
78bf1dd5e9
19 changed files with 276 additions and 181 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:
|
||||
|
|
|
@ -122,7 +122,6 @@ src/cache_subsystem/serpent_dcache.sv
|
|||
src/cache_subsystem/serpent_icache.sv
|
||||
src/cache_subsystem/serpent_l15_adapter.sv
|
||||
src/cache_subsystem/serpent_cache_subsystem.sv
|
||||
src/debug/debug_rom/debug_rom.sv
|
||||
src/debug/dm_csrs.sv
|
||||
src/clint/clint.sv
|
||||
src/clint/axi_lite_interface.sv
|
||||
|
@ -134,6 +133,7 @@ src/debug/dm_sba.sv
|
|||
src/debug/dmi_jtag_tap.sv
|
||||
openpiton/ariane_verilog_wrap.sv
|
||||
openpiton/serpent_peripherals.sv
|
||||
openpiton/debug_rom/debug_rom.sv
|
||||
bootrom/bootrom.sv
|
||||
src/plic/plic.sv
|
||||
src/plic/plic_claim_complete_tracker.sv
|
||||
|
@ -154,4 +154,4 @@ fpga/src/axi_slice/src/axi_ar_buffer.sv
|
|||
fpga/src/axi_slice/src/axi_r_buffer.sv
|
||||
fpga/src/axi_slice/src/axi_aw_buffer.sv
|
||||
src/register_interface/src/apb_to_reg.sv
|
||||
src/register_interface/src/reg_intf.sv
|
||||
src/register_interface/src/reg_intf.sv
|
||||
|
|
4
Makefile
4
Makefile
|
@ -71,7 +71,7 @@ dpi := $(patsubst tb/dpi/%.cc,${dpi-library}/%.o,$(wildcard tb/dpi/*.cc))
|
|||
dpi_hdr := $(wildcard tb/dpi/*.h)
|
||||
dpi_hdr := $(addprefix $(root-dir), $(dpi_hdr))
|
||||
CFLAGS := -I$(QUESTASIM_HOME)/include \
|
||||
-Itb/riscv-isa-sim/install/include/spike \
|
||||
-I$(RISCV)/include \
|
||||
-std=c++11 -I../tb/dpi
|
||||
|
||||
# this list contains the standalone components
|
||||
|
@ -236,7 +236,7 @@ $(dpi-library)/%.o: tb/dpi/%.cc $(dpi_hdr)
|
|||
$(dpi-library)/ariane_dpi.so: $(dpi)
|
||||
mkdir -p $(dpi-library)
|
||||
# Compile C-code and generate .so file
|
||||
$(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -lfesvr
|
||||
$(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -lfesvr
|
||||
|
||||
# single test runs on Questa can be started by calling make <testname>, e.g. make towers.riscv
|
||||
# the test names are defined in ci/riscv-asm-tests.list, and in ci/riscv-benchmarks.list
|
||||
|
|
|
@ -833,7 +833,7 @@
|
|||
#define CSR_DPC 0x7b1
|
||||
#define CSR_DSCRATCH 0x7b2
|
||||
#define CSR_DSCRATCH0 CSR_DSCRATCH
|
||||
#define CSR_DSCRATCH1 0x7b2
|
||||
#define CSR_DSCRATCH1 0x7b3
|
||||
#define CSR_MCYCLE 0xb00
|
||||
#define CSR_MINSTRET 0xb02
|
||||
#define CSR_MHPMCOUNTER3 0xb03
|
||||
|
|
|
@ -85,8 +85,9 @@ def read_bin():
|
|||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
# align to 64 bit
|
||||
align = (int(len(rom) / 8) + 1) * 8;
|
||||
align = (int((len(rom) + 7) / 8 )) * 8;
|
||||
|
||||
for i in range(len(rom), align):
|
||||
rom.append("00")
|
||||
|
|
|
@ -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
|
||||
// ----------------------
|
||||
|
@ -385,23 +367,26 @@ package riscv;
|
|||
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_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;
|
||||
|
@ -502,11 +487,31 @@ package riscv;
|
|||
return {offset[11:0], rs1, 3'b0, rd, 7'h67};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] andi (logic[4:0] rd, logic[4:0] rs1, logic [11:0] imm);
|
||||
// OpCode andi
|
||||
return {imm[11:0], rs1, 3'h7, rd, 7'h13};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] slli (logic[4:0] rd, logic[4:0] rs1, logic [5:0] shamt);
|
||||
// OpCode slli
|
||||
return {6'b0, shamt[5:0], rs1, 3'h1, rd, 7'h13};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] srli (logic[4:0] rd, logic[4:0] rs1, logic [5:0] shamt);
|
||||
// OpCode srli
|
||||
return {6'b0, shamt[5:0], rs1, 3'h5, rd, 7'h13};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] load (logic [2:0] size, logic[4:0] dest, logic[4:0] base, logic [11:0] offset);
|
||||
// OpCode Load
|
||||
return {offset[11:0], base, size, dest, 7'h03};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] auipc (logic[4:0] rd, logic [20:0] imm);
|
||||
// OpCode Auipc
|
||||
return {imm[20], imm[10:1], imm[11], imm[19:12], rd, 7'h17};
|
||||
endfunction
|
||||
|
||||
function automatic logic [31:0] store (logic [2:0] size, logic[4:0] src, logic[4:0] base, logic [11:0] offset);
|
||||
// OpCode Store
|
||||
return {offset[11:5], src, base, size, offset[4:0], 7'h23};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
`endif
|
||||
|
||||
module ariane_verilog_wrap #(
|
||||
parameter logic [63:0] DmBaseAddress = 64'h0, // debug module base address
|
||||
parameter bit SwapEndianess = 1, // swap endianess in l15 adapter
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
parameter logic [63:0] CachedAddrBeg = 64'h00_8000_0000 // begin of cached region
|
||||
|
@ -58,20 +59,18 @@ module ariane_verilog_wrap #(
|
|||
assign axi_resp = axi_resp_i;
|
||||
`else
|
||||
// L15 (memory side)
|
||||
serpent_cache_pkg::l15_req_t l15_req, l15_req_remapped;
|
||||
serpent_cache_pkg::l15_req_t l15_req;
|
||||
serpent_cache_pkg::l15_rtrn_t l15_rtrn;
|
||||
|
||||
always_comb begin : p_remap
|
||||
l15_req_remapped = l15_req;
|
||||
if (l15_req.l15_address < 64'h1000) begin
|
||||
l15_req_remapped.l15_address = l15_req.l15_address + 64'hfff1000000;
|
||||
end
|
||||
end
|
||||
|
||||
assign l15_req_o = l15_req_remapped;
|
||||
assign l15_req_o = l15_req;
|
||||
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,34 +111,66 @@ 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 #(
|
||||
.DmBaseAddress ( DmBaseAddress ),
|
||||
.SwapEndianess ( SwapEndianess ),
|
||||
.CachedAddrEnd ( CachedAddrEnd ),
|
||||
.CachedAddrBeg ( CachedAddrBeg )
|
||||
) 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 )
|
||||
|
|
|
@ -28,6 +28,7 @@ import instruction_tracer_pkg::*;
|
|||
`endif
|
||||
|
||||
module ariane #(
|
||||
parameter logic [63:0] DmBaseAddress = 64'h0, // debug module base address
|
||||
`ifdef PITON_ARIANE
|
||||
parameter bit SwapEndianess = 0, // swap endianess in l15 adapter
|
||||
parameter logic [63:0] CachedAddrEnd = 64'h80_0000_0000, // end of cached region
|
||||
|
@ -187,7 +188,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;
|
||||
|
||||
|
@ -239,7 +240,9 @@ module ariane #(
|
|||
// --------------
|
||||
// Frontend
|
||||
// --------------
|
||||
frontend i_frontend (
|
||||
frontend #(
|
||||
.DmBaseAddress ( DmBaseAddress )
|
||||
) i_frontend (
|
||||
.flush_i ( flush_ctrl_if ), // not entirely correct
|
||||
.flush_bp_i ( 1'b0 ),
|
||||
.debug_mode_i ( debug_mode ),
|
||||
|
@ -469,7 +472,8 @@ module ariane #(
|
|||
// CSR
|
||||
// ---------
|
||||
csr_regfile #(
|
||||
.ASID_WIDTH ( ASID_WIDTH )
|
||||
.AsidWidth ( ASID_WIDTH ),
|
||||
.DmBaseAddress ( DmBaseAddress )
|
||||
) csr_regfile_i (
|
||||
.flush_o ( flush_csr_ctrl ),
|
||||
.halt_csr_o ( halt_csr_ctrl ),
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
import ariane_pkg::*;
|
||||
|
||||
module csr_regfile #(
|
||||
parameter int ASID_WIDTH = 1,
|
||||
parameter int unsigned NR_COMMIT_PORTS = 2
|
||||
parameter logic [63:0] DmBaseAddress = 64'h0, // debug module base address
|
||||
parameter int AsidWidth = 1,
|
||||
parameter int unsigned NrCommitPorts = 2
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
@ -25,8 +26,8 @@ module csr_regfile #(
|
|||
output logic flush_o,
|
||||
output logic halt_csr_o, // halt requested
|
||||
// commit acknowledge
|
||||
input scoreboard_entry_t [NR_COMMIT_PORTS-1:0] commit_instr_i, // the instruction we want to commit
|
||||
input logic [NR_COMMIT_PORTS-1:0] commit_ack_i, // Commit acknowledged a instruction -> increase instret CSR
|
||||
input scoreboard_entry_t [NrCommitPorts-1:0] commit_instr_i, // the instruction we want to commit
|
||||
input logic [NrCommitPorts-1:0] commit_ack_i, // Commit acknowledged a instruction -> increase instret CSR
|
||||
// Core and Cluster ID
|
||||
input logic [63:0] boot_addr_i, // Address from which to start booting, mtvec is set to the same address
|
||||
input logic [63:0] hart_id_i, // Hart id in a multicore environment (reflected in a CSR)
|
||||
|
@ -60,7 +61,7 @@ module csr_regfile #(
|
|||
output logic sum_o,
|
||||
output logic mxr_o,
|
||||
output logic [43:0] satp_ppn_o,
|
||||
output logic [ASID_WIDTH-1:0] asid_o,
|
||||
output logic [AsidWidth-1:0] asid_o,
|
||||
// external interrupts
|
||||
input logic [1:0] irq_i, // external interrupt in
|
||||
input logic ipi_i, // inter processor interrupt -> connected to machine mode sw
|
||||
|
@ -76,7 +77,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 +150,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 +249,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
|
||||
|
@ -273,7 +275,7 @@ module csr_regfile #(
|
|||
instret_d = instret_q;
|
||||
if (!debug_mode_q) begin
|
||||
// increase instruction retired counter
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
for (int i = 0; i < NrCommitPorts; i++) begin
|
||||
if (commit_ack_i[i] && !ex_i.valid) instret++;
|
||||
end
|
||||
instret_d = instret;
|
||||
|
@ -438,7 +440,7 @@ module csr_regfile #(
|
|||
else begin
|
||||
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}}};
|
||||
sapt.asid = sapt.asid & {{(16-AsidWidth){1'b0}}, {AsidWidth{1'b1}}};
|
||||
// only update if we actually support this mode
|
||||
if (sapt.mode == MODE_OFF || sapt.mode == MODE_SV39) satp_d = sapt;
|
||||
end
|
||||
|
@ -905,7 +907,7 @@ module csr_regfile #(
|
|||
|
||||
// if we are in debug mode jump to a specific address
|
||||
if (debug_mode_q) begin
|
||||
trap_vector_base_o = dm::ExceptionAddress;
|
||||
trap_vector_base_o = DmBaseAddress + dm::ExceptionAddress;
|
||||
end
|
||||
|
||||
// check if we are in vectored mode, if yes then do BASE + 4 * cause
|
||||
|
@ -954,7 +956,7 @@ module csr_regfile #(
|
|||
assign fprec_o = fcsr_q.fprec;
|
||||
// MMU outputs
|
||||
assign satp_ppn_o = satp_q.ppn;
|
||||
assign asid_o = satp_q.asid[ASID_WIDTH-1:0];
|
||||
assign asid_o = satp_q.asid[AsidWidth-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 != riscv::PRIV_LVL_M)
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
# See LICENSE.SiFive for license details
|
||||
|
||||
debug_rom = debug_rom.img
|
||||
debug_rom = debug_rom.sv
|
||||
|
||||
GCC=riscv64-unknown-elf-gcc
|
||||
OBJCOPY=riscv64-unknown-elf-objcopy
|
||||
OBJDUMP=riscv64-unknown-elf-objdump
|
||||
|
||||
all: $(debug_rom)
|
||||
|
||||
%.sv: %.img
|
||||
python gen_rom.py $<
|
||||
|
||||
%.img: %.bin
|
||||
dd if=$< of=$@ bs=128 count=1
|
||||
dd if=$< of=$@ bs=256 count=1
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
%.elf: %.S link.ld
|
||||
$(GCC) -I$(RISCV)/include -Tlink.ld $< -nostdlib -static -Wl,--no-gc-sections -o $@
|
||||
$(GCC) -I$(RISCV)/include -Tlink.ld $< -nostdlib -fPIC -static -Wl,--no-gc-sections -o $@
|
||||
|
||||
%.dump: %.elf
|
||||
$(OBJDUMP) -d $< --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data > $@
|
||||
|
||||
clean:
|
||||
rm $(debug_rom)
|
||||
rm -f *.img *.dump *.bin *.sv
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
|
||||
#include "spike/encoding.h"
|
||||
#include "encoding.h"
|
||||
|
||||
// These are implementation-specific addresses in the Debug Module
|
||||
#define HALTED 0x100
|
||||
|
@ -29,11 +29,17 @@ resume:
|
|||
exception:
|
||||
jal zero, _exception
|
||||
|
||||
|
||||
|
||||
_entry:
|
||||
// This fence is required because the execution may have written something
|
||||
// into the Abstract Data or Program Buffer registers.
|
||||
fence
|
||||
csrw CSR_DSCRATCH, s0 // Save s0 to allow signaling MHARTID
|
||||
csrw CSR_DSCRATCH0, s0 // Save s0 to allow signaling MHARTID
|
||||
csrw CSR_DSCRATCH1, a0 // Save a0 to allow loading arbitrary DM base
|
||||
auipc a0, 0 // Get PC
|
||||
srli a0, a0, 12 // And throw away lower 12 bits to get the DM base
|
||||
slli a0, a0, 12
|
||||
|
||||
// We continue to let the hart know that we are halted in order that
|
||||
// a DM which was reset is still made aware that a hart is halted.
|
||||
|
@ -41,28 +47,37 @@ _entry:
|
|||
// us to do, or whether we should resume.
|
||||
entry_loop:
|
||||
csrr s0, CSR_MHARTID
|
||||
sw s0, HALTED(zero)
|
||||
sw s0, HALTED(a0)
|
||||
add s0, s0, a0
|
||||
lbu s0, FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
|
||||
andi s0, s0, (1 << FLAG_GO)
|
||||
bnez s0, going
|
||||
csrr s0, CSR_MHARTID
|
||||
add s0, s0, a0
|
||||
lbu s0, FLAGS(s0) // multiple harts can resume here
|
||||
andi s0, s0, (1 << FLAG_RESUME)
|
||||
bnez s0, resume
|
||||
jal zero, entry_loop
|
||||
|
||||
_exception:
|
||||
sw zero, EXCEPTION(zero) // Let debug module know you got an exception.
|
||||
csrw CSR_DSCRATCH1, a0 // Save a0 to allow loading arbitrary DM offsets
|
||||
auipc a0, 0 // Get POC
|
||||
srli a0, a0, 12 // And throw away lower 12 bits to get the DM base
|
||||
slli a0, a0, 12
|
||||
sw zero, EXCEPTION(a0) // Let debug module know you got an exception.
|
||||
csrr a0, CSR_DSCRATCH1 // Restore a0 here
|
||||
ebreak
|
||||
|
||||
going:
|
||||
csrr s0, CSR_DSCRATCH // Restore s0 here
|
||||
sw zero, GOING(zero) // When debug module sees this write, the GO flag is reset.
|
||||
jalr zero, zero, %lo(whereto)
|
||||
sw zero, GOING(a0) // When debug module sees this write, the GO flag is reset.
|
||||
csrr s0, CSR_DSCRATCH0 // Restore s0 here
|
||||
csrr a0, CSR_DSCRATCH1 // Restore a0 here
|
||||
jal zero, whereto
|
||||
_resume:
|
||||
csrr s0, CSR_MHARTID
|
||||
sw s0, RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
|
||||
csrr s0, CSR_DSCRATCH // Restore s0
|
||||
sw s0, RESUMING(a0) // When Debug Module sees this write, the RESUME flag is reset.
|
||||
csrr s0, CSR_DSCRATCH0 // Restore s0 here
|
||||
csrr a0, CSR_DSCRATCH1 // Restore a0 here
|
||||
dret
|
||||
|
||||
// END OF ACTUAL "ROM" CONTENTS. BELOW IS JUST FOR LINKER SCRIPT.
|
||||
|
|
|
@ -20,22 +20,28 @@ module debug_rom (
|
|||
input logic [63:0] addr_i,
|
||||
output logic [63:0] rdata_o
|
||||
);
|
||||
localparam int RomSize = 13;
|
||||
localparam int RomSize = 19;
|
||||
|
||||
const logic [RomSize-1:0][63:0] mem = {
|
||||
64'h00000000_00000000,
|
||||
64'h7B200073_7B202473,
|
||||
64'h10802423_F1402473,
|
||||
64'h30000067_10002223,
|
||||
64'h7B202473_00100073,
|
||||
64'h10002623_FDDFF06F,
|
||||
64'hFC0418E3_00247413,
|
||||
64'h40044403_F1402473,
|
||||
64'h02041063_00147413,
|
||||
64'h40044403_10802023,
|
||||
64'hF1402473_7B241073,
|
||||
64'h0FF0000F_0340006F,
|
||||
64'h04C0006F_00C0006F
|
||||
64'h00000000_7b200073,
|
||||
64'h7b302573_7b202473,
|
||||
64'h10852423_f1402473,
|
||||
64'ha85ff06f_7b302573,
|
||||
64'h7b202473_10052223,
|
||||
64'h00100073_7b302573,
|
||||
64'h10052623_00c51513,
|
||||
64'h00c55513_00000517,
|
||||
64'h7b351073_fd5ff06f,
|
||||
64'hfa041ce3_00247413,
|
||||
64'h40044403_00a40433,
|
||||
64'hf1402473_02041c63,
|
||||
64'h00147413_40044403,
|
||||
64'h00a40433_10852023,
|
||||
64'hf1402473_00c51513,
|
||||
64'h00c55513_00000517,
|
||||
64'h7b351073_7b241073,
|
||||
64'h0ff0000f_04c0006f,
|
||||
64'h07c0006f_00c0006f
|
||||
};
|
||||
|
||||
logic [$clog2(RomSize)-1:0] addr_q;
|
||||
|
@ -46,7 +52,7 @@ module debug_rom (
|
|||
end
|
||||
end
|
||||
|
||||
// this prevents spurious Xes from propagating into
|
||||
// this prevents spurious Xes from propagating into
|
||||
// the speculative fetch stage of the core
|
||||
assign rdata_o = (addr_q<RomSize) ? mem[addr_q] : '0;
|
||||
assign rdata_o = (addr_q < RomSize) ? mem[addr_q] : '0;
|
||||
endmodule
|
||||
|
|
|
@ -60,11 +60,11 @@ module dm_mem #(
|
|||
localparam logic [DbgAddressBits-1:0] DataEnd = (dm::DataAddr + 4*dm::DataCount);
|
||||
localparam logic [DbgAddressBits-1:0] ProgBufBase = (dm::DataAddr - 4*dm::ProgBufSize);
|
||||
localparam logic [DbgAddressBits-1:0] ProgBufEnd = (dm::DataAddr - 1);
|
||||
localparam logic [DbgAddressBits-1:0] AbstractCmdBase = (ProgBufBase - 4*6);
|
||||
localparam logic [DbgAddressBits-1:0] AbstractCmdBase = (ProgBufBase - 4*10);
|
||||
localparam logic [DbgAddressBits-1:0] AbstractCmdEnd = (ProgBufBase - 1);
|
||||
localparam logic [DbgAddressBits-1:0] WhereTo = 'h300;
|
||||
localparam logic [DbgAddressBits-1:0] FlagsBase = 'h400;
|
||||
localparam logic [DbgAddressBits-1:0] FlagsEnd = 'h7FF;
|
||||
localparam logic [DbgAddressBits-1:0] WhereTo = 'h300;
|
||||
localparam logic [DbgAddressBits-1:0] FlagsBase = 'h400;
|
||||
localparam logic [DbgAddressBits-1:0] FlagsEnd = 'h7FF;
|
||||
|
||||
|
||||
localparam logic [DbgAddressBits-1:0] Halted = 'h100;
|
||||
|
@ -72,7 +72,8 @@ module dm_mem #(
|
|||
localparam logic [DbgAddressBits-1:0] Resuming = 'h108;
|
||||
localparam logic [DbgAddressBits-1:0] Exception = 'h10C;
|
||||
|
||||
logic [2:0][63:0] abstract_cmd;
|
||||
logic [dm::ProgBufSize/2-1:0][63:0] progbuf;
|
||||
logic [4:0][63:0] abstract_cmd;
|
||||
logic [NrHarts-1:0] halted_d, halted_q;
|
||||
logic [NrHarts-1:0] resuming_d, resuming_q;
|
||||
logic resume, go, going;
|
||||
|
@ -95,6 +96,9 @@ module dm_mem #(
|
|||
assign halted_o = halted_q;
|
||||
assign resuming_o = resuming_q;
|
||||
|
||||
// reshape progbuf
|
||||
assign progbuf = progbuf_i;
|
||||
|
||||
enum logic [1:0] { Idle, Go, Resume, CmdExecuting } state_d, state_q;
|
||||
|
||||
// hart ctrl queue
|
||||
|
@ -218,17 +222,17 @@ module dm_mem #(
|
|||
WhereTo: begin
|
||||
// variable jump to abstract cmd, program_buffer or resume
|
||||
if (resumereq_i) begin
|
||||
rdata_d = {32'b0, riscv::jalr(0, 0, dm::ResumeAddress[11:0])};
|
||||
rdata_d = {32'b0, riscv::jal(0, dm::ResumeAddress[11:0]-WhereTo)};
|
||||
end
|
||||
|
||||
// there is a command active so jump there
|
||||
if (cmdbusy_o) begin
|
||||
// transfer not set is a shortcut to the program buffer
|
||||
if (!ac_ar.transfer) begin
|
||||
rdata_d = {32'b0, riscv::jalr(0, 0, ProgBufBase)};
|
||||
rdata_d = {32'b0, riscv::jal(0, ProgBufBase-WhereTo)};
|
||||
// this is a legit abstract cmd -> execute it
|
||||
end else begin
|
||||
rdata_d = {32'b0, riscv::jalr(0, 0, AbstractCmdBase)};
|
||||
rdata_d = {32'b0, riscv::jal(0, AbstractCmdBase-WhereTo)};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -238,13 +242,8 @@ module dm_mem #(
|
|||
rdata_d = {data_i[1], data_i[0]};
|
||||
end
|
||||
|
||||
// TODO(zarubaf) change hard-coded values
|
||||
[ProgBufBase:ProgBufEnd]: begin
|
||||
case (addr_i[DbgAddressBits-1:0])
|
||||
ProgBufBase + 16: rdata_d = {progbuf_i[5], progbuf_i[4]};
|
||||
ProgBufBase + 8: rdata_d = {progbuf_i[3], progbuf_i[2]};
|
||||
ProgBufBase: rdata_d = {progbuf_i[1], progbuf_i[0]};
|
||||
endcase
|
||||
rdata_d = progbuf[(addr_i[DbgAddressBits-1:3] - ProgBufBase[DbgAddressBits-1:3])];
|
||||
end
|
||||
|
||||
// two slots for abstract command
|
||||
|
@ -276,11 +275,16 @@ module dm_mem #(
|
|||
// default memory
|
||||
// if ac_ar.transfer is not set then we can take a shortcut to the program buffer
|
||||
abstract_cmd[0][31:0] = riscv::illegal();
|
||||
abstract_cmd[0][63:32] = riscv::nop();
|
||||
abstract_cmd[1][31:0] = riscv::nop();
|
||||
abstract_cmd[1][63:32] = riscv::nop();
|
||||
// load debug module base address into a0, this is shared among all commands
|
||||
abstract_cmd[0][63:32] = riscv::auipc(10, 0);
|
||||
abstract_cmd[1][31:0] = riscv::srli(10, 10, 12); // clear lowest 12bit to get base offset of DM
|
||||
abstract_cmd[1][63:32] = riscv::slli(10, 10, 12);
|
||||
abstract_cmd[2][31:0] = riscv::nop();
|
||||
abstract_cmd[2][63:32] = riscv::ebreak();
|
||||
abstract_cmd[2][63:32] = riscv::nop();
|
||||
abstract_cmd[3][31:0] = riscv::nop();
|
||||
abstract_cmd[3][63:32] = riscv::nop();
|
||||
abstract_cmd[4][31:0] = riscv::csrr(riscv::CSR_DSCRATCH1, 10);
|
||||
abstract_cmd[4][63:32] = riscv::ebreak();
|
||||
|
||||
// this depends on the command being executed
|
||||
unique case (cmd_i.cmdtype)
|
||||
|
@ -289,58 +293,63 @@ module dm_mem #(
|
|||
// --------------------
|
||||
dm::AccessRegister: begin
|
||||
if (ac_ar.aarsize < 4 && ac_ar.transfer && ac_ar.write) begin
|
||||
// store a0 in dscratch1
|
||||
abstract_cmd[0][31:0] = riscv::csrw(riscv::CSR_DSCRATCH1, 10);
|
||||
// this range is reserved
|
||||
if (ac_ar.regno[15:14] != '0) begin
|
||||
abstract_cmd[0][31:0] = riscv::illegal();
|
||||
// GPR/FPR access
|
||||
if (ac_ar.regno[12]) begin
|
||||
end else if (ac_ar.regno[12]) begin
|
||||
// determine whether we want to access the floating point register or not
|
||||
if (ac_ar.regno[5]) begin
|
||||
abstract_cmd[0][31:0] = riscv::float_load(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
abstract_cmd[2][31:0] = riscv::float_load(ac_ar.aarsize, ac_ar.regno[4:0], 10, dm::DataAddr);
|
||||
end else begin
|
||||
abstract_cmd[0][31:0] = riscv::load(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
abstract_cmd[2][31:0] = riscv::load(ac_ar.aarsize, ac_ar.regno[4:0], 10, dm::DataAddr);
|
||||
end
|
||||
// this range is reserved
|
||||
end else if (ac_ar.regno[15:14] != '0) begin
|
||||
abstract_cmd[0][31:0] = riscv::illegal();
|
||||
// CSR access
|
||||
end else begin
|
||||
// data register to CSR
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[0][31:0] = riscv::csrw(riscv::CSR_DSCRATCH0, 8);
|
||||
abstract_cmd[2][31:0] = riscv::csrw(riscv::CSR_DSCRATCH0, 8);
|
||||
// load from data register
|
||||
abstract_cmd[0][63:32] = riscv::load(ac_ar.aarsize, 8, 0, dm::DataAddr);
|
||||
abstract_cmd[2][63:32] = riscv::load(ac_ar.aarsize, 8, 10, dm::DataAddr);
|
||||
// and store it in the corresponding CSR
|
||||
abstract_cmd[1][31:0] = riscv::csrw(riscv::csr_reg_t'(ac_ar.regno[11:0]), 8);
|
||||
abstract_cmd[3][31:0] = riscv::csrw(riscv::csr_reg_t'(ac_ar.regno[11:0]), 8);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[1][63:32] = riscv::csrr(riscv::CSR_DSCRATCH0, 8);
|
||||
abstract_cmd[3][63:32] = riscv::csrr(riscv::CSR_DSCRATCH0, 8);
|
||||
end
|
||||
end else if (ac_ar.aarsize < 4 && ac_ar.transfer && !ac_ar.write) begin
|
||||
// store a0 in dscratch1
|
||||
abstract_cmd[0][31:0] = riscv::csrw(riscv::CSR_DSCRATCH1, 10);
|
||||
// this range is reserved
|
||||
if (ac_ar.regno[15:14] != '0) begin
|
||||
abstract_cmd[0][31:0] = riscv::illegal();
|
||||
// GPR/FPR access
|
||||
if (ac_ar.regno[12]) begin
|
||||
end else if (ac_ar.regno[12]) begin
|
||||
// determine whether we want to access the floating point register or not
|
||||
if (ac_ar.regno[5]) begin
|
||||
abstract_cmd[0][31:0] = riscv::float_store(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
abstract_cmd[2][31:0] = riscv::float_store(ac_ar.aarsize, ac_ar.regno[4:0], 10, dm::DataAddr);
|
||||
end else begin
|
||||
abstract_cmd[0][31:0] = riscv::store(ac_ar.aarsize, ac_ar.regno[4:0], 0, dm::DataAddr);
|
||||
abstract_cmd[2][31:0] = riscv::store(ac_ar.aarsize, ac_ar.regno[4:0], 10, dm::DataAddr);
|
||||
end
|
||||
end else if (ac_ar.regno[15:14] != '0) begin
|
||||
abstract_cmd[0][31:0] = riscv::illegal();
|
||||
// CSR access
|
||||
end else begin
|
||||
// CSR register to data
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[0][31:0] = riscv::csrw(riscv::CSR_DSCRATCH0, 8);
|
||||
abstract_cmd[2][31:0] = riscv::csrw(riscv::CSR_DSCRATCH0, 8);
|
||||
// read value from CSR into s0
|
||||
abstract_cmd[0][63:32] = riscv::csrr(riscv::csr_reg_t'(ac_ar.regno[11:0]), 8);
|
||||
abstract_cmd[2][63:32] = riscv::csrr(riscv::csr_reg_t'(ac_ar.regno[11:0]), 8);
|
||||
// and store s0 into data section
|
||||
abstract_cmd[1][31:0] = riscv::store(ac_ar.aarsize, 8, 0, dm::DataAddr);
|
||||
abstract_cmd[3][31:0] = riscv::store(ac_ar.aarsize, 8, 10, dm::DataAddr);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[1][63:32] = riscv::csrr(riscv::CSR_DSCRATCH0, 8);
|
||||
abstract_cmd[3][63:32] = riscv::csrr(riscv::CSR_DSCRATCH0, 8);
|
||||
end
|
||||
end
|
||||
|
||||
// check whether we need to execute the program buffer
|
||||
if (ac_ar.postexec) begin
|
||||
// issue a nop, we will automatically run into the program buffer
|
||||
abstract_cmd[2][63:32] = riscv::nop();
|
||||
abstract_cmd[4][63:32] = riscv::nop();
|
||||
end
|
||||
end
|
||||
// not supported at the moment
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
package dm;
|
||||
localparam logic [3:0] DbgVersion013 = 4'h2;
|
||||
// size of program buffer in junks of 32-bit words
|
||||
localparam logic [4:0] ProgBufSize = 5'h6;
|
||||
localparam logic [4:0] ProgBufSize = 5'h8;
|
||||
|
||||
// TODO(zarubaf) This is hard-coded to two at the moment
|
||||
// amount of data count registers implemented
|
||||
|
@ -141,7 +141,7 @@ package dm;
|
|||
typedef struct packed {
|
||||
logic [31:29] zero3;
|
||||
logic [28:24] progbufsize;
|
||||
logic [23:12] zero2;
|
||||
logic [23:13] zero2;
|
||||
logic busy;
|
||||
logic zero1;
|
||||
cmderr_t cmderr;
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
|
||||
import ariane_pkg::*;
|
||||
|
||||
module frontend (
|
||||
module frontend #(
|
||||
parameter logic [63:0] DmBaseAddress = 64'h0 // debug module base address
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush request for PCGEN
|
||||
|
@ -357,7 +359,7 @@ module frontend (
|
|||
// -------------------------------
|
||||
// enter debug on a hard-coded base-address
|
||||
if (set_debug_pc_i) begin
|
||||
npc_d = dm::HaltAddress;
|
||||
npc_d = DmBaseAddress + dm::HaltAddress;
|
||||
end
|
||||
|
||||
icache_dreq_o.vaddr = fetch_address;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ package ariane_soc;
|
|||
localparam PLICIdWidth = 3;
|
||||
localparam ParameterBitwidth = PLICIdWidth;
|
||||
|
||||
typedef enum int unsigned {
|
||||
typedef enum int unsigned {
|
||||
DRAM = 0,
|
||||
GPIO = 1,
|
||||
Ethernet = 2,
|
||||
|
|
|
@ -545,7 +545,8 @@ module ariane_testharness #(
|
|||
.SwapEndianess ( 0 ),
|
||||
.CachedAddrEnd ( (ariane_soc::DRAMBase + ariane_soc::DRAMLength) ),
|
||||
`endif
|
||||
.CachedAddrBeg ( ariane_soc::DRAMBase )
|
||||
.CachedAddrBeg ( ariane_soc::DRAMBase ),
|
||||
.DmBaseAddress ( ariane_soc::DebugBase )
|
||||
) i_ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue