if (inst->Type() == OPER_SVA_STABLE)
{
VerificClocking clocking(this, inst->GetInput2Bit(0));
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
log_assert(inst->Input1Size() == inst->OutputSize());
if (inst->Type() == PRIM_SVA_STABLE)
{
VerificClocking clocking(this, inst->GetInput2());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
SigSpec sig_d = net_map_at(inst->GetInput1());
SigSpec sig_o = net_map_at(inst->GetOutput());
if (inst->Type() == PRIM_SVA_PAST)
{
VerificClocking clocking(this, inst->GetInput2());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
SigBit sig_d = net_map_at(inst->GetInput1());
SigBit sig_q = net_map_at(inst->GetOutput());
if ((inst->Type() == PRIM_SVA_ROSE || inst->Type() == PRIM_SVA_FELL))
{
VerificClocking clocking(this, inst->GetInput2());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
SigBit sig_d = net_map_at(inst->GetInput1());
SigBit sig_o = net_map_at(inst->GetOutput());
if (!mode_nosva)
{
for (auto inst : sva_asserts)
- import_sva_assert(this, inst);
+ verific_import_sva_assert(this, inst);
for (auto inst : sva_assumes)
- import_sva_assume(this, inst);
+ verific_import_sva_assume(this, inst);
for (auto inst : sva_covers)
- import_sva_cover(this, inst);
+ verific_import_sva_cover(this, inst);
for (auto inst : sva_triggers)
- import_sva_trigger(this, inst);
+ verific_import_sva_trigger(this, inst);
merge_past_ffs(past_ffs);
}
inst = net->Driver();;
} while (0);
+ // Detect condition expression
+ do {
+ if (body_net == nullptr)
+ break;
+
+ Instance *inst_mux = body_net->Driver();
+
+ if (inst_mux == nullptr || inst_mux->Type() != PRIM_MUX)
+ break;
+
+ if (!inst_mux->GetInput1()->IsPwr())
+ break;
+
+ Net *sva_net = inst_mux->GetInput2();
+ if (!verific_is_sva_net(importer, sva_net))
+ break;
+
+ body_net = sva_net;
+ cond_net = inst_mux->GetControl();
+ } while (0);
+
clock_net = net;
clock_sig = importer->net_map_at(clock_net);
}
Verific::Net *enable_net = nullptr;
Verific::Net *disable_net = nullptr;
Verific::Net *body_net = nullptr;
+ Verific::Net *cond_net = nullptr;
SigBit clock_sig = State::Sx;
SigBit enable_sig = State::S1;
SigBit disable_sig = State::S0;
void import_netlist(RTLIL::Design *design, Verific::Netlist *nl, std::set<Verific::Netlist*> &nl_todo);
};
-void import_sva_assert(VerificImporter *importer, Verific::Instance *inst);
-void import_sva_assume(VerificImporter *importer, Verific::Instance *inst);
-void import_sva_cover(VerificImporter *importer, Verific::Instance *inst);
-void import_sva_trigger(VerificImporter *importer, Verific::Instance *inst);
+void verific_import_sva_assert(VerificImporter *importer, Verific::Instance *inst);
+void verific_import_sva_assume(VerificImporter *importer, Verific::Instance *inst);
+void verific_import_sva_cover(VerificImporter *importer, Verific::Instance *inst);
+void verific_import_sva_trigger(VerificImporter *importer, Verific::Instance *inst);
+bool verific_is_sva_net(VerificImporter *importer, Verific::Net *net);
YOSYS_NAMESPACE_END
if (inst->Type() == PRIM_SVA_AT)
{
VerificClocking new_clocking(importer, net);
+ log_assert(new_clocking.cond_net == nullptr);
if (!clocking.property_matches_sequence(new_clocking))
parser_error("Mixed clocking is currently not supported", inst);
return parse_sequence(fsm, start_node, new_clocking.body_net);
{
Instance *inst = net_to_ast_driver(net);
+ SigBit trig = State::S1;
+
+ if (clocking.cond_net != nullptr)
+ trig = importer->net_map_at(clocking.cond_net);
+
if (inst == nullptr)
{
+ log_assert(trig == State::S1);
+
if (accept_p != nullptr)
*accept_p = importer->net_map_at(net);
if (reject_p != nullptr)
Net *consequent_net = inst->GetInput2();
int node;
- SvaFsm antecedent_fsm(clocking);
+ SvaFsm antecedent_fsm(clocking, trig);
node = parse_sequence(antecedent_fsm, antecedent_fsm.createStartNode(), antecedent_net);
if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION) {
int next_node = antecedent_fsm.createNode();
inst = net_to_ast_driver(net);
}
- SvaFsm fsm(clocking);
+ SvaFsm fsm(clocking, trig);
int node = parse_sequence(fsm, fsm.createStartNode(), net);
fsm.createLink(node, fsm.acceptNode);
}
};
-void import_sva_assert(VerificImporter *importer, Instance *inst)
+void verific_import_sva_assert(VerificImporter *importer, Instance *inst)
{
VerificSvaImporter worker;
worker.importer = importer;
worker.import();
}
-void import_sva_assume(VerificImporter *importer, Instance *inst)
+void verific_import_sva_assume(VerificImporter *importer, Instance *inst)
{
VerificSvaImporter worker;
worker.importer = importer;
worker.import();
}
-void import_sva_cover(VerificImporter *importer, Instance *inst)
+void verific_import_sva_cover(VerificImporter *importer, Instance *inst)
{
VerificSvaImporter worker;
worker.importer = importer;
worker.import();
}
-void import_sva_trigger(VerificImporter *importer, Instance *inst)
+void verific_import_sva_trigger(VerificImporter *importer, Instance *inst)
{
VerificSvaImporter worker;
worker.importer = importer;
worker.import();
}
+bool verific_is_sva_net(VerificImporter *importer, Verific::Net *net)
+{
+ VerificSvaImporter worker;
+ worker.importer = importer;
+ return worker.net_to_ast_driver(net) != nullptr;
+}
+
YOSYS_NAMESPACE_END