20 ifs.open(m_path.string(), std::ifstream::in);
23 return ERR(
"could not parse Liberty file '" + m_path.string() +
"' : unable to open file");
35 if (
auto res = parse_tokens(); res.is_error())
37 return ERR_APPEND(res.get_error(),
"could not parse Liberty file '" + file_path.string() +
"': unable to parse tokens");
42 if (e.line_number != (
u32)-1)
44 return ERR(
"could not parse Liberty file '" + m_path.string() +
"': " + e.message +
" (line " + std::to_string(e.line_number) +
")");
48 return ERR(
"could not parse Liberty file '" + m_path.string() +
"': " + e.message);
52 return OK(std::move(m_gate_lib));
55 void LibertyParser::tokenize()
57 std::string delimiters =
"{}()[];:\",";
58 std::string current_token;
62 bool in_string =
false;
63 bool was_in_string =
false;
64 bool multi_line_comment =
false;
66 std::vector<Token<std::string>> parsed_tokens;
68 while (std::getline(m_fs, line))
71 this->remove_comments(line, multi_line_comment);
78 in_string = !in_string;
82 if (std::isspace(c) && !in_string)
87 if (delimiters.find(c) == std::string::npos || in_string)
93 if (was_in_string || !current_token.empty())
95 parsed_tokens.emplace_back(line_number, current_token);
96 current_token.clear();
97 was_in_string =
false;
100 if (!std::isspace(c))
102 parsed_tokens.emplace_back(line_number, std::string(1, c));
106 if (!current_token.empty())
108 parsed_tokens.emplace_back(line_number, current_token);
109 current_token.clear();
113 m_token_stream = TokenStream<std::string>(parsed_tokens, {
"(",
"{"}, {
")",
"}"});
116 Result<std::monostate> LibertyParser::parse_tokens()
118 m_token_stream.
consume(
"library",
true);
119 m_token_stream.
consume(
"(",
true);
120 auto lib_name = m_token_stream.
consume();
121 m_token_stream.
consume(
")",
true);
122 m_token_stream.
consume(
"{",
true);
123 m_gate_lib = std::make_unique<GateLibrary>(m_path, lib_name.string);
125 m_token_stream.
consume(
"}",
false);
129 auto next_token = library_str.consume();
130 if (next_token ==
"{")
132 library_str.consume_until(
"}");
133 library_str.consume(
"}");
135 else if (next_token ==
"cell" && library_str.peek() ==
"(")
137 if (
auto cell = parse_cell(library_str); cell.is_error())
139 return ERR_APPEND(cell.get_error(),
"could not parse tokens: unable to parse cell (line " + std::to_string(next_token.number) +
")");
143 if (
auto res = construct_gate_type(cell.get()); res.is_error())
145 return ERR_APPEND(res.get_error(),
"could not parse tokens: unable to construct gate type (line " + std::to_string(next_token.number) +
")");
149 else if (next_token ==
"type" && library_str.peek() ==
"(")
151 if (
auto res = parse_type(library_str); res.is_error())
153 return ERR_APPEND(res.get_error(),
"could not parse tokens: unable to parse type (line " + std::to_string(next_token.number) +
")");
157 auto type = res.get();
158 m_bus_types[
type.name] = std::move(
type);
161 }
while (library_str.remaining() > 0);
163 if (
const u32 unparsed = m_token_stream.
remaining(); unparsed == 0)
169 return ERR(
"could not parse tokens: " + std::to_string(unparsed) +
" unparsed tokens remaining");
173 Result<LibertyParser::type_group> LibertyParser::parse_type(TokenStream<std::string>&
str)
176 type.line_number =
str.peek().number;
177 str.consume(
"(",
true);
178 type.name =
str.consume().string;
179 str.consume(
")",
true);
180 str.consume(
"{",
true);
182 str.consume(
"}",
true);
184 type.start_index = 0;
186 type.ascending =
true;
187 while (type_str.remaining() > 0)
189 auto next_token = type_str.consume();
190 if (next_token ==
"{")
192 type_str.consume_until(
"}");
193 type_str.consume(
"}");
195 else if (next_token ==
"base_type")
197 type_str.consume(
":",
true);
198 type_str.consume(
"array",
true);
200 else if (next_token ==
"data_type")
202 type_str.consume(
":",
true);
203 type_str.consume(
"bit",
true);
205 else if (next_token ==
"bit_width")
207 type_str.consume(
":",
true);
208 type.width = std::stol(type_str.consume().string);
210 else if (next_token ==
"bit_from")
212 type_str.consume(
":",
true);
213 type.start_index = std::stol(type_str.consume().string);
215 else if (next_token ==
"bit_to")
217 type_str.consume(
":",
true);
219 else if (next_token ==
"downto")
221 type_str.consume(
":",
true);
222 auto bval = type_str.consume();
225 type.ascending =
true;
227 else if (bval ==
"true")
229 type.ascending =
false;
233 return ERR(
"could not parse type '" +
type.name +
"': invalid Boolean value '" + bval.string +
"' (line " + std::to_string(bval.number) +
")");
238 return ERR(
"could not parse type '" +
type.name +
"': invalid token '" + next_token.string +
"' (line " + std::to_string(next_token.number) +
")");
240 type_str.consume(
";",
true);
245 Result<LibertyParser::cell_group> LibertyParser::parse_cell(TokenStream<std::string>&
str)
249 cell.line_number =
str.peek().number;
250 str.consume(
"(",
true);
251 cell.name =
str.consume().string;
252 str.consume(
")",
true);
253 str.consume(
"{",
true);
255 str.consume(
"}",
true);
257 if (
const auto cell_it = m_cell_names.find(cell.name); cell_it != m_cell_names.end())
259 return ERR(
"could not parse cell '" + cell.name +
"': a cell with that name already exists");
262 m_cell_names.insert(cell.name);
264 while (cell_str.remaining() > 0)
266 auto next_token = cell_str.consume();
267 if (next_token ==
"{")
269 cell_str.consume_until(
"}");
270 cell_str.consume(
"}");
272 else if (next_token ==
"pin")
274 if (
auto pin = parse_pin(cell_str, cell); pin.is_error())
276 return ERR_APPEND(pin.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'pin' group (line " + std::to_string(next_token.number) +
")");
280 cell.pins.push_back(pin.get());
283 else if (next_token ==
"pg_pin")
285 if (
auto pin = parse_pg_pin(cell_str, cell); pin.is_ok())
287 cell.pins.push_back(pin.get());
290 else if (next_token ==
"bus")
292 if (
auto res = parse_bus(cell_str, cell); res.is_error())
294 return ERR_APPEND(res.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'bus' group (line " + std::to_string(next_token.number) +
")");
298 auto bus = res.get();
299 cell.buses[bus.name] = std::move(bus);
302 else if (next_token ==
"ff")
304 if (
auto ff = parse_ff(cell_str);
ff.is_error())
306 return ERR_APPEND(
ff.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'ff' group (line " + std::to_string(next_token.number) +
")");
315 else if (next_token ==
"latch")
317 if (
auto latch = parse_latch(cell_str);
latch.is_error())
319 return ERR_APPEND(
latch.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'latch' group (line " + std::to_string(next_token.number) +
")");
325 cell.latch =
latch.get();
333 Result<LibertyParser::pin_group> LibertyParser::parse_pin(TokenStream<std::string>&
str, cell_group& cell,
PinDirection direction,
const std::string& external_pin_name)
337 pin.line_number =
str.peek().number;
338 str.consume(
"(",
true);
340 str.consume(
")",
true);
341 str.consume(
"{",
true);
343 str.consume(
"}",
true);
345 if (pin_names_str.size() == 0)
347 return ERR(
"could not parse pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
352 std::string
name = pin_names_str.consume().string;
353 if (!external_pin_name.empty() &&
name != external_pin_name)
355 return ERR(
"could not parse pin '" +
name +
"': pin name does not match external pin name '" + external_pin_name +
"' (line " + std::to_string(pin.line_number) +
")");
358 if (pin_names_str.consume(
"["))
360 if (pin_names_str.peek(1) ==
":")
362 i32 start = std::stol(pin_names_str.consume().string);
363 pin_names_str.consume(
":",
true);
364 i32 end = std::stol(pin_names_str.consume().string);
365 i32 dir = (start <= end) ? 1 : -1;
367 for (
int i = start; i != (end + dir); i += dir)
369 auto new_name =
name +
"(" + std::to_string(i) +
")";
371 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
373 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
376 cell.pin_names.insert(new_name);
377 pin.pin_names.push_back(std::move(new_name));
382 u32 index = std::stoul(pin_names_str.consume().string);
383 auto new_name =
name +
"(" + std::to_string(index) +
")";
385 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
387 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
390 cell.pin_names.insert(new_name);
391 pin.pin_names.push_back(std::move(new_name));
394 pin_names_str.consume(
"]",
true);
398 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
400 return ERR(
"could not parse pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
403 cell.pin_names.insert(
name);
404 pin.pin_names.push_back(std::move(
name));
407 pin_names_str.consume(
",", pin_names_str.remaining() > 0);
408 }
while (pin_names_str.remaining() > 0);
412 while (pin_str.remaining() > 0)
414 auto next_token = pin_str.consume();
415 if (next_token ==
"direction")
417 pin_str.consume(
":",
true);
418 auto direction_str = pin_str.consume().string;
421 pin.direction = enum_from_string<PinDirection>(direction_str);
423 catch (
const std::runtime_error&)
425 return ERR(
"could not parse pin: invalid pin direction '" + direction_str +
"' (line " + std::to_string(pin.line_number) +
")");
428 pin_str.consume(
";",
true);
430 else if (next_token ==
"function")
432 pin_str.consume(
":",
true);
433 pin.function = pin_str.consume().string;
434 pin_str.consume(
";",
true);
436 else if (next_token ==
"x_function")
438 pin_str.consume(
":",
true);
439 pin.x_function = pin_str.consume().string;
440 pin_str.consume(
";",
true);
442 else if (next_token ==
"three_state")
444 pin_str.consume(
":",
true);
445 pin.z_function = pin_str.consume().string;
446 pin_str.consume(
";",
true);
448 else if (next_token ==
"clock")
450 pin_str.consume(
":",
true);
451 if (pin_str.consume() ==
"true")
455 pin_str.consume(
";",
true);
461 return ERR(
"could not parse pin: no pin direction given (line " + std::to_string(pin.line_number) +
")");
467 Result<LibertyParser::pin_group> LibertyParser::parse_pg_pin(TokenStream<std::string>&
str, cell_group& cell)
471 pin.line_number =
str.peek().number;
472 str.consume(
"(",
true);
474 str.consume(
")",
true);
475 str.consume(
"{",
true);
477 str.consume(
"}",
true);
479 if (pin_names_str.size() == 0)
481 return ERR(
"could not parse power/ground pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
483 else if (pin_names_str.size() > 1)
485 return ERR(
"could not parse power/ground pins '" + pin_names_str.join(
"").string +
"': more than one pin name given (line " + std::to_string(pin.line_number) +
")");
488 std::string
name = pin_names_str.consume().string;
489 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
491 return ERR(
"could not parse power/ground pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
494 while (pin_str.remaining() > 0)
496 auto next_token = pin_str.consume();
497 if (next_token ==
"pg_type")
499 pin_str.consume(
":",
true);
500 std::string
type = pin_str.consume().string;
501 if (
type ==
"primary_power")
505 else if (
type ==
"primary_ground")
511 return ERR(
"could not parse power/ground pin '" +
name +
"': invalid pin type '" +
type +
"' (line " + std::to_string(pin.line_number) +
")");
513 pin_str.consume(
";",
true);
518 cell.pin_names.insert(
name);
519 pin.pin_names.push_back(std::move(
name));
524 Result<LibertyParser::bus_group> LibertyParser::parse_bus(TokenStream<std::string>&
str, cell_group& cell)
527 std::vector<u32> range;
529 bus.line_number =
str.peek().number;
530 str.consume(
"(",
true);
531 bus.name =
str.consume().string;
532 str.consume(
")",
true);
533 str.consume(
"{",
true);
535 str.consume(
"}",
true);
539 auto next_token = bus_str.consume();
540 if (next_token ==
"bus_type")
542 bus_str.consume(
":",
true);
543 auto bus_type_str = bus_str.consume().string;
544 if (
const auto& it = m_bus_types.find(bus_type_str); it == m_bus_types.end())
546 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus type '" + bus_type_str +
"' (line " + std::to_string(bus.line_number) +
")");
550 auto&
type = it->second;
551 bus.ascending =
type.ascending;
552 bus.start_index =
type.start_index;
553 i32 dir = (
type.ascending ? 1 : -1);
554 for (
i32 i =
type.start_index; i != (
i32)(
type.start_index + dir *
type.width); i += dir)
559 bus_str.consume(
";",
true);
561 else if (next_token ==
"direction")
563 bus_str.consume(
":",
true);
564 auto direction_str = bus_str.consume().string;
565 if (direction_str ==
"input")
569 else if (direction_str ==
"output")
573 else if (direction_str ==
"inout")
577 else if (direction_str ==
"internal")
583 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus direction '" + direction_str +
"' (line " + std::to_string(bus.line_number) +
")");
585 bus_str.consume(
";",
true);
587 else if (next_token ==
"pin")
589 if (
auto res = parse_pin(bus_str, cell, bus.direction, bus.name); res.is_error())
591 return ERR(
"could not parse bus '" + bus.name +
"': failed to parse pin (line " + std::to_string(bus.line_number) +
")");
595 auto pin = res.get();
596 cell.pins.push_back(pin);
597 bus.pins.push_back(std::move(pin));
600 }
while (bus_str.remaining() > 0);
602 for (
const auto& index : range)
604 auto pin_name = bus.name +
"(" + std::to_string(index) +
")";
605 bus.pin_names.push_back(pin_name);
606 bus.index_to_pin[index] = pin_name;
611 return ERR(
"could not parse bus '" + bus.name +
"': no bus direction given (line " + std::to_string(bus.line_number) +
")");
617 Result<LibertyParser::ff_group> LibertyParser::parse_ff(TokenStream<std::string>&
str)
621 ff.line_number =
str.peek().number;
622 str.consume(
"(",
true);
623 ff.state1 =
str.consume().string;
624 str.consume(
",",
true);
625 ff.state2 =
str.consume().string;
626 str.consume(
")",
true);
627 str.consume(
"{",
true);
629 str.consume(
"}",
true);
633 auto next_token = ff_str.consume();
634 if (next_token ==
"clocked_on")
636 ff_str.consume(
":",
true);
637 ff.clocked_on = ff_str.consume();
638 ff_str.consume(
";",
true);
640 else if (next_token ==
"next_state")
642 ff_str.consume(
":",
true);
643 ff.next_state = ff_str.consume();
644 ff_str.consume(
";",
true);
646 else if (next_token ==
"clear")
648 ff_str.consume(
":",
true);
649 ff.clear = ff_str.consume();
650 ff_str.consume(
";",
true);
652 else if (next_token ==
"preset")
654 ff_str.consume(
":",
true);
655 ff.preset = ff_str.consume();
656 ff_str.consume(
";",
true);
658 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
660 ff_str.consume(
":",
true);
661 Token<std::string> behav_str = ff_str.consume();
662 ff_str.consume(
";",
true);
666 if (next_token ==
"clear_preset_var1")
668 ff.special_behavior_var1 = behav;
672 ff.special_behavior_var2 = behav;
677 return ERR(
"could not parse 'ff' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
680 }
while (ff_str.remaining() > 0);
685 Result<LibertyParser::latch_group> LibertyParser::parse_latch(TokenStream<std::string>&
str)
689 latch.line_number =
str.peek().number;
690 str.consume(
"(",
true);
691 latch.state1 =
str.consume().string;
692 str.consume(
",",
true);
693 latch.state2 =
str.consume().string;
694 str.consume(
")",
true);
695 str.consume(
"{",
true);
697 str.consume(
"}",
true);
701 auto next_token = latch_str.consume();
702 if (next_token ==
"enable")
704 latch_str.consume(
":",
true);
705 latch.enable = latch_str.consume();
706 latch_str.consume(
";",
true);
708 else if (next_token ==
"data_in")
710 latch_str.consume(
":",
true);
711 latch.data_in = latch_str.consume();
712 latch_str.consume(
";",
true);
714 else if (next_token ==
"clear")
716 latch_str.consume(
":",
true);
717 latch.clear = latch_str.consume();
718 latch_str.consume(
";",
true);
720 else if (next_token ==
"preset")
722 latch_str.consume(
":",
true);
723 latch.preset = latch_str.consume();
724 latch_str.consume(
";",
true);
726 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
728 latch_str.consume(
":",
true);
729 Token<std::string> behav_str = latch_str.consume();
730 latch_str.consume(
";",
true);
734 if (next_token ==
"clear_preset_var1")
736 latch.special_behavior_var1 = behav;
740 latch.special_behavior_var2 = behav;
745 return ERR(
"could not parse 'latch' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
748 }
while (latch_str.remaining() > 0);
753 Result<std::monostate> LibertyParser::construct_gate_type(cell_group&& cell)
756 bool has_inputs =
false;
758 std::string output_func;
759 for (
const auto& pin : cell.pins)
763 if (!pin.power && !pin.ground)
770 num_outputs += pin.pin_names.size();
771 output_func = pin.function;
775 std::unique_ptr<GateTypeComponent> parent_component =
nullptr;
776 if (!has_inputs && num_outputs == 1)
778 if (output_func ==
"0")
783 else if (output_func ==
"1")
789 else if (cell.ff.has_value())
791 if (cell.ff->clocked_on.empty() || cell.ff->next_state.empty())
793 return ERR(
"could not construct gate type '" + cell.name +
"': missing 'clocked_on' or 'next_state' function (or both)");
799 if (next_state_function.is_error())
801 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'next_state' function from string");
804 if (clocked_on_function.is_error())
806 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clocked_on' function from string");
810 FFComponent* ff_component = parent_component->convert_to<FFComponent>();
811 if (!cell.ff->clear.empty())
814 if (clear_function.is_error())
816 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
818 ff_component->set_async_reset_function(clear_function.get());
820 if (!cell.ff->preset.empty())
823 if (preset_function.is_error())
825 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
827 ff_component->set_async_set_function(preset_function.get());
830 ff_component->set_async_set_reset_behavior(cell.ff->special_behavior_var1, cell.ff->special_behavior_var2);
832 for (
auto& pin : cell.pins)
834 if (pin.clock ==
true)
838 else if (pin.function == cell.ff->state1)
842 else if (pin.function == cell.ff->state2)
848 else if (cell.latch.has_value())
853 LatchComponent* latch_component = parent_component->convert_to<LatchComponent>();
854 assert(latch_component !=
nullptr);
856 if (!cell.latch->data_in.empty())
861 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'data_in' function from string");
863 latch_component->set_data_in_function(res.get());
865 if (!cell.latch->enable.empty())
870 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'enable' function from string");
872 latch_component->set_enable_function(res.get());
874 if (!cell.latch->clear.empty())
879 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
881 latch_component->set_async_reset_function(res.get());
883 if (!cell.latch->preset.empty())
888 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
890 latch_component->set_async_set_function(res.get());
893 latch_component->set_async_set_reset_behavior(cell.latch->special_behavior_var1, cell.latch->special_behavior_var2);
895 for (
auto& pin : cell.pins)
897 if (pin.clock ==
true)
901 else if (pin.function == cell.latch->state1)
905 else if (pin.function == cell.latch->state2)
912 if (cell.properties.empty())
917 GateType* gt = m_gate_lib->create_gate_type(cell.name, cell.properties, std::move(parent_component));
920 for (
auto& pin : cell.pins)
922 if (pin.power ==
true)
927 if (pin.ground ==
true)
932 for (
const auto& pin_name : pin.pin_names)
934 if (
auto res = gt->create_pin(pin_name, pin.direction, pin.type); res.is_error())
936 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin '" + pin_name +
"'");
941 for (
const auto& [bus_name, bus_info] : cell.buses)
943 std::vector<GatePin*>
pins;
944 for (
const auto& pin_name : bus_info.pin_names)
946 if (
auto res = gt->get_pin_by_name(pin_name); res ==
nullptr)
948 return ERR(
"could not construct gate type '" + cell.name +
"': failed to get pin by name '" + pin_name +
"'");
955 if (
auto res = gt->create_pin_group(bus_name,
pins, bus_info.direction,
PinType::none, bus_info.ascending, bus_info.start_index); res.is_error())
957 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin group '" + bus_name +
"'");
961 if (!cell.buses.empty())
963 auto functions = construct_bus_functions(cell);
964 if (functions.is_error())
966 return ERR_APPEND(functions.get_error(),
"could not construct gate type '" + cell.name +
"': failed to construct bus functions");
968 gt->add_boolean_functions(functions.get());
972 for (
const auto& pin : cell.pins)
974 if (!pin.function.empty())
976 for (
const auto&
name : pin.pin_names)
979 if (
function.is_error())
981 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
983 gt->add_boolean_function(
name,
function.get());
987 if (!pin.x_function.empty())
989 for (
const auto&
name : pin.pin_names)
992 if (
function.is_error())
994 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
996 gt->add_boolean_function(
name +
"_undefined",
function.get());
1000 if (!pin.z_function.empty())
1002 for (
const auto&
name : pin.pin_names)
1005 if (
function.is_error())
1007 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1009 gt->add_boolean_function(
name +
"_tristate",
function.get());
1018 void LibertyParser::remove_comments(std::string& line,
bool& multi_line_comment)
1031 auto multi_line_comment_begin = line.find(
"/*");
1032 auto multi_line_comment_end = line.find(
"*/");
1034 std::string begin =
"";
1035 std::string end =
"";
1037 if (multi_line_comment ==
true)
1039 if (multi_line_comment_end != std::string::npos)
1042 multi_line_comment =
false;
1043 line = line.substr(multi_line_comment_end + 2);
1053 else if (multi_line_comment_begin != std::string::npos)
1055 if (multi_line_comment_end != std::string::npos)
1058 line = line.substr(0, multi_line_comment_begin) + line.substr(multi_line_comment_end + 2);
1064 multi_line_comment =
true;
1065 line = line.substr(0, multi_line_comment_begin);
1071 std::vector<std::string> LibertyParser::tokenize_function(
const std::string&
function)
1073 std::string delimiters =
"()[]:!'^+|&* ";
1074 std::string current_token;
1075 std::vector<std::string> res;
1077 for (
char c :
function)
1079 if (delimiters.find(c) == std::string::npos)
1085 if (!current_token.empty())
1087 res.push_back(current_token);
1088 current_token.clear();
1090 res.push_back(std::string(1, c));
1093 if (!current_token.empty())
1095 res.push_back(current_token);
1096 current_token.clear();
1102 std::map<std::string, std::string> LibertyParser::expand_bus_function(
const std::map<std::string, bus_group>& buses,
const std::vector<std::string>& pin_names,
const std::string&
function)
1104 auto tokenized_funtion = tokenize_function(
function);
1105 std::map<std::string, std::string> res;
1107 for (
const auto&
name : pin_names)
1109 res.emplace(
name,
"");
1112 std::string tmp =
"";
1114 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1116 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1118 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[")
1120 if (tokenized_funtion.size() > (i + 5) && tokenized_funtion.at(i + 3) ==
":" && tokenized_funtion.at(i + 5) ==
"]")
1122 i32 start = std::stoul(tokenized_funtion.at(i + 2));
1123 i32 end = std::stoul(tokenized_funtion.at(i + 4));
1126 for (
const auto&
name : pin_names)
1128 res[
name] += tmp + it->second.index_to_pin.at(start);
1134 else if (tokenized_funtion.at(i + 3) ==
"]")
1136 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1138 for (
const auto&
name : pin_names)
1140 res[
name] += tmp + it->second.index_to_pin.at(index);
1147 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1153 for (
u32 j = 0; j < pin_names.size(); j++)
1155 res[pin_names.at(j)] += tmp + it->second.pin_names.at(j);
1162 tmp += tokenized_funtion.at(i);
1168 for (
const auto&
name : pin_names)
1177 std::string LibertyParser::prepare_pin_function(
const std::map<std::string, bus_group>& buses,
const std::string&
function)
1179 auto tokenized_funtion = tokenize_function(
function);
1180 std::string res =
"";
1182 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1184 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1186 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[" && tokenized_funtion.at(i + 3) ==
"]")
1188 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1190 res += it->second.index_to_pin.at(index);
1196 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1202 res += tokenized_funtion.at(i);
1209 Result<std::unordered_map<std::string, BooleanFunction>> LibertyParser::construct_bus_functions(
const cell_group& cell)
1211 std::unordered_map<std::string, BooleanFunction> res;
1213 for (
const auto& [bus_name, bus] : cell.buses)
1222 for (
const auto& pin : bus.pins)
1224 if (!pin.function.empty())
1226 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.function))
1231 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1233 res.emplace(pin_name, bf.get());
1237 if (!pin.x_function.empty())
1239 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.x_function))
1244 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1246 res.emplace(pin_name +
"_undefined", bf.get());
1250 if (!pin.z_function.empty())
1252 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.z_function))
1257 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1259 res.emplace(pin_name +
"_tristate", bf.get());
1265 for (
const auto& pin : cell.pins)
1267 if (!pin.function.empty())
1269 if (
auto function = prepare_pin_function(cell.buses, pin.function); !
function.empty())
1271 for (
const auto& pin_name : pin.pin_names)
1276 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1278 res.emplace(pin_name, bf.get());
1283 if (!pin.x_function.empty())
1285 if (
auto function = prepare_pin_function(cell.buses, pin.x_function); !
function.empty())
1287 for (
const auto& pin_name : pin.pin_names)
1292 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1294 res.emplace(pin_name +
"_undefined", bf.get());
1299 if (!pin.z_function.empty())
1301 if (
auto function = prepare_pin_function(cell.buses, pin.z_function); !
function.empty())
1303 for (
const auto& pin_name : pin.pin_names)
1308 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1310 res.emplace(pin_name +
"_tristate", bf.get());
static Result< BooleanFunction > from_string(const std::string &expression)
static std::unique_ptr< GateTypeComponent > create_state_component(std::unique_ptr< GateTypeComponent > component, const std::string &state_identifier, const std::string &neg_state_identifier)
static std::unique_ptr< GateTypeComponent > create_latch_component(std::unique_ptr< GateTypeComponent > component)
static std::unique_ptr< GateTypeComponent > create_ff_component(std::unique_ptr< GateTypeComponent > component, const BooleanFunction &next_state_bf, const BooleanFunction &clock_bf)
Result< std::unique_ptr< GateLibrary > > parse(const std::filesystem::path &file_path) override
static const u32 END_OF_STREAM
TokenStream< T > extract_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Token< T > consume(u32 num=1)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
std::vector< PinInformation > pins