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 "passes/techmap/libparse.h"
21 #include "kernel/register.h"
22 #include "kernel/log.h"
29 token_t (char t
) : type(t
) { }
30 token_t (char t
, RTLIL::SigSpec s
) : type(t
), sig(s
) { }
33 static RTLIL::SigSpec
parse_func_identifier(RTLIL::Module
*module
, const char *&expr
)
35 log_assert(*expr
!= 0);
38 while (('a' <= expr
[id_len
] && expr
[id_len
] <= 'z') || ('A' <= expr
[id_len
] && expr
[id_len
] <= 'Z') ||
39 ('0' <= expr
[id_len
] && expr
[id_len
] <= '9') || expr
[id_len
] == '.' ||
40 expr
[id_len
] == '_' || expr
[id_len
] == '[' || expr
[id_len
] == ']') id_len
++;
43 log_error("Expected identifier at `%s'.\n", expr
);
45 if (id_len
== 1 && (*expr
== '0' || *expr
== '1'))
46 return *(expr
++) == '0' ? RTLIL::State::S0
: RTLIL::State::S1
;
48 std::string id
= RTLIL::escape_id(std::string(expr
, id_len
));
49 if (!module
->wires_
.count(id
))
50 log_error("Can't resolve wire name %s.\n", RTLIL::unescape_id(id
).c_str());
53 return module
->wires_
.at(id
);
56 static RTLIL::SigSpec
create_inv_cell(RTLIL::Module
*module
, RTLIL::SigSpec A
)
58 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_NOT_");
59 cell
->setPort("\\A", A
);
60 cell
->setPort("\\Y", module
->addWire(NEW_ID
));
61 return cell
->getPort("\\Y");
64 static RTLIL::SigSpec
create_xor_cell(RTLIL::Module
*module
, RTLIL::SigSpec A
, RTLIL::SigSpec B
)
66 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_XOR_");
67 cell
->setPort("\\A", A
);
68 cell
->setPort("\\B", B
);
69 cell
->setPort("\\Y", module
->addWire(NEW_ID
));
70 return cell
->getPort("\\Y");
73 static RTLIL::SigSpec
create_and_cell(RTLIL::Module
*module
, RTLIL::SigSpec A
, RTLIL::SigSpec B
)
75 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_AND_");
76 cell
->setPort("\\A", A
);
77 cell
->setPort("\\B", B
);
78 cell
->setPort("\\Y", module
->addWire(NEW_ID
));
79 return cell
->getPort("\\Y");
82 static RTLIL::SigSpec
create_or_cell(RTLIL::Module
*module
, RTLIL::SigSpec A
, RTLIL::SigSpec B
)
84 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_OR_");
85 cell
->setPort("\\A", A
);
86 cell
->setPort("\\B", B
);
87 cell
->setPort("\\Y", module
->addWire(NEW_ID
));
88 return cell
->getPort("\\Y");
91 static bool parse_func_reduce(RTLIL::Module
*module
, std::vector
<token_t
> &stack
, token_t next_token
)
93 int top
= int(stack
.size())-1;
95 if (0 <= top
-1 && stack
[top
].type
== 0 && stack
[top
-1].type
== '!') {
96 token_t t
= token_t(0, create_inv_cell(module
, stack
[top
].sig
));
103 if (0 <= top
-1 && stack
[top
].type
== '\'' && stack
[top
-1].type
== 0) {
104 token_t t
= token_t(0, create_inv_cell(module
, stack
[top
-1].sig
));
111 if (0 <= top
&& stack
[top
].type
== 0) {
112 if (next_token
.type
== '\'')
118 if (0 <= top
-2 && stack
[top
-2].type
== 1 && stack
[top
-1].type
== '^' && stack
[top
].type
== 1) {
119 token_t t
= token_t(1, create_xor_cell(module
, stack
[top
-2].sig
, stack
[top
].sig
));
127 if (0 <= top
&& stack
[top
].type
== 1) {
128 if (next_token
.type
== '^')
134 if (0 <= top
-1 && stack
[top
-1].type
== 2 && stack
[top
].type
== 2) {
135 token_t t
= token_t(2, create_and_cell(module
, stack
[top
-1].sig
, stack
[top
].sig
));
142 if (0 <= top
-2 && stack
[top
-2].type
== 2 && (stack
[top
-1].type
== '*' || stack
[top
-1].type
== '&') && stack
[top
].type
== 2) {
143 token_t t
= token_t(2, create_and_cell(module
, stack
[top
-2].sig
, stack
[top
].sig
));
151 if (0 <= top
&& stack
[top
].type
== 2) {
152 if (next_token
.type
== '*' || next_token
.type
== '&' || next_token
.type
== 0 || next_token
.type
== '(' || next_token
.type
== '!')
158 if (0 <= top
-2 && stack
[top
-2].type
== 3 && (stack
[top
-1].type
== '+' || stack
[top
-1].type
== '|') && stack
[top
].type
== 3) {
159 token_t t
= token_t(3, create_or_cell(module
, stack
[top
-2].sig
, stack
[top
].sig
));
167 if (0 <= top
-2 && stack
[top
-2].type
== '(' && stack
[top
-1].type
== 3 && stack
[top
].type
== ')') {
168 token_t t
= token_t(0, stack
[top
-1].sig
);
179 static RTLIL::SigSpec
parse_func_expr(RTLIL::Module
*module
, const char *expr
)
181 const char *orig_expr
= expr
;
182 std::vector
<token_t
> stack
;
186 if (*expr
== ' ' || *expr
== '\t' || *expr
== '\r' || *expr
== '\n' || *expr
== '"') {
191 token_t
next_token(0);
192 if (*expr
== '(' || *expr
== ')' || *expr
== '\'' || *expr
== '!' || *expr
== '^' || *expr
== '*' || *expr
== '+' || *expr
== '|' || *expr
== '&')
193 next_token
= token_t(*(expr
++));
195 next_token
= token_t(0, parse_func_identifier(module
, expr
));
197 while (parse_func_reduce(module
, stack
, next_token
)) {}
198 stack
.push_back(next_token
);
201 while (parse_func_reduce(module
, stack
, token_t('.'))) {}
204 for (size_t i
= 0; i
< stack
.size(); i
++)
205 if (stack
[i
].type
< 16)
206 log("%3d: %d %s\n", int(i
), stack
[i
].type
, log_signal(stack
[i
].sig
));
208 log("%3d: %c\n", int(i
), stack
[i
].type
);
211 if (stack
.size() != 1 || stack
.back().type
!= 3)
212 log_error("Parser error in function expr `%s'.\n", orig_expr
);
214 return stack
.back().sig
;
217 static void create_ff(RTLIL::Module
*module
, LibertyAst
*node
)
219 RTLIL::SigSpec
iq_sig(module
->addWire(RTLIL::escape_id(node
->args
.at(0))));
220 RTLIL::SigSpec
iqn_sig(module
->addWire(RTLIL::escape_id(node
->args
.at(1))));
222 RTLIL::SigSpec clk_sig
, data_sig
, clear_sig
, preset_sig
;
223 bool clk_polarity
= true, clear_polarity
= true, preset_polarity
= true;
225 for (auto child
: node
->children
) {
226 if (child
->id
== "clocked_on")
227 clk_sig
= parse_func_expr(module
, child
->value
.c_str());
228 if (child
->id
== "next_state")
229 data_sig
= parse_func_expr(module
, child
->value
.c_str());
230 if (child
->id
== "clear")
231 clear_sig
= parse_func_expr(module
, child
->value
.c_str());
232 if (child
->id
== "preset")
233 preset_sig
= parse_func_expr(module
, child
->value
.c_str());
236 if (clk_sig
.size() == 0 || data_sig
.size() == 0)
237 log_error("FF cell %s has no next_state and/or clocked_on attribute.\n", log_id(module
->name
));
239 for (bool rerun_invert_rollback
= true; rerun_invert_rollback
;)
241 rerun_invert_rollback
= false;
243 for (auto &it
: module
->cells_
) {
244 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == clk_sig
) {
245 clk_sig
= it
.second
->getPort("\\A");
246 clk_polarity
= !clk_polarity
;
247 rerun_invert_rollback
= true;
249 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == clear_sig
) {
250 clear_sig
= it
.second
->getPort("\\A");
251 clear_polarity
= !clear_polarity
;
252 rerun_invert_rollback
= true;
254 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == preset_sig
) {
255 preset_sig
= it
.second
->getPort("\\A");
256 preset_polarity
= !preset_polarity
;
257 rerun_invert_rollback
= true;
262 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_NOT_");
263 cell
->setPort("\\A", iq_sig
);
264 cell
->setPort("\\Y", iqn_sig
);
266 cell
= module
->addCell(NEW_ID
, "");
267 cell
->setPort("\\D", data_sig
);
268 cell
->setPort("\\Q", iq_sig
);
269 cell
->setPort("\\C", clk_sig
);
271 if (clear_sig
.size() == 0 && preset_sig
.size() == 0) {
272 cell
->type
= stringf("$_DFF_%c_", clk_polarity
? 'P' : 'N');
275 if (clear_sig
.size() == 1 && preset_sig
.size() == 0) {
276 cell
->type
= stringf("$_DFF_%c%c0_", clk_polarity
? 'P' : 'N', clear_polarity
? 'P' : 'N');
277 cell
->setPort("\\R", clear_sig
);
280 if (clear_sig
.size() == 0 && preset_sig
.size() == 1) {
281 cell
->type
= stringf("$_DFF_%c%c1_", clk_polarity
? 'P' : 'N', preset_polarity
? 'P' : 'N');
282 cell
->setPort("\\R", preset_sig
);
285 if (clear_sig
.size() == 1 && preset_sig
.size() == 1) {
286 cell
->type
= stringf("$_DFFSR_%c%c%c_", clk_polarity
? 'P' : 'N', preset_polarity
? 'P' : 'N', clear_polarity
? 'P' : 'N');
287 cell
->setPort("\\S", preset_sig
);
288 cell
->setPort("\\R", clear_sig
);
291 log_assert(!cell
->type
.empty());
294 static bool create_latch(RTLIL::Module
*module
, LibertyAst
*node
, bool flag_ignore_miss_data_latch
)
296 RTLIL::SigSpec
iq_sig(module
->addWire(RTLIL::escape_id(node
->args
.at(0))));
297 RTLIL::SigSpec
iqn_sig(module
->addWire(RTLIL::escape_id(node
->args
.at(1))));
299 RTLIL::SigSpec enable_sig
, data_sig
, clear_sig
, preset_sig
;
300 bool enable_polarity
= true, clear_polarity
= true, preset_polarity
= true;
302 for (auto child
: node
->children
) {
303 if (child
->id
== "enable")
304 enable_sig
= parse_func_expr(module
, child
->value
.c_str());
305 if (child
->id
== "data_in")
306 data_sig
= parse_func_expr(module
, child
->value
.c_str());
307 if (child
->id
== "clear")
308 clear_sig
= parse_func_expr(module
, child
->value
.c_str());
309 if (child
->id
== "preset")
310 preset_sig
= parse_func_expr(module
, child
->value
.c_str());
313 if (enable_sig
.size() == 0 || data_sig
.size() == 0) {
314 if (!flag_ignore_miss_data_latch
)
315 log_error("Latch cell %s has no data_in and/or enable attribute.\n", log_id(module
->name
));
317 log("Ignored latch cell %s with no data_in and/or enable attribute.\n", log_id(module
->name
));
322 for (bool rerun_invert_rollback
= true; rerun_invert_rollback
;)
324 rerun_invert_rollback
= false;
326 for (auto &it
: module
->cells_
) {
327 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == enable_sig
) {
328 enable_sig
= it
.second
->getPort("\\A");
329 enable_polarity
= !enable_polarity
;
330 rerun_invert_rollback
= true;
332 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == clear_sig
) {
333 clear_sig
= it
.second
->getPort("\\A");
334 clear_polarity
= !clear_polarity
;
335 rerun_invert_rollback
= true;
337 if (it
.second
->type
== "$_NOT_" && it
.second
->getPort("\\Y") == preset_sig
) {
338 preset_sig
= it
.second
->getPort("\\A");
339 preset_polarity
= !preset_polarity
;
340 rerun_invert_rollback
= true;
345 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, "$_NOT_");
346 cell
->setPort("\\A", iq_sig
);
347 cell
->setPort("\\Y", iqn_sig
);
349 if (clear_sig
.size() == 1)
351 RTLIL::SigSpec clear_negative
= clear_sig
;
352 RTLIL::SigSpec clear_enable
= clear_sig
;
354 if (clear_polarity
== true || clear_polarity
!= enable_polarity
)
356 RTLIL::Cell
*inv
= module
->addCell(NEW_ID
, "$_NOT_");
357 inv
->setPort("\\A", clear_sig
);
358 inv
->setPort("\\Y", module
->addWire(NEW_ID
));
360 if (clear_polarity
== true)
361 clear_negative
= inv
->getPort("\\Y");
362 if (clear_polarity
!= enable_polarity
)
363 clear_enable
= inv
->getPort("\\Y");
366 RTLIL::Cell
*data_gate
= module
->addCell(NEW_ID
, "$_AND_");
367 data_gate
->setPort("\\A", data_sig
);
368 data_gate
->setPort("\\B", clear_negative
);
369 data_gate
->setPort("\\Y", data_sig
= module
->addWire(NEW_ID
));
371 RTLIL::Cell
*enable_gate
= module
->addCell(NEW_ID
, enable_polarity
? "$_OR_" : "$_AND_");
372 enable_gate
->setPort("\\A", enable_sig
);
373 enable_gate
->setPort("\\B", clear_enable
);
374 enable_gate
->setPort("\\Y", data_sig
= module
->addWire(NEW_ID
));
377 if (preset_sig
.size() == 1)
379 RTLIL::SigSpec preset_positive
= preset_sig
;
380 RTLIL::SigSpec preset_enable
= preset_sig
;
382 if (preset_polarity
== false || preset_polarity
!= enable_polarity
)
384 RTLIL::Cell
*inv
= module
->addCell(NEW_ID
, "$_NOT_");
385 inv
->setPort("\\A", preset_sig
);
386 inv
->setPort("\\Y", module
->addWire(NEW_ID
));
388 if (preset_polarity
== false)
389 preset_positive
= inv
->getPort("\\Y");
390 if (preset_polarity
!= enable_polarity
)
391 preset_enable
= inv
->getPort("\\Y");
394 RTLIL::Cell
*data_gate
= module
->addCell(NEW_ID
, "$_OR_");
395 data_gate
->setPort("\\A", data_sig
);
396 data_gate
->setPort("\\B", preset_positive
);
397 data_gate
->setPort("\\Y", data_sig
= module
->addWire(NEW_ID
));
399 RTLIL::Cell
*enable_gate
= module
->addCell(NEW_ID
, enable_polarity
? "$_OR_" : "$_AND_");
400 enable_gate
->setPort("\\A", enable_sig
);
401 enable_gate
->setPort("\\B", preset_enable
);
402 enable_gate
->setPort("\\Y", data_sig
= module
->addWire(NEW_ID
));
405 cell
= module
->addCell(NEW_ID
, stringf("$_DLATCH_%c_", enable_polarity
? 'P' : 'N'));
406 cell
->setPort("\\D", data_sig
);
407 cell
->setPort("\\Q", iq_sig
);
408 cell
->setPort("\\E", enable_sig
);
413 void parse_type_map(std::map
<std::string
, std::tuple
<int, int, bool>> &type_map
, LibertyAst
*ast
)
415 for (auto type_node
: ast
->children
)
417 if (type_node
->id
!= "type" || type_node
->args
.size() != 1)
420 std::string type_name
= type_node
->args
.at(0);
421 int bit_width
= -1, bit_from
= -1, bit_to
= -1;
424 for (auto child
: type_node
->children
)
426 if (child
->id
== "base_type" && child
->value
!= "array")
429 if (child
->id
== "data_type" && child
->value
!= "bit")
432 if (child
->id
== "bit_width")
433 bit_width
= atoi(child
->value
.c_str());
435 if (child
->id
== "bit_from")
436 bit_from
= atoi(child
->value
.c_str());
438 if (child
->id
== "bit_to")
439 bit_to
= atoi(child
->value
.c_str());
441 if (child
->id
== "downto" && (child
->value
== "0" || child
->value
== "false" || child
->value
== "FALSE"))
445 if (bit_width
!= (std::max(bit_from
, bit_to
) - std::min(bit_from
, bit_to
) + 1))
446 log_error("Incompatible array type '%s': bit_width=%d, bit_from=%d, bit_to=%d.\n",
447 type_name
.c_str(), bit_width
, bit_from
, bit_to
);
449 type_map
[type_name
] = std::tuple
<int, int, bool>(bit_width
, std::min(bit_from
, bit_to
), upto
);
454 struct LibertyFrontend
: public Frontend
{
455 LibertyFrontend() : Frontend("liberty", "read cells from liberty file") { }
456 void help() YS_OVERRIDE
458 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
460 log(" read_liberty [filename]\n");
462 log("Read cells from liberty file as modules into current design.\n");
465 log(" only create empty blackbox modules\n");
467 log(" -nooverwrite\n");
468 log(" ignore re-definitions of modules. (the default behavior is to\n");
469 log(" create an error message if the existing module is not a blackbox\n");
470 log(" module, and overwrite the existing module if it is a blackbox module.)\n");
472 log(" -overwrite\n");
473 log(" overwrite existing modules with the same name\n");
475 log(" -ignore_miss_func\n");
476 log(" ignore cells with missing function specification of outputs\n");
478 log(" -ignore_miss_dir\n");
479 log(" ignore cells with a missing or invalid direction\n");
480 log(" specification on a pin\n");
482 log(" -ignore_miss_data_latch\n");
483 log(" ignore latches with missing data and/or enable pins\n");
485 log(" -setattr <attribute_name>\n");
486 log(" set the specified attribute (to the value 1) on all loaded modules\n");
489 void execute(std::istream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
491 bool flag_lib
= false;
492 bool flag_nooverwrite
= false;
493 bool flag_overwrite
= false;
494 bool flag_ignore_miss_func
= false;
495 bool flag_ignore_miss_dir
= false;
496 bool flag_ignore_miss_data_latch
= false;
497 std::vector
<std::string
> attributes
;
499 log_header(design
, "Executing Liberty frontend.\n");
502 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
503 std::string arg
= args
[argidx
];
508 if (arg
== "-ignore_redef" || arg
== "-nooverwrite") {
509 flag_nooverwrite
= true;
510 flag_overwrite
= false;
513 if (arg
== "-overwrite") {
514 flag_nooverwrite
= false;
515 flag_overwrite
= true;
518 if (arg
== "-ignore_miss_func") {
519 flag_ignore_miss_func
= true;
522 if (arg
== "-ignore_miss_dir") {
523 flag_ignore_miss_dir
= true;
526 if (arg
== "-ignore_miss_data_latch") {
527 flag_ignore_miss_data_latch
= true;
530 if (arg
== "-setattr" && argidx
+1 < args
.size()) {
531 attributes
.push_back(RTLIL::escape_id(args
[++argidx
]));
536 extra_args(f
, filename
, args
, argidx
);
538 LibertyParser
parser(*f
);
541 std::map
<std::string
, std::tuple
<int, int, bool>> global_type_map
;
542 parse_type_map(global_type_map
, parser
.ast
);
544 for (auto cell
: parser
.ast
->children
)
546 if (cell
->id
!= "cell" || cell
->args
.size() != 1)
549 std::string cell_name
= RTLIL::escape_id(cell
->args
.at(0));
551 if (design
->has(cell_name
)) {
552 Module
*existing_mod
= design
->module(cell_name
);
553 if (!flag_nooverwrite
&& !flag_overwrite
&& !existing_mod
->get_bool_attribute("\\blackbox")) {
554 log_error("Re-definition of of cell/module %s!\n", log_id(cell_name
));
555 } else if (flag_nooverwrite
) {
556 log("Ignoring re-definition of module %s.\n", log_id(cell_name
));
559 log("Replacing existing%s module %s.\n", existing_mod
->get_bool_attribute("\\blackbox") ? " blackbox" : "", log_id(cell_name
));
560 design
->remove(existing_mod
);
564 // log("Processing cell type %s.\n", RTLIL::unescape_id(cell_name).c_str());
566 std::map
<std::string
, std::tuple
<int, int, bool>> type_map
= global_type_map
;
567 parse_type_map(type_map
, cell
);
569 RTLIL::Module
*module
= new RTLIL::Module
;
570 module
->name
= cell_name
;
573 module
->set_bool_attribute("\\blackbox");
575 for (auto &attr
: attributes
)
576 module
->attributes
[attr
] = 1;
578 for (auto node
: cell
->children
)
580 if (node
->id
== "pin" && node
->args
.size() == 1) {
581 LibertyAst
*dir
= node
->find("direction");
582 if (!dir
|| (dir
->value
!= "input" && dir
->value
!= "output" && dir
->value
!= "inout" && dir
->value
!= "internal"))
584 if (!flag_ignore_miss_dir
)
586 log_error("Missing or invalid direction for pin %s on cell %s.\n", node
->args
.at(0).c_str(), log_id(module
->name
));
588 log("Ignoring cell %s with missing or invalid direction for pin %s.\n", log_id(module
->name
), node
->args
.at(0).c_str());
593 if (!flag_lib
|| dir
->value
!= "internal")
594 module
->addWire(RTLIL::escape_id(node
->args
.at(0)));
597 if (node
->id
== "bus" && node
->args
.size() == 1)
600 log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name
));
602 LibertyAst
*dir
= node
->find("direction");
604 if (dir
== nullptr) {
605 LibertyAst
*pin
= node
->find("pin");
607 dir
= pin
->find("direction");
610 if (!dir
|| (dir
->value
!= "input" && dir
->value
!= "output" && dir
->value
!= "inout" && dir
->value
!= "internal"))
611 log_error("Missing or invalid direction for bus %s on cell %s.\n", node
->args
.at(0).c_str(), log_id(module
->name
));
613 if (dir
->value
== "internal")
616 LibertyAst
*bus_type_node
= node
->find("bus_type");
618 if (!bus_type_node
|| !type_map
.count(bus_type_node
->value
))
619 log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
620 node
->args
.at(0).c_str(), log_id(cell_name
));
622 int bus_type_width
= std::get
<0>(type_map
.at(bus_type_node
->value
));
623 int bus_type_offset
= std::get
<1>(type_map
.at(bus_type_node
->value
));
624 bool bus_type_upto
= std::get
<2>(type_map
.at(bus_type_node
->value
));
626 Wire
*wire
= module
->addWire(RTLIL::escape_id(node
->args
.at(0)), bus_type_width
);
627 wire
->start_offset
= bus_type_offset
;
628 wire
->upto
= bus_type_upto
;
630 if (dir
->value
== "input" || dir
->value
== "inout")
631 wire
->port_input
= true;
633 if (dir
->value
== "output" || dir
->value
== "inout")
634 wire
->port_output
= true;
640 // some liberty files do not put ff/latch at the beginning of a cell
641 // try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes
642 for (auto node
: cell
->children
)
644 if (node
->id
== "ff" && node
->args
.size() == 2)
645 create_ff(module
, node
);
646 if (node
->id
== "latch" && node
->args
.size() == 2)
647 if (!create_latch(module
, node
, flag_ignore_miss_data_latch
)) {
654 for (auto node
: cell
->children
)
656 if (node
->id
== "pin" && node
->args
.size() == 1)
658 LibertyAst
*dir
= node
->find("direction");
660 if (flag_lib
&& dir
->value
== "internal")
663 RTLIL::Wire
*wire
= module
->wires_
.at(RTLIL::escape_id(node
->args
.at(0)));
665 if (dir
&& dir
->value
== "inout") {
666 wire
->port_input
= true;
667 wire
->port_output
= true;
670 if (dir
&& dir
->value
== "input") {
671 wire
->port_input
= true;
675 if (dir
&& dir
->value
== "output")
676 wire
->port_output
= true;
681 LibertyAst
*func
= node
->find("function");
684 if (!flag_ignore_miss_func
)
686 log_error("Missing function on output %s of cell %s.\n", log_id(wire
->name
), log_id(module
->name
));
688 log("Ignoring cell %s with missing function on output %s.\n", log_id(module
->name
), log_id(wire
->name
));
694 RTLIL::SigSpec out_sig
= parse_func_expr(module
, func
->value
.c_str());
695 module
->connect(RTLIL::SigSig(wire
, out_sig
));
699 module
->fixup_ports();
705 log("Imported %d cell types from liberty file.\n", cell_count
);