2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 // Currently supported SVA sequence and property syntax:
22 // http://symbiyosys.readthedocs.io/en/latest/verific.html
24 // Next gen property syntax:
26 // [antecedent_condition] property
27 // [antecedent_condition] always.. property
28 // [antecedent_condition] eventually.. basic_property
29 // [antecedent_condition] property until.. expression
30 // [antecedent_condition] basic_property until.. basic_property (assert/assume only)
32 // antecedent_condition:
39 // sequence #-# basic_property
40 // sequence #=# basic_property
41 // basic_property or basic_property (cover only)
42 // basic_property and basic_property (assert/assume only)
43 // basic_property implies basic_property
44 // basic_property iff basic_property
48 // sequence ##N sequence
49 // sequence ##[*] sequence
50 // sequence ##[+] sequence
51 // sequence ##[N:M] sequence
52 // sequence ##[N:$] sequence
58 // sequence or sequence
59 // sequence and sequence
60 // expression throughout sequence
61 // sequence intersect sequence
62 // sequence within sequence
63 // first_match( sequence )
72 #include "kernel/yosys.h"
73 #include "frontends/verific/verific.h"
77 #ifdef VERIFIC_NAMESPACE
78 using namespace Verific
;
81 PRIVATE_NAMESPACE_BEGIN
83 // Non-deterministic FSM
86 // Edge: Activate the target node if ctrl signal is true, consumes clock cycle
87 // Link: Activate the target node if ctrl signal is true, doesn't consume clock cycle
88 vector
<pair
<int, SigBit
>> edges
, links
;
92 // Non-deterministic FSM after resolving links
95 // Edge: Activate the target node if all bits in ctrl signal are true, consumes clock cycle
96 // Accept: This node functions as an accept node if all bits in ctrl signal are true
97 vector
<pair
<int, SigSpec
>> edges
;
98 vector
<SigSpec
> accept
, cond
;
105 // A DFSM state corresponds to a set of NFSM states. We represent DFSM states as sorted vectors
106 // of NFSM state node ids. Edge/accept controls are constants matched against the ctrl sigspec.
108 vector
<pair
<vector
<int>, Const
>> edges
;
109 vector
<Const
> accept
, reject
;
111 // additional temp data for getReject()
116 // additional temp data for getDFsm()
123 VerificClocking clocking
;
125 SigBit trigger_sig
= State::S1
, disable_sig
;
126 SigBit throughout_sig
= State::S1
;
127 bool in_cond_mode
= false;
129 vector
<SigBit
> disable_stack
;
130 vector
<SigBit
> throughout_stack
;
132 int startNode
, acceptNode
, condNode
;
133 vector
<SvaNFsmNode
> nodes
;
135 vector
<SvaUFsmNode
> unodes
;
136 dict
<vector
<int>, SvaDFsmNode
> dnodes
;
137 dict
<pair
<SigSpec
, SigSpec
>, SigBit
> cond_eq_cache
;
138 bool materialized
= false;
140 SigBit final_accept_sig
= State::Sx
;
141 SigBit final_reject_sig
= State::Sx
;
143 SvaFsm(const VerificClocking
&clking
, SigBit trig
= State::S1
)
145 module
= clking
.module
;
149 startNode
= createNode();
150 acceptNode
= createNode();
153 condNode
= createNode();
154 in_cond_mode
= false;
157 void pushDisable(SigBit sig
)
159 log_assert(!materialized
);
161 disable_stack
.push_back(disable_sig
);
163 if (disable_sig
== State::S0
)
166 disable_sig
= module
->Or(NEW_ID
, disable_sig
, sig
);
171 log_assert(!materialized
);
172 log_assert(!disable_stack
.empty());
174 disable_sig
= disable_stack
.back();
175 disable_stack
.pop_back();
178 void pushThroughout(SigBit sig
)
180 log_assert(!materialized
);
182 throughout_stack
.push_back(throughout_sig
);
184 if (throughout_sig
== State::S1
)
185 throughout_sig
= sig
;
187 throughout_sig
= module
->And(NEW_ID
, throughout_sig
, sig
);
192 log_assert(!materialized
);
193 log_assert(!throughout_stack
.empty());
195 throughout_sig
= throughout_stack
.back();
196 throughout_stack
.pop_back();
199 int createNode(int link_node
= -1)
201 log_assert(!materialized
);
203 int idx
= GetSize(nodes
);
204 nodes
.push_back(SvaNFsmNode());
205 nodes
.back().is_cond_node
= in_cond_mode
;
207 createLink(link_node
, idx
);
211 int createStartNode()
213 return createNode(startNode
);
216 void createEdge(int from_node
, int to_node
, SigBit ctrl
= State::S1
)
218 log_assert(!materialized
);
219 log_assert(0 <= from_node
&& from_node
< GetSize(nodes
));
220 log_assert(0 <= to_node
&& to_node
< GetSize(nodes
));
221 log_assert(from_node
!= acceptNode
);
222 log_assert(to_node
!= acceptNode
);
223 log_assert(from_node
!= condNode
);
224 log_assert(to_node
!= condNode
);
225 log_assert(to_node
!= startNode
);
227 if (from_node
!= startNode
)
228 log_assert(nodes
.at(from_node
).is_cond_node
== nodes
.at(to_node
).is_cond_node
);
230 if (throughout_sig
!= State::S1
) {
231 if (ctrl
!= State::S1
)
232 ctrl
= module
->And(NEW_ID
, throughout_sig
, ctrl
);
234 ctrl
= throughout_sig
;
237 nodes
[from_node
].edges
.push_back(make_pair(to_node
, ctrl
));
240 void createLink(int from_node
, int to_node
, SigBit ctrl
= State::S1
)
242 log_assert(!materialized
);
243 log_assert(0 <= from_node
&& from_node
< GetSize(nodes
));
244 log_assert(0 <= to_node
&& to_node
< GetSize(nodes
));
245 log_assert(from_node
!= acceptNode
);
246 log_assert(from_node
!= condNode
);
247 log_assert(to_node
!= startNode
);
249 if (from_node
!= startNode
)
250 log_assert(nodes
.at(from_node
).is_cond_node
== nodes
.at(to_node
).is_cond_node
);
252 if (throughout_sig
!= State::S1
) {
253 if (ctrl
!= State::S1
)
254 ctrl
= module
->And(NEW_ID
, throughout_sig
, ctrl
);
256 ctrl
= throughout_sig
;
259 nodes
[from_node
].links
.push_back(make_pair(to_node
, ctrl
));
262 void make_link_order(vector
<int> &order
, int node
, int min
)
264 order
[node
] = std::max(order
[node
], min
);
265 for (auto &it
: nodes
[node
].links
)
266 make_link_order(order
, it
.first
, order
[node
]+1);
269 // ----------------------------------------------------
270 // Generating NFSM circuit to acquire accept signal
274 log_assert(!materialized
);
277 vector
<Wire
*> state_wire(GetSize(nodes
));
278 vector
<SigBit
> state_sig(GetSize(nodes
));
279 vector
<SigBit
> next_state_sig(GetSize(nodes
));
281 // Create state signals
284 SigBit not_disable
= State::S1
;
286 if (disable_sig
!= State::S0
)
287 not_disable
= module
->Not(NEW_ID
, disable_sig
);
289 for (int i
= 0; i
< GetSize(nodes
); i
++)
291 Wire
*w
= module
->addWire(NEW_ID
);
296 state_sig
[i
] = module
->Or(NEW_ID
, state_sig
[i
], trigger_sig
);
298 if (disable_sig
!= State::S0
)
299 state_sig
[i
] = module
->And(NEW_ID
, state_sig
[i
], not_disable
);
306 vector
<int> node_order(GetSize(nodes
));
307 vector
<vector
<int>> order_to_nodes
;
309 for (int i
= 0; i
< GetSize(nodes
); i
++)
310 make_link_order(node_order
, i
, 0);
312 for (int i
= 0; i
< GetSize(nodes
); i
++) {
313 if (node_order
[i
] >= GetSize(order_to_nodes
))
314 order_to_nodes
.resize(node_order
[i
]+1);
315 order_to_nodes
[node_order
[i
]].push_back(i
);
318 for (int order
= 0; order
< GetSize(order_to_nodes
); order
++)
319 for (int node
: order_to_nodes
[order
])
321 for (auto &it
: nodes
[node
].links
)
323 int target
= it
.first
;
324 SigBit ctrl
= state_sig
[node
];
326 if (it
.second
!= State::S1
)
327 ctrl
= module
->And(NEW_ID
, ctrl
, it
.second
);
329 state_sig
[target
] = module
->Or(NEW_ID
, state_sig
[target
], ctrl
);
334 // Construct activations
337 vector
<SigSpec
> activate_sig(GetSize(nodes
));
338 vector
<SigBit
> activate_bit(GetSize(nodes
));
340 for (int i
= 0; i
< GetSize(nodes
); i
++) {
341 for (auto &it
: nodes
[i
].edges
)
342 activate_sig
[it
.first
].append(module
->And(NEW_ID
, state_sig
[i
], it
.second
));
345 for (int i
= 0; i
< GetSize(nodes
); i
++) {
346 if (GetSize(activate_sig
[i
]) == 0)
347 next_state_sig
[i
] = State::S0
;
348 else if (GetSize(activate_sig
[i
]) == 1)
349 next_state_sig
[i
] = activate_sig
[i
];
351 next_state_sig
[i
] = module
->ReduceOr(NEW_ID
, activate_sig
[i
]);
357 for (int i
= 0; i
< GetSize(nodes
); i
++)
359 if (next_state_sig
[i
] != State::S0
) {
360 clocking
.addDff(NEW_ID
, next_state_sig
[i
], state_wire
[i
], Const(0, 1));
362 module
->connect(state_wire
[i
], State::S0
);
366 final_accept_sig
= state_sig
[acceptNode
];
367 return final_accept_sig
;
370 // ----------------------------------------------------
371 // Generating quantifier-based NFSM circuit to acquire reject signal
373 SigBit
getAnyAllRejectWorker(bool /* allMode */)
379 SigBit
getAnyReject()
381 return getAnyAllRejectWorker(false);
384 SigBit
getAllReject()
386 return getAnyAllRejectWorker(true);
389 // ----------------------------------------------------
390 // Generating DFSM circuit to acquire reject signal
392 void node_to_unode(int node
, int unode
, SigSpec ctrl
)
394 if (node
== acceptNode
)
395 unodes
[unode
].accept
.push_back(ctrl
);
397 if (node
== condNode
)
398 unodes
[unode
].cond
.push_back(ctrl
);
400 for (auto &it
: nodes
[node
].edges
) {
401 if (it
.second
!= State::S1
) {
402 SigSpec s
= {ctrl
, it
.second
};
404 unodes
[unode
].edges
.push_back(make_pair(it
.first
, s
));
406 unodes
[unode
].edges
.push_back(make_pair(it
.first
, ctrl
));
410 for (auto &it
: nodes
[node
].links
) {
411 if (it
.second
!= State::S1
) {
412 SigSpec s
= {ctrl
, it
.second
};
414 node_to_unode(it
.first
, unode
, s
);
416 node_to_unode(it
.first
, unode
, ctrl
);
421 void mark_reachable_unode(int unode
)
423 if (unodes
[unode
].reachable
)
426 unodes
[unode
].reachable
= true;
427 for (auto &it
: unodes
[unode
].edges
)
428 mark_reachable_unode(it
.first
);
431 void usortint(vector
<int> &vec
)
434 std::sort(vec
.begin(), vec
.end());
435 for (int i
= 0; i
< GetSize(vec
); i
++)
436 if (i
== GetSize(vec
)-1 || vec
[i
] != vec
[i
+1])
437 newvec
.push_back(vec
[i
]);
441 bool cmp_ctrl(const pool
<SigBit
> &ctrl_bits
, const SigSpec
&ctrl
)
443 for (int i
= 0; i
< GetSize(ctrl
); i
++)
444 if (ctrl_bits
.count(ctrl
[i
]) == 0)
449 void create_dnode(const vector
<int> &state
, bool firstmatch
, bool condaccept
)
451 if (dnodes
.count(state
) != 0)
455 dnodes
[state
] = SvaDFsmNode();
457 for (int unode
: state
) {
458 log_assert(unodes
[unode
].reachable
);
459 for (auto &it
: unodes
[unode
].edges
)
460 dnode
.ctrl
.append(it
.second
);
461 for (auto &it
: unodes
[unode
].accept
)
462 dnode
.ctrl
.append(it
);
463 for (auto &it
: unodes
[unode
].cond
)
464 dnode
.ctrl
.append(it
);
467 dnode
.ctrl
.sort_and_unify();
469 if (GetSize(dnode
.ctrl
) > verific_sva_fsm_limit
) {
470 if (verific_verbose
>= 2) {
471 log(" detected state explosion in DFSM generation:\n");
473 log(" ctrl signal: %s\n", log_signal(dnode
.ctrl
));
475 log_error("SVA DFSM state ctrl signal has %d (>%d) bits. Stopping to prevent exponential design size explosion.\n",
476 GetSize(dnode
.ctrl
), verific_sva_fsm_limit
);
479 for (int i
= 0; i
< (1 << GetSize(dnode
.ctrl
)); i
++)
481 Const
ctrl_val(i
, GetSize(dnode
.ctrl
));
482 pool
<SigBit
> ctrl_bits
;
484 for (int i
= 0; i
< GetSize(dnode
.ctrl
); i
++)
485 if (ctrl_val
[i
] == State::S1
)
486 ctrl_bits
.insert(dnode
.ctrl
[i
]);
488 vector
<int> new_state
;
489 bool accept
= false, cond
= false;
491 for (int unode
: state
) {
492 for (auto &it
: unodes
[unode
].accept
)
493 if (cmp_ctrl(ctrl_bits
, it
))
495 for (auto &it
: unodes
[unode
].cond
)
496 if (cmp_ctrl(ctrl_bits
, it
))
500 bool new_state_cond
= false;
501 bool new_state_noncond
= false;
503 if (accept
&& condaccept
)
506 if (!accept
|| !firstmatch
) {
507 for (int unode
: state
)
508 for (auto &it
: unodes
[unode
].edges
)
509 if (cmp_ctrl(ctrl_bits
, it
.second
)) {
510 if (nodes
.at(it
.first
).is_cond_node
)
511 new_state_cond
= true;
513 new_state_noncond
= true;
514 new_state
.push_back(it
.first
);
519 dnode
.accept
.push_back(ctrl_val
);
521 if (condaccept
&& (!new_state_cond
|| !new_state_noncond
))
524 if (new_state
.empty()) {
526 dnode
.reject
.push_back(ctrl_val
);
529 dnode
.edges
.push_back(make_pair(new_state
, ctrl_val
));
530 create_dnode(new_state
, firstmatch
, condaccept
);
534 dnodes
[state
] = dnode
;
537 void optimize_cond(vector
<Const
> &values
)
539 bool did_something
= true;
541 while (did_something
)
543 did_something
= false;
545 for (int i
= 0; i
< GetSize(values
); i
++)
546 for (int j
= 0; j
< GetSize(values
); j
++)
551 log_assert(GetSize(values
[i
]) == GetSize(values
[j
]));
554 bool i_within_j
= true;
555 bool j_within_i
= true;
557 for (int k
= 0; k
< GetSize(values
[i
]); k
++) {
558 if (values
[i
][k
] == State::Sa
&& values
[j
][k
] != State::Sa
) {
562 if (values
[i
][k
] != State::Sa
&& values
[j
][k
] == State::Sa
) {
566 if (values
[i
][k
] == values
[j
][k
])
573 if (delta_pos
>= 0 && i_within_j
&& j_within_i
) {
574 did_something
= true;
575 values
[i
][delta_pos
] = State::Sa
;
576 values
[j
] = values
.back();
581 if (delta_pos
< 0 && i_within_j
) {
582 did_something
= true;
583 values
[i
] = values
.back();
588 if (delta_pos
< 0 && j_within_i
) {
589 did_something
= true;
590 values
[j
] = values
.back();
599 SigBit
make_cond_eq(const SigSpec
&ctrl
, const Const
&value
, SigBit enable
= State::S1
)
601 SigSpec sig_a
, sig_b
;
603 log_assert(GetSize(ctrl
) == GetSize(value
));
605 for (int i
= 0; i
< GetSize(ctrl
); i
++)
606 if (value
[i
] != State::Sa
) {
607 sig_a
.append(ctrl
[i
]);
608 sig_b
.append(value
[i
]);
611 if (GetSize(sig_a
) == 0)
614 if (enable
!= State::S1
) {
615 sig_a
.append(enable
);
616 sig_b
.append(State::S1
);
619 auto key
= make_pair(sig_a
, sig_b
);
621 if (cond_eq_cache
.count(key
) == 0)
623 if (sig_b
== State::S1
)
624 cond_eq_cache
[key
] = sig_a
;
625 else if (sig_b
== State::S0
)
626 cond_eq_cache
[key
] = module
->Not(NEW_ID
, sig_a
);
628 cond_eq_cache
[key
] = module
->Eq(NEW_ID
, sig_a
, sig_b
);
630 if (verific_verbose
>= 2) {
631 log(" Cond: %s := %s == %s\n", log_signal(cond_eq_cache
[key
]),
632 log_signal(sig_a
), log_signal(sig_b
));
636 return cond_eq_cache
.at(key
);
639 void getFirstAcceptReject(SigBit
*accept_p
, SigBit
*reject_p
)
641 log_assert(!materialized
);
644 // Create unlinked NFSM
646 unodes
.resize(GetSize(nodes
));
648 for (int node
= 0; node
< GetSize(nodes
); node
++)
649 node_to_unode(node
, node
, SigSpec());
651 mark_reachable_unode(startNode
);
655 create_dnode(vector
<int>{startNode
}, true, false);
658 // Create DFSM Circuit
660 SigSpec accept_sig
, reject_sig
;
662 for (auto &it
: dnodes
)
664 SvaDFsmNode
&dnode
= it
.second
;
665 dnode
.ffoutwire
= module
->addWire(NEW_ID
);
666 dnode
.statesig
= dnode
.ffoutwire
;
668 if (it
.first
== vector
<int>{startNode
})
669 dnode
.statesig
= module
->Or(NEW_ID
, dnode
.statesig
, trigger_sig
);
672 for (auto &it
: dnodes
)
674 SvaDFsmNode
&dnode
= it
.second
;
675 dict
<vector
<int>, vector
<Const
>> edge_cond
;
677 for (auto &edge
: dnode
.edges
)
678 edge_cond
[edge
.first
].push_back(edge
.second
);
680 for (auto &it
: edge_cond
) {
681 optimize_cond(it
.second
);
682 for (auto &value
: it
.second
)
683 dnodes
.at(it
.first
).nextstate
.append(make_cond_eq(dnode
.ctrl
, value
, dnode
.statesig
));
687 vector
<Const
> accept_cond
= dnode
.accept
;
688 optimize_cond(accept_cond
);
689 for (auto &value
: accept_cond
)
690 accept_sig
.append(make_cond_eq(dnode
.ctrl
, value
, dnode
.statesig
));
694 vector
<Const
> reject_cond
= dnode
.reject
;
695 optimize_cond(reject_cond
);
696 for (auto &value
: reject_cond
)
697 reject_sig
.append(make_cond_eq(dnode
.ctrl
, value
, dnode
.statesig
));
701 for (auto &it
: dnodes
)
703 SvaDFsmNode
&dnode
= it
.second
;
704 if (GetSize(dnode
.nextstate
) == 0) {
705 module
->connect(dnode
.ffoutwire
, State::S0
);
707 if (GetSize(dnode
.nextstate
) == 1) {
708 clocking
.addDff(NEW_ID
, dnode
.nextstate
, dnode
.ffoutwire
, State::S0
);
710 SigSpec nextstate
= module
->ReduceOr(NEW_ID
, dnode
.nextstate
);
711 clocking
.addDff(NEW_ID
, nextstate
, dnode
.ffoutwire
, State::S0
);
717 if (GetSize(accept_sig
) == 0)
718 final_accept_sig
= State::S0
;
719 else if (GetSize(accept_sig
) == 1)
720 final_accept_sig
= accept_sig
;
722 final_accept_sig
= module
->ReduceOr(NEW_ID
, accept_sig
);
723 *accept_p
= final_accept_sig
;
728 if (GetSize(reject_sig
) == 0)
729 final_reject_sig
= State::S0
;
730 else if (GetSize(reject_sig
) == 1)
731 final_reject_sig
= reject_sig
;
733 final_reject_sig
= module
->ReduceOr(NEW_ID
, reject_sig
);
734 *reject_p
= final_reject_sig
;
738 SigBit
getFirstAccept()
741 getFirstAcceptReject(&accept
, nullptr);
748 getFirstAcceptReject(nullptr, &reject
);
752 void getDFsm(SvaFsm
&output_fsm
, int output_start_node
, int output_accept_node
, int output_reject_node
= -1, bool firstmatch
= true, bool condaccept
= false)
754 log_assert(!materialized
);
757 // Create unlinked NFSM
759 unodes
.resize(GetSize(nodes
));
761 for (int node
= 0; node
< GetSize(nodes
); node
++)
762 node_to_unode(node
, node
, SigSpec());
764 mark_reachable_unode(startNode
);
768 create_dnode(vector
<int>{startNode
}, firstmatch
, condaccept
);
773 for (auto &it
: dnodes
)
775 SvaDFsmNode
&dnode
= it
.second
;
776 dnode
.outnode
= output_fsm
.createNode();
778 if (it
.first
== vector
<int>{startNode
})
779 output_fsm
.createLink(output_start_node
, dnode
.outnode
);
781 if (output_accept_node
>= 0) {
782 vector
<Const
> accept_cond
= dnode
.accept
;
783 optimize_cond(accept_cond
);
784 for (auto &value
: accept_cond
)
785 output_fsm
.createLink(it
.second
.outnode
, output_accept_node
, make_cond_eq(dnode
.ctrl
, value
));
788 if (output_reject_node
>= 0) {
789 vector
<Const
> reject_cond
= dnode
.reject
;
790 optimize_cond(reject_cond
);
791 for (auto &value
: reject_cond
)
792 output_fsm
.createLink(it
.second
.outnode
, output_reject_node
, make_cond_eq(dnode
.ctrl
, value
));
796 for (auto &it
: dnodes
)
798 SvaDFsmNode
&dnode
= it
.second
;
799 dict
<vector
<int>, vector
<Const
>> edge_cond
;
801 for (auto &edge
: dnode
.edges
)
802 edge_cond
[edge
.first
].push_back(edge
.second
);
804 for (auto &it
: edge_cond
) {
805 optimize_cond(it
.second
);
806 for (auto &value
: it
.second
)
807 output_fsm
.createEdge(dnode
.outnode
, dnodes
.at(it
.first
).outnode
, make_cond_eq(dnode
.ctrl
, value
));
812 // ----------------------------------------------------
813 // State dump for verbose log messages
820 log(" non-deterministic encoding:\n");
821 for (int i
= 0; i
< GetSize(nodes
); i
++)
823 log(" node %d:%s\n", i
,
824 i
== startNode
? " [start]" :
825 i
== acceptNode
? " [accept]" :
826 i
== condNode
? " [cond]" : "");
828 for (auto &it
: nodes
[i
].edges
) {
829 if (it
.second
!= State::S1
)
830 log(" egde %s -> %d\n", log_signal(it
.second
), it
.first
);
832 log(" egde -> %d\n", it
.first
);
835 for (auto &it
: nodes
[i
].links
) {
836 if (it
.second
!= State::S1
)
837 log(" link %s -> %d\n", log_signal(it
.second
), it
.first
);
839 log(" link -> %d\n", it
.first
);
849 log(" unlinked non-deterministic encoding:\n");
850 for (int i
= 0; i
< GetSize(unodes
); i
++)
852 if (!unodes
[i
].reachable
)
855 log(" unode %d:%s\n", i
, i
== startNode
? " [start]" : "");
857 for (auto &it
: unodes
[i
].edges
) {
858 if (!it
.second
.empty())
859 log(" egde %s -> %d\n", log_signal(it
.second
), it
.first
);
861 log(" egde -> %d\n", it
.first
);
864 for (auto &ctrl
: unodes
[i
].accept
) {
866 log(" accept %s\n", log_signal(ctrl
));
871 for (auto &ctrl
: unodes
[i
].cond
) {
873 log(" cond %s\n", log_signal(ctrl
));
885 log(" deterministic encoding:\n");
886 for (auto &it
: dnodes
)
889 for (int i
= 0; i
< GetSize(it
.first
); i
++)
890 log("%s%d", i
? "," : "", it
.first
[i
]);
891 log("}:%s\n", GetSize(it
.first
) == 1 && it
.first
[0] == startNode
? " [start]" : "");
893 log(" ctrl %s\n", log_signal(it
.second
.ctrl
));
895 for (auto &edge
: it
.second
.edges
) {
896 log(" edge %s -> {", log_signal(edge
.second
));
897 for (int i
= 0; i
< GetSize(edge
.first
); i
++)
898 log("%s%d", i
? "," : "", edge
.first
[i
]);
902 for (auto &value
: it
.second
.accept
)
903 log(" accept %s\n", log_signal(value
));
905 for (auto &value
: it
.second
.reject
)
906 log(" reject %s\n", log_signal(value
));
913 log(" number of NFSM states: %d\n", GetSize(nodes
));
915 if (!unodes
.empty()) {
917 for (auto &unode
: unodes
)
920 log(" number of reachable UFSM states: %d\n", count
);
924 log(" number of DFSM states: %d\n", GetSize(dnodes
));
926 if (verific_verbose
>= 2) {
932 if (trigger_sig
!= State::S1
)
933 log(" trigger signal: %s\n", log_signal(trigger_sig
));
935 if (final_accept_sig
!= State::Sx
)
936 log(" accept signal: %s\n", log_signal(final_accept_sig
));
938 if (final_reject_sig
!= State::Sx
)
939 log(" reject signal: %s\n", log_signal(final_reject_sig
));
943 PRIVATE_NAMESPACE_END
945 YOSYS_NAMESPACE_BEGIN
947 pool
<int> verific_sva_prims
= {
948 // Copy&paste from Verific 3.16_484_32_170630 Netlist.h
949 PRIM_SVA_IMMEDIATE_ASSERT
, PRIM_SVA_ASSERT
, PRIM_SVA_COVER
, PRIM_SVA_ASSUME
,
950 PRIM_SVA_EXPECT
, PRIM_SVA_POSEDGE
, PRIM_SVA_NOT
, PRIM_SVA_FIRST_MATCH
,
951 PRIM_SVA_ENDED
, PRIM_SVA_MATCHED
, PRIM_SVA_CONSECUTIVE_REPEAT
,
952 PRIM_SVA_NON_CONSECUTIVE_REPEAT
, PRIM_SVA_GOTO_REPEAT
,
953 PRIM_SVA_MATCH_ITEM_TRIGGER
, PRIM_SVA_AND
, PRIM_SVA_OR
, PRIM_SVA_SEQ_AND
,
954 PRIM_SVA_SEQ_OR
, PRIM_SVA_EVENT_OR
, PRIM_SVA_OVERLAPPED_IMPLICATION
,
955 PRIM_SVA_NON_OVERLAPPED_IMPLICATION
, PRIM_SVA_OVERLAPPED_FOLLOWED_BY
,
956 PRIM_SVA_NON_OVERLAPPED_FOLLOWED_BY
, PRIM_SVA_INTERSECT
, PRIM_SVA_THROUGHOUT
,
957 PRIM_SVA_WITHIN
, PRIM_SVA_AT
, PRIM_SVA_DISABLE_IFF
, PRIM_SVA_SAMPLED
,
958 PRIM_SVA_ROSE
, PRIM_SVA_FELL
, PRIM_SVA_STABLE
, PRIM_SVA_PAST
,
959 PRIM_SVA_MATCH_ITEM_ASSIGN
, PRIM_SVA_SEQ_CONCAT
, PRIM_SVA_IF
,
960 PRIM_SVA_RESTRICT
, PRIM_SVA_TRIGGERED
, PRIM_SVA_STRONG
, PRIM_SVA_WEAK
,
961 PRIM_SVA_NEXTTIME
, PRIM_SVA_S_NEXTTIME
, PRIM_SVA_ALWAYS
, PRIM_SVA_S_ALWAYS
,
962 PRIM_SVA_S_EVENTUALLY
, PRIM_SVA_EVENTUALLY
, PRIM_SVA_UNTIL
, PRIM_SVA_S_UNTIL
,
963 PRIM_SVA_UNTIL_WITH
, PRIM_SVA_S_UNTIL_WITH
, PRIM_SVA_IMPLIES
, PRIM_SVA_IFF
,
964 PRIM_SVA_ACCEPT_ON
, PRIM_SVA_REJECT_ON
, PRIM_SVA_SYNC_ACCEPT_ON
,
965 PRIM_SVA_SYNC_REJECT_ON
, PRIM_SVA_GLOBAL_CLOCKING_DEF
,
966 PRIM_SVA_GLOBAL_CLOCKING_REF
, PRIM_SVA_IMMEDIATE_ASSUME
,
967 PRIM_SVA_IMMEDIATE_COVER
, OPER_SVA_SAMPLED
, OPER_SVA_STABLE
970 struct VerificSvaImporter
972 VerificImporter
*importer
= nullptr;
973 Module
*module
= nullptr;
975 Netlist
*netlist
= nullptr;
976 Instance
*root
= nullptr;
978 VerificClocking clocking
;
980 bool mode_assert
= false;
981 bool mode_assume
= false;
982 bool mode_cover
= false;
983 bool mode_trigger
= false;
985 Instance
*net_to_ast_driver(Net
*n
)
990 if (n
->IsMultipleDriven())
993 Instance
*inst
= n
->Driver();
998 if (!verific_sva_prims
.count(inst
->Type()))
1001 if (inst
->Type() == PRIM_SVA_ROSE
|| inst
->Type() == PRIM_SVA_FELL
||
1002 inst
->Type() == PRIM_SVA_STABLE
|| inst
->Type() == OPER_SVA_STABLE
||
1003 inst
->Type() == PRIM_SVA_PAST
|| inst
->Type() == PRIM_SVA_TRIGGERED
)
1009 Instance
*get_ast_input(Instance
*inst
) { return net_to_ast_driver(inst
->GetInput()); }
1010 Instance
*get_ast_input1(Instance
*inst
) { return net_to_ast_driver(inst
->GetInput1()); }
1011 Instance
*get_ast_input2(Instance
*inst
) { return net_to_ast_driver(inst
->GetInput2()); }
1012 Instance
*get_ast_input3(Instance
*inst
) { return net_to_ast_driver(inst
->GetInput3()); }
1013 Instance
*get_ast_control(Instance
*inst
) { return net_to_ast_driver(inst
->GetControl()); }
1015 // ----------------------------------------------------------
1018 struct ParserErrorException
{
1021 [[noreturn
]] void parser_error(std::string errmsg
)
1023 if (!importer
->mode_keep
)
1024 log_error("%s", errmsg
.c_str());
1025 log_warning("%s", errmsg
.c_str());
1026 throw ParserErrorException();
1029 [[noreturn
]] void parser_error(std::string errmsg
, linefile_type loc
)
1031 parser_error(stringf("%s at %s:%d.\n", errmsg
.c_str(), LineFile::GetFileName(loc
), LineFile::GetLineNo(loc
)));
1034 [[noreturn
]] void parser_error(std::string errmsg
, Instance
*inst
)
1036 parser_error(stringf("%s at %s (%s)", errmsg
.c_str(), inst
->View()->Owner()->Name(), inst
->Name()), inst
->Linefile());
1039 [[noreturn
]] void parser_error(Instance
*inst
)
1041 parser_error(stringf("Verific SVA primitive %s (%s) is currently unsupported in this context",
1042 inst
->View()->Owner()->Name(), inst
->Name()), inst
->Linefile());
1045 dict
<Net
*, bool, hash_ptr_ops
> check_expression_cache
;
1047 bool check_expression(Net
*net
, bool raise_error
= false)
1049 while (!check_expression_cache
.count(net
))
1051 Instance
*inst
= net_to_ast_driver(net
);
1053 if (inst
== nullptr) {
1054 check_expression_cache
[net
] = true;
1058 if (inst
->Type() == PRIM_SVA_AT
)
1060 VerificClocking
new_clocking(importer
, net
);
1061 log_assert(new_clocking
.cond_net
== nullptr);
1062 if (!clocking
.property_matches_sequence(new_clocking
))
1063 parser_error("Mixed clocking is currently not supported", inst
);
1064 check_expression_cache
[net
] = check_expression(new_clocking
.body_net
, raise_error
);
1068 if (inst
->Type() == PRIM_SVA_FIRST_MATCH
|| inst
->Type() == PRIM_SVA_NOT
)
1070 check_expression_cache
[net
] = check_expression(inst
->GetInput(), raise_error
);
1074 if (inst
->Type() == PRIM_SVA_SEQ_OR
|| inst
->Type() == PRIM_SVA_SEQ_AND
|| inst
->Type() == PRIM_SVA_INTERSECT
||
1075 inst
->Type() == PRIM_SVA_WITHIN
|| inst
->Type() == PRIM_SVA_THROUGHOUT
||
1076 inst
->Type() == PRIM_SVA_OR
|| inst
->Type() == PRIM_SVA_AND
)
1078 check_expression_cache
[net
] = check_expression(inst
->GetInput1(), raise_error
) && check_expression(inst
->GetInput2(), raise_error
);
1082 if (inst
->Type() == PRIM_SVA_SEQ_CONCAT
)
1084 const char *sva_low_s
= inst
->GetAttValue("sva:low");
1085 const char *sva_high_s
= inst
->GetAttValue("sva:high");
1087 int sva_low
= atoi(sva_low_s
);
1088 int sva_high
= atoi(sva_high_s
);
1089 bool sva_inf
= !strcmp(sva_high_s
, "$");
1091 if (sva_low
== 0 && sva_high
== 0 && !sva_inf
)
1092 check_expression_cache
[net
] = check_expression(inst
->GetInput1(), raise_error
) && check_expression(inst
->GetInput2(), raise_error
);
1094 check_expression_cache
[net
] = false;
1098 check_expression_cache
[net
] = false;
1101 if (raise_error
&& !check_expression_cache
.at(net
))
1102 parser_error(net_to_ast_driver(net
));
1103 return check_expression_cache
.at(net
);
1106 SigBit
parse_expression(Net
*net
)
1108 check_expression(net
, true);
1110 Instance
*inst
= net_to_ast_driver(net
);
1112 if (inst
== nullptr) {
1113 return importer
->net_map_at(net
);
1116 if (inst
->Type() == PRIM_SVA_AT
)
1118 VerificClocking
new_clocking(importer
, net
);
1119 log_assert(new_clocking
.cond_net
== nullptr);
1120 if (!clocking
.property_matches_sequence(new_clocking
))
1121 parser_error("Mixed clocking is currently not supported", inst
);
1122 return parse_expression(new_clocking
.body_net
);
1125 if (inst
->Type() == PRIM_SVA_FIRST_MATCH
)
1126 return parse_expression(inst
->GetInput());
1128 if (inst
->Type() == PRIM_SVA_NOT
)
1129 return module
->Not(NEW_ID
, parse_expression(inst
->GetInput()));
1131 if (inst
->Type() == PRIM_SVA_SEQ_OR
|| inst
->Type() == PRIM_SVA_OR
)
1132 return module
->Or(NEW_ID
, parse_expression(inst
->GetInput1()), parse_expression(inst
->GetInput2()));
1134 if (inst
->Type() == PRIM_SVA_SEQ_AND
|| inst
->Type() == PRIM_SVA_AND
|| inst
->Type() == PRIM_SVA_INTERSECT
||
1135 inst
->Type() == PRIM_SVA_WITHIN
|| inst
->Type() == PRIM_SVA_THROUGHOUT
|| inst
->Type() == PRIM_SVA_SEQ_CONCAT
)
1136 return module
->And(NEW_ID
, parse_expression(inst
->GetInput1()), parse_expression(inst
->GetInput2()));
1141 bool check_zero_consecutive_repeat(Net
*net
)
1143 Instance
*inst
= net_to_ast_driver(net
);
1145 if (inst
== nullptr)
1148 if (inst
->Type() != PRIM_SVA_CONSECUTIVE_REPEAT
)
1151 const char *sva_low_s
= inst
->GetAttValue("sva:low");
1152 int sva_low
= atoi(sva_low_s
);
1154 return sva_low
== 0;
1157 int parse_consecutive_repeat(SvaFsm
&fsm
, int start_node
, Net
*net
, bool add_pre_delay
, bool add_post_delay
)
1159 Instance
*inst
= net_to_ast_driver(net
);
1161 log_assert(inst
->Type() == PRIM_SVA_CONSECUTIVE_REPEAT
);
1163 const char *sva_low_s
= inst
->GetAttValue("sva:low");
1164 const char *sva_high_s
= inst
->GetAttValue("sva:high");
1166 int sva_low
= atoi(sva_low_s
);
1167 int sva_high
= atoi(sva_high_s
);
1168 bool sva_inf
= !strcmp(sva_high_s
, "$");
1170 Net
*body_net
= inst
->GetInput();
1172 if (add_pre_delay
|| add_post_delay
)
1173 log_assert(sva_low
== 0);
1176 if (!add_pre_delay
&& !add_post_delay
)
1177 parser_error("Possibly zero-length consecutive repeat must follow or precede a delay of at least one cycle", inst
);
1181 int node
= fsm
.createNode(start_node
);
1184 if (add_pre_delay
) {
1185 node
= fsm
.createNode(start_node
);
1186 fsm
.createEdge(start_node
, node
);
1189 int prev_node
= node
;
1190 node
= parse_sequence(fsm
, node
, body_net
);
1192 for (int i
= 1; i
< sva_low
; i
++)
1194 int next_node
= fsm
.createNode();
1195 fsm
.createEdge(node
, next_node
);
1198 node
= parse_sequence(fsm
, next_node
, body_net
);
1203 log_assert(prev_node
>= 0);
1204 fsm
.createEdge(node
, prev_node
);
1208 for (int i
= sva_low
; i
< sva_high
; i
++)
1210 int next_node
= fsm
.createNode();
1211 fsm
.createEdge(node
, next_node
);
1214 node
= parse_sequence(fsm
, next_node
, body_net
);
1216 fsm
.createLink(prev_node
, node
);
1220 if (add_post_delay
) {
1221 int next_node
= fsm
.createNode();
1222 fsm
.createEdge(node
, next_node
);
1226 if (add_pre_delay
|| add_post_delay
)
1227 fsm
.createLink(start_node
, node
);
1232 int parse_sequence(SvaFsm
&fsm
, int start_node
, Net
*net
)
1234 if (check_expression(net
)) {
1235 int node
= fsm
.createNode();
1236 fsm
.createLink(start_node
, node
, parse_expression(net
));
1240 Instance
*inst
= net_to_ast_driver(net
);
1242 if (inst
->Type() == PRIM_SVA_AT
)
1244 VerificClocking
new_clocking(importer
, net
);
1245 log_assert(new_clocking
.cond_net
== nullptr);
1246 if (!clocking
.property_matches_sequence(new_clocking
))
1247 parser_error("Mixed clocking is currently not supported", inst
);
1248 return parse_sequence(fsm
, start_node
, new_clocking
.body_net
);
1251 if (inst
->Type() == PRIM_SVA_FIRST_MATCH
)
1253 SvaFsm
match_fsm(clocking
);
1254 match_fsm
.createLink(parse_sequence(match_fsm
, match_fsm
.createStartNode(), inst
->GetInput()), match_fsm
.acceptNode
);
1256 int node
= fsm
.createNode();
1257 match_fsm
.getDFsm(fsm
, start_node
, node
);
1259 if (verific_verbose
) {
1260 log(" First Match FSM:\n");
1267 if (inst
->Type() == PRIM_SVA_SEQ_CONCAT
)
1269 const char *sva_low_s
= inst
->GetAttValue("sva:low");
1270 const char *sva_high_s
= inst
->GetAttValue("sva:high");
1272 int sva_low
= atoi(sva_low_s
);
1273 int sva_high
= atoi(sva_high_s
);
1274 bool sva_inf
= !strcmp(sva_high_s
, "$");
1277 bool past_add_delay
= false;
1279 if (check_zero_consecutive_repeat(inst
->GetInput1()) && sva_low
> 0) {
1280 node
= parse_consecutive_repeat(fsm
, start_node
, inst
->GetInput1(), false, true);
1281 sva_low
--, sva_high
--;
1283 node
= parse_sequence(fsm
, start_node
, inst
->GetInput1());
1286 if (check_zero_consecutive_repeat(inst
->GetInput2()) && sva_low
> 0) {
1287 past_add_delay
= true;
1288 sva_low
--, sva_high
--;
1291 for (int i
= 0; i
< sva_low
; i
++) {
1292 int next_node
= fsm
.createNode();
1293 fsm
.createEdge(node
, next_node
);
1299 fsm
.createEdge(node
, node
);
1303 for (int i
= sva_low
; i
< sva_high
; i
++)
1305 int next_node
= fsm
.createNode();
1306 fsm
.createEdge(node
, next_node
);
1307 fsm
.createLink(node
, next_node
);
1313 node
= parse_consecutive_repeat(fsm
, node
, inst
->GetInput2(), true, false);
1315 node
= parse_sequence(fsm
, node
, inst
->GetInput2());
1320 if (inst
->Type() == PRIM_SVA_CONSECUTIVE_REPEAT
)
1322 return parse_consecutive_repeat(fsm
, start_node
, net
, false, false);
1325 if (inst
->Type() == PRIM_SVA_NON_CONSECUTIVE_REPEAT
|| inst
->Type() == PRIM_SVA_GOTO_REPEAT
)
1327 const char *sva_low_s
= inst
->GetAttValue("sva:low");
1328 const char *sva_high_s
= inst
->GetAttValue("sva:high");
1330 int sva_low
= atoi(sva_low_s
);
1331 int sva_high
= atoi(sva_high_s
);
1332 bool sva_inf
= !strcmp(sva_high_s
, "$");
1334 Net
*body_net
= inst
->GetInput();
1335 int node
= fsm
.createNode(start_node
);
1337 SigBit cond
= parse_expression(body_net
);
1338 SigBit not_cond
= module
->Not(NEW_ID
, cond
);
1340 for (int i
= 0; i
< sva_low
; i
++)
1342 int wait_node
= fsm
.createNode();
1343 fsm
.createEdge(wait_node
, wait_node
, not_cond
);
1346 fsm
.createLink(node
, wait_node
);
1348 fsm
.createEdge(node
, wait_node
);
1350 int next_node
= fsm
.createNode();
1351 fsm
.createLink(wait_node
, next_node
, cond
);
1358 int wait_node
= fsm
.createNode();
1359 fsm
.createEdge(wait_node
, wait_node
, not_cond
);
1360 fsm
.createEdge(node
, wait_node
);
1361 fsm
.createLink(wait_node
, node
, cond
);
1365 for (int i
= sva_low
; i
< sva_high
; i
++)
1367 int wait_node
= fsm
.createNode();
1368 fsm
.createEdge(wait_node
, wait_node
, not_cond
);
1371 fsm
.createLink(node
, wait_node
);
1373 fsm
.createEdge(node
, wait_node
);
1375 int next_node
= fsm
.createNode();
1376 fsm
.createLink(wait_node
, next_node
, cond
);
1378 fsm
.createLink(node
, next_node
);
1383 if (inst
->Type() == PRIM_SVA_NON_CONSECUTIVE_REPEAT
)
1384 fsm
.createEdge(node
, node
);
1389 if (inst
->Type() == PRIM_SVA_SEQ_OR
|| inst
->Type() == PRIM_SVA_OR
)
1391 int node
= parse_sequence(fsm
, start_node
, inst
->GetInput1());
1392 int node2
= parse_sequence(fsm
, start_node
, inst
->GetInput2());
1393 fsm
.createLink(node2
, node
);
1397 if (inst
->Type() == PRIM_SVA_SEQ_AND
|| inst
->Type() == PRIM_SVA_AND
)
1399 SvaFsm
fsm1(clocking
);
1400 fsm1
.createLink(parse_sequence(fsm1
, fsm1
.createStartNode(), inst
->GetInput1()), fsm1
.acceptNode
);
1402 SvaFsm
fsm2(clocking
);
1403 fsm2
.createLink(parse_sequence(fsm2
, fsm2
.createStartNode(), inst
->GetInput2()), fsm2
.acceptNode
);
1405 SvaFsm
combined_fsm(clocking
);
1406 fsm1
.getDFsm(combined_fsm
, combined_fsm
.createStartNode(), -1, combined_fsm
.acceptNode
);
1407 fsm2
.getDFsm(combined_fsm
, combined_fsm
.createStartNode(), -1, combined_fsm
.acceptNode
);
1409 int node
= fsm
.createNode();
1410 combined_fsm
.getDFsm(fsm
, start_node
, -1, node
);
1412 if (verific_verbose
)
1414 log(" Left And FSM:\n");
1417 log(" Right And FSM:\n");
1420 log(" Combined And FSM:\n");
1421 combined_fsm
.dump();
1427 if (inst
->Type() == PRIM_SVA_INTERSECT
|| inst
->Type() == PRIM_SVA_WITHIN
)
1429 SvaFsm
intersect_fsm(clocking
);
1431 if (inst
->Type() == PRIM_SVA_INTERSECT
)
1433 intersect_fsm
.createLink(parse_sequence(intersect_fsm
, intersect_fsm
.createStartNode(), inst
->GetInput1()), intersect_fsm
.acceptNode
);
1437 int n
= intersect_fsm
.createNode();
1438 intersect_fsm
.createLink(intersect_fsm
.createStartNode(), n
);
1439 intersect_fsm
.createEdge(n
, n
);
1441 n
= parse_sequence(intersect_fsm
, n
, inst
->GetInput1());
1443 intersect_fsm
.createLink(n
, intersect_fsm
.acceptNode
);
1444 intersect_fsm
.createEdge(n
, n
);
1447 intersect_fsm
.in_cond_mode
= true;
1448 intersect_fsm
.createLink(parse_sequence(intersect_fsm
, intersect_fsm
.createStartNode(), inst
->GetInput2()), intersect_fsm
.condNode
);
1449 intersect_fsm
.in_cond_mode
= false;
1451 int node
= fsm
.createNode();
1452 intersect_fsm
.getDFsm(fsm
, start_node
, node
, -1, false, true);
1454 if (verific_verbose
) {
1455 log(" Intersect FSM:\n");
1456 intersect_fsm
.dump();
1462 if (inst
->Type() == PRIM_SVA_THROUGHOUT
)
1464 SigBit expr
= parse_expression(inst
->GetInput1());
1466 fsm
.pushThroughout(expr
);
1467 int node
= parse_sequence(fsm
, start_node
, inst
->GetInput2());
1468 fsm
.popThroughout();
1476 void get_fsm_accept_reject(SvaFsm
&fsm
, SigBit
*accept_p
, SigBit
*reject_p
, bool swap_accept_reject
= false)
1478 log_assert(accept_p
!= nullptr || reject_p
!= nullptr);
1480 if (swap_accept_reject
)
1481 get_fsm_accept_reject(fsm
, reject_p
, accept_p
);
1482 else if (reject_p
== nullptr)
1483 *accept_p
= fsm
.getAccept();
1484 else if (accept_p
== nullptr)
1485 *reject_p
= fsm
.getReject();
1487 fsm
.getFirstAcceptReject(accept_p
, reject_p
);
1490 bool eventually_property(Net
*&net
, SigBit
&trig
)
1492 Instance
*inst
= net_to_ast_driver(net
);
1494 if (inst
== nullptr)
1497 if (clocking
.cond_net
!= nullptr)
1498 trig
= importer
->net_map_at(clocking
.cond_net
);
1502 if (inst
->Type() == PRIM_SVA_S_EVENTUALLY
|| inst
->Type() == PRIM_SVA_EVENTUALLY
)
1504 if (mode_cover
|| mode_trigger
)
1507 net
= inst
->GetInput();
1508 clocking
.cond_net
= nullptr;
1513 if (inst
->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION
||
1514 inst
->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION
)
1516 Net
*antecedent_net
= inst
->GetInput1();
1517 Net
*consequent_net
= inst
->GetInput2();
1519 Instance
*consequent_inst
= net_to_ast_driver(consequent_net
);
1521 if (consequent_inst
== nullptr)
1524 if (consequent_inst
->Type() != PRIM_SVA_S_EVENTUALLY
&& consequent_inst
->Type() != PRIM_SVA_EVENTUALLY
)
1527 if (mode_cover
|| mode_trigger
)
1528 parser_error(consequent_inst
);
1532 SvaFsm
antecedent_fsm(clocking
, trig
);
1533 node
= parse_sequence(antecedent_fsm
, antecedent_fsm
.createStartNode(), antecedent_net
);
1534 if (inst
->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION
) {
1535 int next_node
= antecedent_fsm
.createNode();
1536 antecedent_fsm
.createEdge(node
, next_node
);
1539 antecedent_fsm
.createLink(node
, antecedent_fsm
.acceptNode
);
1541 trig
= antecedent_fsm
.getAccept();
1542 net
= consequent_inst
->GetInput();
1543 clocking
.cond_net
= nullptr;
1545 if (verific_verbose
) {
1546 log(" Eventually Antecedent FSM:\n");
1547 antecedent_fsm
.dump();
1556 void parse_property(Net
*net
, SigBit
*accept_p
, SigBit
*reject_p
)
1558 Instance
*inst
= net_to_ast_driver(net
);
1560 SigBit trig
= State::S1
;
1562 if (clocking
.cond_net
!= nullptr)
1563 trig
= importer
->net_map_at(clocking
.cond_net
);
1565 if (inst
== nullptr)
1567 log_assert(trig
== State::S1
);
1569 if (accept_p
!= nullptr)
1570 *accept_p
= importer
->net_map_at(net
);
1571 if (reject_p
!= nullptr)
1572 *reject_p
= module
->Not(NEW_ID
, importer
->net_map_at(net
));
1575 if (inst
->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION
||
1576 inst
->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION
)
1578 Net
*antecedent_net
= inst
->GetInput1();
1579 Net
*consequent_net
= inst
->GetInput2();
1582 SvaFsm
antecedent_fsm(clocking
, trig
);
1583 node
= parse_sequence(antecedent_fsm
, antecedent_fsm
.createStartNode(), antecedent_net
);
1584 if (inst
->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION
) {
1585 int next_node
= antecedent_fsm
.createNode();
1586 antecedent_fsm
.createEdge(node
, next_node
);
1590 Instance
*consequent_inst
= net_to_ast_driver(consequent_net
);
1592 if (consequent_inst
&& (consequent_inst
->Type() == PRIM_SVA_UNTIL
|| consequent_inst
->Type() == PRIM_SVA_S_UNTIL
||
1593 consequent_inst
->Type() == PRIM_SVA_UNTIL_WITH
|| consequent_inst
->Type() == PRIM_SVA_S_UNTIL_WITH
))
1595 bool until_with
= consequent_inst
->Type() == PRIM_SVA_UNTIL_WITH
|| consequent_inst
->Type() == PRIM_SVA_S_UNTIL_WITH
;
1597 Net
*until_net
= consequent_inst
->GetInput2();
1598 consequent_net
= consequent_inst
->GetInput1();
1599 consequent_inst
= net_to_ast_driver(consequent_net
);
1601 SigBit until_sig
= parse_expression(until_net
);
1602 SigBit not_until_sig
= module
->Not(NEW_ID
, until_sig
);
1603 antecedent_fsm
.createEdge(node
, node
, not_until_sig
);
1605 antecedent_fsm
.createLink(node
, antecedent_fsm
.acceptNode
, until_with
? State::S1
: not_until_sig
);
1609 antecedent_fsm
.createLink(node
, antecedent_fsm
.acceptNode
);
1612 SigBit antecedent_match
= antecedent_fsm
.getAccept();
1614 if (verific_verbose
) {
1615 log(" Antecedent FSM:\n");
1616 antecedent_fsm
.dump();
1619 bool consequent_not
= false;
1620 if (consequent_inst
&& consequent_inst
->Type() == PRIM_SVA_NOT
) {
1621 consequent_not
= true;
1622 consequent_net
= consequent_inst
->GetInput();
1623 consequent_inst
= net_to_ast_driver(consequent_net
);
1626 SvaFsm
consequent_fsm(clocking
, antecedent_match
);
1627 node
= parse_sequence(consequent_fsm
, consequent_fsm
.createStartNode(), consequent_net
);
1628 consequent_fsm
.createLink(node
, consequent_fsm
.acceptNode
);
1630 get_fsm_accept_reject(consequent_fsm
, accept_p
, reject_p
, consequent_not
);
1632 if (verific_verbose
) {
1633 log(" Consequent FSM:\n");
1634 consequent_fsm
.dump();
1639 bool prop_not
= inst
->Type() == PRIM_SVA_NOT
;
1641 net
= inst
->GetInput();
1642 inst
= net_to_ast_driver(net
);
1645 SvaFsm
fsm(clocking
, trig
);
1646 int node
= parse_sequence(fsm
, fsm
.createStartNode(), net
);
1647 fsm
.createLink(node
, fsm
.acceptNode
);
1649 get_fsm_accept_reject(fsm
, accept_p
, reject_p
, prop_not
);
1651 if (verific_verbose
) {
1652 log(" Sequence FSM:\n");
1662 module
= importer
->module
;
1663 netlist
= root
->Owner();
1665 if (verific_verbose
)
1666 log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root
->Name(), root
->View()->Owner()->Name(),
1667 LineFile::GetFileName(root
->Linefile()), LineFile::GetLineNo(root
->Linefile()));
1669 RTLIL::IdString root_name
= module
->uniquify(importer
->mode_names
|| root
->IsUserDeclared() ? RTLIL::escape_id(root
->Name()) : NEW_ID
);
1671 // parse SVA sequence into trigger signal
1673 clocking
= VerificClocking(importer
, root
->GetInput(), true);
1674 SigBit accept_bit
= State::S0
, reject_bit
= State::S0
;
1676 if (clocking
.body_net
== nullptr)
1678 if (clocking
.clock_net
!= nullptr || clocking
.enable_net
!= nullptr || clocking
.disable_net
!= nullptr || clocking
.cond_net
!= nullptr)
1679 parser_error(stringf("Failed to parse SVA clocking"), root
);
1681 if (mode_assert
|| mode_assume
) {
1682 reject_bit
= module
->Not(NEW_ID
, parse_expression(root
->GetInput()));
1684 accept_bit
= parse_expression(root
->GetInput());
1689 Net
*net
= clocking
.body_net
;
1692 if (eventually_property(net
, trig
))
1694 SigBit sig_a
, sig_en
= trig
;
1695 parse_property(net
, &sig_a
, nullptr);
1697 // add final FF stage
1699 SigBit sig_a_q
, sig_en_q
;
1701 if (clocking
.body_net
== nullptr) {
1705 sig_a_q
= module
->addWire(NEW_ID
);
1706 sig_en_q
= module
->addWire(NEW_ID
);
1707 clocking
.addDff(NEW_ID
, sig_a
, sig_a_q
, State::S0
);
1708 clocking
.addDff(NEW_ID
, sig_en
, sig_en_q
, State::S0
);
1711 // generate fair/live cell
1713 RTLIL::Cell
*c
= nullptr;
1715 if (mode_assert
) c
= module
->addLive(root_name
, sig_a_q
, sig_en_q
);
1716 if (mode_assume
) c
= module
->addFair(root_name
, sig_a_q
, sig_en_q
);
1718 importer
->import_attributes(c
->attributes
, root
);
1724 if (mode_assert
|| mode_assume
) {
1725 parse_property(net
, nullptr, &reject_bit
);
1727 parse_property(net
, &accept_bit
, nullptr);
1734 module
->connect(importer
->net_map_at(root
->GetOutput()), accept_bit
);
1738 SigBit sig_a
= module
->Not(NEW_ID
, reject_bit
);
1739 SigBit sig_en
= module
->Or(NEW_ID
, accept_bit
, reject_bit
);
1741 // add final FF stage
1743 SigBit sig_a_q
, sig_en_q
;
1745 if (clocking
.body_net
== nullptr) {
1749 sig_a_q
= module
->addWire(NEW_ID
);
1750 sig_en_q
= module
->addWire(NEW_ID
);
1751 clocking
.addDff(NEW_ID
, sig_a
, sig_a_q
, State::S0
);
1752 clocking
.addDff(NEW_ID
, sig_en
, sig_en_q
, State::S0
);
1755 // generate assert/assume/cover cell
1757 RTLIL::Cell
*c
= nullptr;
1759 if (mode_assert
) c
= module
->addAssert(root_name
, sig_a_q
, sig_en_q
);
1760 if (mode_assume
) c
= module
->addAssume(root_name
, sig_a_q
, sig_en_q
);
1761 if (mode_cover
) c
= module
->addCover(root_name
, sig_a_q
, sig_en_q
);
1763 importer
->import_attributes(c
->attributes
, root
);
1766 catch (ParserErrorException
)
1772 void verific_import_sva_assert(VerificImporter
*importer
, Instance
*inst
)
1774 VerificSvaImporter worker
;
1775 worker
.importer
= importer
;
1777 worker
.mode_assert
= true;
1781 void verific_import_sva_assume(VerificImporter
*importer
, Instance
*inst
)
1783 VerificSvaImporter worker
;
1784 worker
.importer
= importer
;
1786 worker
.mode_assume
= true;
1790 void verific_import_sva_cover(VerificImporter
*importer
, Instance
*inst
)
1792 VerificSvaImporter worker
;
1793 worker
.importer
= importer
;
1795 worker
.mode_cover
= true;
1799 void verific_import_sva_trigger(VerificImporter
*importer
, Instance
*inst
)
1801 VerificSvaImporter worker
;
1802 worker
.importer
= importer
;
1804 worker
.mode_trigger
= true;
1808 bool verific_is_sva_net(VerificImporter
*importer
, Verific::Net
*net
)
1810 VerificSvaImporter worker
;
1811 worker
.importer
= importer
;
1812 return worker
.net_to_ast_driver(net
) != nullptr;