diff options
-rw-r--r-- | backends/smt2/smtbmc.py | 58 | ||||
-rw-r--r-- | backends/smt2/smtio.py | 24 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 3 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 2 | ||||
-rw-r--r-- | kernel/rtlil.cc | 1 | ||||
-rw-r--r-- | passes/equiv/equiv_simple.cc | 4 | ||||
-rw-r--r-- | passes/fsm/fsm_expand.cc | 30 | ||||
-rw-r--r-- | passes/hierarchy/hierarchy.cc | 4 | ||||
-rw-r--r-- | passes/opt/opt_rmdff.cc | 26 |
10 files changed, 127 insertions, 27 deletions
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index ecee6795e..10875f523 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -29,7 +29,9 @@ num_steps = 20 append_steps = 0 vcdfile = None cexfile = None -aigprefix = None +aimfile = None +aiwfile = None +aigheader = True vlogtbfile = None inconstr = list() outconstr = None @@ -73,6 +75,14 @@ yosys-smtbmc [options] <yosys_smt2_output> and AIGER witness file. The file names are <prefix>.aim for the map file and <prefix>.aiw for the witness file. + --aig <aim_filename>:<aiw_filename> + like above, but for map files and witness files that do not + share a filename prefix (or use differen file extensions). + + --aig-noheader + the AIGER witness file does not include the status and + properties lines. + --noinfo only run the core proof, do not collect and print any additional information (e.g. which assert failed) @@ -111,7 +121,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=", "cex=", "aig=", + ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "dump-vcd=", "dump-vlogtb=", "dump-smtc=", "dump-all", "noinfo", "append="]) except: usage() @@ -140,7 +150,13 @@ for o, a in opts: elif o == "--cex": cexfile = a elif o == "--aig": - aigprefix = a + if ":" in a: + aimfile, aiwfile = a.split(":") + else: + aimfile = a + ".aim" + aiwfile = a + ".aiw" + elif o == "--aig-noheader": + aigheader = False elif o == "--dump-vcd": vcdfile = a elif o == "--dump-vlogtb": @@ -375,7 +391,7 @@ if cexfile is not None: skip_steps = max(skip_steps, step) num_steps = max(num_steps, step+1) -if aigprefix is not None: +if aimfile is not None: input_map = dict() init_map = dict() latch_map = dict() @@ -385,7 +401,7 @@ if aigprefix is not None: skip_steps = 0 num_steps = 0 - with open(aigprefix + ".aim", "r") as f: + with open(aimfile, "r") as f: for entry in f.read().splitlines(): entry = entry.split() @@ -406,11 +422,14 @@ if aigprefix is not None: assert False - with open(aigprefix + ".aiw", "r") as f: + with open(aiwfile, "r") as f: got_state = False got_ffinit = False step = 0 + if not aigheader: + got_state = True + for entry in f.read().splitlines(): if len(entry) == 0 or entry[0] in "bcjfu.": continue @@ -458,13 +477,30 @@ if aigprefix is not None: bitidx = init_map[i][1] path = smt.get_path(topmod, name) - width = smt.net_width(topmod, path) + + if not smt.net_exists(topmod, path): + match = re.match(r"(.*)\[(\d+)\]$", path[-1]) + if match: + path[-1] = match.group(1) + addr = int(match.group(2)) + + if not match or not smt.mem_exists(topmod, path): + print_msg("Ignoring init value for unknown net: %s" % (name)) + continue + + meminfo = smt.mem_info(topmod, path) + smtexpr = "(select [%s] #b%s)" % (".".join(path), bin(addr)[2:].zfill(meminfo[0])) + width = meminfo[1] + + else: + smtexpr = "[%s]" % name + width = smt.net_width(topmod, path) if width == 1: assert bitidx == 0 - smtexpr = "(= [%s] %s)" % (name, "true" if value else "false") + smtexpr = "(= %s %s)" % (smtexpr, "true" if value else "false") else: - smtexpr = "(= ((_ extract %d %d) [%s]) #b%d)" % (bitidx, bitidx, name, value) + smtexpr = "(= ((_ extract %d %d) %s) #b%d)" % (bitidx, bitidx, smtexpr, value) constr_assumes[0].append((cexfile, smtexpr)) @@ -569,7 +605,7 @@ def write_vlogtb_trace(steps_start, steps_stop, index): mems = sorted(smt.hiermems(topmod)) for mempath in mems: - abits, width, ports = smt.mem_info(topmod, "s%d" % steps_start, mempath) + abits, width, ports = smt.mem_info(topmod, mempath) mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath) addr_expr_list = list() @@ -630,7 +666,7 @@ def write_constr_trace(steps_start, steps_stop, index): mems = sorted(smt.hiermems(topmod)) for mempath in mems: - abits, width, ports = smt.mem_info(topmod, "s%d" % steps_start, mempath) + abits, width, ports = smt.mem_info(topmod, mempath) mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath) addr_expr_list = list() diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 497b72db8..3946c3423 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -567,6 +567,26 @@ class SmtIo: assert net_path[-1] in self.modinfo[mod].wsize return self.modinfo[mod].wsize[net_path[-1]] + def net_exists(self, mod, net_path): + for i in range(len(net_path)-1): + if mod not in self.modinfo: return False + if net_path[i] not in self.modinfo[mod].cells: return False + mod = self.modinfo[mod].cells[net_path[i]] + + if mod not in self.modinfo: return False + if net_path[-1] not in self.modinfo[mod].wsize: return False + return True + + def mem_exists(self, mod, mem_path): + for i in range(len(mem_path)-1): + if mod not in self.modinfo: return False + if mem_path[i] not in self.modinfo[mod].cells: return False + mod = self.modinfo[mod].cells[mem_path[i]] + + if mod not in self.modinfo: return False + if mem_path[-1] not in self.modinfo[mod].memories: return False + return True + def mem_expr(self, mod, base, path, portidx=None, infomode=False): if len(path) == 1: assert mod in self.modinfo @@ -582,8 +602,8 @@ class SmtIo: nextbase = "(|%s_h %s| %s)" % (mod, path[0], base) return self.mem_expr(nextmod, nextbase, path[1:], portidx=portidx, infomode=infomode) - def mem_info(self, mod, base, path): - return self.mem_expr(mod, base, path, infomode=True) + def mem_info(self, mod, path): + return self.mem_expr(mod, "", path, infomode=True) def get_net(self, mod_name, net_path, state_name): return self.get(self.net_expr(mod_name, state_name, net_path)) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index de85355b5..c1e77c6ec 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3079,6 +3079,8 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, if (bit_part_sel) children.push_back(bit_part_sel); + + did_something = true; } log_assert(id2ast == NULL || mem2reg_set.count(id2ast) == 0); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 405aeb975..c22fdf39c 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -192,6 +192,9 @@ YOSYS_NAMESPACE_END "genvar" { return TOK_GENVAR; } "real" { return TOK_REAL; } +"enum" { SV_KEYWORD(TOK_ENUM); } +"typedef" { SV_KEYWORD(TOK_TYPEDEF); } + [0-9][0-9_]* { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONST; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 607c48a81..ba47bf2d3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -114,7 +114,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME -%token TOK_RESTRICT TOK_PROPERTY +%token TOK_RESTRICT TOK_PROPERTY TOK_ENUM TOK_TYPEDEF %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 40ad8ca13..365bfd9f8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2050,6 +2050,7 @@ RTLIL::Memory::Memory() hashidx_ = hashidx_count; width = 1; + start_offset = 0; size = 0; } diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index 49963ed68..270200c34 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -59,7 +59,7 @@ struct EquivSimpleWorker for (auto &conn : cell->connections()) if (yosys_celltypes.cell_input(cell->type, conn.first)) for (auto bit : sigmap(conn.second)) { - if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_")) { + if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) { if (!conn.first.in("\\CLK", "\\C")) next_seed.insert(bit); } else @@ -329,7 +329,7 @@ struct EquivSimplePass : public Pass { unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module)); for (auto cell : module->cells()) { - if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_")) + if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) continue; for (auto &conn : cell->connections()) if (yosys_celltypes.cell_output(cell->type, conn.first)) diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index e7b9dcf90..2c344a1c1 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -54,13 +54,27 @@ struct FsmExpand if (cell->getPort("\\A").size() < 2) return true; + int in_bits = 0; RTLIL::SigSpec new_signals; - if (cell->hasPort("\\A")) + + if (cell->hasPort("\\A")) { + in_bits += GetSize(cell->getPort("\\A")); new_signals.append(assign_map(cell->getPort("\\A"))); - if (cell->hasPort("\\B")) + } + + if (cell->hasPort("\\B")) { + in_bits += GetSize(cell->getPort("\\B")); new_signals.append(assign_map(cell->getPort("\\B"))); - if (cell->hasPort("\\S")) + } + + if (cell->hasPort("\\S")) { + in_bits += GetSize(cell->getPort("\\S")); new_signals.append(assign_map(cell->getPort("\\S"))); + } + + if (in_bits > 8) + return false; + if (cell->hasPort("\\Y")) new_signals.append(assign_map(cell->getPort("\\Y"))); @@ -173,6 +187,16 @@ struct FsmExpand new_ctrl_out.append(output_sig); fsm_cell->setPort("\\CTRL_OUT", new_ctrl_out); + if (GetSize(input_sig) > 10) + log_warning("Cell %s.%s (%s) has %d input bits, merging into FSM %s.%s might be problematic.\n", + log_id(cell->module), log_id(cell), log_id(cell->type), + GetSize(input_sig), log_id(fsm_cell->module), log_id(fsm_cell)); + + if (GetSize(fsm_data.transition_table) > 10000) + log_warning("Transition table for FSM %s.%s already has %d rows, merging more cells " + "into this FSM might be problematic.\n", log_id(fsm_cell->module), log_id(fsm_cell), + GetSize(fsm_data.transition_table)); + std::vector<FsmData::transition_t> new_transition_table; for (auto &tr : fsm_data.transition_table) { for (int i = 0; i < (1 << input_sig.size()); i++) { diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 337af7fd7..f1c4a1d3b 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -175,16 +175,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check { filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".v"; if (check_file_exists(filename)) { - std::vector<std::string> args; - args.push_back(filename); Frontend::frontend_call(design, NULL, filename, "verilog"); goto loaded_module; } filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".il"; if (check_file_exists(filename)) { - std::vector<std::string> args; - args.push_back(filename); Frontend::frontend_call(design, NULL, filename, "ilang"); goto loaded_module; } diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 922f086f1..00094738c 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -41,9 +41,27 @@ void remove_init_attr(SigSpec sig) bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) { - SigSpec sig_e = dlatch->getPort("\\EN"); + SigSpec sig_e; + State on_state, off_state; + + if (dlatch->type == "$dlatch") { + sig_e = assign_map(dlatch->getPort("\\EN")); + on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0; + off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1; + } else + if (dlatch->type == "$_DLATCH_P_") { + sig_e = assign_map(dlatch->getPort("\\E")); + on_state = State::S1; + off_state = State::S0; + } else + if (dlatch->type == "$_DLATCH_N_") { + sig_e = assign_map(dlatch->getPort("\\E")); + on_state = State::S0; + off_state = State::S1; + } else + log_abort(); - if (sig_e == State::S0) + if (sig_e == off_state) { RTLIL::Const val_init; for (auto bit : dff_init_map(dlatch->getPort("\\Q"))) @@ -52,7 +70,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) goto delete_dlatch; } - if (sig_e == State::S1) + if (sig_e == on_state) { mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D")); goto delete_dlatch; @@ -268,7 +286,7 @@ struct OptRmdffPass : public Pass { "$ff", "$dff", "$adff")) dff_list.push_back(cell->name); - if (cell->type == "$dlatch") + if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_")) dlatch_list.push_back(cell->name); } |