Merge branch 'master' into rgmii_eth

This commit is contained in:
msfschaffner 2019-01-28 16:32:51 +01:00 committed by GitHub
commit 78bf1dd5e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 276 additions and 181 deletions

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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

View file

@ -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};

View file

@ -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 )

View file

@ -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 ),

View file

@ -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)

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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,

View file

@ -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 ),