Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ doc/html
*.data*
*.txt
emu/obj*
*.fst
*.fst.hier
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "ready-to-run"]
path = ready-to-run
url = git@github.com:jaypiper/gsim-ready-to-run.git
url = http://github.com/jaypiper/gsim-ready-to-run.git
63 changes: 49 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ else ifeq ($(dutName),large-boom)
NAME ?= TestHarness
TEST_FILE = $(NAME)-LargeBoom
GSIM_FLAGS += --supernode-max-size=65 --cpp-max-size-KB=4096
VERI_THREADS = --threads 5
VERI_THREADS = --threads 4
else ifeq ($(dutName),small-boom)
NAME ?= TestHarness
TEST_FILE = $(NAME)-SmallBoom
GSIM_FLAGS += --supernode-max-size=90 --cpp-max-size-KB=4096
VERI_THREADS = --threads 5
VERI_THREADS = --threads 4
else ifeq ($(dutName),minimal-xiangshan)
NAME ?= SimTop
TEST_FILE = $(NAME)-xiangshan-minimal
GSIM_FLAGS += --supernode-max-size=60 --cpp-max-size-KB=8192
VERI_THREADS = --threads 16
VERI_THREADS = --threads 4
else ifeq ($(dutName),default-xiangshan)
NAME ?= SimTop
TEST_FILE = $(NAME)-xiangshan-default
GSIM_FLAGS += --supernode-max-size=2 --cpp-max-size-KB=8192
VERI_THREADS = --threads 16
VERI_THREADS = --threads 4
endif

##############################################
Expand All @@ -49,13 +49,18 @@ endif
BUILD_DIR ?= build
WORK_DIR = $(BUILD_DIR)/$(dutName)
CXX = clang++
CC = clang

SHELL := /bin/bash
TIME = /usr/bin/time
LOG_FILE = $(WORK_DIR)/$(dutName).log

CFLAGS_DUT = -DDUT_NAME=S$(NAME) -DDUT_HEADER=\"$(NAME).h\" -D__DUT_$(shell echo $(dutName) | tr - _)__

# FST_CFLAGS = -DFST_WAVE -I$(abspath include/libfst)
FST_CFLAGS = -I$(abspath include/libfst)
FST_LDFLAGS = -L$(abspath $(BUILD_DIR)/gsim/libfst) -lfst -lz

# $(1): object file
# $(2): source file
# $(3): compile flags (for linker flags, use -Xlinker --xxx instead of -Wl,--xxx)
Expand Down Expand Up @@ -129,9 +134,24 @@ PARSER_GEN_SRCS = $(foreach x, $(LEXICAL_NAME) $(SYNTAX_NAME), $(PARSER_BUILD_DI
PARSER_GEN_HEADER = $(PARSER_BUILD_DIR)/$(SYNTAX_NAME).hh
GSIM_SRCS = $(foreach x, src $(PARSER_DIR), $(wildcard $(x)/*.cpp))

GSIM_INC_DIR = include $(PARSER_DIR)/include $(PARSER_BUILD_DIR)
GSIM_INC_DIR = include $(PARSER_DIR)/include $(PARSER_BUILD_DIR) include/libfst
CXXFLAGS += -ggdb -O3 -MMD $(addprefix -I,$(GSIM_INC_DIR)) -Wall -Werror --std=c++17

LDLIBS = -lz

LIBFST_DIR = include/libfst
CFLAGS_LIBFST = -ggdb -O3 -MMD $(addprefix -I,$(GSIM_INC_DIR)) -Wall
LIBFST_SRCS = $(wildcard $(LIBFST_DIR)/*.c)
LIBFST_OBJS = $(patsubst %.c,$(GSIM_BUILD_DIR)/libfst/%.o,$(notdir $(LIBFST_SRCS)))
LIBFST_A = $(GSIM_BUILD_DIR)/libfst/libfst.a

$(GSIM_BUILD_DIR)/libfst/%.o: $(LIBFST_DIR)/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS_LIBFST) -c $< -o $@

$(LIBFST_A): $(LIBFST_OBJS)
ar rcs $@ $^

ifeq ($(DEBUG),1)
CXXFLAGS += -DDEBUG
endif
Expand All @@ -150,9 +170,9 @@ $(foreach x, $(PARSER_GEN_SRCS), $(eval \
$(call CXX_TEMPLATE, $(PARSER_BUILD_DIR)/$(basename $(notdir $(x))).o, $(x), $(CXXFLAGS), GSIM_OBJS, $(PARSER_GEN_HEADER))))

$(foreach x, $(GSIM_SRCS), $(eval \
$(call CXX_TEMPLATE, $(GSIM_BUILD_DIR)/$(basename $(x)).o, $(x), $(CXXFLAGS), GSIM_OBJS, $(PARSER_GEN_HEADER))))
$(call CXX_TEMPLATE, $(GSIM_BUILD_DIR)/$(basename $(x)).o, $(x), $(CXXFLAGS) $(FST_CFLAGS), GSIM_OBJS, $(PARSER_GEN_HEADER))))

$(eval $(call LD_TEMPLATE, $(GSIM_BIN), $(GSIM_OBJS), $(CXXFLAGS) -lgmp))
$(eval $(call LD_TEMPLATE, $(GSIM_BIN), $(GSIM_OBJS) $(LIBFST_A), $(CXXFLAGS) -lgmp $(FST_LDFLAGS)))

build-gsim: $(GSIM_BIN)

Expand All @@ -172,7 +192,6 @@ $(GEN_CPP_DIR)/$(NAME)0.cpp: $(GSIM_BIN) $(FIRRTL_FILE)
@mkdir -p $(@D)
set -o pipefail && $(TIME) $(GSIM_BIN) $(GSIM_FLAGS) --dir $(@D) \
$(GSIM_FLAGS_EXTRA) $(FIRRTL_FILE) | tee $(BUILD_DIR)/gsim.log
$(SIG_COMMAND)

compile: $(GEN_CPP_DIR)/$(NAME)0.cpp

Expand All @@ -194,19 +213,23 @@ EMU_GEN_SRCS = $(shell find $(GEN_CPP_DIR) -name "*.cpp" 2> /dev/null)
EMU_SRCS = $(EMU_MAIN_SRCS) $(EMU_GEN_SRCS)

EMU_CFLAGS := -O1 -MMD $(addprefix -I, $(abspath $(GEN_CPP_DIR))) $(EMU_CFLAGS) # allow to overwrite optimization level
EMU_CFLAGS += $(MODE_FLAGS) $(CFLAGS_DUT) -Wno-parentheses-equality
EMU_CFLAGS += $(MODE_FLAGS) $(CFLAGS_DUT) -Wno-parentheses-equality -Wno-unknown-warning-option
EMU_CFLAGS += -fbracket-depth=2048
EMU_CFLAGS += $(FST_CFLAGS)
#EMU_CFLAGS += -fsanitize=address -fsanitize-address-use-after-scope
#EMU_CFLAGS += -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract
#EMU_CFLAGS += -pg -ggdb
ifeq ($(SIMPOINT),1)
EMU_LDFLAGS += -lz -lzstd
endif
EMU_LDFLAGS += $(FST_LDFLAGS)

$(foreach x, $(EMU_SRCS), $(eval \
$(call CXX_TEMPLATE, $(EMU_BUILD_DIR)/$(basename $(notdir $(x))).o, $(x), $(EMU_CFLAGS), EMU_OBJS,)))

$(eval $(call LD_TEMPLATE, $(EMU_BIN), $(EMU_OBJS), $(EMU_CFLAGS) $(EMU_LDFLAGS)))
$(EMU_BIN): $(EMU_OBJS) $(LIBFST_A)
@mkdir -p $(@D) && echo + LD $@
@$(CXX) $^ $(EMU_CFLAGS) $(EMU_LDFLAGS) -o $@

build-emu: $(EMU_BIN)

Expand Down Expand Up @@ -240,7 +263,8 @@ VERI_GEN_MK = $(VERI_BUILD_DIR)/V$(NAME).mk

VERI_CFLAGS = $(call escape_quote,$(EMU_CFLAGS) $(CFLAGS_REF))
VERI_LDFLAGS = -O1
VERI_VFLAGS = --top $(NAME) -Wno-lint -j 8 --cc --exe +define+RANDOMIZE_GARBAGE_ASSIGN --max-num-width 1048576 --compiler clang
VERI_LDFLAGS += $(FST_LDFLAGS)
VERI_VFLAGS = --top $(NAME) -Wno-lint -O0 -j 8 --cc --exe +define+RANDOMIZE_GARBAGE_ASSIGN --max-num-width 1048576 --compiler clang
ifeq ($(SIMPOINT),1)
VERI_LDFLAGS += -lz -lzstd
endif
Expand All @@ -251,15 +275,18 @@ VERI_VFLAGS += $(VERI_THREADS)
VERI_VSRCS = ready-to-run/difftest/$(TEST_FILE).sv
VERI_CSRCS-2 = $(EMU_GEN_SRCS)

$(VERI_GEN_MK): $(VERI_VSRCS) $(VERI_CSRCS-$(MODE)) | $(EMU_MAIN_SRCS)
$(VERI_GEN_MK): $(VERI_VSRCS) $(VERI_CSRCS-$(MODE)) $(LIBFST_A) | $(EMU_MAIN_SRCS)
@mkdir -p $(@D)
verilator $(VERI_VFLAGS) $(abspath $^ $|)
verilator $(VERI_VFLAGS) $(abspath $(VERI_VSRCS) $(VERI_CSRCS-$(MODE)) $|)

$(VERI_BIN): | $(VERI_GEN_MK)
$(TIME) $(MAKE) OPT_FAST="-O1" CXX=clang++ -s -C $(VERI_BUILD_DIR) -f $(abspath $|)
ln -sf $(abspath $(VERI_BUILD_DIR)/V$(NAME)) $@

compile-veri: $(VERI_GEN_MK)
ifeq ($(MODE), 2)
$(SIG_COMMAND)
endif

run-veri-simpoint: $(VERI_BIN)
@echo 'Please run "$^ <gcpt> <checkpoint>" manually'
Expand Down Expand Up @@ -352,8 +379,8 @@ run-internal:
$(MAKE) MODE=0 difftest

diff-internal:
$(MAKE) MODE=2 compile-veri
$(MAKE) MODE=2 compile
$(MAKE) MODE=2 compile-veri
$(MAKE) MODE=2 difftest

run:
Expand Down Expand Up @@ -388,3 +415,11 @@ format-obj:
@clang-format -i --style=file obj/$(NAME).cpp

.PHONY: clean run-internal diff-internal run diff init perf count gendoc format-obj

$(EMU_EXE): $(EMU_OBJS) $(WORK_OBJS) $(LIBFST_A)
@mkdir -p $(@D)
$(CXX) $(LDFLAGS) $^ -o $@ $(LDLIBS)

# LDFLAGS
LDFLAGS ?=
LDFLAGS += -lz
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ GSIM accepts chirrtl, and compiles it to C++

+ Install [GMP](https://gmplib.org/), [clang 19(+)](https://clang.llvm.org/).

## Quike Start
## Quick Start

+ GSIM provides 4 RISC-V cores ready for simulation: [ysyx3](https://ysyx.oscc.cc/), [Rocket](https://github.com/chipsalliance/rocket-chip), [BOOM](https://github.com/riscv-boom/riscv-boom), [XiangShan](https://github.com/OpenXiangShan/XiangShan).

Expand All @@ -23,3 +23,19 @@ GSIM accepts chirrtl, and compiles it to C++
+ Run `build/gsim/gsim $(chirrtl-file)` to compile chirrtl to C++
+ Refer to `build/gsim/gsim --help` for more information
+ See [C++ harness example](https://github.com/jaypiper/simulator/blob/master/emu/emu.cpp) to know how it interacts with the emitted C++ code.

## FST Waveform Generation

GSIM supports FST waveform generation for debugging and analysis. You can control this feature via Makefile:

+ **Enable FST waveform**: Add `-DFST_WAVE` to `FST_CFLAGS` in Makefile
```
FST_CFLAGS = -DFST_WAVE -I$(abspath include/libfst)
```

+ **Disable FST waveform**: Remove `-DFST_WAVE` from `FST_CFLAGS`
```
FST_CFLAGS = -I$(abspath include/libfst)
```

When enabled, the generated C++ model will produce `.fst` waveform files that can be viewed with tools like GTKWave.
103 changes: 69 additions & 34 deletions emu/emu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,62 @@

#define CYCLE_STEP_PERCENT 1



template<typename T>
void* getDutMemory(T* dut) {
#if defined(__DUT_ysyx3__)
return (void*)&dut->mem_ram;
#elif defined(__DUT_NutShell__)
return (void*)&dut->mem_rdata_mem_mem;
#elif defined(__DUT_rocket__)
return (void*)&dut->mem_srams_mem;
#elif defined(__DUT_large_boom__) || defined(__DUT_small_boom__)
return (void*)&dut->mem_srams_mem;
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
return (void*)&dut->memory_ram_rdata_mem_mem;
#else
return nullptr;
#endif
}

template<typename T>
void* getRefMemory(T* ref) {
#if defined(__DUT_ysyx3__)
return (void*)&ref->rootp->__PVT__newtop->__PVT__mem->__PVT__ram_ext->__PVT__Memory;
#elif defined(__DUT_NutShell__)
return (void*)&ref->rootp->__PVT__SimTop->__PVT__mem->__PVT__rdata_mem->__PVT__mem_ext->__PVT__Memory;
#elif defined(__DUT_rocket__)
return (void*)&ref->rootp->__PVT__TestHarness->__PVT__mem->__PVT__srams->__PVT__mem_ext->__PVT__Memory;
#elif defined(__DUT_large_boom__) || defined(__DUT_small_boom__)
return (void*)&ref->rootp->__PVT__TestHarness->__PVT__mem->__PVT__srams->__PVT__mem_ext->__PVT__Memory;
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
return (void*)&ref->rootp->__PVT__SimTop->__PVT__memory->__PVT__ram->__PVT__rdata_mem->__PVT__mem_ext->__PVT__Memory;
#else
return nullptr;
#endif
}

#define GET_DUT_MEMORY(dut, mem) getDutMemory(dut)
#define GET_REF_MEMORY(ref, path) getRefMemory(ref)

#if defined(__DUT_ysyx3__)
#define DUT_MEMORY mem$ram
#define REF_MEMORY newtop__DOT__mem__DOT__ram_ext__DOT__Memory
#define CYCLE_MAX_PERF 5000000
#define CYCLE_MAX_SIM 11000000
#elif defined(__DUT_NutShell__)
#define DUT_MEMORY mem$rdata_mem$mem
#define REF_MEMORY SimTop__DOT__mem__DOT__rdata_mem__DOT__mem_ext__DOT__Memory
#define CYCLE_MAX_PERF 50000000
#define CYCLE_MAX_SIM 250000000
#elif defined(__DUT_rocket__)
#define DUT_MEMORY mem$srams$mem
#define REF_MEMORY TestHarness__DOT__mem__DOT__srams__DOT__mem_ext__DOT__Memory
#define CYCLE_MAX_PERF 2000000
#define CYCLE_MAX_SIM 4200000
#elif defined(__DUT_large_boom__) || defined(__DUT_small_boom__)
#define DUT_MEMORY mem$srams$mem
#define REF_MEMORY TestHarness__DOT__mem__DOT__srams__DOT__mem_ext__DOT__Memory
#define CYCLE_MAX_PERF 1000000
#ifdef __DUT_large_boom__
#define CYCLE_MAX_SIM 3900000
#else
#define CYCLE_MAX_SIM 5400000
#endif
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
#define DUT_MEMORY memory$ram$rdata_mem$mem
#define REF_MEMORY SimTop__DOT__memory__DOT__ram__DOT__rdata_mem__DOT__mem_ext__DOT__Memory
#define CYCLE_MAX_PERF 500000
#ifdef __DUT_default_xiangshan__
#define CYCLE_MAX_SIM 1900000
Expand Down Expand Up @@ -98,28 +127,26 @@ static DUT_NAME* dut;

void dut_init(DUT_NAME *dut) {
#if defined(__DUT_NutShell__)
dut->set_difftest$$logCtrl$$begin(0);
dut->set_difftest$$logCtrl$$end(0);
dut->set_difftest$$uart$$in$$ch(-1);
dut->set_difftest__uart__in__ch(-1);
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
// dut->set_difftest$$perfCtrl$$clean(0);
// dut->set_difftest$$perfCtrl$$dump(0);
// dut->set_difftest$$logCtrl$$begin(0);
// dut->set_difftest$$logCtrl$$end(0);
// dut->set_difftest$$logCtrl$$level(0);
dut->set_difftest$$uart$$in$$ch(-1);
// dut->set_difftest__perfCtrl__clean(0);
// dut->set_difftest__perfCtrl__dump(0);
// dut->set_difftest__logCtrl__begin(0);
// dut->set_difftest__logCtrl__end(0);
// dut->set_difftest__logCtrl__level(0);
dut->set_difftest__uart__in__ch(-1);
#endif
}

void dut_hook(DUT_NAME *dut) {
#if defined(__DUT_NutShell__)
if (dut->get_difftest$$uart$$out$$valid()) {
printf("%c", dut->get_difftest$$uart$$out$$ch());
if (dut->get_difftest__uart__out__valid()) {
printf("%c", dut->get_difftest__uart__out__ch());
fflush(stdout);
}
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
if (dut->get_difftest$$uart$$out$$valid()) {
printf("%c", dut->get_difftest$$uart$$out$$ch());
if (dut->get_difftest__uart__out__valid()) {
printf("%c", dut->get_difftest__uart__out__ch());
fflush(stdout);
}
#endif
Expand All @@ -133,8 +160,9 @@ static REF_NAME* ref;

void ref_init(REF_NAME *ref) {
#if defined(__DUT_NutShell__)
ref->rootp->difftest_logCtrl_begin = ref->rootp->difftest_logCtrl_begin = 0;
ref->rootp->difftest_uart_in_valid = -1;
ref->difftest_perfCtrl_clean = ref->difftest_perfCtrl_dump = 0;
ref->difftest_uart_in_ch = -1;
ref->difftest_uart_in_valid = 0;
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
ref->difftest_perfCtrl_clean = ref->difftest_perfCtrl_dump = 0;
ref->difftest_uart_in_ch = -1;
Expand All @@ -144,8 +172,8 @@ void ref_init(REF_NAME *ref) {

void ref_hook(REF_NAME *ref) {
#if defined(__DUT_NutShell__)
if (ref->rootp->difftest_uart_out_valid) {
printf("%c", ref->rootp->difftest_uart_out_ch);
if (ref->difftest_uart_out_valid) {
printf("%c", ref->difftest_uart_out_ch);
fflush(stdout);
}
#elif defined(__DUT_minimal_xiangshan__) || defined(__DUT_default_xiangshan__)
Expand Down Expand Up @@ -232,19 +260,19 @@ int main(int argc, char** argv) {
load_program(argv[1]);
#ifdef GSIM
dut = new DUT_NAME();
memcpy(&dut->DUT_MEMORY, program, program_sz);
memcpy(GET_DUT_MEMORY(dut, DUT_MEMORY), program, program_sz);
dut_init(dut);
dut_reset();
#endif
#ifdef VERILATOR
ref = new REF_NAME();
memcpy(&ref->rootp->REF_MEMORY, program, program_sz);
memcpy(GET_REF_MEMORY(ref, REF_MEMORY_PATH), program, program_sz);
ref_init(ref);
ref_reset();
#endif
#ifdef GSIM_DIFF
ref = new REF_NAME();
memcpy(&ref->DUT_MEMORY, program, program_sz);
memcpy(GET_DUT_MEMORY(ref, DUT_MEMORY), program, program_sz);
ref_reset();
#endif
close_program();
Expand Down Expand Up @@ -284,8 +312,9 @@ int main(int argc, char** argv) {
if (cycles % (CYCLE_MAX_SIM / (CYCLE_STEP_PERCENT * 100)) == 0 && cycles <= CYCLE_MAX_SIM) {
auto dur = std::chrono::system_clock::now() - start;
auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
fprintf(stderr, "cycles %ld (%ld ms, %ld per sec) simulation process %.2lf%% \n",
cycles, msec.count(), cycles * 1000 / msec.count(), (double)cycles * 100 / CYCLE_MAX_SIM);
long long ips = msec.count() == 0 ? 0 : cycles * 1000 / msec.count();
fprintf(stderr, "cycles %ld (%ld ms, %lld per sec) simulation process %.2lf%% \n",
cycles, msec.count(), ips, (double)cycles * 100 / CYCLE_MAX_SIM);
#ifdef PERF
size_t totalActives = 0;
size_t validActives = 0;
Expand Down Expand Up @@ -315,9 +344,15 @@ int main(int argc, char** argv) {
}
#endif
#if defined(PERF) || defined(PERF_CYCLE)
if (cycles >= CYCLE_MAX_PERF) return 0;
if (cycles >= CYCLE_MAX_PERF) break;
#endif
if (cycles == CYCLE_MAX_SIM) return 0;
if (cycles == CYCLE_MAX_SIM) break;
}
}
#ifdef GSIM
delete dut;
#endif
#if (defined(VERILATOR) || defined(GSIM_DIFF)) && defined(GSIM)
delete ref;
#endif
}
Loading