More cleanly separate init/finish from host IF

This commit is contained in:
David Biancolin 2021-10-28 20:06:25 +00:00
parent 60310c6b8a
commit 6935b34285
11 changed files with 57 additions and 36 deletions

View File

@ -24,9 +24,10 @@ simif_t::simif_t() {
this->clock_bridge_mmio_addrs = CLOCKBRIDGEMODULE_0_substruct;
}
void simif_t::init(int argc, char** argv, bool log) {
void simif_t::init(int argc, char** argv) {
// Do any post-constructor initialization required before requesting MMIO
this->host_init(argc, argv);
while(!read(this->master_mmio_addrs->INIT_DONE));
this->log = log;
std::vector<std::string> args(argv + 1, argv + argc);
std::string loadmem;
bool fastloadmem = false;

View File

@ -44,20 +44,39 @@ class simif_t
public:
// Simulation APIs
virtual void init(int argc, char** argv, bool log = false);
virtual int finish() = 0;
virtual void init(int argc, char** argv);
inline bool done() { return read(this->master_mmio_addrs->DONE); }
inline void take_steps(size_t n, bool blocking) {
write(this->master_mmio_addrs->STEP, n);
if (blocking) while(!done());
}
// Host-platform interface. See simif_f1; simif_emul for implementation examples
// Performs platform-level initialization that for some reason or another
// cannot be done in the constructor. (For one, currently command line args
// are not passed to constructor).
virtual void host_init(int argc, char** argv) = 0;
// Does final platform-specific cleanup before destructors are called.
virtual int host_finish() = 0;
// Widget communication
// 32b MMIO, issued over the simulation control bus (AXI4-lite).
virtual void write(size_t addr, data_t data) = 0;
virtual data_t read(size_t addr) = 0;
// Bulk transfers / bridge streaming interfaces.
// Moves <bytes>B of data from a bridge FIFO at address <addr> (on the
// FPGA) to a buffer specified by <data>. FIFO addresses are emitted in the
// simulation header, and are in a distinct address space from MMIO.
virtual ssize_t pull(size_t addr, char *data, size_t size) = 0;
// Moves <bytes>B of data from the buffer <data> to a bridge FIFO at
// address <addr> (on the FPGA.
virtual ssize_t push(size_t addr, char *data, size_t size) = 0;
// End host-platform interface.
// LOADMEM functions
void read_mem(size_t addr, mpz_t& value);
void write_mem(size_t addr, mpz_t& value);

View File

@ -50,7 +50,7 @@ void handle_sigterm(int sig) {
simif_emul_t::~simif_emul_t() { }
void simif_emul_t::init(int argc, char** argv, bool log) {
void simif_emul_t::host_init(int argc, char** argv) {
// Parse args
std::vector<std::string> args(argv + 1, argv + argc);
std::string waveform = "dump.vcd";
@ -110,11 +110,9 @@ void simif_emul_t::init(int argc, char** argv, bool log) {
for (size_t i = 0 ; i < 10 ; i++) ::tick();
top->reset = 0;
#endif
simif_t::init(argc, argv, log);
}
int simif_emul_t::finish() {
int simif_emul_t::host_finish() {
::finish();
return 0;
}

View File

@ -17,8 +17,8 @@ class simif_emul_t : public virtual simif_t
public:
simif_emul_t() { }
virtual ~simif_emul_t();
virtual void init(int argc, char** argv, bool log = false);
virtual int finish();
virtual void host_init(int argc, char** argv);
virtual int host_finish();
virtual void write(size_t addr, data_t data);
virtual data_t read(size_t addr);

View File

@ -13,6 +13,11 @@ class simif_f1_t: public virtual simif_t
public:
simif_f1_t(int argc, char** argv);
virtual ~simif_f1_t();
// Unused by F1 since initialization / deinitization is done in the constructor
virtual void host_init(int argc, char** argv) {};
virtual int host_finish() { return 0; };
virtual void write(size_t addr, uint32_t data);
virtual uint32_t read(size_t addr);
virtual ssize_t pull(size_t addr, char* data, size_t size);

View File

@ -101,7 +101,7 @@ int fasedtests_top_t::exit_code(){
}
void fasedtests_top_t::run() {
int fasedtests_top_t::run() {
for (auto &e: fpga_models) {
e->init();
}
@ -115,8 +115,7 @@ void fasedtests_top_t::run() {
zero_out_dram();
}
fprintf(stderr, "Commencing simulation.\n");
uint64_t start_hcycle = hcycle();
uint64_t start_time = timestamp();
record_start_times();
while (!simulation_complete() && !has_timed_out()) {
run_scheduled_tasks();
@ -126,13 +125,10 @@ void fasedtests_top_t::run() {
}
}
uint64_t end_time = timestamp();
record_end_times();
fprintf(stderr, "\nSimulation complete.\n");
uint64_t end_cycle = actual_tcycle();
uint64_t hcycles = hcycle() - start_hcycle;
double sim_time = diff_secs(end_time, start_time);
double sim_speed = ((double) end_cycle) / (sim_time * 1000.0);
// always print a newline after target's output
fprintf(stderr, "\n");
int exitcode = exit_code();
if (exitcode) {
fprintf(stderr, "*** FAILED *** (code = %d) after %llu cycles\n", exitcode, end_cycle);
@ -141,21 +137,18 @@ void fasedtests_top_t::run() {
} else {
fprintf(stderr, "*** PASSED *** after %llu cycles\n", end_cycle);
}
if (sim_speed > 1000.0) {
fprintf(stderr, "time elapsed: %.1f s, simulation speed = %.2f MHz\n", sim_time, sim_speed / 1000.0);
} else {
fprintf(stderr, "time elapsed: %.1f s, simulation speed = %.2f KHz\n", sim_time, sim_speed);
}
double fmr = ((double) hcycles / end_cycle);
fprintf(stderr, "FPGA-Cycles-to-Model-Cycles Ratio (FMR): %.2f\n", fmr);
expect(!exitcode, NULL);
print_simulation_performance_summary();
for (auto e: fpga_models) {
e->finish();
}
#ifdef PRINTBRIDGEMODULE_0_PRESENT
print_bridge->finish();
#endif
for (auto &e: bridges) {
e->finish();
}
this->host_finish();
return (exitcode || has_timed_out()) ? EXIT_SUCCESS : EXIT_FAILURE;
}
@ -178,6 +171,5 @@ class fasedtests_driver_t:
int main(int argc, char** argv) {
fasedtests_driver_t driver(argc, argv);
driver.init(argc, argv);
driver.run();
return driver.finish();
return driver.run();
}

View File

@ -16,7 +16,7 @@ class fasedtests_top_t: virtual simif_peek_poke_t, public systematic_scheduler_t
public:
fasedtests_top_t(int argc, char** argv);
~fasedtests_top_t() { }
void run();
int run();
protected:
void add_bridge_driver(bridge_driver_t* bridge_driver) {

View File

@ -24,6 +24,10 @@ test_harness_bridge_t::test_harness_bridge_t(
// it then reads uarch event counts from the FASED instance and compares them against
// expected values
void test_harness_bridge_t::tick(){
// Wait for reset to complete.
if (sim->actual_tcycle() < 100)
return;
this->done = sim->sample_value(done); // use a non-blocking sample since this signal is monotonic
if(done) {
this->error = 0;

View File

@ -570,7 +570,7 @@ void firesim_top_t::run() {
while (!simulation_complete() && !has_timed_out()) {
run_scheduled_tasks();
step(get_largest_stepsize(), false);
take_steps(get_largest_stepsize(), false);
while(!done() && !simulation_complete()){
for (auto &e: bridges) e->tick();
}
@ -599,5 +599,7 @@ int firesim_top_t::teardown() {
for (auto &e: bridges) {
e->finish();
}
this->host_finish();
return (exitcode || has_timed_out()) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -110,7 +110,7 @@ public:
int main(int argc, char** argv)
{
dut_emul_t dut(argc, argv);
dut.init(argc, argv, true);
dut.init(argc, argv);
dut.run();
return dut.teardown();
}

View File

@ -124,7 +124,7 @@ int simif_peek_poke_t::teardown() {
fprintf(stderr, "SEED: %ld\n", get_seed());
this->print_simulation_performance_summary();
finish();
this->host_finish();
return pass ? EXIT_SUCCESS : EXIT_FAILURE;
}