2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/cellaigs.h"
24 PRIVATE_NAMESPACE_BEGIN
26 struct AigmapPass
: public Pass
{
27 AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { }
28 void help() YS_OVERRIDE
31 log(" aigmap [options] [selection]\n");
33 log("Replace all logic cells with circuits made of only $_AND_ and\n");
34 log("$_NOT_ cells.\n");
37 log(" Enable creation of $_NAND_ cells\n");
40 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
42 bool nand_mode
= false;
44 log_header(design
, "Executing AIGMAP pass (map logic to AIG).\n");
47 for (argidx
= 1; argidx
< args
.size(); argidx
++)
49 if (args
[argidx
] == "-nand") {
55 extra_args(args
, argidx
, design
);
57 for (auto module
: design
->selected_modules())
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());
65 for (auto cell
: module
->selected_cells())
69 if (cell
->type
.in(ID($_AND_
), ID($_NOT_
)))
72 if (nand_mode
&& cell
->type
== ID($_NAND_
))
75 if (aig
.name
.empty()) {
77 stat_not_replaced
[cell
->type
]++;
82 dict
<pair
<int, int>, SigBit
> and_cache
;
84 for (int node_idx
= 0; node_idx
< GetSize(aig
.nodes
); node_idx
++)
87 auto &node
= aig
.nodes
[node_idx
];
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::S1
: State::S0
;
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
);
101 pair
<int, int> key(node
.left_parent
, node
.right_parent
);
102 if (and_cache
.count(key
))
103 bit
= and_cache
.at(key
);
105 bit
= module
->AndGate(NEW_ID
, A
, B
);
110 bit
= module
->NotGate(NEW_ID
, bit
);
113 for (auto &op
: node
.outports
)
114 module
->connect(cell
->getPort(op
.first
)[op
.second
], bit
);
119 replaced_cells
.push_back(cell
);
120 stat_replaced
[cell
->type
]++;
123 if (not_replaced_count
== 0 && replaced_cells
.empty())
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
);
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
));
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
));
143 for (auto cell
: replaced_cells
)
144 module
->remove(cell
);
149 PRIVATE_NAMESPACE_END