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:
parent
2d1d7266f5
commit
ed827678ac
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -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
|
||||
|
@ -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
|
||||
|
23
Makefrag
23
Makefrag
@ -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:
|
||||
|
14
README.md
14
README.md
@ -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
chisel2
1
chisel2
@ -1 +0,0 @@
|
||||
Subproject commit 23b48e11852458512b706f387d60ee1542458149
|
@ -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(_&&_)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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
47
csrc/SimDTM.cc
Normal 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;
|
||||
}
|
195
csrc/emulator.cc
195
csrc/emulator.cc
@ -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)
|
||||
|
@ -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
|
140
csrc/mm.cc
140
csrc/mm.cc
@ -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
146
csrc/mm.h
@ -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
|
@ -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++;
|
||||
}
|
@ -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
|
@ -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
dramsim2
1
dramsim2
@ -1 +0,0 @@
|
||||
Subproject commit 0b3ee6799a523fc40973dae8dc967ece6f2e3bb9
|
@ -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
|
||||
|
@ -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)
|
@ -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
2
firrtl
@ -1 +1 @@
|
||||
Subproject commit 7cda3c2825daa97422548e2f0658623234ca0e95
|
||||
Subproject commit 197760a962633d0e6140bcff16b96cc3d6b4e776
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 }
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
})
|
||||
|
116
src/main/scala/TestHarness.scala
Normal file
116
src/main/scala/TestHarness.scala
Normal 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
1
vsim/.gitignore
vendored
@ -13,6 +13,5 @@ timestamp
|
||||
*.ucli
|
||||
*.a
|
||||
*.vcd
|
||||
dramsim2_ini
|
||||
generated-src
|
||||
output
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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
80
vsrc/SimDTM.v
Normal 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
90
vsrc/TestDriver.v
Normal 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
|
@ -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
|
Loading…
Reference in New Issue
Block a user