mirror of https://github.com/YosysHQ/yosys.git
Add ability to write to FST file
This commit is contained in:
parent
9e9083bbe9
commit
ccfc00705a
|
@ -21,6 +21,7 @@
|
||||||
#include "kernel/sigtools.h"
|
#include "kernel/sigtools.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
|
#include "libs/fst/fstapi.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@ struct SimInstance
|
||||||
std::vector<Mem> memories;
|
std::vector<Mem> memories;
|
||||||
|
|
||||||
dict<Wire*, pair<int, Const>> vcd_database;
|
dict<Wire*, pair<int, Const>> vcd_database;
|
||||||
|
dict<Wire*, pair<fstHandle, Const>> fst_database;
|
||||||
|
|
||||||
SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
|
SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
|
||||||
shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
|
shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
|
||||||
|
@ -616,12 +618,60 @@ struct SimInstance
|
||||||
for (auto child : children)
|
for (auto child : children)
|
||||||
child.second->write_vcd_step(f);
|
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
|
struct SimWorker : SimShared
|
||||||
{
|
{
|
||||||
SimInstance *top = nullptr;
|
SimInstance *top = nullptr;
|
||||||
std::ofstream vcdfile;
|
std::ofstream vcdfile;
|
||||||
|
struct fstContext *fstfile = nullptr;
|
||||||
pool<IdString> clock, clockn, reset, resetn;
|
pool<IdString> clock, clockn, reset, resetn;
|
||||||
std::string timescale;
|
std::string timescale;
|
||||||
|
|
||||||
|
@ -632,9 +682,6 @@ struct SimWorker : SimShared
|
||||||
|
|
||||||
void write_vcd_header()
|
void write_vcd_header()
|
||||||
{
|
{
|
||||||
if (!vcdfile.is_open())
|
|
||||||
return;
|
|
||||||
|
|
||||||
vcdfile << stringf("$version %s $end\n", yosys_version_str);
|
vcdfile << stringf("$version %s $end\n", yosys_version_str);
|
||||||
|
|
||||||
std::time_t t = std::time(nullptr);
|
std::time_t t = std::time(nullptr);
|
||||||
|
@ -654,13 +701,53 @@ struct SimWorker : SimShared
|
||||||
|
|
||||||
void write_vcd_step(int t)
|
void write_vcd_step(int t)
|
||||||
{
|
{
|
||||||
if (!vcdfile.is_open())
|
|
||||||
return;
|
|
||||||
|
|
||||||
vcdfile << stringf("#%d\n", t);
|
vcdfile << stringf("#%d\n", t);
|
||||||
top->write_vcd_step(vcdfile);
|
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()
|
void update()
|
||||||
{
|
{
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -714,8 +801,8 @@ struct SimWorker : SimShared
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
write_vcd_header();
|
write_output_header();
|
||||||
write_vcd_step(0);
|
write_output_step(0);
|
||||||
|
|
||||||
for (int cycle = 0; cycle < numcycles; cycle++)
|
for (int cycle = 0; cycle < numcycles; cycle++)
|
||||||
{
|
{
|
||||||
|
@ -726,7 +813,7 @@ struct SimWorker : SimShared
|
||||||
set_inports(clockn, State::S1);
|
set_inports(clockn, State::S1);
|
||||||
|
|
||||||
update();
|
update();
|
||||||
write_vcd_step(10*cycle + 5);
|
write_output_step(10*cycle + 5);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
log("\n===== %d =====\n", 10*cycle + 10);
|
log("\n===== %d =====\n", 10*cycle + 10);
|
||||||
|
@ -742,10 +829,12 @@ struct SimWorker : SimShared
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
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) {
|
if (writeback) {
|
||||||
pool<Module*> wbmods;
|
pool<Module*> wbmods;
|
||||||
|
@ -767,6 +856,9 @@ struct SimPass : public Pass {
|
||||||
log(" -vcd <filename>\n");
|
log(" -vcd <filename>\n");
|
||||||
log(" write the simulation results to the given VCD file\n");
|
log(" write the simulation results to the given VCD file\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -fst <filename>\n");
|
||||||
|
log(" write the simulation results to the given FST file\n");
|
||||||
|
log("\n");
|
||||||
log(" -clock <portname>\n");
|
log(" -clock <portname>\n");
|
||||||
log(" name of top-level clock input\n");
|
log(" name of top-level clock input\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -816,6 +908,12 @@ struct SimPass : public Pass {
|
||||||
worker.vcdfile.open(vcd_filename.c_str());
|
worker.vcdfile.open(vcd_filename.c_str());
|
||||||
continue;
|
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()) {
|
if (args[argidx] == "-n" && argidx+1 < args.size()) {
|
||||||
numcycles = atoi(args[++argidx].c_str());
|
numcycles = atoi(args[++argidx].c_str());
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue