abc9: generate $abc9_holes design instead of <name>$holes
[yosys.git] / passes / techmap / aigmap.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/cellaigs.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 struct AigmapPass : public Pass {
27 AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { }
28 void help() YS_OVERRIDE
29 {
30 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
31 log("\n");
32 log(" aigmap [options] [selection]\n");
33 log("\n");
34 log("Replace all logic cells with circuits made of only $_AND_ and\n");
35 log("$_NOT_ cells.\n");
36 log("\n");
37 log(" -nand\n");
38 log(" Enable creation of $_NAND_ cells\n");
39 log("\n");
40 log(" -select\n");
41 log(" Overwrite replaced cells in the current selection with new $_AND_,\n");
42 log(" $_NOT_, and $_NAND_, cells\n");
43
44 log("\n");
45 }
46 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
47 {
48 bool nand_mode = false, select_mode = false;
49
50 log_header(design, "Executing AIGMAP pass (map logic to AIG).\n");
51
52 size_t argidx;
53 for (argidx = 1; argidx < args.size(); argidx++)
54 {
55 if (args[argidx] == "-nand") {
56 nand_mode = true;
57 continue;
58 }
59 if (args[argidx] == "-select") {
60 select_mode = true;
61 continue;
62 }
63 break;
64 }
65 extra_args(args, argidx, design);
66
67 for (auto module : design->selected_modules())
68 {
69 vector<Cell*> replaced_cells;
70 int not_replaced_count = 0;
71 dict<IdString, int> stat_replaced;
72 dict<IdString, int> stat_not_replaced;
73 int orig_num_cells = GetSize(module->cells());
74
75 pool<IdString> new_sel;
76 for (auto cell : module->selected_cells())
77 {
78 Aig aig(cell);
79
80 if (cell->type.in(ID($_AND_), ID($_NOT_)))
81 aig.name.clear();
82
83 if (nand_mode && cell->type == ID($_NAND_))
84 aig.name.clear();
85
86 if (aig.name.empty()) {
87 not_replaced_count++;
88 stat_not_replaced[cell->type]++;
89 if (select_mode)
90 new_sel.insert(cell->name);
91 continue;
92 }
93
94 vector<SigBit> sigs;
95 dict<pair<int, int>, SigBit> and_cache;
96
97 for (int node_idx = 0; node_idx < GetSize(aig.nodes); node_idx++)
98 {
99 SigBit bit;
100 auto &node = aig.nodes[node_idx];
101
102 if (node.portbit >= 0) {
103 bit = cell->getPort(node.portname)[node.portbit];
104 } else if (node.left_parent < 0 && node.right_parent < 0) {
105 bit = node.inverter ? State::S1 : State::S0;
106 goto skip_inverter;
107 } else {
108 SigBit A = sigs.at(node.left_parent);
109 SigBit B = sigs.at(node.right_parent);
110 if (nand_mode && node.inverter) {
111 bit = module->addWire(NEW_ID);
112 auto gate = module->addNandGate(NEW_ID, A, B, bit);
113 if (select_mode)
114 new_sel.insert(gate->name);
115
116 goto skip_inverter;
117 } else {
118 pair<int, int> key(node.left_parent, node.right_parent);
119 if (and_cache.count(key))
120 bit = and_cache.at(key);
121 else {
122 bit = module->addWire(NEW_ID);
123 auto gate = module->addAndGate(NEW_ID, A, B, bit);
124 if (select_mode)
125 new_sel.insert(gate->name);
126 }
127 }
128 }
129
130 if (node.inverter) {
131 SigBit new_bit = module->addWire(NEW_ID);
132 auto gate = module->addNotGate(NEW_ID, bit, new_bit);
133 bit = new_bit;
134 if (select_mode)
135 new_sel.insert(gate->name);
136
137 }
138
139 skip_inverter:
140 for (auto &op : node.outports)
141 module->connect(cell->getPort(op.first)[op.second], bit);
142
143 sigs.push_back(bit);
144 }
145
146 replaced_cells.push_back(cell);
147 stat_replaced[cell->type]++;
148 }
149
150 if (not_replaced_count == 0 && replaced_cells.empty())
151 continue;
152
153 log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", log_id(module),
154 GetSize(replaced_cells), GetSize(module->cells()) - orig_num_cells, not_replaced_count);
155
156 if (!stat_replaced.empty()) {
157 stat_replaced.sort();
158 log(" replaced %d cell types:\n", GetSize(stat_replaced));
159 for (auto &it : stat_replaced)
160 log("%8d %s\n", it.second, log_id(it.first));
161 }
162
163 if (!stat_not_replaced.empty()) {
164 stat_not_replaced.sort();
165 log(" not replaced %d cell types:\n", GetSize(stat_not_replaced));
166 for (auto &it : stat_not_replaced)
167 log("%8d %s\n", it.second, log_id(it.first));
168 }
169
170 for (auto cell : replaced_cells)
171 module->remove(cell);
172
173 if (select_mode) {
174 log_assert(!design->selection_stack.empty());
175 RTLIL::Selection& sel = design->selection_stack.back();
176 sel.selected_members[module->name] = std::move(new_sel);
177 }
178
179 }
180 }
181 } AigmapPass;
182
183 PRIVATE_NAMESPACE_END