aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/memory/memory_share.cc2
-rw-r--r--passes/opt/opt_mem.cc156
-rw-r--r--passes/techmap/abc.cc28
3 files changed, 158 insertions, 28 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/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)
{