diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/memory/memory_share.cc | 2 | ||||
-rw-r--r-- | passes/opt/opt_mem.cc | 156 | ||||
-rw-r--r-- | passes/sat/sim.cc | 20 | ||||
-rw-r--r-- | passes/techmap/abc.cc | 28 |
4 files changed, 176 insertions, 30 deletions
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index 1ddc13f90..5cb11d62b 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -555,7 +555,7 @@ struct MemorySharePass : public Pass { } break; } - extra_args(args, 1, design); + extra_args(args, argidx, design); MemoryShareWorker msw(design, flag_widen, flag_sat); for (auto module : design->selected_modules()) diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc index edadf2c7b..885b6f97d 100644 --- a/passes/opt/opt_mem.cc +++ b/passes/opt/opt_mem.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/mem.h" +#include "kernel/ff.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -54,31 +55,160 @@ struct OptMemPass : public Pass { SigMap sigmap(module); FfInitVals initvals(&sigmap, module); for (auto &mem : Mem::get_selected_memories(module)) { + std::vector<bool> always_0(mem.width, true); + std::vector<bool> always_1(mem.width, true); bool changed = false; for (auto &port : mem.wr_ports) { if (port.en.is_fully_zero()) { port.removed = true; changed = true; total_count++; + } else { + for (int sub = 0; sub < (1 << port.wide_log2); sub++) { + for (int i = 0; i < mem.width; i++) { + int bit = sub * mem.width + i; + if (port.en[bit] != State::S0) { + if (port.data[bit] != State::Sx && port.data[bit] != State::S0) { + always_0[i] = false; + } + if (port.data[bit] != State::Sx && port.data[bit] != State::S1) { + always_1[i] = false; + } + } else { + if (port.data[bit] != State::Sx) { + port.data[bit] = State::Sx; + changed = true; + total_count++; + } + } + } + } } } - if (changed) { - mem.emit(); + for (auto &init : mem.inits) { + for (int i = 0; i < GetSize(init.data); i++) { + State bit = init.data.bits[i]; + int lane = i % mem.width; + if (bit != State::Sx && bit != State::S0) { + always_0[lane] = false; + } + if (bit != State::Sx && bit != State::S1) { + always_1[lane] = false; + } + } } - - if (mem.wr_ports.empty() && mem.inits.empty()) { - // The whole memory array will contain - // only State::Sx, but the embedded read - // registers could have reset or init values. - // They will probably be optimized away by - // opt_dff later. - for (int i = 0; i < GetSize(mem.rd_ports); i++) { - mem.extract_rdff(i, &initvals); - auto &port = mem.rd_ports[i]; - module->connect(port.data, Const(State::Sx, GetSize(port.data))); + std::vector<int> swizzle; + for (int i = 0; i < mem.width; i++) { + if (!always_0[i] && !always_1[i]) { + swizzle.push_back(i); + continue; } + State bit; + if (!always_0[i]) { + log("%s.%s: removing const-1 lane %d\n", log_id(module->name), log_id(mem.memid), i); + bit = State::S1; + } else if (!always_1[i]) { + log("%s.%s: removing const-0 lane %d\n", log_id(module->name), log_id(mem.memid), i); + bit = State::S0; + } else { + log("%s.%s: removing const-x lane %d\n", log_id(module->name), log_id(mem.memid), i); + bit = State::Sx; + } + // Reconnect read port data. + for (auto &port: mem.rd_ports) { + for (int sub = 0; sub < (1 << port.wide_log2); sub++) { + int bidx = sub * mem.width + i; + if (!port.clk_enable) { + module->connect(port.data[bidx], bit); + } else { + // The FF will most likely be redundant, but it's up to opt_dff to deal with this. + FfData ff(module, &initvals, NEW_ID); + ff.width = 1; + ff.has_clk = true; + ff.sig_clk = port.clk; + ff.pol_clk = port.clk_polarity; + if (port.en != State::S1) { + ff.has_ce = true; + ff.pol_ce = true; + ff.sig_ce = port.en; + } + if (port.arst != State::S0) { + ff.has_arst = true; + ff.pol_arst = true; + ff.sig_arst = port.arst; + ff.val_arst = port.arst_value[bidx]; + } + if (port.srst != State::S0) { + ff.has_srst = true; + ff.pol_srst = true; + ff.sig_srst = port.srst; + ff.val_srst = port.srst_value[bidx]; + } + ff.sig_d = bit; + ff.sig_q = port.data[bidx]; + ff.val_init = port.init_value[bidx]; + ff.emit(); + } + } + } + } + if (GetSize(swizzle) == 0) { mem.remove(); total_count++; + continue; + } + if (GetSize(swizzle) != mem.width) { + for (auto &port: mem.wr_ports) { + SigSpec new_data; + SigSpec new_en; + for (int sub = 0; sub < (1 << port.wide_log2); sub++) { + for (auto i: swizzle) { + new_data.append(port.data[sub * mem.width + i]); + new_en.append(port.en[sub * mem.width + i]); + } + } + port.data = new_data; + port.en = new_en; + } + for (auto &port: mem.rd_ports) { + SigSpec new_data; + Const new_init; + Const new_arst; + Const new_srst; + for (int sub = 0; sub < (1 << port.wide_log2); sub++) { + for (auto i: swizzle) { + int bidx = sub * mem.width + i; + new_data.append(port.data[bidx]); + new_init.bits.push_back(port.init_value.bits[bidx]); + new_arst.bits.push_back(port.arst_value.bits[bidx]); + new_srst.bits.push_back(port.srst_value.bits[bidx]); + } + } + port.data = new_data; + port.init_value = new_init; + port.arst_value = new_arst; + port.srst_value = new_srst; + } + for (auto &init: mem.inits) { + Const new_data; + Const new_en; + for (int s = 0; s < GetSize(init.data); s += mem.width) { + for (auto i: swizzle) { + new_data.bits.push_back(init.data.bits[s + i]); + } + } + for (auto i: swizzle) { + new_en.bits.push_back(init.en.bits[i]); + } + init.data = new_data; + init.en = new_en; + } + mem.width = GetSize(swizzle); + changed = true; + total_count++; + } + if (changed) { + mem.emit(); } } } diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 7b52b85cd..d085fab2d 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -157,6 +157,7 @@ struct SimInstance dict<Wire*, pair<int, Const>> signal_database; dict<Wire*, fstHandle> fst_handles; + dict<IdString, dict<int,fstHandle>> fst_memories; SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) : shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module) @@ -243,7 +244,10 @@ struct SimInstance if (cell->is_mem_cell()) { - mem_cells[cell] = cell->parameters.at(ID::MEMID).decode_string(); + std::string name = cell->parameters.at(ID::MEMID).decode_string(); + mem_cells[cell] = name; + if (shared->fst) + fst_memories[name] = shared->fst->getMemoryHandles(scope + "." + RTLIL::unescape_id(name)); } if (cell->type.in(ID($assert), ID($cover), ID($assume))) { formal_database.insert(cell); @@ -336,7 +340,7 @@ struct SimInstance int offset = (addr.as_int() - state.mem->start_offset) * state.mem->width; for (int i = 0; i < GetSize(data); i++) - if (0 <= i+offset && i+offset < GetSize(data)) + if (0 <= i+offset && i+offset < state.mem->size * state.mem->width) state.data.bits[i+offset] = data.bits[i]; } @@ -799,6 +803,18 @@ struct SimInstance did_something |= true; } } + for (auto cell : module->cells()) + { + if (cell->is_mem_cell()) { + std::string memid = cell->parameters.at(ID::MEMID).decode_string(); + for (auto &data : fst_memories[memid]) + { + std::string v = shared->fst->valueOf(data.second); + set_memory_state(memid, Const(data.first), Const::from_string(v)); + } + } + } + for (auto child : children) did_something |= child.second->setInitState(); return did_something; diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index a37b2a0f3..ff98a6e36 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -115,7 +115,7 @@ int map_autoidx; SigMap assign_map; RTLIL::Module *module; std::vector<gate_t> signal_list; -std::map<RTLIL::SigBit, int> signal_map; +dict<RTLIL::SigBit, int> signal_map; FfInitVals initvals; pool<std::string> enabled_gates; bool cmos_cost; @@ -409,7 +409,7 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1); } -void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts) +void dump_loop_graph(FILE *f, int &nr, dict<int, pool<int>> &edges, pool<int> &workpool, std::vector<int> &in_counts) { if (f == nullptr) return; @@ -420,7 +420,7 @@ void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std: fprintf(f, " label=\"slide%d\";\n", nr); fprintf(f, " rankdir=\"TD\";\n"); - std::set<int> nodes; + pool<int> nodes; for (auto &e : edges) { nodes.insert(e.first); for (auto n : e.second) @@ -443,9 +443,9 @@ void handle_loops() // http://en.wikipedia.org/wiki/Topological_sorting // (Kahn, Arthur B. (1962), "Topological sorting of large networks") - std::map<int, std::set<int>> edges; + dict<int, pool<int>> edges; std::vector<int> in_edges_count(signal_list.size()); - std::set<int> workpool; + pool<int> workpool; FILE *dot_f = nullptr; int dot_nr = 0; @@ -1135,7 +1135,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin SigMap mapped_sigmap(mapped_mod); FfInitVals mapped_initvals(&mapped_sigmap, mapped_mod); - std::map<std::string, int> cell_stats; + dict<std::string, int> cell_stats; for (auto c : mapped_mod->cells()) { if (builtin_lib) @@ -2000,18 +2000,18 @@ struct AbcPass : public Pass { CellTypes ct(design); std::vector<RTLIL::Cell*> all_cells = mod->selected_cells(); - std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end()); + pool<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end()); - std::set<RTLIL::Cell*> expand_queue, next_expand_queue; - std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up; - std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down; + pool<RTLIL::Cell*> expand_queue, next_expand_queue; + pool<RTLIL::Cell*> expand_queue_up, next_expand_queue_up; + pool<RTLIL::Cell*> expand_queue_down, next_expand_queue_down; typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec, bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t; - std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells; - std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse; + dict<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells; + dict<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse; - std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down; - std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down; + dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down; + dict<RTLIL::SigBit, pool<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down; for (auto cell : all_cells) { |