@@ -32,16 +32,17 @@ struct Smt2Worker
32
32
CellTypes ct;
33
33
SigMap sigmap;
34
34
RTLIL::Module *module ;
35
- bool bvmode, memmode, wiresmode, verbose, statebv, statedt;
35
+ bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode ;
36
36
dict<IdString, int > &mod_stbv_width;
37
- int idcounter, statebv_width;
37
+ int idcounter = 0 , statebv_width = 0 ;
38
38
39
39
std::vector<std::string> decls, trans, hier, dtmembers;
40
40
std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver;
41
41
std::set<RTLIL::Cell*> exported_cells, hiercells, hiercells_queue;
42
42
pool<Cell*> recursive_cells, registers;
43
43
44
44
pool<SigBit> clock_posedge, clock_negedge;
45
+ vector<string> ex_state_eq, ex_input_eq;
45
46
46
47
std::map<RTLIL::SigBit, std::pair<int , int >> fcache;
47
48
std::map<Cell*, int > memarrays;
@@ -106,10 +107,10 @@ struct Smt2Worker
106
107
decls.push_back (decl_str + " \n " );
107
108
}
108
109
109
- Smt2Worker (RTLIL::Module *module , bool bvmode, bool memmode, bool wiresmode, bool verbose, bool statebv, bool statedt,
110
+ Smt2Worker (RTLIL::Module *module , bool bvmode, bool memmode, bool wiresmode, bool verbose, bool statebv, bool statedt, bool forallmode,
110
111
dict<IdString, int > &mod_stbv_width, dict<IdString, dict<IdString, pair<bool , bool >>> &mod_clk_cache) :
111
112
ct (module ->design), sigmap(module ), module (module ), bvmode(bvmode), memmode(memmode), wiresmode(wiresmode),
112
- verbose (verbose), statebv(statebv), statedt(statedt), mod_stbv_width(mod_stbv_width ), idcounter( 0 ), statebv_width( 0 )
113
+ verbose (verbose), statebv(statebv), statedt(statedt), forallmode(forallmode ), mod_stbv_width(mod_stbv_width )
113
114
{
114
115
pool<SigBit> noclock;
115
116
@@ -507,14 +508,16 @@ struct Smt2Worker
507
508
return ;
508
509
}
509
510
510
- if (cell->type .in (" $anyconst" , " $anyseq" ))
511
+ if (cell->type .in (" $anyconst" , " $anyseq" , " $allconst " , " $allseq " ))
511
512
{
512
513
registers.insert (cell);
513
514
string infostr = cell->attributes .count (" \\ src" ) ? cell->attributes .at (" \\ src" ).decode_string ().c_str () : get_id (cell);
514
515
if (cell->attributes .count (" \\ reg" ))
515
516
infostr += " " + cell->attributes .at (" \\ reg" ).decode_string ();
516
- decls.push_back (stringf (" ; yosys-smt2-%s %s#%d %s\n " , cell->type .c_str () + 1 , get_id (module ), idcounter, infostr.c_str ()));
517
+ decls.push_back (stringf (" ; yosys-smt2-%s %s#%d %d % s\n " , cell->type .c_str () + 1 , get_id (module ), idcounter, GetSize (cell-> getPort ( " \\ Y " )) , infostr.c_str ()));
517
518
makebits (stringf (" %s#%d" , get_id (module ), idcounter), GetSize (cell->getPort (" \\ Y" )), log_signal (cell->getPort (" \\ Y" )));
519
+ if (cell->type == " $anyseq" )
520
+ ex_input_eq.push_back (stringf (" (= (|%s#%d| state) (|%s#%d| other_state))" , get_id (module ), idcounter, get_id (module ), idcounter));
518
521
register_bv (cell->getPort (" \\ Y" ), idcounter++);
519
522
recursive_cells.erase (cell);
520
523
return ;
@@ -787,14 +790,24 @@ struct Smt2Worker
787
790
if (bvmode && GetSize (sig) > 1 ) {
788
791
decls.push_back (stringf (" (define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n " ,
789
792
get_id (module ), get_id (wire), get_id (module ), GetSize (sig), get_bv (sig).c_str ()));
793
+ if (wire->port_input )
794
+ ex_input_eq.push_back (stringf (" (= (|%s_n %s| state) (|%s_n %s| other_state))" ,
795
+ get_id (module ), get_id (wire), get_id (module ), get_id (wire)));
790
796
} else {
791
797
for (int i = 0 ; i < GetSize (sig); i++)
792
- if (GetSize (sig) > 1 )
798
+ if (GetSize (sig) > 1 ) {
793
799
decls.push_back (stringf (" (define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n " ,
794
800
get_id (module ), get_id (wire), i, get_id (module ), get_bool (sig[i]).c_str ()));
795
- else
801
+ if (wire->port_input )
802
+ ex_input_eq.push_back (stringf (" (= (|%s_n %s %d| state) (|%s_n %s %d| other_state))" ,
803
+ get_id (module ), get_id (wire), i, get_id (module ), get_id (wire), i));
804
+ } else {
796
805
decls.push_back (stringf (" (define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n " ,
797
806
get_id (module ), get_id (wire), get_id (module ), get_bool (sig[i]).c_str ()));
807
+ if (wire->port_input )
808
+ ex_input_eq.push_back (stringf (" (= (|%s_n %s| state) (|%s_n %s| other_state))" ,
809
+ get_id (module ), get_id (wire), get_id (module ), get_id (wire)));
810
+ }
798
811
}
799
812
}
800
813
}
@@ -919,20 +932,24 @@ struct Smt2Worker
919
932
std::string expr_d = get_bool (cell->getPort (" \\ D" ));
920
933
std::string expr_q = get_bool (cell->getPort (" \\ Q" ), " next_state" );
921
934
trans.push_back (stringf (" (= %s %s) ; %s %s\n " , expr_d.c_str (), expr_q.c_str (), get_id (cell), log_signal (cell->getPort (" \\ Q" ))));
935
+ ex_state_eq.push_back (stringf (" (= %s %s)" , get_bool (cell->getPort (" \\ Q" )).c_str (), get_bool (cell->getPort (" \\ Q" ), " other_state" ).c_str ()));
922
936
}
923
937
924
938
if (cell->type .in (" $ff" , " $dff" ))
925
939
{
926
940
std::string expr_d = get_bv (cell->getPort (" \\ D" ));
927
941
std::string expr_q = get_bv (cell->getPort (" \\ Q" ), " next_state" );
928
942
trans.push_back (stringf (" (= %s %s) ; %s %s\n " , expr_d.c_str (), expr_q.c_str (), get_id (cell), log_signal (cell->getPort (" \\ Q" ))));
943
+ ex_state_eq.push_back (stringf (" (= %s %s)" , get_bv (cell->getPort (" \\ Q" )).c_str (), get_bv (cell->getPort (" \\ Q" ), " other_state" ).c_str ()));
929
944
}
930
945
931
- if (cell->type == " $anyconst" )
946
+ if (cell->type . in ( " $anyconst" , " $allconst " ) )
932
947
{
933
948
std::string expr_d = get_bv (cell->getPort (" \\ Y" ));
934
949
std::string expr_q = get_bv (cell->getPort (" \\ Y" ), " next_state" );
935
950
trans.push_back (stringf (" (= %s %s) ; %s %s\n " , expr_d.c_str (), expr_q.c_str (), get_id (cell), log_signal (cell->getPort (" \\ Y" ))));
951
+ if (cell->type == " $anyconst" )
952
+ ex_state_eq.push_back (stringf (" (= %s %s)" , get_bv (cell->getPort (" \\ Y" )).c_str (), get_bv (cell->getPort (" \\ Y" ), " other_state" ).c_str ()));
936
953
}
937
954
938
955
if (cell->type == " $mem" )
@@ -1044,6 +1061,7 @@ struct Smt2Worker
1044
1061
std::string expr_d = stringf (" (|%s#%d#%d| state)" , get_id (module ), arrayid, wr_ports);
1045
1062
std::string expr_q = stringf (" (|%s#%d#0| next_state)" , get_id (module ), arrayid);
1046
1063
trans.push_back (stringf (" (= %s %s) ; %s\n " , expr_d.c_str (), expr_q.c_str (), get_id (cell)));
1064
+ ex_state_eq.push_back (stringf (" (= (|%s#%d#0| state) (|%s#%d#0| other_state))" , get_id (module ), arrayid, get_id (module ), arrayid));
1047
1065
1048
1066
if (async_read)
1049
1067
hier.push_back (stringf (" (= %s (|%s| state)) ; %s\n " , expr_d.c_str (), final_memstate.c_str (), get_id (cell)));
@@ -1086,6 +1104,37 @@ struct Smt2Worker
1086
1104
hier.push_back (stringf (" (|%s_h| (|%s_h %s| state))\n " , get_id (c->type ), get_id (module ), get_id (c->name )));
1087
1105
trans.push_back (stringf (" (|%s_t| (|%s_h %s| state) (|%s_h %s| next_state))\n " ,
1088
1106
get_id (c->type ), get_id (module ), get_id (c->name ), get_id (module ), get_id (c->name )));
1107
+ ex_state_eq.push_back (stringf (" (|%s_ex_state_eq| (|%s_h %s| state) (|%s_h %s| other_state))\n " ,
1108
+ get_id (c->type ), get_id (module ), get_id (c->name ), get_id (module ), get_id (c->name )));
1109
+ }
1110
+
1111
+ if (forallmode)
1112
+ {
1113
+ string expr = ex_state_eq.empty () ? " true" : " (and" ;
1114
+ if (!ex_state_eq.empty ()) {
1115
+ if (GetSize (ex_state_eq) == 1 ) {
1116
+ expr = " \n " + ex_state_eq.front () + " \n " ;
1117
+ } else {
1118
+ for (auto &str : ex_state_eq)
1119
+ expr += stringf (" \n %s" , str.c_str ());
1120
+ expr += " \n )" ;
1121
+ }
1122
+ }
1123
+ decls.push_back (stringf (" (define-fun |%s_ex_state_eq| ((state |%s_s|) (other_state |%s_s|)) Bool %s)\n " ,
1124
+ get_id (module ), get_id (module ), get_id (module ), expr.c_str ()));
1125
+
1126
+ expr = ex_input_eq.empty () ? " true" : " (and" ;
1127
+ if (!ex_input_eq.empty ()) {
1128
+ if (GetSize (ex_input_eq) == 1 ) {
1129
+ expr = " \n " + ex_input_eq.front () + " \n " ;
1130
+ } else {
1131
+ for (auto &str : ex_input_eq)
1132
+ expr += stringf (" \n %s" , str.c_str ());
1133
+ expr += " \n )" ;
1134
+ }
1135
+ }
1136
+ decls.push_back (stringf (" (define-fun |%s_ex_input_eq| ((state |%s_s|) (other_state |%s_s|)) Bool %s)\n " ,
1137
+ get_id (module ), get_id (module ), get_id (module ), expr.c_str ()));
1089
1138
}
1090
1139
1091
1140
string assert_expr = assert_list.empty () ? " true" : " (and" ;
@@ -1336,6 +1385,7 @@ struct Smt2Backend : public Backend {
1336
1385
{
1337
1386
std::ifstream template_f;
1338
1387
bool bvmode = true , memmode = true , wiresmode = false , verbose = false , statebv = false , statedt = false ;
1388
+ bool forallmode = false ;
1339
1389
1340
1390
log_header (design, " Executing SMT2 backend.\n " );
1341
1391
@@ -1443,14 +1493,26 @@ struct Smt2Backend : public Backend {
1443
1493
Module *topmod = design->top_module ();
1444
1494
std::string topmod_id;
1445
1495
1496
+ for (auto module : sorted_modules)
1497
+ for (auto cell : module ->cells ())
1498
+ if (cell->type .in (" $allconst" , " $allseq" ))
1499
+ goto found_forall;
1500
+ if (0 ) {
1501
+ found_forall:
1502
+ forallmode = true ;
1503
+ *f << stringf (" ; yosys-smt2-forall\n " );
1504
+ if (!statebv && !statedt)
1505
+ log_error (" Forall-exists problems are only supported in -stbv or -stdt mode.\n " );
1506
+ }
1507
+
1446
1508
for (auto module : sorted_modules)
1447
1509
{
1448
1510
if (module ->get_bool_attribute (" \\ blackbox" ) || module ->has_memories_warn () || module ->has_processes_warn ())
1449
1511
continue ;
1450
1512
1451
1513
log (" Creating SMT-LIBv2 representation of module %s.\n " , log_id (module ));
1452
1514
1453
- Smt2Worker worker (module , bvmode, memmode, wiresmode, verbose, statebv, statedt, mod_stbv_width, mod_clk_cache);
1515
+ Smt2Worker worker (module , bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache);
1454
1516
worker.run ();
1455
1517
worker.write (*f);
1456
1518
0 commit comments