From ccfc00705a1658260e792e9604ae5319ec7b7c2a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 26 Jan 2022 09:26:19 +0100 Subject: Add ability to write to FST file --- passes/sat/sim.cc | 120 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 11 deletions(-) (limited to 'passes/sat') diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 4e158da62..ba7519be5 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -21,6 +21,7 @@ #include "kernel/sigtools.h" #include "kernel/celltypes.h" #include "kernel/mem.h" +#include "libs/fst/fstapi.h" #include @@ -92,6 +93,7 @@ struct SimInstance std::vector memories; dict> vcd_database; + dict> fst_database; SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : shared(shared), module(module), instance(instance), parent(parent), sigmap(module) @@ -616,12 +618,60 @@ struct SimInstance for (auto child : children) child.second->write_vcd_step(f); } + + void write_fst_header(struct fstContext *f) + { + fstWriterSetScope(f, FST_ST_VCD_MODULE, stringf("%s",log_id(name())).c_str(), nullptr); + for (auto wire : module->wires()) + { + if (shared->hide_internal && wire->name[0] == '$') + continue; + + fstHandle id = fstWriterCreateVar(f, FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire), + stringf("%s%s", wire->name[0] == '$' ? "\\" : "", log_id(wire)).c_str(), 0); + fst_database[wire] = make_pair(id, Const()); + } + + for (auto child : children) + child.second->write_fst_header(f); + + fstWriterSetUpscope(f); + } + + void write_fst_step(struct fstContext *f) + { + for (auto &it : fst_database) + { + Wire *wire = it.first; + Const value = get_state(wire); + fstHandle id = it.second.first; + + if (it.second.second == value) + continue; + + it.second.second = value; + 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(f, id, ss.str().c_str()); + } + + for (auto child : children) + child.second->write_fst_step(f); + } }; struct SimWorker : SimShared { SimInstance *top = nullptr; std::ofstream vcdfile; + struct fstContext *fstfile = nullptr; pool clock, clockn, reset, resetn; std::string timescale; @@ -632,9 +682,6 @@ struct SimWorker : SimShared void write_vcd_header() { - if (!vcdfile.is_open()) - return; - vcdfile << stringf("$version %s $end\n", yosys_version_str); std::time_t t = std::time(nullptr); @@ -654,13 +701,53 @@ struct SimWorker : SimShared void write_vcd_step(int t) { - if (!vcdfile.is_open()) - return; - vcdfile << stringf("#%d\n", t); top->write_vcd_step(vcdfile); } + void write_fst_header() + { + std::time_t t = std::time(nullptr); + fstWriterSetDate(fstfile, asctime(std::localtime(&t))); + fstWriterSetVersion(fstfile, yosys_version_str); + if (!timescale.empty()) + fstWriterSetTimescaleFromString(fstfile, timescale.c_str()); + + fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ); + fstWriterSetRepackOnClose(fstfile, 1); + + top->write_fst_header(fstfile); + } + + void write_fst_step(int t) + { + fstWriterEmitTimeChange(fstfile, t); + + top->write_fst_step(fstfile); + } + + void write_output_header() + { + if (vcdfile.is_open()) + write_vcd_header(); + if (fstfile) + write_fst_header(); + } + + void write_output_step(int t) + { + if (vcdfile.is_open()) + write_vcd_step(t); + if (fstfile) + write_fst_step(t); + } + + void write_output_end() + { + if (fstfile) + fstWriterClose(fstfile); + } + void update() { while (1) @@ -714,8 +801,8 @@ struct SimWorker : SimShared update(); - write_vcd_header(); - write_vcd_step(0); + write_output_header(); + write_output_step(0); for (int cycle = 0; cycle < numcycles; cycle++) { @@ -726,7 +813,7 @@ struct SimWorker : SimShared set_inports(clockn, State::S1); update(); - write_vcd_step(10*cycle + 5); + write_output_step(10*cycle + 5); if (debug) log("\n===== %d =====\n", 10*cycle + 10); @@ -742,10 +829,12 @@ struct SimWorker : SimShared } update(); - write_vcd_step(10*cycle + 10); + write_output_step(10*cycle + 10); } - write_vcd_step(10*numcycles + 2); + write_output_step(10*numcycles + 2); + + write_output_end(); if (writeback) { pool wbmods; @@ -767,6 +856,9 @@ struct SimPass : public Pass { log(" -vcd \n"); log(" write the simulation results to the given VCD file\n"); log("\n"); + log(" -fst \n"); + log(" write the simulation results to the given FST file\n"); + log("\n"); log(" -clock \n"); log(" name of top-level clock input\n"); log("\n"); @@ -816,6 +908,12 @@ struct SimPass : public Pass { worker.vcdfile.open(vcd_filename.c_str()); continue; } + if (args[argidx] == "-fst" && argidx+1 < args.size()) { + std::string fst_filename = args[++argidx]; + rewrite_filename(fst_filename); + worker.fstfile = (struct fstContext *)fstWriterCreate(fst_filename.c_str(),1); + continue; + } if (args[argidx] == "-n" && argidx+1 < args.size()) { numcycles = atoi(args[++argidx].c_str()); continue; -- cgit v1.2.3 From 9a8939f0a4584c13bfceb978120cc8605ede03ee Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 26 Jan 2022 15:50:38 +0100 Subject: Read fst and use data to set inputs --- passes/sat/sim.cc | 102 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 10 deletions(-) (limited to 'passes/sat') diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index ba7519be5..99ea701d9 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -21,7 +21,7 @@ #include "kernel/sigtools.h" #include "kernel/celltypes.h" #include "kernel/mem.h" -#include "libs/fst/fstapi.h" +#include "kernel/fstdata.h" #include @@ -35,6 +35,7 @@ struct SimShared bool writeback = false; bool zinit = false; int rstlen = 1; + FstData *fst = nullptr; }; void zinit(State &v) @@ -52,7 +53,8 @@ void zinit(Const &v) struct SimInstance { SimShared *shared; - + + std::string scope; Module *module; Cell *instance; @@ -95,8 +97,8 @@ struct SimInstance dict> vcd_database; dict> fst_database; - SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : - shared(shared), module(module), instance(instance), parent(parent), sigmap(module) + SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : + shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module) { log_assert(module); @@ -146,7 +148,7 @@ struct SimInstance Module *mod = module->design->module(cell->type); if (mod != nullptr) { - dirty_children.insert(new SimInstance(shared, mod, cell, this)); + dirty_children.insert(new SimInstance(shared, scope + "." + RTLIL::unescape_id(module->name), mod, cell, this)); } for (auto &port : cell->connections()) { @@ -674,6 +676,8 @@ struct SimWorker : SimShared struct fstContext *fstfile = nullptr; pool clock, clockn, reset, resetn; std::string timescale; + std::string sim_filename; + std::string scope; ~SimWorker() { @@ -708,10 +712,10 @@ struct SimWorker : SimShared void write_fst_header() { std::time_t t = std::time(nullptr); - fstWriterSetDate(fstfile, asctime(std::localtime(&t))); - fstWriterSetVersion(fstfile, yosys_version_str); + fstWriterSetDate(fstfile, asctime(std::localtime(&t))); + fstWriterSetVersion(fstfile, yosys_version_str); if (!timescale.empty()) - fstWriterSetTimescaleFromString(fstfile, timescale.c_str()); + fstWriterSetTimescaleFromString(fstfile, timescale.c_str()); fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ); fstWriterSetRepackOnClose(fstfile, 1); @@ -786,7 +790,7 @@ struct SimWorker : SimShared void run(Module *topmod, int numcycles) { log_assert(top == nullptr); - top = new SimInstance(this, topmod); + top = new SimInstance(this, scope, topmod); if (debug) log("\n===== 0 =====\n"); @@ -841,6 +845,65 @@ struct SimWorker : SimShared top->writeback(wbmods); } } + + void run_cosim(Module *topmod, int numcycles) + { + log_assert(top == nullptr); + top = new SimInstance(this, scope, topmod); + + fst = new FstData(sim_filename); + + std::vector fst_clock; + + for (auto portname : clock) + { + Wire *w = topmod->wire(portname); + if (!w) + log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + if (!w->port_input) + log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); + if (id==0) + log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname)); + fst_clock.push_back(id); + } + for (auto portname : clockn) + { + Wire *w = topmod->wire(portname); + if (!w) + log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + if (!w->port_input) + log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); + if (id==0) + log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname)); + fst_clock.push_back(id); + } + if (fst_clock.size()==0) + log_error("No clock signals defined for input file\n"); + + SigMap sigmap(topmod); + log ("Get inputs\n"); + std::map inputs; + + for (auto wire : topmod->wires()) { + if (wire->port_input) { + fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); + log("Input %s\n",log_id(wire)); + inputs[wire] = id; + } + } + + fst->reconstruct(fst_clock); + auto edges = fst->edges(fst_clock.back(), true, true); + fst->reconstructAllAtTimes(edges); + for(auto &time : edges) { + for(auto &item : inputs) { + std::string v = fst->valueAt(item.second, time); + top->set_state(item.first, Const::from_string(v)); + } + update(); + } }; struct SimPass : public Pass { @@ -889,6 +952,12 @@ struct SimPass : public Pass { log(" -w\n"); log(" writeback mode: use final simulation state as new init state\n"); log("\n"); + log(" -r\n"); + log(" read simulation results file (file formats supported: FST)\n"); + log("\n"); + log(" -scope\n"); + log(" scope of simulation top model\n"); + log("\n"); log(" -d\n"); log(" enable debug output\n"); log("\n"); @@ -958,6 +1027,16 @@ struct SimPass : public Pass { worker.zinit = true; continue; } + if (args[argidx] == "-r" && argidx+1 < args.size()) { + std::string sim_filename = args[++argidx]; + rewrite_filename(sim_filename); + worker.sim_filename = sim_filename; + continue; + } + if (args[argidx] == "-scope" && argidx+1 < args.size()) { + worker.scope = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); @@ -976,7 +1055,10 @@ struct SimPass : public Pass { top_mod = mods.front(); } - worker.run(top_mod, numcycles); + if (worker.sim_filename.empty()) + worker.run(top_mod, numcycles); + else + worker.run_cosim(top_mod, numcycles); } } SimPass; -- cgit v1.2.3 From be7be63fece641db3e3fa1bd28f10603d07732bf Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 26 Jan 2022 15:51:43 +0100 Subject: Check if stimulated --- passes/sat/sim.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'passes/sat') diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 99ea701d9..605dc8e1e 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -903,7 +903,21 @@ struct SimWorker : SimShared top->set_state(item.first, Const::from_string(v)); } update(); + + /*Wire *wire = topmod->wire("\\cnt"); + Const value = top->get_state(wire); + 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"; + } + } + log("%s\n",ss.str().c_str());*/ } + } }; struct SimPass : public Pass { -- cgit v1.2.3 From 40018e191b7f5e233b2da4eab823f37d51a07778 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 26 Jan 2022 16:52:36 +0100 Subject: Display values of outputs --- passes/sat/sim.cc | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'passes/sat') diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 605dc8e1e..8cabcfbb4 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -885,6 +885,7 @@ struct SimWorker : SimShared SigMap sigmap(topmod); log ("Get inputs\n"); std::map inputs; + std::map outputs; for (auto wire : topmod->wires()) { if (wire->port_input) { @@ -892,6 +893,11 @@ struct SimWorker : SimShared log("Input %s\n",log_id(wire)); inputs[wire] = id; } + if (wire->port_output) { + fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); + log("Output %s %d\n",log_id(wire), id); + outputs[wire] = id; + } } fst->reconstruct(fst_clock); @@ -903,19 +909,11 @@ struct SimWorker : SimShared top->set_state(item.first, Const::from_string(v)); } update(); - - /*Wire *wire = topmod->wire("\\cnt"); - Const value = top->get_state(wire); - 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 &item : outputs) { + Const fst_val = Const::from_string(fst->valueAt(item.second, time)); + Const sim_val = top->get_state(item.first); + log("%s %s\n", log_signal(fst_val), log_signal(sim_val)); } - log("%s\n",ss.str().c_str());*/ } } }; -- cgit v1.2.3 From 3e35de2be108b7d8b24808aa55a0f0f9f8570705 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 28 Jan 2022 10:18:02 +0100 Subject: Add more options and time handling --- passes/sat/sim.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 2 deletions(-) (limited to 'passes/sat') diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 8cabcfbb4..d6f5f3a81 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -28,6 +28,41 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +enum class SimulationMode { + cmp, + gold, + gate, +}; + +static const std::map g_units = +{ + { "", -9 }, // default is ns + { "s", 0 }, + { "ms", -3 }, + { "us", -6 }, + { "ns", -9 }, + { "ps", -12 }, + { "fs", -15 }, + { "as", -18 }, + { "zs", -21 }, +}; + +static double stringToTime(std::string str) +{ + if (str=="END") return -1; + + char *endptr; + long value = strtol(str.c_str(), &endptr, 10); + + if (g_units.find(endptr)==g_units.end()) + log_error("Cannot parse '%s', bad unit '%s'\n", str.c_str(), endptr); + + if (value < 0) + log_error("Time value '%s' must be positive\n", str.c_str()); + + return value * pow(10.0, g_units.at(endptr)); +} + struct SimShared { bool debug = false; @@ -36,6 +71,9 @@ struct SimShared bool zinit = false; int rstlen = 1; FstData *fst = nullptr; + double start_time = 0; + double stop_time = -1; + SimulationMode sim_mode = SimulationMode::cmp; }; void zinit(State &v) @@ -900,10 +938,38 @@ struct SimWorker : SimShared } } + uint64_t startCount = 0; + uint64_t stopCount = 0; + if (start_time==0) { + if (start_time < fst->getStartTime()) + log_warning("Start time is before simulation file start time\n"); + startCount = fst->getStartTime(); + } else if (start_time==-1) + startCount = fst->getEndTime(); + else { + startCount = start_time / fst->getTimescale(); + if (startCount > fst->getEndTime()) { + startCount = fst->getEndTime(); + log_warning("Start time is after simulation file end time\n"); + } + } + if (stop_time==0) { + if (stop_time < fst->getStartTime()) + log_warning("Stop time is before simulation file start time\n"); + stopCount = fst->getStartTime(); + } else if (stop_time==-1) + stopCount = fst->getEndTime(); + else { + stopCount = stop_time / fst->getTimescale(); + if (stopCount > fst->getEndTime()) { + stopCount = fst->getEndTime(); + log_warning("Stop time is after simulation file end time\n"); + } + } fst->reconstruct(fst_clock); auto edges = fst->edges(fst_clock.back(), true, true); fst->reconstructAllAtTimes(edges); - for(auto &time : edges) { +/* for(auto &time : edges) { for(auto &item : inputs) { std::string v = fst->valueAt(item.second, time); top->set_state(item.first, Const::from_string(v)); @@ -914,7 +980,7 @@ struct SimWorker : SimShared Const sim_val = top->get_state(item.first); log("%s %s\n", log_signal(fst_val), log_signal(sim_val)); } - } + }*/ } }; @@ -970,6 +1036,21 @@ struct SimPass : public Pass { log(" -scope\n"); log(" scope of simulation top model\n"); log("\n"); + log(" -start