diff --git a/src/main/cc/Makefile b/src/main/cc/Makefile index 221a5d09..cc9fb34b 100644 --- a/src/main/cc/Makefile +++ b/src/main/cc/Makefile @@ -50,17 +50,14 @@ $(OUT_DIR)/$(DESIGN).chain: $(if $(wildcard $(GEN_DIR)/$(DESIGN).chain),cp $(GEN_DIR)/$(DESIGN).chain $@,) override CXXFLAGS += -I$(midas_dir) -I$(util_dir) -# The trailing whitespace is important for some reason... -override LDFLAGS := $(LDFLAGS) -L$(GEN_DIR) -lstdc++ -lpthread -lgmp -lmidas +override LDFLAGS := $(LDFLAGS) -L$(GEN_DIR) -lstdc++ -lpthread -lgmp -design_v := $(GEN_DIR)/$(shim).v -design_h := $(GEN_DIR)/$(DESIGN)-const.h -design_vh := $(GEN_DIR)/$(DESIGN)-const.vh +design_v = $(GEN_DIR)/$(shim).v driver_h = $(foreach t, $(DRIVER), $(wildcard $(dir $(t))/*.h)) endpoint_h := $(wildcard $(endpoint_dir)/*.h) endpoint_cc := $(wildcard $(endpoint_dir)/*.cc) endpoint_o := $(patsubst $(endpoint_dir)/%.cc, $(GEN_DIR)/%.o, $(endpoint_cc)) -$(endpoint_o): $(GEN_DIR)/%.o: $(endpoint_dir)/%.cc $(design_h) $(endpoint_h) +$(endpoint_o): $(GEN_DIR)/%.o: $(endpoint_dir)/%.cc $(GEN_DIR)/$(DESIGN)-const.h $(endpoint_h) $(CXX) $(CXXFLAGS) -c -o $@ $< -include $(word 2, $^) platform_files := simif simif_$(PLATFORM) sample/sample @@ -68,43 +65,84 @@ platform_h := $(addprefix $(midas_dir)/, $(addsuffix .h, $(platform_files))) platform_cc := $(addprefix $(midas_dir)/, $(addsuffix .cc, $(platform_files) sample/simif_sample)) platform_o := $(addprefix $(GEN_DIR)/, $(addsuffix .o, $(platform_files) sample/simif_sample)) -$(platform_o): $(GEN_DIR)/%.o: $(midas_dir)/%.cc $(design_h) $(platform_h) +$(platform_o): $(GEN_DIR)/%.o: $(midas_dir)/%.cc $(GEN_DIR)/$(DESIGN)-const.h $(platform_h) mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) -c -o $@ $< -include $(word 2, $^) -$(OUT_DIR)/$(DESIGN)-$(PLATFORM): $(design_h) $(lib) $(DRIVER) $(driver_h) $(platform_o) $(endpoint_o) +$(OUT_DIR)/$(DESIGN)-$(PLATFORM): $(GEN_DIR)/$(DESIGN)-const.h $(lib) $(DRIVER) $(driver_h) $(platform_o) $(endpoint_o) mkdir -p $(OUT_DIR) $(CXX) $(CXXFLAGS) -include $< \ -o $@ $(DRIVER) $(dramsim_o) $(lib_o) $(platform_o) $(endpoint_o) $(LDFLAGS) $(PLATFORM): $(OUT_DIR)/$(DESIGN)-$(PLATFORM) $(OUT_DIR)/$(DESIGN).chain -# Sources for building MIDAS-level simulators. Must be defined before sources VCS/Verilator Makefrags -override CFLAGS += -include $(design_h) - emul_files := simif simif_emul emul/mmio_$(PLATFORM) sample/sample -emul_h := $(driver_h) $(endpoint_h) $( $(addprefix $(midas_dir)/, $(addsuffix .h, $(emul_files) emul/mmio))) -# This includes c sources and static libraries -emul_cc := $(DRIVER) $(endpoint_cc) $(addprefix $(midas_dir)/, $(addsuffix .cc, $(emul_files) sample/simif_sample)) $(lib) -emul_v := $(design_vh) $(design_v) +emul_h := $(addprefix $(midas_dir)/, $(addsuffix .h, $(emul_files) emul/mmio)) +emul_cc := $(addprefix $(midas_dir)/, $(addsuffix .cc, $(emul_files) sample/simif_sample)) +emul_v := $(v_dir)/emul_$(PLATFORM).v + +# Compile verilator emulation binary +VERILATOR ?= verilator --cc --exe +override VERILATOR_FLAGS := --assert -Wno-STMTDLY -O3 \ + -CFLAGS "$(CXXFLAGS)" -LDFLAGS "$(LDFLAGS) -lmidas" \ + $(VERILATOR_FLAGS) -# The lop level module must be called out for verilator ifeq ($(PLATFORM),zynq) top_module = ZynqShim endif ifeq ($(PLATFORM),f1) top_module = F1Shim endif -include rtlsim/Makefrag-verilator + +$(OUT_DIR)/V$(DESIGN): $(GEN_DIR)/$(DESIGN)-const.h $(design_v) $(lib) $(DRIVER) $(driver_h) $(emul_cc) $(emul_h) $(endpoint_cc) $(endpoint_h) + mkdir -p $(OUT_DIR) + rm -rf $(GEN_DIR)/V$(DESIGN).csrc + $(VERILATOR) $(VERILATOR_FLAGS) --top-module $(top_module) -Mdir $(GEN_DIR)/V$(DESIGN).csrc \ + -CFLAGS "-include $< -include $(GEN_DIR)/V$(DESIGN).csrc/V$(top_module).h" \ + -o $@ $(design_v) $(DRIVER) $(emul_cc) $(endpoint_cc) + $(MAKE) -C $(GEN_DIR)/V$(DESIGN).csrc -f V$(top_module).mk + +$(OUT_DIR)/V$(DESIGN)-debug: $(GEN_DIR)/$(DESIGN)-const.h $(design_v) $(lib) $(DRIVER) $(driver_h) $(emul_cc) $(emul_h) $(endpoint_cc) $(endpoint_h) + mkdir -p $(OUT_DIR) + rm -rf $(GEN_DIR)/V$(DESIGN)-debug.csrc + $(VERILATOR) $(VERILATOR_FLAGS) --trace --top-module $(top_module) -Mdir $(GEN_DIR)/V$(DESIGN)-debug.csrc \ + -CFLAGS "-include $< -include $(GEN_DIR)/V$(DESIGN)-debug.csrc/V$(top_module).h" \ + -o $@ $(design_v) $(DRIVER) $(emul_cc) $(endpoint_cc) + $(MAKE) -C $(GEN_DIR)/V$(DESIGN)-debug.csrc -f V$(top_module).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 -# Add an extra wrapper source for VCS simulators -vcs_wrapper_v := $(v_dir)/emul_$(PLATFORM).v -TB := emul -VCS_FLAGS := -e vcs_main -include rtlsim/Makefrag-vcs +# Compile VCS emulation binary +VCS ?= vcs -full64 +override VCS_FLAGS := -quiet -timescale=1ns/1ps +v2k +rad +vcs+initreg+random +vcs+lic+wait \ + -notice -line +lint=all,noVCDE,noONGS,noUI -quiet -debug_pp +no_notifier -e vcs_main -cpp $(CXX) \ + -CFLAGS "$(CXXFLAGS) -DVCS -I$(VCS_HOME)/include" \ + -LDFLAGS "$(LDFLAGS) -lmidas" \ + +define+CLOCK_PERIOD=$(CLOCK_PERIOD) \ + +define+RANDOMIZE_MEM_INIT \ + +define+RANDOMIZE_REG_INIT \ + +define+RANDOMIZE_GARBAGE_ASSIGN \ + +define+RANDOMIZE_INVALID_ASSIGN \ + $(VCS_FLAGS) + +$(OUT_DIR)/$(DESIGN): $(GEN_DIR)/$(DESIGN)-const.h $(design_v) $(emul_v) $(lib) $(DRIVER) $(driver_h) $(emul_cc) $(emul_h) $(endpoint_cc) $(endpoint_h) + mkdir -p $(OUT_DIR) + rm -rf $(GEN_DIR)/$(DESIGN).csrc + rm -rf $(OUT_DIR)/$(DESIGN).daidir + $(VCS) $(VCS_FLAGS) -Mdir=$(GEN_DIR)/$(DESIGN).csrc +vc+list \ + +define+STOP_COND=!emul.reset +define+PRINTF_COND=!emul.reset \ + -CFLAGS "-include $<" \ + -o $@ $(GEN_DIR)/$(DESIGN)-const.vh $(design_v) $(emul_v) $(lib) $(DRIVER) $(emul_cc) $(endpoint_cc) + +$(OUT_DIR)/$(DESIGN)-debug: $(GEN_DIR)/$(DESIGN)-const.h $(design_v) $(emul_v) $(lib) $(DRIVER) $(driver_h) $(emul_cc) $(emul_h) $(endpoint_cc) $(endpoint_h) + mkdir -p $(OUT_DIR) + rm -rf $(GEN_DIR)/$(DESIGN)-debug.csrc + rm -rf $(OUT_DIR)/$(DESIGN)-debug.daidir + $(VCS) $(VCS_FLAGS) -Mdir=$(GEN_DIR)/$(DESIGN)-debug.csrc +vc+list \ + +define+STOP_COND=!emul.reset +define+PRINTF_COND=!emul.reset +define+DEBUG \ + -CFLAGS "-include $<" \ + -o $@ $(GEN_DIR)/$(DESIGN)-const.vh $(design_v) $(emul_v) $(lib) $(DRIVER) $(emul_cc) $(endpoint_cc) 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 diff --git a/src/main/cc/rtlsim/Makefrag-vcs b/src/main/cc/rtlsim/Makefrag-vcs deleted file mode 100644 index ed12fcf0..00000000 --- a/src/main/cc/rtlsim/Makefrag-vcs +++ /dev/null @@ -1,43 +0,0 @@ -# VCS RTL Simulation Makefrag -# -# This makefrag stores common recipes for building RTL simulators with VCS -# -# Compulsory variables: -# All those described Makefrag-verilator -# vcs_wrapper_v: An additional verilog wrapper around the DUT not used in verilator -# CLOCK_PERIOD: Self explanatory -# TB := The top level module on which the stop and printf conditions are defined -# - -VCS ?= vcs -full64 -override VCS_FLAGS := -quiet -timescale=1ns/1ps +v2k +rad +vcs+initreg+random +vcs+lic+wait \ - -notice -line +lint=all,noVCDE,noONGS,noUI -quiet -debug_pp +no_notifier -cpp $(CXX) \ - -Mdir=$(GEN_DIR)/$(DESIGN)-debug.csrc \ - +vc+list \ - -CFLAGS "$(CXXFLAGS) $(CFLAGS) -DVCS -I$(VCS_HOME)/include" \ - -LDFLAGS "$(LDFLAGS)" \ - -sverilog \ - +define+CLOCK_PERIOD=$(CLOCK_PERIOD) \ - +define+RANDOMIZE_MEM_INIT \ - +define+RANDOMIZE_REG_INIT \ - +define+RANDOMIZE_GARBAGE_ASSIGN \ - +define+RANDOMIZE_INVALID_ASSIGN \ - +define+STOP_COND=!$(TB).reset \ - +define+PRINTF_COND=!$(TB).reset \ - $(VCS_FLAGS) - -vcs_v := $(emul_v) $(vcs_wrapper_v) - -$(OUT_DIR)/$(DESIGN): $(vcs_v) $(emul_cc) $(emul_h) - mkdir -p $(OUT_DIR) - rm -rf $(GEN_DIR)/$(DESIGN).csrc - rm -rf $(OUT_DIR)/$(DESIGN).daidir - $(VCS) $(VCS_FLAGS) \ - -o $@ $(vcs_v) $(emul_cc) - -$(OUT_DIR)/$(DESIGN)-debug: $(vcs_v) $(emul_cc) $(emul_h) - mkdir -p $(OUT_DIR) - rm -rf $(GEN_DIR)/$(DESIGN)-debug.csrc - rm -rf $(OUT_DIR)/$(DESIGN)-debug.daidir - $(VCS) $(VCS_FLAGS) +define+DEBUG \ - -o $@ $(vcs_v) $(emul_cc) diff --git a/src/main/cc/rtlsim/Makefrag-verilator b/src/main/cc/rtlsim/Makefrag-verilator deleted file mode 100644 index aa0610c8..00000000 --- a/src/main/cc/rtlsim/Makefrag-verilator +++ /dev/null @@ -1,36 +0,0 @@ -# Verilator RTL Simulation Makefrag -# -# This makefrag stores common recipes for building RTL simulators with Verilator -# -# Compulsory variables: -# OUT_DIR: See Makefile -# GEN_DIR: See Makefile -# DESIGN: See Makefile -# emul_cc: C++ sources -# emul_h: C++ headers -# emul_v: verilog sources and headers -# -# Verilator Only: -# top_module: The top of the DUT - -VERILATOR ?= verilator --cc --exe -override VERILATOR_FLAGS := --assert -Wno-STMTDLY -O3 \ - -CFLAGS "$(CXXFLAGS) $(CFLAGS)" \ - -LDFLAGS "$(LDFLAGS) " \ - $(VERILATOR_FLAGS) - -$(OUT_DIR)/V$(DESIGN): $(emul_v) $(emul_cc) $(emul_h) - mkdir -p $(OUT_DIR) - rm -rf $(GEN_DIR)/V$(DESIGN).csrc - $(VERILATOR) $(VERILATOR_FLAGS) --top-module $(top_module) -Mdir $(GEN_DIR)/V$(DESIGN).csrc \ - -CFLAGS "-include $(GEN_DIR)/V$(DESIGN).csrc/V$(top_module).h" \ - -o $@ $(emul_v) $(emul_cc) - $(MAKE) -C $(GEN_DIR)/V$(DESIGN).csrc -f V$(top_module).mk - -$(OUT_DIR)/V$(DESIGN)-debug: $(emul_v) $(emul_cc) $(emul_h) - mkdir -p $(OUT_DIR) - rm -rf $(GEN_DIR)/V$(DESIGN)-debug.csrc - $(VERILATOR) $(VERILATOR_FLAGS) --trace --top-module $(top_module) -Mdir $(GEN_DIR)/V$(DESIGN)-debug.csrc \ - -CFLAGS "-include $(GEN_DIR)/V$(DESIGN)-debug.csrc/V$(top_module).h" \ - -o $@ $(emul_v) $(emul_cc) - $(MAKE) -C $(GEN_DIR)/V$(DESIGN)-debug.csrc -f V$(top_module).mk diff --git a/src/main/cc/rtlsim/generic_vharness.cc b/src/main/cc/rtlsim/generic_vharness.cc deleted file mode 100644 index 5346ecbc..00000000 --- a/src/main/cc/rtlsim/generic_vharness.cc +++ /dev/null @@ -1,273 +0,0 @@ -// See LICENSE.SiFive for license details. -// See LICENSE.Berkeley for license details. - -#include "verilated.h" -#if VM_TRACE -#include -#include "verilated_vcd_c.h" -#endif -#include -#include -#include -#include -#include -#include -#include - -// Originally from Rocket-Chip, with RISC-V specific stuff stripped out - -// For option parsing, which is split across this file, Verilog, a few external -// files must be pulled in. The list of files and what they provide is -// enumerated: -// -// Biancolin: This will be useful later. -// $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs: -// defines: -// - PLUSARG_USAGE_OPTIONS -// variables: -// - static const char * verilog_plusargs - -static uint64_t trace_count = 0; -bool verbose; -bool done_reset; - -//void handle_sigterm(int sig) -//{ -// Biancolin: //TODO -//} - -double sc_time_stamp() -{ - return trace_count; -} - -extern "C" int vpi_get_vlog_info(void* arg) -{ - return 0; -} - -static void usage(const char * program_name) -{ - printf("Usage: %s [VERILOG PLUSARG]...\n", - program_name); - fputs("\ -Run a BINARY on the Rocket Chip emulator.\n\ -\n\ -Mandatory arguments to long options are mandatory for short options too.\n\ -\n\ -EMULATOR OPTIONS\n\ - -c, --cycle-count Print the cycle count before exiting\n\ - +cycle-count\n\ - -h, --help Display this help and exit\n\ - -m, --max-cycles=CYCLES Kill the emulation after CYCLES\n\ - +max-cycles=CYCLES\n\ - -s, --seed=SEED Use random number seed SEED\n\ - automatically.\n\ - -V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\ - +verbose\n\ -", stdout); -#if VM_TRACE == 0 - fputs("\ -\n\ -EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n", - stdout); -#endif - fputs("\ - -v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\ - -x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\ - +dump-start\n\ -", stdout); - //fputs("\n" PLUSARG_USAGE_OPTIONS, stdout); -} - -int main(int argc, char** argv) -{ - unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid(); - uint64_t max_cycles = -1; - int ret = 0; - bool print_cycles = false; - // Port numbers are 16 bit unsigned integers. -#if VM_TRACE - FILE * vcdfile = NULL; - uint64_t start = 0; -#endif - int verilog_plusargs_legal = 1; - - while (1) { - static struct option long_options[] = { - {"cycle-count", no_argument, 0, 'c' }, - {"help", no_argument, 0, 'h' }, - {"max-cycles", required_argument, 0, 'm' }, - {"seed", required_argument, 0, 's' }, - {"rbb-port", required_argument, 0, 'r' }, -#if VM_TRACE - {"vcd", required_argument, 0, 'v' }, - {"dump-start", required_argument, 0, 'x' }, -#endif - {"verbose", no_argument, 0, 'V' } - }; - int option_index = 0; -#if VM_TRACE - int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:", long_options, &option_index); -#else - int c = getopt_long(argc, argv, "-chm:s:r:V", long_options, &option_index); -#endif - if (c == -1) break; - retry: - switch (c) { - // Process long and short EMULATOR options - case '?': usage(argv[0]); return 1; - case 'c': print_cycles = true; break; - case 'h': usage(argv[0]); return 0; - case 'm': max_cycles = atoll(optarg); break; - case 's': random_seed = atoi(optarg); break; - case 'V': verbose = true; break; -#if VM_TRACE - case 'v': { - vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w"); - if (!vcdfile) { - std::cerr << "Unable to open " << optarg << " for VCD write\n"; - return 1; - } - break; - } - case 'x': start = atoll(optarg); break; -#endif - // Process legacy '+' EMULATOR arguments by replacing them with - // their getopt equivalents - case 1: { - std::string arg = optarg; - if (arg.substr(0, 1) != "+") { - optind--; - goto done_processing; - } - if (arg == "+verbose") - c = 'V'; - else if (arg.substr(0, 12) == "+max-cycles=") { - c = 'm'; - optarg = optarg+12; - } -#if VM_TRACE - else if (arg.substr(0, 12) == "+dump-start=") { - c = 'x'; - optarg = optarg+12; - } -#endif - else if (arg.substr(0, 12) == "+cycle-count") - c = 'c'; - // If we don't find a legacy '+' EMULATOR argument, it still could be - // a VERILOG_PLUSARG and not an error. - //else if (verilog_plusargs_legal) { - // const char ** plusarg = &verilog_plusargs[0]; - // int legal_verilog_plusarg = 0; - // while (*plusarg && (legal_verilog_plusarg == 0)){ - // if (arg.substr(1, strlen(*plusarg)) == *plusarg) { - // legal_verilog_plusarg = 1; - // } - // plusarg ++; - // } - // if (!legal_verilog_plusarg) { - // verilog_plusargs_legal = 0; - // } else { - // c = 'P'; - // } - // goto retry; - //} - // Not a recongized plus-arg - else { - std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \"" - << arg << "\"\n"; - c = '?'; - } - goto retry; - } - case 'P': break; // Nothing to do here, Verilog PlusArg - default: - c = '?'; - goto retry; - } - } - -done_processing: - if (verbose) - fprintf(stderr, "using random seed %u\n", random_seed); - - srand(random_seed); - srand48(random_seed); - - Verilated::randReset(2); - Verilated::commandArgs(argc, argv); - TEST_HARNESS *tile = new TEST_HARNESS; - -#if VM_TRACE - Verilated::traceEverOn(true); // Verilator must compute traced signals - std::unique_ptr vcdfd(new VerilatedVcdFILE(vcdfile)); - std::unique_ptr tfp(new VerilatedVcdC(vcdfd.get())); - if (vcdfile) { - tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy - tfp->open(""); - } -#endif - - //signal(SIGTERM, handle_sigterm); - - bool dump; - // reset for several cycles to handle pipelined reset - for (int i = 0; i < 10; i++) { - tile->reset = 1; - tile->clock = 0; - tile->eval(); -#if VM_TRACE - dump = tfp && trace_count >= start; - if (dump) - tfp->dump(static_cast(trace_count * 2)); -#endif - tile->clock = 1; - tile->eval(); -#if VM_TRACE - if (dump) - tfp->dump(static_cast(trace_count * 2 + 1)); -#endif - trace_count ++; - } - tile->reset = 0; - done_reset = true; - - while (!tile->io_success && trace_count < max_cycles) { - tile->clock = 0; - tile->eval(); -#if VM_TRACE - dump = tfp && trace_count >= start; - if (dump) - tfp->dump(static_cast(trace_count * 2)); -#endif - - tile->clock = 1; - tile->eval(); -#if VM_TRACE - if (dump) - tfp->dump(static_cast(trace_count * 2 + 1)); -#endif - trace_count++; - } - -#if VM_TRACE - if (tfp) - tfp->close(); - if (vcdfile) - fclose(vcdfile); -#endif - - if (trace_count == max_cycles) - { - fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %ld cycles\n", random_seed, trace_count); - ret = 2; - } - else if (verbose || print_cycles) - { - fprintf(stderr, "Completed after %ld cycles\n", trace_count); - } - - if (tile) delete tile; - return ret; -} diff --git a/src/main/cc/unittest/Makefrag b/src/main/cc/unittest/Makefrag deleted file mode 100644 index ac2ba22b..00000000 --- a/src/main/cc/unittest/Makefrag +++ /dev/null @@ -1,83 +0,0 @@ -# See LICENSE for license details. -# -# Makefrag for generating MIDAS's synthesizable unit tests - -# Compulsory arguments: -# ROCKETCHIP_DIR: Location of rocket chip source -- to grab verilog sources and simulation makefrags -# TODO: These are provided as resources -- fix. -# SBT: command to invoke sbt -# GEN_DIR: Directory into which to emit generate verilog - -DESIGN := TestHarness -CONFIG ?= AllUnitTests -OUT_DIR ?= $(GEN_DIR) -TB ?= TestDriver -EMUL ?= vcs -CLOCK_PERIOD ?= 1.0 - -MAKEFRAG_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) -sim_makefrag_dir := $(MAKEFRAG_DIR)/../rtlsim - -vsrc := $(ROCKETCHIP_DIR)/src/main/resources/vsrc -csrc := $(ROCKETCHIP_DIR)/src/main/resources/csrc - -# Stupidly guess what this test might depend on -src_path = src/main/scala -scala_srcs := $(shell find $(BASE_DIR) -name "*.scala") - -$(GEN_DIR)/$(DESIGN).v $(GEN_DIR)/$(DESIGN).behav_srams.v: $(scala_srcs) - mkdir -p $(@D) - cd $(BASE_DIR) && $(SBT) "runMain midas.unittest.Generator -td $(GEN_DIR) -conf $(CONFIG)" - touch $(GEN_DIR)/$(DESIGN).behav_srams.v - -verilog: $(GEN_DIR)/$(DESIGN).v - -# Common SW RTL simulation Makefrag arguments -# These aren't required as yet, but will be in the future -#bb_vsrcs = \ -# $(vsrc)/ClockDivider2.v \ -# $(vsrc)/ClockDivider3.v \ -# $(vsrc)/AsyncResetReg.v \ -# -#sim_vsrcs = \ -# $(bb_vsrcs) - -emul_v := $(GEN_DIR)/$(DESIGN).v #$(sim_vsrcs) -emul_h := -emul_cc := - -# VCS Makefrag arguments -ifeq ($(EMUL),vcs) -vcs_wrapper_v := $(vsrc)/TestDriver.v -VCS_FLAGS = +verbose -include $(sim_makefrag_dir)/Makefrag-vcs - -vcs = $(OUT_DIR)/$(DESIGN) -vcs_debug = $(OUT_DIR)/$(DESIGN)-debug - -vcs: $(vcs) -vcs-debug: $(vcs_debug) -else - -# Verilator Makefrag arguments -top_module := TestHarness -override CFLAGS += -I$(csrc) -include $(csrc)/verilator.h -DTEST_HARNESS=V$(top_module) -std=c++11 -override emul_cc += $(sim_makefrag_dir)/generic_vharness.cc - -include $(sim_makefrag_dir)/Makefrag-verilator - -verilator = $(OUT_DIR)/V$(DESIGN) -verilator_debug = $(OUT_DIR)/V$(DESIGN)-debug - -verilator: $(verilator) -verilator-debug: $(verilator_debug) -endif - -# Run recipes -run-midas-unittests: $($(EMUL)) - cd $(GEN_DIR) && $< - -run-midas-unittests-debug: $($(EMUL)_debug) - cd $(GEN_DIR) && $< - -.PHONY: run-midas-unittests run-midas-unittests-debug verilog diff --git a/src/main/scala/midas/Config.scala b/src/main/scala/midas/Config.scala index 6893c9a7..c637836a 100644 --- a/src/main/scala/midas/Config.scala +++ b/src/main/scala/midas/Config.scala @@ -8,7 +8,6 @@ import platform._ import strober.core._ import junctions.{NastiKey, NastiParameters} import freechips.rocketchip.config.{Parameters, Config, Field} -import freechips.rocketchip.unittest.UnitTests trait PlatformType case object Zynq extends PlatformType @@ -61,4 +60,3 @@ class F1Config extends Config(new Config((site, here, up) => { class F1ConfigWithSnapshot extends Config(new Config((site, here, up) => { case EnableSnapshot => true }) ++ new F1Config) - diff --git a/src/main/scala/midas/SynthUnitTests.scala b/src/main/scala/midas/SynthUnitTests.scala deleted file mode 100644 index 6cc8e53e..00000000 --- a/src/main/scala/midas/SynthUnitTests.scala +++ /dev/null @@ -1,103 +0,0 @@ -// See LICENSE for license details. - -package midas -package unittest - -import core._ - -import chisel3._ -import firrtl.{ExecutionOptionsManager, HasFirrtlOptions} - -import freechips.rocketchip.config.{Parameters, Config, Field} -import freechips.rocketchip.unittest.{UnitTests, TestHarness} - - -// Unittests -class WithWireChannelTests extends Config((site, here, up) => { - case UnitTests => (q: Parameters) => { - implicit val p = q - val timeout = 2000000 - Seq( - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(2))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(3))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(4))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(7))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(2))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(3))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(4))), - Module(new WireChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(7))), - Module(new WireChannelUnitTest) - ) - } -}) - -class WithReadyValidChannelTests extends Config((site, here, up) => { - case UnitTests => (q: Parameters) => { - implicit val p = q - val timeout = 200000 - Seq( - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(2))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(3))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(4))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = ReciprocalClockRatio(7))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(2))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(3))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(4))), - Module(new ReadyValidChannelUnitTest(timeout = timeout, clockRatio = IntegralClockRatio(7))), - Module(new ReadyValidChannelUnitTest) - ) - } -}) - -// Failing tests -class WithTimeOutCheck extends Config((site, here, up) => { - case UnitTests => (q: Parameters) => { - implicit val p = q - Seq( - Module(new WireChannelUnitTest(timeout = 100, clockRatio = ReciprocalClockRatio(2))), - ) - } -}) - -// Complete configs -class AllUnitTests extends Config(new WithReadyValidChannelTests ++ new WithWireChannelTests ++ new SimConfig) -class TimeOutCheck extends Config(new WithTimeOutCheck ++ new SimConfig) - -// Generates synthesizable unit tests for key modules, such as simulation channels -// See: src/main/cc/unittest/Makefile for the downstream RTL-simulation flow -// -// TODO: Make the core of this generator a trait that can be mixed into -// FireSim's ScalaTests for more type safety -object Generator extends App with freechips.rocketchip.util.HasGeneratorUtilities { - - case class UnitTestOptions( - configProject: String = "midas.unittest", - config: String = "AllUnitTests") { - val fullConfigClasses: Seq[String] = Seq(configProject + "." + config) - } - - trait HasUnitTestOptions { - self: ExecutionOptionsManager => - var utOptions = UnitTestOptions() - parser.note("MIDAS Unit Test Generator Options") - parser.opt[String]("config-project") - .abbr("cp") - .valueName("") - .foreach { d => utOptions = utOptions.copy(configProject = d) } - parser.opt[String]("config") - .abbr("conf") - .valueName("") - .foreach { cfg => utOptions = utOptions.copy(config = cfg) } - } - - val exOptions = new ExecutionOptionsManager("regressions") - with HasChiselExecutionOptions - with HasFirrtlOptions - with HasUnitTestOptions - - exOptions.parse(args) - - val params = getConfig(exOptions.utOptions.fullConfigClasses).toInstance - Driver.execute(exOptions, () => new TestHarness()(params)) -} - diff --git a/src/main/scala/midas/core/Channel.scala b/src/main/scala/midas/core/Channel.scala index 0d33b425..2a7c4323 100644 --- a/src/main/scala/midas/core/Channel.scala +++ b/src/main/scala/midas/core/Channel.scala @@ -3,45 +3,13 @@ package midas package core +import strober.core.{TraceQueue, TraceMaxLen} import freechips.rocketchip.config.Parameters -import freechips.rocketchip.unittest._ -import freechips.rocketchip.tilelink.LFSR64 // Better than chisel's +import freechips.rocketchip.util.ParameterizedBundle import chisel3._ import chisel3.util._ -import strober.core.{TraceQueue, TraceMaxLen} - -// For now use the convention that clock ratios are set with respect to the transformed RTL -trait IsRationalClockRatio { - def numerator: Int - def denominator: Int - def isUnity() = numerator == denominator - def isReciprocal() = numerator == 1 - def isIntegral() = denominator == 1 - def inverse: IsRationalClockRatio -} - -case class RationalClockRatio(numerator: Int, denominator: Int) extends IsRationalClockRatio { - def inverse() = RationalClockRatio(denominator, numerator) -} - -case object UnityClockRatio extends IsRationalClockRatio { - val numerator = 1 - val denominator = 1 - def inverse() = UnityClockRatio -} - -case class ReciprocalClockRatio(denominator: Int) extends IsRationalClockRatio { - val numerator = 1 - def inverse = IntegralClockRatio(numerator = denominator) -} - -case class IntegralClockRatio(numerator: Int) extends IsRationalClockRatio { - val denominator = 1 - def inverse = ReciprocalClockRatio(denominator = numerator) -} - class WireChannelIO(w: Int)(implicit p: Parameters) extends Bundle { val in = Flipped(Decoupled(UInt(w.W))) val out = Decoupled(UInt(w.W)) @@ -50,44 +18,11 @@ class WireChannelIO(w: Int)(implicit p: Parameters) extends Bundle { override def cloneType = new WireChannelIO(w)(p).asInstanceOf[this.type] } -class WireChannel( - val w: Int, - clockRatio: IsRationalClockRatio = UnityClockRatio - )(implicit p: Parameters) extends Module { - - require(clockRatio.isReciprocal || clockRatio.isIntegral) - require(p(ChannelLen) >= clockRatio.denominator) - +class WireChannel(val w: Int)(implicit p: Parameters) extends Module { val io = IO(new WireChannelIO(w)) val tokens = Module(new Queue(UInt(w.W), p(ChannelLen))) tokens.io.enq <> io.in io.out <> tokens.io.deq - - // Dequeuing domain is faster; duplicate tokens by dequeuing from the token - // queue every N handshakes - if (clockRatio.isIntegral && !clockRatio.isUnity) { - val deqTokenCount = RegInit((clockRatio.numerator - 1).U(log2Ceil(clockRatio.numerator).W)) - deqTokenCount.suggestName("deqTokenCount") - tokens.io.deq.ready := false.B - when (io.out.fire && deqTokenCount =/= 0.U) { - deqTokenCount := deqTokenCount - 1.U - }.elsewhen(io.out.fire && deqTokenCount === 0.U) { - deqTokenCount := (clockRatio.numerator - 1).U - tokens.io.deq.ready := true.B - } - // Dequeuing domain is slower; drop enqueued tokens by ignoring M-1 enqueue handshakes - } else if (clockRatio.isReciprocal && !clockRatio.isUnity) { - val enqTokenCount = RegInit(0.U(log2Ceil(clockRatio.denominator).W)) - enqTokenCount.suggestName("enqTokenCount") - tokens.io.enq.valid := false.B - when (io.in.fire && enqTokenCount =/= 0.U) { - enqTokenCount := enqTokenCount - 1.U - }.elsewhen(io.in.fire && enqTokenCount === 0.U) { - enqTokenCount := (clockRatio.denominator - 1).U - tokens.io.enq.valid := true.B - } - } - if (p(EnableSnapshot)) { io.trace <> TraceQueue(tokens.io.deq, io.traceLen) } else { @@ -96,61 +31,6 @@ class WireChannel( } } -class WireChannelUnitTest( - clockRatio: IsRationalClockRatio = UnityClockRatio, - numTokens: Int = 4096, - timeout: Int = 50000 - )(implicit p: Parameters) extends UnitTest(timeout) { - - require(clockRatio.isReciprocal || clockRatio.isIntegral) - override val testName = "WireChannel ClockRatio: ${clockRatio.numerator}/${clockRatio.denominator}" - - val payloadWidth = numTokens * clockRatio.numerator - - val dut = Module(new WireChannel(payloadWidth, clockRatio)) - val inputTokenNum = RegInit(0.U(payloadWidth.W)) - val outputTokenNum = RegInit(0.U(payloadWidth.W)) - val expectedOutputToken = RegInit(0.U(payloadWidth.W)) - val outputDuplicatesRemaining = RegInit((clockRatio.numerator - 1).U) - - val outputReadyFuzz = LFSR64()(0) - val inputValidFuzz = LFSR64()(0) - - val finished = RegInit(false.B) - - dut.io.in.bits := inputTokenNum - dut.io.in.valid := inputValidFuzz - dut.io.out.ready := outputReadyFuzz && !finished - - dut.io.traceLen := DontCare - dut.io.trace.ready := DontCare - - - when (dut.io.in.fire) { - inputTokenNum := inputTokenNum + 1.U - } - - when (dut.io.out.fire) { - assert(finished || dut.io.out.bits === expectedOutputToken, "Output token does not match expected value") - - outputTokenNum := outputTokenNum + 1.U - outputDuplicatesRemaining := Mux(outputDuplicatesRemaining === 0.U, - (clockRatio.numerator-1).U, - outputDuplicatesRemaining - 1.U) - if (clockRatio.isIntegral) { - expectedOutputToken := Mux(outputDuplicatesRemaining === 0.U, - expectedOutputToken + 1.U, - expectedOutputToken) - } else { - expectedOutputToken := expectedOutputToken + clockRatio.denominator.U - } - - finished := finished || outputTokenNum === (numTokens-1).U - } - - io.finished := finished -} - class SimReadyValidIO[T <: Data](gen: T) extends Bundle { val target = EnqIO(gen) val host = new HostReadyValid @@ -181,15 +61,7 @@ class ReadyValidChannelIO[T <: Data](gen: T)(implicit p: Parameters) extends Bun override def cloneType = new ReadyValidChannelIO(gen)(p).asInstanceOf[this.type] } -class ReadyValidChannel[T <: Data]( - gen: T, - flipped: Boolean, - n: Int = 2, // Target queue depth - // Clock ratio (N/M) of deq interface (N) vs enq interface (M) - clockRatio: IsRationalClockRatio = UnityClockRatio - )(implicit p: Parameters) extends Module { - require(clockRatio.isReciprocal || clockRatio.isIntegral) - +class ReadyValidChannel[T <: Data](gen: T, flipped: Boolean, n: Int = 2)(implicit p: Parameters) extends Module { val io = IO(new ReadyValidChannelIO(gen)) // Stores tokens with valid target-data that have been successfully enqueued val target = Module(new Queue(gen, n)) @@ -201,68 +73,30 @@ class ReadyValidChannel[T <: Data]( io.targetReset.ready := true.B // TODO: is it ok? target.io.enq.bits := io.enq.target.bits - target.io.enq.valid := io.enq.target.valid && io.enq.host.fire + target.io.enq.valid := io.enq.target.valid && io.enq.host.hValid io.enq.target.ready := target.io.enq.ready io.enq.host.hReady := tokens.io.enq.ready tokens.io.enq.bits := target.io.enq.fire() tokens.io.enq.valid := io.enq.host.hValid - // Track the number of tokens with valid target-data that should be visible - // to the dequeuer. This allows the enq-side model to advance ahead of the deq-side model - val numTValid = RegInit(0.U(8.W)) - val tValid = tokens.io.deq.bits || numTValid =/= 0.U - val newTValid = tokens.io.deq.fire && tokens.io.deq.bits - val tValidConsumed = io.deq.host.fire && io.deq.target.fire - + // Track the number of valid target-handshakes that should be visible to the dequeuer + val deqCnts = RegInit(0.U(8.W)) + val deqValid = tokens.io.deq.bits || deqCnts.orR io.deq.target.bits := target.io.deq.bits - io.deq.target.valid := target.io.deq.valid && tValid - target.io.deq.ready := io.deq.target.ready && tValid && io.deq.host.fire - - when(newTValid && !tValidConsumed) { - numTValid := numTValid + 1.U - }.elsewhen(!newTValid && tValidConsumed) { - numTValid := numTValid - 1.U - } - - // Enqueuing and dequeuing domains have the same frequency - // The token queue can be directly coupled between domains - if (clockRatio.isUnity) { - io.deq.host.hValid := tokens.io.deq.valid - tokens.io.deq.ready := io.deq.host.hReady - } - // Dequeuing domain is faster - // Each token in the "token" queue represents a token in the slow domain - // Issue N output tokens per entry in the token queue - else if (clockRatio.isIntegral) { - val deqTokenCount = RegInit((clockRatio.numerator - 1).U(log2Ceil(clockRatio.numerator).W)) - deqTokenCount.suggestName("deqTokenCount") - tokens.io.deq.ready := false.B - io.deq.host.hValid := tokens.io.deq.valid - - when (io.deq.host.fire && deqTokenCount =/= 0.U) { - deqTokenCount := deqTokenCount - 1.U - }.elsewhen(io.deq.host.fire && deqTokenCount === 0.U) { - deqTokenCount := (clockRatio.numerator - 1).U - tokens.io.deq.ready := true.B - } - } - // Dequeuing domain is slower - // Each entry in the "token" queue represents a token in the slow domain - // Every M tokens received in the fast domain, enqueue a single entry into the "tokens" queue - else if (clockRatio.isReciprocal) { - val enqTokensRemaining = RegInit((clockRatio.denominator - 1).U(log2Ceil(clockRatio.denominator).W)) - enqTokensRemaining.suggestName("enqTokensRemaining") - tokens.io.deq.ready := enqTokensRemaining =/= 0.U || io.deq.host.hReady - io.deq.host.hValid := tokens.io.deq.valid && enqTokensRemaining === 0.U - - when (tokens.io.deq.fire) { - enqTokensRemaining := Mux(enqTokensRemaining === 0.U, - (clockRatio.denominator - 1).U, - enqTokensRemaining - 1.U) + io.deq.target.valid := target.io.deq.valid && deqValid + target.io.deq.ready := io.deq.target.ready && deqValid && io.deq.host.fire + io.deq.host.hValid := tokens.io.deq.valid + tokens.io.deq.ready := io.deq.host.hReady + + when(tokens.io.deq.fire()) { + // target value is valid, but not ready + when(tokens.io.deq.bits && !io.deq.target.ready) { + deqCnts := deqCnts + 1.U + }.elsewhen(!tokens.io.deq.bits && io.deq.target.ready && deqCnts.orR) { + deqCnts := deqCnts - 1.U } } - if (p(EnableSnapshot)) { val wires = Wire(ReadyValidTrace(gen)) val targetFace = if (flipped) io.deq.target else io.enq.target @@ -288,92 +122,3 @@ class ReadyValidChannel[T <: Data]( io.trace.ready.valid := Bool(false) } } - -class ReadyValidChannelUnitTest( - clockRatio: IsRationalClockRatio = UnityClockRatio, - numNonEmptyTokens: Int = 2048, - timeout: Int = 50000 - )(implicit p: Parameters) extends UnitTest(timeout) { - - require(clockRatio.isReciprocal || clockRatio.isIntegral) - override val testName = "WireChannel ClockRatio: ${clockRatio.numerator}/${clockRatio.denominator}" - - val payloadWidth = log2Ceil(numNonEmptyTokens + 1) - - val dut = Module(new ReadyValidChannel(UInt(payloadWidth.W), flipped = false, clockRatio = clockRatio)) - // Count host-level handshakes on tokens - val inputTokenNum = RegInit(0.U(log2Ceil(timeout).W)) - val outputTokenNum = RegInit(0.U(log2Ceil(timeout).W)) - - // For driving the values of non-empty tokens - val inputTokenPayload = RegInit(0.U(payloadWidth.W)) - val expectedOutputPayload = RegInit(0.U(payloadWidth.W)) - - val outputHReadyFuzz = LFSR64()(0) - val outputTReadyFuzz = LFSR64()(0) - val inputHValidFuzz = LFSR64()(0) - val inputTValidFuzz = LFSR64()(0) - - val finished = RegInit(false.B) - - dut.io.enq.host.hValid := inputHValidFuzz - dut.io.enq.target.valid := inputTValidFuzz - dut.io.enq.target.bits := inputTokenPayload - - dut.io.deq.host.hReady := outputHReadyFuzz && !finished - dut.io.deq.target.ready := outputTReadyFuzz && !finished - - dut.io.traceLen := DontCare - dut.io.trace.ready := DontCare - - - when (dut.io.enq.host.fire) { - inputTokenNum := inputTokenNum + 1.U - - when ( dut.io.enq.target.fire) { - inputTokenPayload := inputTokenPayload + 1.U - } - } - - val (lowerTokenBound, upperTokenBound) = if (clockRatio.isIntegral) { - val lB = Mux( inputTokenNum > p(ChannelLen).U, - (inputTokenNum - p(ChannelLen).U) * clockRatio.numerator.U, - 0.U) - val uB = inputTokenNum * clockRatio.numerator.U - (lB, uB) - } else { - // The channel requires only a single input token after reset to produce its output token - val uB = (inputTokenNum + (clockRatio.denominator - 1).U) / clockRatio.denominator.U - val lB = Mux(uB > p(ChannelLen).U, - uB - p(ChannelLen).U, - 0.U) - (lB, uB) - } - - when (dut.io.deq.host.fire) { - outputTokenNum := outputTokenNum + 1.U - - assert(finished || outputTokenNum <= upperTokenBound, "Received too many output tokens.") - assert(finished || outputTokenNum >= lowerTokenBound, "Received too few output tokens.") - - // Check the target-data - when (dut.io.deq.target.fire) { - assert(finished || dut.io.deq.target.bits === expectedOutputPayload, "Output token does not match expected value") - expectedOutputPayload := expectedOutputPayload + 1.U //clockRatio.denominator.U - - finished := finished || expectedOutputPayload === (numNonEmptyTokens - 1).U - } - } - - io.finished := finished - - dut.io.traceLen := DontCare - dut.io.traceLen := DontCare - // TODO: FIXME - dut.io.targetReset.valid := reset.toBool() - dut.io.targetReset.bits := reset.toBool() - dut.io.trace.ready.ready := DontCare - dut.io.trace.valid.ready := DontCare - dut.io.trace.bits.ready := DontCare - dut.io.traceLen := DontCare -} diff --git a/src/main/scala/midas/core/Endpoints.scala b/src/main/scala/midas/core/Endpoints.scala index 7adee192..ba86215e 100644 --- a/src/main/scala/midas/core/Endpoints.scala +++ b/src/main/scala/midas/core/Endpoints.scala @@ -17,7 +17,6 @@ import scala.collection.mutable.{ArrayBuffer, HashSet} trait Endpoint { protected val channels = ArrayBuffer[(String, Record)]() protected val wires = HashSet[Bits]() - def clockRatio: IsRationalClockRatio = UnityClockRatio def matchType(data: Data): Boolean def widget(p: Parameters): EndpointWidget def widgetName: String = getClass.getSimpleName @@ -65,9 +64,7 @@ abstract class SimMemIO extends Endpoint { } } -class SimNastiMemIO( - override val clockRatio: IsRationalClockRatio = UnityClockRatio - ) extends SimMemIO { +class SimNastiMemIO extends SimMemIO { def matchType(data: Data) = data match { case channel: NastiIO => directionOf(channel.w.valid) == ActualDirection.Output @@ -75,9 +72,7 @@ class SimNastiMemIO( } } -class SimAXI4MemIO( - override val clockRatio: IsRationalClockRatio = UnityClockRatio - ) extends SimMemIO { +class SimAXI4MemIO extends SimMemIO { def matchType(data: Data) = data match { case channel: AXI4Bundle => directionOf(channel.w.valid) == ActualDirection.Output diff --git a/src/main/scala/midas/core/FPGATop.scala b/src/main/scala/midas/core/FPGATop.scala index ad7d481c..6da8c532 100644 --- a/src/main/scala/midas/core/FPGATop.scala +++ b/src/main/scala/midas/core/FPGATop.scala @@ -164,14 +164,12 @@ class FPGATop(simIoType: SimWrapperIO)(implicit p: Parameters) extends Module wi } // each widget should have its own reset queue - val resetQueue = Module(new WireChannel(1, endpoint.clockRatio)) - resetQueue.io.traceLen := DontCare - resetQueue.io.trace.ready := DontCare + val resetQueue = Module(new Queue(Bool(), 4)) resetQueue.reset := reset.toBool || simReset - widget.io.tReset <> resetQueue.io.out - resetQueue.io.in.bits := defaultIOWidget.io.tReset.bits - resetQueue.io.in.valid := defaultIOWidget.io.tReset.valid - ready && resetQueue.io.in.ready + widget.io.tReset <> resetQueue.io.deq + resetQueue.io.enq.bits := defaultIOWidget.io.tReset.bits + resetQueue.io.enq.valid := defaultIOWidget.io.tReset.valid + ready && resetQueue.io.enq.ready } } diff --git a/src/main/scala/midas/core/SimWrapper.scala b/src/main/scala/midas/core/SimWrapper.scala index 0fde21d7..3794e1f9 100644 --- a/src/main/scala/midas/core/SimWrapper.scala +++ b/src/main/scala/midas/core/SimWrapper.scala @@ -252,18 +252,7 @@ class SimWrapper(targetIo: Seq[Data]) arg match { case (port, name) => (0 until getChunks(port)) map { off => val width = scala.math.min(channelWidth, port.getWidth - off * channelWidth) - // Figure out the clock ratio by looking up the endpoint to which this wire belongs - val endpointClockRatio = io.endpoints.find(_(port)) match { - case Some(endpoint) => endpoint.clockRatio - case None => UnityClockRatio - } - - // A channel is considered "flipped" if it's sunk by the tranformed RTL (sourced by an endpoint) - val flipped = directionOf(port) == ActualDirection.Input - val channel = Module(new WireChannel( - width, - clockRatio = if (flipped) endpointClockRatio.inverse else endpointClockRatio - )) + val channel = Module(new WireChannel(width)) // FIXME: it's not working /* port match { case _: Reset => @@ -315,28 +304,14 @@ class SimWrapper(targetIo: Seq[Data]) } def genReadyValidChannel[T <: Data](arg: (String, ReadyValidIO[T])) = - arg match { case (name, rvInterface) => - // Determine which endpoint this channel belongs to by looking it up with the valid - val endpointClockRatio = io.endpoints.find(_(rvInterface.valid)) match { - case Some(endpoint) => endpoint.clockRatio - case None => UnityClockRatio - } - // A channel is considered "flipped" if it's sunk by the tranformed RTL (sourced by an endpoint) - val flipped = directionOf(rvInterface.valid) == ActualDirection.Input + arg match { case (name, io) => val channel = Module(new ReadyValidChannel( - rvInterface.bits.cloneType, - flipped, - clockRatio = if (flipped) endpointClockRatio.inverse else endpointClockRatio - )) - + io.bits.cloneType, directionOf(io.valid) == ActualDirection.Input)) channel suggestName s"ReadyValidChannel_$name" - - if (flipped) { - rvInterface <> channel.io.deq.target - } else { - channel.io.enq.target <> rvInterface + (directionOf(io.valid): @unchecked) match { + case ActualDirection.Input => io <> channel.io.deq.target + case ActualDirection.Output => channel.io.enq.target <> io } - if (!enableSnapshot) channel.io.trace := DontCare channel.io.targetReset.bits := targetReset channel.io.targetReset.valid := fire @@ -347,7 +322,7 @@ class SimWrapper(targetIo: Seq[Data]) // Firing condtion: // 1) all input values are valid // 2) all output FIFOs are not full - fire := (wireInChannels foldLeft true.B)(_ && _.io.out.valid) && + fire := (wireInChannels foldLeft true.B)(_ && _.io.out.valid) && (wireOutChannels foldLeft true.B)(_ && _.io.in.ready) && (readyValidInChannels foldLeft true.B)(_ && _.io.deq.host.hValid) && (readyValidOutChannels foldLeft true.B)(_ && _.io.enq.host.hReady) @@ -356,8 +331,7 @@ class SimWrapper(targetIo: Seq[Data]) wireInChannels foreach (_.io.out.ready := fire) readyValidInChannels foreach (_.io.deq.host.hReady := fire) - // Outputs should be ready when firing conditions are met, inject an intial - // token into each output queue after reset is asserted + // Outputs should be ready when firing conditions are met val resetNext = RegNext(reset.toBool) wireOutChannels foreach (_.io.in.valid := fire || resetNext) readyValidOutChannels foreach (_.io.enq.host.hValid := fire || resetNext)