21 ifs.open(m_path.string(), std::ifstream::in);
24 return ERR(
"could not parse Liberty file '" + m_path.string() +
"' : unable to open file");
36 if (
auto res = parse_tokens(); res.is_error())
38 return ERR_APPEND(res.get_error(),
"could not parse Liberty file '" + file_path.string() +
"': unable to parse tokens");
43 if (e.line_number != (
u32)-1)
45 return ERR(
"could not parse Liberty file '" + m_path.string() +
"': " + e.message +
" (line " + std::to_string(e.line_number) +
")");
49 return ERR(
"could not parse Liberty file '" + m_path.string() +
"': " + e.message);
53 return OK(std::move(m_gate_lib));
56 void LibertyParser::tokenize()
58 std::string delimiters =
"{}()[];:\",";
59 std::string current_token;
63 bool in_string =
false;
64 bool was_in_string =
false;
65 bool multi_line_comment =
false;
67 std::vector<Token<std::string>> parsed_tokens;
69 while (std::getline(m_fs, line))
72 this->remove_comments(line, multi_line_comment);
79 in_string = !in_string;
83 if (std::isspace(c) && !in_string)
88 if (delimiters.find(c) == std::string::npos || in_string)
94 if (was_in_string || !current_token.empty())
96 parsed_tokens.emplace_back(line_number, current_token);
97 current_token.clear();
98 was_in_string =
false;
101 if (!std::isspace(c))
103 parsed_tokens.emplace_back(line_number, std::string(1, c));
107 if (!current_token.empty())
109 parsed_tokens.emplace_back(line_number, current_token);
110 current_token.clear();
114 m_token_stream = TokenStream<std::string>(parsed_tokens, {
"(",
"{"}, {
")",
"}"});
117 Result<std::monostate> LibertyParser::parse_tokens()
119 m_token_stream.
consume(
"library",
true);
120 m_token_stream.
consume(
"(",
true);
121 auto lib_name = m_token_stream.
consume();
122 m_token_stream.
consume(
")",
true);
123 m_token_stream.
consume(
"{",
true);
124 m_gate_lib = std::make_unique<GateLibrary>(m_path, lib_name.string);
126 m_token_stream.
consume(
"}",
false);
130 auto next_token = library_str.consume();
131 if (next_token ==
"{")
133 library_str.consume_until(
"}");
134 library_str.consume(
"}");
136 else if (next_token ==
"cell" && library_str.peek() ==
"(")
138 if (
auto cell = parse_cell(library_str); cell.is_error())
140 return ERR_APPEND(cell.get_error(),
"could not parse tokens: unable to parse cell (line " + std::to_string(next_token.number) +
")");
144 if (
auto res = construct_gate_type(cell.get()); res.is_error())
146 return ERR_APPEND(res.get_error(),
"could not parse tokens: unable to construct gate type (line " + std::to_string(next_token.number) +
")");
150 else if (next_token ==
"type" && library_str.peek() ==
"(")
152 if (
auto res = parse_type(library_str); res.is_error())
154 return ERR_APPEND(res.get_error(),
"could not parse tokens: unable to parse type (line " + std::to_string(next_token.number) +
")");
158 auto type = res.get();
159 m_bus_types[
type.name] = std::move(
type);
162 }
while (library_str.remaining() > 0);
164 if (
const u32 unparsed = m_token_stream.
remaining(); unparsed == 0)
170 return ERR(
"could not parse tokens: " + std::to_string(unparsed) +
" unparsed tokens remaining");
174 Result<LibertyParser::type_group> LibertyParser::parse_type(TokenStream<std::string>& str)
177 type.line_number = str.peek().number;
178 str.consume(
"(",
true);
179 type.name = str.consume().string;
180 str.consume(
")",
true);
181 str.consume(
"{",
true);
183 str.consume(
"}",
true);
185 type.start_index = 0;
187 type.ascending =
true;
188 while (type_str.remaining() > 0)
190 auto next_token = type_str.consume();
191 if (next_token ==
"{")
193 type_str.consume_until(
"}");
194 type_str.consume(
"}");
196 else if (next_token ==
"base_type")
198 type_str.consume(
":",
true);
199 type_str.consume(
"array",
true);
201 else if (next_token ==
"data_type")
203 type_str.consume(
":",
true);
204 type_str.consume(
"bit",
true);
206 else if (next_token ==
"bit_width")
208 type_str.consume(
":",
true);
209 type.width = std::stol(type_str.consume().string);
211 else if (next_token ==
"bit_from")
213 type_str.consume(
":",
true);
214 type.start_index = std::stol(type_str.consume().string);
216 else if (next_token ==
"bit_to")
219 type_str.consume(
":",
true);
220 type_str.consume_until(
";");
222 else if (next_token ==
"downto")
224 type_str.consume(
":",
true);
225 auto bval = type_str.consume();
228 type.ascending =
true;
230 else if (bval ==
"true")
232 type.ascending =
false;
236 return ERR(
"could not parse type '" +
type.name +
"': invalid Boolean value '" + bval.string +
"' (line " + std::to_string(bval.number) +
")");
241 return ERR(
"could not parse type '" +
type.name +
"': invalid token '" + next_token.string +
"' (line " + std::to_string(next_token.number) +
")");
243 type_str.consume(
";",
true);
248 Result<LibertyParser::cell_group> LibertyParser::parse_cell(TokenStream<std::string>& str)
252 cell.line_number = str.peek().number;
253 str.consume(
"(",
true);
254 cell.name = str.consume().string;
255 str.consume(
")",
true);
256 str.consume(
"{",
true);
258 str.consume(
"}",
true);
260 if (
const auto cell_it = m_cell_names.find(cell.name); cell_it != m_cell_names.end())
262 return ERR(
"could not parse cell '" + cell.name +
"': a cell with that name already exists");
265 m_cell_names.insert(cell.name);
267 while (cell_str.remaining() > 0)
269 auto next_token = cell_str.consume();
270 if (next_token ==
"{")
272 cell_str.consume_until(
"}");
273 cell_str.consume(
"}");
275 else if (next_token ==
"pin")
277 if (
auto pin = parse_pin(cell_str, cell); pin.is_error())
279 return ERR_APPEND(pin.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'pin' group (line " + std::to_string(next_token.number) +
")");
283 cell.pins.push_back(pin.get());
286 else if (next_token ==
"pg_pin")
288 if (
auto pin = parse_pg_pin(cell_str, cell); pin.is_ok())
290 cell.pins.push_back(pin.get());
293 else if (next_token ==
"bus")
295 if (
auto res = parse_bus(cell_str, cell); res.is_error())
297 return ERR_APPEND(res.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'bus' group (line " + std::to_string(next_token.number) +
")");
301 auto bus = res.get();
302 cell.buses[bus.name] = std::move(bus);
305 else if (next_token ==
"ff")
307 if (
auto ff = parse_ff(cell_str);
ff.is_error())
309 return ERR_APPEND(
ff.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'ff' group (line " + std::to_string(next_token.number) +
")");
318 else if (next_token ==
"latch")
320 if (
auto latch = parse_latch(cell_str);
latch.is_error())
322 return ERR_APPEND(
latch.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'latch' group (line " + std::to_string(next_token.number) +
")");
328 cell.latch =
latch.get();
336 Result<LibertyParser::pin_group> LibertyParser::parse_pin(TokenStream<std::string>& str, cell_group& cell,
PinDirection direction,
const std::string& external_pin_name)
340 pin.line_number = str.peek().number;
341 str.consume(
"(",
true);
343 str.consume(
")",
true);
344 str.consume(
"{",
true);
346 str.consume(
"}",
true);
348 if (pin_names_str.size() == 0)
350 return ERR(
"could not parse pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
355 std::string
name = pin_names_str.consume().string;
356 if (!external_pin_name.empty() &&
name != external_pin_name)
358 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) +
")");
361 if (pin_names_str.consume(
"["))
363 if (pin_names_str.peek(1) ==
":")
365 i32 start = std::stol(pin_names_str.consume().string);
366 pin_names_str.consume(
":",
true);
367 i32 end = std::stol(pin_names_str.consume().string);
368 i32 dir = (start <= end) ? 1 : -1;
370 for (
int i = start; i != (end + dir); i += dir)
372 auto new_name =
name +
"(" + std::to_string(i) +
")";
374 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
376 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
379 cell.pin_names.insert(new_name);
380 pin.pin_names.push_back(std::move(new_name));
385 u32 index = std::stoul(pin_names_str.consume().string);
386 auto new_name =
name +
"(" + std::to_string(
index) +
")";
388 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
390 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
393 cell.pin_names.insert(new_name);
394 pin.pin_names.push_back(std::move(new_name));
397 pin_names_str.consume(
"]",
true);
401 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
403 return ERR(
"could not parse pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
406 cell.pin_names.insert(
name);
407 pin.pin_names.push_back(std::move(
name));
410 pin_names_str.consume(
",", pin_names_str.remaining() > 0);
411 }
while (pin_names_str.remaining() > 0);
415 while (pin_str.remaining() > 0)
417 auto next_token = pin_str.consume();
418 if (next_token ==
"direction")
420 pin_str.consume(
":",
true);
421 auto direction_str = pin_str.consume().string;
424 pin.direction = enum_from_string<PinDirection>(direction_str);
426 catch (
const std::runtime_error&)
428 return ERR(
"could not parse pin: invalid pin direction '" + direction_str +
"' (line " + std::to_string(pin.line_number) +
")");
431 pin_str.consume(
";",
true);
433 else if (next_token ==
"function")
435 pin_str.consume(
":",
true);
436 pin.function = pin_str.consume().string;
437 pin_str.consume(
";",
true);
439 else if (next_token ==
"x_function")
441 pin_str.consume(
":",
true);
442 pin.x_function = pin_str.consume().string;
443 pin_str.consume(
";",
true);
445 else if (next_token ==
"three_state")
447 pin_str.consume(
":",
true);
448 pin.z_function = pin_str.consume().string;
449 pin_str.consume(
";",
true);
451 else if (next_token ==
"clock")
453 pin_str.consume(
":",
true);
454 if (pin_str.consume() ==
"true")
458 pin_str.consume(
";",
true);
464 return ERR(
"could not parse pin: no pin direction given (line " + std::to_string(pin.line_number) +
")");
470 Result<LibertyParser::pin_group> LibertyParser::parse_pg_pin(TokenStream<std::string>& str, cell_group& cell)
474 pin.line_number = str.peek().number;
475 str.consume(
"(",
true);
477 str.consume(
")",
true);
478 str.consume(
"{",
true);
480 str.consume(
"}",
true);
482 if (pin_names_str.size() == 0)
484 return ERR(
"could not parse power/ground pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
486 else if (pin_names_str.size() > 1)
488 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) +
")");
491 std::string
name = pin_names_str.consume().string;
492 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
494 return ERR(
"could not parse power/ground pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
497 while (pin_str.remaining() > 0)
499 auto next_token = pin_str.consume();
500 if (next_token ==
"pg_type")
502 pin_str.consume(
":",
true);
503 std::string
type = pin_str.consume().string;
504 if (
type ==
"primary_power")
508 else if (
type ==
"primary_ground")
514 return ERR(
"could not parse power/ground pin '" +
name +
"': invalid pin type '" +
type +
"' (line " + std::to_string(pin.line_number) +
")");
516 pin_str.consume(
";",
true);
521 cell.pin_names.insert(
name);
522 pin.pin_names.push_back(std::move(
name));
527 Result<LibertyParser::bus_group> LibertyParser::parse_bus(TokenStream<std::string>& str, cell_group& cell)
530 std::vector<u32> range;
532 bus.line_number = str.peek().number;
533 str.consume(
"(",
true);
534 bus.name = str.consume().string;
535 str.consume(
")",
true);
536 str.consume(
"{",
true);
538 str.consume(
"}",
true);
542 auto next_token = bus_str.consume();
543 if (next_token ==
"bus_type")
545 bus_str.consume(
":",
true);
546 auto bus_type_str = bus_str.consume().string;
547 if (
const auto& it = m_bus_types.find(bus_type_str); it == m_bus_types.end())
549 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus type '" + bus_type_str +
"' (line " + std::to_string(bus.line_number) +
")");
553 auto&
type = it->second;
554 bus.ascending =
type.ascending;
555 bus.start_index =
type.start_index;
556 i32 dir = (
type.ascending ? 1 : -1);
557 for (
i32 i =
type.start_index; i != (
i32)(
type.start_index + dir *
type.width); i += dir)
562 bus_str.consume(
";",
true);
564 else if (next_token ==
"direction")
566 bus_str.consume(
":",
true);
567 auto direction_str = bus_str.consume().string;
568 if (direction_str ==
"input")
572 else if (direction_str ==
"output")
576 else if (direction_str ==
"inout")
580 else if (direction_str ==
"internal")
586 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus direction '" + direction_str +
"' (line " + std::to_string(bus.line_number) +
")");
588 bus_str.consume(
";",
true);
590 else if (next_token ==
"pin")
592 if (
auto res = parse_pin(bus_str, cell, bus.direction, bus.name); res.is_error())
594 return ERR(
"could not parse bus '" + bus.name +
"': failed to parse pin (line " + std::to_string(bus.line_number) +
")");
598 auto pin = res.get();
599 cell.pins.push_back(pin);
600 bus.pins.push_back(std::move(pin));
603 }
while (bus_str.remaining() > 0);
605 for (
const auto&
index : range)
607 auto pin_name = bus.name +
"(" + std::to_string(
index) +
")";
608 bus.pin_names.push_back(pin_name);
609 bus.index_to_pin[
index] = pin_name;
614 return ERR(
"could not parse bus '" + bus.name +
"': no bus direction given (line " + std::to_string(bus.line_number) +
")");
620 Result<LibertyParser::ff_group> LibertyParser::parse_ff(TokenStream<std::string>& str)
624 ff.line_number = str.peek().number;
625 str.consume(
"(",
true);
626 ff.state1 = str.consume().string;
627 str.consume(
",",
true);
628 ff.state2 = str.consume().string;
629 str.consume(
")",
true);
630 str.consume(
"{",
true);
632 str.consume(
"}",
true);
636 auto next_token = ff_str.consume();
637 if (next_token ==
"clocked_on")
639 ff_str.consume(
":",
true);
640 ff.clocked_on = ff_str.consume();
641 ff_str.consume(
";",
true);
643 else if (next_token ==
"next_state")
645 ff_str.consume(
":",
true);
646 ff.next_state = ff_str.consume();
647 ff_str.consume(
";",
true);
649 else if (next_token ==
"clear")
651 ff_str.consume(
":",
true);
652 ff.clear = ff_str.consume();
653 ff_str.consume(
";",
true);
655 else if (next_token ==
"preset")
657 ff_str.consume(
":",
true);
658 ff.preset = ff_str.consume();
659 ff_str.consume(
";",
true);
661 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
663 ff_str.consume(
":",
true);
664 Token<std::string> behav_str = ff_str.consume();
665 ff_str.consume(
";",
true);
669 if (next_token ==
"clear_preset_var1")
671 ff.special_behavior_var1 = behav;
675 ff.special_behavior_var2 = behav;
680 return ERR(
"could not parse 'ff' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
683 }
while (ff_str.remaining() > 0);
688 Result<LibertyParser::latch_group> LibertyParser::parse_latch(TokenStream<std::string>& str)
692 latch.line_number = str.peek().number;
693 str.consume(
"(",
true);
694 latch.state1 = str.consume().string;
695 str.consume(
",",
true);
696 latch.state2 = str.consume().string;
697 str.consume(
")",
true);
698 str.consume(
"{",
true);
700 str.consume(
"}",
true);
704 auto next_token = latch_str.consume();
705 if (next_token ==
"enable")
707 latch_str.consume(
":",
true);
708 latch.enable = latch_str.consume();
709 latch_str.consume(
";",
true);
711 else if (next_token ==
"data_in")
713 latch_str.consume(
":",
true);
714 latch.data_in = latch_str.consume();
715 latch_str.consume(
";",
true);
717 else if (next_token ==
"clear")
719 latch_str.consume(
":",
true);
720 latch.clear = latch_str.consume();
721 latch_str.consume(
";",
true);
723 else if (next_token ==
"preset")
725 latch_str.consume(
":",
true);
726 latch.preset = latch_str.consume();
727 latch_str.consume(
";",
true);
729 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
731 latch_str.consume(
":",
true);
732 Token<std::string> behav_str = latch_str.consume();
733 latch_str.consume(
";",
true);
737 if (next_token ==
"clear_preset_var1")
739 latch.special_behavior_var1 = behav;
743 latch.special_behavior_var2 = behav;
748 return ERR(
"could not parse 'latch' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
751 }
while (latch_str.remaining() > 0);
756 Result<std::monostate> LibertyParser::construct_gate_type(cell_group&& cell)
759 bool has_inputs =
false;
761 std::string output_func;
762 for (
const auto& pin : cell.pins)
766 if (!pin.power && !pin.ground)
773 num_outputs += pin.pin_names.size();
774 output_func = pin.function;
778 std::unique_ptr<GateTypeComponent> parent_component =
nullptr;
779 if (!has_inputs && num_outputs == 1)
781 if (output_func ==
"0")
786 else if (output_func ==
"1")
792 else if (cell.ff.has_value())
794 if (cell.ff->clocked_on.empty() || cell.ff->next_state.empty())
796 return ERR(
"could not construct gate type '" + cell.name +
"': missing 'clocked_on' or 'next_state' function (or both)");
799 std::unique_ptr<GateTypeComponent> state_component =
StateComponent::create(
nullptr, cell.ff->state1, cell.ff->state2);
802 if (next_state_function.is_error())
804 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'next_state' function from string");
807 if (clocked_on_function.is_error())
809 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clocked_on' function from string");
811 parent_component =
FFComponent::create(std::move(state_component), next_state_function.get(), clocked_on_function.get());
813 FFComponent* ff_component = parent_component->convert_to<FFComponent>();
814 if (!cell.ff->clear.empty())
817 if (clear_function.is_error())
819 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
821 ff_component->set_async_reset_function(clear_function.get());
823 if (!cell.ff->preset.empty())
826 if (preset_function.is_error())
828 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
830 ff_component->set_async_set_function(preset_function.get());
833 ff_component->set_async_set_reset_behavior(cell.ff->special_behavior_var1, cell.ff->special_behavior_var2);
835 for (
auto& pin : cell.pins)
837 if (pin.clock ==
true)
841 else if (pin.function == cell.ff->state1)
845 else if (pin.function == cell.ff->state2)
851 else if (cell.latch.has_value())
853 std::unique_ptr<GateTypeComponent> state_component =
StateComponent::create(
nullptr, cell.latch->state1, cell.latch->state2);
856 LatchComponent* latch_component = parent_component->convert_to<LatchComponent>();
857 assert(latch_component !=
nullptr);
859 if (!cell.latch->data_in.empty())
864 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'data_in' function from string");
866 latch_component->set_data_in_function(res.get());
868 if (!cell.latch->enable.empty())
873 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'enable' function from string");
875 latch_component->set_enable_function(res.get());
877 if (!cell.latch->clear.empty())
882 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
884 latch_component->set_async_reset_function(res.get());
886 if (!cell.latch->preset.empty())
891 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
893 latch_component->set_async_set_function(res.get());
896 latch_component->set_async_set_reset_behavior(cell.latch->special_behavior_var1, cell.latch->special_behavior_var2);
898 for (
auto& pin : cell.pins)
900 if (pin.clock ==
true)
904 else if (pin.function == cell.latch->state1)
908 else if (pin.function == cell.latch->state2)
915 if (cell.properties.empty())
920 GateType* gt = m_gate_lib->create_gate_type(cell.name, cell.properties, std::move(parent_component));
923 for (
auto& pin : cell.pins)
925 if (pin.power ==
true)
930 if (pin.ground ==
true)
935 for (
const auto& pin_name : pin.pin_names)
937 if (
auto res = gt->create_pin(pin_name, pin.direction, pin.type); res.is_error())
939 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin '" + pin_name +
"'");
944 for (
const auto& [bus_name, bus_info] : cell.buses)
946 std::vector<GatePin*>
pins;
947 for (
const auto& pin_name : bus_info.pin_names)
949 if (
auto res = gt->get_pin_by_name(pin_name); res ==
nullptr)
951 return ERR(
"could not construct gate type '" + cell.name +
"': failed to get pin by name '" + pin_name +
"'");
958 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())
960 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin group '" + bus_name +
"'");
964 if (!cell.buses.empty())
966 auto functions = construct_bus_functions(cell);
967 if (functions.is_error())
969 return ERR_APPEND(functions.get_error(),
"could not construct gate type '" + cell.name +
"': failed to construct bus functions");
971 gt->add_boolean_functions(functions.get());
975 for (
const auto& pin : cell.pins)
977 if (!pin.function.empty())
979 for (
const auto&
name : pin.pin_names)
982 if (
function.is_error())
984 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
986 gt->add_boolean_function(
name,
function.get());
990 if (!pin.x_function.empty())
992 for (
const auto&
name : pin.pin_names)
995 if (
function.is_error())
997 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
999 gt->add_boolean_function(
name +
"_undefined",
function.get());
1003 if (!pin.z_function.empty())
1005 for (
const auto&
name : pin.pin_names)
1008 if (
function.is_error())
1010 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1012 gt->add_boolean_function(
name +
"_tristate",
function.get());
1021 void LibertyParser::remove_comments(std::string& line,
bool& multi_line_comment)
1034 auto multi_line_comment_begin = line.find(
"/*");
1035 auto multi_line_comment_end = line.find(
"*/");
1037 std::string begin =
"";
1038 std::string end =
"";
1040 if (multi_line_comment ==
true)
1042 if (multi_line_comment_end != std::string::npos)
1045 multi_line_comment =
false;
1046 line = line.substr(multi_line_comment_end + 2);
1056 else if (multi_line_comment_begin != std::string::npos)
1058 if (multi_line_comment_end != std::string::npos)
1061 line = line.substr(0, multi_line_comment_begin) + line.substr(multi_line_comment_end + 2);
1067 multi_line_comment =
true;
1068 line = line.substr(0, multi_line_comment_begin);
1074 std::vector<std::string> LibertyParser::tokenize_function(
const std::string&
function)
1076 std::string delimiters =
"()[]:!'^+|&* ";
1077 std::string current_token;
1078 std::vector<std::string> res;
1080 for (
char c :
function)
1082 if (delimiters.find(c) == std::string::npos)
1088 if (!current_token.empty())
1090 res.push_back(current_token);
1091 current_token.clear();
1093 res.push_back(std::string(1, c));
1096 if (!current_token.empty())
1098 res.push_back(current_token);
1099 current_token.clear();
1105 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)
1107 auto tokenized_funtion = tokenize_function(
function);
1108 std::map<std::string, std::string> res;
1110 for (
const auto&
name : pin_names)
1112 res.emplace(
name,
"");
1115 std::string tmp =
"";
1117 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1119 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1121 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[")
1123 if (tokenized_funtion.size() > (i + 5) && tokenized_funtion.at(i + 3) ==
":" && tokenized_funtion.at(i + 5) ==
"]")
1125 i32 start = std::stoul(tokenized_funtion.at(i + 2));
1126 i32 end = std::stoul(tokenized_funtion.at(i + 4));
1129 for (
const auto&
name : pin_names)
1131 res[
name] += tmp + it->second.index_to_pin.at(start);
1137 else if (tokenized_funtion.at(i + 3) ==
"]")
1139 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1141 for (
const auto&
name : pin_names)
1143 res[
name] += tmp + it->second.index_to_pin.at(
index);
1150 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1156 for (
u32 j = 0; j < pin_names.size(); j++)
1158 res[pin_names.at(j)] += tmp + it->second.pin_names.at(j);
1165 tmp += tokenized_funtion.at(i);
1171 for (
const auto&
name : pin_names)
1180 std::string LibertyParser::prepare_pin_function(
const std::map<std::string, bus_group>& buses,
const std::string&
function)
1182 auto tokenized_funtion = tokenize_function(
function);
1183 std::string res =
"";
1185 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1187 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1189 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[" && tokenized_funtion.at(i + 3) ==
"]")
1191 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1193 res += it->second.index_to_pin.at(
index);
1199 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1205 res += tokenized_funtion.at(i);
1212 Result<std::unordered_map<std::string, BooleanFunction>> LibertyParser::construct_bus_functions(
const cell_group& cell)
1214 std::unordered_map<std::string, BooleanFunction> res;
1216 for (
const auto& [bus_name, bus] : cell.buses)
1225 for (
const auto& pin : bus.pins)
1227 if (!pin.function.empty())
1229 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.function))
1234 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1236 res.emplace(pin_name, bf.get());
1240 if (!pin.x_function.empty())
1242 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.x_function))
1247 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1249 res.emplace(pin_name +
"_undefined", bf.get());
1253 if (!pin.z_function.empty())
1255 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.z_function))
1260 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1262 res.emplace(pin_name +
"_tristate", bf.get());
1268 for (
const auto& pin : cell.pins)
1270 if (!pin.function.empty())
1272 if (
auto function = prepare_pin_function(cell.buses, pin.function); !
function.empty())
1274 for (
const auto& pin_name : pin.pin_names)
1279 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1281 res.emplace(pin_name, bf.get());
1286 if (!pin.x_function.empty())
1288 if (
auto function = prepare_pin_function(cell.buses, pin.x_function); !
function.empty())
1290 for (
const auto& pin_name : pin.pin_names)
1295 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1297 res.emplace(pin_name +
"_undefined", bf.get());
1302 if (!pin.z_function.empty())
1304 if (
auto function = prepare_pin_function(cell.buses, pin.z_function); !
function.empty())
1306 for (
const auto& pin_name : pin.pin_names)
1311 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1313 res.emplace(pin_name +
"_tristate", bf.get());
static Result< BooleanFunction > from_string(const std::string &expression)
static std::unique_ptr< FFComponent > create(std::unique_ptr< GateTypeComponent > component, const BooleanFunction &next_state_bf, const BooleanFunction &clock_bf)
static std::unique_ptr< LatchComponent > create(std::unique_ptr< GateTypeComponent > component)
Result< std::unique_ptr< GateLibrary > > parse(const std::filesystem::path &file_path) override
static std::unique_ptr< StateComponent > create(std::unique_ptr< GateTypeComponent > component, const std::string &state_identifier, const std::string &neg_state_identifier)
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