1 /*
2  *  yosys -- Yosys Open SYnthesis Suite
3  *
4  *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
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 "simplemap.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/ff.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 USING_YOSYS_NAMESPACE
28 YOSYS_NAMESPACE_BEGIN
29 
simplemap_not(RTLIL::Module * module,RTLIL::Cell * cell)30 void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
31 {
32 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
33 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
34 
35 	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
36 
37 	for (int i = 0; i < GetSize(sig_y); i++) {
38 		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
39 		gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
40 		gate->setPort(ID::A, sig_a[i]);
41 		gate->setPort(ID::Y, sig_y[i]);
42 	}
43 }
44 
simplemap_pos(RTLIL::Module * module,RTLIL::Cell * cell)45 void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
46 {
47 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
48 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
49 
50 	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
51 
52 	module->connect(RTLIL::SigSig(sig_y, sig_a));
53 }
54 
simplemap_bitop(RTLIL::Module * module,RTLIL::Cell * cell)55 void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
56 {
57 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
58 	RTLIL::SigSpec sig_b = cell->getPort(ID::B);
59 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
60 
61 	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
62 	sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool());
63 
64 	if (cell->type == ID($xnor))
65 	{
66 		RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y));
67 
68 		for (int i = 0; i < GetSize(sig_y); i++) {
69 			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
70 			gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
71 			gate->setPort(ID::A, sig_t[i]);
72 			gate->setPort(ID::Y, sig_y[i]);
73 		}
74 
75 		sig_y = sig_t;
76 	}
77 
78 	IdString gate_type;
79 	if (cell->type == ID($and))  gate_type = ID($_AND_);
80 	if (cell->type == ID($or))   gate_type = ID($_OR_);
81 	if (cell->type == ID($xor))  gate_type = ID($_XOR_);
82 	if (cell->type == ID($xnor)) gate_type = ID($_XOR_);
83 	log_assert(!gate_type.empty());
84 
85 	for (int i = 0; i < GetSize(sig_y); i++) {
86 		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
87 		gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
88 		gate->setPort(ID::A, sig_a[i]);
89 		gate->setPort(ID::B, sig_b[i]);
90 		gate->setPort(ID::Y, sig_y[i]);
91 	}
92 }
93 
simplemap_reduce(RTLIL::Module * module,RTLIL::Cell * cell)94 void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
95 {
96 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
97 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
98 
99 	if (sig_y.size() == 0)
100 		return;
101 
102 	if (sig_a.size() == 0) {
103 		if (cell->type == ID($reduce_and))  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
104 		if (cell->type == ID($reduce_or))   module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
105 		if (cell->type == ID($reduce_xor))  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
106 		if (cell->type == ID($reduce_xnor)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
107 		if (cell->type == ID($reduce_bool)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
108 		return;
109 	}
110 
111 	if (sig_y.size() > 1) {
112 		module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
113 		sig_y = sig_y.extract(0, 1);
114 	}
115 
116 	IdString gate_type;
117 	if (cell->type == ID($reduce_and))  gate_type = ID($_AND_);
118 	if (cell->type == ID($reduce_or))   gate_type = ID($_OR_);
119 	if (cell->type == ID($reduce_xor))  gate_type = ID($_XOR_);
120 	if (cell->type == ID($reduce_xnor)) gate_type = ID($_XOR_);
121 	if (cell->type == ID($reduce_bool)) gate_type = ID($_OR_);
122 	log_assert(!gate_type.empty());
123 
124 	RTLIL::Cell *last_output_cell = NULL;
125 
126 	while (sig_a.size() > 1)
127 	{
128 		RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig_a.size() / 2);
129 
130 		for (int i = 0; i < sig_a.size(); i += 2)
131 		{
132 			if (i+1 == sig_a.size()) {
133 				sig_t.append(sig_a[i]);
134 				continue;
135 			}
136 
137 			RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
138 			gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
139 			gate->setPort(ID::A, sig_a[i]);
140 			gate->setPort(ID::B, sig_a[i+1]);
141 			gate->setPort(ID::Y, sig_t[i/2]);
142 			last_output_cell = gate;
143 		}
144 
145 		sig_a = sig_t;
146 	}
147 
148 	if (cell->type == ID($reduce_xnor)) {
149 		RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
150 		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
151 		gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
152 		gate->setPort(ID::A, sig_a);
153 		gate->setPort(ID::Y, sig_t);
154 		last_output_cell = gate;
155 		sig_a = sig_t;
156 	}
157 
158 	if (last_output_cell == NULL) {
159 		module->connect(RTLIL::SigSig(sig_y, sig_a));
160 	} else {
161 		last_output_cell->setPort(ID::Y, sig_y);
162 	}
163 }
164 
logic_reduce(RTLIL::Module * module,RTLIL::SigSpec & sig,RTLIL::Cell * cell)165 static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell *cell)
166 {
167 	while (sig.size() > 1)
168 	{
169 		RTLIL::SigSpec sig_t = module->addWire(NEW_ID, sig.size() / 2);
170 
171 		for (int i = 0; i < sig.size(); i += 2)
172 		{
173 			if (i+1 == sig.size()) {
174 				sig_t.append(sig[i]);
175 				continue;
176 			}
177 
178 			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
179 			gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
180 			gate->setPort(ID::A, sig[i]);
181 			gate->setPort(ID::B, sig[i+1]);
182 			gate->setPort(ID::Y, sig_t[i/2]);
183 		}
184 
185 		sig = sig_t;
186 	}
187 
188 	if (sig.size() == 0)
189 		sig = State::S0;
190 }
191 
simplemap_lognot(RTLIL::Module * module,RTLIL::Cell * cell)192 void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
193 {
194 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
195 	logic_reduce(module, sig_a, cell);
196 
197 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
198 
199 	if (sig_y.size() == 0)
200 		return;
201 
202 	if (sig_y.size() > 1) {
203 		module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
204 		sig_y = sig_y.extract(0, 1);
205 	}
206 
207 	RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
208 	gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
209 	gate->setPort(ID::A, sig_a);
210 	gate->setPort(ID::Y, sig_y);
211 }
212 
simplemap_logbin(RTLIL::Module * module,RTLIL::Cell * cell)213 void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
214 {
215 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
216 	logic_reduce(module, sig_a, cell);
217 
218 	RTLIL::SigSpec sig_b = cell->getPort(ID::B);
219 	logic_reduce(module, sig_b, cell);
220 
221 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
222 
223 	if (sig_y.size() == 0)
224 		return;
225 
226 	if (sig_y.size() > 1) {
227 		module->connect(RTLIL::SigSig(sig_y.extract(1, sig_y.size()-1), RTLIL::SigSpec(0, sig_y.size()-1)));
228 		sig_y = sig_y.extract(0, 1);
229 	}
230 
231 	IdString gate_type;
232 	if (cell->type == ID($logic_and)) gate_type = ID($_AND_);
233 	if (cell->type == ID($logic_or))  gate_type = ID($_OR_);
234 	log_assert(!gate_type.empty());
235 
236 	RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
237 	gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
238 	gate->setPort(ID::A, sig_a);
239 	gate->setPort(ID::B, sig_b);
240 	gate->setPort(ID::Y, sig_y);
241 }
242 
simplemap_eqne(RTLIL::Module * module,RTLIL::Cell * cell)243 void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
244 {
245 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
246 	RTLIL::SigSpec sig_b = cell->getPort(ID::B);
247 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
248 	bool is_signed = cell->parameters.at(ID::A_SIGNED).as_bool();
249 	bool is_ne = cell->type.in(ID($ne), ID($nex));
250 
251 	RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b)));
252 	RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
253 	xor_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
254 	simplemap_bitop(module, xor_cell);
255 	module->remove(xor_cell);
256 
257 	RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
258 	RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out);
259 	reduce_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
260 	simplemap_reduce(module, reduce_cell);
261 	module->remove(reduce_cell);
262 
263 	if (!is_ne) {
264 		RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y);
265 		not_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
266 		simplemap_lognot(module, not_cell);
267 		module->remove(not_cell);
268 	}
269 }
270 
simplemap_mux(RTLIL::Module * module,RTLIL::Cell * cell)271 void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
272 {
273 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
274 	RTLIL::SigSpec sig_b = cell->getPort(ID::B);
275 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
276 
277 	for (int i = 0; i < GetSize(sig_y); i++) {
278 		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
279 		gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
280 		gate->setPort(ID::A, sig_a[i]);
281 		gate->setPort(ID::B, sig_b[i]);
282 		gate->setPort(ID::S, cell->getPort(ID::S));
283 		gate->setPort(ID::Y, sig_y[i]);
284 	}
285 }
286 
simplemap_tribuf(RTLIL::Module * module,RTLIL::Cell * cell)287 void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
288 {
289 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
290 	RTLIL::SigSpec sig_e = cell->getPort(ID::EN);
291 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
292 
293 	for (int i = 0; i < GetSize(sig_y); i++) {
294 		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
295 		gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
296 		gate->setPort(ID::A, sig_a[i]);
297 		gate->setPort(ID::E, sig_e);
298 		gate->setPort(ID::Y, sig_y[i]);
299 	}
300 }
301 
simplemap_lut(RTLIL::Module * module,RTLIL::Cell * cell)302 void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
303 {
304 	SigSpec lut_ctrl = cell->getPort(ID::A);
305 	SigSpec lut_data = cell->getParam(ID::LUT);
306 	lut_data.extend_u0(1 << cell->getParam(ID::WIDTH).as_int());
307 
308 	for (int idx = 0; GetSize(lut_data) > 1; idx++) {
309 		SigSpec sig_s = lut_ctrl[idx];
310 		SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
311 		for (int i = 0; i < GetSize(lut_data); i += 2) {
312 			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
313 			gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
314 			gate->setPort(ID::A, lut_data[i]);
315 			gate->setPort(ID::B, lut_data[i+1]);
316 			gate->setPort(ID::S, lut_ctrl[idx]);
317 			gate->setPort(ID::Y, new_lut_data[i/2]);
318 		}
319 		lut_data = new_lut_data;
320 	}
321 
322 	module->connect(cell->getPort(ID::Y), lut_data);
323 }
324 
simplemap_sop(RTLIL::Module * module,RTLIL::Cell * cell)325 void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
326 {
327 	SigSpec ctrl = cell->getPort(ID::A);
328 	SigSpec table = cell->getParam(ID::TABLE);
329 
330 	int width = cell->getParam(ID::WIDTH).as_int();
331 	int depth = cell->getParam(ID::DEPTH).as_int();
332 	table.extend_u0(2 * width * depth);
333 
334 	SigSpec products;
335 
336 	for (int i = 0; i < depth; i++) {
337 		SigSpec in, pat;
338 		for (int j = 0; j < width; j++) {
339 			if (table[2*i*width + 2*j + 0] == State::S1) {
340 				in.append(ctrl[j]);
341 				pat.append(State::S0);
342 			}
343 			if (table[2*i*width + 2*j + 1] == State::S1) {
344 				in.append(ctrl[j]);
345 				pat.append(State::S1);
346 			}
347 		}
348 
349 		products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
350 	}
351 
352 	module->connect(cell->getPort(ID::Y), module->ReduceOr(NEW_ID, products));
353 }
354 
simplemap_slice(RTLIL::Module * module,RTLIL::Cell * cell)355 void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
356 {
357 	int offset = cell->parameters.at(ID::OFFSET).as_int();
358 	RTLIL::SigSpec sig_a = cell->getPort(ID::A);
359 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
360 	module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
361 }
362 
simplemap_concat(RTLIL::Module * module,RTLIL::Cell * cell)363 void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
364 {
365 	RTLIL::SigSpec sig_ab = cell->getPort(ID::A);
366 	sig_ab.append(cell->getPort(ID::B));
367 	RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
368 	module->connect(RTLIL::SigSig(sig_y, sig_ab));
369 }
370 
simplemap_ff(RTLIL::Module *,RTLIL::Cell * cell)371 void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell)
372 {
373 	FfData ff(nullptr, cell);
374 	for (int i = 0; i < ff.width; i++) {
375 		FfData fff = ff.slice({i});
376 		fff.is_fine = true;
377 		fff.emit();
378 	}
379 }
380 
simplemap_get_mappers(dict<IdString,void (*)(RTLIL::Module *,RTLIL::Cell *)> & mappers)381 void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
382 {
383 	mappers[ID($not)]         = simplemap_not;
384 	mappers[ID($pos)]         = simplemap_pos;
385 	mappers[ID($and)]         = simplemap_bitop;
386 	mappers[ID($or)]          = simplemap_bitop;
387 	mappers[ID($xor)]         = simplemap_bitop;
388 	mappers[ID($xnor)]        = simplemap_bitop;
389 	mappers[ID($reduce_and)]  = simplemap_reduce;
390 	mappers[ID($reduce_or)]   = simplemap_reduce;
391 	mappers[ID($reduce_xor)]  = simplemap_reduce;
392 	mappers[ID($reduce_xnor)] = simplemap_reduce;
393 	mappers[ID($reduce_bool)] = simplemap_reduce;
394 	mappers[ID($logic_not)]   = simplemap_lognot;
395 	mappers[ID($logic_and)]   = simplemap_logbin;
396 	mappers[ID($logic_or)]    = simplemap_logbin;
397 	mappers[ID($eq)]          = simplemap_eqne;
398 	mappers[ID($eqx)]         = simplemap_eqne;
399 	mappers[ID($ne)]          = simplemap_eqne;
400 	mappers[ID($nex)]         = simplemap_eqne;
401 	mappers[ID($mux)]         = simplemap_mux;
402 	mappers[ID($tribuf)]      = simplemap_tribuf;
403 	mappers[ID($lut)]         = simplemap_lut;
404 	mappers[ID($sop)]         = simplemap_sop;
405 	mappers[ID($slice)]       = simplemap_slice;
406 	mappers[ID($concat)]      = simplemap_concat;
407 	mappers[ID($sr)]          = simplemap_ff;
408 	mappers[ID($ff)]          = simplemap_ff;
409 	mappers[ID($dff)]         = simplemap_ff;
410 	mappers[ID($dffe)]        = simplemap_ff;
411 	mappers[ID($dffsr)]       = simplemap_ff;
412 	mappers[ID($dffsre)]      = simplemap_ff;
413 	mappers[ID($adff)]        = simplemap_ff;
414 	mappers[ID($sdff)]        = simplemap_ff;
415 	mappers[ID($adffe)]       = simplemap_ff;
416 	mappers[ID($sdffe)]       = simplemap_ff;
417 	mappers[ID($sdffce)]      = simplemap_ff;
418 	mappers[ID($aldff)]       = simplemap_ff;
419 	mappers[ID($aldffe)]      = simplemap_ff;
420 	mappers[ID($dlatch)]      = simplemap_ff;
421 	mappers[ID($adlatch)]     = simplemap_ff;
422 	mappers[ID($dlatchsr)]    = simplemap_ff;
423 }
424 
simplemap(RTLIL::Module * module,RTLIL::Cell * cell)425 void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
426 {
427 	static dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
428 	static bool initialized_mappers = false;
429 
430 	if (!initialized_mappers) {
431 		simplemap_get_mappers(mappers);
432 		initialized_mappers = true;
433 	}
434 
435 	mappers.at(cell->type)(module, cell);
436 }
437 
438 YOSYS_NAMESPACE_END
439 PRIVATE_NAMESPACE_BEGIN
440 
441 struct SimplemapPass : public Pass {
SimplemapPassSimplemapPass442 	SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
helpSimplemapPass443 	void help() override
444 	{
445 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
446 		log("\n");
447 		log("    simplemap [selection]\n");
448 		log("\n");
449 		log("This pass maps a small selection of simple coarse-grain cells to yosys gate\n");
450 		log("primitives. The following internal cell types are mapped by this pass:\n");
451 		log("\n");
452 		log("  $not, $pos, $and, $or, $xor, $xnor\n");
453 		log("  $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
454 		log("  $logic_not, $logic_and, $logic_or, $mux, $tribuf\n");
455 		log("  $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
456 		log("\n");
457 	}
executeSimplemapPass458 	void execute(std::vector<std::string> args, RTLIL::Design *design) override
459 	{
460 		log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
461 		extra_args(args, 1, design);
462 
463 		dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
464 		simplemap_get_mappers(mappers);
465 
466 		for (auto mod : design->modules()) {
467 			if (!design->selected(mod) || mod->get_blackbox_attribute())
468 				continue;
469 			std::vector<RTLIL::Cell*> cells = mod->cells();
470 			for (auto cell : cells) {
471 				if (mappers.count(cell->type) == 0)
472 					continue;
473 				if (!design->selected(mod, cell))
474 					continue;
475 				log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
476 				mappers.at(cell->type)(mod, cell);
477 				mod->remove(cell);
478 			}
479 		}
480 	}
481 } SimplemapPass;
482 
483 PRIVATE_NAMESPACE_END
484