summaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/blif/blif.cc11
-rw-r--r--backends/ilang/ilang_backend.cc8
-rw-r--r--backends/smt2/smt2.cc14
-rw-r--r--backends/smt2/smtbmc.py63
-rw-r--r--backends/smt2/smtio.py101
-rw-r--r--backends/verilog/verilog_backend.cc28
6 files changed, 188 insertions, 37 deletions
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index 6a379e67..d9d0cc17 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -77,9 +77,6 @@ struct BlifDumper
case State::S1:
init_bits[initsig[i]] = 1;
break;
- case State::Sx:
- init_bits[initsig[i]] = 2;
- break;
default:
break;
}
@@ -126,7 +123,7 @@ struct BlifDumper
sigmap.apply(sig);
if (init_bits.count(sig) == 0)
- return "";
+ return " 2";
string str = stringf(" %d", init_bits.at(sig));
@@ -315,6 +312,12 @@ struct BlifDumper
continue;
}
+ if (!config->icells_mode && cell->type == "$_FF_") {
+ f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
+ cstr_init(cell->getPort("\\Q")));
+ continue;
+ }
+
if (!config->icells_mode && cell->type == "$_DFF_N_") {
f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q")));
diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc
index 03e29c52..16d1a97f 100644
--- a/backends/ilang/ilang_backend.cc
+++ b/backends/ilang/ilang_backend.cc
@@ -228,6 +228,7 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
f << stringf("\n");
break;
case RTLIL::STa: f << stringf("always\n"); break;
+ case RTLIL::STg: f << stringf("global\n"); break;
case RTLIL::STi: f << stringf("init\n"); break;
}
@@ -277,6 +278,13 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
}
f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str());
+
+ if (!module->avail_parameters.empty()) {
+ if (only_selected)
+ f << stringf("\n");
+ for (auto &p : module->avail_parameters)
+ f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str());
+ }
}
if (print_body)
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index 9a25f3a2..ddac6900 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -379,7 +379,7 @@ struct Smt2Worker
return;
}
- if (cell->type == "$_DFF_P_" || cell->type == "$_DFF_N_")
+ if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_"))
{
registers.insert(cell);
decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n",
@@ -407,7 +407,7 @@ struct Smt2Worker
if (bvmode)
{
- if (cell->type == "$dff")
+ if (cell->type.in("$ff", "$dff"))
{
registers.insert(cell);
decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n",
@@ -417,7 +417,7 @@ struct Smt2Worker
return;
}
- if (cell->type == "$anyconst")
+ if (cell->type.in("$anyconst", "$anyseq"))
{
registers.insert(cell);
decls.push_back(stringf("; yosys-smt2-%s %s#%d %s\n", cell->type.c_str() + 1, get_id(module), idcounter,
@@ -586,7 +586,7 @@ struct Smt2Worker
return;
}
- log_error("Unsupported cell type %s for cell %s.%s. (Maybe this cell type would be supported in -bv or -mem mode?)\n",
+ log_error("Unsupported cell type %s for cell %s.%s.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
@@ -596,7 +596,7 @@ struct Smt2Worker
pool<SigBit> reg_bits;
for (auto cell : module->cells())
- if (cell->type.in("$_DFF_P_", "$_DFF_N_", "$dff")) {
+ if (cell->type.in("$ff", "$dff", "$_FF_", "$_DFF_P_", "$_DFF_N_")) {
// not using sigmap -- we want the net directly at the dff output
for (auto bit : cell->getPort("\\Q"))
reg_bits.insert(bit);
@@ -674,14 +674,14 @@ struct Smt2Worker
for (auto cell : this_regs)
{
- if (cell->type == "$_DFF_P_" || cell->type == "$_DFF_N_")
+ if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_"))
{
std::string expr_d = get_bool(cell->getPort("\\D"));
std::string expr_q = get_bool(cell->getPort("\\Q"), "next_state");
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"))));
}
- if (cell->type == "$dff")
+ if (cell->type.in("$ff", "$dff"))
{
std::string expr_d = get_bv(cell->getPort("\\D"));
std::string expr_q = get_bv(cell->getPort("\\Q"), "next_state");
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index bb763647..04c25f91 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -26,6 +26,7 @@ skip_steps = 0
step_size = 1
num_steps = 20
vcdfile = None
+cexfile = None
vlogtbfile = None
inconstr = list()
outconstr = None
@@ -61,6 +62,9 @@ yosys-smtbmc [options] <yosys_smt2_output>
--smtc <constr_filename>
read constraints file
+ --cex <cex_filename>
+ read cex file as written by ABC's "write_cex -n"
+
--noinfo
only run the core proof, do not collect and print any
additional information (e.g. which assert failed)
@@ -94,7 +98,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
try:
opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igm:", so.longopts +
- ["final-only", "assume-skipped=", "smtc=", "dump-vcd=", "dump-vlogtb=", "dump-smtc=", "dump-all", "noinfo"])
+ ["final-only", "assume-skipped=", "smtc=", "cex=", "dump-vcd=", "dump-vlogtb=", "dump-smtc=", "dump-all", "noinfo"])
except:
usage()
@@ -118,6 +122,8 @@ for o, a in opts:
final_only = True
elif o == "--smtc":
inconstr.append(a)
+ elif o == "--cex":
+ cexfile = a
elif o == "--dump-vcd":
vcdfile = a
elif o == "--dump-vlogtb":
@@ -146,6 +152,7 @@ if len(args) != 1:
constr_final_start = None
constr_asserts = defaultdict(list)
constr_assumes = defaultdict(list)
+constr_write = list()
for fn in inconstr:
current_states = None
@@ -229,6 +236,14 @@ for fn in inconstr:
continue
+ if tokens[0] == "write":
+ constr_write.append(" ".join(tokens[1:]))
+ continue
+
+ if tokens[0] == "logic":
+ so.logic = " ".join(tokens[1:])
+ continue
+
assert 0
@@ -240,7 +255,7 @@ def get_constr_expr(db, state, final=False, getvalues=False):
if state not in db:
return ([], [], []) if getvalues else "true"
- netref_regex = re.compile(r'(^|[( ])\[(-?[0-9]+:|)([^\]]+)\](?=[ )]|$)')
+ netref_regex = re.compile(r'(^|[( ])\[(-?[0-9]+:|)([^\]]*)\](?=[ )]|$)')
def replace_netref(match):
state_sel = match.group(2)
@@ -280,6 +295,9 @@ def get_constr_expr(db, state, final=False, getvalues=False):
smt = SmtIo(opts=so)
+if noinfo and vcdfile is None and vlogtbfile is None and outconstr is None:
+ smt.produce_models = False
+
def print_msg(msg):
print("%s %s" % (smt.timestamp(), msg))
sys.stdout.flush()
@@ -290,12 +308,46 @@ with open(args[0], "r") as f:
for line in f:
smt.write(line)
+for line in constr_write:
+ smt.write(line)
+
if topmod is None:
topmod = smt.topmod
assert topmod is not None
assert topmod in smt.modinfo
+if cexfile is not None:
+ with open(cexfile, "r") as f:
+ cex_regex = re.compile(r'([^\[@=]+)(\[\d+\])?([^@=]*)(@\d+)=([01])')
+ for entry in f.read().split():
+ match = cex_regex.match(entry)
+ assert match
+
+ name, bit, extra_name, step, val = match.group(1), match.group(2), match.group(3), match.group(4), match.group(5)
+
+ if extra_name != "":
+ continue
+
+ if name not in smt.modinfo[topmod].inputs:
+ continue
+
+ if bit is None:
+ bit = 0
+ else:
+ bit = int(bit[1:-1])
+
+ step = int(step[1:])
+ val = int(val)
+
+ if smt.modinfo[topmod].wsize[name] == 1:
+ assert bit == 0
+ smtexpr = "(= [%s] %s)" % (name, "true" if val else "false")
+ else:
+ smtexpr = "(= ((_ extract %d %d) [%s]) #b%d)" % (bit, bit, name, val)
+
+ # print("cex@%d: %s" % (step, smtexpr))
+ constr_assumes[step].append((cexfile, smtexpr))
def write_vcd_trace(steps_start, steps_stop, index):
filename = vcdfile.replace("%", index)
@@ -625,9 +677,10 @@ else: # not tempind
smt.write("(pop 1)")
- for i in range(step, last_check_step+1):
- smt.write("(assert (|%s_a| s%d))" % (topmod, i))
- smt.write("(assert %s)" % get_constr_expr(constr_asserts, i))
+ if (constr_final_start is not None) or (last_check_step+1 != num_steps):
+ for i in range(step, last_check_step+1):
+ smt.write("(assert (|%s_a| s%d))" % (topmod, i))
+ smt.write("(assert %s)" % get_constr_expr(constr_asserts, i))
if constr_final_start is not None:
for i in range(step, last_check_step+1):
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index 58554572..865eed1f 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -53,6 +53,9 @@ class SmtIo:
self.logic_ax = True
self.logic_uf = True
self.logic_bv = True
+ self.produce_models = True
+ self.smt2cache = [list()]
+ self.p = None
if opts is not None:
self.logic = opts.logic
@@ -62,6 +65,9 @@ class SmtIo:
self.dummy_file = opts.dummy_file
self.timeinfo = opts.timeinfo
self.unroll = opts.unroll
+ self.noincr = opts.noincr
+ self.info_stmts = opts.info_stmts
+ self.nocomments = opts.nocomments
else:
self.solver = "z3"
@@ -70,30 +76,40 @@ class SmtIo:
self.dummy_file = None
self.timeinfo = True
self.unroll = False
+ self.noincr = False
+ self.info_stmts = list()
+ self.nocomments = False
if self.solver == "yices":
- popen_vargs = ['yices-smt2', '--incremental']
+ self.popen_vargs = ['yices-smt2', '--incremental']
if self.solver == "z3":
- popen_vargs = ['z3', '-smt2', '-in']
+ self.popen_vargs = ['z3', '-smt2', '-in']
if self.solver == "cvc4":
- popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2']
+ self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2']
if self.solver == "mathsat":
- popen_vargs = ['mathsat']
+ self.popen_vargs = ['mathsat']
if self.solver == "boolector":
- popen_vargs = ['boolector', '--smt2', '-i']
+ self.popen_vargs = ['boolector', '--smt2', '-i']
self.unroll = True
+ if self.solver == "abc":
+ self.popen_vargs = ['yosys-abc', '-S', '%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000']
+ self.logic_ax = False
+ self.unroll = True
+ self.noincr = True
+
if self.solver == "dummy":
assert self.dummy_file is not None
self.dummy_fd = open(self.dummy_file, "r")
else:
if self.dummy_file is not None:
self.dummy_fd = open(self.dummy_file, "w")
- self.p = subprocess.Popen(popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ if not self.noincr:
+ self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if self.unroll:
self.logic_uf = False
@@ -123,9 +139,15 @@ class SmtIo:
if self.logic_bv: self.logic += "BV"
self.setup_done = True
- self.write("(set-option :produce-models true)")
+
+ if self.produce_models:
+ self.write("(set-option :produce-models true)")
+
self.write("(set-logic %s)" % self.logic)
+ for stmt in self.info_stmts:
+ self.write(stmt)
+
def timestamp(self):
secs = int(time() - self.start_time)
return "## %6d %3d:%02d:%02d " % (secs, secs // (60*60), (secs // 60) % 60, secs % 60)
@@ -187,11 +209,12 @@ class SmtIo:
stmt = stmt.strip()
- if unroll and self.unroll:
+ if self.nocomments or self.unroll:
if stmt.startswith(";"):
return
-
stmt = re.sub(r" ;.*", "", stmt)
+
+ if unroll and self.unroll:
stmt = self.unroll_buffer + stmt
self.unroll_buffer = ""
@@ -246,8 +269,22 @@ class SmtIo:
self.debug_file.flush()
if self.solver != "dummy":
- self.p.stdin.write(bytes(stmt + "\n", "ascii"))
- self.p.stdin.flush()
+ if self.noincr:
+ if self.p is not None and not stmt.startswith("(get-"):
+ self.p.stdin.close()
+ self.p = None
+ if stmt == "(push 1)":
+ self.smt2cache.append(list())
+ elif stmt == "(pop 1)":
+ self.smt2cache.pop()
+ else:
+ if self.p is not None:
+ self.p.stdin.write(bytes(stmt + "\n", "ascii"))
+ self.p.stdin.flush()
+ self.smt2cache[-1].append(stmt)
+ else:
+ self.p.stdin.write(bytes(stmt + "\n", "ascii"))
+ self.p.stdin.flush()
def info(self, stmt):
if not stmt.startswith("; yosys-smt2-"):
@@ -355,11 +392,20 @@ class SmtIo:
def check_sat(self):
if self.debug_print:
print("> (check-sat)")
- if self.debug_file:
+ if self.debug_file and not self.nocomments:
print("; running check-sat..", file=self.debug_file)
self.debug_file.flush()
if self.solver != "dummy":
+ if self.noincr:
+ if self.p is not None:
+ self.p.stdin.close()
+ self.p = None
+ self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ for cache_ctx in self.smt2cache:
+ for cache_stmt in cache_ctx:
+ self.p.stdin.write(bytes(cache_stmt + "\n", "ascii"))
+
self.p.stdin.write(bytes("(check-sat)\n", "ascii"))
self.p.stdin.flush()
@@ -495,6 +541,10 @@ class SmtIo:
def net_expr(self, mod, base, path):
if len(path) == 1:
assert mod in self.modinfo
+ if path[0] == "":
+ return base
+ if path[0] in self.modinfo[mod].cells:
+ return "(|%s_h %s| %s)" % (mod, path[0], base)
if path[0] in self.modinfo[mod].wsize:
return "(|%s_n %s| %s)" % (mod, path[0], base)
if path[0] in self.modinfo[mod].memories:
@@ -555,21 +605,24 @@ class SmtIo:
return [self.bv2bin(v) for v in self.get_net_list(mod_name, net_path_list, state_name)]
def wait(self):
- if self.solver != "dummy":
+ if self.p is not None:
self.p.wait()
class SmtOpts:
def __init__(self):
self.shortopts = "s:v"
- self.longopts = ["unroll", "no-progress", "dump-smt2=", "logic=", "dummy="]
+ self.longopts = ["unroll", "noincr", "noprogress", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"]
self.solver = "z3"
self.debug_print = False
self.debug_file = None
self.dummy_file = None
self.unroll = False
+ self.noincr = False
self.timeinfo = True
self.logic = None
+ self.info_stmts = list()
+ self.nocomments = False
def handle(self, o, a):
if o == "-s":
@@ -578,7 +631,9 @@ class SmtOpts:
self.debug_print = True
elif o == "--unroll":
self.unroll = True
- elif o == "--no-progress":
+ elif o == "--noincr":
+ self.noincr = True
+ elif o == "--noprogress":
self.timeinfo = True
elif o == "--dump-smt2":
self.debug_file = open(a, "w")
@@ -586,6 +641,10 @@ class SmtOpts:
self.logic = a
elif o == "--dummy":
self.dummy_file = a
+ elif o == "--info":
+ self.info_stmts.append(a)
+ elif o == "--nocomments":
+ self.nocomments = True
else:
return False
return True
@@ -609,11 +668,21 @@ class SmtOpts:
--unroll
unroll uninterpreted functions
- --no-progress
+ --noincr
+ don't use incremental solving, instead restart solver for
+ each (check-sat). This also avoids (push) and (pop).
+
+ --noprogress
disable timer display during solving
--dump-smt2 <filename>
write smt2 statements to file
+
+ --info <smt2-info-stmt>
+ include the specified smt2 info statement in the smt2 output
+
+ --nocomments
+ strip all comments from the generated smt2 code
"""
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 52cf861d..a617215f 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -33,10 +33,11 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool norename, noattr, attr2comment, noexpr, nodec, nostr, defparam;
+bool verbose, norename, noattr, attr2comment, noexpr, nodec, nostr, defparam;
int auto_name_counter, auto_name_offset, auto_name_digits;
std::map<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires, reg_ct;
+std::string auto_prefix;
RTLIL::Module *active_module;
@@ -85,13 +86,14 @@ void reset_auto_counter(RTLIL::Module *module)
for (size_t i = 10; i < auto_name_offset + auto_name_map.size(); i = i*10)
auto_name_digits++;
- for (auto it = auto_name_map.begin(); it != auto_name_map.end(); ++it)
- log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second);
+ if (verbose)
+ for (auto it = auto_name_map.begin(); it != auto_name_map.end(); ++it)
+ log(" renaming `%s' to `%s_%0*d_'.\n", it->first.c_str(), auto_prefix.c_str(), auto_name_digits, auto_name_offset + it->second);
}
std::string next_auto_id()
{
- return stringf("_%0*d_", auto_name_digits, auto_name_offset + auto_name_counter++);
+ return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_counter++);
}
std::string id(RTLIL::IdString internal_id, bool may_rename = true)
@@ -100,7 +102,7 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true)
bool do_escape = false;
if (may_rename && auto_name_map.count(internal_id) != 0)
- return stringf("_%0*d_", auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
+ return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
if (*str == '\\')
str++;
@@ -1342,6 +1344,9 @@ struct VerilogBackend : public Backend {
log(" instead of a backslash prefix) are changed to short names in the\n");
log(" format '_<number>_'.\n");
log("\n");
+ log(" -renameprefix <prefix>\n");
+ log(" insert this prefix in front of auto-generated instance names\n");
+ log("\n");
log(" -noattr\n");
log(" with this option no attributes are included in the output\n");
log("\n");
@@ -1376,6 +1381,9 @@ struct VerilogBackend : public Backend {
log(" only write selected modules. modules must be selected entirely or\n");
log(" not at all.\n");
log("\n");
+ log(" -v\n");
+ log(" verbose output (print new names of all renamed wires and cells)\n");
+ log("\n");
log("Note that RTLIL processes can't always be mapped directly to Verilog\n");
log("always blocks. This frontend should only be used to export an RTLIL\n");
log("netlist, i.e. after the \"proc\" pass has been used to convert all\n");
@@ -1387,6 +1395,7 @@ struct VerilogBackend : public Backend {
{
log_header(design, "Executing Verilog backend.\n");
+ verbose = false;
norename = false;
noattr = false;
attr2comment = false;
@@ -1394,6 +1403,7 @@ struct VerilogBackend : public Backend {
nodec = false;
nostr = false;
defparam = false;
+ auto_prefix = "";
bool blackboxes = false;
bool selected = false;
@@ -1431,6 +1441,10 @@ struct VerilogBackend : public Backend {
norename = true;
continue;
}
+ if (arg == "-renameprefix" && argidx+1 < args.size()) {
+ auto_prefix = args[++argidx];
+ continue;
+ }
if (arg == "-noattr") {
noattr = true;
continue;
@@ -1463,6 +1477,10 @@ struct VerilogBackend : public Backend {
selected = true;
continue;
}
+ if (arg == "-v") {
+ verbose = true;
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);