mirror of https://github.com/YosysHQ/yosys.git
Add "verific -extnets"
This commit is contained in:
parent
493fedbaf9
commit
6dbe1d4c92
|
@ -82,6 +82,16 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil
|
||||||
log("%s\n", message.c_str());
|
log("%s\n", message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string get_full_netlist_name(Netlist *nl)
|
||||||
|
{
|
||||||
|
if (nl->NumOfRefs() == 1) {
|
||||||
|
Instance *inst = (Instance*)nl->GetReferences()->GetLast();
|
||||||
|
return get_full_netlist_name(inst->Owner()) + "." + inst->Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl->CellBaseName();
|
||||||
|
}
|
||||||
|
|
||||||
struct VerificImporter
|
struct VerificImporter
|
||||||
{
|
{
|
||||||
RTLIL::Module *module;
|
RTLIL::Module *module;
|
||||||
|
@ -100,8 +110,8 @@ struct VerificImporter
|
||||||
RTLIL::SigBit net_map_at(Net *net)
|
RTLIL::SigBit net_map_at(Net *net)
|
||||||
{
|
{
|
||||||
if (net->IsExternalTo(netlist))
|
if (net->IsExternalTo(netlist))
|
||||||
log_error("Found unflattened external reference to net '%s' in netlist '%s' from netlist '%s'.\n",
|
log_error("Found external reference to '%s.%s' in netlist '%s', please use -flatten or -extnets.\n",
|
||||||
net->Name(), net->Owner()->CellBaseName(), netlist->CellBaseName());
|
get_full_netlist_name(net->Owner()).c_str(), net->Name(), get_full_netlist_name(netlist).c_str());
|
||||||
|
|
||||||
return net_map.at(net);
|
return net_map.at(net);
|
||||||
}
|
}
|
||||||
|
@ -1059,6 +1069,88 @@ struct VerificImporter
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VerificExtNets
|
||||||
|
{
|
||||||
|
// a map from nets to the same nets one level up in the design hierarchy
|
||||||
|
std::map<Net*, Net*> net_level_up;
|
||||||
|
int portname_cnt = 0;
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
|
Net *get_net_level_up(Net *net)
|
||||||
|
{
|
||||||
|
if (net_level_up.count(net) == 0)
|
||||||
|
{
|
||||||
|
Netlist *nl = net->Owner();
|
||||||
|
|
||||||
|
// Simple return if Netlist is not unique
|
||||||
|
if (nl->NumOfRefs() != 1)
|
||||||
|
return net;
|
||||||
|
|
||||||
|
Instance *up_inst = (Instance*)nl->GetReferences()->GetLast();
|
||||||
|
Netlist *up_nl = up_inst->Owner();
|
||||||
|
|
||||||
|
// create new Port
|
||||||
|
string name = stringf("___extnets_%d", portname_cnt++);
|
||||||
|
Port *new_port = new Port(name.c_str(), DIR_OUT);
|
||||||
|
nl->Add(new_port);
|
||||||
|
net->Connect(new_port);
|
||||||
|
|
||||||
|
// create new Net in up Netlist
|
||||||
|
Net *new_net = new Net(name.c_str());
|
||||||
|
up_nl->Add(new_net);
|
||||||
|
up_inst->Connect(new_port, new_net);
|
||||||
|
|
||||||
|
net_level_up[net] = new_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
return net_level_up.at(net);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(Netlist *nl)
|
||||||
|
{
|
||||||
|
MapIter mi, mi2;
|
||||||
|
Instance *inst;
|
||||||
|
PortRef *pr;
|
||||||
|
|
||||||
|
vector<tuple<Instance*, Port*, Net*>> todo_connect;
|
||||||
|
|
||||||
|
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
|
||||||
|
run(inst->View());
|
||||||
|
|
||||||
|
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
|
||||||
|
FOREACH_PORTREF_OF_INST(inst, mi2, pr)
|
||||||
|
{
|
||||||
|
Port *port = pr->GetPort();
|
||||||
|
Net *net = pr->GetNet();
|
||||||
|
|
||||||
|
if (!net->IsExternalTo(nl))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
log("Fixing external net reference on port %s.%s.%s:\n", get_full_netlist_name(nl).c_str(), inst->Name(), port->Name());
|
||||||
|
|
||||||
|
while (net->IsExternalTo(nl))
|
||||||
|
{
|
||||||
|
Net *newnet = get_net_level_up(net);
|
||||||
|
if (newnet == net) break;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
log(" external net: %s.%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name());
|
||||||
|
net = newnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
log(" final net: %s.%s%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name(), net->IsExternalTo(nl) ? " (external)" : "");
|
||||||
|
todo_connect.push_back(tuple<Instance*, Port*, Net*>(inst, port, net));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it : todo_connect) {
|
||||||
|
get<0>(it)->Disconnect(get<1>(it));
|
||||||
|
get<0>(it)->Connect(get<1>(it), get<2>(it));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* YOSYS_ENABLE_VERIFIC */
|
#endif /* YOSYS_ENABLE_VERIFIC */
|
||||||
|
|
||||||
struct VerificPass : public Pass {
|
struct VerificPass : public Pass {
|
||||||
|
@ -1095,6 +1187,9 @@ struct VerificPass : public Pass {
|
||||||
log(" -flatten\n");
|
log(" -flatten\n");
|
||||||
log(" Flatten the design in Verific before importing.\n");
|
log(" Flatten the design in Verific before importing.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -extnets\n");
|
||||||
|
log(" Resolve references to external nets by adding module ports as needed.\n");
|
||||||
|
log("\n");
|
||||||
log(" -v\n");
|
log(" -v\n");
|
||||||
log(" Verbose log messages.\n");
|
log(" Verbose log messages.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -1210,7 +1305,7 @@ struct VerificPass : public Pass {
|
||||||
{
|
{
|
||||||
std::set<Netlist*> nl_todo, nl_done;
|
std::set<Netlist*> nl_todo, nl_done;
|
||||||
bool mode_all = false, mode_gates = false, mode_keep = false;
|
bool mode_all = false, mode_gates = false, mode_keep = false;
|
||||||
bool verbose = false, flatten = false;
|
bool verbose = false, flatten = false, extnets = false;
|
||||||
string dumpfile;
|
string dumpfile;
|
||||||
|
|
||||||
for (argidx++; argidx < GetSize(args); argidx++) {
|
for (argidx++; argidx < GetSize(args); argidx++) {
|
||||||
|
@ -1226,6 +1321,10 @@ struct VerificPass : public Pass {
|
||||||
flatten = true;
|
flatten = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-extnets") {
|
||||||
|
extnets = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-k") {
|
if (args[argidx] == "-k") {
|
||||||
mode_keep = true;
|
mode_keep = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1254,27 +1353,32 @@ struct VerificPass : public Pass {
|
||||||
if (!vhdl_file::ElaborateAll())
|
if (!vhdl_file::ElaborateAll())
|
||||||
log_cmd_error("Elaboration of VHDL modules failed.\n");
|
log_cmd_error("Elaboration of VHDL modules failed.\n");
|
||||||
|
|
||||||
std::set<string> modnames;
|
|
||||||
for (; argidx < GetSize(args); argidx++)
|
|
||||||
modnames.insert(args[argidx]);
|
|
||||||
|
|
||||||
Library *lib = Netlist::PresentDesign()->Owner()->Owner();
|
Library *lib = Netlist::PresentDesign()->Owner()->Owner();
|
||||||
|
|
||||||
|
if (argidx == GetSize(args))
|
||||||
|
{
|
||||||
MapIter iter;
|
MapIter iter;
|
||||||
char *iter_name;
|
char *iter_name;
|
||||||
Verific::Cell *iter_cell;
|
Verific::Cell *iter_cell;
|
||||||
|
|
||||||
FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell)
|
FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) {
|
||||||
{
|
if (*iter_name != '$')
|
||||||
if (*iter_name == '$' || (!modnames.empty() && !modnames.count(iter_name)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
nl_todo.insert(iter_cell->GetFirstNetlist());
|
nl_todo.insert(iter_cell->GetFirstNetlist());
|
||||||
modnames.erase(iter_name);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (; argidx < GetSize(args); argidx++)
|
||||||
|
{
|
||||||
|
Verific::Cell *cell = lib->GetCell(args[argidx].c_str());
|
||||||
|
|
||||||
for (auto name : modnames)
|
if (cell == nullptr)
|
||||||
log_cmd_error("Module not found: %s\n", name.c_str());
|
log_cmd_error("Module not found: %s\n", args[argidx].c_str());
|
||||||
|
|
||||||
|
nl_todo.insert(cell->GetFirstNetlist());
|
||||||
|
cell->GetFirstNetlist()->SetPresentDesign();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1301,13 +1405,16 @@ struct VerificPass : public Pass {
|
||||||
nl->Flatten();
|
nl->Flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dumpfile.empty())
|
if (extnets) {
|
||||||
{
|
VerificExtNets worker;
|
||||||
if (GetSize(nl_todo) != 1)
|
worker.verbose = verbose;
|
||||||
log_cmd_error("Verific dump mode needs exactly one top module.\n");
|
for (auto nl : nl_todo)
|
||||||
|
worker.run(nl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dumpfile.empty()) {
|
||||||
VeriWrite veri_writer;
|
VeriWrite veri_writer;
|
||||||
veri_writer.WriteFile(dumpfile.c_str(), *nl_todo.begin());
|
veri_writer.WriteFile(dumpfile.c_str(), Netlist::PresentDesign());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!nl_todo.empty()) {
|
while (!nl_todo.empty()) {
|
||||||
|
|
Loading…
Reference in New Issue