From 48b56a4f7fb13b27522dc243e68d8f67bcde705a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 2 Mar 2022 15:23:07 +0100 Subject: [PATCH] Write simulation files after simulation is performed --- passes/sat/sim.cc | 296 +++++++++++++++++++++++----------------------- 1 file changed, 151 insertions(+), 145 deletions(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 7189b54e8..6be8c080b 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -70,12 +70,7 @@ struct OutputWriter { OutputWriter(SimWorker *w) { worker = w;}; virtual ~OutputWriter() {}; - virtual void write_header() = 0; - virtual void write_step_header(int t) = 0; - virtual void enter_scope(IdString) {}; - virtual void exit_scope() {}; - virtual void register_signal(Wire *, int) {}; - virtual void write_value(int, Const&) {}; + virtual void write() = 0; SimWorker *worker; }; @@ -92,6 +87,7 @@ struct SimShared SimulationMode sim_mode = SimulationMode::sim; bool cycles_set = false; std::vector> outputfiles; + std::vector>> output_data; }; void zinit(State &v) @@ -699,27 +695,37 @@ struct SimInstance it.second->writeback(wbmods); } - void write_output_header(OutputWriter *writer, int &id) + void register_signals(int &id) { - writer->enter_scope(name()); - for (auto wire : module->wires()) { if (shared->hide_internal && wire->name[0] == '$') continue; signal_database[wire] = make_pair(id, Const()); - writer->register_signal(wire, id); id++; } for (auto child : children) - child.second->write_output_header(writer, id); + child.second->register_signals(id); + } + + void write_output_header(std::function enter_scope, std::function exit_scope, std::function register_signal) + { + enter_scope(name()); - writer->exit_scope(); + for (auto signal : signal_database) + { + register_signal(signal.first, signal.second.first); + } + + for (auto child : children) + child.second->write_output_header(enter_scope, exit_scope, register_signal); + + exit_scope(); } - void write_output_step_values() + void register_output_step_values(std::map *data) { for (auto &it : signal_database) { @@ -731,13 +737,11 @@ struct SimInstance continue; it.second.second = value; - - for(auto& writer : shared->outputfiles) - writer->write_value(id, value); + data->emplace(id, value); } for (auto child : children) - child.second->write_output_step_values(); + child.second->register_output_step_values(data); } void setInitState() @@ -828,20 +832,24 @@ struct SimWorker : SimShared delete top; } - void write_output_header() + void register_signals() { - for(auto& writer : outputfiles) - writer->write_header(); + int id = 1; + top->register_signals(id); } - void write_output_step(int t) + void register_output_step(int t) { - for(auto& writer : outputfiles) - writer->write_step_header(t); - - top->write_output_step_values(); + std::map data; + top->register_output_step_values(&data); + output_data.emplace_back(t, data); } + void write_output_files() + { + for(auto& writer : outputfiles) + writer->write(); + } void update() { @@ -882,6 +890,7 @@ struct SimWorker : SimShared { log_assert(top == nullptr); top = new SimInstance(this, scope, topmod); + register_signals(); if (debug) log("\n===== 0 =====\n"); @@ -896,8 +905,7 @@ struct SimWorker : SimShared update(); - write_output_header(); - write_output_step(0); + register_output_step(0); for (int cycle = 0; cycle < numcycles; cycle++) { @@ -909,7 +917,7 @@ struct SimWorker : SimShared set_inports(clockn, State::S1); update(); - write_output_step(10*cycle + 5); + register_output_step(10*cycle + 5); if (debug) log("\n===== %d =====\n", 10*cycle + 10); @@ -925,10 +933,12 @@ struct SimWorker : SimShared } update(); - write_output_step(10*cycle + 10); + register_output_step(10*cycle + 10); } - write_output_step(10*numcycles + 2); + register_output_step(10*numcycles + 2); + + write_output_files(); if (writeback) { pool wbmods; @@ -945,6 +955,7 @@ struct SimWorker : SimShared log_error("Scope must be defined for co-simulation.\n"); top = new SimInstance(this, scope, topmod); + register_signals(); std::vector fst_clock; @@ -1036,12 +1047,11 @@ struct SimWorker : SimShared if (initial) { top->setInitState(); - write_output_header(); initial = false; } if (did_something) update(); - write_output_step(time); + register_output_step(time); bool status = top->checkSignals(); if (status) @@ -1058,6 +1068,8 @@ struct SimWorker : SimShared // end of data detected } + write_output_files(); + if (writeback) { pool wbmods; top->writeback(wbmods); @@ -1098,6 +1110,8 @@ struct SimWorker : SimShared std::string status; int cycle = 0; top = new SimInstance(this, scope, topmod); + register_signals(); + while (!f.eof()) { std::string line; @@ -1109,7 +1123,6 @@ struct SimWorker : SimShared state = 2; } if (state==1 && line[0]!='b' && line[0]!='c') { - write_output_header(); // was old format but with 1 bit latch top->setState(latches, status); state = 3; @@ -1125,7 +1138,6 @@ struct SimWorker : SimShared state = 2; break; case 2: - write_output_header(); top->setState(latches, line); state = 3; break; @@ -1141,18 +1153,19 @@ struct SimWorker : SimShared set_inports(clockn, State::S1); } update(); - write_output_step(10*cycle); + register_output_step(10*cycle); if (cycle) { set_inports(clock, State::S0); set_inports(clockn, State::S1); update(); - write_output_step(10*cycle + 5); + register_output_step(10*cycle + 5); } cycle++; break; } } - write_output_step(10*cycle); + register_output_step(10*cycle); + write_output_files(); } }; @@ -1162,7 +1175,7 @@ struct VCDWriter : public OutputWriter vcdfile.open(filename.c_str()); } - void write_header() override + void write() override { if (!vcdfile.is_open()) return; vcdfile << stringf("$version %s $end\n", yosys_version_str); @@ -1176,46 +1189,33 @@ struct VCDWriter : public OutputWriter if (!worker->timescale.empty()) vcdfile << stringf("$timescale %s $end\n", worker->timescale.c_str()); - int id = 1; - worker->top->write_output_header(this, id); + worker->top->write_output_header( + [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); }, + [this]() { vcdfile << stringf("$upscope $end\n");}, + [this](Wire *wire, int id) { vcdfile << stringf("$var wire %d n%d %s%s $end\n", GetSize(wire), id, wire->name[0] == '$' ? "\\" : "", log_id(wire)); } + ); vcdfile << stringf("$enddefinitions $end\n"); - } - void write_step_header(int t) override - { - if (!vcdfile.is_open()) return; - vcdfile << stringf("#%d\n", t); - } - - void enter_scope(IdString name) override - { - vcdfile << stringf("$scope module %s $end\n", log_id(name)); - } - - void exit_scope() override - { - vcdfile << stringf("$upscope $end\n"); - } - - void register_signal(Wire *wire, int id) override - { - vcdfile << stringf("$var wire %d n%d %s%s $end\n", GetSize(wire), id, wire->name[0] == '$' ? "\\" : "", log_id(wire)); - } + for(auto& d : worker->output_data) + { + vcdfile << stringf("#%d\n", d.first); + for (auto &data : d.second) + { - void write_value(int id, Const& value) override - { - if (!vcdfile.is_open()) return; - vcdfile << "b"; - for (int i = GetSize(value)-1; i >= 0; i--) { - switch (value[i]) { - case State::S0: vcdfile << "0"; break; - case State::S1: vcdfile << "1"; break; - case State::Sx: vcdfile << "x"; break; - default: vcdfile << "z"; + Const value = data.second; + vcdfile << "b"; + for (int i = GetSize(value)-1; i >= 0; i--) { + switch (value[i]) { + case State::S0: vcdfile << "0"; break; + case State::S1: vcdfile << "1"; break; + case State::Sx: vcdfile << "x"; break; + default: vcdfile << "z"; + } + } + vcdfile << stringf(" n%d\n", data.first); } } - vcdfile << stringf(" n%d\n", id); } std::ofstream vcdfile; @@ -1232,7 +1232,7 @@ struct FSTWriter : public OutputWriter fstWriterClose(fstfile); } - void write_header() override + void write() override { if (!fstfile) return; std::time_t t = std::time(nullptr); @@ -1244,47 +1244,35 @@ struct FSTWriter : public OutputWriter fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ); fstWriterSetRepackOnClose(fstfile, 1); - int id = 1; - worker->top->write_output_header(this, id); - } - - void write_step_header(int t) override - { - if (!fstfile) return; - fstWriterEmitTimeChange(fstfile, t); - } - - void enter_scope(IdString name) override - { - fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",log_id(name)).c_str(), nullptr); - } - - void exit_scope() override - { - fstWriterSetUpscope(fstfile); - } - - void register_signal(Wire *wire, int id) override - { - fstHandle fst_id = fstWriterCreateVar(fstfile, FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire), + worker->top->write_output_header( + [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",log_id(name)).c_str(), nullptr); }, + [this]() { fstWriterSetUpscope(fstfile); }, + [this](Wire *wire, int id) { + fstHandle fst_id = fstWriterCreateVar(fstfile, FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire), stringf("%s%s", wire->name[0] == '$' ? "\\" : "", log_id(wire)).c_str(), 0); - mapping.emplace(id, fst_id); - } + mapping.emplace(id, fst_id); + } + ); - void write_value(int id, Const& value) override - { - if (!fstfile) return; - std::stringstream ss; - for (int i = GetSize(value)-1; i >= 0; i--) { - switch (value[i]) { - case State::S0: ss << "0"; break; - case State::S1: ss << "1"; break; - case State::Sx: ss << "x"; break; - default: ss << "z"; + for(auto& d : worker->output_data) + { + fstWriterEmitTimeChange(fstfile, d.first); + for (auto &data : d.second) + { + Const value = data.second; + std::stringstream ss; + for (int i = GetSize(value)-1; i >= 0; i--) { + switch (value[i]) { + case State::S0: ss << "0"; break; + case State::S1: ss << "1"; break; + case State::Sx: ss << "x"; break; + default: ss << "z"; + } + } + fstWriterEmitValueChange(fstfile, mapping[data.first], ss.str().c_str()); } } - fstWriterEmitValueChange(fstfile, mapping[id], ss.str().c_str()); } struct fstContext *fstfile = nullptr; @@ -1302,7 +1290,7 @@ struct AIWWriter : public OutputWriter aiwfile << '.' << '\n'; } - void write_header() override + void write() override { if (!aiwfile.is_open()) return; std::ifstream mf(worker->map_filename); @@ -1326,50 +1314,68 @@ struct AIWWriter : public OutputWriter } } - for (int i = 0;; i++) - { - if (aiw_latches.count(i)) { - auto v = worker->top->get_state(aiw_latches.at(i).first); - if (v == State::S1) - aiwfile << (aiw_latches.at(i).second ? '0' : '1'); - else - aiwfile << (aiw_latches.at(i).second ? '1' : '0'); - continue; - } - aiwfile << '\n'; - break; - } - } + worker->top->write_output_header( + [](IdString) {}, + []() {}, + [this](Wire *wire, int id) { mapping[wire] = id; } + ); - void write_step_header(int) override - { - if (!aiwfile.is_open()) return; - for (int i = 0;; i++) + std::map current; + bool first = true; + for(auto& d : worker->output_data) { - if (aiw_inputs.count(i)) { - auto v = worker->top->get_state(aiw_inputs.at(i)); - if (v == State::S1) - aiwfile << '1'; - else - aiwfile << '0'; - continue; + for (auto &data : d.second) + { + current[data.first] = data.second; } - if (aiw_inits.count(i)) { - auto v = worker->top->get_state(aiw_inits.at(i)); - if (v == State::S1) - aiwfile << '1'; - else - aiwfile << '0'; - continue; + if (first) { + for (int i = 0;; i++) + { + if (aiw_latches.count(i)) { + SigBit bit = aiw_latches.at(i).first; + auto v = current[mapping[bit.wire]].bits.at(bit.offset); + if (v == State::S1) + aiwfile << (aiw_latches.at(i).second ? '0' : '1'); + else + aiwfile << (aiw_latches.at(i).second ? '1' : '0'); + continue; + } + aiwfile << '\n'; + break; + } + first = false; } - aiwfile << '\n'; - break; - } + + for (int i = 0;; i++) + { + if (aiw_inputs.count(i)) { + SigBit bit = aiw_inputs.at(i); + auto v = current[mapping[bit.wire]].bits.at(bit.offset); + if (v == State::S1) + aiwfile << '1'; + else + aiwfile << '0'; + continue; + } + if (aiw_inits.count(i)) { + SigBit bit = aiw_inits.at(i); + auto v = current[mapping[bit.wire]].bits.at(bit.offset); + if (v == State::S1) + aiwfile << '1'; + else + aiwfile << '0'; + continue; + } + aiwfile << '\n'; + break; + } + } } std::ofstream aiwfile; dict> aiw_latches; dict aiw_inputs, aiw_inits; + std::map mapping; }; struct SimPass : public Pass { -- 2.30.2