diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/cmds/show.cc | 7 | ||||
-rw-r--r-- | passes/cmds/sta.cc | 5 | ||||
-rw-r--r-- | passes/fsm/fsmdata.h | 4 | ||||
-rw-r--r-- | passes/memory/memory.cc | 11 | ||||
-rw-r--r-- | passes/memory/memory_dff.cc | 27 | ||||
-rw-r--r-- | passes/memory/memory_libmap.cc | 3 | ||||
-rw-r--r-- | passes/opt/opt_ffinv.cc | 4 | ||||
-rw-r--r-- | passes/opt/wreduce.cc | 10 | ||||
-rw-r--r-- | passes/sat/fmcombine.cc | 3 | ||||
-rw-r--r-- | passes/techmap/iopadmap.cc | 28 |
10 files changed, 84 insertions, 18 deletions
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 35aa410e4..43deba47b 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -191,7 +191,12 @@ struct ShowWorker std::string str; for (char ch : id) { - if (ch == '\\' || ch == '"') + if (ch == '\\') { + // new graphviz have bug with escaping '\' + str += "╲"; + continue; + } + if (ch == '"') str += "\\"; str += ch; } diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 13e1ee13c..4ad0e96be 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -58,11 +58,14 @@ struct StaWorker { TimingInfo timing; + pool<IdString> unrecognised_cells; + for (auto cell : module->cells()) { Module *inst_module = design->module(cell->type); if (!inst_module) { - log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); + if (unrecognised_cells.insert(cell->type).second) + log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); continue; } diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 4ba3b4e4f..97371efab 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -91,8 +91,8 @@ struct FsmData if (reset_state < 0 || reset_state >= state_num) reset_state = -1; - RTLIL::Const state_table = cell->parameters[ID::STATE_TABLE]; - RTLIL::Const trans_table = cell->parameters[ID::TRANS_TABLE]; + const RTLIL::Const &state_table = cell->parameters[ID::STATE_TABLE]; + const RTLIL::Const &trans_table = cell->parameters[ID::TRANS_TABLE]; for (int i = 0; i < state_num; i++) { RTLIL::Const state_code; diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index e34cc927e..d5dec6198 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -31,7 +31,7 @@ struct MemoryPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-bram <bram_rules>] [selection]\n"); + log(" memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram <bram_rules>] [selection]\n"); log("\n"); log("This pass calls all the other memory_* passes in a useful order:\n"); log("\n"); @@ -39,7 +39,7 @@ struct MemoryPass : public Pass { log(" opt_mem_priority\n"); log(" opt_mem_feedback\n"); log(" memory_bmux2rom (skipped if called with -norom)\n"); - log(" memory_dff (skipped if called with -nordff or -memx)\n"); + log(" memory_dff [-no-rw-check] (skipped if called with -nordff or -memx)\n"); log(" opt_clean\n"); log(" memory_share [-nowiden] [-nosat]\n"); log(" opt_mem_widen\n"); @@ -59,6 +59,7 @@ struct MemoryPass : public Pass { bool flag_nomap = false; bool flag_nordff = false; bool flag_memx = false; + string memory_dff_opts; string memory_bram_opts; string memory_share_opts; @@ -92,6 +93,10 @@ struct MemoryPass : public Pass { memory_share_opts += " -nosat"; continue; } + if (args[argidx] == "-no-rw-check") { + memory_dff_opts += " -no-rw-check"; + continue; + } if (argidx+1 < args.size() && args[argidx] == "-bram") { memory_bram_opts += " -rules " + args[++argidx]; continue; @@ -106,7 +111,7 @@ struct MemoryPass : public Pass { if (!flag_norom) Pass::call(design, "memory_bmux2rom"); if (!flag_nordff) - Pass::call(design, "memory_dff"); + Pass::call(design, "memory_dff" + memory_dff_opts); Pass::call(design, "opt_clean"); Pass::call(design, "memory_share" + memory_share_opts); Pass::call(design, "opt_mem_widen"); diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 91209d428..998e86491 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -220,8 +220,9 @@ struct MemoryDffWorker ModWalker modwalker; FfInitVals initvals; FfMergeHelper merger; + bool flag_no_rw_check; - MemoryDffWorker(Module *module) : module(module), modwalker(module->design) + MemoryDffWorker(Module *module, bool flag_no_rw_check) : module(module), modwalker(module->design), flag_no_rw_check(flag_no_rw_check) { modwalker.setup(module); initvals.set(&modwalker.sigmap, module); @@ -357,6 +358,14 @@ struct MemoryDffWorker return; } + // Check for no_rw_check + bool no_rw_check = flag_no_rw_check || mem.get_bool_attribute(ID::no_rw_check); + for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) { + if (mem.get_string_attribute(attr) == "no_rw_check") { + no_rw_check = true; + } + } + // Construct cache. MemQueryCache cache(qcsat, mem, port, ff); @@ -392,6 +401,8 @@ struct MemoryDffWorker pd.uncollidable_mask[j] = true; pd.collision_x_mask[j] = true; } + if (no_rw_check) + pd.collision_x_mask[j] = true; } } portdata.push_back(pd); @@ -618,25 +629,35 @@ struct MemoryDffPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory_dff [options] [selection]\n"); + log(" memory_dff [-no-rw-check] [selection]\n"); log("\n"); log("This pass detects DFFs at memory read ports and merges them into the memory port.\n"); log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n"); log("interface and yields a synchronous memory port.\n"); log("\n"); + log(" -no-rw-check\n"); + log(" marks all recognized read ports as \"return don't-care value on\n"); + log(" read/write collision\" (same result as setting the no_rw_check\n"); + log(" attribute on all memories).\n"); + log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) override { + bool flag_no_rw_check = false; log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd).\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-no-rw-check") { + flag_no_rw_check = true; + continue; + } break; } extra_args(args, argidx, design); for (auto mod : design->selected_modules()) { - MemoryDffWorker worker(mod); + MemoryDffWorker worker(mod, flag_no_rw_check); worker.run(); } } diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index ab7bb7bb2..898e0af85 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -443,6 +443,9 @@ void MemMapping::determine_style() { std::string val_s = val.decode_string(); for (auto &c: val_s) c = std::tolower(c); + // Handled in memory_dff. + if (val_s == "no_rw_check") + continue; if (val_s == "auto") { // Nothing. } else if (val_s == "logic" || val_s == "registers") { diff --git a/passes/opt/opt_ffinv.cc b/passes/opt/opt_ffinv.cc index fd76dd2be..fe5b59fa5 100644 --- a/passes/opt/opt_ffinv.cc +++ b/passes/opt/opt_ffinv.cc @@ -72,6 +72,8 @@ struct OptFfInvWorker for (auto &port: q_ports) { if (port.cell == ff.cell && port.port == ID::Q) continue; + if (port.cell == d_inv) + return false; if (port.port != ID::A) return false; if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut))) @@ -148,6 +150,8 @@ struct OptFfInvWorker for (auto &port: q_ports) { if (port.cell == ff.cell && port.port == ID::Q) continue; + if (port.cell == d_lut) + return false; if (port.port != ID::A) return false; if (port.cell->type.in(ID($not), ID($_NOT_))) { diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index aaad28ef0..08ab6de6f 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -30,6 +30,7 @@ struct WreduceConfig { pool<IdString> supported_cell_types; bool keepdc = false; + bool mux_undef = false; WreduceConfig() { @@ -83,7 +84,7 @@ struct WreduceWorker SigBit ref = sig_a[i]; for (int k = 0; k < GetSize(sig_s); k++) { - if ((config->keepdc || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) + if ((config->keepdc || !config->mux_undef || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) goto no_match_ab; if (sig_b[k*GetSize(sig_a) + i] != State::Sx) ref = sig_b[k*GetSize(sig_a) + i]; @@ -479,6 +480,9 @@ struct WreducePass : public Pass { log(" Do not change the width of memory address ports. Use this options in\n"); log(" flows that use the 'memory_memx' pass.\n"); log("\n"); + log(" -mux_undef\n"); + log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n"); + log("\n"); log(" -keepdc\n"); log(" Do not optimize explicit don't-care values.\n"); log("\n"); @@ -500,6 +504,10 @@ struct WreducePass : public Pass { config.keepdc = true; continue; } + if (args[argidx] == "-mux_undef") { + config.mux_undef = true; + continue; + } break; } extra_args(args, argidx, design); diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index e15bdf6a8..220cf5c52 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -64,6 +64,9 @@ struct FmcombineWorker c->parameters = cell->parameters; c->attributes = cell->attributes; + if (cell->is_mem_cell()) + c->parameters[ID::MEMID] = cell->parameters[ID::MEMID].decode_string() + suffix; + for (auto &conn : cell->connections()) c->setPort(conn.first, import_sig(conn.second, suffix)); diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index 437ad5156..322eb7779 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -240,13 +240,13 @@ struct IopadmapPass : public Pass { for (auto module : design->selected_modules()) { dict<Wire *, dict<int, pair<Cell *, IdString>>> rewrite_bits; - pool<SigSig> remove_conns; + dict<SigSig, pool<int>> remove_conns; if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty()) { dict<SigBit, Cell *> tbuf_bits; pool<SigBit> driven_bits; - dict<SigBit, SigSig> z_conns; + dict<SigBit, std::pair<SigSig, int>> z_conns; // Gather tristate buffers and always-on drivers. for (auto cell : module->cells()) @@ -266,7 +266,7 @@ struct IopadmapPass : public Pass { SigBit dstbit = conn.first[i]; SigBit srcbit = conn.second[i]; if (!srcbit.wire && srcbit.data == State::Sz) { - z_conns[dstbit] = conn; + z_conns[dstbit] = {conn, i}; continue; } driven_bits.insert(dstbit); @@ -317,8 +317,9 @@ struct IopadmapPass : public Pass { // enable. en_sig = SigBit(State::S0); data_sig = SigBit(State::Sx); - if (z_conns.count(wire_bit)) - remove_conns.insert(z_conns[wire_bit]); + auto it = z_conns.find(wire_bit); + if (it != z_conns.end()) + remove_conns[it->second.first].insert(it->second.second); } if (wire->port_input) @@ -477,9 +478,22 @@ struct IopadmapPass : public Pass { if (!remove_conns.empty()) { std::vector<SigSig> new_conns; - for (auto &conn : module->connections()) - if (!remove_conns.count(conn)) + for (auto &conn : module->connections()) { + auto it = remove_conns.find(conn); + if (it == remove_conns.end()) { new_conns.push_back(conn); + } else { + SigSpec lhs, rhs; + for (int i = 0; i < GetSize(conn.first); i++) { + if (!it->second.count(i)) { + lhs.append(conn.first[i]); + rhs.append(conn.second[i]); + } + } + new_conns.push_back(SigSig(lhs, rhs)); + + } + } module->new_connections(new_conns); } |