Add assert/assume support to verific front-end

This commit is contained in:
Clifford Wolf 2017-02-04 13:36:00 +01:00
parent 249ddbc16c
commit 911c44d164
2 changed files with 769 additions and 707 deletions

View File

@ -6,7 +6,7 @@ only have the i386 eval version of Verific:
1.) Use a Makefile.conf like the following one:
--snip--
CONFIG := clang
CONFIG := gcc
ENABLE_TCL := 0
ENABLE_PLUGINS := 0
ENABLE_VERIFIC := 1

View File

@ -49,7 +49,13 @@ USING_YOSYS_NAMESPACE
using namespace Verific ;
#endif
static void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)
#endif
PRIVATE_NAMESPACE_BEGIN
#ifdef YOSYS_ENABLE_VERIFIC
void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefile, const char *msg, va_list args)
{
log("VERIFIC-%s [%s] ",
msg_type == VERIFIC_NONE ? "NONE" :
@ -65,7 +71,13 @@ static void msg_func(msg_type_t msg_type, const char *message_id, linefile_type
log("\n");
}
static void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
struct VerificImporter
{
RTLIL::Module *module;
std::map<Net*, RTLIL::SigBit> net_map;
std::map<Net*, Net*> sva_posedge_map;
void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
{
MapIter mi;
Att *attr;
@ -78,7 +90,7 @@ static void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, D
attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value()));
}
static RTLIL::SigSpec operatorInput(Instance *inst, std::map<Net*, RTLIL::SigBit> &net_map)
RTLIL::SigSpec operatorInput(Instance *inst)
{
RTLIL::SigSpec sig;
for (int i = int(inst->InputSize())-1; i >= 0; i--)
@ -89,7 +101,7 @@ static RTLIL::SigSpec operatorInput(Instance *inst, std::map<Net*, RTLIL::SigBit
return sig;
}
static RTLIL::SigSpec operatorInput1(Instance *inst, std::map<Net*, RTLIL::SigBit> &net_map)
RTLIL::SigSpec operatorInput1(Instance *inst)
{
RTLIL::SigSpec sig;
for (int i = int(inst->Input1Size())-1; i >= 0; i--)
@ -100,7 +112,7 @@ static RTLIL::SigSpec operatorInput1(Instance *inst, std::map<Net*, RTLIL::SigBi
return sig;
}
static RTLIL::SigSpec operatorInput2(Instance *inst, std::map<Net*, RTLIL::SigBit> &net_map)
RTLIL::SigSpec operatorInput2(Instance *inst)
{
RTLIL::SigSpec sig;
for (int i = int(inst->Input2Size())-1; i >= 0; i--)
@ -111,7 +123,7 @@ static RTLIL::SigSpec operatorInput2(Instance *inst, std::map<Net*, RTLIL::SigBi
return sig;
}
static RTLIL::SigSpec operatorInport(Instance *inst, const char *portname, std::map<Net*, RTLIL::SigBit> &net_map)
RTLIL::SigSpec operatorInport(Instance *inst, const char *portname)
{
PortBus *portbus = inst->View()->GetPortBus(portname);
if (portbus) {
@ -137,7 +149,7 @@ static RTLIL::SigSpec operatorInport(Instance *inst, const char *portname, std::
}
}
static RTLIL::SigSpec operatorOutput(Instance *inst, std::map<Net*, RTLIL::SigBit> &net_map, RTLIL::Module *module)
RTLIL::SigSpec operatorOutput(Instance *inst)
{
RTLIL::SigSpec sig;
RTLIL::Wire *dummy_wire = NULL;
@ -155,7 +167,7 @@ static RTLIL::SigSpec operatorOutput(Instance *inst, std::map<Net*, RTLIL::SigBi
return sig;
}
static bool import_netlist_instance_gates(RTLIL::Module *module, std::map<Net*, RTLIL::SigBit> &net_map, Instance *inst)
bool import_netlist_instance_gates(Instance *inst)
{
if (inst->Type() == PRIM_AND) {
module->addAndGate(RTLIL::escape_id(inst->Name()), net_map.at(inst->GetInput1()), net_map.at(inst->GetInput2()), net_map.at(inst->GetOutput()));
@ -246,7 +258,7 @@ static bool import_netlist_instance_gates(RTLIL::Module *module, std::map<Net*,
return false;
}
static bool import_netlist_instance_cells(RTLIL::Module *module, std::map<Net*, RTLIL::SigBit> &net_map, Instance *inst)
bool import_netlist_instance_cells(Instance *inst)
{
if (inst->Type() == PRIM_AND) {
module->addAnd(RTLIL::escape_id(inst->Name()), net_map.at(inst->GetInput1()), net_map.at(inst->GetInput2()), net_map.at(inst->GetOutput()));
@ -334,10 +346,10 @@ static bool import_netlist_instance_cells(RTLIL::Module *module, std::map<Net*,
return true;
}
#define IN operatorInput(inst, net_map)
#define IN1 operatorInput1(inst, net_map)
#define IN2 operatorInput2(inst, net_map)
#define OUT operatorOutput(inst, net_map, module)
#define IN operatorInput(inst)
#define IN1 operatorInput1(inst)
#define IN2 operatorInput2(inst)
#define OUT operatorOutput(inst)
#define SIGNED inst->View()->IsSigned()
if (inst->Type() == OPER_ADDER) {
@ -503,8 +515,8 @@ static bool import_netlist_instance_cells(RTLIL::Module *module, std::map<Net*,
}
if (inst->Type() == OPER_WIDE_DFFRS) {
RTLIL::SigSpec sig_set = operatorInport(inst, "set", net_map);
RTLIL::SigSpec sig_reset = operatorInport(inst, "reset", net_map);
RTLIL::SigSpec sig_set = operatorInport(inst, "set");
RTLIL::SigSpec sig_reset = operatorInport(inst, "reset");
if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool())
module->addDff(RTLIL::escape_id(inst->Name()), net_map.at(inst->GetClock()), IN, OUT);
else
@ -521,7 +533,7 @@ static bool import_netlist_instance_cells(RTLIL::Module *module, std::map<Net*,
return false;
}
static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo, bool mode_gates)
void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*> &nl_todo, bool mode_gates)
{
std::string module_name = nl->IsOperator() ? std::string("$verific$") + nl->Owner()->Name() : RTLIL::escape_id(nl->Owner()->Name());
@ -531,14 +543,12 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
return;
}
RTLIL::Module *module = new RTLIL::Module;
module = new RTLIL::Module;
module->name = module_name;
design->add(module);
log("Importing module %s.\n", RTLIL::id2cstr(module->name));
std::map<Net*, RTLIL::SigBit> net_map;
SetIter si;
MapIter mi, mi2;
Port *port;
@ -694,8 +704,59 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
{
if (inst->Type() == PRIM_SVA_POSEDGE) {
Net *in_net = inst->GetInput();
Net *out_net = inst->GetOutput();
sva_posedge_map[out_net] = in_net;
continue;
}
}
FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)
{
if (inst->Type() == PRIM_SVA_POSEDGE)
continue;
// log(" importing cell %s (%s).\n", inst->Name(), inst->View()->Owner()->Name());
if (inst->Type() == PRIM_SVA_AT)
{
Net *in1 = inst->GetInput1();
Net *in2 = inst->GetInput2();
Net *out = inst->GetOutput();
if (sva_posedge_map.count(in2))
std::swap(in1, in2);
log_assert(sva_posedge_map.count(in1));
Net *clk = sva_posedge_map.at(in1);
SigBit outsig = net_map.at(out);
log_assert(outsig.wire && GetSize(outsig.wire) == 1);
outsig.wire->attributes["\\init"] == Const(0, 1);
module->addDff(NEW_ID, net_map.at(clk), net_map.at(in2), net_map.at(out));
continue;
}
if (inst->Type() == PRIM_SVA_IMMEDIATE_ASSERT || inst->Type() == PRIM_SVA_ASSERT) {
Net *in = inst->GetInput();
module->addAssert(NEW_ID, net_map.at(in), State::S1);
continue;
}
if (inst->Type() == PRIM_SVA_IMMEDIATE_ASSUME || inst->Type() == PRIM_SVA_ASSUME) {
Net *in = inst->GetInput();
module->addAssume(NEW_ID, net_map.at(in), State::S1);
continue;
}
if (inst->Type() == PRIM_SVA_IMMEDIATE_COVER || inst->Type() == PRIM_SVA_COVER) {
// Net *in = inst->GetInput();
// module->addCover(NEW_ID, net_map.at(in), State::S1);
continue;
}
if (inst->Type() == PRIM_PWR) {
module->connect(net_map.at(inst->GetOutput()), RTLIL::State::S1);
continue;
@ -727,8 +788,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
if (memory->width != int(inst->OutputSize()))
log_error("Import of asymetric memories from Verific is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
RTLIL::SigSpec addr = operatorInput1(inst, net_map);
RTLIL::SigSpec data = operatorOutput(inst, net_map, module);
RTLIL::SigSpec addr = operatorInput1(inst);
RTLIL::SigSpec data = operatorOutput(inst);
RTLIL::Cell *cell = module->addCell(RTLIL::escape_id(inst->Name()), "$memrd");
cell->parameters["\\MEMID"] = memory->name.str();
@ -750,8 +811,8 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
if (memory->width != int(inst->Input2Size()))
log_error("Import of asymetric memories from Verific is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
RTLIL::SigSpec addr = operatorInput1(inst, net_map);
RTLIL::SigSpec data = operatorInput2(inst, net_map);
RTLIL::SigSpec addr = operatorInput1(inst);
RTLIL::SigSpec data = operatorInput2(inst);
RTLIL::Cell *cell = module->addCell(RTLIL::escape_id(inst->Name()), "$memwr");
cell->parameters["\\MEMID"] = memory->name.str();
@ -773,12 +834,12 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
}
if (!mode_gates) {
if (import_netlist_instance_cells(module, net_map, inst))
if (import_netlist_instance_cells(inst))
continue;
if (inst->IsOperator())
log_warning("Unsupported Verific operator: %s (fallback to gate level implementation provided by verific)\n", inst->View()->Owner()->Name());
} else {
if (import_netlist_instance_gates(module, net_map, inst))
if (import_netlist_instance_gates(inst))
continue;
}
@ -817,11 +878,10 @@ static void import_netlist(RTLIL::Design *design, Netlist *nl, std::set<Netlist*
}
}
}
};
#endif /* YOSYS_ENABLE_VERIFIC */
YOSYS_NAMESPACE_BEGIN
struct VerificPass : public Pass {
VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { }
virtual void help()
@ -982,8 +1042,10 @@ struct VerificPass : public Pass {
while (!nl_todo.empty()) {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0)
import_netlist(design, nl, nl_todo, mode_gates);
if (nl_done.count(nl) == 0) {
VerificImporter importer;
importer.import_netlist(design, nl, nl_todo, mode_gates);
}
nl_todo.erase(nl);
nl_done.insert(nl);
}
@ -1001,5 +1063,5 @@ struct VerificPass : public Pass {
#endif
} VerificPass;
YOSYS_NAMESPACE_END
PRIVATE_NAMESPACE_END