1
0
Fork 0

Write test harness in Chisel

This is an unavoidably invasive commit, because it affects the unit tests
(which formerly exited using stop()), the test harness Verilog generator
(since it is no longer necessary), and the DRAM model (since it is no
longer connected).  However, this should substantially reduce the effort
of building test harnesses in the future, since manual or semi-automatic
Verilog writing should no longer be necessary.  Furthermore, there is now
very little duplication of effort between the Verilator and VCS test
harnesses.

This commit removes support for DRAMsim, which is a bit of an unfortunate
consequence.  The main blocker is the lack of Verilog parameterization for
BlackBox.  It would be straightforward to revive DRAMsim once support for
that feature is added to Chisel and FIRRTL.  But that might not even be
necessary, as we move towards synthesizable DRAM models and FAME-1
transformations.
This commit is contained in:
Andrew Waterman 2016-08-15 22:03:03 -07:00
parent 2d1d7266f5
commit ed827678ac
38 changed files with 483 additions and 1792 deletions

6
.gitmodules vendored
View File

@ -1,12 +1,6 @@
[submodule "dramsim2"]
path = dramsim2
url = https://github.com/dramninjasUMD/DRAMSim2.git
[submodule "riscv-tools"]
path = riscv-tools
url = https://github.com/riscv/riscv-tools.git
[submodule "chisel"]
path = chisel2
url = https://github.com/ucb-bar/chisel.git
[submodule "hardfloat"]
path = hardfloat
url = https://github.com/ucb-bar/berkeley-hardfloat.git

View File

@ -32,8 +32,8 @@ addons:
env:
matrix:
- SUITE=RocketSuite CHISEL_VERSION=3
- SUITE=GroundtestSuite CHISEL_VERSION=3
- SUITE=RocketSuite
- SUITE=GroundtestSuite
# blacklist private branches
branches:
@ -46,8 +46,8 @@ before_install:
- export CXX=g++-4.8 CC=gcc-4.8
script:
- make emulator-ndebug -C regression SUITE=$SUITE TORTURE_CONFIG=default CHISEL_VERSION=$CHISEL_VERSION
- make emulator-regression-tests -C regression SUITE=$SUITE TORTURE_CONFIG=default CHISEL_VERSION=$CHISEL_VERSION
- make emulator-ndebug -C regression SUITE=$SUITE TORTURE_CONFIG=default
- make emulator-regression-tests -C regression SUITE=$SUITE TORTURE_CONFIG=default
before_cache:
- ls -tr regression/install | tail -n+2 | sed s@^@regression/install/@ | xargs rm -rf

View File

@ -3,14 +3,11 @@ ifndef RISCV
$(error Please set environment variable RISCV. Please take a look at README)
endif
MODEL ?= Top
MODEL ?= TestHarness
PROJECT := rocketchip
CXX ?= g++
CXXFLAGS := -O1
CHISEL_VERSION ?= 3
export CHISEL_VERSION
SBT ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -jar $(base_dir)/sbt-launch.jar
SHELL := /bin/bash
@ -20,11 +17,7 @@ FIRRTL ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp $(FIRRTL_JAR) firrtl.Drive
$(FIRRTL_JAR): $(shell find $(base_dir)/firrtl/src/main/scala -iname "*.scala")
$(MAKE) -C $(base_dir)/firrtl SBT="$(SBT)" root_dir=$(base_dir)/firrtl build-scala
ifeq ($(CHISEL_VERSION),2)
CHISEL_ARGS := $(PROJECT) $(MODEL) $(CONFIG) --W0W --minimumCompatibility 3.0.0 --backend $(BACKEND) --configName $(CONFIG) --compileInitializationUnoptimized --targetDir $(generated_dir)
else
CHISEL_ARGS := --W0W --minimumCompatibility 3.0.0 --backend $(BACKEND) --configName $(CONFIG) --compileInitializationUnoptimized --targetDir $(generated_dir)
endif
CHISEL_ARGS := --targetDir $(generated_dir)
src_path = src/main/scala
default_submodules = . junctions uncore hardfloat rocket groundtest coreplex context-dependent-environments
@ -41,16 +34,6 @@ timeout_cycles = 100000000
bootrom_img = $(base_dir)/bootrom/bootrom.img
#--------------------------------------------------------------------
# DRAMSim2
#--------------------------------------------------------------------
DRAMSIM_OBJS := $(patsubst %.cpp,%.o,$(wildcard $(base_dir)/dramsim2/*.cpp))
$(DRAMSIM_OBJS): %.o: %.cpp
$(CXX) $(CXXFLAGS) -DNO_STORAGE -DNO_OUTPUT -Dmain=nomain -c -o $@ $<
$(sim_dir)/libdramsim.a: $(DRAMSIM_OBJS)
ar rcs $@ $^
#--------------------------------------------------------------------
# Build Tests
#--------------------------------------------------------------------
@ -71,7 +54,6 @@ $(consts_header): $(params_file)
echo "#ifndef __CONST_H__" > $@
echo "#define __CONST_H__" >> $@
sed -r 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@
echo "#define TBFRAG \"$(MODEL).$(CONFIG).tb.cpp\"" >> $@
echo "#endif // __CONST_H__" >> $@
params_file_debug = $(generated_dir_debug)/$(MODEL).$(CONFIG).prm
@ -80,7 +62,6 @@ $(consts_header_debug): $(params_file_debug)
echo "#ifndef __CONST_H__" > $@
echo "#define __CONST_H__" >> $@
sed -r 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/#define \1 \2/' $< >> $@
echo "#define TBFRAG \"$(MODEL).$(CONFIG).tb.cpp\"" >> $@
echo "#endif // __CONST_H__" >> $@
clean-run-output:

View File

@ -117,8 +117,8 @@ submodule.
Here's a look at all the git submodules that are currently tracked in
the rocket-chip repository:
* **chisel2**
([https://github.com/ucb-bar/chisel](https://github.com/ucb-bar/chisel)):
* **chisel3**
([https://github.com/ucb-bar/chisel3](https://github.com/ucb-bar/chisel3)):
At Berkeley, we write RTL in Chisel. For those who are not familiar
with Chisel, please go take a look at
[http://chisel.eecs.berkeley.edu](http://chisel.eecs.berkeley.edu). We
@ -129,12 +129,6 @@ and hence it was easiest to use submodule to track bleeding edge commits
to Chisel, which contained a bunch of new features and bug fixes. As
Chisel gets more stable, we will likely replace this submodule with an
external dependency.
* **chisel3**
([https://github.com/ucb-bar/chisel3](https://github.com/ucb-bar/chisel3)):
Chisel3 is a newer version of Chisel, which is based on FIRRTL. The Chisel
code in this repository is generally compatible with both Chisel2 and Chisel3.
The [chisel3/README](https://github.com/ucb-bar/chisel3/blob/master/README.md).gives
instructions on how to build your design with Chisel3 instead of Chisel2.
* **firrtl**
([https://github.com/ucb-bar/firrtl](https://github.com/ucb-bar/firrtl)):
FIRRTL (Flexible Internal Representation for RTL) is the intermediate format
@ -157,10 +151,6 @@ The rocket-chip Chisel code is highly parameterizable, and utilizes the classes
this subrepo to set and pass parameters to different levels of the design. Note that in
Chisel2, this was handled by Chisel itself, but has been moved into a seperate
library for use with Chisel3.
* **dramsim2**
([https://github.com/dramninjasUMD/DRAMSim2](https://github.com/dramninjasUMD/DRAMSim2)):
Currently, the DRAM memory system is implemented in the testbench. We
use dramsim2 to emulate DRAM timing.
* **riscv-tools**
([https://github.com/riscv/riscv-tools](https://github.com/riscv/riscv-tools)):
We tag a version of riscv-tools that works with the RTL committed in the

@ -1 +0,0 @@
Subproject commit 23b48e11852458512b706f387d60ee1542458149

View File

@ -228,18 +228,19 @@ class DefaultOuterMemorySystem(implicit p: Parameters) extends OuterMemorySystem
io.mem <> mem_ic.io.out
}
class CoreplexIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
with HasCoreplexParameters {
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams))
val bus = if (p(ExportBusPort)) Some(new ClientUncachedTileLinkIO()(innerParams).flip) else None
val mmio = if(p(ExportMMIOPort)) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams)) else None
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
val debug = new DebugBusIO()(p).flip
val extra = p(ExtraCoreplexPorts)(p)
}
abstract class Coreplex(implicit val p: Parameters) extends Module
with HasCoreplexParameters {
class CoreplexIO(implicit val p: Parameters) extends Bundle {
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams))
val bus = if (p(ExportBusPort)) Some(new ClientUncachedTileLinkIO()(innerParams).flip) else None
val mmio = if(p(ExportMMIOPort)) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams)) else None
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
val debug = new DebugBusIO()(p).flip
val extra = p(ExtraCoreplexPorts)(p)
val success: Option[Bool] = if (hasSuccessFlag) Some(Bool(OUTPUT)) else None
}
def hasSuccessFlag: Boolean = false
val io = new CoreplexIO
}
@ -276,3 +277,8 @@ class DefaultCoreplex(topParams: Parameters) extends Coreplex()(topParams) {
if (exportMMIO) { io.mmio.get <> uncore.io.mmio.get }
io.mem <> uncore.io.mem
}
class GroundTestCoreplex(topParams: Parameters) extends DefaultCoreplex(topParams) {
override def hasSuccessFlag = true
io.success.get := tileList.flatMap(_.io.elements get "success").map(_.asInstanceOf[Bool]).reduce(_&&_)
}

View File

@ -9,7 +9,6 @@ import uncore.agents._
case object ExportGroundTestStatus extends Field[Boolean]
class DirectGroundTestCoreplex(topParams: Parameters) extends Coreplex()(topParams) {
// Not using the debug
io.debug.req.ready := Bool(false)
io.debug.resp.valid := Bool(false)
@ -27,8 +26,6 @@ class DirectGroundTestCoreplex(topParams: Parameters) extends Coreplex()(topPara
require(test.io.mem.size == nBanksPerMemChannel)
require(test.io.ptw.size == 0)
when (test.io.status.finished) { stop() }
val mem_ic = Module(new TileLinkMemoryInterconnect(
nBanksPerMemChannel, nMemChannels)(outermostParams))
@ -59,4 +56,7 @@ class DirectGroundTestCoreplex(topParams: Parameters) extends Coreplex()(topPara
status.timeout.valid := (state === s_timeout)
status.timeout.bits := timeout_code
}
override def hasSuccessFlag = true
io.success.get := test.io.status.finished
}

View File

@ -15,51 +15,6 @@ import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
import scala.math.max
import ConfigUtils._
class WithGroundTest extends Config(
(pname, site, here) => pname match {
case TLKey("L1toL2") => {
val useMEI = site(NTiles) <= 1 && site(NCachedTileLinkPorts) <= 1
TileLinkParameters(
coherencePolicy = (
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
else new MESICoherence(site(L2DirectoryRepresentation))),
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1,
nCachingClients = site(NCachedTileLinkPorts),
nCachelessClients = site(NUncachedTileLinkPorts),
maxClientXacts = ((site(NMSHRs) + 1) +:
site(GroundTestKey).map(_.maxXacts))
.reduce(max(_, _)),
maxClientsPerPort = 1,
maxManagerXacts = site(NAcquireTransactors) + 2,
dataBeats = 8,
dataBits = site(CacheBlockBytes)*8)
}
case BuildTiles => {
val groundtest = if (site(XLen) == 64)
DefaultTestSuites.groundtest64
else
DefaultTestSuites.groundtest32
TestGeneration.addSuite(groundtest("p"))
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
(0 until site(NTiles)).map { i =>
val tileSettings = site(GroundTestKey)(i)
(r: Bool, p: Parameters) => {
Module(new GroundTestTile(resetSignal = r)(p.alterPartial({
case TLId => "L1toL2"
case GroundTestId => i
case NCachedTileLinkPorts => if(tileSettings.cached > 0) 1 else 0
case NUncachedTileLinkPorts => tileSettings.uncached
})))
}
}
}
case UseFPU => false
case UseAtomics => false
case UseCompressed => false
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
case _ => throw new CDEMatchError
})
class WithComparator extends Config(
(pname, site, here) => pname match {
case GroundTestKey => Seq.fill(site(NTiles)) {

View File

@ -16,5 +16,7 @@ class UnitTestCoreplex(topParams: Parameters) extends Coreplex()(topParams) {
val l1params = p.alterPartial({ case TLId => "L1toL2" })
val tests = Module(new UnitTestSuite()(l1params))
when (tests.io.finished) { stop() }
override def hasSuccessFlag = true
io.success.get := tests.io.finished
}

47
csrc/SimDTM.cc Normal file
View File

@ -0,0 +1,47 @@
// See LICENSE for license details.
#include <fesvr/dtm.h>
#include <vpi_user.h>
#include <svdpi.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,
long long* debug_req_bits_data,
unsigned char debug_resp_valid,
unsigned char* debug_resp_ready,
int debug_resp_bits_resp,
long long debug_resp_bits_data
)
{
if (!dtm) {
s_vpi_vlog_info info;
if (!vpi_get_vlog_info(&info))
abort();
dtm = new dtm_t(std::vector<std::string>(info.argv + 1, info.argv + info.argc));
}
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;
}

View File

@ -1,15 +1,9 @@
// See LICENSE for license details.
#ifndef VERILATOR
#include "emulator.h"
#else
#include "verilated.h"
#if VM_TRACE
#include "verilated_vcd_c.h"
#endif
#endif
#include "mm.h"
#include "mm_dramsim2.h"
#include <fesvr/dtm.h>
#include <iostream>
#include <fcntl.h>
@ -18,13 +12,7 @@
#include <stdlib.h>
#include <unistd.h>
#define MEM_SIZE_BITS 3
#define MEM_LEN_BITS 8
#define MEM_RESP_BITS 2
#include "emulator_type.h"
static dtm_t* dtm;
extern dtm_t* dtm;
static uint64_t trace_count = 0;
bool verbose;
@ -38,18 +26,19 @@ double sc_time_stamp()
return trace_count;
}
extern "C" int vpi_get_vlog_info(void* arg)
{
return 0;
}
int main(int argc, char** argv)
{
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
uint64_t max_cycles = -1;
uint64_t start = 0;
int ret = 0;
const char* loadmem = NULL;
FILE *vcdfile = NULL;
bool dramsim2 = false;
bool print_cycles = false;
uint64_t memsz_mb = MEM_SIZE / (1024*1024);
mm_t *mm[N_MEM_CHANNELS];
for (int i = 1; i < argc; i++)
{
@ -59,18 +48,12 @@ int main(int argc, char** argv)
vcdfile = strcmp(filename, "-") == 0 ? stdout : fopen(filename, "w");
if (!vcdfile)
abort();
} else if (arg.substr(0, 9) == "+memsize=")
memsz_mb = atoll(argv[i]+9);
else if (arg.substr(0, 2) == "-s")
} else if (arg.substr(0, 2) == "-s")
random_seed = atoi(argv[i]+2);
else if (arg == "+dramsim")
dramsim2 = true;
else if (arg == "+verbose")
verbose = true;
else if (arg.substr(0, 12) == "+max-cycles=")
max_cycles = atoll(argv[i]+12);
else if (arg.substr(0, 9) == "+loadmem=")
loadmem = argv[i]+9;
else if (arg.substr(0, 7) == "+start=")
start = atoll(argv[i]+7);
else if (arg.substr(0, 12) == "+cycle-count")
@ -80,12 +63,8 @@ int main(int argc, char** argv)
srand(random_seed);
srand48(random_seed);
#ifndef VERILATOR
Top_t tile;
tile.init(random_seed);
#else
Verilated::randReset(2);
VTop tile;
VTestHarness tile;
#if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals
@ -96,30 +75,6 @@ int main(int argc, char** argv)
tfp->open("");
}
#endif
#endif
uint64_t mem_width = MEM_DATA_BITS / 8;
// Instantiate and initialize main memory
for (int i = 0; i < N_MEM_CHANNELS; i++) {
mm[i] = dramsim2 ? (mm_t*)(new mm_dramsim2_t) : (mm_t*)(new mm_magic_t);
try {
mm[i]->init(memsz_mb*1024*1024 / N_MEM_CHANNELS, mem_width, CACHE_BLOCK_BYTES);
} catch (const std::bad_alloc& e) {
fprintf(stderr,
"Failed to allocate %ld bytes (%ld MiB) of memory\n"
"Set smaller amount of memory using +memsize=<N> (in MiB)\n",
memsz_mb*1024*1024, memsz_mb);
exit(-1);
}
}
if (loadmem) {
void *mems[N_MEM_CHANNELS];
for (int i = 0; i < N_MEM_CHANNELS; i++)
mems[i] = mm[i]->get_data();
load_mem(mems, loadmem, CACHE_BLOCK_BYTES, N_MEM_CHANNELS);
}
dtm = new dtm_t(std::vector<std::string>(argv + 1, argv + argc));
@ -127,155 +82,35 @@ int main(int argc, char** argv)
// reset for several cycles to handle pipelined reset
for (int i = 0; i < 10; i++) {
#ifndef VERILATOR
tile.clock_lo(LIT<1>(1));
tile.clock_hi(LIT<1>(1));
#else
tile.reset = 1;
tile.clk = 0;
tile.eval();
tile.clk = 1;
tile.eval();
tile.reset = 0;
#endif
}
bool_t *mem_ar_valid[N_MEM_CHANNELS];
bool_t *mem_ar_ready[N_MEM_CHANNELS];
mem_addr_t *mem_ar_bits_addr[N_MEM_CHANNELS];
mem_id_t *mem_ar_bits_id[N_MEM_CHANNELS];
mem_size_t *mem_ar_bits_size[N_MEM_CHANNELS];
mem_len_t *mem_ar_bits_len[N_MEM_CHANNELS];
bool_t *mem_aw_valid[N_MEM_CHANNELS];
bool_t *mem_aw_ready[N_MEM_CHANNELS];
mem_addr_t *mem_aw_bits_addr[N_MEM_CHANNELS];
mem_id_t *mem_aw_bits_id[N_MEM_CHANNELS];
mem_size_t *mem_aw_bits_size[N_MEM_CHANNELS];
mem_len_t *mem_aw_bits_len[N_MEM_CHANNELS];
bool_t *mem_w_valid[N_MEM_CHANNELS];
bool_t *mem_w_ready[N_MEM_CHANNELS];
mem_data_t *mem_w_bits_data[N_MEM_CHANNELS];
mem_strb_t *mem_w_bits_strb[N_MEM_CHANNELS];
bool_t *mem_w_bits_last[N_MEM_CHANNELS];
bool_t *mem_b_valid[N_MEM_CHANNELS];
bool_t *mem_b_ready[N_MEM_CHANNELS];
mem_resp_t *mem_b_bits_resp[N_MEM_CHANNELS];
mem_id_t *mem_b_bits_id[N_MEM_CHANNELS];
bool_t *mem_r_valid[N_MEM_CHANNELS];
bool_t *mem_r_ready[N_MEM_CHANNELS];
mem_resp_t *mem_r_bits_resp[N_MEM_CHANNELS];
mem_id_t *mem_r_bits_id[N_MEM_CHANNELS];
mem_data_t *mem_r_bits_data[N_MEM_CHANNELS];
bool_t *mem_r_bits_last[N_MEM_CHANNELS];
#include TBFRAG
while (!dtm->done() && trace_count < max_cycles && ret == 0)
{
for (int i = 0; i < N_MEM_CHANNELS; i++) {
value(mem_ar_ready[i]) = mm[i]->ar_ready();
value(mem_aw_ready[i]) = mm[i]->aw_ready();
value(mem_w_ready[i]) = mm[i]->w_ready();
value(mem_b_valid[i]) = mm[i]->b_valid();
value(mem_b_bits_resp[i]) = mm[i]->b_resp();
value(mem_b_bits_id[i]) = mm[i]->b_id();
value(mem_r_valid[i]) = mm[i]->r_valid();
value(mem_r_bits_resp[i]) = mm[i]->r_resp();
value(mem_r_bits_id[i]) = mm[i]->r_id();
value(mem_r_bits_last[i]) = mm[i]->r_last();
memcpy(values(mem_r_bits_data[i]), mm[i]->r_data(), mem_width);
}
value(field(io_debug_resp_ready)) = dtm->resp_ready();
value(field(io_debug_req_valid)) = dtm->req_valid();
value(field(io_debug_req_bits_addr)) = dtm->req_bits().addr;
value(field(io_debug_req_bits_op)) = dtm->req_bits().op;
value(field(io_debug_req_bits_data)) = dtm->req_bits().data;
try {
#ifndef VERILATOR
tile.clock_lo(LIT<1>(0));
#else
tile.clk = 0;
tile.eval();
// make sure we dump on cycle 0 to get dump_init
while (!dtm->done() && !tile.io_success && trace_count < max_cycles) {
tile.clk = 0;
tile.eval();
#if VM_TRACE
if (tfp && (trace_count == 0 || trace_count >= start))
tfp->dump(trace_count * 2);
bool dump = tfp && trace_count >= start;
if (dump)
tfp->dump(trace_count * 2);
#endif
#endif
} catch (std::runtime_error& e) {
max_cycles = trace_count; // terminate cleanly after this cycle
ret = 1;
std::cerr << e.what() << std::endl;
}
dtm_t::resp debug_resp_bits;
debug_resp_bits.resp = value(field(io_debug_resp_bits_resp));
debug_resp_bits.data = value(field(io_debug_resp_bits_data));
dtm->tick(
value(field(io_debug_req_ready)),
value(field(io_debug_resp_valid)),
debug_resp_bits
);
for (int i = 0; i < N_MEM_CHANNELS; i++) {
mm[i]->tick(
value(mem_ar_valid[i]),
value(mem_ar_bits_addr[i]) - MEM_BASE,
value(mem_ar_bits_id[i]),
value(mem_ar_bits_size[i]),
value(mem_ar_bits_len[i]),
value(mem_aw_valid[i]),
value(mem_aw_bits_addr[i]) - MEM_BASE,
value(mem_aw_bits_id[i]),
value(mem_aw_bits_size[i]),
value(mem_aw_bits_len[i]),
value(mem_w_valid[i]),
value(mem_w_bits_strb[i]),
values(mem_w_bits_data[i]),
value(mem_w_bits_last[i]),
value(mem_r_ready[i]),
value(mem_b_ready[i])
);
}
#ifndef VERILATOR
if (verbose && trace_count >= start)
tile.print(stderr);
// make sure we dump on cycle 0 to get dump_init
if (vcdfile && (trace_count == 0 || trace_count >= start))
tile.dump(vcdfile, trace_count);
tile.clock_hi(LIT<1>(0));
#else
tile.clk = 1;
tile.eval();
#if VM_TRACE
if (tfp && (trace_count == 0 || trace_count >= start))
if (dump)
tfp->dump(trace_count * 2 + 1);
#endif
#endif
trace_count++;
}
#ifdef VERILATOR
#if VM_TRACE
if (tfp)
tfp->close();
#endif
#endif
if (vcdfile)

View File

@ -1,110 +0,0 @@
// See LICENSE for license details.
#ifndef VERILATOR
# define bool_t dat_t<1>
# define values(x) ((x)->values)
# define field(name) &(tile.Top__ ## name)
#else
# define bool_t CData
# define values(x) (x)
# define field(name) &(tile.name)
#endif
#define value(x) (*values(x))
#ifndef VERILATOR
#define mem_addr_t dat_t<MEM_ADDR_BITS>
#elif MEM_ADDR_BITS <= 8
#define mem_addr_t CData
#elif MEM_ADDR_BITS <= 16
#define mem_addr_t SData
#elif MEM_ADDR_BITS <= 32
#define mem_addr_t IData
#elif MEM_ADDR_BITS <= 64
#define mem_addr_t QData
#else // MEM_ADDR_BITS > 64
#define mem_addr_t WData*
#endif
#ifndef VERILATOR
#define mem_id_t dat_t<MEM_ID_BITS>
#elif MEM_ID_BITS <= 8
#define mem_id_t CData
#elif MEM_ID_BITS <= 16
#define mem_id_t SData
#elif MEM_ID_BITS <= 32
#define mem_id_t IData
#elif MEM_ID_BITS <= 64
#define mem_id_t QData
#else // MEM_ID_BITS > 64
#define mem_id_t WData*
#endif
#ifndef VERILATOR
#define mem_size_t dat_t<MEM_SIZE_BITS>
#elif MEM_SIZE_BITS <= 8
#define mem_size_t CData
#elif MEM_SIZE_BITS <= 16
#define mem_size_t SData
#elif MEM_SIZE_BITS <= 32
#define mem_size_t IData
#elif MEM_SIZE_BITS <= 64
#define mem_size_t QData
#else // MEM_SIZE_BITS > 64
#define mem_size_t WData*
#endif
#ifndef VERILATOR
#define mem_len_t dat_t<MEM_LEN_BITS>
#elif MEM_LEN_BITS <= 8
#define mem_len_t CData
#elif MEM_LEN_BITS <= 16
#define mem_len_t SData
#elif MEM_LEN_BITS <= 32
#define mem_len_t IData
#elif MEM_LEN_BITS <= 64
#define mem_len_t QData
#else // MEM_LEN_BITS > 64
#define mem_len_t WData*
#endif
#ifndef VERILATOR
#define mem_strb_t dat_t<MEM_STRB_BITS>
#elif MEM_STRB_BITS <= 8
#define mem_strb_t CData
#elif MEM_STRB_BITS <= 16
#define mem_strb_t SData
#elif MEM_STRB_BITS <= 32
#define mem_strb_t IData
#elif MEM_STRB_BITS <= 64
#define mem_strb_t QData
#else // MEM_STRB_BITS > 64
#define mem_strb_t WData*
#endif
#ifndef VERILATOR
#define mem_data_t dat_t<MEM_DATA_BITS>
#elif MEM_DATA_BITS <= 8
#define mem_data_t CData
#elif MEM_DATA_BITS <= 16
#define mem_data_t SData
#elif MEM_DATA_BITS <= 32
#define mem_data_t IData
#elif MEM_DATA_BITS <= 64
#define mem_data_t QData
#else // MEM_DATA_BITS > 64
#define mem_data_t WData*
#endif
#ifndef VERILATOR
#define mem_resp_t dat_t<MEM_RESP_BITS>
#elif MEM_RESP_BITS <= 8
#define mem_resp_t CData
#elif MEM_RESP_BITS <= 16
#define mem_resp_t SData
#elif MEM_RESP_BITS <= 32
#define mem_resp_t IData
#elif MEM_RESP_BITS <= 64
#define mem_resp_t QData
#else // MEM_RESP_BITS > 64
#define mem_resp_t WData*
#endif

View File

@ -1,140 +0,0 @@
// See LICENSE for license details.
#include "mm.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cassert>
void mm_t::write(uint64_t addr, uint8_t *data, uint64_t strb, uint64_t size)
{
strb &= ((1 << size) - 1) << (addr % word_size);
addr %= this->size;
uint8_t *base = this->data + (addr / word_size) * word_size;
for (int i = 0; i < word_size; i++) {
if (strb & 1)
base[i] = data[i];
strb >>= 1;
}
}
std::vector<char> mm_t::read(uint64_t addr)
{
addr %= this->size;
uint8_t *base = this->data + addr;
return std::vector<char>(base, base + word_size);
}
void mm_t::init(size_t sz, int wsz, int lsz)
{
assert(wsz > 0 && lsz > 0 && (lsz & (lsz-1)) == 0 && lsz % wsz == 0);
word_size = wsz;
line_size = lsz;
data = new uint8_t[sz];
size = sz;
}
mm_t::~mm_t()
{
delete [] data;
}
void mm_magic_t::init(size_t sz, int wsz, int lsz)
{
mm_t::init(sz, wsz, lsz);
dummy_data.resize(word_size);
}
void mm_magic_t::tick(
bool ar_valid,
uint64_t ar_addr,
uint64_t ar_id,
uint64_t ar_size,
uint64_t ar_len,
bool aw_valid,
uint64_t aw_addr,
uint64_t aw_id,
uint64_t aw_size,
uint64_t aw_len,
bool w_valid,
uint64_t w_strb,
void *w_data,
bool w_last,
bool r_ready,
bool b_ready)
{
bool ar_fire = ar_valid && ar_ready();
bool aw_fire = aw_valid && aw_ready();
bool w_fire = w_valid && w_ready();
bool r_fire = r_valid() && r_ready;
bool b_fire = b_valid() && b_ready;
if (ar_fire) {
uint64_t start_addr = (ar_addr / word_size) * word_size;
for (int i = 0; i <= ar_len; i++) {
auto dat = read(start_addr + i * word_size);
rresp.push(mm_rresp_t(ar_id, dat, i == ar_len));
}
}
if (aw_fire) {
store_addr = aw_addr;
store_id = aw_id;
store_count = aw_len + 1;
store_size = 1 << aw_size;
store_inflight = true;
}
if (w_fire) {
write(store_addr, (uint8_t *) w_data, w_strb, store_size);
store_addr += store_size;
store_count--;
if (store_count == 0) {
store_inflight = false;
bresp.push(store_id);
assert(w_last);
}
}
if (b_fire)
bresp.pop();
if (r_fire)
rresp.pop();
cycle++;
}
void load_mem(void** mems, const char* fn, int line_size, int nchannels)
{
char* m;
ssize_t start = 0;
std::ifstream in(fn);
if (!in)
{
std::cerr << "could not open " << fn << std::endl;
exit(-1);
}
std::string line;
while (std::getline(in, line))
{
#define parse_nibble(c) ((c) >= 'a' ? (c)-'a'+10 : (c)-'0')
for (ssize_t i = line.length()-2, j = 0; i >= 0; i -= 2, j++) {
char data = (parse_nibble(line[i]) << 4) | parse_nibble(line[i+1]);
ssize_t addr = start + j;
int channel = (addr / line_size) % nchannels;
m = (char *) mems[channel];
addr = (addr / line_size / nchannels) * line_size + (addr % line_size);
m[addr] = data;
}
start += line.length()/2;
}
}

146
csrc/mm.h
View File

@ -1,146 +0,0 @@
// See LICENSE for license details.
#ifndef MM_EMULATOR_H
#define MM_EMULATOR_H
#include <stdint.h>
#include <cstring>
#include <queue>
class mm_t
{
public:
mm_t() : data(0), size(0) {}
virtual void init(size_t sz, int word_size, int line_size);
virtual bool ar_ready() = 0;
virtual bool aw_ready() = 0;
virtual bool w_ready() = 0;
virtual bool b_valid() = 0;
virtual uint64_t b_resp() = 0;
virtual uint64_t b_id() = 0;
virtual bool r_valid() = 0;
virtual uint64_t r_resp() = 0;
virtual uint64_t r_id() = 0;
virtual void *r_data() = 0;
virtual bool r_last() = 0;
virtual void tick
(
bool ar_valid,
uint64_t ar_addr,
uint64_t ar_id,
uint64_t ar_size,
uint64_t ar_len,
bool aw_valid,
uint64_t aw_addr,
uint64_t aw_id,
uint64_t aw_size,
uint64_t aw_len,
bool w_valid,
uint64_t w_strb,
void *w_data,
bool w_last,
bool r_ready,
bool b_ready
) = 0;
virtual void* get_data() { return data; }
virtual size_t get_size() { return size; }
virtual size_t get_word_size() { return word_size; }
virtual size_t get_line_size() { return line_size; }
void write(uint64_t addr, uint8_t *data, uint64_t strb, uint64_t size);
std::vector<char> read(uint64_t addr);
virtual ~mm_t();
protected:
uint8_t* data;
size_t size;
int word_size;
int line_size;
};
struct mm_rresp_t
{
uint64_t id;
std::vector<char> data;
bool last;
mm_rresp_t(uint64_t id, std::vector<char> data, bool last)
{
this->id = id;
this->data = data;
this->last = last;
}
mm_rresp_t()
{
this->id = 0;
this->last = false;
}
};
class mm_magic_t : public mm_t
{
public:
mm_magic_t() : store_inflight(false) {}
virtual void init(size_t sz, int word_size, int line_size);
virtual bool ar_ready() { return true; }
virtual bool aw_ready() { return !store_inflight; }
virtual bool w_ready() { return store_inflight; }
virtual bool b_valid() { return !bresp.empty(); }
virtual uint64_t b_resp() { return 0; }
virtual uint64_t b_id() { return b_valid() ? bresp.front() : 0; }
virtual bool r_valid() { return !rresp.empty(); }
virtual uint64_t r_resp() { return 0; }
virtual uint64_t r_id() { return r_valid() ? rresp.front().id: 0; }
virtual void *r_data() { return r_valid() ? &rresp.front().data[0] : &dummy_data[0]; }
virtual bool r_last() { return r_valid() ? rresp.front().last : false; }
virtual void tick
(
bool ar_valid,
uint64_t ar_addr,
uint64_t ar_id,
uint64_t ar_size,
uint64_t ar_len,
bool aw_valid,
uint64_t aw_addr,
uint64_t aw_id,
uint64_t aw_size,
uint64_t aw_len,
bool w_valid,
uint64_t w_strb,
void *w_data,
bool w_last,
bool r_ready,
bool b_ready
);
protected:
bool store_inflight;
uint64_t store_addr;
uint64_t store_id;
uint64_t store_size;
uint64_t store_count;
std::vector<char> dummy_data;
std::queue<uint64_t> bresp;
std::queue<mm_rresp_t> rresp;
uint64_t cycle;
};
void load_mem(void** mems, const char* fn, int line_size, int nchannels);
#endif

View File

@ -1,124 +0,0 @@
// See LICENSE for license details.
#include "mm_dramsim2.h"
#include "mm.h"
#include <DRAMSim.h>
#include <iostream>
#include <fstream>
#include <list>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <cassert>
//#define DEBUG_DRAMSIM2
using namespace DRAMSim;
void mm_dramsim2_t::read_complete(unsigned id, uint64_t address, uint64_t clock_cycle)
{
mm_rresp_t resp;
do {
resp = rreq[address].front();
rresp.push(resp);
rreq[address].pop();
} while (!resp.last);
}
void mm_dramsim2_t::write_complete(unsigned id, uint64_t address, uint64_t clock_cycle)
{
auto b_id = wreq[address].front();
bresp.push(b_id);
wreq[address].pop();
}
void power_callback(double a, double b, double c, double d)
{
//fprintf(stderr, "power callback: %0.3f, %0.3f, %0.3f, %0.3f\n",a,b,c,d);
}
void mm_dramsim2_t::init(size_t sz, int wsz, int lsz)
{
assert(lsz == 64); // assumed by dramsim2
mm_t::init(sz, wsz, lsz);
dummy_data.resize(word_size);
assert(size % (1024*1024) == 0);
mem = getMemorySystemInstance("DDR3_micron_64M_8B_x4_sg15.ini", "system.ini", "dramsim2_ini", "results", size/(1024*1024));
TransactionCompleteCB *read_cb = new Callback<mm_dramsim2_t, void, unsigned, uint64_t, uint64_t>(this, &mm_dramsim2_t::read_complete);
TransactionCompleteCB *write_cb = new Callback<mm_dramsim2_t, void, unsigned, uint64_t, uint64_t>(this, &mm_dramsim2_t::write_complete);
mem->RegisterCallbacks(read_cb, write_cb, power_callback);
#ifdef DEBUG_DRAMSIM2
fprintf(stderr,"Dramsim2 init successful\n");
#endif
}
void mm_dramsim2_t::tick(
bool ar_valid,
uint64_t ar_addr,
uint64_t ar_id,
uint64_t ar_size,
uint64_t ar_len,
bool aw_valid,
uint64_t aw_addr,
uint64_t aw_id,
uint64_t aw_size,
uint64_t aw_len,
bool w_valid,
uint64_t w_strb,
void *w_data,
bool w_last,
bool r_ready,
bool b_ready)
{
bool ar_fire = ar_valid && ar_ready();
bool aw_fire = aw_valid && aw_ready();
bool w_fire = w_valid && w_ready();
bool r_fire = r_valid() && r_ready;
bool b_fire = b_valid() && b_ready;
if (ar_fire) {
uint64_t start_addr = (ar_addr / word_size) * word_size;
for (int i = 0; i <= ar_len; i++) {
auto dat = read(start_addr + i * word_size);
rreq[ar_addr].push(mm_rresp_t(ar_id, dat, (i == ar_len)));
}
mem->addTransaction(false, ar_addr);
}
if (aw_fire) {
store_addr = aw_addr;
store_id = aw_id;
store_count = aw_len + 1;
store_size = 1 << aw_size;
store_inflight = true;
}
if (w_fire) {
write(store_addr, (uint8_t *) w_data, w_strb, store_size);
store_addr += store_size;
store_count--;
if (store_count == 0) {
store_inflight = false;
mem->addTransaction(true, store_addr);
wreq[store_addr].push(store_id);
assert(w_last);
}
}
if (b_fire)
bresp.pop();
if (r_fire)
rresp.pop();
mem->update();
cycle++;
}

View File

@ -1,75 +0,0 @@
// See LICENSE for license details.
#ifndef _MM_EMULATOR_DRAMSIM2_H
#define _MM_EMULATOR_DRAMSIM2_H
#include "mm.h"
#include <DRAMSim.h>
#include <map>
#include <queue>
#include <stdint.h>
class mm_dramsim2_t : public mm_t
{
public:
mm_dramsim2_t() : store_inflight(false) {}
virtual void init(size_t sz, int word_size, int line_size);
virtual bool ar_ready() { return mem->willAcceptTransaction(); }
virtual bool aw_ready() { return mem->willAcceptTransaction() && !store_inflight; }
virtual bool w_ready() { return store_inflight; }
virtual bool b_valid() { return !bresp.empty(); }
virtual uint64_t b_resp() { return 0; }
virtual uint64_t b_id() { return b_valid() ? bresp.front() : 0; }
virtual bool r_valid() { return !rresp.empty(); }
virtual uint64_t r_resp() { return 0; }
virtual uint64_t r_id() { return r_valid() ? rresp.front().id: 0; }
virtual void *r_data() { return r_valid() ? &rresp.front().data[0] : &dummy_data[0]; }
virtual bool r_last() { return r_valid() ? rresp.front().last : false; }
virtual void tick
(
bool ar_valid,
uint64_t ar_addr,
uint64_t ar_id,
uint64_t ar_size,
uint64_t ar_len,
bool aw_valid,
uint64_t aw_addr,
uint64_t aw_id,
uint64_t aw_size,
uint64_t aw_len,
bool w_valid,
uint64_t w_strb,
void *w_data,
bool w_last,
bool r_ready,
bool b_ready
);
protected:
DRAMSim::MultiChannelMemorySystem *mem;
uint64_t cycle;
bool store_inflight;
uint64_t store_addr;
uint64_t store_id;
uint64_t store_size;
uint64_t store_count;
std::vector<char> dummy_data;
std::queue<uint64_t> bresp;
std::map<uint64_t, std::queue<uint64_t> > wreq;
std::map<uint64_t, std::queue<mm_rresp_t> > rreq;
std::queue<mm_rresp_t> rresp;
void read_complete(unsigned id, uint64_t address, uint64_t clock_cycle);
void write_complete(unsigned id, uint64_t address, uint64_t clock_cycle);
};
#endif

View File

@ -1,209 +0,0 @@
// See LICENSE for license details.
#include "mm.h"
#include "mm_dramsim2.h"
#include <fesvr/dtm.h>
#include <assert.h>
#include <DirectC.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include <iterator>
extern "C" {
extern int vcs_main(int argc, char** argv);
static dtm_t* dtm;
static mm_t* mm[N_MEM_CHANNELS];
static const char* loadmem;
static bool dramsim = false;
static int memory_channel_mux_select = 0;
int main(int argc, char** argv)
{
for (int i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "+dramsim"))
dramsim = true;
else if (!strncmp(argv[i], "+loadmem=", 9))
loadmem = argv[i]+9;
else if (!strncmp(argv[i], "+memory_channel_mux_select=", 27))
memory_channel_mux_select = atoi(argv[i]+27);
}
dtm = new dtm_t(std::vector<std::string>(argv + 1, argv + argc));
for (int i=0; i<N_MEM_CHANNELS; i++) {
mm[i] = dramsim ? (mm_t*)(new mm_dramsim2_t) : (mm_t*)(new mm_magic_t);
mm[i]->init(MEM_SIZE / N_MEM_CHANNELS, MEM_DATA_BITS / 8, CACHE_BLOCK_BYTES);
}
if (loadmem) {
void *mems[N_MEM_CHANNELS];
for (int i = 0; i < N_MEM_CHANNELS; i++)
mems[i] = mm[i]->get_data();
load_mem(mems, loadmem, CACHE_BLOCK_BYTES, N_MEM_CHANNELS);
}
vcs_main(argc, argv);
abort(); // should never get here
}
void memory_tick(
vc_handle channel,
vc_handle ar_valid,
vc_handle ar_ready,
vc_handle ar_addr,
vc_handle ar_id,
vc_handle ar_size,
vc_handle ar_len,
vc_handle aw_valid,
vc_handle aw_ready,
vc_handle aw_addr,
vc_handle aw_id,
vc_handle aw_size,
vc_handle aw_len,
vc_handle w_valid,
vc_handle w_ready,
vc_handle w_strb,
vc_handle w_data,
vc_handle w_last,
vc_handle r_valid,
vc_handle r_ready,
vc_handle r_resp,
vc_handle r_id,
vc_handle r_data,
vc_handle r_last,
vc_handle b_valid,
vc_handle b_ready,
vc_handle b_resp,
vc_handle b_id)
{
int c = vc_4stVectorRef(channel)->d;
assert(c < N_MEM_CHANNELS);
mm_t* mmc = mm[c];
uint32_t write_data[mmc->get_word_size()/sizeof(uint32_t)];
for (size_t i = 0; i < mmc->get_word_size()/sizeof(uint32_t); i++)
write_data[i] = vc_4stVectorRef(w_data)[i].d;
uint32_t aw_id_val, ar_id_val;
if (MEM_ID_BITS == 1) {
aw_id_val = vc_getScalar(aw_id);
ar_id_val = vc_getScalar(ar_id);
} else {
aw_id_val = vc_4stVectorRef(aw_id)->d;
ar_id_val = vc_4stVectorRef(ar_id)->d;
}
mmc->tick
(
vc_getScalar(ar_valid),
vc_4stVectorRef(ar_addr)->d - MEM_BASE,
ar_id_val,
vc_4stVectorRef(ar_size)->d,
vc_4stVectorRef(ar_len)->d,
vc_getScalar(aw_valid),
vc_4stVectorRef(aw_addr)->d - MEM_BASE,
aw_id_val,
vc_4stVectorRef(aw_size)->d,
vc_4stVectorRef(aw_len)->d,
vc_getScalar(w_valid),
vc_4stVectorRef(w_strb)->d,
write_data,
vc_getScalar(w_last),
vc_getScalar(r_ready),
vc_getScalar(b_ready)
);
vc_putScalar(ar_ready, mmc->ar_ready());
vc_putScalar(aw_ready, mmc->aw_ready());
vc_putScalar(w_ready, mmc->w_ready());
vc_putScalar(b_valid, mmc->b_valid());
vc_putScalar(r_valid, mmc->r_valid());
vc_putScalar(r_last, mmc->r_last());
vec32 d[mmc->get_word_size()/sizeof(uint32_t)];
d[0].c = 0;
d[0].d = mmc->b_resp();
vc_put4stVector(b_resp, d);
d[0].c = 0;
d[0].d = mmc->r_resp();
vc_put4stVector(r_resp, d);
if (MEM_ID_BITS > 1) {
d[0].c = 0;
d[0].d = mmc->b_id();
vc_put4stVector(b_id, d);
d[0].c = 0;
d[0].d = mmc->r_id();
vc_put4stVector(r_id, d);
} else {
vc_putScalar(b_id, mmc->b_id());
vc_putScalar(r_id, mmc->r_id());
}
for (size_t i = 0; i < mmc->get_word_size()/sizeof(uint32_t); i++)
{
d[i].c = 0;
d[i].d = ((uint32_t*)mmc->r_data())[i];
}
vc_put4stVector(r_data, d);
}
void debug_tick
(
vc_handle debug_req_valid,
vc_handle debug_req_ready,
vc_handle debug_req_bits_addr,
vc_handle debug_req_bits_op,
vc_handle debug_req_bits_data,
vc_handle debug_resp_valid,
vc_handle debug_resp_ready,
vc_handle debug_resp_bits_resp,
vc_handle debug_resp_bits_data,
vc_handle exit
)
{
vec32 tmp[2];
dtm_t::resp resp_bits;
vc_get4stVector(debug_resp_bits_resp, tmp);
resp_bits.resp = tmp[0].d;
vc_get4stVector(debug_resp_bits_data, tmp);
resp_bits.data = tmp[0].d | ((uint64_t)tmp[1].d << 32);
dtm->tick
(
vc_getScalar(debug_req_ready),
vc_getScalar(debug_resp_valid),
resp_bits
);
vc_putScalar(debug_resp_ready, dtm->resp_ready());
vc_putScalar(debug_req_valid, dtm->req_valid());
tmp[0].d = dtm->req_bits().addr;
vc_put4stVector(debug_req_bits_addr, tmp);
tmp[0].d = dtm->req_bits().op;
vc_put4stVector(debug_req_bits_op, tmp);
tmp[0].d = dtm->req_bits().data;
tmp[1].d = dtm->req_bits().data >> 32;
vc_put4stVector(debug_req_bits_data, tmp);
tmp[0].d = dtm->done() ? (dtm->exit_code() << 1 | 1) : 0;
vc_put4stVector(exit, tmp);
}
}

@ -1 +0,0 @@
Subproject commit 0b3ee6799a523fc40973dae8dc967ece6f2e3bb9

View File

@ -11,18 +11,14 @@ CONFIG ?= DefaultConfig
include $(base_dir)/Makefrag
CXXSRCS := emulator mm mm_dramsim2
CXXFLAGS := $(CXXFLAGS) -std=c++11 -I$(RISCV)/include -I$(base_dir)/csrc -I$(base_dir)/dramsim2
LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(abspath $(sim_dir)) -ldramsim -lfesvr -lpthread
CXXSRCS := emulator SimDTM
CXXFLAGS := $(CXXFLAGS) -std=c++11 -I$(RISCV)/include -I$(base_dir)/csrc
LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(abspath $(sim_dir)) -lfesvr -lpthread
emu = emulator-$(MODEL)-$(CONFIG)
emu_debug = emulator-$(MODEL)-$(CONFIG)-debug
ifeq ($(CHISEL_VERSION),2)
include $(sim_dir)/Makefrag-emulator
else
include $(sim_dir)/Makefrag-verilator
endif
all: $(emu)
debug: $(emu_debug)
@ -44,18 +40,18 @@ ifneq ($(MAKECMDGOALS),clean)
endif
$(output_dir)/%.run: $(output_dir)/% $(emu)
./$(emu) +dramsim +max-cycles=$(timeout_cycles) $< 2> /dev/null 2> $@ && [ $$PIPESTATUS -eq 0 ]
./$(emu) +max-cycles=$(timeout_cycles) $< 2> /dev/null 2> $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.out: $(output_dir)/% $(emu)
./$(emu) +dramsim +max-cycles=$(timeout_cycles) +verbose $< $(disasm) $@ && [ $$PIPESTATUS -eq 0 ]
./$(emu) +max-cycles=$(timeout_cycles) +verbose $< $(disasm) $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vcd: $(output_dir)/% $(emu_debug)
./$(emu_debug) +dramsim +max-cycles=$(timeout_cycles) +verbose -v$@ $< $(disasm) $(patsubst %.vcd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
./$(emu_debug) +max-cycles=$(timeout_cycles) +verbose -v$@ $< $(disasm) $(patsubst %.vcd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vpd: $(output_dir)/% $(emu_debug)
rm -rf $@.vcd && mkfifo $@.vcd
vcd2vpd $@.vcd $@ > /dev/null &
./$(emu_debug) +dramsim +max-cycles=$(timeout_cycles) +verbose -v$@.vcd $< $(disasm) $(patsubst %.vpd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
./$(emu_debug) +max-cycles=$(timeout_cycles) +verbose -v$@.vcd $< $(disasm) $(patsubst %.vpd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
run: run-asm-tests run-bmark-tests
run-debug: run-asm-tests-debug run-bmark-tests-debug

View File

@ -1,40 +0,0 @@
#--------------------------------------------------------------------
# Chisel Emulator Generation
#--------------------------------------------------------------------
OBJS := $(addsuffix .o,$(CXXSRCS) $(MODEL).$(CONFIG))
DEBUG_OBJS := $(addsuffix .debug.o,$(CXXSRCS) $(MODEL).$(CONFIG))
model_header = $(generated_dir)/$(MODEL).$(CONFIG).h
model_header_debug = $(generated_dir_debug)/$(MODEL).$(CONFIG).h
$(MODEL).$(CONFIG).o: %.o: $(generated_dir)/%.h
$(MAKE) -j $(patsubst %.cpp,%.o,$(shell ls $(generated_dir)/$(MODEL).$(CONFIG)-*.cpp))
$(LD) -r $(patsubst %.cpp,%.o,$(shell ls $(generated_dir)/$(MODEL).$(CONFIG)-*.cpp)) -o $@
$(MODEL).$(CONFIG).debug.o: %.debug.o: $(generated_dir_debug)/%.h
$(MAKE) -j $(patsubst %.cpp,%.o,$(shell ls $(generated_dir_debug)/$(MODEL).$(CONFIG)-*.cpp))
$(LD) -r $(patsubst %.cpp,%.o,$(shell ls $(generated_dir_debug)/$(MODEL).$(CONFIG)-*.cpp)) -o $@
$(generated_dir)/%.o: $(generated_dir)/%.cpp $(generated_dir)/%.h
$(CXX) $(CXXFLAGS) -I$(generated_dir) -c -o $@ $<
$(generated_dir_debug)/%.o: $(generated_dir_debug)/%.cpp $(generated_dir_debug)/%.h
$(CXX) $(CXXFLAGS) -I$(generated_dir_debug) -c -o $@ $<
$(addsuffix .o,$(CXXSRCS)): %.o: $(base_dir)/csrc/%.cc $(base_dir)/csrc/*.h $(model_header) $(consts_header)
$(CXX) $(CXXFLAGS) -include $(model_header) -include $(consts_header) -I$(generated_dir) -c -o $@ $<
$(addsuffix .debug.o,$(CXXSRCS)): %.debug.o: $(base_dir)/csrc/%.cc $(base_dir)/csrc/*.h $(model_header_debug) $(consts_header_debug)
$(CXX) $(CXXFLAGS) -include $(model_header_debug) -include $(consts_header_debug) -I$(generated_dir_debug) -c -o $@ $<
$(generated_dir)/%.$(CONFIG).d $(generated_dir)/%.$(CONFIG).h $(generated_dir)/%.$(CONFIG).prm: $(chisel_srcs)
cd $(base_dir) && $(SBT) "project $(PROJECT)" "run $(CHISEL_ARGS) --noIoDebug"
$(generated_dir_debug)/%.$(CONFIG).d $(generated_dir_debug)/%.$(CONFIG).h $(generated_dir_debug)/%.$(CONFIG).prm: $(chisel_srcs)
cd $(base_dir) && $(SBT) "project $(PROJECT)" "run $(CHISEL_ARGS)-debug --debug --vcd --ioDebug"
$(emu): $(model_header) $(OBJS) libdramsim.a
$(CXX) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS)
$(emu_debug): $(generated_dir)/$(MODEL).$(CONFIG).d $(model_header_debug) $(DEBUG_OBJS) libdramsim.a
$(CXX) $(CXXFLAGS) -o $@ $(DEBUG_OBJS) $(LDFLAGS)

View File

@ -53,6 +53,7 @@ verilator/verilator-$(VERILATOR_VERSION).tar.gz:
VERILATOR := $(INSTALLED_VERILATOR) --cc --exe
VERILATOR_FLAGS := --top-module $(MODEL) +define+PRINTF_COND=\$$c\(\"verbose\"\) --assert \
-Wno-STMTDLY --x-assign unique \
-I$(base_dir)/vsrc \
-O3 -CFLAGS "$(CXXFLAGS) -DVERILATOR -include $(base_dir)/csrc/verilator.h"
cppfiles = $(addprefix $(base_dir)/csrc/, $(addsuffix .cc, $(CXXSRCS)))
headers = $(wildcard $(base_dir)/csrc/*.h)
@ -60,14 +61,14 @@ headers = $(wildcard $(base_dir)/csrc/*.h)
model_header = $(generated_dir)/$(MODEL).$(CONFIG)/V$(MODEL).h
model_header_debug = $(generated_dir_debug)/$(MODEL).$(CONFIG)/V$(MODEL).h
$(emu): $(verilog) $(cppfiles) $(headers) libdramsim.a $(consts_header) $(INSTALLED_VERILATOR)
$(emu): $(verilog) $(cppfiles) $(headers) $(consts_header) $(INSTALLED_VERILATOR)
mkdir -p $(generated_dir)/$(MODEL).$(CONFIG)
$(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(generated_dir)/$(MODEL).$(CONFIG) \
-o $(abspath $(sim_dir))/$@ $< $(cppfiles) -LDFLAGS "$(LDFLAGS)" \
-CFLAGS "-I$(generated_dir) -include $(model_header) -include $(consts_header)"
$(MAKE) -C $(generated_dir)/$(MODEL).$(CONFIG) -f V$(MODEL).mk
$(emu_debug): $(verilog_debug) $(cppfiles) $(headers) libdramsim.a $(consts_header_debug) $(generated_dir)/$(MODEL).$(CONFIG).d $(INSTALLED_VERILATOR)
$(emu_debug): $(verilog_debug) $(cppfiles) $(headers) $(consts_header_debug) $(generated_dir)/$(MODEL).$(CONFIG).d $(INSTALLED_VERILATOR)
mkdir -p $(generated_dir_debug)/$(MODEL).$(CONFIG)
$(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(generated_dir_debug)/$(MODEL).$(CONFIG) --trace \
-o $(abspath $(sim_dir))/$@ $< $(cppfiles) -LDFLAGS "$(LDFLAGS)" \

2
firrtl

@ -1 +1 @@
Subproject commit 7cda3c2825daa97422548e2f0658623234ca0e95
Subproject commit 197760a962633d0e6140bcff16b96cc3d6b4e776

View File

@ -97,6 +97,10 @@ class GroundTestTile(resetSignal: Bool)
extends Tile(resetSignal = resetSignal)(p)
with HasGroundTestParameters {
override val io = new TileIO {
val success = Bool(OUTPUT)
}
val test = p(BuildGroundTest)(dcacheParams)
val ptwPorts = ListBuffer.empty ++= test.io.ptw
@ -123,8 +127,6 @@ class GroundTestTile(resetSignal: Bool)
ptwPorts += dcache_io.ptw
}
when (test.io.status.finished) { stop() }
if (ptwPorts.size > 0) {
val ptw = Module(new DummyPTW(ptwPorts.size))
ptw.io.requestors <> ptwPorts
@ -134,4 +136,6 @@ class GroundTestTile(resetSignal: Bool)
if (memPorts.size > 0) {
io.uncached <> memPorts
}
io.success := test.io.status.finished
}

View File

@ -16,7 +16,7 @@ object BuildSettings extends Build {
libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value)
)
lazy val chisel = project in file("chisel" + sys.env.getOrElse("CHISEL_VERSION", 3))
lazy val chisel = project in file("chisel3")
lazy val cde = project in file("context-dependent-environments")
lazy val hardfloat = project.dependsOn(chisel)
lazy val junctions = project.dependsOn(chisel, cde)

View File

@ -8,12 +8,8 @@ regression: vsim-regression emulator-regression
vsim-regression: vsim-torture
emulator-regression: emulator-torture
ifeq ($(TORTURE_CONFIG),)
$(error Set TORTURE_CONFIG to the torture configuration to run)
endif
# The version of Chisel to use
CHISEL_VERSION ?= 2
# The torture configuration to use
TORTURE_CONFIG ?= default
# The top-level directory that contains rocket-chip
TOP ?= ..
@ -90,7 +86,7 @@ vsim-bmark-tests: $(VSIM_BMARK_TEST_STAMPS)
vsim-regression-tests: $(VSIM_REGRESSION_TEST_STAMPS)
vsim-torture: $(VSIM_TORTURE_STAMPS)
submodule_names = chisel2 chisel3 context-dependent-environments dramsim2 firrtl groundtest hardfloat junctions rocket torture uncore $(ROCKETCHIP_ADDONS)
submodule_names = chisel3 context-dependent-environments firrtl groundtest hardfloat junctions rocket torture uncore $(ROCKETCHIP_ADDONS)
# Checks out all the rocket-chip submodules
stamps/other-submodules.stamp:
@ -114,65 +110,65 @@ $(RISCV)/install.stamp:
# Builds the various simulators
stamps/%/emulator-verilog.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) verilog
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) verilog
date > $@
stamps/%/emulator-ndebug.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV))
date > $@
stamps/%/emulator-debug.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) debug
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) debug
date > $@
stamps/%/vsim-verilog.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) verilog
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) verilog
date > $@
stamps/%/vsim-ndebug.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV))
date > $@
stamps/%/vsim-debug.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) debug
+flock -x $(dir $@)/chisel-lock $(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) debug
date > $@
# Runs tests on one of the simulators
stamps/%/emulator-asm-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-asm-tests-fast
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) run-asm-tests-fast
date > $@
stamps/%/emulator-bmark-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-bmark-tests-fast
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) run-bmark-tests-fast
date > $@
stamps/%/emulator-regression-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) clean-run-output
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-regression-tests-fast
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) clean-run-output
$(MAKE) -C $(abspath $(TOP))/emulator CONFIG=$* RISCV=$(abspath $(RISCV)) run-regression-tests-fast
date > $@
stamps/%/vsim-asm-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-asm-tests-fast
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) run-asm-tests-fast
date > $@
stamps/%/vsim-bmark-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-bmark-tests-fast
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) run-bmark-tests-fast
date > $@
stamps/%/vsim-regression-tests.stamp: stamps/other-submodules.stamp $(RISCV)/install.stamp
mkdir -p $(dir $@)
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) clean-run-output
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) CHISEL_VERSION=$(CHISEL_VERSION) run-regression-tests-fast
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) clean-run-output
$(MAKE) -C $(abspath $(TOP))/vsim CONFIG=$* RISCV=$(abspath $(RISCV)) run-regression-tests-fast
date > $@
# The torture tests run subtly differently on the different targets, so they

View File

@ -26,11 +26,13 @@ abstract class Tile(clockSignal: Clock = null, resetSignal: Bool = null)
val nUncachedTileLinkPorts = p(NUncachedTileLinkPorts)
val dcacheParams = p.alterPartial({ case CacheName => "L1D" })
val io = new Bundle {
class TileIO extends Bundle {
val cached = Vec(nCachedTileLinkPorts, new ClientTileLinkIO)
val uncached = Vec(nUncachedTileLinkPorts, new ClientUncachedTileLinkIO)
val prci = new PRCITileIO().flip
}
val io = new TileIO
}
class RocketTile(clockSignal: Clock = null, resetSignal: Bool = null)

View File

@ -77,10 +77,6 @@ object RocketChipGenerator extends App {
TestGeneration.addSuite(new RegressionTestSuite(paramsFromConfig(RegressionTestNames)))
TestGeneration.generateMakefrag(topModuleName, configClassName)
TestBenchGeneration.generateVerilogFragment(
topModuleName, configClassName, paramsFromConfig)
TestBenchGeneration.generateCPPFragment(
topModuleName, configClassName, paramsFromConfig)
dumpParameters(s"$topModuleName.$configClassName.prm")
dumpKnobs(configClassName, world)

View File

@ -122,11 +122,15 @@ object TopUtils {
//TODO: Remove this wrapper once multichannel DRAM controller is provided
class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
implicit val p = topParams
val io = new TopIO
val coreplex = p(BuildCoreplex)(p)
val periphery = Module(new Periphery()(innerParams))
val io = new TopIO {
val success = if (coreplex.hasSuccessFlag) Some(Bool(OUTPUT)) else None
}
io.success zip coreplex.io.success map { case (x, y) => x := y }
if (exportMMIO) { periphery.io.mmio_in.get <> coreplex.io.mmio.get }
periphery.io.mem_in <> coreplex.io.mem
if (exportBus) { coreplex.io.bus.get <> periphery.io.bus_out.get }

View File

@ -1,400 +0,0 @@
// See LICENSE for license details.
package rocketchip
import Chisel._
import cde.Parameters
import uncore.devices.{DbBusConsts, DMKey}
import coreplex._
object TestBenchGeneration {
def generateVerilogFragment(
topModuleName: String, configClassName: String, p: Parameters) = {
val nMemChannel = p(NMemoryChannels)
// YUNSUP:
// I originally wrote this using a 2d wire array, but of course Synopsys'
// DirectC implementation totally chokes on it when the 2d array is
// referenced by the first dimension: the wire shows up as a contiguous
// bit collection on the DirectC side. I had to individually define the
// wires.
val daw = p(DMKey).nDebugBusAddrSize
val dow = DbBusConsts.dbOpSize
val ddw = DbBusConsts.dbDataSize
val drw = DbBusConsts.dbRespSize
val debugDefs = s"""
wire debug_req_valid_delay;
reg debug_req_valid;
assign #0.1 debug_req_valid_delay = debug_req_valid;
wire debug_req_ready, debug_req_ready_delay;
assign #0.1 debug_req_ready = debug_req_ready_delay;
wire [${daw-1}:0] debug_req_bits_addr_delay;
reg [${daw-1}:0] debug_req_bits_addr;
assign #0.1 debug_req_bits_addr_delay = debug_req_bits_addr;
wire [${dow-1}:0] debug_req_bits_op_delay;
reg [${dow-1}:0] debug_req_bits_op;
assign #0.1 debug_req_bits_op_delay = debug_req_bits_op;
wire [${ddw-1}:0] debug_req_bits_data_delay;
reg [${ddw-1}:0] debug_req_bits_data;
assign #0.1 debug_req_bits_data_delay = debug_req_bits_data;
wire debug_resp_valid, debug_resp_valid_delay;
assign #0.1 debug_resp_valid = debug_resp_valid_delay;
wire debug_resp_ready_delay;
reg debug_resp_ready;
assign #0.1 debug_resp_ready_delay = debug_resp_ready;
wire [${drw-1}:0] debug_resp_bits_resp, debug_resp_bits_resp_delay;
assign #0.1 debug_resp_bits_resp = debug_resp_bits_resp_delay;
wire [${ddw-1}:0] debug_resp_bits_data, debug_resp_bits_data_delay;
assign #0.1 debug_resp_bits_data = debug_resp_bits_data_delay;
"""
val debugBus = s"""
.io_debug_req_ready(debug_req_ready_delay),
.io_debug_req_valid(debug_req_valid_delay),
.io_debug_req_bits_addr(debug_req_bits_addr_delay),
.io_debug_req_bits_op(debug_req_bits_op_delay),
.io_debug_req_bits_data(debug_req_bits_data_delay),
.io_debug_resp_ready(debug_resp_ready_delay),
.io_debug_resp_valid(debug_resp_valid_delay),
.io_debug_resp_bits_resp(debug_resp_bits_resp_delay),
.io_debug_resp_bits_data(debug_resp_bits_data_delay)
"""
val nasti_defs = (0 until nMemChannel) map { i => s"""
wire ar_valid_$i;
reg ar_ready_$i;
wire [`MEM_ADDR_BITS-1:0] ar_addr_$i;
wire [`MEM_ID_BITS-1:0] ar_id_$i;
wire [2:0] ar_size_$i;
wire [7:0] ar_len_$i;
wire aw_valid_$i;
reg aw_ready_$i;
wire [`MEM_ADDR_BITS-1:0] aw_addr_$i;
wire [`MEM_ID_BITS-1:0] aw_id_$i;
wire [2:0] aw_size_$i;
wire [7:0] aw_len_$i;
wire w_valid_$i;
reg w_ready_$i;
wire [`MEM_STRB_BITS-1:0] w_strb_$i;
wire [`MEM_DATA_BITS-1:0] w_data_$i;
wire w_last_$i;
reg r_valid_$i;
wire r_ready_$i;
reg [1:0] r_resp_$i;
reg [`MEM_ID_BITS-1:0] r_id_$i;
reg [`MEM_DATA_BITS-1:0] r_data_$i;
reg r_last_$i;
reg b_valid_$i;
wire b_ready_$i;
reg [1:0] b_resp_$i;
reg [`MEM_ID_BITS-1:0] b_id_$i;
""" } mkString
val nasti_delays = (0 until nMemChannel) map { i => s"""
wire ar_valid_delay_$i;
wire ar_ready_delay_$i;
wire [`MEM_ADDR_BITS-1:0] ar_addr_delay_$i;
wire [`MEM_ID_BITS-1:0] ar_id_delay_$i;
wire [2:0] ar_size_delay_$i;
wire [7:0] ar_len_delay_$i;
wire aw_valid_delay_$i;
wire aw_ready_delay_$i;
wire [`MEM_ADDR_BITS-1:0] aw_addr_delay_$i;
wire [`MEM_ID_BITS-1:0] aw_id_delay_$i;
wire [2:0] aw_size_delay_$i;
wire [7:0] aw_len_delay_$i;
wire w_valid_delay_$i;
wire w_ready_delay_$i;
wire [`MEM_STRB_BITS-1:0] w_strb_delay_$i;
wire [`MEM_DATA_BITS-1:0] w_data_delay_$i;
wire w_last_delay_$i;
wire r_valid_delay_$i;
wire r_ready_delay_$i;
wire [1:0] r_resp_delay_$i;
wire [`MEM_ID_BITS-1:0] r_id_delay_$i;
wire [`MEM_DATA_BITS-1:0] r_data_delay_$i;
wire r_last_delay_$i;
wire b_valid_delay_$i;
wire b_ready_delay_$i;
wire [1:0] b_resp_delay_$i;
wire [`MEM_ID_BITS-1:0] b_id_delay_$i;
assign #0.1 ar_valid_$i = ar_valid_delay_$i;
assign #0.1 ar_ready_delay_$i = ar_ready_$i;
assign #0.1 ar_addr_$i = ar_addr_delay_$i;
assign #0.1 ar_id_$i = ar_id_delay_$i;
assign #0.1 ar_size_$i = ar_size_delay_$i;
assign #0.1 ar_len_$i = ar_len_delay_$i;
assign #0.1 aw_valid_$i = aw_valid_delay_$i;
assign #0.1 aw_ready_delay_$i = aw_ready_$i;
assign #0.1 aw_addr_$i = aw_addr_delay_$i;
assign #0.1 aw_id_$i = aw_id_delay_$i;
assign #0.1 aw_size_$i = aw_size_delay_$i;
assign #0.1 aw_len_$i = aw_len_delay_$i;
assign #0.1 w_valid_$i = w_valid_delay_$i;
assign #0.1 w_ready_delay_$i = w_ready_$i;
assign #0.1 w_strb_$i = w_strb_delay_$i;
assign #0.1 w_data_$i = w_data_delay_$i;
assign #0.1 w_last_$i = w_last_delay_$i;
assign #0.1 r_valid_delay_$i = r_valid_$i;
assign #0.1 r_ready_$i = r_ready_delay_$i;
assign #0.1 r_resp_delay_$i = r_resp_$i;
assign #0.1 r_id_delay_$i = r_id_$i;
assign #0.1 r_data_delay_$i = r_data_$i;
assign #0.1 r_last_delay_$i = r_last_$i;
assign #0.1 b_valid_delay_$i = b_valid_$i;
assign #0.1 b_ready_$i = b_ready_delay_$i;
assign #0.1 b_resp_delay_$i = b_resp_$i;
assign #0.1 b_id_delay_$i = b_id_$i;
""" } mkString
val nasti_connections = (0 until nMemChannel) map { i => s"""
.io_mem_axi_${i}_ar_valid (ar_valid_delay_$i),
.io_mem_axi_${i}_ar_ready (ar_ready_delay_$i),
.io_mem_axi_${i}_ar_bits_addr (ar_addr_delay_$i),
.io_mem_axi_${i}_ar_bits_id (ar_id_delay_$i),
.io_mem_axi_${i}_ar_bits_size (ar_size_delay_$i),
.io_mem_axi_${i}_ar_bits_len (ar_len_delay_$i),
.io_mem_axi_${i}_ar_bits_burst (),
.io_mem_axi_${i}_ar_bits_lock (),
.io_mem_axi_${i}_ar_bits_cache (),
.io_mem_axi_${i}_ar_bits_prot (),
.io_mem_axi_${i}_ar_bits_qos (),
.io_mem_axi_${i}_ar_bits_region (),
.io_mem_axi_${i}_ar_bits_user (),
.io_mem_axi_${i}_aw_valid (aw_valid_delay_$i),
.io_mem_axi_${i}_aw_ready (aw_ready_delay_$i),
.io_mem_axi_${i}_aw_bits_addr (aw_addr_delay_$i),
.io_mem_axi_${i}_aw_bits_id (aw_id_delay_$i),
.io_mem_axi_${i}_aw_bits_size (aw_size_delay_$i),
.io_mem_axi_${i}_aw_bits_len (aw_len_delay_$i),
.io_mem_axi_${i}_aw_bits_burst (),
.io_mem_axi_${i}_aw_bits_lock (),
.io_mem_axi_${i}_aw_bits_cache (),
.io_mem_axi_${i}_aw_bits_prot (),
.io_mem_axi_${i}_aw_bits_qos (),
.io_mem_axi_${i}_aw_bits_region (),
.io_mem_axi_${i}_aw_bits_user (),
.io_mem_axi_${i}_w_valid (w_valid_delay_$i),
.io_mem_axi_${i}_w_ready (w_ready_delay_$i),
.io_mem_axi_${i}_w_bits_id (),
.io_mem_axi_${i}_w_bits_strb (w_strb_delay_$i),
.io_mem_axi_${i}_w_bits_data (w_data_delay_$i),
.io_mem_axi_${i}_w_bits_last (w_last_delay_$i),
.io_mem_axi_${i}_w_bits_user (),
.io_mem_axi_${i}_r_valid (r_valid_delay_$i),
.io_mem_axi_${i}_r_ready (r_ready_delay_$i),
.io_mem_axi_${i}_r_bits_resp (r_resp_delay_$i),
.io_mem_axi_${i}_r_bits_id (r_id_delay_$i),
.io_mem_axi_${i}_r_bits_data (r_data_delay_$i),
.io_mem_axi_${i}_r_bits_last (r_last_delay_$i),
.io_mem_axi_${i}_r_bits_user (1'b0),
.io_mem_axi_${i}_b_valid (b_valid_delay_$i),
.io_mem_axi_${i}_b_ready (b_ready_delay_$i),
.io_mem_axi_${i}_b_bits_resp (b_resp_delay_$i),
.io_mem_axi_${i}_b_bits_id (b_id_delay_$i),
.io_mem_axi_${i}_b_bits_user (1'b0),
""" } mkString
val interrupts = (0 until p(NExtInterrupts)) map { i => s"""
.io_interrupts_$i (1'b0),
""" } mkString
val instantiation = s"""
${topModuleName} dut
(
.clk(clk),
.reset(reset),
$nasti_connections
$interrupts
$debugBus
);
"""
val ticks = (0 until nMemChannel) map { i => s"""
reg [31:0] channel_$i = $i;
always @(posedge clk)
begin
if (reset || r_reset)
begin
ar_ready_$i <= 1'b0;
aw_ready_$i <= 1'b0;
w_ready_$i <= 1'b0;
r_valid_$i <= 1'b0;
r_resp_$i <= 2'b0;
r_id_$i <= {`MEM_ID_BITS {1'b0}};
r_data_$i <= {`MEM_DATA_BITS {1'b0}};
r_last_$i <= 1'b0;
b_valid_$i <= 1'b0;
b_resp_$i <= 2'b0;
b_id_$i <= {`MEM_ID_BITS {1'b0}};
end
else
begin
memory_tick
(
channel_$i,
ar_valid_$i, ar_ready_$i, ar_addr_$i, ar_id_$i, ar_size_$i, ar_len_$i,
aw_valid_$i, aw_ready_$i, aw_addr_$i, aw_id_$i, aw_size_$i, aw_len_$i,
w_valid_$i, w_ready_$i, w_strb_$i, w_data_$i, w_last_$i,
r_valid_$i, r_ready_$i, r_resp_$i, r_id_$i, r_data_$i, r_last_$i,
b_valid_$i, b_ready_$i, b_resp_$i, b_id_$i
);
end
end
always @(posedge clk)
begin
if (verbose)
begin
if (ar_valid_$i && ar_ready_$i)
begin
$$fdisplay(stderr, "MC$i: ar addr=%x size=%x", ar_addr_$i, ar_size_$i);
end
if (aw_valid_$i && aw_ready_$i)
begin
$$fdisplay(stderr, "MC$i: aw addr=%x size=%x", aw_addr_$i, aw_size_$i);
end
if (w_valid_$i && w_ready_$i)
begin
$$fdisplay(stderr, "MC$i: w data=%x strb=%x", w_data_$i, w_strb_$i);
end
if (r_valid_$i && r_ready_$i)
begin
$$fdisplay(stderr, "MC$i: r data=%x", r_data_$i);
end
end
end
""" } mkString
val f = TestGeneration.createOutputFile(s"$topModuleName.$configClassName.tb.vfrag")
f.write(debugDefs + nasti_defs + nasti_delays + instantiation + ticks)
f.close
}
def generateCPPFragment(
topModuleName: String, configClassName: String, p: Parameters) = {
val nMemChannel = p(NMemoryChannels)
val assigns = (0 until nMemChannel).map { i => s"""
#ifndef VERILATOR
mem_ar_valid[$i] = &tile.Top__io_mem_axi_${i}_ar_valid;
mem_ar_ready[$i] = &tile.Top__io_mem_axi_${i}_ar_ready;
mem_ar_bits_addr[$i] = &tile.Top__io_mem_axi_${i}_ar_bits_addr;
mem_ar_bits_id[$i] = &tile.Top__io_mem_axi_${i}_ar_bits_id;
mem_ar_bits_size[$i] = &tile.Top__io_mem_axi_${i}_ar_bits_size;
mem_ar_bits_len[$i] = &tile.Top__io_mem_axi_${i}_ar_bits_len;
mem_aw_valid[$i] = &tile.Top__io_mem_axi_${i}_aw_valid;
mem_aw_ready[$i] = &tile.Top__io_mem_axi_${i}_aw_ready;
mem_aw_bits_addr[$i] = &tile.Top__io_mem_axi_${i}_aw_bits_addr;
mem_aw_bits_id[$i] = &tile.Top__io_mem_axi_${i}_aw_bits_id;
mem_aw_bits_size[$i] = &tile.Top__io_mem_axi_${i}_aw_bits_size;
mem_aw_bits_len[$i] = &tile.Top__io_mem_axi_${i}_aw_bits_len;
mem_w_valid[$i] = &tile.Top__io_mem_axi_${i}_w_valid;
mem_w_ready[$i] = &tile.Top__io_mem_axi_${i}_w_ready;
mem_w_bits_data[$i] = &tile.Top__io_mem_axi_${i}_w_bits_data;
mem_w_bits_strb[$i] = &tile.Top__io_mem_axi_${i}_w_bits_strb;
mem_w_bits_last[$i] = &tile.Top__io_mem_axi_${i}_w_bits_last;
mem_b_valid[$i] = &tile.Top__io_mem_axi_${i}_b_valid;
mem_b_ready[$i] = &tile.Top__io_mem_axi_${i}_b_ready;
mem_b_bits_resp[$i] = &tile.Top__io_mem_axi_${i}_b_bits_resp;
mem_b_bits_id[$i] = &tile.Top__io_mem_axi_${i}_b_bits_id;
mem_r_valid[$i] = &tile.Top__io_mem_axi_${i}_r_valid;
mem_r_ready[$i] = &tile.Top__io_mem_axi_${i}_r_ready;
mem_r_bits_resp[$i] = &tile.Top__io_mem_axi_${i}_r_bits_resp;
mem_r_bits_id[$i] = &tile.Top__io_mem_axi_${i}_r_bits_id;
mem_r_bits_data[$i] = &tile.Top__io_mem_axi_${i}_r_bits_data;
mem_r_bits_last[$i] = &tile.Top__io_mem_axi_${i}_r_bits_last;
#else
mem_ar_valid[$i] = &tile.io_mem_axi_${i}_ar_valid;
mem_ar_ready[$i] = &tile.io_mem_axi_${i}_ar_ready;
mem_ar_bits_addr[$i] = &tile.io_mem_axi_${i}_ar_bits_addr;
mem_ar_bits_id[$i] = &tile.io_mem_axi_${i}_ar_bits_id;
mem_ar_bits_size[$i] = &tile.io_mem_axi_${i}_ar_bits_size;
mem_ar_bits_len[$i] = &tile.io_mem_axi_${i}_ar_bits_len;
mem_aw_valid[$i] = &tile.io_mem_axi_${i}_aw_valid;
mem_aw_ready[$i] = &tile.io_mem_axi_${i}_aw_ready;
mem_aw_bits_addr[$i] = &tile.io_mem_axi_${i}_aw_bits_addr;
mem_aw_bits_id[$i] = &tile.io_mem_axi_${i}_aw_bits_id;
mem_aw_bits_size[$i] = &tile.io_mem_axi_${i}_aw_bits_size;
mem_aw_bits_len[$i] = &tile.io_mem_axi_${i}_aw_bits_len;
mem_w_valid[$i] = &tile.io_mem_axi_${i}_w_valid;
mem_w_ready[$i] = &tile.io_mem_axi_${i}_w_ready;
#if MEM_DATA_BITS > 64
mem_w_bits_data[$i] = tile.io_mem_axi_${i}_w_bits_data;
#else
mem_w_bits_data[$i] = &tile.io_mem_axi_${i}_w_bits_data;
#endif
mem_w_bits_strb[$i] = &tile.io_mem_axi_${i}_w_bits_strb;
mem_w_bits_last[$i] = &tile.io_mem_axi_${i}_w_bits_last;
mem_b_valid[$i] = &tile.io_mem_axi_${i}_b_valid;
mem_b_ready[$i] = &tile.io_mem_axi_${i}_b_ready;
mem_b_bits_resp[$i] = &tile.io_mem_axi_${i}_b_bits_resp;
mem_b_bits_id[$i] = &tile.io_mem_axi_${i}_b_bits_id;
mem_r_valid[$i] = &tile.io_mem_axi_${i}_r_valid;
mem_r_ready[$i] = &tile.io_mem_axi_${i}_r_ready;
mem_r_bits_resp[$i] = &tile.io_mem_axi_${i}_r_bits_resp;
mem_r_bits_id[$i] = &tile.io_mem_axi_${i}_r_bits_id;
#if MEM_DATA_BITS > 64
mem_r_bits_data[$i] = tile.io_mem_axi_${i}_r_bits_data;
#else
mem_r_bits_data[$i] = &tile.io_mem_axi_${i}_r_bits_data;
#endif
mem_r_bits_last[$i] = &tile.io_mem_axi_${i}_r_bits_last;
#endif
""" }.mkString
val interrupts = (0 until p(NExtInterrupts)) map { i => s"""
#ifndef VERILATOR
tile.Top__io_interrupts_$i = LIT<1>(0);
#else
tile.io_interrupts_$i = 0;
#endif
""" } mkString
val f = TestGeneration.createOutputFile(s"$topModuleName.$configClassName.tb.cpp")
f.write(assigns)
f.write(interrupts)
f.close
}
}

View File

@ -128,3 +128,49 @@ class DirectMemtestFPGAConfig extends Config(
new FPGAConfig ++ new DirectMemtestConfig)
class DirectComparatorFPGAConfig extends Config(
new FPGAConfig ++ new DirectComparatorConfig)
class WithGroundTest extends Config(
(pname, site, here) => pname match {
case BuildCoreplex => (p: Parameters) => Module(new GroundTestCoreplex(p))
case TLKey("L1toL2") => {
val useMEI = site(NTiles) <= 1 && site(NCachedTileLinkPorts) <= 1
TileLinkParameters(
coherencePolicy = (
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
else new MESICoherence(site(L2DirectoryRepresentation))),
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1,
nCachingClients = site(NCachedTileLinkPorts),
nCachelessClients = site(NUncachedTileLinkPorts),
maxClientXacts = ((site(NMSHRs) + 1) +:
site(GroundTestKey).map(_.maxXacts))
.reduce(max(_, _)),
maxClientsPerPort = 1,
maxManagerXacts = site(NAcquireTransactors) + 2,
dataBeats = 8,
dataBits = site(CacheBlockBytes)*8)
}
case BuildTiles => {
val groundtest = if (site(XLen) == 64)
DefaultTestSuites.groundtest64
else
DefaultTestSuites.groundtest32
TestGeneration.addSuite(groundtest("p"))
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
(0 until site(NTiles)).map { i =>
val tileSettings = site(GroundTestKey)(i)
(r: Bool, p: Parameters) => {
Module(new GroundTestTile(resetSignal = r)(p.alterPartial({
case TLId => "L1toL2"
case GroundTestId => i
case NCachedTileLinkPorts => if(tileSettings.cached > 0) 1 else 0
case NUncachedTileLinkPorts => tileSettings.uncached
})))
}
}
}
case UseFPU => false
case UseAtomics => false
case UseCompressed => false
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
case _ => throw new CDEMatchError
})

View File

@ -0,0 +1,116 @@
// See LICENSE for license details.
package rocketchip
import Chisel._
import cde.{Parameters, Field}
import rocket.Util._
import junctions._
class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle {
val success = Bool(OUTPUT)
}
val dut = Module(new Top(p))
// This test harness isn't especially flexible yet
require(dut.io.mem_clk.isEmpty)
require(dut.io.mem_rst.isEmpty)
require(dut.io.mem_ahb.isEmpty)
require(dut.io.mem_tl.isEmpty)
require(dut.io.bus_clk.isEmpty)
require(dut.io.bus_rst.isEmpty)
require(dut.io.bus_axi.isEmpty)
require(dut.io.mmio_clk.isEmpty)
require(dut.io.mmio_rst.isEmpty)
require(dut.io.mmio_axi.isEmpty)
require(dut.io.mmio_ahb.isEmpty)
require(dut.io.mmio_tl.isEmpty)
require(dut.io.debug_clk.isEmpty)
require(dut.io.debug_rst.isEmpty)
require(dut.io.debug_rst.isEmpty)
require(dut.io.extra.elements.isEmpty)
for (int <- dut.io.interrupts)
int := false
if (dut.io.mem_axi.nonEmpty) {
val memSize = p(GlobalAddrMap)("mem").size
require(memSize % dut.io.mem_axi.size == 0)
for (axi <- dut.io.mem_axi)
Module(new SimAXIMem(memSize / dut.io.mem_axi.size)).io.axi <> axi
}
val dtm = Module(new SimDTM)
dut.io.debug <> dtm.io.debug
dtm.io.clk := clock
dtm.io.reset := reset
io.success := dut.io.success.getOrElse(dtm.io.exit === 1)
when (dtm.io.exit >= 2) {
printf("*** FAILED *** (exit code = %d)\n", dtm.io.exit >> 1)
stop(1)
}
}
class SimAXIMem(size: BigInt)(implicit p: Parameters) extends Module {
val io = new Bundle {
val axi = new NastiIO().flip
}
val rValid = Reg(init = Bool(false))
val ar = RegEnable(io.axi.ar.bits, io.axi.ar.fire())
io.axi.ar.ready := !rValid
when (io.axi.ar.fire()) { rValid := true }
when (io.axi.r.fire()) {
assert(ar.burst === NastiConstants.BURST_INCR)
ar.addr := ar.addr + (UInt(1) << ar.size)
ar.len := ar.len - 1
when (ar.len === UInt(0)) { rValid := false }
}
val w = io.axi.w.bits
require((size * 8) % w.data.getWidth == 0)
val depth = (size * 8) / w.data.getWidth
val mem = Mem(depth.toInt, w.data)
val wValid = Reg(init = Bool(false))
val bValid = Reg(init = Bool(false))
val aw = RegEnable(io.axi.aw.bits, io.axi.aw.fire())
io.axi.aw.ready := !wValid && !bValid
io.axi.w.ready := wValid
when (io.axi.b.fire()) { bValid := false }
when (io.axi.aw.fire()) { wValid := true }
when (io.axi.w.fire()) {
assert(aw.burst === NastiConstants.BURST_INCR)
aw.addr := aw.addr + (UInt(1) << aw.size)
aw.len := aw.len - 1
when (aw.len === UInt(0)) {
wValid := false
bValid := true
}
def row = mem((aw.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
val mask = FillInterleaved(8, w.strb)
val newData = mask & w.data | ~mask & row
row := newData
}
io.axi.b.valid := bValid
io.axi.b.bits.id := aw.id
io.axi.b.bits.resp := UInt(0)
io.axi.r.valid := rValid
io.axi.r.bits.id := ar.id
io.axi.r.bits.data := mem((ar.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
io.axi.r.bits.resp := UInt(0)
io.axi.r.bits.last := ar.len === UInt(0)
}
class SimDTM(implicit p: Parameters) extends BlackBox {
val io = new Bundle {
val clk = Clock(INPUT)
val reset = Bool(INPUT)
val debug = new uncore.devices.DebugBusIO
val exit = UInt(OUTPUT, 32)
}
}

1
vsim/.gitignore vendored
View File

@ -13,6 +13,5 @@ timestamp
*.ucli
*.a
*.vcd
dramsim2_ini
generated-src
output

View File

@ -17,7 +17,7 @@ output_dir = $(sim_dir)/output
BACKEND ?= v
CONFIG ?= DefaultConfig
TB ?= rocketTestHarness
TB ?= TestDriver
include $(base_dir)/Makefrag
include $(sim_dir)/Makefrag

View File

@ -8,13 +8,12 @@ sim_vsrcs = \
$(generated_dir)/$(MODEL).$(CONFIG).v \
$(generated_dir)/consts.$(CONFIG).vh \
$(base_dir)/vsrc/$(TB).v \
$(base_dir)/vsrc/SimDTM.v \
# C sources
sim_csrcs = \
$(base_dir)/csrc/vcs_main.$(TB).cc \
$(base_dir)/csrc/mm.cc \
$(base_dir)/csrc/mm_dramsim2.cc \
$(base_dir)/csrc/SimDTM.cc \
#--------------------------------------------------------------------
# Build Verilog
@ -34,17 +33,15 @@ VCS_OPTS = -notice -line +lint=all,noVCDE,noONGS,noUI -error=PCWM-L -timescale=1
+rad +v2k +vcs+lic+wait \
+vc+list -CC "-I$(VCS_HOME)/include" \
-CC "-I$(RISCV)/include" \
-CC "-I$(realpath $(base_dir))/dramsim2" \
-CC "-std=c++11" \
-CC "-Wl,-rpath,$(RISCV)/lib" \
-CC "-include $(consts_header)" \
-e vcs_main \
$(RISCV)/lib/libfesvr.so \
$(sim_dir)/libdramsim.a \
-sverilog \
+incdir+$(generated_dir) \
+define+CLOCK_PERIOD=0.5 $(sim_vsrcs) $(sim_csrcs) \
+define+PRINTF_COND=$(TB).printf_cond \
+define+STOP_COND=!$(TB).reset \
+define+RANDOMIZE \
+libext+.v \
@ -53,14 +50,14 @@ VCS_OPTS = -notice -line +lint=all,noVCDE,noONGS,noUI -error=PCWM-L -timescale=1
#--------------------------------------------------------------------
simv = $(sim_dir)/simv-$(MODEL)-$(CONFIG)
$(simv) : $(sim_vsrcs) $(sim_csrcs) $(sim_dir)/libdramsim.a $(consts_header)
$(simv) : $(sim_vsrcs) $(sim_csrcs) $(consts_header)
cd $(sim_dir) && \
rm -rf csrc && \
$(VCS) $(VCS_OPTS) -o $(simv) \
-debug_pp \
simv_debug = $(sim_dir)/simv-$(MODEL)-$(CONFIG)-debug
$(simv_debug) : $(sim_vsrcs) $(sim_csrcs) $(sim_dir)/libdramsim.a $(consts_header)
$(simv_debug) : $(sim_vsrcs) $(sim_csrcs) $(consts_header)
cd $(sim_dir) && \
rm -rf csrc && \
$(VCS) $(VCS_OPTS) -o $(simv_debug) \

View File

@ -1,17 +1,6 @@
#--------------------------------------------------------------------
# Verilog Generation
#--------------------------------------------------------------------
ifeq ($(CHISEL_VERSION),2)
$(generated_dir)/$(MODEL).$(CONFIG).v $(generated_dir)/$(MODEL).$(CONFIG).d $(generated_dir)/$(MODEL).$(CONFIG).prm : $(chisel_srcs)
cd $(base_dir) && mkdir -p $(generated_dir) && $(SBT) "run $(CHISEL_ARGS) --configDump --noInlineMem"
cd $(generated_dir) && \
if [ -a $(MODEL).$(CONFIG).conf ]; then \
$(mem_gen) $(generated_dir)/$(MODEL).$(CONFIG).conf >> $(generated_dir)/$(MODEL).$(CONFIG).v; \
fi
else
# If I don't mark these as .SECONDARY then make will delete these internal
# files.
.SECONDARY: $(generated_dir)/$(MODEL).$(CONFIG).fir
@ -25,36 +14,30 @@ $(generated_dir)/%.v: $(generated_dir)/%.fir $(FIRRTL_JAR)
mkdir -p $(dir $@)
$(FIRRTL) -i $< -o $@ -X verilog
endif
$(generated_dir)/consts.$(CONFIG).vh: $(generated_dir)/$(MODEL).$(CONFIG).prm
echo "\`ifndef CONST_VH" > $@
echo "\`define CONST_VH" >> $@
sed -r 's/\(([A-Za-z0-9_]+),([A-Za-z0-9_]+)\)/`define \1 \2/' $(patsubst %.v,%.prm,$<) >> $@
echo "\`define TBVFRAG \"$(MODEL).$(CONFIG).tb.vfrag\"" >> $@
echo "\`endif // CONST_VH" >> $@
#--------------------------------------------------------------------
# Run
#--------------------------------------------------------------------
$(sim_dir)/dramsim2_ini:
ln -s $(base_dir)/emulator/dramsim2_ini $(sim_dir)/dramsim2_ini
$(output_dir)/%.run: $(output_dir)/% $(simv)
cd $(sim_dir) && $(exec_simv) +max-cycles=$(timeout_cycles) $< 2> /dev/null 2> $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.run: $(output_dir)/% $(sim_dir)/dramsim2_ini $(simv)
cd $(sim_dir) && $(exec_simv) +dramsim +max-cycles=$(timeout_cycles) $< 2> /dev/null 2> $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.out: $(output_dir)/% $(simv)
cd $(sim_dir) && $(exec_simv) +verbose +max-cycles=$(timeout_cycles) $< $(disasm) $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.out: $(output_dir)/% $(sim_dir)/dramsim2_ini $(simv)
cd $(sim_dir) && $(exec_simv) +dramsim +verbose +max-cycles=$(timeout_cycles) $< $(disasm) $@ && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vcd: $(output_dir)/% $(simv_debug)
cd $(sim_dir) && $(exec_simv_debug) +verbose +vcdfile=$@ +max-cycles=$(timeout_cycles) $< $(disasm) $(patsubst %.vcd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vcd: $(output_dir)/% $(sim_dir)/dramsim2_ini $(simv_debug)
cd $(sim_dir) && $(exec_simv_debug) +dramsim +verbose +vcdfile=$@ +max-cycles=$(timeout_cycles) $< $(disasm) $(patsubst %.vcd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vpd: $(output_dir)/% $(simv_debug)
cd $(sim_dir) && $(exec_simv_debug) +verbose +vcdplusfile=$@ +max-cycles=$(timeout_cycles) $< $(disasm) $(patsubst %.vpd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.vpd: $(output_dir)/% $(sim_dir)/dramsim2_ini $(simv_debug)
cd $(sim_dir) && $(exec_simv_debug) +dramsim +verbose +vcdplusfile=$@ +max-cycles=$(timeout_cycles) $< $(disasm) $(patsubst %.vpd,%.out,$@) && [ $$PIPESTATUS -eq 0 ]
$(output_dir)/%.saif: $(output_dir)/% $(sim_dir)/dramsim2_ini $(simv_debug)
cd $(sim_dir) && rm -f $(output_dir)/pipe-$*.vcd && vcd2saif -input $(output_dir)/pipe-$*.vcd -pipe "$(exec_simv_debug) +dramsim +verbose +vcdfile=$(output_dir)/pipe-$*.vcd +max-cycles=$(bmark_timeout_cycles) $<" -output $@ > $(patsubst %.saif,%.out,$@) 2>&1
$(output_dir)/%.saif: $(output_dir)/% $(simv_debug)
cd $(sim_dir) && rm -f $(output_dir)/pipe-$*.vcd && vcd2saif -input $(output_dir)/pipe-$*.vcd -pipe "$(exec_simv_debug) +verbose +vcdfile=$(output_dir)/pipe-$*.vcd +max-cycles=$(bmark_timeout_cycles) $<" -output $@ > $(patsubst %.saif,%.out,$@) 2>&1
run: run-asm-tests run-bmark-tests
run-debug: run-asm-tests-debug run-bmark-tests-debug

80
vsrc/SimDTM.v Normal file
View File

@ -0,0 +1,80 @@
// See LICENSE for license details.
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 longint debug_req_bits_data,
input bit debug_resp_valid,
output bit debug_resp_ready,
input int debug_resp_bits_resp,
input longint debug_resp_bits_data
);
module SimDTM(
input clk,
input reset,
output debug_req_valid,
input debug_req_ready,
output [ 4:0] debug_req_bits_addr,
output [ 1:0] debug_req_bits_op,
output [33:0] debug_req_bits_data,
input debug_resp_valid,
output debug_resp_ready,
input [ 1:0] debug_resp_bits_resp,
input [33: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 [63:0] #0.1 __debug_resp_bits_data = {30'b0, debug_resp_bits_data};
bit __debug_req_valid;
int __debug_req_bits_addr;
int __debug_req_bits_op;
longint __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[4: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[33: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

90
vsrc/TestDriver.v Normal file
View File

@ -0,0 +1,90 @@
// See LICENSE for license details.
module TestDriver;
reg clk = 1'b0;
reg reset = 1'b1;
always #`CLOCK_PERIOD clk = ~clk;
initial #777.7 reset = 0;
// Read input arguments and initialize
reg verbose = 1'b0;
wire printf_cond = verbose && !reset;
reg [63:0] max_cycles = 0;
reg [63:0] trace_count = 0;
reg [1023:0] vcdplusfile = 0;
reg [1023:0] vcdfile = 0;
initial
begin
$value$plusargs("max-cycles=%d", max_cycles);
verbose = $test$plusargs("verbose");
`ifdef DEBUG
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
begin
$vcdplusfile(vcdplusfile);
$vcdpluson(0);
$vcdplusmemon(0);
end
if ($value$plusargs("vcdfile=%s", vcdfile))
begin
$dumpfile(vcdfile);
$dumpvars(0, testHarness);
$dumpon;
end
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
`else
`define VCDPLUSCLOSE
`endif
end
reg [255:0] reason = "";
reg failure = 1'b0;
wire success;
integer stderr = 32'h80000002;
always @(posedge clk)
begin
if (!reset)
begin
if (max_cycles > 0 && trace_count > max_cycles)
begin
reason = " (timeout)";
failure = 1'b1;
end
if (failure)
begin
$fdisplay(stderr, "*** FAILED ***%s after %d simulation cycles", reason, trace_count);
`VCDPLUSCLOSE
$fatal;
end
if (success)
begin
if (verbose)
$fdisplay(stderr, "Completed after %d simulation cycles", trace_count);
`VCDPLUSCLOSE
$finish;
end
end
end
always @(posedge clk)
begin
trace_count = trace_count + 1;
`ifdef GATE_LEVEL
if (verbose)
begin
$fdisplay(stderr, "C: %10d", trace_count-1);
end
`endif
end
TestHarness testHarness(
.clk(clk),
.reset(reset),
.io_success(success)
);
endmodule

View File

@ -1,183 +0,0 @@
// See LICENSE for license details.
extern "A" void debug_tick
(
output reg debug_req_valid,
input reg debug_req_ready,
output reg [ 4:0] debug_req_bits_addr,
output reg [ 1:0] debug_req_bits_op,
output reg [33:0] debug_req_bits_data,
input reg debug_resp_valid,
output reg debug_resp_ready,
input reg [ 1:0] debug_resp_bits_resp,
input reg [33:0] debug_resp_bits_data,
output reg [31:0] exit
);
extern "A" void memory_tick
(
input reg [31:0] channel,
input reg ar_valid,
output reg ar_ready,
input reg [`MEM_ADDR_BITS-1:0] ar_addr,
input reg [`MEM_ID_BITS-1:0] ar_id,
input reg [2:0] ar_size,
input reg [7:0] ar_len,
input reg aw_valid,
output reg aw_ready,
input reg [`MEM_ADDR_BITS-1:0] aw_addr,
input reg [`MEM_ID_BITS-1:0] aw_id,
input reg [2:0] aw_size,
input reg [7:0] aw_len,
input reg w_valid,
output reg w_ready,
input reg [`MEM_STRB_BITS-1:0] w_strb,
input reg [`MEM_DATA_BITS-1:0] w_data,
input reg w_last,
output reg r_valid,
input reg r_ready,
output reg [1:0] r_resp,
output reg [`MEM_ID_BITS-1:0] r_id,
output reg [`MEM_DATA_BITS-1:0] r_data,
output reg r_last,
output reg b_valid,
input reg b_ready,
output reg [1:0] b_resp,
output reg [`MEM_ID_BITS-1:0] b_id
);
module rocketTestHarness;
reg [31:0] seed;
initial seed = $get_initial_random_seed();
//-----------------------------------------------
// Instantiate the processor
reg clk = 1'b0;
reg reset = 1'b1;
reg r_reset = 1'b1;
reg start = 1'b0;
always #`CLOCK_PERIOD clk = ~clk;
reg [ 31:0] n_mem_channel = `N_MEM_CHANNELS;
reg [ 31:0] mem_width = `MEM_DATA_BITS;
reg [ 63:0] max_cycles = 0;
reg [ 63:0] trace_count = 0;
reg [1023:0] loadmem = 0;
reg [1023:0] vcdplusfile = 0;
reg [1023:0] vcdfile = 0;
reg verbose = 0;
wire printf_cond = verbose && !reset;
integer stderr = 32'h80000002;
`include `TBVFRAG
always @(posedge clk)
begin
r_reset <= reset;
end
reg [31:0] exit = 0;
always @(posedge clk)
begin
if (reset || r_reset)
begin
debug_req_valid <= 0;
debug_resp_ready <= 0;
end
else
begin
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,
exit
);
end
end
//-----------------------------------------------
// Start the simulation
// Read input arguments and initialize
initial
begin
$value$plusargs("max-cycles=%d", max_cycles);
verbose = $test$plusargs("verbose");
`ifdef DEBUG
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
begin
$vcdplusfile(vcdplusfile);
$vcdpluson(0);
$vcdplusmemon(0);
end
if ($value$plusargs("vcdfile=%s", vcdfile))
begin
$dumpfile(vcdfile);
$dumpvars(0, dut);
$dumpon;
end
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
`else
`define VCDPLUSCLOSE
`endif
// Strobe reset
#777.7 reset = 0;
end
reg [255:0] reason = 0;
always @(posedge clk)
begin
if (max_cycles > 0 && trace_count > max_cycles)
reason = "timeout";
if (exit > 1)
$sformat(reason, "tohost = %d", exit >> 1);
if (reason)
begin
$fdisplay(stderr, "*** FAILED *** (%s) after %d simulation cycles", reason, trace_count);
`VCDPLUSCLOSE
$fatal;
end
if (exit == 1)
begin
if (verbose)
$fdisplay(stderr, "Completed after %d simulation cycles", trace_count);
`VCDPLUSCLOSE
$finish;
end
end
always @(posedge clk)
begin
trace_count = trace_count + 1;
`ifdef GATE_LEVEL
if (verbose)
begin
$fdisplay(stderr, "C: %10d", trace_count-1);
end
`endif
end
endmodule