diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/cmds/rename.cc | 32 | ||||
-rw-r--r-- | passes/hierarchy/uniquify.cc | 2 | ||||
-rw-r--r-- | passes/memory/memory_bram.cc | 3 | ||||
-rw-r--r-- | passes/proc/proc_mux.cc | 28 | ||||
-rw-r--r-- | passes/sat/cutpoint.cc | 24 | ||||
-rw-r--r-- | passes/techmap/libparse.cc | 61 |
6 files changed, 130 insertions, 20 deletions
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 698ce7235..9b1830b7b 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name) +static void rename_in_module(RTLIL::Module *module, std::string from_name, std::string to_name, bool flag_output) { from_name = RTLIL::escape_id(from_name); to_name = RTLIL::escape_id(to_name); @@ -37,13 +37,18 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: Wire *w = it.second; log("Renaming wire %s to %s in module %s.\n", log_id(w), log_id(to_name), log_id(module)); module->rename(w, to_name); - if (w->port_id) + if (w->port_id || flag_output) { + if (flag_output) + w->port_output = true; module->fixup_ports(); + } return; } for (auto &it : module->cells_) if (it.first == from_name) { + if (flag_output) + log_cmd_error("Called with -output but the specified object is a cell.\n"); log("Renaming cell %s to %s in module %s.\n", log_id(it.second), log_id(to_name), log_id(module)); module->rename(it.second, to_name); return; @@ -108,15 +113,26 @@ struct RenamePass : public Pass { log("Rename the specified object. Note that selection patterns are not supported\n"); log("by this command.\n"); log("\n"); + log("\n"); + log("\n"); + log(" rename -output old_name new_name\n"); + log("\n"); + log("Like above, but also make the wire an output. This will fail if the object is\n"); + log("not a wire.\n"); + log("\n"); + log("\n"); log(" rename -src [selection]\n"); log("\n"); log("Assign names auto-generated from the src attribute to all selected wires and\n"); log("cells with private names.\n"); log("\n"); + log("\n"); log(" rename -wire [selection]\n"); + log("\n"); log("Assign auto-generated names based on the wires they drive to all selected\n"); log("cells with private names. Ignores cells driving privatly named wires.\n"); log("\n"); + log("\n"); log(" rename -enumerate [-pattern <pattern>] [selection]\n"); log("\n"); log("Assign short auto-generated names to all selected wires and cells with private\n"); @@ -124,11 +140,13 @@ struct RenamePass : public Pass { log("The character %% in the pattern is replaced with a integer number. The default\n"); log("pattern is '_%%_'.\n"); log("\n"); + log("\n"); log(" rename -hide [selection]\n"); log("\n"); log("Assign private names (the ones with $-prefix) to all selected wires and cells\n"); log("with public names. This ignores all selected ports.\n"); log("\n"); + log("\n"); log(" rename -top new_name\n"); log("\n"); log("Rename top module.\n"); @@ -142,6 +160,7 @@ struct RenamePass : public Pass { bool flag_enumerate = false; bool flag_hide = false; bool flag_top = false; + bool flag_output = false; bool got_mode = false; size_t argidx; @@ -153,6 +172,11 @@ struct RenamePass : public Pass { got_mode = true; continue; } + if (arg == "-output" && !got_mode) { + flag_output = true; + got_mode = true; + continue; + } if (arg == "-wire" && !got_mode) { flag_wire = true; got_mode = true; @@ -322,10 +346,12 @@ struct RenamePass : public Pass { if (!design->selected_active_module.empty()) { if (design->modules_.count(design->selected_active_module) > 0) - rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name); + rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name, flag_output); } else { + if (flag_output) + log_cmd_error("Mode -output requires that there is an active module selected.\n"); for (auto &mod : design->modules_) { if (mod.first == from_name || RTLIL::unescape_id(mod.first) == from_name) { to_name = RTLIL::escape_id(to_name); diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc index c88ecd82e..e6154e94f 100644 --- a/passes/hierarchy/uniquify.cc +++ b/passes/hierarchy/uniquify.cc @@ -87,6 +87,8 @@ struct UniquifyPass : public Pass { smod->name = newname; cell->type = newname; smod->set_bool_attribute("\\unique"); + if (smod->attributes.count("\\hdlname") == 0) + smod->attributes["\\hdlname"] = string(log_id(tmod->name)); design->add(smod); did_something = true; diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index c38eabaee..804aa21f9 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -641,6 +641,7 @@ grow_read_ports:; pi.sig_data = SigSpec(); pi.sig_en = SigSpec(); pi.make_outreg = false; + pi.make_transp = false; } new_portinfos.push_back(pi); if (pi.dupidx == dup_count-1) { @@ -956,6 +957,8 @@ grow_read_ports:; SigSpec addr_ok_q = addr_ok; if ((pi.clocks || pi.make_outreg) && !addr_ok.empty()) { addr_ok_q = module->addWire(NEW_ID); + if (!pi.sig_en.empty()) + addr_ok = module->Mux(NEW_ID, addr_ok_q, addr_ok, pi.sig_en); module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol); } diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index 1329c1fef..7d3d23408 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -340,6 +340,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d // evaluate in reverse order to give the first entry the top priority RTLIL::SigSpec initial_val = result; RTLIL::Cell *last_mux_cell = NULL; + bool shiftx = initial_val.is_fully_undef(); for (size_t i = 0; i < sw->cases.size(); i++) { int case_idx = sw->cases.size() - i - 1; RTLIL::CaseRule *cs2 = sw->cases[case_idx]; @@ -348,6 +349,33 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode); else result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode); + + // Ignore output values which are entirely don't care + if (shiftx && !value.is_fully_undef()) { + // Keep checking if case condition is the same as the current case index + if (cs2->compare.size() == 1 && cs2->compare.front().is_fully_const()) + shiftx = (cs2->compare.front().as_int() == case_idx); + else + shiftx = false; + } + } + + // Transform into a $shiftx where possible + if (shiftx && last_mux_cell->type == "$pmux") { + // Create bit-blasted $shiftx-es that shifts by the address line used in the case statement + auto pmux_b_port = last_mux_cell->getPort("\\B"); + auto pmux_y_port = last_mux_cell->getPort("\\Y"); + int width = last_mux_cell->getParam("\\WIDTH").as_int(); + for (int i = 0; i < width; ++i) { + RTLIL::SigSpec a_port; + // Because we went in reverse order above, un-reverse $pmux's B port here + for (int j = pmux_b_port.size()/width-1; j >= 0; --j) + a_port.append(pmux_b_port.extract(j*width+i, 1)); + // Create a $shiftx that shifts by the address line used in the case statement + mod->addShiftx(NEW_ID, a_port, sw->signal, pmux_y_port.extract(i, 1)); + } + // Disconnect $pmux by replacing its output port with a floating wire + last_mux_cell->setPort("\\Y", mod->addWire(NEW_ID, width)); } } diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 3a38ebac0..048aec7f3 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -33,20 +33,24 @@ struct CutpointPass : public Pass { log("\n"); log("This command adds formal cut points to the design.\n"); log("\n"); + log(" -undef\n"); + log(" set cupoint nets to undef (x). the default behavior is to create a\n"); + log(" $anyseq cell and drive the cutpoint net from that\n"); + log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - // bool flag_noinit = false; + bool flag_undef = false; log_header(design, "Executing CUTPOINT pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-noinit") { - // flag_noinit = true; - // continue; - // } + if (args[argidx] == "-undef") { + flag_undef = true; + continue; + } break; } extra_args(args, argidx, design); @@ -63,7 +67,7 @@ struct CutpointPass : public Pass { if (wire->port_output) output_wires.push_back(wire); for (auto wire : output_wires) - module->connect(wire, module->Anyseq(NEW_ID, GetSize(wire))); + module->connect(wire, flag_undef ? Const(State::Sx, GetSize(wire)) : module->Anyseq(NEW_ID, GetSize(wire))); continue; } @@ -76,7 +80,7 @@ struct CutpointPass : public Pass { log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell)); for (auto &conn : cell->connections()) { if (cell->output(conn.first)) - module->connect(conn.second, module->Anyseq(NEW_ID, GetSize(conn.second))); + module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); } module->remove(cell); } @@ -86,7 +90,7 @@ struct CutpointPass : public Pass { log("Making output wire %s.%s a cutpoint.\n", log_id(module), log_id(wire)); Wire *new_wire = module->addWire(NEW_ID, wire); module->swap_names(wire, new_wire); - module->connect(new_wire, module->Anyseq(NEW_ID, GetSize(new_wire))); + module->connect(new_wire, flag_undef ? Const(State::Sx, GetSize(new_wire)) : module->Anyseq(NEW_ID, GetSize(new_wire))); wire->port_id = 0; wire->port_input = false; wire->port_output = false; @@ -142,7 +146,7 @@ struct CutpointPass : public Pass { rhs.append(SigBit(new_wire, i)); } if (GetSize(lhs)) - module->connect(lhs, rhs); + module->connect(lhs, rhs); module->swap_names(wire, new_wire); wire->port_id = 0; wire->port_input = false; @@ -154,7 +158,7 @@ struct CutpointPass : public Pass { for (auto chunk : sig.chunks()) { SigSpec s(chunk); - module->connect(s, module->Anyseq(NEW_ID, GetSize(s))); + module->connect(s, flag_undef ? Const(State::Sx, GetSize(s)) : module->Anyseq(NEW_ID, GetSize(s))); } } } diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 8eadd8735..991cc4498 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -155,11 +155,13 @@ int LibertyParser::lexer(std::string &str) // check for a backslash if (c == '\\') { - c = f.get(); + c = f.get(); if (c == '\r') c = f.get(); - if (c == '\n') + if (c == '\n') { + line++; return lexer(str); + } f.unget(); return '\\'; } @@ -186,14 +188,39 @@ LibertyAst *LibertyParser::parse() int tok = lexer(str); - while (tok == 'n') + // there are liberty files in the wild that + // have superfluous ';' at the end of + // a { ... }. We simply ignore a ';' here. + // and get to the next statement. + + while ((tok == 'n') || (tok == ';')) tok = lexer(str); if (tok == '}' || tok < 0) return NULL; - if (tok != 'v') - error(); + if (tok != 'v') { + std::string eReport; + switch(tok) + { + case 'n': + error("Unexpected newline."); + break; + case '[': + case ']': + case '}': + case '{': + case '\"': + case ':': + eReport = "Unexpected '"; + eReport += static_cast<char>(tok); + eReport += "'."; + error(eReport); + break; + default: + error(); + } + } LibertyAst *ast = new LibertyAst; ast->id = str; @@ -282,8 +309,28 @@ LibertyAst *LibertyParser::parse() } continue; } - if (tok != 'v') - error(); + if (tok != 'v') { + std::string eReport; + switch(tok) + { + case 'n': + error("Unexpected newline."); + break; + case '[': + case ']': + case '}': + case '{': + case '\"': + case ':': + eReport = "Unexpected '"; + eReport += static_cast<char>(tok); + eReport += "'."; + error(eReport); + break; + default: + error(); + } + } ast->args.push_back(arg); } continue; |