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/sigtools.h"
27 PRIVATE_NAMESPACE_BEGIN
30 std::string cell_name
;
31 std::map
<std::string
, char> ports
;
33 static std::map
<RTLIL::IdString
, cell_mapping
> cell_mappings
;
35 static void logmap(std::string dff
)
37 if (cell_mappings
.count(dff
) == 0) {
38 log(" unmapped dff cell: %s\n", dff
.c_str());
40 log(" %s %s (", cell_mappings
[dff
].cell_name
.c_str(), dff
.substr(1).c_str());
42 for (auto &port
: cell_mappings
[dff
].ports
) {
43 char arg
[3] = { port
.second
, 0, 0 };
44 if ('a' <= arg
[0] && arg
[0] <= 'z')
45 arg
[1] = arg
[0] - ('a' - 'A'), arg
[0] = '~';
47 arg
[1] = arg
[0], arg
[0] = ' ';
48 log("%s.%s(%s)", first
? "" : ", ", port
.first
.c_str(), arg
);
55 static void logmap_all()
69 logmap("$_DFFSR_NNN_");
70 logmap("$_DFFSR_NNP_");
71 logmap("$_DFFSR_NPN_");
72 logmap("$_DFFSR_NPP_");
73 logmap("$_DFFSR_PNN_");
74 logmap("$_DFFSR_PNP_");
75 logmap("$_DFFSR_PPN_");
76 logmap("$_DFFSR_PPP_");
79 static bool parse_pin(LibertyAst
*cell
, LibertyAst
*attr
, std::string
&pin_name
, bool &pin_pol
)
81 if (cell
== NULL
|| attr
== NULL
|| attr
->value
.empty())
84 std::string value
= attr
->value
;
86 for (size_t pos
= value
.find_first_of("\" \t()"); pos
!= std::string::npos
; pos
= value
.find_first_of("\" \t()"))
89 if (value
[value
.size()-1] == '\'') {
90 pin_name
= value
.substr(0, value
.size()-1);
92 } else if (value
[0] == '!') {
93 pin_name
= value
.substr(1, value
.size()-1);
100 for (auto child
: cell
->children
)
101 if (child
->id
== "pin" && child
->args
.size() == 1 && child
->args
[0] == pin_name
)
106 static void find_cell(LibertyAst
*ast
, std::string cell_type
, bool clkpol
, bool has_reset
, bool rstpol
, bool rstval
, bool prepare_mode
)
108 LibertyAst
*best_cell
= NULL
;
109 std::map
<std::string
, char> best_cell_ports
;
110 int best_cell_pins
= 0;
111 bool best_cell_noninv
= false;
112 double best_cell_area
= 0;
114 if (ast
->id
!= "library")
115 log_error("Format error in liberty file.\n");
117 for (auto cell
: ast
->children
)
119 if (cell
->id
!= "cell" || cell
->args
.size() != 1)
122 LibertyAst
*dn
= cell
->find("dont_use");
123 if (dn
!= NULL
&& dn
->value
== "true")
126 LibertyAst
*ff
= cell
->find("ff");
130 std::string cell_clk_pin
, cell_rst_pin
, cell_next_pin
;
131 bool cell_clk_pol
, cell_rst_pol
, cell_next_pol
;
133 if (!parse_pin(cell
, ff
->find("clocked_on"), cell_clk_pin
, cell_clk_pol
) || cell_clk_pol
!= clkpol
)
135 if (!parse_pin(cell
, ff
->find("next_state"), cell_next_pin
, cell_next_pol
))
137 if (has_reset
&& rstval
== false) {
138 if (!parse_pin(cell
, ff
->find("clear"), cell_rst_pin
, cell_rst_pol
) || cell_rst_pol
!= rstpol
)
141 if (has_reset
&& rstval
== true) {
142 if (!parse_pin(cell
, ff
->find("preset"), cell_rst_pin
, cell_rst_pol
) || cell_rst_pol
!= rstpol
)
146 std::map
<std::string
, char> this_cell_ports
;
147 this_cell_ports
[cell_clk_pin
] = 'C';
149 this_cell_ports
[cell_rst_pin
] = 'R';
150 this_cell_ports
[cell_next_pin
] = 'D';
153 LibertyAst
*ar
= cell
->find("area");
154 if (ar
!= NULL
&& !ar
->value
.empty())
155 area
= atof(ar
->value
.c_str());
158 bool found_output
= false;
159 bool found_noninv_output
= false;
160 for (auto pin
: cell
->children
)
162 if (pin
->id
!= "pin" || pin
->args
.size() != 1)
165 LibertyAst
*dir
= pin
->find("direction");
166 if (dir
== NULL
|| dir
->value
== "internal")
170 if (dir
->value
== "input" && this_cell_ports
.count(pin
->args
[0]) == 0)
171 goto continue_cell_loop
;
173 LibertyAst
*func
= pin
->find("function");
174 if (dir
->value
== "output" && func
!= NULL
) {
175 std::string value
= func
->value
;
176 for (size_t pos
= value
.find_first_of("\" \t"); pos
!= std::string::npos
; pos
= value
.find_first_of("\" \t"))
178 if (value
== ff
->args
[0]) {
179 this_cell_ports
[pin
->args
[0]] = cell_next_pol
? 'Q' : 'q';
181 found_noninv_output
= true;
184 if (value
== ff
->args
[1]) {
185 this_cell_ports
[pin
->args
[0]] = cell_next_pol
? 'q' : 'Q';
187 found_noninv_output
= true;
192 if (this_cell_ports
.count(pin
->args
[0]) == 0)
193 this_cell_ports
[pin
->args
[0]] = 0;
196 if (!found_output
|| (best_cell
!= NULL
&& (num_pins
> best_cell_pins
|| (best_cell_noninv
&& !found_noninv_output
))))
199 if (best_cell
!= NULL
&& num_pins
== best_cell_pins
&& area
> best_cell_area
)
203 best_cell_pins
= num_pins
;
204 best_cell_area
= area
;
205 best_cell_noninv
= found_noninv_output
;
206 best_cell_ports
.swap(this_cell_ports
);
210 if (best_cell
!= NULL
) {
211 log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
212 best_cell
->args
[0].c_str(), best_cell_noninv
? "non" : "", best_cell_pins
, best_cell_area
, cell_type
.c_str());
214 cell_mappings
[cell_type
].cell_name
= cell_type
;
215 cell_mappings
[cell_type
].ports
["C"] = 'C';
217 cell_mappings
[cell_type
].ports
["R"] = 'R';
218 cell_mappings
[cell_type
].ports
["D"] = 'D';
219 cell_mappings
[cell_type
].ports
["Q"] = 'Q';
221 cell_mappings
[cell_type
].cell_name
= best_cell
->args
[0];
222 cell_mappings
[cell_type
].ports
= best_cell_ports
;
227 static void find_cell_sr(LibertyAst
*ast
, std::string cell_type
, bool clkpol
, bool setpol
, bool clrpol
, bool prepare_mode
)
229 LibertyAst
*best_cell
= NULL
;
230 std::map
<std::string
, char> best_cell_ports
;
231 int best_cell_pins
= 0;
232 bool best_cell_noninv
= false;
233 double best_cell_area
= 0;
235 if (ast
->id
!= "library")
236 log_error("Format error in liberty file.\n");
238 for (auto cell
: ast
->children
)
240 if (cell
->id
!= "cell" || cell
->args
.size() != 1)
243 LibertyAst
*dn
= cell
->find("dont_use");
244 if (dn
!= NULL
&& dn
->value
== "true")
247 LibertyAst
*ff
= cell
->find("ff");
251 std::string cell_clk_pin
, cell_set_pin
, cell_clr_pin
, cell_next_pin
;
252 bool cell_clk_pol
, cell_set_pol
, cell_clr_pol
, cell_next_pol
;
254 if (!parse_pin(cell
, ff
->find("clocked_on"), cell_clk_pin
, cell_clk_pol
) || cell_clk_pol
!= clkpol
)
256 if (!parse_pin(cell
, ff
->find("next_state"), cell_next_pin
, cell_next_pol
))
258 if (!parse_pin(cell
, ff
->find("preset"), cell_set_pin
, cell_set_pol
) || cell_set_pol
!= setpol
)
260 if (!parse_pin(cell
, ff
->find("clear"), cell_clr_pin
, cell_clr_pol
) || cell_clr_pol
!= clrpol
)
263 std::map
<std::string
, char> this_cell_ports
;
264 this_cell_ports
[cell_clk_pin
] = 'C';
265 this_cell_ports
[cell_set_pin
] = 'S';
266 this_cell_ports
[cell_clr_pin
] = 'R';
267 this_cell_ports
[cell_next_pin
] = 'D';
270 LibertyAst
*ar
= cell
->find("area");
271 if (ar
!= NULL
&& !ar
->value
.empty())
272 area
= atof(ar
->value
.c_str());
275 bool found_output
= false;
276 bool found_noninv_output
= false;
277 for (auto pin
: cell
->children
)
279 if (pin
->id
!= "pin" || pin
->args
.size() != 1)
282 LibertyAst
*dir
= pin
->find("direction");
283 if (dir
== NULL
|| dir
->value
== "internal")
287 if (dir
->value
== "input" && this_cell_ports
.count(pin
->args
[0]) == 0)
288 goto continue_cell_loop
;
290 LibertyAst
*func
= pin
->find("function");
291 if (dir
->value
== "output" && func
!= NULL
) {
292 std::string value
= func
->value
;
293 for (size_t pos
= value
.find_first_of("\" \t"); pos
!= std::string::npos
; pos
= value
.find_first_of("\" \t"))
295 if (value
== ff
->args
[0]) {
296 this_cell_ports
[pin
->args
[0]] = cell_next_pol
? 'Q' : 'q';
298 found_noninv_output
= true;
301 if (value
== ff
->args
[1]) {
302 this_cell_ports
[pin
->args
[0]] = cell_next_pol
? 'q' : 'Q';
304 found_noninv_output
= true;
309 if (this_cell_ports
.count(pin
->args
[0]) == 0)
310 this_cell_ports
[pin
->args
[0]] = 0;
313 if (!found_output
|| (best_cell
!= NULL
&& (num_pins
> best_cell_pins
|| (best_cell_noninv
&& !found_noninv_output
))))
316 if (best_cell
!= NULL
&& num_pins
== best_cell_pins
&& area
> best_cell_area
)
320 best_cell_pins
= num_pins
;
321 best_cell_area
= area
;
322 best_cell_noninv
= found_noninv_output
;
323 best_cell_ports
.swap(this_cell_ports
);
327 if (best_cell
!= NULL
) {
328 log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
329 best_cell
->args
[0].c_str(), best_cell_noninv
? "non" : "", best_cell_pins
, best_cell_area
, cell_type
.c_str());
331 cell_mappings
[cell_type
].cell_name
= cell_type
;
332 cell_mappings
[cell_type
].ports
["C"] = 'C';
333 cell_mappings
[cell_type
].ports
["S"] = 'S';
334 cell_mappings
[cell_type
].ports
["R"] = 'R';
335 cell_mappings
[cell_type
].ports
["D"] = 'D';
336 cell_mappings
[cell_type
].ports
["Q"] = 'Q';
338 cell_mappings
[cell_type
].cell_name
= best_cell
->args
[0];
339 cell_mappings
[cell_type
].ports
= best_cell_ports
;
344 static bool expand_cellmap_worker(std::string from
, std::string to
, std::string inv
)
346 if (cell_mappings
.count(to
) > 0)
349 log(" create mapping for %s from mapping for %s.\n", to
.c_str(), from
.c_str());
350 cell_mappings
[to
].cell_name
= cell_mappings
[from
].cell_name
;
351 cell_mappings
[to
].ports
= cell_mappings
[from
].ports
;
353 for (auto &it
: cell_mappings
[to
].ports
) {
354 char cmp_ch
= it
.second
;
355 if ('a' <= cmp_ch
&& cmp_ch
<= 'z')
357 if (inv
.find(cmp_ch
) == std::string::npos
)
359 if ('a' <= it
.second
&& it
.second
<= 'z')
360 it
.second
-= 'a' - 'A';
361 else if ('A' <= it
.second
&& it
.second
<= 'Z')
362 it
.second
+= 'a' - 'A';
367 static bool expand_cellmap(std::string pattern
, std::string inv
)
369 std::vector
<std::pair
<std::string
, std::string
>> from_to_list
;
370 bool return_status
= false;
372 for (auto &it
: cell_mappings
) {
373 std::string from
= it
.first
.str(), to
= it
.first
.str();
374 if (from
.size() != pattern
.size())
376 for (size_t i
= 0; i
< from
.size(); i
++) {
377 if (pattern
[i
] == '*') {
378 to
[i
] = from
[i
] == 'P' ? 'N' :
379 from
[i
] == 'N' ? 'P' :
380 from
[i
] == '1' ? '0' :
381 from
[i
] == '0' ? '1' : '*';
383 if (pattern
[i
] != '?' && pattern
[i
] != from
[i
])
386 from_to_list
.push_back(std::pair
<std::string
, std::string
>(from
, to
));
390 for (auto &it
: from_to_list
)
391 return_status
= return_status
|| expand_cellmap_worker(it
.first
, it
.second
, inv
);
392 return return_status
;
395 static void map_sr_to_arst(const char *from
, const char *to
)
397 if (!cell_mappings
.count(from
) || cell_mappings
.count(to
) > 0)
400 char from_clk_pol
YS_ATTRIBUTE(unused
) = from
[8];
401 char from_set_pol
= from
[9];
402 char from_clr_pol
= from
[10];
403 char to_clk_pol
YS_ATTRIBUTE(unused
) = to
[6];
404 char to_rst_pol
YS_ATTRIBUTE(unused
) = to
[7];
405 char to_rst_val
= to
[8];
407 log_assert(from_clk_pol
== to_clk_pol
);
408 log_assert(to_rst_pol
== from_set_pol
&& to_rst_pol
== from_clr_pol
);
410 log(" create mapping for %s from mapping for %s.\n", to
, from
);
411 cell_mappings
[to
].cell_name
= cell_mappings
[from
].cell_name
;
412 cell_mappings
[to
].ports
= cell_mappings
[from
].ports
;
414 for (auto &it
: cell_mappings
[to
].ports
)
416 bool is_set_pin
= it
.second
== 'S' || it
.second
== 's';
417 bool is_clr_pin
= it
.second
== 'R' || it
.second
== 'r';
419 if (!is_set_pin
&& !is_clr_pin
)
422 if ((to_rst_val
== '0' && is_set_pin
) || (to_rst_val
== '1' && is_clr_pin
))
424 // this is the unused set/clr pin -- deactivate it
426 it
.second
= (from_set_pol
== 'P') == (it
.second
== 'S') ? '0' : '1';
428 it
.second
= (from_clr_pol
== 'P') == (it
.second
== 'R') ? '0' : '1';
432 // this is the used set/clr pin -- rename it to 'reset'
433 if (it
.second
== 'S')
435 if (it
.second
== 's')
441 static void map_adff_to_dff(const char *from
, const char *to
)
443 if (!cell_mappings
.count(from
) || cell_mappings
.count(to
) > 0)
446 char from_clk_pol
YS_ATTRIBUTE(unused
) = from
[6];
447 char from_rst_pol
= from
[7];
448 char to_clk_pol
YS_ATTRIBUTE(unused
) = to
[6];
450 log_assert(from_clk_pol
== to_clk_pol
);
452 log(" create mapping for %s from mapping for %s.\n", to
, from
);
453 cell_mappings
[to
].cell_name
= cell_mappings
[from
].cell_name
;
454 cell_mappings
[to
].ports
= cell_mappings
[from
].ports
;
456 for (auto &it
: cell_mappings
[to
].ports
) {
457 if (it
.second
== 'S' || it
.second
== 'R')
458 it
.second
= from_rst_pol
== 'P' ? '0' : '1';
459 if (it
.second
== 's' || it
.second
== 'r')
460 it
.second
= from_rst_pol
== 'P' ? '1' : '0';
464 static void dfflibmap(RTLIL::Design
*design
, RTLIL::Module
*module
, bool prepare_mode
)
466 log("Mapping DFF cells in module `%s':\n", module
->name
.c_str());
468 dict
<SigBit
, pool
<Cell
*>> notmap
;
469 SigMap
sigmap(module
);
471 std::vector
<RTLIL::Cell
*> cell_list
;
472 for (auto &it
: module
->cells_
) {
473 if (design
->selected(module
, it
.second
) && cell_mappings
.count(it
.second
->type
) > 0)
474 cell_list
.push_back(it
.second
);
475 if (it
.second
->type
== "$_NOT_")
476 notmap
[sigmap(it
.second
->getPort("\\A"))].insert(it
.second
);
479 std::map
<std::string
, int> stats
;
480 for (auto cell
: cell_list
)
482 auto cell_type
= cell
->type
;
483 auto cell_name
= cell
->name
;
484 auto cell_connections
= cell
->connections();
485 std::string src
= cell
->get_src_attribute();
487 module
->remove(cell
);
489 cell_mapping
&cm
= cell_mappings
[cell_type
];
490 RTLIL::Cell
*new_cell
= module
->addCell(cell_name
, prepare_mode
? cm
.cell_name
: "\\" + cm
.cell_name
);
492 new_cell
->set_src_attribute(src
);
494 bool has_q
= false, has_qn
= false;
495 for (auto &port
: cm
.ports
) {
496 if (port
.second
== 'Q') has_q
= true;
497 if (port
.second
== 'q') has_qn
= true;
500 for (auto &port
: cm
.ports
) {
502 if ('A' <= port
.second
&& port
.second
<= 'Z') {
503 sig
= cell_connections
[std::string("\\") + port
.second
];
505 if (port
.second
== 'q') {
506 RTLIL::SigSpec old_sig
= cell_connections
[std::string("\\") + char(port
.second
- ('a' - 'A'))];
507 sig
= module
->addWire(NEW_ID
, GetSize(old_sig
));
508 if (has_q
&& has_qn
) {
509 for (auto &it
: notmap
[sigmap(old_sig
)]) {
510 module
->connect(it
->getPort("\\Y"), sig
);
511 it
->setPort("\\Y", module
->addWire(NEW_ID
, GetSize(old_sig
)));
514 module
->addNotGate(NEW_ID
, sig
, old_sig
);
517 if ('a' <= port
.second
&& port
.second
<= 'z') {
518 sig
= cell_connections
[std::string("\\") + char(port
.second
- ('a' - 'A'))];
519 sig
= module
->NotGate(NEW_ID
, sig
);
521 if (port
.second
== '0' || port
.second
== '1') {
522 sig
= RTLIL::SigSpec(port
.second
== '0' ? 0 : 1, 1);
524 if (port
.second
== 0) {
525 sig
= module
->addWire(NEW_ID
);
528 new_cell
->setPort("\\" + port
.first
, sig
);
531 stats
[stringf(" mapped %%d %s cells to %s cells.\n", cell_type
.c_str(), new_cell
->type
.c_str())]++;
534 for (auto &stat
: stats
)
535 log(stat
.first
.c_str(), stat
.second
);
538 struct DfflibmapPass
: public Pass
{
539 DfflibmapPass() : Pass("dfflibmap", "technology mapping of flip-flops") { }
540 void help() YS_OVERRIDE
543 log(" dfflibmap [-prepare] -liberty <file> [selection]\n");
545 log("Map internal flip-flop cells to the flip-flop cells in the technology\n");
546 log("library specified in the given liberty file.\n");
548 log("This pass may add inverters as needed. Therefore it is recommended to\n");
549 log("first run this pass and then map the logic paths to the target technology.\n");
551 log("When called with -prepare, this command will convert the internal FF cells\n");
552 log("to the internal cell types that best match the cells found in the given\n");
553 log("liberty file.\n");
556 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
558 log_header(design
, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
560 std::string liberty_file
;
561 bool prepare_mode
= false;
564 for (argidx
= 1; argidx
< args
.size(); argidx
++)
566 std::string arg
= args
[argidx
];
567 if (arg
== "-liberty" && argidx
+1 < args
.size()) {
568 liberty_file
= args
[++argidx
];
569 rewrite_filename(liberty_file
);
572 if (arg
== "-prepare") {
578 extra_args(args
, argidx
, design
);
580 if (liberty_file
.empty())
581 log_cmd_error("Missing `-liberty liberty_file' option!\n");
584 f
.open(liberty_file
.c_str());
586 log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file
.c_str(), strerror(errno
));
587 LibertyParser
libparser(f
);
590 find_cell(libparser
.ast
, "$_DFF_N_", false, false, false, false, prepare_mode
);
591 find_cell(libparser
.ast
, "$_DFF_P_", true, false, false, false, prepare_mode
);
593 find_cell(libparser
.ast
, "$_DFF_NN0_", false, true, false, false, prepare_mode
);
594 find_cell(libparser
.ast
, "$_DFF_NN1_", false, true, false, true, prepare_mode
);
595 find_cell(libparser
.ast
, "$_DFF_NP0_", false, true, true, false, prepare_mode
);
596 find_cell(libparser
.ast
, "$_DFF_NP1_", false, true, true, true, prepare_mode
);
597 find_cell(libparser
.ast
, "$_DFF_PN0_", true, true, false, false, prepare_mode
);
598 find_cell(libparser
.ast
, "$_DFF_PN1_", true, true, false, true, prepare_mode
);
599 find_cell(libparser
.ast
, "$_DFF_PP0_", true, true, true, false, prepare_mode
);
600 find_cell(libparser
.ast
, "$_DFF_PP1_", true, true, true, true, prepare_mode
);
602 find_cell_sr(libparser
.ast
, "$_DFFSR_NNN_", false, false, false, prepare_mode
);
603 find_cell_sr(libparser
.ast
, "$_DFFSR_NNP_", false, false, true, prepare_mode
);
604 find_cell_sr(libparser
.ast
, "$_DFFSR_NPN_", false, true, false, prepare_mode
);
605 find_cell_sr(libparser
.ast
, "$_DFFSR_NPP_", false, true, true, prepare_mode
);
606 find_cell_sr(libparser
.ast
, "$_DFFSR_PNN_", true, false, false, prepare_mode
);
607 find_cell_sr(libparser
.ast
, "$_DFFSR_PNP_", true, false, true, prepare_mode
);
608 find_cell_sr(libparser
.ast
, "$_DFFSR_PPN_", true, true, false, prepare_mode
);
609 find_cell_sr(libparser
.ast
, "$_DFFSR_PPP_", true, true, true, prepare_mode
);
611 // try to implement as many cells as possible just by inverting
612 // the SET and RESET pins. If necessary, implement cell types
613 // by inverting both D and Q. Only invert clock pins if there
614 // is no other way of implementing the cell.
617 if (expand_cellmap("$_DFF_?*?_", "R") ||
618 expand_cellmap("$_DFFSR_?*?_", "S") ||
619 expand_cellmap("$_DFFSR_??*_", "R"))
622 if (expand_cellmap("$_DFF_??*_", "DQ"))
625 if (expand_cellmap("$_DFF_*_", "C") ||
626 expand_cellmap("$_DFF_*??_", "C") ||
627 expand_cellmap("$_DFFSR_*??_", "C"))
633 map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN0_");
634 map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN1_");
635 map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP0_");
636 map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP1_");
637 map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN0_");
638 map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN1_");
639 map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP0_");
640 map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP1_");
642 map_adff_to_dff("$_DFF_NN0_", "$_DFF_N_");
643 map_adff_to_dff("$_DFF_NN1_", "$_DFF_N_");
644 map_adff_to_dff("$_DFF_NP0_", "$_DFF_N_");
645 map_adff_to_dff("$_DFF_NP1_", "$_DFF_N_");
646 map_adff_to_dff("$_DFF_PN0_", "$_DFF_P_");
647 map_adff_to_dff("$_DFF_PN1_", "$_DFF_P_");
648 map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
649 map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
651 log(" final dff cell mappings:\n");
654 for (auto &it
: design
->modules_
)
655 if (design
->selected(it
.second
) && !it
.second
->get_bool_attribute("\\blackbox"))
656 dfflibmap(design
, it
.second
, prepare_mode
);
658 cell_mappings
.clear();
662 PRIVATE_NAMESPACE_END