9f552e3e568fc0c24a151c181e7aa62f82b82646
[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 virtual void help()
29 {
30 log("\n");
31 log(" aigmap [options] [selection]\n");
32 log("\n");
33 log("Replace all logic cells with circuits made of only $_AND_ and\n");
34 log("$_NOT_ cells.\n");
35 log("\n");
36 log(" -nand\n");
37 log(" Enable creation of $_NAND_ cells\n");
38 log("\n");
39 }
40 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
41 {
42 bool nand_mode = false;
43
44 log_header("Executing AIGMAP pass (map logic to AIG).\n");
45
46 size_t argidx;
47 for (argidx = 1; argidx < args.size(); argidx++)
48 {
49 if (args[argidx] == "-nand") {
50 nand_mode = true;
51 continue;
52 }
53 break;
54 }
55 extra_args(args, argidx, design);
56
57 for (auto module : design->selected_modules())
58 {
59 vector<Cell*> replaced_cells;
60 int not_replaced_count = 0;
61 dict<IdString, int> stat_replaced;
62 dict<IdString, int> stat_not_replaced;
63 int orig_num_cells = GetSize(module->cells());
64
65 for (auto cell : module->selected_cells())
66 {
67 Aig aig(cell);
68
69 if (cell->type == "$_AND_" || cell->type == "$_NOT_")
70 aig.name.clear();
71
72 if (nand_mode && cell->type == "$_NAND_")
73 aig.name.clear();
74
75 if (aig.name.empty()) {
76 not_replaced_count++;
77 stat_not_replaced[cell->type]++;
78 continue;
79 }
80
81 vector<SigBit> sigs;
82 dict<pair<int, int>, SigBit> and_cache;
83
84 for (int node_idx = 0; node_idx < GetSize(aig.nodes); node_idx++)
85 {
86 SigBit bit;
87 auto &node = aig.nodes[node_idx];
88
89 if (node.portbit >= 0) {
90 bit = cell->getPort(node.portname)[node.portbit];
91 } else if (node.left_parent < 0 && node.right_parent < 0) {
92 bit = node.inverter ? State::S0 : State::S1;
93 goto skip_inverter;
94 } else {
95 SigBit A = sigs.at(node.left_parent);
96 SigBit B = sigs.at(node.right_parent);
97 if (nand_mode && node.inverter) {
98 bit = module->NandGate(NEW_ID, A, B);
99 goto skip_inverter;
100 } else {
101 pair<int, int> key(node.left_parent, node.right_parent);
102 if (and_cache.count(key))
103 bit = and_cache.at(key);
104 else
105 bit = module->AndGate(NEW_ID, A, B);
106 }
107 }
108
109 if (node.inverter)
110 bit = module->NotGate(NEW_ID, bit);
111
112 skip_inverter:
113 for (auto &op : node.outports)
114 module->connect(cell->getPort(op.first)[op.second], bit);
115
116 sigs.push_back(bit);
117 }
118
119 replaced_cells.push_back(cell);
120 stat_replaced[cell->type]++;
121 }
122
123 if (not_replaced_count == 0 && replaced_cells.empty())
124 continue;
125
126 log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", log_id(module),
127 GetSize(replaced_cells), GetSize(module->cells()) - orig_num_cells, not_replaced_count);
128
129 if (!stat_replaced.empty()) {
130 stat_replaced.sort();
131 log(" replaced %d cell types:\n", GetSize(stat_replaced));
132 for (auto &it : stat_replaced)
133 log("%8d %s\n", it.second, log_id(it.first));
134 }
135
136 if (!stat_not_replaced.empty()) {
137 stat_not_replaced.sort();
138 log(" not replaced %d cell types:\n", GetSize(stat_not_replaced));
139 for (auto &it : stat_not_replaced)
140 log("%8d %s\n", it.second, log_id(it.first));
141 }
142
143 for (auto cell : replaced_cells)
144 module->remove(cell);
145 }
146 }
147 } AigmapPass;
148
149 PRIVATE_NAMESPACE_END