mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
verification: Add co-simulation with dromajo (#445)
* Summary: initial dromajo integration * some changes to Makefile to enable `make verilate DROMAJO=1` * adding ifdefs to ariane_tb.cpp to disable HTIF * adding dromajo repo * making dromajo repo a submodule * syncing with upstream * bumping to the latest dromajo commit * Summary: adding DPI functions for cosim * added new file tb/dpi/dromajo_cosim.cc that contains all DPIs for dromajo to work * editted Makefile to see the above file * Summary: fixing build issues * fixing syntax errors in dpi file * renaming dpi file due to name conflict with shared library * fixing path in Makefile to the shared dromajo lib * bumping to the latest dromajo change * Summary: loading checkpoint to bootrom This change adds `+checkpoint=` argument to the verilator simulator as well as corresponding changes to load the dromajo checkpoint into the bootrom. Dromajo checkpoint bootcode contains series of csrw and immediate loads to restore the architectural state of the processor. dromajo_bootrom.sv is a copy of a generated bootrom.sv file. This file parses the verilog plusargs and loads the bootrom with the code that is pointed by the +checkpoint. csr_regfile.sv Dromajo needs to start running the code in debug mode. The default value of debug_mode_q was changed to 1. * updating dromajo to the latest change * Summary: sync main memories of dromajo and ariane These changes load the checkpoint into the main memory of Ariane. The checkpointed memory that is dumped from dromajo contains (1) the binary and (2) the values of all stores that dromajo globally performed before dumping the checkpoint. dromajo_ram.sv This file is a copy of SyncSpRamBeNx64.sv and was modified to parse +checkpoint argument to load the memory from the path pointed by the argument. The remaining changes were introduced to instantiate the above file when DROMAJO=1 flag is set. * Summary: calling DPIs for cosimulation This change introduces the calls to DPI functions that interface with Dromajo. * updating to the latest commit of dromajo * disabling verbose output when preloading bootrom and mainram * Summary: bug fix - update logic of `dcsr_d.prv` This change was made per discussion with Florian via email. The current versionincorrectly implements the update logic of `dcsr_d.prv`. The confusion came from the fact that the core should update its `dcsr_d.prv` to the current running privilege level when entering debug mode. I've attached a patch which, as you suggested, removes the wrong update logic in the CSR write process and should now correctly handle the update when entering debug mode (4.9.1 Debug Control and Status of the debug specification). * bump to the latest version of dromajo * Summary: dromajo DPI change This change: * Ariane doesn't commit ebreaks and ecalls so some workaround was encorporated * Proper exit(0) on cosim pass * Summary: support for running binaries with dromajo This change adds the ability to run the following command: `make run_dromajo BIN=\path\to\riscv\bin` It automates the dromajo's checkpoint creation and runs the binary on Ariane with dromajo cosimulation. For this to work Ariane must be build with DROMAJO=1. * changing dromajo recipe name to be consistent with existing names * adding instructions on how to run cosim with dromajo * Bump to release 0.6.2 * added license headers * added more details about dromajo
This commit is contained in:
parent
cbbcf3565c
commit
2d81445209
13 changed files with 499 additions and 9 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -49,3 +49,6 @@
|
|||
[submodule "fpga/src/apb_timer"]
|
||||
path = fpga/src/apb_timer
|
||||
url = https://github.com/pulp-platform/apb_timer.git
|
||||
[submodule "tb/dromajo"]
|
||||
path = tb/dromajo
|
||||
url = https://github.com/kabylkas/dromajo.git
|
||||
|
|
|
@ -71,6 +71,7 @@ src/util/axi_master_connect_rev.sv
|
|||
src/util/axi_slave_connect.sv
|
||||
src/util/axi_slave_connect_rev.sv
|
||||
src/fpga-support/rtl/SyncSpRamBeNx64.sv
|
||||
src/dromajo_ram.sv
|
||||
src/axi_mem_if/src/axi2mem.sv
|
||||
src/tech_cells_generic/src/pulp_clock_gating.sv
|
||||
src/tech_cells_generic/src/cluster_clock_inverter.sv
|
||||
|
|
71
Makefile
71
Makefile
|
@ -114,8 +114,10 @@ dpi_hdr := $(wildcard tb/dpi/*.h)
|
|||
dpi_hdr := $(addprefix $(root-dir), $(dpi_hdr))
|
||||
CFLAGS := -I$(QUESTASIM_HOME)/include \
|
||||
-I$(RISCV)/include \
|
||||
$(if $(DROMAJO), -I../tb/dromajo/src,) \
|
||||
-std=c++11 -I../tb/dpi
|
||||
|
||||
|
||||
ifdef spike-tandem
|
||||
CFLAGS += -Itb/riscv-isa-sim/install/include/spike
|
||||
endif
|
||||
|
@ -385,17 +387,78 @@ verilate_command := $(verilator)
|
|||
-Wno-UNOPTFLAT \
|
||||
-Wno-BLKANDNBLK \
|
||||
-Wno-style \
|
||||
$(if $(DROMAJO), -DDROMAJO=1,) \
|
||||
$(if $(PROFILE),--stats --stats-vars --profile-cfuncs,) \
|
||||
$(if $(DEBUG),--trace --trace-structs,) \
|
||||
-LDFLAGS "-L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -lfesvr$(if $(PROFILE), -g -pg,) -lpthread" \
|
||||
-CFLAGS "$(CFLAGS)$(if $(PROFILE), -g -pg,)" -Wall --cc --vpi \
|
||||
-LDFLAGS "-L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -lfesvr$(if $(PROFILE), -g -pg,) $(if $(DROMAJO), -L../tb/dromajo/src -ldromajo_cosim,) -lpthread" \
|
||||
-CFLAGS "$(CFLAGS)$(if $(PROFILE), -g -pg,) $(if $(DROMAJO), -DDROMAJO=1,)" -Wall --cc --vpi \
|
||||
$(list_incdir) --top-module ariane_testharness \
|
||||
--Mdir $(ver-library) -O3 \
|
||||
--exe tb/ariane_tb.cpp tb/dpi/SimDTM.cc tb/dpi/SimJTAG.cc \
|
||||
tb/dpi/remote_bitbang.cc tb/dpi/msim_helper.cc
|
||||
tb/dpi/remote_bitbang.cc tb/dpi/msim_helper.cc $(if $(DROMAJO), tb/dpi/dromajo_cosim_dpi.cc,)
|
||||
|
||||
dromajo:
|
||||
cd ./tb/dromajo/src && make
|
||||
|
||||
run-dromajo-verilator:
|
||||
$(if $(BIN), $(MAKE) checkpoint_dromajo, $(error "Please provide absolute path to the binary. Usage: make run_dromajo BIN=/absolute/path/to/binary"))
|
||||
|
||||
checkpoint_dromajo:
|
||||
cd ./tb/dromajo/run/checkpoints/ && \
|
||||
rm -rf $(notdir $(BIN)) && mkdir $(notdir $(BIN)) && cd $(notdir $(BIN)) && \
|
||||
cp $(BIN) . && \
|
||||
echo -e "\
|
||||
{\n\
|
||||
\"version\":1,\n\
|
||||
\"machine\":\"riscv64\",\n\
|
||||
\"memory_size\":256,\n\
|
||||
\"bios\":\"$(shell pwd)/tb/dromajo/run/checkpoints/$(notdir $(BIN))/$(notdir $(BIN))\",\n\
|
||||
\"memory_base_addr\":0x80000000,\n\
|
||||
\"missing_csrs\": [0x323, 0x324, 0x325, 0x326, //mhpmevent csrs\n\
|
||||
0x327, 0x328, 0x329, 0x32a,\n\
|
||||
0x32b, 0x32c, 0x32d, 0x32e,\n\
|
||||
0x32f, 0x330, 0x331, 0x332,\n\
|
||||
0x333, 0x334, 0x335, 0x336,\n\
|
||||
0x337, 0x338, 0x339, 0x33a,\n\
|
||||
0x33b, 0x33c, 0x33d, 0x33e,\n\
|
||||
0x33f,\n\
|
||||
0x3a0, 0x3a1, 0x3a2, 0x3a3, //pmp csrs\n\
|
||||
0x3b0, 0x3b1, 0x3b2, 0x3b3,\n\
|
||||
0x3b4, 0x3b5, 0x3b6, 0x3b7,\n\
|
||||
0x3b8, 0x3b9, 0x3ba, 0x3bb,\n\
|
||||
0x3bc, 0x3bd, 0x3be, 0x3bf,\n\
|
||||
0x320], //mcountinhibit\n\
|
||||
\"maxinsns\": 100,\n\
|
||||
\"clint_base_addr\": 0x02000000,\n\
|
||||
\"clint_size\": 0xC0000,\n\
|
||||
\"plic_base_addr\": 0x0C000000,\n\
|
||||
\"plic_size\": 0x3FFFFFF,\n\
|
||||
\"uart_base_addr\": 0x10000000,\n\
|
||||
\"uart_size\": 0x1000\n\
|
||||
}" > "$(notdir $(BIN))_boot.cfg" && \
|
||||
echo -e "\
|
||||
{\n\
|
||||
\"version\":1,\n\
|
||||
\"machine\":\"riscv64\",\n\
|
||||
\"memory_size\":256,\n\
|
||||
\"bios\":\"$(shell pwd)/tb/dromajo/run/checkpoints/$(notdir $(BIN))/$(notdir $(BIN))\",\n\
|
||||
\"load\":\"$(shell pwd)/tb/dromajo/run/checkpoints/$(notdir $(BIN))/$(notdir $(BIN))\",\n\
|
||||
\"skip_commit\": [0x73, 0x9002, 0x100073],\n\
|
||||
\"memory_base_addr\":0x80000000,\n\
|
||||
\"clint_base_addr\": 0x02000000,\n\
|
||||
\"clint_size\": 0xC0000,\n\
|
||||
\"plic_base_addr\": 0x0C000000,\n\
|
||||
\"plic_size\": 0x3FFFFFF,\n\
|
||||
\"uart_base_addr\": 0x10000000,\n\
|
||||
\"uart_size\": 0x1000\n\
|
||||
}" > "$(notdir $(BIN)).cfg" && \
|
||||
../../../src/dromajo --save=$(notdir $(BIN)) --save_format=1 ./$(notdir $(BIN))_boot.cfg && \
|
||||
cd ../../../../../ && \
|
||||
./work-ver/Variane_testharness +checkpoint=$(shell pwd)/tb/dromajo/run/checkpoints/$(notdir $(BIN))/$(notdir $(BIN))
|
||||
|
||||
|
||||
# User Verilator, at some point in the future this will be auto-generated
|
||||
verilate:
|
||||
verilate: $(if $(DROMAJO), dromajo,)
|
||||
@echo "[Verilator] Building Model$(if $(PROFILE), for Profiling,)"
|
||||
$(verilate_command)
|
||||
cd $(ver-library) && $(MAKE) -j${NUM_JOBS} -f Variane_testharness.mk
|
||||
|
|
17
README.md
17
README.md
|
@ -44,6 +44,7 @@ Table of Contents
|
|||
* [Going Beyond](#going-beyond)
|
||||
* [CI Testsuites and Randomized Constrained Testing with Torture](#ci-testsuites-and-randomized-constrained-testing-with-torture)
|
||||
* [Re-generating the Bootcode (ZSBL)](#re-generating-the-bootcode-zsbl)
|
||||
* [Co-simulation with Dromajo](#co-simulation-with-dromajo)
|
||||
* [Contributing](#contributing)
|
||||
* [Acknowledgements](#acknowledgements)
|
||||
|
||||
|
@ -337,6 +338,22 @@ The zero stage bootloader (ZSBL) for RTL simulation lives in `bootrom/` while th
|
|||
|
||||
To re-generate the bootcode you can use the existing makefile within those directories. To generate the SystemVerilog files you will need the `bitstring` python package installed on your system.
|
||||
|
||||
### Co-simulation with Dromajo
|
||||
Ariane can be co-simulated with [Dromajo](https://github.com/chipsalliance/dromajo) (currently in the verilator model).
|
||||
|
||||
```
|
||||
make verilate DROMAJO=1
|
||||
make run-dromajo-verilator BIN=/path/to/elf
|
||||
```
|
||||
|
||||
The co-simulation flow is depicted in the figure below.
|
||||

|
||||
1. Load the binary of interest into Dromajo.
|
||||
2. Run Dromajo stand alone and let a couple of instructions to complete.
|
||||
3. Dump the checkpoint. This is the whole architectural state of the reference model. Dromajo dumps the main and boot memories. In addition, it generates a boot code. If you were to run that code it will restore the whole architectural state. This means that you can bring any two or more cores into complete synced architectural state by running this piece of code.
|
||||
4. Load the checkpoint into the RTL memory and the instance of Dromajo in RTL. Dromajo gets linked to a simulator as a shared library. RTL communicates to Dromajo through set of DPI calls.
|
||||
5. Run the RTL simulation and perform co-simulation.
|
||||
|
||||
# Contributing
|
||||
|
||||
Check out the [contribution guide](CONTRIBUTING.md)
|
||||
|
|
62
bootrom/dromajo_bootrom.sv
Normal file
62
bootrom/dromajo_bootrom.sv
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Copyright 2020 ETH Zurich and University of Bologna.
|
||||
* Copyright and related rights are licensed under the Solderpad Hardware
|
||||
* License, Version 0.51 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
* or agreed to in writing, software, hardware and materials distributed under
|
||||
* this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* File: dromajo_bootrom.sv
|
||||
*
|
||||
* Author: Nursultan Kabylkas, UCSC
|
||||
* Description: bootrom that gets synced with dromajo for
|
||||
* cosimulation purposes.
|
||||
*/
|
||||
|
||||
module dromajo_bootrom (
|
||||
input logic clk_i,
|
||||
input logic req_i,
|
||||
input logic [63:0] addr_i,
|
||||
output logic [63:0] rdata_o
|
||||
);
|
||||
localparam int RomSize = 4096;
|
||||
logic [63:0] mem[RomSize-1:0];
|
||||
|
||||
initial begin
|
||||
integer hex_file, num_bytes;
|
||||
longint address, value;
|
||||
string f_name;
|
||||
// init to 0
|
||||
for (int k=0; k<RomSize; k++) begin
|
||||
mem[k] = 0;
|
||||
end
|
||||
|
||||
// sync with dromajo
|
||||
if ($value$plusargs("checkpoint=%s", f_name)) begin
|
||||
hex_file = $fopen({f_name,".bootram.hex"}, "r");
|
||||
while (!$feof(hex_file)) begin
|
||||
num_bytes = $fscanf(hex_file, "%d %h\n", address, value);
|
||||
//$display("%d %h", address, value);
|
||||
mem[address] = value;
|
||||
end
|
||||
$display("Done syncing boot ROM with dromajo...\n");
|
||||
end else begin
|
||||
$display("Failed syncing boot ROM: provide path to a checkpoint.\n");
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
logic [$clog2(RomSize)-1:0] addr_q;
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
|
||||
end
|
||||
end
|
||||
|
||||
// this prevents spurious Xes from propagating into
|
||||
// the speculative fetch stage of the core
|
||||
assign rdata_o = (addr_q < RomSize) ? mem[addr_q] : '0;
|
||||
endmodule
|
|
@ -12,6 +12,16 @@
|
|||
// Date: 19.03.2017
|
||||
// Description: Ariane Top-level module
|
||||
|
||||
`ifdef DROMAJO
|
||||
import "DPI-C" function void dromajo_trap(int hart_id,
|
||||
longint cause);
|
||||
import "DPI-C" function void dromajo_step(int hart_id,
|
||||
longint pc,
|
||||
int insn,
|
||||
longint wdata, longint cycle);
|
||||
import "DPI-C" function void init_dromajo(string cfg_f_name);
|
||||
`endif
|
||||
|
||||
import ariane_pkg::*;
|
||||
|
||||
module ariane #(
|
||||
|
@ -781,10 +791,51 @@ module ariane #(
|
|||
int f;
|
||||
logic [63:0] cycles;
|
||||
|
||||
`ifdef DROMAJO
|
||||
initial begin
|
||||
string f_name;
|
||||
if ($value$plusargs("checkpoint=%s", f_name)) begin
|
||||
init_dromajo({f_name, ".cfg"});
|
||||
$display("Done initing dromajo...");
|
||||
end else begin
|
||||
$display("Failed initing dromajo. Provide checkpoint name.");
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
initial begin
|
||||
f = $fopen("trace_hart_00.dasm", "w");
|
||||
end
|
||||
|
||||
`ifdef DROMAJO
|
||||
always_ff @(posedge clk_i) begin
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
if (commit_instr_id_commit[i].ex.valid) begin
|
||||
dromajo_trap(hart_id_i,
|
||||
commit_instr_id_commit[i].ex.cause);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
if (commit_ack[i] && !commit_instr_id_commit[i].ex.valid) begin
|
||||
if (csr_op_commit_csr == 0) begin
|
||||
dromajo_step(hart_id_i,
|
||||
commit_instr_id_commit[i].pc,
|
||||
commit_instr_id_commit[i].ex.tval[31:0],
|
||||
commit_instr_id_commit[i].result, cycles);
|
||||
end else begin
|
||||
dromajo_step(hart_id_i,
|
||||
commit_instr_id_commit[i].pc,
|
||||
commit_instr_id_commit[i].ex.tval[31:0],
|
||||
csr_rdata_csr_commit, cycles);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
cycles <= 0;
|
||||
|
|
|
@ -400,8 +400,6 @@ module csr_regfile #(
|
|||
dcsr_d = csr_wdata[31:0];
|
||||
// debug is implemented
|
||||
dcsr_d.xdebugver = 4'h4;
|
||||
// privilege level
|
||||
dcsr_d.prv = priv_lvl_q;
|
||||
// currently not supported
|
||||
dcsr_d.nmip = 1'b0;
|
||||
dcsr_d.stopcount = 1'b0;
|
||||
|
@ -662,6 +660,7 @@ module csr_regfile #(
|
|||
|
||||
// caused by a breakpoint
|
||||
if (ex_i.valid && ex_i.cause == riscv::BREAKPOINT) begin
|
||||
dcsr_d.prv = priv_lvl_o;
|
||||
// check that we actually want to enter debug depending on the privilege level we are currently in
|
||||
unique case (priv_lvl_o)
|
||||
riscv::PRIV_LVL_M: begin
|
||||
|
@ -685,6 +684,7 @@ module csr_regfile #(
|
|||
|
||||
// we've got a debug request
|
||||
if (ex_i.valid && ex_i.cause == riscv::DEBUG_REQUEST) begin
|
||||
dcsr_d.prv = priv_lvl_o;
|
||||
// save the PC
|
||||
dpc_d = {{64-riscv::VLEN{pc_i[riscv::VLEN-1]}},pc_i};
|
||||
// enter debug mode
|
||||
|
@ -697,6 +697,7 @@ module csr_regfile #(
|
|||
|
||||
// single step enable and we just retired an instruction
|
||||
if (dcsr_q.step && commit_ack_i[0]) begin
|
||||
dcsr_d.prv = priv_lvl_o;
|
||||
// valid CTRL flow change
|
||||
if (commit_instr_i[0].fu == CTRL_FLOW) begin
|
||||
// we saved the correct target address during execute
|
||||
|
@ -989,7 +990,11 @@ module csr_regfile #(
|
|||
// floating-point registers
|
||||
fcsr_q <= 64'b0;
|
||||
// debug signals
|
||||
`ifdef DROMAJO
|
||||
debug_mode_q <= 1'b1;
|
||||
`else
|
||||
debug_mode_q <= 1'b0;
|
||||
`endif
|
||||
dcsr_q <= '0;
|
||||
dcsr_q.prv <= riscv::PRIV_LVL_M;
|
||||
dpc_q <= 64'b0;
|
||||
|
|
129
src/dromajo_ram.sv
Normal file
129
src/dromajo_ram.sv
Normal file
|
@ -0,0 +1,129 @@
|
|||
// Copyright 2014 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
/**
|
||||
* This is the copied and modified version of Inferable, Synchronous Single
|
||||
* -Port N x 64bit RAM with Byte-Wise Enable to support dromajo cosimulation
|
||||
*
|
||||
* Current Maintainers:
|
||||
* - Nursultan Kabylkas
|
||||
*/
|
||||
|
||||
module dromajo_ram
|
||||
#(
|
||||
parameter ADDR_WIDTH = 10,
|
||||
parameter DATA_DEPTH = 1024, // usually 2**ADDR_WIDTH, but can be lower
|
||||
parameter OUT_REGS = 0 // set to 1 to enable outregs
|
||||
)(
|
||||
input logic Clk_CI,
|
||||
input logic Rst_RBI,
|
||||
input logic CSel_SI,
|
||||
input logic WrEn_SI,
|
||||
input logic [7:0] BEn_SI,
|
||||
input logic [63:0] WrData_DI,
|
||||
input logic [ADDR_WIDTH-1:0] Addr_DI,
|
||||
output logic [63:0] RdData_DO
|
||||
);
|
||||
|
||||
////////////////////////////
|
||||
// signals, localparams
|
||||
////////////////////////////
|
||||
|
||||
// needs to be consistent with the Altera implemenation below
|
||||
localparam DATA_BYTES = 8;
|
||||
|
||||
logic [DATA_BYTES*8-1:0] RdData_DN;
|
||||
logic [DATA_BYTES*8-1:0] RdData_DP;
|
||||
|
||||
logic [DATA_BYTES*8-1:0] Mem_DP[DATA_DEPTH-1:0];
|
||||
|
||||
////////////////////////////
|
||||
// DROMAJO COSIM OPTION
|
||||
// sync rams
|
||||
////////////////////////////\
|
||||
initial begin
|
||||
integer hex_file, num_bytes;
|
||||
longint address, value;
|
||||
string f_name;
|
||||
// init to 0
|
||||
for (int k=0; k<DATA_DEPTH; k++) begin
|
||||
Mem_DP[k] = 0;
|
||||
end
|
||||
|
||||
// sync with dromajo
|
||||
if ($value$plusargs("checkpoint=%s", f_name)) begin
|
||||
hex_file = $fopen({f_name,".mainram.hex"}, "r");
|
||||
while (!$feof(hex_file)) begin
|
||||
num_bytes = $fscanf(hex_file, "%d %h\n", address, value);
|
||||
//$display("%d %h", address, value);
|
||||
Mem_DP[address] = value;
|
||||
end
|
||||
$display("Done syncing RAM with dromajo...\n");
|
||||
end else begin
|
||||
$display("Failed syncing RAM: provide path to a checkpoint.\n");
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge Clk_CI) begin
|
||||
if(CSel_SI) begin
|
||||
if(WrEn_SI) begin
|
||||
if(BEn_SI[0]) Mem_DP[Addr_DI][7:0] <= WrData_DI[7:0];
|
||||
if(BEn_SI[1]) Mem_DP[Addr_DI][15:8] <= WrData_DI[15:8];
|
||||
if(BEn_SI[2]) Mem_DP[Addr_DI][23:16] <= WrData_DI[23:16];
|
||||
if(BEn_SI[3]) Mem_DP[Addr_DI][31:24] <= WrData_DI[31:24];
|
||||
if(BEn_SI[4]) Mem_DP[Addr_DI][39:32] <= WrData_DI[39:32];
|
||||
if(BEn_SI[5]) Mem_DP[Addr_DI][47:40] <= WrData_DI[47:40];
|
||||
if(BEn_SI[6]) Mem_DP[Addr_DI][55:48] <= WrData_DI[55:48];
|
||||
if(BEn_SI[7]) Mem_DP[Addr_DI][63:56] <= WrData_DI[63:56];
|
||||
end
|
||||
RdData_DN <= Mem_DP[Addr_DI];
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////
|
||||
// optional output regs
|
||||
////////////////////////////
|
||||
|
||||
// output regs
|
||||
generate
|
||||
if (OUT_REGS>0) begin : g_outreg
|
||||
always_ff @(posedge Clk_CI or negedge Rst_RBI) begin
|
||||
if(Rst_RBI == 1'b0)
|
||||
begin
|
||||
RdData_DP <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
RdData_DP <= RdData_DN;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate // g_outreg
|
||||
|
||||
// output reg bypass
|
||||
generate
|
||||
if (OUT_REGS==0) begin : g_oureg_byp
|
||||
assign RdData_DP = RdData_DN;
|
||||
end
|
||||
endgenerate// g_oureg_byp
|
||||
|
||||
assign RdData_DO = RdData_DP;
|
||||
|
||||
////////////////////////////
|
||||
// assertions
|
||||
////////////////////////////
|
||||
|
||||
// pragma translate_off
|
||||
assert property
|
||||
(@(posedge Clk_CI) (longint'(2)**longint'(ADDR_WIDTH) >= longint'(DATA_DEPTH)))
|
||||
else $error("depth out of bounds");
|
||||
// pragma translate_on
|
||||
|
||||
endmodule //dromajo_ram
|
|
@ -21,7 +21,8 @@
|
|||
module sram #(
|
||||
parameter DATA_WIDTH = 64,
|
||||
parameter NUM_WORDS = 1024,
|
||||
parameter OUT_REGS = 0 // enables output registers in FPGA macro (read lat = 2)
|
||||
parameter OUT_REGS = 0, // enables output registers in FPGA macro (read lat = 2)
|
||||
parameter DROMAJO_RAM = 0
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -53,6 +54,22 @@ end
|
|||
genvar k;
|
||||
generate
|
||||
for (k = 0; k<(DATA_WIDTH+63)/64; k++) begin
|
||||
if (DROMAJO_RAM) begin
|
||||
dromajo_ram #(
|
||||
.ADDR_WIDTH($clog2(NUM_WORDS)),
|
||||
.DATA_DEPTH(NUM_WORDS),
|
||||
.OUT_REGS (0)
|
||||
) i_ram (
|
||||
.Clk_CI ( clk_i ),
|
||||
.Rst_RBI ( rst_ni ),
|
||||
.CSel_SI ( req_i ),
|
||||
.WrEn_SI ( we_i ),
|
||||
.BEn_SI ( be_aligned[k*8 +: 8] ),
|
||||
.WrData_DI ( wdata_aligned[k*64 +: 64] ),
|
||||
.Addr_DI ( addr_i ),
|
||||
.RdData_DO ( rdata_aligned[k*64 +: 64] )
|
||||
);
|
||||
end else begin
|
||||
// unused byte-enable segments (8bits) are culled by the tool
|
||||
SyncSpRamBeNx64 #(
|
||||
.ADDR_WIDTH($clog2(NUM_WORDS)),
|
||||
|
@ -71,7 +88,7 @@ generate
|
|||
.Addr_DI ( addr_i ),
|
||||
.RdData_DO ( rdata_aligned[k*64 +: 64] )
|
||||
);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule : sram
|
||||
|
|
|
@ -44,12 +44,14 @@ static vluint64_t main_time = 0;
|
|||
|
||||
static const char *verilog_plusargs[] = {"jtag_rbb_enable"};
|
||||
|
||||
#ifndef DROMAJO
|
||||
extern dtm_t* dtm;
|
||||
extern remote_bitbang_t * jtag;
|
||||
|
||||
void handle_sigterm(int sig) {
|
||||
dtm->stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Called by $time in Verilog converts to double, to match what SystemC does
|
||||
double sc_time_stamp () {
|
||||
|
@ -150,6 +152,9 @@ int main(int argc, char **argv) {
|
|||
case 'r': rbb_port = atoi(optarg); break;
|
||||
case 'V': verbose = true; break;
|
||||
case 'p': perf = true; break;
|
||||
#ifdef DROMAJO
|
||||
case 'D': break;
|
||||
#endif
|
||||
#if VM_TRACE
|
||||
case 'v': {
|
||||
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
|
||||
|
@ -175,6 +180,12 @@ int main(int argc, char **argv) {
|
|||
c = 'm';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#ifdef DROMAJO
|
||||
else if (arg.substr(0, 12) == "+checkpoint=") {
|
||||
c = 'D';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#endif
|
||||
#if VM_TRACE
|
||||
else if (arg.substr(0, 12) == "+dump-start=") {
|
||||
c = 'x';
|
||||
|
@ -233,11 +244,15 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
done_processing:
|
||||
// allow proceeding without a binary if DROMAJO set,
|
||||
// binary will be loaded through checkpoint
|
||||
#ifndef DROMAJO
|
||||
if (optind == argc) {
|
||||
std::cerr << "No binary specified for emulator\n";
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
int htif_argc = 1 + argc - optind;
|
||||
htif_argv = (char **) malloc((htif_argc) * sizeof (char *));
|
||||
htif_argv[0] = argv[0];
|
||||
|
@ -246,9 +261,11 @@ done_processing:
|
|||
const char *vcd_file = NULL;
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
#ifndef DROMAJO
|
||||
jtag = new remote_bitbang_t(rbb_port);
|
||||
dtm = new dtm_t(htif_argc, htif_argv);
|
||||
signal(SIGTERM, handle_sigterm);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Variane_testharness> top(new Variane_testharness);
|
||||
|
||||
|
@ -279,7 +296,12 @@ done_processing:
|
|||
}
|
||||
top->rst_ni = 1;
|
||||
|
||||
#ifndef DROMAJO
|
||||
while (!dtm->done() && !jtag->done()) {
|
||||
#else
|
||||
// the simulation gets killed by dromajo
|
||||
while (true) {
|
||||
#endif
|
||||
top->clk_i = 0;
|
||||
top->eval();
|
||||
#if VM_TRACE
|
||||
|
@ -308,6 +330,7 @@ done_processing:
|
|||
fclose(vcdfile);
|
||||
#endif
|
||||
|
||||
#ifndef DROMAJO
|
||||
if (dtm->exit_code()) {
|
||||
fprintf(stderr, "%s *** FAILED *** (code = %d) after %ld cycles\n", htif_argv[1], dtm->exit_code(), main_time);
|
||||
ret = dtm->exit_code();
|
||||
|
@ -320,6 +343,7 @@ done_processing:
|
|||
|
||||
if (dtm) delete dtm;
|
||||
if (jtag) delete jtag;
|
||||
#endif
|
||||
|
||||
std::clock_t c_end = std::clock();
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
|
|
|
@ -17,7 +17,11 @@ module ariane_testharness #(
|
|||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_ADDRESS_WIDTH = 64,
|
||||
parameter int unsigned AXI_DATA_WIDTH = 64,
|
||||
`ifdef DROMAJO
|
||||
parameter bit InclSimDTM = 1'b0,
|
||||
`else
|
||||
parameter bit InclSimDTM = 1'b1,
|
||||
`endif
|
||||
parameter int unsigned NUM_WORDS = 2**25, // memory size
|
||||
parameter bit StallRandomOutput = 1'b0,
|
||||
parameter bit StallRandomInput = 1'b0
|
||||
|
@ -319,13 +323,21 @@ module ariane_testharness #(
|
|||
.data_i ( rom_rdata )
|
||||
);
|
||||
|
||||
`ifdef DROMAJO
|
||||
dromajo_bootrom i_bootrom (
|
||||
.clk_i ( clk_i ),
|
||||
.req_i ( rom_req ),
|
||||
.addr_i ( rom_addr ),
|
||||
.rdata_o ( rom_rdata )
|
||||
);
|
||||
`else
|
||||
bootrom i_bootrom (
|
||||
.clk_i ( clk_i ),
|
||||
.req_i ( rom_req ),
|
||||
.addr_i ( rom_addr ),
|
||||
.rdata_o ( rom_rdata )
|
||||
);
|
||||
|
||||
`endif
|
||||
// ------------------------------
|
||||
// Memory + Exclusive Access
|
||||
// ------------------------------
|
||||
|
@ -514,6 +526,9 @@ module ariane_testharness #(
|
|||
|
||||
sram #(
|
||||
.DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
`ifdef DROMAJO
|
||||
.DROMAJO_RAM (1),
|
||||
`endif
|
||||
.NUM_WORDS ( NUM_WORDS )
|
||||
) i_sram (
|
||||
.clk_i ( clk_i ),
|
||||
|
|
102
tb/dpi/dromajo_cosim_dpi.cc
Normal file
102
tb/dpi/dromajo_cosim_dpi.cc
Normal file
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2017-2020 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
// Author: Nursultan Kabylkas, UCSC
|
||||
// Date: Jun 15, 2020
|
||||
// Description: DPI wrappers to interface with Dromajo RISC-V emulator
|
||||
|
||||
#include <svdpi.h>
|
||||
#include <iostream>
|
||||
#include "dromajo_cosim.h"
|
||||
#include "stdlib.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* pointer to the dromajo emulator this pointer gets
|
||||
* accessed from RTL
|
||||
*/
|
||||
dromajo_cosim_state_t* dromajo_pointer;
|
||||
|
||||
/**
|
||||
* set the counter variable to number of instructions
|
||||
* you want to commit after the cosim failure. This is
|
||||
* sometimes useful when debugging to see waveform
|
||||
* activity post failure
|
||||
*/
|
||||
bool kill_soon = false;
|
||||
uint32_t counter = 0;
|
||||
|
||||
/**
|
||||
* Initialize dromajo emulator
|
||||
*
|
||||
* This function should usually be called from the initial
|
||||
* block in RTL.
|
||||
*
|
||||
* @param config (.cfg) file with the configurations
|
||||
*/
|
||||
extern "C" void init_dromajo(char* cfg_f_name) {
|
||||
char *argv[] = {(char*)"Variane", cfg_f_name};
|
||||
|
||||
dromajo_pointer = dromajo_cosim_init(2, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress the emulator
|
||||
*
|
||||
* This function progresses the emulator by one instruction
|
||||
* and compares the results by the committed instruction
|
||||
* in RTL. The following parameters are passed from RTL to
|
||||
* dromajo for comparison purposes.
|
||||
*
|
||||
* @param hart_id - id of the HART that is commiting instruction
|
||||
* @param pc - pc of the instruction being committed
|
||||
* @param insn - RISCV instruction being committed
|
||||
* @param wdata - the value being committed (what's going to destination register)
|
||||
* @param cycle - clock cycle number (optional, this is not compared)
|
||||
*/
|
||||
extern "C" void dromajo_step(int hart_id,
|
||||
uint64_t pc,
|
||||
uint32_t insn,
|
||||
uint64_t wdata,
|
||||
uint64_t cycle) {
|
||||
int exit_code;
|
||||
do {
|
||||
exit_code = dromajo_cosim_step(dromajo_pointer, hart_id, pc, insn, wdata, 0, true);
|
||||
} while (exit_code == 0x3);
|
||||
|
||||
if (exit_code > 3) {
|
||||
kill_soon = true;
|
||||
} else if (exit_code == 0x2){
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (kill_soon) {
|
||||
if (counter == 0) {
|
||||
std::cout << "Cosim failed!" << std::endl;
|
||||
exit(1);
|
||||
} else {
|
||||
std::cout << "Let's let it run for a couple of instructions" << std::endl;
|
||||
}
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects dromajo's execution flow on exception/interrupt
|
||||
*
|
||||
* @param hart_id - id of the HART that is trapping
|
||||
* @param cause - exception or interrupt cause
|
||||
*/
|
||||
extern "C" void dromajo_trap(int hart_id,
|
||||
uint64_t cause) {
|
||||
std::cout << "Dromajo trapping. Cause = " << cause << std::endl;
|
||||
dromajo_cosim_raise_trap(dromajo_pointer, hart_id, cause);
|
||||
}
|
1
tb/dromajo
Submodule
1
tb/dromajo
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 8acade8725d5e6cbf373304b348a8d77e0a5c713
|
Loading…
Add table
Add a link
Reference in a new issue