Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a unified emulator for both IP and subsystem. #487

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ object emuhelper extends EmuHelper

trait EmuHelper
extends millbuild.common.EmuHelperModule {
override def millSourcePath = os.pwd / "emulator" / "emuhelper"

def scalaVersion = T(v.scala)

def chiselModule = Some(chisel)
Expand All @@ -217,6 +219,8 @@ object ipemu extends IPEmulator

trait IPEmulator
extends millbuild.common.IPEmulatorModule {
override def millSourcePath = os.pwd / "emulator" / "ipemu"

def scalaVersion = T(v.scala)

def t1Module = t1
Expand Down
90 changes: 90 additions & 0 deletions emulator/csrc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 17)

option(IPEMU "configure to ip emulator(spike as scalar core)" OFF)
option(SUBSYSTEMEMU "configure to subsystem emulator(rocket as scalar core)" OFF)
option(VERILATE_TRACE "enable verilator trace" OFF)

if (${IPEMU})
project(ipemu)
elseif (${SUBSYSTEMEMU})
project(subsystememu)
else()
message(FATAL_ERROR "either IPEMU or SUBSYSTEMEMU should be defined via -D")
endif()

# read VERILATE_SRC_DIR from args, else read from environment
if (NOT DEFINED VERILATE_SRC_DIR)
set(VERILATE_SRC_DIR "$ENV{VERILATE_SRC_DIR}")
if (VERILATE_SRC_DIR STREQUAL "")
message(FATAL_ERROR "You should specify rtl directory via -DVERILATE_SRC_DIR or environment variable VERILATE_SRC_DIR, but it seems not")
endif()
endif()
set(VERILATE_ARGS
# TODO: configurable top name?
TOP_MODULE TestBench
PREFIX VTestBench
OPT_FAST
# TODO: configurable threads?
THREADS 8
VERILATOR_ARGS --x-initial unique --output-split 2048 --max-num-width 1048576 --threads-max-mtasks 100000 --main --timing --assert
)
if (${VERILATE_TRACE})
list(PREPEND VERILATE_ARGS "TRACE_FST")
endif()

# parse filelist.f into VERILATE_SRC_LIST
file(READ "${VERILATE_SRC_DIR}/filelist.f" filelist_content)
string(REPLACE "\n" ";" VERILATE_SRC_LIST "${filelist_content}") # transform lines into a list
list(FILTER VERILATE_SRC_LIST EXCLUDE REGEX "^$") # filter out empty lines
list(TRANSFORM VERILATE_SRC_LIST PREPEND "${VERILATE_SRC_DIR}/") # add base directory prefix

message(STATUS "Project '${PROJECT_NAME}' build type: ${CMAKE_BUILD_TYPE}")

find_package(args REQUIRED)
find_package(spdlog REQUIRED)
find_package(fmt REQUIRED)
find_package(verilator REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(Threads REQUIRED)
find_package(dramsim3 REQUIRED)
if (${IPEMU})
find_package(libspike REQUIRED)
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON)

if (${IPEMU})
add_executable(ipemu
spike_event.cc
spdlog_ext.cc
ipemu.cc
dpi.cc
memory.cc
)
target_link_libraries(ipemu PUBLIC ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(ipemu PUBLIC libspike fmt::fmt spdlog::spdlog nlohmann_json::nlohmann_json dramsim3 taywee::args)
target_compile_definitions(ipemu PRIVATE COSIM_VERILATOR)
target_compile_definitions(ipemu PRIVATE IPEMU)
verilate(ipemu
SOURCES ${VERILATE_SRC_LIST}
${VERILATE_ARGS}
)
install(TARGETS ipemu RUNTIME)
endif()

if (${SUBSYSTEMEMU})
add_executable(subsystememu
)
target_link_libraries(subsystememu PUBLIC ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(subsystememu PUBLIC fmt::fmt spdlog::spdlog nlohmann_json::nlohmann_json dramsim3 taywee::args)
target_compile_definitions(subsystememu PRIVATE COSIM_VERILATOR)
target_compile_definitions(subsystememu PRIVATE IPEMU)

verilate(subsystememu
SOURCES ${VERILATE_SRC_LIST}
${VERILATE_ARGS}
)
install(TARGETS subsystememu RUNTIME)
endif()


170 changes: 170 additions & 0 deletions emulator/csrc/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#pragma once

#include <condition_variable>
#include <list>
#include <mutex>
#include <optional>
#include <queue>
#include <thread>
#include <utility>
#include <string>
#include <args.hxx>
#include "spdlog_ext.h"


class Config {
public:
explicit Config() {
std::ifstream cmdline("/proc/self/cmdline");
std::vector<std::string> arg_vec;
for (std::string line; std::getline(cmdline, line, '\0');) {
arg_vec.emplace_back(line);
}
std::vector<const char *> argv;
argv.reserve(arg_vec.size());
for (const auto &arg: arg_vec) {
argv.emplace_back(arg.c_str());
}

args::ArgumentParser parser("emulator for t1");

args::Flag no_logging(parser, "no_logging", "Disable all logging utilities.", {"no-logging"});
args::Flag no_file_logging(parser, "no_file_logging", "Disable file logging utilities.", {"no-file-logging"});
args::Flag no_console_logging(parser, "no_console_logging", "Disable console logging utilities.",
{"no-console-logging"});
args::ValueFlag<std::string> log_path(parser, "log path", "Path to store logging file", {"log-path"});

args::ValueFlag<size_t> vlen(parser, "vlen", "match from RTL config, tobe removed", {"vlen"},
args::Options::Required);
args::ValueFlag<size_t> dlen(parser, "dlen", "match from RTL config, tobe removed", {"dlen"},
args::Options::Required);
args::ValueFlag<size_t> tl_bank_number(parser, "tl_bank_number", "match from RTL config, tobe removed",
{"tl_bank_number"}, args::Options::Required);
args::ValueFlag<size_t> beat_byte(parser, "beat_byte", "match from RTL config, tobe removed", {"beat_byte"},
args::Options::Required);

args::ValueFlag<std::string> bin_path(parser, "elf path", "", {"elf"}, args::Options::Required);
args::ValueFlag<std::string> wave_path(parser, "wave path", "", {"wave"}, args::Options::Required);
args::ValueFlag<std::optional<std::string>> perf_path(parser, "perf path", "", {"perf"});
args::ValueFlag<uint64_t> timeout(parser, "timeout", "", {"timeout"}, args::Options::Required);
#if VM_TRACE
args::ValueFlag<uint64_t> dump_from_cycle(parser, "dump_from_cycle", "start to dump wave at cycle", {"dump-from-cycle"}, args::Options::Required);
#endif
args::ValueFlag<double> tck(parser, "tck", "", {"tck"}, args::Options::Required);
args::Group dramsim_group(parser, "dramsim config", args::Group::Validators::AllOrNone);
args::ValueFlag<std::optional<std::string>> dramsim3_config_path(dramsim_group, "config path", "",
{"dramsim3-config"});
args::ValueFlag<std::optional<std::string>> dramsim3_result_dir(dramsim_group, "result dir", "",
{"dramsim-result"});

try {
parser.ParseCLI((int) argv.size(), argv.data());
} catch (args::Help &) {
std::cerr << parser;
std::exit(0);
} catch (args::Error &e) {
std::cerr << e.what() << std::endl << parser;
std::exit(1);
}
Log = JsonLogger(no_logging.Get(), no_file_logging.Get(), no_console_logging.Get(), log_path.Get());

Config(
bin_path.Get(),
wave_path.Get(),
perf_path.Get(),
timeout.Get(),
#if VM_TRACE
dump_from_cycle(dump_from_cycle.Get(),
#endif
tck.Get(),
dramsim3_config_path.Get(),
dramsim3_result_dir.Get(),
vlen.Get(),
dlen.Get(),
tl_bank_number.Get(),
// TODO: clean me up
32,
dlen.Get() / 32,
32,
32,
3,
255,
vlen.Get() / 8,
beat_byte.Get()
);
}

public:
Config(
std::string binPath,
std::string wavePath,
const std::optional<std::string> perfPath,
uint64_t timeout,
#if VM_TRACE
uint64_t dumpFromCycle,
#endif
double tck,
const std::optional<std::string> &dramsim3ConfigPath,
const std::optional<std::string> &dramsim3ResultDir,
size_t vlen,
size_t dlen,
size_t tlBankNumber,
size_t datapathWidth,
size_t laneNumber,
size_t elen,
size_t vregNumber,
size_t mshrNumber,
size_t lsuIdxDefault,
size_t vlenInBytes,
size_t datapathWidthInBytes
)
:
bin_path(std::move(binPath)),
wave_path(std::move(wavePath)),
perf_path(perfPath),
timeout(timeout),
#if VM_TRACE
dump_from_cycle(dumpFromCycle),
#endif
tck(tck),
dramsim3_config_path(dramsim3ConfigPath),
dramsim3_result_dir(dramsim3ResultDir),
vlen(vlen),
dlen(dlen),
tl_bank_number(tlBankNumber),
datapath_width(datapathWidth),
lane_number(laneNumber),
elen(elen),
vreg_number(vregNumber),
mshr_number(mshrNumber),
lsu_idx_default(lsuIdxDefault),
vlen_in_bytes(vlenInBytes),
datapath_width_in_bytes(datapathWidthInBytes) {};

std::string bin_path;
std::string wave_path;
std::optional<std::string> perf_path;
uint64_t timeout{};

#ifdef VM_TRACE
uint64_t dump_from_cycle{};
#endif

double tck{};
std::optional<std::string> dramsim3_config_path;
std::optional<std::string> dramsim3_result_dir;
// TODO: move these configs to compiler time after t1 support OM:
// TODO: these are unused parameters
size_t vlen{};
size_t dlen{};
size_t tl_bank_number{};

size_t datapath_width{};
size_t lane_number{};
size_t elen{};
size_t vreg_number{};
size_t mshr_number{};
size_t lsu_idx_default{};
size_t vlen_in_bytes{};
size_t datapath_width_in_bytes{};
};
5 changes: 3 additions & 2 deletions ipemu/csrc/dpi.cc → emulator/csrc/dpi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#include "encoding.h"
#include "exceptions.h"
#include "svdpi.h"
#include "vbridge_impl.h"
// TODO: add macro
#include "ipemu.h"

static bool terminated = false;

Expand Down Expand Up @@ -38,7 +39,7 @@ void sigint_handler(int s) {
}

#if VM_TRACE
void VBridgeImpl::dpiDumpWave() {
void T1IPEmulator::dpiDumpWave() {
TRY({
svSetScope(
svGetScopeFromName("TOP.TestBench.verificationModule.dpiDumpWave"));
Expand Down
45 changes: 4 additions & 41 deletions ipemu/csrc/encoding.h → emulator/csrc/encoding.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
#ifdef IPEMU
#pragma once

#include <svdpi.h>
#include "tilelink.h"

// Write this CSR to end simulation.
// TODO: no maintaining it anymore? just wait finish
constexpr uint32_t CSR_MSIMEND = 0x7cc;

namespace TlOpcode {
constexpr int Get = 4, AccessAckData = 1, PutFullData = 0, PutPartialData = 1,
AccessAck = 0;
}

struct VCsrInterfacePoke {
svBitVecVal *vl;
svBitVecVal *vStart;
Expand All @@ -21,36 +18,6 @@ struct VCsrInterfacePoke {
svBit *ignoreException;
};

struct VTlInterface {
uint32_t channel_id;
svBitVecVal a_bits_opcode;
svBitVecVal a_bits_param;
svBitVecVal a_bits_size;
svBitVecVal a_bits_source;
svBitVecVal a_bits_address;
const svBitVecVal *a_bits_mask;
const svBitVecVal *a_bits_data;
svBit a_corrupt;
svBit a_valid;
svBit d_ready;
};

struct VTlInterfacePoke {
uint32_t channel_id;
svBitVecVal *d_bits_opcode;
svBitVecVal *d_bits_param;
svBitVecVal *d_bits_size;
svBitVecVal *d_bits_source;
svBitVecVal *d_bits_sink;
svBit *d_bits_denied;
svBitVecVal *d_bits_data;
svBit *d_corrupt;
svBit *d_valid;
svBit *a_ready;

svBit d_ready;
};

struct VInstrInterfacePoke {
svBitVecVal *inst;
svBitVecVal *src1Data;
Expand All @@ -64,11 +31,6 @@ struct VRespInterface {
svBit vxsat;
};

struct VInstrFire {
svBit ready;
svBitVecVal index;
};

struct VLsuWriteQueuePeek {
uint32_t mshr_index;
svBit write_valid;
Expand All @@ -93,3 +55,4 @@ struct VrfWritePeek {
struct VLsuReqEnqPeek {
svBitVecVal enq;
};
#endif
5 changes: 0 additions & 5 deletions ipemu/csrc/exceptions.h → emulator/csrc/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ class CosimException : public std::runtime_error {
explicit CosimException(const char *what) : runtime_error(what) {}
};

class TimeoutException : CosimException {
public:
TimeoutException() : CosimException("timeout") {}
};

class ReturnException : CosimException {
public:
ReturnException() : CosimException("returned") {}
Expand Down
Loading
Loading