[MIDAS] refactor test code
This commit is contained in:
parent
beacd34b09
commit
9272a8d457
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/main/cc/dramsim"]
|
||||
path = src/main/cc/dramsim2
|
||||
url = https://github.com/dramninjasUMD/DRAMSim2.git
|
|
@ -0,0 +1,108 @@
|
|||
base_dir = $(abspath .)
|
||||
util_dir = $(base_dir)/utils
|
||||
v_dir = $(abspath ../verilog)
|
||||
r_dir = $(abspath ../resources)
|
||||
|
||||
CXXFLAGS := $(CXXFLAGS) -std=c++11 -Wall -I$(base_dir)/dramsim2
|
||||
|
||||
include $(util_dir)/Makefrag
|
||||
|
||||
########################################################################
|
||||
# Parameters:
|
||||
# 1) DESIGN: Target design of strober
|
||||
# 2) GEN_DIR: Directory for generated source code
|
||||
# 3) OUT_DIR: Directory for binary files (by default GEN_DIR)
|
||||
# 4) TESTBENCH: C++ testbench written by user (not necessary for replay)
|
||||
# 5) CLOCK_PERIOD(optional): clock period of tests
|
||||
########################################################################
|
||||
OUT_DIR ?= $(GEN_DIR)
|
||||
CLOCK_PERIOD ?= 0.5
|
||||
|
||||
CXXFLAGS := $(CXXFLAGS) -I$(base_dir) -I$(util_dir) $(if $(TESTBENCH),-I$(dir $(TESTBENCH)))
|
||||
LDFLAGS := $(LDFLAGS) -L$(util_dir) -lstdc++
|
||||
|
||||
zynq_files := sample simif simif_zynq
|
||||
zynq_h := $(addprefix $(base_dir)/, $(addsuffix .h, $(zynq_files)))
|
||||
zynq_cc := $(addprefix $(base_dir)/, $(addsuffix .cc, $(zynq_files)))
|
||||
|
||||
$(OUT_DIR)/$(DESIGN)-zynq: $(TESTBENCH) $(util_dir)/biguint.cc $(util_dir)/biguint.h $(zynq_cc) $(zynq_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(CXX) $(CXXFLAGS) -include $(GEN_DIR)/$(DESIGN)-const.h -o $@ $< $(word 2, $^) $(zynq_cc)
|
||||
|
||||
zynq: $(OUT_DIR)/$(DESIGN)-zynq
|
||||
|
||||
|
||||
$(OUT_DIR)/dramsim2_ini: $(r_dir)/dramsim2_ini
|
||||
ln -sf $< $@
|
||||
|
||||
$(OUT_DIR)/$(DESIGN).chain: $(GEN_DIR)/$(DESIGN).chain
|
||||
cp -n $< $@
|
||||
|
||||
emul_files := sample simif simif_emul
|
||||
emul_h := $(addprefix $(base_dir)/, $(addsuffix .h, $(emul_files)))
|
||||
emul_cc := $(addprefix $(base_dir)/, $(addsuffix .cc, $(emul_files)))
|
||||
|
||||
# Compile verilator emulation binary
|
||||
VERILATOR := verilator --cc --exe
|
||||
VERILATOR_FLAGS := --assert -Wno-STMTDLY -O3 -CFLAGS "$(CXXFLAGS)"
|
||||
|
||||
$(OUT_DIR)/V$(DESIGN): $(GEN_DIR)/ZynqShim.v $(TESTBENCH) $(util_dir)/libemul.a $(emul_cc) $(emul_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(VERILATOR) $(VERILATOR_FLAGS) --top-module ZynqShim -Mdir $(GEN_DIR)/V$(DESIGN).csrc \
|
||||
-CFLAGS "-include $(GEN_DIR)/$(DESIGN)-const.h" \
|
||||
-CFLAGS "-include $(GEN_DIR)/V$(DESIGN).csrc/VZynqShim.h" \
|
||||
-LDFLAGS "$(LDFLAGS) -lemul -lpthread" \
|
||||
-o $@ $< $(TESTBENCH) $(emul_cc)
|
||||
$(MAKE) -C $(GEN_DIR)/V$(DESIGN).csrc -f VZynqShim.mk
|
||||
|
||||
$(OUT_DIR)/V$(DESIGN)-debug: $(GEN_DIR)/ZynqShim.v $(TESTBENCH) $(util_dir)/libemul.a $(emul_cc) $(emul_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(VERILATOR) $(VERILATOR_FLAGS) --trace --top-module ZynqShim -Mdir $(GEN_DIR)/V$(DESIGN)-debug.csrc \
|
||||
-CFLAGS "-include $(GEN_DIR)/$(DESIGN)-const.h" \
|
||||
-CFLAGS "-include $(GEN_DIR)/V$(DESIGN)-debug.csrc/VZynqShim.h" \
|
||||
-LDFLAGS "$(LDFLAGS) -lemul -lpthread" \
|
||||
-o $@ $< $(TESTBENCH) $(emul_cc)
|
||||
$(MAKE) -C $(GEN_DIR)/V$(DESIGN)-debug.csrc -f VZynqShim.mk
|
||||
|
||||
verilator: $(OUT_DIR)/V$(DESIGN) $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
|
||||
verilator-debug: $(OUT_DIR)/V$(DESIGN)-debug $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
|
||||
|
||||
# Compile VCS emulation binary
|
||||
VCS := vcs -full64
|
||||
VCS_FLAGS := -quiet -timescale=1ns/1ps +v2k +rad +vcs+initreg+random +vcs+lic+wait \
|
||||
-e vcs_main -cpp $(CXX) -CFLAGS "$(CXXFLAGS) -I$(VCS_HOME)/include -DVCS" \
|
||||
+define+CLOCK_PERIOD=$(CLOCK_PERIOD)
|
||||
|
||||
$(OUT_DIR)/$(DESIGN): $(GEN_DIR)/ZynqShim.v $(v_dir)/emul.v $(TESTBENCH) $(util_dir)/libemul.a $(emul_cc) $(emul_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(VCS) $(VCS_FLAGS) -Mdir=$(GEN_DIR)/$(DESIGN).csrc +vc+list \
|
||||
-CFLAGS "-include $(GEN_DIR)/$(DESIGN)-const.h" -LDFLAGS "$(LDFLAGS) -lemul -lpthread" \
|
||||
-o $@ $< $(GEN_DIR)/$(DESIGN)-const.vh $(word 2, $^) $(TESTBENCH) $(emul_cc) $(word 4, $^)
|
||||
|
||||
$(OUT_DIR)/$(DESIGN)-debug: $(GEN_DIR)/ZynqShim.v $(v_dir)/emul.v $(TESTBENCH) $(util_dir)/libemul.a $(emul_cc) $(emul_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(VCS) $(VCS_FLAGS) -Mdir=$(GEN_DIR)/$(DESIGN)-debug.csrc +vc+list -debug_pp +define+DEBUG \
|
||||
-CFLAGS "-include $(GEN_DIR)/$(DESIGN)-const.h" -LDFLAGS "$(LDFLAGS) -lemul -lpthread" \
|
||||
-o $@ $< $(GEN_DIR)/$(DESIGN)-const.vh $(word 2, $^) $(TESTBENCH) $(emul_cc) $(word 4, $^)
|
||||
|
||||
vcs: $(OUT_DIR)/$(DESIGN) $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
|
||||
vcs-debug: $(OUT_DIR)/$(DESIGN)-debug $(OUT_DIR)/$(DESIGN).chain $(OUT_DIR)/dramsim2_ini
|
||||
|
||||
# Compile VCS replay binary
|
||||
replay_files := sample replay_vpi
|
||||
replay_h := $(addprefix $(base_dir)/, $(addsuffix .h, $(replay_files) replay))
|
||||
replay_cc := $(addprefix $(base_dir)/, $(addsuffix .cc, $(replay_files)))
|
||||
|
||||
$(OUT_DIR)/$(DESIGN)-replay: $(GEN_DIR)/$(DESIGN).v $(v_dir)/replay.v $(util_dir)/libreplay.a $(replay_cc) $(replay_h)
|
||||
mkdir -p $(OUT_DIR)
|
||||
$(VCS) $(VCS_FLAGS) -Mdir=$(GEN_DIR)/$(DESIGN)-replay.csrc \
|
||||
+define+VFRAG=\"$(GEN_DIR)/$(DESIGN).vfrag\" \
|
||||
-debug_pp +vpi -P $(r_dir)/vpi.tab -LDFLAGS "$(LDFLAGS) -lreplay" \
|
||||
-o $@ $< $(word 2, $^) $(replay_cc) $(word 3, $^)
|
||||
|
||||
vcs-replay: $(OUT_DIR)/$(DESIGN)-replay
|
||||
|
||||
clean:
|
||||
rm -rf $(util_dir)/*.o $(util_dir)/*.a
|
||||
|
||||
.PHONY: zynq verilator verilator-debug vcs vcs-debug vcs-replay clean
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2fa5ab55dbb639fa5991218f7b959061f19f590c
|
|
@ -163,22 +163,22 @@ private:
|
|||
}
|
||||
|
||||
inline void force(const std::string& node, biguint_t& data) {
|
||||
check_signal(node);
|
||||
if (log) std::cerr << " * FORCE " << node << " <- 0x" << data << " *" << std::endl;
|
||||
check_signal(node);
|
||||
size_t id = replay_data.signal_map[node];
|
||||
put_value(replay_data.signals[id], data, true);
|
||||
}
|
||||
|
||||
inline void load(const std::string& node, biguint_t& data) {
|
||||
check_signal(node);
|
||||
if (log) std::cerr << " * LOAD " << node << " <- 0x" << data << " *" << std::endl;
|
||||
check_signal(node);
|
||||
size_t id = replay_data.signal_map[node];
|
||||
put_value(replay_data.signals[id], data, false);
|
||||
}
|
||||
|
||||
inline void poke(const std::string& node, biguint_t& data) {
|
||||
check_signal(node);
|
||||
if (log) std::cerr << " * POKE " << node << " <- 0x" << data << " *" << std::endl;
|
||||
check_signal(node);
|
||||
size_t id = replay_data.signal_map[node];
|
||||
put_value(replay_data.signals[id], data, false);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <iostream>
|
||||
|
||||
static const size_t MEM_WIDTH = MEM_DATA_BITS / 8;
|
||||
static const size_t MMIO_WIDTH = CHANNEL_DATA_BITS / 8;
|
||||
static uint64_t main_time = 0;
|
||||
static mmio_t* master = NULL;
|
||||
static mm_t* slave = NULL;
|
||||
|
@ -367,6 +368,7 @@ void simif_emul_t::init(int argc, char** argv, bool log, bool fast_loadmem) {
|
|||
const char* loadmem = NULL;
|
||||
const char* waveform = "dump.vcd";
|
||||
bool dramsim = false;
|
||||
size_t memsize = 1 << 30;
|
||||
for (auto &arg: args) {
|
||||
if (arg.find("+loadmem=") == 0) {
|
||||
loadmem = arg.c_str() + 9;
|
||||
|
@ -377,10 +379,13 @@ void simif_emul_t::init(int argc, char** argv, bool log, bool fast_loadmem) {
|
|||
if (arg.find("+dramsim") == 0) {
|
||||
dramsim = true;
|
||||
}
|
||||
if (arg.find("+memsize=") == 0) {
|
||||
memsize = strtol(arg.c_str() + 9, NULL, 10);
|
||||
}
|
||||
}
|
||||
|
||||
size_t memsize = 1 << 30;
|
||||
master = (mmio_t*) new mmio_t;
|
||||
master->init(CHANNEL_DATA_BITS / 8);
|
||||
slave = dramsim ? (mm_t*) new mm_dramsim2_t : (mm_t*) new mm_magic_t;
|
||||
slave->init(memsize, MEM_DATA_BITS / 8, 64);
|
||||
|
||||
|
@ -426,8 +431,9 @@ int simif_emul_t::finish() {
|
|||
}
|
||||
|
||||
void simif_emul_t::write(size_t addr, uint32_t data) {
|
||||
static const size_t CHANNEL_STRB = (1 << CHANNEL_STRB_BITS) - 1;
|
||||
try {
|
||||
master->write_req(addr, &data);
|
||||
master->write_req(addr << CHANNEL_SIZE, CHANNEL_SIZE, &data, CHANNEL_STRB);
|
||||
while(!master->write_resp()) {
|
||||
#ifdef VCS
|
||||
target->switch_to();
|
||||
|
@ -449,7 +455,7 @@ void simif_emul_t::write(size_t addr, uint32_t data) {
|
|||
uint32_t simif_emul_t::read(size_t addr) {
|
||||
uint32_t data;
|
||||
try {
|
||||
master->read_req(addr);
|
||||
master->read_req(addr << CHANNEL_SIZE, CHANNEL_SIZE);
|
||||
while(!master->read_resp(&data)) {
|
||||
#ifdef VCS
|
||||
target->switch_to();
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
*.o
|
||||
*.a
|
|
@ -0,0 +1,18 @@
|
|||
# compile 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 $@ $<
|
||||
|
||||
# Compile utility code
|
||||
emul_files := biguint context mmio mm mm_dramsim2
|
||||
replay_files := biguint context
|
||||
|
||||
UTIL_OBJS = $(patsubst %.cc, %.o, $(wildcard $(utils_dir)/*.cc))
|
||||
$(UTIL_OBJS): %.o: %.cc %.h
|
||||
$(CXX) $(CXXFLAGS) -I$(util_dir) -I$(base_dir)/dramsim2 -c -o $@ $<
|
||||
|
||||
$(util_dir)/libemul.a: $(DRAMSIM_OBJS) $(addprefix $(util_dir)/, $(addsuffix .o, $(emul_files)))
|
||||
ar rcs $@ $^
|
||||
|
||||
$(util_dir)/libreplay.a: $(addprefix $(util_dir)/, $(addsuffix .o, $(replay_files)))
|
||||
ar rcs $@ $^
|
|
@ -1,16 +1,19 @@
|
|||
#include "mmio.h"
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
const size_t CHANNEL_STRB = (1 << CHANNEL_STRB_BITS) - 1;
|
||||
void mmio_t::init(size_t word_size) {
|
||||
dummy_data.resize(word_size);
|
||||
}
|
||||
|
||||
void mmio_t::read_req(uint64_t addr) {
|
||||
mmio_req_addr_t ar(0, addr << CHANNEL_SIZE, CHANNEL_SIZE, 0);
|
||||
void mmio_t::read_req(uint64_t addr, size_t size) {
|
||||
mmio_req_addr_t ar(0, addr, size, 0);
|
||||
this->ar.push(ar);
|
||||
}
|
||||
|
||||
void mmio_t::write_req(uint64_t addr, void* data) {
|
||||
mmio_req_addr_t aw(0, addr << CHANNEL_SIZE, CHANNEL_SIZE, 0);
|
||||
mmio_req_data_t w((char*) data, CHANNEL_STRB, true);
|
||||
void mmio_t::write_req(uint64_t addr, size_t size, void* data, size_t strb) {
|
||||
mmio_req_addr_t aw(0, addr, size, 0);
|
||||
mmio_req_data_t w((char*) data, strb, true);
|
||||
this->aw.push(aw);
|
||||
this->w.push(w);
|
||||
}
|
|
@ -6,8 +6,6 @@
|
|||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
const size_t MMIO_WIDTH = CHANNEL_DATA_BITS / 8;
|
||||
|
||||
struct mmio_req_addr_t
|
||||
{
|
||||
size_t id;
|
||||
|
@ -46,6 +44,8 @@ public:
|
|||
read_inflight = false;
|
||||
write_inflight = false;
|
||||
}
|
||||
|
||||
void init(size_t data_bits);
|
||||
|
||||
bool aw_valid() { return !aw.empty() && !write_inflight; }
|
||||
size_t aw_id() { return aw_valid() ? aw.front().id : 0; }
|
||||
|
@ -62,13 +62,13 @@ public:
|
|||
bool w_valid() { return !w.empty(); }
|
||||
size_t w_strb() { return w_valid() ? w.front().strb : 0; }
|
||||
bool w_last() { return w_valid() ? w.front().last : false; }
|
||||
void* w_data() { return w_valid() ? w.front().data : dummy_data; }
|
||||
void* w_data() { return w_valid() ? w.front().data : &dummy_data[0]; }
|
||||
|
||||
bool r_ready() { return read_inflight; }
|
||||
bool b_ready() { return write_inflight; }
|
||||
|
||||
void read_req(uint64_t addr);
|
||||
void write_req(uint64_t addr, void* data);
|
||||
void read_req(uint64_t addr, size_t size);
|
||||
void write_req(uint64_t addr, size_t size, void* data, size_t strb);
|
||||
|
||||
void tick
|
||||
(
|
||||
|
@ -96,7 +96,7 @@ private:
|
|||
|
||||
bool read_inflight;
|
||||
bool write_inflight;
|
||||
char dummy_data[MMIO_WIDTH];
|
||||
std::vector<char> dummy_data;
|
||||
};
|
||||
|
||||
#endif // __MMIO_H
|
|
@ -0,0 +1,58 @@
|
|||
NUM_BANKS=8
|
||||
NUM_ROWS=32768
|
||||
NUM_COLS=2048
|
||||
DEVICE_WIDTH=4
|
||||
|
||||
;in nanoseconds
|
||||
;#define REFRESH_PERIOD 7800
|
||||
REFRESH_PERIOD=7800
|
||||
tCK=1.5 ;*
|
||||
|
||||
CL=10 ;*
|
||||
AL=0 ;*
|
||||
;AL=3; needs to be tRCD-1 or 0
|
||||
;RL=(CL+AL)
|
||||
;WL=(RL-1)
|
||||
BL=8 ;*
|
||||
tRAS=24;*
|
||||
tRCD=10 ;*
|
||||
tRRD=4 ;*
|
||||
tRC=34 ;*
|
||||
tRP=10 ;*
|
||||
tCCD=4 ;*
|
||||
tRTP=5 ;*
|
||||
tWTR=5 ;*
|
||||
tWR=10 ;*
|
||||
tRTRS=1; -- RANK PARAMETER, TODO
|
||||
tRFC=107;*
|
||||
tFAW=20;*
|
||||
tCKE=4 ;*
|
||||
tXP=4 ;*
|
||||
|
||||
tCMD=1 ;*
|
||||
|
||||
IDD0=100;
|
||||
IDD1=130;
|
||||
IDD2P=10;
|
||||
IDD2Q=70;
|
||||
IDD2N=70;
|
||||
IDD3Pf=60;
|
||||
IDD3Ps=60;
|
||||
IDD3N=90;
|
||||
IDD4W=255;
|
||||
IDD4R=230;
|
||||
IDD5=305;
|
||||
IDD6=9;
|
||||
IDD6L=12;
|
||||
IDD7=415;
|
||||
|
||||
;same bank
|
||||
;READ_TO_PRE_DELAY=(AL+BL/2+max(tRTP,2)-2)
|
||||
;WRITE_TO_PRE_DELAY=(WL+BL/2+tWR)
|
||||
;READ_TO_WRITE_DELAY=(RL+BL/2+tRTRS-WL)
|
||||
;READ_AUTOPRE_DELAY=(AL+tRTP+tRP)
|
||||
;WRITE_AUTOPRE_DELAY=(WL+BL/2+tWR+tRP)
|
||||
;WRITE_TO_READ_DELAY_B=(WL+BL/2+tWTR);interbank
|
||||
;WRITE_TO_READ_DELAY_R=(WL+BL/2+tRTRS-RL);interrank
|
||||
|
||||
Vdd=1.5 ; TODO: double check this
|
|
@ -0,0 +1,25 @@
|
|||
; COPY THIS FILE AND MODIFY IT TO SUIT YOUR NEEDS
|
||||
|
||||
NUM_CHANS=1 ; number of *logically independent* channels (i.e. each with a separate memory controller); should be a power of 2
|
||||
JEDEC_DATA_BUS_BITS=64 ; Always 64 for DDRx; if you want multiple *ganged* channels, set this to N*64
|
||||
TRANS_QUEUE_DEPTH=32 ; transaction queue, i.e., CPU-level commands such as: READ 0xbeef
|
||||
CMD_QUEUE_DEPTH=32 ; command queue, i.e., DRAM-level commands such as: CAS 544, RAS 4
|
||||
EPOCH_LENGTH=100000 ; length of an epoch in cycles (granularity of simulation)
|
||||
ROW_BUFFER_POLICY=open_page ; close_page or open_page
|
||||
ADDRESS_MAPPING_SCHEME=scheme2 ;valid schemes 1-7; For multiple independent channels, use scheme7 since it has the most parallelism
|
||||
SCHEDULING_POLICY=rank_then_bank_round_robin ; bank_then_rank_round_robin or rank_then_bank_round_robin
|
||||
QUEUING_STRUCTURE=per_rank ;per_rank or per_rank_per_bank
|
||||
|
||||
;for true/false, please use all lowercase
|
||||
DEBUG_TRANS_Q=false
|
||||
DEBUG_CMD_Q=false
|
||||
DEBUG_ADDR_MAP=false
|
||||
DEBUG_BUS=false
|
||||
DEBUG_BANKSTATE=false
|
||||
DEBUG_BANKS=false
|
||||
DEBUG_POWER=false
|
||||
VIS_FILE_OUTPUT=false
|
||||
|
||||
USE_LOW_POWER=true ; go into low power mode when idle?
|
||||
VERIFICATION_OUTPUT=false ; should be false for normal operation
|
||||
TOTAL_ROW_ACCESSES=4 ; maximum number of open page requests to send to the same row before forcing a row close (to prevent starvation)
|
|
@ -23,6 +23,7 @@ private class Compiler(conf: File) extends firrtl.Compiler {
|
|||
|
||||
object Compiler {
|
||||
def apply[T <: chisel3.Module](w: => T, dir: File): firrtl.ir.Circuit = {
|
||||
dir.mkdirs
|
||||
lazy val dut = w
|
||||
val chirrtl = firrtl.Parser.parse(chisel3.Driver.emit(() => dut))
|
||||
val conf = new File(dir, s"${chirrtl.main}.conf")
|
||||
|
|
|
@ -69,7 +69,7 @@ extern "A" void tick
|
|||
output reg [`MEM_ID_BITS-1:0] slave_b_id
|
||||
);
|
||||
|
||||
module vcsHarness;
|
||||
module emul;
|
||||
reg clock = 1'b0;
|
||||
reg reset = 1'b1;
|
||||
reg exit = 1'b0;
|
Loading…
Reference in New Issue