mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-19 11:54:46 -04:00
🎨 Flatten tb submodule
This commit is contained in:
parent
319ed5632e
commit
622a09779a
20 changed files with 1833 additions and 48 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,9 +1,6 @@
|
|||
[submodule "riscv-torture"]
|
||||
path = riscv-torture
|
||||
url = https://github.com/pulp-platform/riscv-torture.git
|
||||
[submodule "tb"]
|
||||
path = tb
|
||||
url = https://github.com/pulp-platform/uvm-components.git
|
||||
[submodule "src/axi_mem_if"]
|
||||
path = src/axi_mem_if
|
||||
url = https://github.com/pulp-platform/axi_mem_if.git
|
||||
|
|
49
Makefile
49
Makefile
|
@ -17,20 +17,10 @@ questa_version ?=
|
|||
verilator ?= verilator
|
||||
# Sources
|
||||
# Ariane PKG
|
||||
ariane_pkg := include/riscv_pkg.sv src/debug/dm_pkg.sv include/ariane_pkg.sv include/nbdcache_pkg.sv
|
||||
ariane_pkg := include/riscv_pkg.sv src/debug/dm_pkg.sv include/ariane_pkg.sv include/nbdcache_pkg.sv include/axi_if.sv
|
||||
# utility modules
|
||||
util := $(wildcard src/util/*.svh) src/util/instruction_tracer_pkg.sv src/util/instruction_tracer_if.sv \
|
||||
src/util/generic_fifo.sv src/util/cluster_clock_gating.sv src/util/behav_sram.sv
|
||||
# test targets
|
||||
tests := alu scoreboard fifo dcache_arbiter store_queue lsu core fetch_fifo
|
||||
# UVM agents
|
||||
agents := $(wildcard tb/agents/*/*.sv*)
|
||||
# path to interfaces
|
||||
interfaces := $(wildcard include/*.svh)
|
||||
# UVM environments
|
||||
envs := $(wildcard tb/env/*/*.sv*)
|
||||
# UVM Sequences
|
||||
sequences := $(wildcard tb/sequences/*/*.sv*)
|
||||
# Test packages
|
||||
test_pkg := $(wildcard tb/test/*/*sequence_pkg.sv*) $(wildcard tb/test/*/*_pkg.sv*)
|
||||
# DPI
|
||||
|
@ -43,7 +33,7 @@ src := $(wildcard src/*.sv) $(wildcard tb/common/*.sv) $(wildcard tb/common/*.v)
|
|||
$(filter-out src/debug/dm_pkg.sv, $(wildcard src/debug/*.sv)) $(wildcard bootrom/*.sv) \
|
||||
$(wildcard src/debug/debug_rom/*.sv)
|
||||
# look for testbenches
|
||||
tbs := tb/alu_tb.sv tb/ariane_tb.sv tb/ariane_testharness.sv tb/dcache_arbiter_tb.sv tb/store_queue_tb.sv tb/scoreboard_tb.sv tb/fifo_tb.sv
|
||||
tbs := tb/ariane_tb.sv tb/ariane_testharness.sv
|
||||
|
||||
# RISCV-tests path
|
||||
riscv-test-dir := tmp/riscv-tests/build/isa
|
||||
|
@ -63,16 +53,15 @@ uvm-flags += +UVM_NO_RELNOTES
|
|||
list_incdir := $(foreach dir, ${incdir}, +incdir+$(dir))
|
||||
|
||||
# Build the TB and module using QuestaSim
|
||||
build: $(library) $(library)/.build-agents $(library)/.build-interfaces $(library)/.build-components \
|
||||
$(library)/.build-srcs $(library)/.build-tb $(library)/ariane_dpi.so
|
||||
build: $(library) $(library)/.build-srcs $(library)/.build-tb $(library)/ariane_dpi.so
|
||||
# Optimize top level
|
||||
vopt$(questa_version) $(compile_flag) -work $(library) $(test_top_level) -o $(test_top_level)_optimized +acc -check_synthesis
|
||||
|
||||
# src files
|
||||
$(library)/.build-srcs: $(util) $(src)
|
||||
$(library)/.build-srcs: $(ariane_pkg) $(util) $(src)
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) $(filter %.sv,$(ariane_pkg)) $(list_incdir) -suppress 2583
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) $(filter %.sv,$(util)) $(list_incdir) -suppress 2583
|
||||
# Suppress message that always_latch may not be checked thoroughly by QuestaSim.
|
||||
# Compile agents, interfaces and environments
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) -pedanticerrors $(src) $(list_incdir) -suppress 2583
|
||||
touch $(library)/.build-srcs
|
||||
|
||||
|
@ -90,22 +79,6 @@ $(library)/ariane_dpi.so: $(dpi)
|
|||
# Compile C-code and generate .so file
|
||||
g++ -shared -m64 -o $(library)/ariane_dpi.so $? -lfesvr
|
||||
|
||||
# Compile Sequences and Tests
|
||||
$(library)/.build-components: $(envs) $(sequences) $(test_pkg)
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) $(filter %.sv,$(envs)) $(filter %.sv,$(sequences)) \
|
||||
$(filter %.sv,$(test_pkg)) ${list_incdir} -suppress 2583
|
||||
touch $(library)/.build-components
|
||||
|
||||
# Compile Agents
|
||||
$(library)/.build-agents: $(agents) $(ariane_pkg)
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) $(ariane_pkg) $(filter %.sv,$(agents)) $(list_incdir) -suppress 2583
|
||||
touch $(library)/.build-agents
|
||||
|
||||
# Compile Interfaces
|
||||
$(library)/.build-interfaces: $(interfaces)
|
||||
vlog$(questa_version) $(compile_flag) -work $(library) $(interfaces) $(list_incdir) -suppress 2583
|
||||
touch $(library)/.build-interfaces
|
||||
|
||||
$(library):
|
||||
# Create the library
|
||||
vlib${questa_version} ${library}
|
||||
|
@ -127,17 +100,6 @@ run-asm-tests: build
|
|||
-do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
|
||||
$(library).$(test_top_level)_optimized +permissive-off ++$(test);)
|
||||
|
||||
# Run the specified test case
|
||||
$(tests): build
|
||||
# Optimize top level
|
||||
vopt${questa_version} -work ${library} ${compile_flag} $@_tb -o $@_tb_optimized +acc -check_synthesis
|
||||
# vsim${questa_version} $@_tb_optimized
|
||||
# vsim${questa_version} +UVM_TESTNAME=$@_test -coverage -classdebug $@_tb_optimized
|
||||
vsim${questa_version} -64 +UVM_TESTNAME=$@_test +ASMTEST=$(riscv-test-dir)/$(riscv-test) \
|
||||
+uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c -coverage -classdebug -sv_lib $(library)/ariane_dpi \
|
||||
-do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
|
||||
${library}.$@_tb_optimized
|
||||
|
||||
# User Verilator, at some point in the future this will be auto-generated
|
||||
verilate:
|
||||
$(verilator) \
|
||||
|
@ -155,7 +117,6 @@ verilate:
|
|||
src/util/cluster_clock_gating.sv \
|
||||
src/util/behav_sram.sv \
|
||||
src/axi_mem_if/src/axi2mem.sv \
|
||||
tb/agents/axi_if/axi_if.sv \
|
||||
+incdir+src/axi_node \
|
||||
--unroll-count 256 \
|
||||
-Werror-PINMISSING \
|
||||
|
|
128
include/axi_if.sv
Normal file
128
include/axi_if.sv
Normal file
|
@ -0,0 +1,128 @@
|
|||
// Copyright 2015 - 2018 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Only general functions and definitions are defined here //
|
||||
// These functions are not intended to be modified //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
interface AXI_BUS
|
||||
#(
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_DATA_WIDTH = 64,
|
||||
parameter AXI_ID_WIDTH = 10,
|
||||
parameter AXI_USER_WIDTH = 6
|
||||
);
|
||||
|
||||
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH/8;
|
||||
|
||||
logic [AXI_ADDR_WIDTH-1:0] aw_addr;
|
||||
logic [2:0] aw_prot;
|
||||
logic [3:0] aw_region;
|
||||
logic [7:0] aw_len;
|
||||
logic [2:0] aw_size;
|
||||
logic [1:0] aw_burst;
|
||||
logic aw_lock;
|
||||
logic [3:0] aw_cache;
|
||||
logic [3:0] aw_qos;
|
||||
logic [AXI_ID_WIDTH-1:0] aw_id;
|
||||
logic [AXI_USER_WIDTH-1:0] aw_user;
|
||||
logic aw_ready;
|
||||
logic aw_valid;
|
||||
|
||||
logic [AXI_ADDR_WIDTH-1:0] ar_addr;
|
||||
logic [2:0] ar_prot;
|
||||
logic [3:0] ar_region;
|
||||
logic [7:0] ar_len;
|
||||
logic [2:0] ar_size;
|
||||
logic [1:0] ar_burst;
|
||||
logic ar_lock;
|
||||
logic [3:0] ar_cache;
|
||||
logic [3:0] ar_qos;
|
||||
logic [AXI_ID_WIDTH-1:0] ar_id;
|
||||
logic [AXI_USER_WIDTH-1:0] ar_user;
|
||||
logic ar_ready;
|
||||
logic ar_valid;
|
||||
|
||||
logic w_valid;
|
||||
logic [AXI_DATA_WIDTH-1:0] w_data;
|
||||
logic [AXI_STRB_WIDTH-1:0] w_strb;
|
||||
logic [AXI_USER_WIDTH-1:0] w_user;
|
||||
logic w_last;
|
||||
logic w_ready;
|
||||
|
||||
logic [AXI_DATA_WIDTH-1:0] r_data;
|
||||
logic [1:0] r_resp;
|
||||
logic r_last;
|
||||
logic [AXI_ID_WIDTH-1:0] r_id;
|
||||
logic [AXI_USER_WIDTH-1:0] r_user;
|
||||
logic r_ready;
|
||||
logic r_valid;
|
||||
|
||||
logic [1:0] b_resp;
|
||||
logic [AXI_ID_WIDTH-1:0] b_id;
|
||||
logic [AXI_USER_WIDTH-1:0] b_user;
|
||||
logic b_ready;
|
||||
logic b_valid;
|
||||
|
||||
// Master Side
|
||||
//***************************************
|
||||
modport Master
|
||||
(
|
||||
|
||||
output aw_valid, output aw_addr, output aw_prot, output aw_region,
|
||||
output aw_len, output aw_size, output aw_burst, output aw_lock,
|
||||
output aw_cache, output aw_qos, output aw_id, output aw_user,
|
||||
input aw_ready,
|
||||
|
||||
output ar_valid, output ar_addr, output ar_prot, output ar_region,
|
||||
output ar_len, output ar_size, output ar_burst, output ar_lock,
|
||||
output ar_cache, output ar_qos, output ar_id, output ar_user,
|
||||
input ar_ready,
|
||||
|
||||
output w_valid, output w_data, output w_strb, output w_user, output w_last,
|
||||
input w_ready,
|
||||
|
||||
input r_valid, input r_data, input r_resp, input r_last, input r_id, input r_user,
|
||||
output r_ready,
|
||||
|
||||
input b_valid, input b_resp, input b_id, input b_user,
|
||||
output b_ready
|
||||
|
||||
);
|
||||
|
||||
// Slave Side
|
||||
//***************************************
|
||||
modport Slave
|
||||
(
|
||||
|
||||
input aw_valid, input aw_addr, input aw_prot, input aw_region,
|
||||
input aw_len, input aw_size, input aw_burst, input aw_lock,
|
||||
input aw_cache, input aw_qos, input aw_id, input aw_user,
|
||||
output aw_ready,
|
||||
|
||||
input ar_valid, input ar_addr, input ar_prot, input ar_region,
|
||||
input ar_len, input ar_size, input ar_burst, input ar_lock,
|
||||
input ar_cache, input ar_qos, input ar_id, input ar_user,
|
||||
output ar_ready,
|
||||
|
||||
input w_valid, input w_data, input w_strb, input w_user, input w_last,
|
||||
output w_ready,
|
||||
|
||||
output r_valid, output r_data, output r_resp, output r_last, output r_id, output r_user,
|
||||
input r_ready,
|
||||
|
||||
output b_valid, output b_resp, output b_id, output b_user,
|
||||
input b_ready
|
||||
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
1
tb
1
tb
|
@ -1 +0,0 @@
|
|||
Subproject commit 61b5a5eeeb79cd21382f1ab7fb856134ce63cf4f
|
329
tb/ariane_tb.cpp
Normal file
329
tb/ariane_tb.cpp
Normal file
|
@ -0,0 +1,329 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the 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.
|
||||
|
||||
#include "Variane_testharness.h"
|
||||
#include "verilator.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
#include "Variane_testharness__Dpi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <getopt.h>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
#include <fesvr/dtm.h>
|
||||
#include "remote_bitbang.h"
|
||||
// This software is heavily based on Rocket Chip
|
||||
// Checkout this awesome project:
|
||||
// https://github.com/freechipsproject/rocket-chip/
|
||||
|
||||
|
||||
// This is a 64-bit integer to reduce wrap over issues and
|
||||
// allow modulus. You can also use a double, if you wish.
|
||||
static vluint64_t main_time = 0;
|
||||
|
||||
static const char *verilog_plusargs[] = {"jtag_rbb_enable"};
|
||||
|
||||
extern dtm_t* dtm;
|
||||
extern remote_bitbang_t * jtag;
|
||||
|
||||
void handle_sigterm(int sig) {
|
||||
dtm->stop();
|
||||
}
|
||||
|
||||
// Called by $time in Verilog converts to double, to match what SystemC does
|
||||
double sc_time_stamp () {
|
||||
return main_time;
|
||||
}
|
||||
|
||||
static void usage(const char * program_name) {
|
||||
printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\n",
|
||||
program_name);
|
||||
fputs("\
|
||||
Run a BINARY on the Ariane emulator.\n\
|
||||
\n\
|
||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
||||
\n\
|
||||
EMULATOR OPTIONS\n\
|
||||
-r, --rbb-port=PORT Use PORT for remote bit bang (with OpenOCD and GDB) \n\
|
||||
If not specified, a random port will be chosen\n\
|
||||
automatically.\n\
|
||||
", stdout);
|
||||
#if VM_TRACE == 0
|
||||
fputs("\
|
||||
\n\
|
||||
EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n",
|
||||
stdout);
|
||||
#endif
|
||||
fputs("\
|
||||
-v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\
|
||||
-p, Print performance statistic at end of test\n\
|
||||
", stdout);
|
||||
// fputs("\n" PLUSARG_USAGE_OPTIONS, stdout);
|
||||
fputs("\n" HTIF_USAGE_OPTIONS, stdout);
|
||||
printf("\n"
|
||||
"EXAMPLES\n"
|
||||
" - run a bare metal test:\n"
|
||||
" %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
||||
" - run a bare metal test showing cycle-by-cycle information:\n"
|
||||
" %s spike-dasm < trace_core_00_0.dasm > trace.out\n"
|
||||
#if VM_TRACE
|
||||
" - run a bare metal test to generate a VCD waveform:\n"
|
||||
" %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
||||
#endif
|
||||
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
|
||||
" %s pk hello\n",
|
||||
program_name, program_name, program_name
|
||||
#if VM_TRACE
|
||||
, program_name
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::clock_t c_start = std::clock();
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
bool verbose;
|
||||
bool perf;
|
||||
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
uint64_t max_cycles = -1;
|
||||
int ret = 0;
|
||||
bool print_cycles = false;
|
||||
// Port numbers are 16 bit unsigned integers.
|
||||
uint16_t rbb_port = 0;
|
||||
#if VM_TRACE
|
||||
FILE * vcdfile = NULL;
|
||||
uint64_t start = 0;
|
||||
#endif
|
||||
char ** htif_argv = NULL;
|
||||
int verilog_plusargs_legal = 1;
|
||||
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"cycle-count", no_argument, 0, 'c' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"max-cycles", required_argument, 0, 'm' },
|
||||
{"seed", required_argument, 0, 's' },
|
||||
{"rbb-port", required_argument, 0, 'r' },
|
||||
{"verbose", no_argument, 0, 'V' },
|
||||
#if VM_TRACE
|
||||
{"vcd", required_argument, 0, 'v' },
|
||||
{"dump-start", required_argument, 0, 'x' },
|
||||
#endif
|
||||
HTIF_LONG_OPTIONS
|
||||
};
|
||||
int option_index = 0;
|
||||
#if VM_TRACE
|
||||
int c = getopt_long(argc, argv, "-chpm:s:r:v:Vx:", long_options, &option_index);
|
||||
#else
|
||||
int c = getopt_long(argc, argv, "-chpm:s:r:V", long_options, &option_index);
|
||||
#endif
|
||||
if (c == -1) break;
|
||||
retry:
|
||||
switch (c) {
|
||||
// Process long and short EMULATOR options
|
||||
case '?': usage(argv[0]); return 1;
|
||||
case 'c': print_cycles = true; break;
|
||||
case 'h': usage(argv[0]); return 0;
|
||||
case 'm': max_cycles = atoll(optarg); break;
|
||||
case 's': random_seed = atoi(optarg); break;
|
||||
case 'r': rbb_port = atoi(optarg); break;
|
||||
case 'V': verbose = true; break;
|
||||
case 'p': perf = true; break;
|
||||
#if VM_TRACE
|
||||
case 'v': {
|
||||
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
|
||||
if (!vcdfile) {
|
||||
std::cerr << "Unable to open " << optarg << " for VCD write\n";
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x': start = atoll(optarg); break;
|
||||
#endif
|
||||
// Process legacy '+' EMULATOR arguments by replacing them with
|
||||
// their getopt equivalents
|
||||
case 1: {
|
||||
std::string arg = optarg;
|
||||
if (arg.substr(0, 1) != "+") {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
if (arg == "+verbose")
|
||||
c = 'V';
|
||||
else if (arg.substr(0, 12) == "+max-cycles=") {
|
||||
c = 'm';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#if VM_TRACE
|
||||
else if (arg.substr(0, 12) == "+dump-start=") {
|
||||
c = 'x';
|
||||
optarg = optarg+12;
|
||||
}
|
||||
#endif
|
||||
else if (arg.substr(0, 12) == "+cycle-count")
|
||||
c = 'c';
|
||||
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
||||
// a VERILOG_PLUSARG and not an error.
|
||||
else if (verilog_plusargs_legal) {
|
||||
const char ** plusarg = &verilog_plusargs[0];
|
||||
int legal_verilog_plusarg = 0;
|
||||
while (*plusarg && (legal_verilog_plusarg == 0)){
|
||||
if (arg.substr(1, strlen(*plusarg)) == *plusarg) {
|
||||
legal_verilog_plusarg = 1;
|
||||
}
|
||||
plusarg ++;
|
||||
}
|
||||
if (!legal_verilog_plusarg) {
|
||||
verilog_plusargs_legal = 0;
|
||||
} else {
|
||||
c = 'P';
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
// If we STILL don't find a legacy '+' argument, it still could be
|
||||
// an HTIF (HOST) argument and not an error. If this is the case, then
|
||||
// we're done processing EMULATOR and VERILOG arguments.
|
||||
else {
|
||||
static struct option htif_long_options [] = { HTIF_LONG_OPTIONS };
|
||||
struct option * htif_option = &htif_long_options[0];
|
||||
while (htif_option->name) {
|
||||
if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
htif_option++;
|
||||
}
|
||||
std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
|
||||
<< arg << "\"\n";
|
||||
c = '?';
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
case 'P': break; // Nothing to do here, Verilog PlusArg
|
||||
// Realize that we've hit HTIF (HOST) arguments or error out
|
||||
default:
|
||||
if (c >= HTIF_LONG_OPTIONS_OPTIND) {
|
||||
optind--;
|
||||
goto done_processing;
|
||||
}
|
||||
c = '?';
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
done_processing:
|
||||
if (optind == argc) {
|
||||
std::cerr << "No binary specified for emulator\n";
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
int htif_argc = 1 + argc - optind;
|
||||
htif_argv = (char **) malloc((htif_argc) * sizeof (char *));
|
||||
htif_argv[0] = argv[0];
|
||||
for (int i = 1; optind < argc;) htif_argv[i++] = argv[optind++];
|
||||
|
||||
const char *vcd_file = NULL;
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
jtag = new remote_bitbang_t(rbb_port);
|
||||
dtm = new dtm_t(htif_argc, htif_argv);
|
||||
signal(SIGTERM, handle_sigterm);
|
||||
|
||||
std::unique_ptr<Variane_testharness> top(new Variane_testharness);
|
||||
|
||||
#if VM_TRACE
|
||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
||||
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
|
||||
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
|
||||
if (vcdfile) {
|
||||
top->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
|
||||
tfp->open("");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
top->rst_ni = 0;
|
||||
top->clk_i = 0;
|
||||
top->eval();
|
||||
#if VM_TRACE
|
||||
tfp->dump(static_cast<vluint64_t>(main_time * 2));
|
||||
#endif
|
||||
top->clk_i = 1;
|
||||
top->eval();
|
||||
#if VM_TRACE
|
||||
tfp->dump(static_cast<vluint64_t>(main_time * 2 + 1));
|
||||
#endif
|
||||
main_time ++;
|
||||
}
|
||||
top->rst_ni = 1;
|
||||
|
||||
while (!dtm->done() && !jtag->done()) {
|
||||
top->clk_i = 0;
|
||||
top->eval();
|
||||
#if VM_TRACE
|
||||
// dump = tfp && trace_count >= start;
|
||||
// if (dump)
|
||||
tfp->dump(static_cast<vluint64_t>(main_time * 2));
|
||||
#endif
|
||||
|
||||
top->clk_i = 1;
|
||||
top->eval();
|
||||
#if VM_TRACE
|
||||
// if (dump)
|
||||
tfp->dump(static_cast<vluint64_t>(main_time * 2 + 1));
|
||||
#endif
|
||||
main_time++;
|
||||
}
|
||||
|
||||
#if VM_TRACE
|
||||
if (tfp)
|
||||
tfp->close();
|
||||
if (vcdfile)
|
||||
fclose(vcdfile);
|
||||
#endif
|
||||
|
||||
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();
|
||||
} else if (jtag->exit_code()) {
|
||||
fprintf(stderr, "%s *** FAILED *** (code = %d, seed %d) after %ld cycles\n", htif_argv[1], jtag->exit_code(), random_seed, main_time);
|
||||
ret = jtag->exit_code();
|
||||
} else {
|
||||
fprintf(stderr, "%s completed after %ld cycles\n", htif_argv[1], main_time);
|
||||
}
|
||||
|
||||
if (dtm) delete dtm;
|
||||
if (jtag) delete jtag;
|
||||
|
||||
std::clock_t c_end = std::clock();
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (perf) {
|
||||
std::cout << std::fixed << std::setprecision(2) << "CPU time used: "
|
||||
<< 1000.0 * (c_end-c_start) / CLOCKS_PER_SEC << " ms\n"
|
||||
<< "Wall clock time passed: "
|
||||
<< std::chrono::duration<double, std::milli>(t_end-t_start).count()
|
||||
<< " ms\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
86
tb/ariane_tb.sv
Normal file
86
tb/ariane_tb.sv
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2018 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: Florian Zaruba, ETH Zurich
|
||||
// Date: 15/04/2017
|
||||
// Description: Top level testbench module. Instantiates the top level DUT, configures
|
||||
// the virtual interfaces and starts the test passed by +UVM_TEST+
|
||||
|
||||
|
||||
import ariane_pkg::*;
|
||||
import uvm_pkg::*;
|
||||
|
||||
`include "uvm_macros.svh"
|
||||
|
||||
module ariane_tb;
|
||||
|
||||
// static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
|
||||
|
||||
localparam int unsigned CLOCK_PERIOD = 20ns;
|
||||
|
||||
logic clk_i;
|
||||
logic rst_ni;
|
||||
logic [63:0] time_i;
|
||||
|
||||
longint unsigned cycles;
|
||||
longint unsigned max_cycles;
|
||||
|
||||
logic [31:0] exit_o;
|
||||
|
||||
ariane_testharness dut (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.exit_o ( exit_o )
|
||||
);
|
||||
|
||||
// Clock process
|
||||
initial begin
|
||||
clk_i = 1'b0;
|
||||
rst_ni = 1'b0;
|
||||
repeat(8)
|
||||
#(CLOCK_PERIOD/2) clk_i = ~clk_i;
|
||||
rst_ni = 1'b1;
|
||||
forever begin
|
||||
#(CLOCK_PERIOD/2) clk_i = 1'b1;
|
||||
#(CLOCK_PERIOD/2) clk_i = 1'b0;
|
||||
|
||||
//if (cycles > max_cycles)
|
||||
// $fatal(1, "Simulation reached maximum cycle count of %d", max_cycles);
|
||||
|
||||
cycles++;
|
||||
end
|
||||
end
|
||||
// Real Time Clock
|
||||
initial begin
|
||||
// initialize platform timer
|
||||
time_i = 64'b0;
|
||||
// increment timer with a frequency of 32.768 kHz
|
||||
forever begin
|
||||
#30.517578us;
|
||||
time_i++;
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
forever begin
|
||||
|
||||
wait (exit_o[0]);
|
||||
|
||||
if ((exit_o >> 1)) begin
|
||||
`uvm_error( "Core Test", $sformatf("*** FAILED *** (tohost = %0d)", (exit_o >> 1)))
|
||||
end else begin
|
||||
`uvm_info( "Core Test", $sformatf("*** SUCCESS *** (tohost = %0d)", (exit_o >> 1)), UVM_LOW)
|
||||
end
|
||||
|
||||
$finish();
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
315
tb/ariane_testharness.sv
Normal file
315
tb/ariane_testharness.sv
Normal file
|
@ -0,0 +1,315 @@
|
|||
// Copyright 2018 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: Florian Zaruba, ETH Zurich
|
||||
// Date: 19.03.2017
|
||||
// Description: Test-harness for Ariane
|
||||
// Instantiates an AXI-Bus and memories
|
||||
|
||||
module ariane_testharness #(
|
||||
parameter logic [63:0] CACHE_START_ADDR = 64'h8000_0000, // address on which to decide whether the request is cache-able or not
|
||||
parameter int unsigned AXI_ID_WIDTH = 10,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_ADDRESS_WIDTH = 64,
|
||||
parameter int unsigned AXI_DATA_WIDTH = 64,
|
||||
parameter int unsigned NUM_WORDS = 2**24 // memory size
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
output logic [31:0] exit_o
|
||||
);
|
||||
|
||||
// disable test-enable
|
||||
logic test_en;
|
||||
logic ndmreset;
|
||||
logic ndmreset_n;
|
||||
logic debug_req;
|
||||
|
||||
int jtag_enable;
|
||||
logic init_done;
|
||||
logic [31:0] jtag_exit, dmi_exit;
|
||||
|
||||
logic jtag_TCK;
|
||||
logic jtag_TMS;
|
||||
logic jtag_TDI;
|
||||
logic jtag_TRSTn;
|
||||
logic jtag_TDO_data;
|
||||
logic jtag_TDO_driven;
|
||||
|
||||
logic debug_req_valid;
|
||||
logic debug_req_ready;
|
||||
logic [6:0] debug_req_bits_addr;
|
||||
logic [1:0] debug_req_bits_op;
|
||||
logic [31:0] debug_req_bits_data;
|
||||
logic debug_resp_valid;
|
||||
logic debug_resp_ready;
|
||||
logic [1:0] debug_resp_bits_resp;
|
||||
logic [31:0] debug_resp_bits_data;
|
||||
|
||||
logic jtag_req_valid;
|
||||
logic [6:0] jtag_req_bits_addr;
|
||||
logic [1:0] jtag_req_bits_op;
|
||||
logic [31:0] jtag_req_bits_data;
|
||||
logic jtag_resp_ready;
|
||||
logic jtag_resp_valid;
|
||||
|
||||
logic dmi_req_valid;
|
||||
logic [6:0] dmi_req_bits_addr;
|
||||
logic [1:0] dmi_req_bits_op;
|
||||
logic [31:0] dmi_req_bits_data;
|
||||
logic dmi_resp_ready;
|
||||
logic dmi_resp_valid;
|
||||
|
||||
assign test_en = 1'b0;
|
||||
assign ndmreset_n = ~ndmreset ;
|
||||
|
||||
localparam NB_SLAVE = 3;
|
||||
localparam NB_MASTER = 3;
|
||||
localparam AXI_ID_WIDTH_SLAVES = AXI_ID_WIDTH + $clog2(NB_SLAVE);
|
||||
|
||||
AXI_BUS #(
|
||||
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
|
||||
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
|
||||
) slave[NB_SLAVE-1:0]();
|
||||
|
||||
AXI_BUS #(
|
||||
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
|
||||
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
|
||||
) master[NB_MASTER-1:0]();
|
||||
|
||||
// ---------------
|
||||
// Debug
|
||||
// ---------------
|
||||
assign init_done = rst_ni;
|
||||
|
||||
initial begin
|
||||
if (!$value$plusargs("jtag_rbb_enable=%b", jtag_enable)) jtag_enable = 'h0;
|
||||
end
|
||||
|
||||
// debug if MUX
|
||||
assign debug_req_valid = (jtag_enable[0]) ? jtag_req_valid : dmi_req_valid;
|
||||
assign debug_req_bits_addr = (jtag_enable[0]) ? jtag_req_bits_addr : dmi_req_bits_addr;
|
||||
assign debug_req_bits_op = (jtag_enable[0]) ? jtag_req_bits_op : dmi_req_bits_op;
|
||||
assign debug_req_bits_data = (jtag_enable[0]) ? jtag_req_bits_data : dmi_req_bits_data;
|
||||
assign debug_resp_ready = (jtag_enable[0]) ? jtag_resp_ready : dmi_resp_ready;
|
||||
assign exit_o = (jtag_enable[0]) ? jtag_exit : dmi_exit;
|
||||
assign jtag_resp_valid = (jtag_enable[0]) ? debug_resp_valid : 1'b0;
|
||||
assign dmi_resp_valid = (jtag_enable[0]) ? 1'b0 : debug_resp_valid;
|
||||
|
||||
// SiFive's SimJTAG Module
|
||||
// Converts to DPI calls
|
||||
SimJTAG i_SimJTAG (
|
||||
.clock ( clk_i ),
|
||||
.reset ( ~rst_ni ),
|
||||
.enable ( jtag_enable[0] ),
|
||||
.init_done ( init_done ),
|
||||
.jtag_TCK ( jtag_TCK ),
|
||||
.jtag_TMS ( jtag_TMS ),
|
||||
.jtag_TDI ( jtag_TDI ),
|
||||
.jtag_TRSTn ( jtag_TRSTn ),
|
||||
.jtag_TDO_data ( jtag_TDO_data ),
|
||||
.jtag_TDO_driven ( jtag_TDO_driven ),
|
||||
.exit ( jtag_exit )
|
||||
);
|
||||
|
||||
dmi_jtag i_dmi_jtag (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
||||
.dmi_rst_no ( ),
|
||||
.dmi_req_valid_o ( jtag_req_valid ),
|
||||
.dmi_req_ready_i ( debug_req_ready ),
|
||||
.dmi_req_bits_addr_o ( jtag_req_bits_addr ),
|
||||
.dmi_req_bits_op_o ( jtag_req_bits_op ),
|
||||
.dmi_req_bits_data_o ( jtag_req_bits_data ),
|
||||
.dmi_resp_valid_i ( jtag_resp_valid ),
|
||||
.dmi_resp_ready_o ( jtag_resp_ready ),
|
||||
.dmi_resp_bits_resp_i ( debug_resp_bits_resp ),
|
||||
.dmi_resp_bits_data_i ( debug_resp_bits_data ),
|
||||
|
||||
.tck_i ( jtag_TCK ),
|
||||
.tms_i ( jtag_TMS ),
|
||||
.trst_ni ( jtag_TRSTn ),
|
||||
.td_i ( jtag_TDI ),
|
||||
.td_o ( jtag_TDO_data ),
|
||||
.tdo_oe_o ( jtag_TDO_driven )
|
||||
);
|
||||
|
||||
// SiFive's SimDTM Module
|
||||
// Converts to DPI calls
|
||||
SimDTM i_SimDTM (
|
||||
.clk ( clk_i ),
|
||||
.reset ( ~rst_ni ),
|
||||
.debug_req_valid ( dmi_req_valid ),
|
||||
.debug_req_ready ( debug_req_ready ),
|
||||
.debug_req_bits_addr ( dmi_req_bits_addr ),
|
||||
.debug_req_bits_op ( dmi_req_bits_op ),
|
||||
.debug_req_bits_data ( dmi_req_bits_data ),
|
||||
.debug_resp_valid ( dmi_resp_valid ),
|
||||
.debug_resp_ready ( dmi_resp_ready ),
|
||||
.debug_resp_bits_resp ( debug_resp_bits_resp ),
|
||||
.debug_resp_bits_data ( debug_resp_bits_data ),
|
||||
.exit ( dmi_exit )
|
||||
);
|
||||
|
||||
// debug module
|
||||
dm_top #(
|
||||
// current implementation only supports 1 hart
|
||||
.NrHarts ( 1 ),
|
||||
.AxiIdWidth ( AXI_ID_WIDTH_SLAVES ),
|
||||
.AxiAddrWidth ( AXI_ADDRESS_WIDTH ),
|
||||
.AxiDataWidth ( AXI_DATA_WIDTH ),
|
||||
.AxiUserWidth ( AXI_USER_WIDTH )
|
||||
) i_dm_top (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ), // PoR
|
||||
.ndmreset_o ( ndmreset ),
|
||||
.dmactive_o ( ), // active debug session
|
||||
.debug_req_o ( debug_req ),
|
||||
.axi_slave ( master[2] ),
|
||||
.dmi_rst_ni ( rst_ni ),
|
||||
.dmi_req_valid_i ( debug_req_valid ),
|
||||
.dmi_req_ready_o ( debug_req_ready ),
|
||||
.dmi_req_bits_addr_i ( debug_req_bits_addr ),
|
||||
.dmi_req_bits_op_i ( debug_req_bits_op ),
|
||||
.dmi_req_bits_data_i ( debug_req_bits_data ),
|
||||
.dmi_resp_valid_o ( debug_resp_valid ),
|
||||
.dmi_resp_ready_i ( debug_resp_ready ),
|
||||
.dmi_resp_bits_resp_o ( debug_resp_bits_resp ),
|
||||
.dmi_resp_bits_data_o ( debug_resp_bits_data )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// ROM
|
||||
// ---------------
|
||||
logic rom_req;
|
||||
logic [AXI_ADDRESS_WIDTH-1:0] rom_addr;
|
||||
logic [AXI_DATA_WIDTH-1:0] rom_rdata;
|
||||
|
||||
axi2mem #(
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
|
||||
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
|
||||
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
|
||||
) i_axi2rom (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.slave ( master[1] ),
|
||||
.req_o ( rom_req ),
|
||||
.we_o ( ),
|
||||
.addr_o ( rom_addr ),
|
||||
.be_o ( ),
|
||||
.data_o ( ),
|
||||
.data_i ( rom_rdata )
|
||||
);
|
||||
|
||||
bootrom i_bootrom (
|
||||
.clk_i ( clk_i ),
|
||||
.req_i ( rom_req ),
|
||||
.addr_i ( rom_addr ),
|
||||
.rdata_o ( rom_rdata )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// Memory
|
||||
// ---------------
|
||||
logic req;
|
||||
logic we;
|
||||
logic [AXI_ADDRESS_WIDTH-1:0] addr;
|
||||
logic [AXI_DATA_WIDTH/8-1:0] be;
|
||||
logic [AXI_DATA_WIDTH-1:0] wdata;
|
||||
logic [AXI_DATA_WIDTH-1:0] rdata;
|
||||
logic [AXI_DATA_WIDTH-1:0] bit_en;
|
||||
|
||||
// convert byte enable to bit enable
|
||||
for (genvar i = 0; i < AXI_DATA_WIDTH/8; i++) begin
|
||||
assign bit_en[i*8 +: 8] = {8{be[i]}};
|
||||
end
|
||||
|
||||
axi2mem #(
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
|
||||
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
|
||||
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
|
||||
) i_axi2mem (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.slave ( master[0] ),
|
||||
.req_o ( req ),
|
||||
.we_o ( we ),
|
||||
.addr_o ( addr ),
|
||||
.be_o ( be ),
|
||||
.data_o ( wdata ),
|
||||
.data_i ( rdata )
|
||||
);
|
||||
|
||||
sram #(
|
||||
.DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.NUM_WORDS ( NUM_WORDS )
|
||||
) i_sram (
|
||||
.clk_i ( clk_i ),
|
||||
.req_i ( req ),
|
||||
.we_i ( we ),
|
||||
.addr_i ( addr[$clog2(NUM_WORDS)-1+$clog2(AXI_DATA_WIDTH/8):$clog2(AXI_DATA_WIDTH/8)] ),
|
||||
.wdata_i ( wdata ),
|
||||
.be_i ( bit_en ),
|
||||
.rdata_o ( rdata )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// AXI Xbar
|
||||
// ---------------
|
||||
axi_node_intf_wrap #(
|
||||
// three ports from Ariane (instruction, data and bypass)
|
||||
.NB_SLAVE ( NB_SLAVE ),
|
||||
.NB_MASTER ( NB_MASTER ), // debug unit, memory unit
|
||||
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
|
||||
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
|
||||
) i_axi_xbar (
|
||||
.clk ( clk_i ),
|
||||
.rst_n ( ndmreset_n ),
|
||||
.test_en_i ( test_en ),
|
||||
.slave ( slave ),
|
||||
.master ( master ),
|
||||
.start_addr_i ( {64'h0, 64'h10000, CACHE_START_ADDR} ),
|
||||
.end_addr_i ( {64'hFFF, 64'h1FFFF, CACHE_START_ADDR + 2**24} )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// Core
|
||||
// ---------------
|
||||
ariane #(
|
||||
.CACHE_START_ADDR ( CACHE_START_ADDR ),
|
||||
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
|
||||
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
|
||||
) i_ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.test_en_i ( test_en ),
|
||||
.boot_addr_i ( 64'h10000 ), // start fetching from ROM
|
||||
.core_id_i ( '0 ),
|
||||
.cluster_id_i ( '0 ),
|
||||
.irq_i ( '0 ),
|
||||
.ipi_i ( '0 ),
|
||||
.time_irq_i ( '0 ),
|
||||
.debug_req_i ( debug_req ),
|
||||
.data_if ( slave[2] ),
|
||||
.bypass_if ( slave[1] ),
|
||||
.instr_if ( slave[0] )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
81
tb/common/SimDTM.sv
Normal file
81
tb/common/SimDTM.sv
Normal file
|
@ -0,0 +1,81 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
//VCS coverage exclude_file
|
||||
|
||||
import "DPI-C" function int debug_tick
|
||||
(
|
||||
output bit debug_req_valid,
|
||||
input bit debug_req_ready,
|
||||
output int debug_req_bits_addr,
|
||||
output int debug_req_bits_op,
|
||||
output int debug_req_bits_data,
|
||||
|
||||
input bit debug_resp_valid,
|
||||
output bit debug_resp_ready,
|
||||
input int debug_resp_bits_resp,
|
||||
input int debug_resp_bits_data
|
||||
);
|
||||
|
||||
module SimDTM(
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
output debug_req_valid,
|
||||
input debug_req_ready,
|
||||
output [ 6:0] debug_req_bits_addr,
|
||||
output [ 1:0] debug_req_bits_op,
|
||||
output [31:0] debug_req_bits_data,
|
||||
|
||||
input debug_resp_valid,
|
||||
output debug_resp_ready,
|
||||
input [ 1:0] debug_resp_bits_resp,
|
||||
input [31:0] debug_resp_bits_data,
|
||||
|
||||
output [31:0] exit
|
||||
);
|
||||
|
||||
bit r_reset;
|
||||
|
||||
wire #0.1 __debug_req_ready = debug_req_ready;
|
||||
wire #0.1 __debug_resp_valid = debug_resp_valid;
|
||||
wire [31:0] #0.1 __debug_resp_bits_resp = {30'b0, debug_resp_bits_resp};
|
||||
wire [31:0] #0.1 __debug_resp_bits_data = debug_resp_bits_data;
|
||||
|
||||
bit __debug_req_valid;
|
||||
int __debug_req_bits_addr;
|
||||
int __debug_req_bits_op;
|
||||
int __debug_req_bits_data;
|
||||
bit __debug_resp_ready;
|
||||
int __exit;
|
||||
|
||||
assign #0.1 debug_req_valid = __debug_req_valid;
|
||||
assign #0.1 debug_req_bits_addr = __debug_req_bits_addr[6:0];
|
||||
assign #0.1 debug_req_bits_op = __debug_req_bits_op[1:0];
|
||||
assign #0.1 debug_req_bits_data = __debug_req_bits_data[31:0];
|
||||
assign #0.1 debug_resp_ready = __debug_resp_ready;
|
||||
assign #0.1 exit = __exit;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
r_reset <= reset;
|
||||
if (reset || r_reset)
|
||||
begin
|
||||
__debug_req_valid = 0;
|
||||
__debug_resp_ready = 0;
|
||||
__exit = 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
__exit = debug_tick(
|
||||
__debug_req_valid,
|
||||
__debug_req_ready,
|
||||
__debug_req_bits_addr,
|
||||
__debug_req_bits_op,
|
||||
__debug_req_bits_data,
|
||||
__debug_resp_valid,
|
||||
__debug_resp_ready,
|
||||
__debug_resp_bits_resp,
|
||||
__debug_resp_bits_data
|
||||
);
|
||||
end
|
||||
end
|
||||
endmodule
|
83
tb/common/SimJTAG.sv
Normal file
83
tb/common/SimJTAG.sv
Normal file
|
@ -0,0 +1,83 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
//VCS coverage exclude_file
|
||||
import "DPI-C" function int jtag_tick
|
||||
(
|
||||
output bit jtag_TCK,
|
||||
output bit jtag_TMS,
|
||||
output bit jtag_TDI,
|
||||
output bit jtag_TRSTn,
|
||||
|
||||
input bit jtag_TDO
|
||||
);
|
||||
|
||||
module SimJTAG #(
|
||||
parameter TICK_DELAY = 50
|
||||
)(
|
||||
|
||||
input clock,
|
||||
input reset,
|
||||
|
||||
input enable,
|
||||
input init_done,
|
||||
|
||||
output jtag_TCK,
|
||||
output jtag_TMS,
|
||||
output jtag_TDI,
|
||||
output jtag_TRSTn,
|
||||
|
||||
input jtag_TDO_data,
|
||||
input jtag_TDO_driven,
|
||||
|
||||
output [31:0] exit
|
||||
);
|
||||
|
||||
reg [31:0] tickCounterReg;
|
||||
wire [31:0] tickCounterNxt;
|
||||
|
||||
assign tickCounterNxt = (tickCounterReg == 0) ? TICK_DELAY : (tickCounterReg - 1);
|
||||
|
||||
bit r_reset;
|
||||
|
||||
wire [31:0] random_bits = $random;
|
||||
|
||||
wire #0.1 __jtag_TDO = jtag_TDO_driven ?
|
||||
jtag_TDO_data : random_bits[0];
|
||||
|
||||
bit __jtag_TCK;
|
||||
bit __jtag_TMS;
|
||||
bit __jtag_TDI;
|
||||
bit __jtag_TRSTn;
|
||||
int __exit;
|
||||
|
||||
reg init_done_sticky;
|
||||
|
||||
assign #0.1 jtag_TCK = __jtag_TCK;
|
||||
assign #0.1 jtag_TMS = __jtag_TMS;
|
||||
assign #0.1 jtag_TDI = __jtag_TDI;
|
||||
assign #0.1 jtag_TRSTn = __jtag_TRSTn;
|
||||
|
||||
assign #0.1 exit = __exit;
|
||||
|
||||
always @(posedge clock) begin
|
||||
r_reset <= reset;
|
||||
if (reset || r_reset) begin
|
||||
__exit = 0;
|
||||
tickCounterReg <= TICK_DELAY;
|
||||
init_done_sticky <= 1'b0;
|
||||
end else begin
|
||||
init_done_sticky <= init_done | init_done_sticky;
|
||||
if (enable && init_done_sticky) begin
|
||||
tickCounterReg <= tickCounterNxt;
|
||||
if (tickCounterReg == 0) begin
|
||||
__exit = jtag_tick(
|
||||
__jtag_TCK,
|
||||
__jtag_TMS,
|
||||
__jtag_TDI,
|
||||
__jtag_TRSTn,
|
||||
__jtag_TDO);
|
||||
end
|
||||
end // if (enable && init_done_sticky)
|
||||
end // else: !if(reset || r_reset)
|
||||
end // always @ (posedge clock)
|
||||
|
||||
endmodule
|
77
tb/common/core_mem.sv
Executable file
77
tb/common/core_mem.sv
Executable file
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2018 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: Florian Zaruba, ETH Zurich
|
||||
// Date: 23.05.2017
|
||||
// Description: Load Store Unit, handles address calculation and memory interface signals
|
||||
|
||||
module core_mem #(
|
||||
parameter logic [63:0] DRAM_BASE = 64'h80000000
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
// Data memory/cache
|
||||
input logic [63:0] data_if_address_i,
|
||||
input logic data_if_data_req_i,
|
||||
input logic [7:0] data_if_data_be_i,
|
||||
output logic data_if_data_rvalid_o,
|
||||
output logic [63:0] data_if_data_rdata_o,
|
||||
input logic [63:0] data_if_data_wdata_i,
|
||||
input logic data_if_data_we_i
|
||||
);
|
||||
// we always grant the access
|
||||
localparam ADDRESS_WIDTH = 24;
|
||||
|
||||
logic [63:0] fetch_data_ram, fetch_data_rom;
|
||||
|
||||
logic [63:0] data_address_q;
|
||||
logic [63:0] data_ram, data_rom;
|
||||
|
||||
// look at the address of the previous cycle to determine what to return
|
||||
assign data_if_data_rdata_o = (data_address_q >= DRAM_BASE) ? data_ram : data_rom;
|
||||
|
||||
dp_ram #(
|
||||
.ADDR_WIDTH ( ADDRESS_WIDTH ),
|
||||
.DATA_WIDTH ( 64 )
|
||||
) ram_i (
|
||||
.clk ( clk_i ),
|
||||
.en_a_i ( 1'b0 ),
|
||||
.addr_a_i ( ),
|
||||
.wdata_a_i ( ), // not connected
|
||||
.rdata_a_o ( ),
|
||||
.we_a_i ( 1'b0 ), // r/o interface
|
||||
.be_a_i ( ),
|
||||
// data RAM
|
||||
.en_b_i ( data_if_data_req_i ),
|
||||
.addr_b_i ( data_if_address_i[ADDRESS_WIDTH-1+3:3] ),
|
||||
.wdata_b_i ( data_if_data_wdata_i ),
|
||||
.rdata_b_o ( data_ram ),
|
||||
.we_b_i ( ((data_if_address_i >= DRAM_BASE) ? data_if_data_we_i : 1'b0) ),
|
||||
.be_b_i ( data_if_data_be_i )
|
||||
);
|
||||
|
||||
boot_rom data_boot_rom_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.address_i ( data_address_q ),
|
||||
.data_o ( data_rom )
|
||||
);
|
||||
|
||||
// Output the rvalid one cycle later, together with the rdata
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
|
||||
if (~rst_ni) begin
|
||||
data_if_data_rvalid_o <= 1'b0;
|
||||
data_address_q <= '0;
|
||||
end else begin
|
||||
data_if_data_rvalid_o <= data_if_data_req_i;
|
||||
data_address_q <= data_if_address_i;
|
||||
end
|
||||
end
|
||||
endmodule
|
60
tb/common/dp_ram.sv
Executable file
60
tb/common/dp_ram.sv
Executable file
|
@ -0,0 +1,60 @@
|
|||
// Copyright 2015-2018 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.
|
||||
|
||||
module dp_ram
|
||||
#(
|
||||
parameter int ADDR_WIDTH = 8,
|
||||
parameter int DATA_WIDTH = 64
|
||||
)(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
|
||||
input logic en_a_i,
|
||||
input logic [ADDR_WIDTH-1:0] addr_a_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_a_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_a_o,
|
||||
input logic we_a_i,
|
||||
input logic [DATA_WIDTH/8-1:0] be_a_i,
|
||||
|
||||
input logic en_b_i,
|
||||
input logic [ADDR_WIDTH-1:0] addr_b_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_b_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_b_o,
|
||||
input logic we_b_i,
|
||||
input logic [DATA_WIDTH/8-1:0] be_b_i
|
||||
);
|
||||
|
||||
localparam words = 2**ADDR_WIDTH;
|
||||
|
||||
logic [DATA_WIDTH/8-1:0][7:0] mem [words-1:0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
if (en_a_i && we_a_i) begin
|
||||
for (int i = 0; i < DATA_WIDTH/8; i++) begin
|
||||
if (be_a_i[i])
|
||||
mem[addr_a_i][i] <= wdata_a_i[i*8 +: 8];
|
||||
end
|
||||
end
|
||||
|
||||
rdata_a_o <= mem[addr_a_i];
|
||||
|
||||
if (en_b_i && we_b_i) begin
|
||||
for (int i = 0; i < DATA_WIDTH/8; i++) begin
|
||||
if (be_b_i[i])
|
||||
mem[addr_b_i][i] <= wdata_b_i[i*8 +: 8];
|
||||
end
|
||||
end
|
||||
|
||||
rdata_b_o <= mem[addr_b_i];
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
33
tb/common/pulp_sync.sv
Normal file
33
tb/common/pulp_sync.sv
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module pulp_sync #(
|
||||
parameter STAGES = 2
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic serial_i,
|
||||
output logic serial_o
|
||||
);
|
||||
|
||||
logic [STAGES-1:0] r_reg;
|
||||
|
||||
always_ff @(posedge clk_i, negedge rstn_i) begin
|
||||
if (!rstn_i)
|
||||
r_reg <= 'h0;
|
||||
else
|
||||
r_reg <= {r_reg[STAGES-2:0], serial_i};
|
||||
end
|
||||
|
||||
assign serial_o = r_reg[STAGES-1];
|
||||
|
||||
endmodule
|
67
tb/common/string_buffer.svh
Executable file
67
tb/common/string_buffer.svh
Executable file
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2018 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: Florian Zaruba, ETH Zurich
|
||||
// Date: 13.07.2017
|
||||
// Description: Buffers a string until a new line appears.
|
||||
|
||||
class string_buffer extends uvm_component;
|
||||
|
||||
/*-------------------------------------------------------------------------------
|
||||
-- Interface, port, fields
|
||||
-------------------------------------------------------------------------------*/
|
||||
// string buffer
|
||||
byte buffer [$];
|
||||
// name to display in console
|
||||
string logger_name;
|
||||
/*-------------------------------------------------------------------------------
|
||||
-- UVM Factory register
|
||||
-------------------------------------------------------------------------------*/
|
||||
// Provide implementations of virtual methods such as get_type_name and create
|
||||
`uvm_component_utils(string_buffer)
|
||||
|
||||
/*-------------------------------------------------------------------------------
|
||||
-- Functions
|
||||
-------------------------------------------------------------------------------*/
|
||||
// Constructor
|
||||
function new(string name = "string_buffer", uvm_component parent=null);
|
||||
super.new(name, parent);
|
||||
// default logger name
|
||||
logger_name = "String Buffer";
|
||||
endfunction : new
|
||||
|
||||
function void set_logger(string logger_name);
|
||||
this.logger_name = logger_name;
|
||||
endfunction : set_logger
|
||||
|
||||
function void flush();
|
||||
string s;
|
||||
// dump the buffer out the whole buffer
|
||||
foreach (buffer[i]) begin
|
||||
s = $sformatf("%s%c",s, buffer[i]);
|
||||
end
|
||||
|
||||
uvm_report_info(logger_name, s, UVM_LOW);
|
||||
|
||||
// clear buffer afterwards
|
||||
buffer = {};
|
||||
endfunction : flush
|
||||
|
||||
// put a char to the buffer
|
||||
function void append(byte ch);
|
||||
|
||||
// wait for the new line
|
||||
if (ch == 8'hA)
|
||||
this.flush();
|
||||
else
|
||||
buffer.push_back(ch);
|
||||
|
||||
endfunction : append
|
||||
endclass : string_buffer
|
114
tb/common/uart.sv
Normal file
114
tb/common/uart.sv
Normal file
|
@ -0,0 +1,114 @@
|
|||
// Copyright 2018 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: Unknown
|
||||
// Date: Unknown
|
||||
// Description: This module takes data over UART and prints them to the console
|
||||
// A string is printed to the console as soon as a '\n' character is found
|
||||
|
||||
interface uart_bus
|
||||
#(
|
||||
parameter BAUD_RATE = 115200,
|
||||
parameter PARITY_EN = 0
|
||||
)
|
||||
(
|
||||
input logic rx,
|
||||
output logic tx,
|
||||
|
||||
input logic rx_en
|
||||
);
|
||||
|
||||
localparam BIT_PERIOD = (1000000000/BAUD_RATE*1000);
|
||||
|
||||
logic [7:0] character;
|
||||
logic [256*8-1:0] stringa;
|
||||
logic parity;
|
||||
integer charnum;
|
||||
integer file;
|
||||
|
||||
initial
|
||||
begin
|
||||
tx = 1'bZ;
|
||||
file = $fopen("stdout/uart", "w");
|
||||
end
|
||||
|
||||
always
|
||||
begin
|
||||
if (rx_en)
|
||||
begin
|
||||
@(negedge rx);
|
||||
#(BIT_PERIOD/2) ;
|
||||
for (int i=0;i<=7;i++)
|
||||
begin
|
||||
#BIT_PERIOD character[i] = rx;
|
||||
end
|
||||
|
||||
if(PARITY_EN == 1)
|
||||
begin
|
||||
// check parity
|
||||
#BIT_PERIOD parity = rx;
|
||||
|
||||
for (int i=7;i>=0;i--)
|
||||
begin
|
||||
parity = character[i] ^ parity;
|
||||
end
|
||||
|
||||
if(parity == 1'b1)
|
||||
begin
|
||||
$display("Parity error detected");
|
||||
end
|
||||
end
|
||||
|
||||
// STOP BIT
|
||||
#BIT_PERIOD;
|
||||
|
||||
$fwrite(file, "%c", character);
|
||||
stringa[(255-charnum)*8 +: 8] = character;
|
||||
if (character == 8'h0A || charnum == 254) // line feed or max. chars reached
|
||||
begin
|
||||
if (character == 8'h0A)
|
||||
stringa[(255-charnum)*8 +: 8] = 8'h0; // null terminate string, replace line feed
|
||||
else
|
||||
stringa[(255-charnum-1)*8 +: 8] = 8'h0; // null terminate string
|
||||
|
||||
$write("RX string: %s\n",stringa);
|
||||
charnum = 0;
|
||||
stringa = "";
|
||||
end
|
||||
else
|
||||
begin
|
||||
charnum = charnum + 1;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
charnum = 0;
|
||||
stringa = "";
|
||||
#10;
|
||||
end
|
||||
end
|
||||
|
||||
task send_char(input logic [7:0] c);
|
||||
int i;
|
||||
|
||||
// start bit
|
||||
tx = 1'b0;
|
||||
|
||||
for (i = 0; i < 8; i++) begin
|
||||
#(BIT_PERIOD);
|
||||
tx = c[i];
|
||||
end
|
||||
|
||||
// stop bit
|
||||
#(BIT_PERIOD);
|
||||
tx = 1'b1;
|
||||
#(BIT_PERIOD);
|
||||
endtask
|
||||
endinterface
|
59
tb/dpi/SimDTM.cc
Normal file
59
tb/dpi/SimDTM.cc
Normal file
|
@ -0,0 +1,59 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
|
||||
#include <fesvr/dtm.h>
|
||||
#include <vpi_user.h>
|
||||
#include <svdpi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
dtm_t* dtm;
|
||||
|
||||
extern "C" int debug_tick
|
||||
(
|
||||
unsigned char* debug_req_valid,
|
||||
unsigned char debug_req_ready,
|
||||
int* debug_req_bits_addr,
|
||||
int* debug_req_bits_op,
|
||||
int* debug_req_bits_data,
|
||||
unsigned char debug_resp_valid,
|
||||
unsigned char* debug_resp_ready,
|
||||
int debug_resp_bits_resp,
|
||||
int debug_resp_bits_data
|
||||
)
|
||||
{
|
||||
if (!dtm) {
|
||||
s_vpi_vlog_info info;
|
||||
if (!vpi_get_vlog_info(&info))
|
||||
abort();
|
||||
// sanitize arguments
|
||||
for (int i = 0; i < info.argc; i++) {
|
||||
// remove any two double pluses at the beginning (those are target arguments)
|
||||
if (info.argv[i][0] == '+' && info.argv[i][1] == '+' && strlen(info.argv[i]) > 3) {
|
||||
for (int j = 0; j < strlen(info.argv[i]) - 1; j++) {
|
||||
info.argv[i][j] = info.argv[i][j + 2];
|
||||
}
|
||||
}
|
||||
// printf("Argument %d: %s\n", i, info.argv[i]);
|
||||
}
|
||||
|
||||
dtm = new dtm_t(info.argc, info.argv);
|
||||
}
|
||||
|
||||
dtm_t::resp resp_bits;
|
||||
resp_bits.resp = debug_resp_bits_resp;
|
||||
resp_bits.data = debug_resp_bits_data;
|
||||
|
||||
dtm->tick
|
||||
(
|
||||
debug_req_ready,
|
||||
debug_resp_valid,
|
||||
resp_bits
|
||||
);
|
||||
|
||||
*debug_resp_ready = dtm->resp_ready();
|
||||
*debug_req_valid = dtm->req_valid();
|
||||
*debug_req_bits_addr = dtm->req_bits().addr;
|
||||
*debug_req_bits_op = dtm->req_bits().op;
|
||||
*debug_req_bits_data = dtm->req_bits().data;
|
||||
|
||||
return dtm->done() ? (dtm->exit_code() << 1 | 1) : 0;
|
||||
}
|
25
tb/dpi/SimJTAG.cc
Normal file
25
tb/dpi/SimJTAG.cc
Normal file
|
@ -0,0 +1,25 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
|
||||
#include <cstdlib>
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
remote_bitbang_t* jtag;
|
||||
extern "C" int jtag_tick
|
||||
(
|
||||
unsigned char * jtag_TCK,
|
||||
unsigned char * jtag_TMS,
|
||||
unsigned char * jtag_TDI,
|
||||
unsigned char * jtag_TRSTn,
|
||||
unsigned char jtag_TDO
|
||||
)
|
||||
{
|
||||
if (!jtag) {
|
||||
// TODO: Pass in real port number
|
||||
jtag = new remote_bitbang_t(0);
|
||||
}
|
||||
|
||||
jtag->tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, jtag_TDO);
|
||||
|
||||
return jtag->done() ? (jtag->exit_code() << 1 | 1) : 0;
|
||||
|
||||
}
|
202
tb/dpi/remote_bitbang.cc
Normal file
202
tb/dpi/remote_bitbang.cc
Normal file
|
@ -0,0 +1,202 @@
|
|||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
/////////// remote_bitbang_t
|
||||
|
||||
remote_bitbang_t::remote_bitbang_t(uint16_t port) :
|
||||
socket_fd(0),
|
||||
client_fd(0),
|
||||
recv_start(0),
|
||||
recv_end(0),
|
||||
err(0)
|
||||
{
|
||||
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socket_fd == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
fcntl(socket_fd, F_SETFL, O_NONBLOCK);
|
||||
int reuseaddr = 1;
|
||||
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
|
||||
sizeof(int)) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (::bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (listen(socket_fd, 1) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) {
|
||||
fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
tck = 1;
|
||||
tms = 1;
|
||||
tdi = 1;
|
||||
trstn = 1;
|
||||
quit = 0;
|
||||
|
||||
fprintf(stderr, "This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.\n");
|
||||
fprintf(stderr, "Listening on port %d\n",
|
||||
ntohs(addr.sin_port));
|
||||
}
|
||||
|
||||
void remote_bitbang_t::accept()
|
||||
{
|
||||
|
||||
fprintf(stderr,"Attempting to accept client socket\n");
|
||||
int again = 1;
|
||||
while (again != 0) {
|
||||
client_fd = ::accept(socket_fd, NULL, NULL);
|
||||
if (client_fd == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
// No client waiting to connect right now.
|
||||
} else {
|
||||
fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
|
||||
errno);
|
||||
again = 0;
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
fcntl(client_fd, F_SETFL, O_NONBLOCK);
|
||||
fprintf(stderr, "Accepted successfully.");
|
||||
again = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remote_bitbang_t::tick(
|
||||
unsigned char * jtag_tck,
|
||||
unsigned char * jtag_tms,
|
||||
unsigned char * jtag_tdi,
|
||||
unsigned char * jtag_trstn,
|
||||
unsigned char jtag_tdo
|
||||
)
|
||||
{
|
||||
if (client_fd > 0) {
|
||||
tdo = jtag_tdo;
|
||||
execute_command();
|
||||
} else {
|
||||
this->accept();
|
||||
}
|
||||
|
||||
* jtag_tck = tck;
|
||||
* jtag_tms = tms;
|
||||
* jtag_tdi = tdi;
|
||||
* jtag_trstn = trstn;
|
||||
|
||||
}
|
||||
|
||||
void remote_bitbang_t::reset(){
|
||||
//trstn = 0;
|
||||
}
|
||||
|
||||
void remote_bitbang_t::set_pins(char _tck, char _tms, char _tdi){
|
||||
tck = _tck;
|
||||
tms = _tms;
|
||||
tdi = _tdi;
|
||||
}
|
||||
|
||||
void remote_bitbang_t::execute_command()
|
||||
{
|
||||
char command;
|
||||
int again = 1;
|
||||
while (again) {
|
||||
ssize_t num_read = read(client_fd, &command, sizeof(command));
|
||||
if (num_read == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
// We'll try again the next call.
|
||||
//fprintf(stderr, "Received no command. Will try again on the next call\n");
|
||||
} else {
|
||||
fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
again = 0;
|
||||
abort();
|
||||
}
|
||||
} else if (num_read == 0) {
|
||||
fprintf(stderr, "No Command Received.\n");
|
||||
again = 1;
|
||||
} else {
|
||||
again = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(stderr, "Received a command %c\n", command);
|
||||
|
||||
int dosend = 0;
|
||||
|
||||
char tosend = '?';
|
||||
|
||||
switch (command) {
|
||||
case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
|
||||
case 'b': /* fprintf(stderr, "_______\n"); */ break;
|
||||
case 'r': reset(); break; // This is wrong. 'r' has other bits that indicated TRST and SRST.
|
||||
case '0': set_pins(0, 0, 0); break;
|
||||
case '1': set_pins(0, 0, 1); break;
|
||||
case '2': set_pins(0, 1, 0); break;
|
||||
case '3': set_pins(0, 1, 1); break;
|
||||
case '4': set_pins(1, 0, 0); break;
|
||||
case '5': set_pins(1, 0, 1); break;
|
||||
case '6': set_pins(1, 1, 0); break;
|
||||
case '7': set_pins(1, 1, 1); break;
|
||||
case 'R': dosend = 1; tosend = tdo ? '1' : '0'; break;
|
||||
case 'Q': quit = 1; break;
|
||||
default:
|
||||
fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
|
||||
command);
|
||||
}
|
||||
|
||||
if (dosend){
|
||||
while (1) {
|
||||
ssize_t bytes = write(client_fd, &tosend, sizeof(tosend));
|
||||
if (bytes == -1) {
|
||||
fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
if (bytes > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quit) {
|
||||
// The remote disconnected.
|
||||
fprintf(stderr, "Remote end disconnected\n");
|
||||
close(client_fd);
|
||||
client_fd = 0;
|
||||
}
|
||||
}
|
59
tb/dpi/remote_bitbang.h
Normal file
59
tb/dpi/remote_bitbang.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
#ifndef REMOTE_BITBANG_H
|
||||
#define REMOTE_BITBANG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
class remote_bitbang_t
|
||||
{
|
||||
public:
|
||||
// Create a new server, listening for connections from localhost on the given
|
||||
// port.
|
||||
remote_bitbang_t(uint16_t port);
|
||||
|
||||
// Do a bit of work.
|
||||
void tick(unsigned char * jtag_tck,
|
||||
unsigned char * jtag_tms,
|
||||
unsigned char * jtag_tdi,
|
||||
unsigned char * jtag_trstn,
|
||||
unsigned char jtag_tdo);
|
||||
|
||||
unsigned char done() {return quit;}
|
||||
|
||||
int exit_code() {return err;}
|
||||
|
||||
private:
|
||||
|
||||
int err;
|
||||
|
||||
unsigned char tck;
|
||||
unsigned char tms;
|
||||
unsigned char tdi;
|
||||
unsigned char trstn;
|
||||
unsigned char tdo;
|
||||
unsigned char quit;
|
||||
|
||||
int socket_fd;
|
||||
int client_fd;
|
||||
|
||||
static const ssize_t buf_size = 64 * 1024;
|
||||
char recv_buf[buf_size];
|
||||
ssize_t recv_start, recv_end;
|
||||
|
||||
// Check for a client connecting, and accept if there is one.
|
||||
void accept();
|
||||
// Execute any commands the client has for us.
|
||||
// But we only execute 1 because we need time for the
|
||||
// simulation to run.
|
||||
void execute_command();
|
||||
|
||||
// Reset. Currently does nothing.
|
||||
void reset();
|
||||
|
||||
void set_pins(char _tck, char _tms, char _tdi);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
29
tb/dpi/verilator.h
Normal file
29
tb/dpi/verilator.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef _ROCKET_VERILATOR_H
|
||||
#define _ROCKET_VERILATOR_H
|
||||
|
||||
#include "verilated_vcd_c.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern bool verbose;
|
||||
extern bool done_reset;
|
||||
|
||||
class VerilatedVcdFILE : public VerilatedVcdFile {
|
||||
public:
|
||||
VerilatedVcdFILE(FILE* file) : file(file) {}
|
||||
~VerilatedVcdFILE() {}
|
||||
bool open(const std::string& name) override {
|
||||
// file should already be open
|
||||
return file != NULL;
|
||||
}
|
||||
void close() override {
|
||||
// file should be closed elsewhere
|
||||
}
|
||||
ssize_t write(const char* bufp, ssize_t len) override {
|
||||
return fwrite(bufp, 1, len, file);
|
||||
}
|
||||
private:
|
||||
FILE* file;
|
||||
};
|
||||
|
||||
#endif
|
81
tb/wave/wave_core.do
Normal file
81
tb/wave/wave_core.do
Normal file
|
@ -0,0 +1,81 @@
|
|||
add wave -noupdate -group core /ariane_tb/dut/i_ariane/*
|
||||
|
||||
add wave -noupdate -group frontend /ariane_tb/dut/i_ariane/i_frontend/*
|
||||
add wave -noupdate -group frontend -group icache /ariane_tb/dut/i_ariane/i_frontend/i_icache/*
|
||||
add wave -noupdate -group frontend -group ras /ariane_tb/dut/i_ariane/i_frontend/i_ras/*
|
||||
add wave -noupdate -group frontend -group btb /ariane_tb/dut/i_ariane/i_frontend/i_btb/*
|
||||
add wave -noupdate -group frontend -group bht /ariane_tb/dut/i_ariane/i_frontend/i_bht/*
|
||||
# add wave -noupdate -group frontend -group instr_scan /ariane_tb/dut/i_ariane/i_frontend/*i_instr_scan/*
|
||||
add wave -noupdate -group frontend -group fetch_fifo /ariane_tb/dut/i_ariane/i_frontend/i_fetch_fifo/*
|
||||
|
||||
add wave -noupdate -group id_stage -group decoder /ariane_tb/dut/i_ariane/id_stage_i/decoder_i/*
|
||||
add wave -noupdate -group id_stage -group compressed_decoder /ariane_tb/dut/i_ariane/id_stage_i/compressed_decoder_i/*
|
||||
add wave -noupdate -group id_stage -group instr_realigner /ariane_tb/dut/i_ariane/id_stage_i/instr_realigner_i/*
|
||||
add wave -noupdate -group id_stage /ariane_tb/dut/i_ariane/id_stage_i/*
|
||||
|
||||
add wave -noupdate -group issue_stage -group scoreboard /ariane_tb/dut/i_ariane/issue_stage_i/i_scoreboard/*
|
||||
add wave -noupdate -group issue_stage -group issue_read_operands /ariane_tb/dut/i_ariane/issue_stage_i/i_issue_read_operands/*
|
||||
add wave -noupdate -group issue_stage -group rename /ariane_tb/dut/i_ariane/issue_stage_i/i_re_name/*
|
||||
add wave -noupdate -group issue_stage /ariane_tb/dut/i_ariane/issue_stage_i/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group alu /ariane_tb/dut/i_ariane/ex_stage_i/alu_i/*
|
||||
add wave -noupdate -group ex_stage -group mult /ariane_tb/dut/i_ariane/ex_stage_i/i_mult/*
|
||||
add wave -noupdate -group ex_stage -group mult -group mul /ariane_tb/dut/i_ariane/ex_stage_i/i_mult/i_mul/*
|
||||
add wave -noupdate -group ex_stage -group mult -group div /ariane_tb/dut/i_ariane/ex_stage_i/i_mult/i_div/*
|
||||
add wave -noupdate -group ex_stage -group mult -group ff1 /ariane_tb/dut/i_ariane/ex_stage_i/i_mult/i_ff1/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group lsu /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group lsu_bypass /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/lsu_bypass_i/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group mmu /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_mmu/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group mmu -group itlb /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_mmu/i_itlb/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group mmu -group dtlb /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_mmu/i_dtlb/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group mmu -group ptw /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_mmu/i_ptw/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group lsu -group store_unit /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_store_unit/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group store_unit -group store_buffer /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_store_unit/store_buffer_i/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group lsu -group load_unit /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_load_unit/*
|
||||
add wave -noupdate -group ex_stage -group lsu -group lsu_arbiter /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_lsu_arbiter/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group branch_unit /ariane_tb/dut/i_ariane/ex_stage_i/branch_unit_i/*
|
||||
|
||||
add wave -noupdate -group ex_stage -group csr_buffer /ariane_tb/dut/i_ariane/ex_stage_i/csr_buffer_i/*
|
||||
add wave -noupdate -group ex_stage /ariane_tb/dut/i_ariane/ex_stage_i/*
|
||||
|
||||
add wave -noupdate -group commit_stage /ariane_tb/dut/i_ariane/commit_stage_i/*
|
||||
|
||||
add wave -noupdate -group csr_file /ariane_tb/dut/i_ariane/csr_regfile_i/*
|
||||
|
||||
add wave -noupdate -group controller /ariane_tb/dut/i_ariane/controller_i/*
|
||||
|
||||
add wave -noupdate -group nbdcache /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/*
|
||||
add wave -noupdate -group nbdcache -group miss_handler /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_miss_handler/*
|
||||
|
||||
add wave -noupdate -group nbdcache -group bypass_arbiter /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_miss_handler/i_bypass_arbiter/*
|
||||
add wave -noupdate -group nbdcache -group bypass_axi /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_miss_handler/i_bypass_axi_adapter/*
|
||||
|
||||
add wave -noupdate -group nbdcache -group miss_axi /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_miss_handler/i_miss_axi_adapter/*
|
||||
add wave -noupdate -group nbdcache -group lfsr /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_miss_handler/i_lfsr/*
|
||||
|
||||
add wave -noupdate -group nbdcache -group dirty_ram /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/dirty_sram/*
|
||||
add wave -noupdate -group nbdcache -group tag_cmp /ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/i_tag_cmp/*
|
||||
|
||||
add wave -noupdate -group nbdcache -group ptw {/ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/master_ports[0]/i_cache_ctrl/*}
|
||||
add wave -noupdate -group nbdcache -group load {/ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/master_ports[1]/i_cache_ctrl/*}
|
||||
add wave -noupdate -group nbdcache -group store {/ariane_tb/dut/i_ariane/ex_stage_i/lsu_i/i_nbdcache/master_ports[2]/i_cache_ctrl/*}
|
||||
|
||||
add wave -noupdate -group perf_counters {/ariane_tb/dut/i_ariane/i_perf_counters/*}
|
||||
|
||||
add wave -noupdate -group dm_top /ariane_tb/dut/i_dm_top/*
|
||||
add wave -noupdate -group dm_top -group dm_csrs /ariane_tb/dut/i_dm_top/i_dm_csrs/*
|
||||
add wave -noupdate -group dm_top -group dm_mem /ariane_tb/dut/i_dm_top/i_dm_mem/*
|
||||
|
||||
add wave -noupdate -group bootrom /ariane_tb/dut/i_bootrom/*
|
||||
|
||||
add wave -noupdate -group tracer_if /ariane_tb/dut/i_ariane/instr_tracer_i/tracer_if/*
|
||||
|
||||
add wave -group SimJTAG /ariane_tb/dut/i_SimJTAG/*
|
||||
|
||||
add wave -group dmi_jtag /ariane_tb/dut/i_dmi_jtag/*
|
||||
add wave -group dmi_jtag -group dmi_jtag_tap /ariane_tb/dut/i_dmi_jtag/i_dmi_jtag_tap/*
|
||||
add wave -group dmi_jtag -group dmi_cdc /ariane_tb/dut/i_dmi_jtag/i_dmi_cdc/*
|
Loading…
Add table
Reference in a new issue