29 #define USE_CELL_HASH_CACHE
43 #ifdef USE_CELL_HASH_CACHE
47 #ifdef USE_CELL_HASH_CACHE
54 str +=
'a' + (v & 15);
65 std::string hash_string = cell->
type.
str() +
"\n";
68 hash_string +=
"P " + it.first.str() +
"=" + it.second.as_string() +
"\n";
70 const std::map<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->
connections();
71 std::map<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
73 if (cell->
type ==
"$and" || cell->
type ==
"$or" || cell->
type ==
"$xor" || cell->
type ==
"$xnor" || cell->
type ==
"$add" || cell->
type ==
"$mul" ||
74 cell->
type ==
"$logic_and" || cell->
type ==
"$logic_or" || cell->
type ==
"$_AND_" || cell->
type ==
"$_OR_" || cell->
type ==
"$_XOR_") {
77 alt_conn[
"\\A"] = conn->at(
"\\B");
78 alt_conn[
"\\B"] = conn->at(
"\\A");
82 if (cell->
type ==
"$reduce_xor" || cell->
type ==
"$reduce_xnor") {
85 alt_conn.at(
"\\A").sort();
88 if (cell->
type ==
"$reduce_and" || cell->
type ==
"$reduce_or" || cell->
type ==
"$reduce_bool") {
91 alt_conn.at(
"\\A").sort_and_unify();
95 for (
auto &it : *conn) {
100 hash_string +=
"C " + it.first.str() +
"=";
101 for (
auto &chunk : sig.
chunks()) {
103 hash_string +=
"{" + chunk.wire->name.str() +
" " +
119 #ifdef USE_CELL_HASH_CACHE
123 if (hash1 != hash2) {
134 std::map<RTLIL::IdString, RTLIL::SigSpec> conn1 = cell1->
connections();
135 std::map<RTLIL::IdString, RTLIL::SigSpec> conn2 = cell2->
connections();
137 for (
auto &it : conn1) {
144 for (
auto &it : conn2) {
151 if (cell1->
type ==
"$and" || cell1->
type ==
"$or" || cell1->
type ==
"$xor" || cell1->
type ==
"$xnor" || cell1->
type ==
"$add" || cell1->
type ==
"$mul" ||
152 cell1->
type ==
"$logic_and" || cell1->
type ==
"$logic_or" || cell1->
type ==
"$_AND_" || cell1->
type ==
"$_OR_" || cell1->
type ==
"$_XOR_") {
153 if (conn1.at(
"\\A") < conn1.at(
"\\B")) {
155 conn1[
"\\A"] = conn1[
"\\B"];
158 if (conn2.at(
"\\A") < conn2.at(
"\\B")) {
160 conn2[
"\\A"] = conn2[
"\\B"];
164 if (cell1->
type ==
"$reduce_xor" || cell1->
type ==
"$reduce_xnor") {
168 if (cell1->
type ==
"$reduce_and" || cell1->
type ==
"$reduce_or" || cell1->
type ==
"$reduce_bool") {
169 conn1[
"\\A"].sort_and_unify();
170 conn2[
"\\A"].sort_and_unify();
173 if (conn1 != conn2) {
178 if (cell1->
type.
substr(0, 1) ==
"$" && conn1.count(
"\\Q") != 0) {
181 for (
size_t i = 0; i < q1.size(); i++)
182 if ((q1.at(i).wire ==
NULL || q2.at(i).wire ==
NULL) && q1.at(i) != q2.at(i)) {
183 lt = q1.at(i) < q2.at(i);
197 return cell1 < cell2;
200 return cell1 < cell2;
218 design(design), module(module),
assign_map(module)
231 log(
"Finding identical cells in module `%s'.\n", module->
name.
c_str());
235 for (
auto &it : module->
wires_)
236 if (it.second->attributes.count(
"\\init") != 0)
240 while (did_something)
242 #ifdef USE_CELL_HASH_CACHE
245 std::vector<RTLIL::Cell*> cells;
246 cells.reserve(module->
cells_.size());
247 for (
auto &it : module->
cells_) {
249 cells.push_back(it.second);
252 did_something =
false;
253 std::map<RTLIL::Cell*, RTLIL::Cell*, CompareCells> sharemap(
CompareCells(
this));
254 for (
auto cell : cells)
256 if (sharemap.count(cell) > 0) {
257 did_something =
true;
258 log(
" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
259 for (
auto &it : cell->connections()) {
262 log(
" Redirecting output %s: %s = %s\n", it.first.c_str(),
268 log(
" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->
name.
c_str());
272 sharemap[cell] = cell;
285 log(
" opt_share [-nomux] [selection]\n");
287 log(
"This pass identifies cells with identical type and input signals. Such cells\n");
288 log(
"are then merged to one cell.\n");
291 log(
" Do not merge MUX cells.\n");
296 log_header(
"Executing OPT_SHARE pass (detect identical cells).\n");
298 bool mode_nomux =
false;
301 for (argidx = 1; argidx < args.size(); argidx++) {
302 std::string arg = args[argidx];
303 if (arg ==
"-nomux") {
312 for (
auto &mod_it : design->
modules_) {
313 if (!design->
selected(mod_it.second))
321 log(
"Removed a total of %d cells.\n", total_count);
const char * c_str() const
bool selected(T1 *module) const
bool operator()(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const
void setup_internals_mem()
void log_header(const char *format,...)
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
std::map< RTLIL::IdString, RTLIL::Const > parameters
void apply(RTLIL::SigBit &bit) const
std::string int_to_hash_string(unsigned int v)
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool did_something
std::map< RTLIL::IdString, CellType > cell_types
void set(RTLIL::Module *module)
bool cell_known(RTLIL::IdString type)
void connect(const RTLIL::SigSig &conn)
std::string as_string() const
#define PRIVATE_NAMESPACE_BEGIN
std::string hash_cell_parameters_and_connections(const RTLIL::Cell *cell)
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
OptSharePass OptSharePass
CompareCells(OptShareWorker *that)
OptShareWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux)
bool compare_cells(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2)
#define PRIVATE_NAMESPACE_END
std::string substr(size_t pos=0, size_t len=std::string::npos) const
#define USING_YOSYS_NAMESPACE
std::map< RTLIL::IdString, RTLIL::Module * > modules_
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
void remove(const std::set< RTLIL::Wire * > &wires)
void log(const char *format,...)
std::string sha1(const std::string &string)
void scratchpad_set_bool(std::string varname, bool value)
void setup_stdcells_mem()
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2, bool <)
std::map< const RTLIL::Cell *, std::string > cell_hash_cache
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
std::pair< SigSpec, SigSpec > SigSig
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
bool has_keep_attr() const
const std::vector< RTLIL::SigChunk > & chunks() const