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")
218 type_str.consume(
":",
true);
219 type_str.consume_until(
";");
221 else if (next_token ==
"downto")
223 type_str.consume(
":",
true);
224 auto bval = type_str.consume();
227 type.ascending =
true;
229 else if (bval ==
"true")
231 type.ascending =
false;
235 return ERR(
"could not parse type '" +
type.name +
"': invalid Boolean value '" + bval.string +
"' (line " + std::to_string(bval.number) +
")");
240 return ERR(
"could not parse type '" +
type.name +
"': invalid token '" + next_token.string +
"' (line " + std::to_string(next_token.number) +
")");
242 type_str.consume(
";",
true);
247 Result<LibertyParser::cell_group> LibertyParser::parse_cell(TokenStream<std::string>& str)
251 cell.line_number = str.peek().number;
252 str.consume(
"(",
true);
253 cell.name = str.consume().string;
254 str.consume(
")",
true);
255 str.consume(
"{",
true);
257 str.consume(
"}",
true);
259 if (
const auto cell_it = m_cell_names.find(cell.name); cell_it != m_cell_names.end())
261 return ERR(
"could not parse cell '" + cell.name +
"': a cell with that name already exists");
264 m_cell_names.insert(cell.name);
266 while (cell_str.remaining() > 0)
268 auto next_token = cell_str.consume();
269 if (next_token ==
"{")
271 cell_str.consume_until(
"}");
272 cell_str.consume(
"}");
274 else if (next_token ==
"pin")
276 if (
auto pin = parse_pin(cell_str, cell); pin.is_error())
278 return ERR_APPEND(pin.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'pin' group (line " + std::to_string(next_token.number) +
")");
282 cell.pins.push_back(pin.get());
285 else if (next_token ==
"pg_pin")
287 if (
auto pin = parse_pg_pin(cell_str, cell); pin.is_ok())
289 cell.pins.push_back(pin.get());
292 else if (next_token ==
"bus")
294 if (
auto res = parse_bus(cell_str, cell); res.is_error())
296 return ERR_APPEND(res.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'bus' group (line " + std::to_string(next_token.number) +
")");
300 auto bus = res.get();
301 cell.buses[bus.name] = std::move(bus);
304 else if (next_token ==
"ff")
306 if (
auto ff = parse_ff(cell_str);
ff.is_error())
308 return ERR_APPEND(
ff.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'ff' group (line " + std::to_string(next_token.number) +
")");
317 else if (next_token ==
"latch")
319 if (
auto latch = parse_latch(cell_str);
latch.is_error())
321 return ERR_APPEND(
latch.get_error(),
"could not parse cell '" + cell.name +
"': failed to parse 'latch' group (line " + std::to_string(next_token.number) +
")");
327 cell.latch =
latch.get();
335 Result<LibertyParser::pin_group> LibertyParser::parse_pin(TokenStream<std::string>& str, cell_group& cell,
PinDirection direction,
const std::string& external_pin_name)
339 pin.line_number = str.peek().number;
340 str.consume(
"(",
true);
342 str.consume(
")",
true);
343 str.consume(
"{",
true);
345 str.consume(
"}",
true);
347 if (pin_names_str.size() == 0)
349 return ERR(
"could not parse pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
354 std::string
name = pin_names_str.consume().string;
355 if (!external_pin_name.empty() &&
name != external_pin_name)
357 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) +
")");
360 if (pin_names_str.consume(
"["))
362 if (pin_names_str.peek(1) ==
":")
364 i32 start = std::stol(pin_names_str.consume().string);
365 pin_names_str.consume(
":",
true);
366 i32 end = std::stol(pin_names_str.consume().string);
367 i32 dir = (start <= end) ? 1 : -1;
369 for (
int i = start; i != (end + dir); i += dir)
371 auto new_name =
name +
"(" + std::to_string(i) +
")";
373 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
375 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
378 cell.pin_names.insert(new_name);
379 pin.pin_names.push_back(std::move(new_name));
384 u32 index = std::stoul(pin_names_str.consume().string);
385 auto new_name =
name +
"(" + std::to_string(
index) +
")";
387 if (
const auto pin_it = cell.pin_names.find(new_name); pin_it != cell.pin_names.end())
389 return ERR(
"could not parse pin '" + new_name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
392 cell.pin_names.insert(new_name);
393 pin.pin_names.push_back(std::move(new_name));
396 pin_names_str.consume(
"]",
true);
400 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
402 return ERR(
"could not parse pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
405 cell.pin_names.insert(
name);
406 pin.pin_names.push_back(std::move(
name));
409 pin_names_str.consume(
",", pin_names_str.remaining() > 0);
410 }
while (pin_names_str.remaining() > 0);
414 while (pin_str.remaining() > 0)
416 auto next_token = pin_str.consume();
417 if (next_token ==
"direction")
419 pin_str.consume(
":",
true);
420 auto direction_str = pin_str.consume().string;
423 pin.direction = enum_from_string<PinDirection>(direction_str);
425 catch (
const std::runtime_error&)
427 return ERR(
"could not parse pin: invalid pin direction '" + direction_str +
"' (line " + std::to_string(pin.line_number) +
")");
430 pin_str.consume(
";",
true);
432 else if (next_token ==
"function")
434 pin_str.consume(
":",
true);
435 pin.function = pin_str.consume().string;
436 pin_str.consume(
";",
true);
438 else if (next_token ==
"x_function")
440 pin_str.consume(
":",
true);
441 pin.x_function = pin_str.consume().string;
442 pin_str.consume(
";",
true);
444 else if (next_token ==
"three_state")
446 pin_str.consume(
":",
true);
447 pin.z_function = pin_str.consume().string;
448 pin_str.consume(
";",
true);
450 else if (next_token ==
"clock")
452 pin_str.consume(
":",
true);
453 if (pin_str.consume() ==
"true")
457 pin_str.consume(
";",
true);
463 return ERR(
"could not parse pin: no pin direction given (line " + std::to_string(pin.line_number) +
")");
469 Result<LibertyParser::pin_group> LibertyParser::parse_pg_pin(TokenStream<std::string>& str, cell_group& cell)
473 pin.line_number = str.peek().number;
474 str.consume(
"(",
true);
476 str.consume(
")",
true);
477 str.consume(
"{",
true);
479 str.consume(
"}",
true);
481 if (pin_names_str.size() == 0)
483 return ERR(
"could not parse power/ground pin: no pin name given (line " + std::to_string(pin.line_number) +
")");
485 else if (pin_names_str.size() > 1)
487 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) +
")");
490 std::string
name = pin_names_str.consume().string;
491 if (
const auto pin_it = cell.pin_names.find(
name); pin_it != cell.pin_names.end())
493 return ERR(
"could not parse power/ground pin '" +
name +
"': a pin with that name already exists (line " + std::to_string(pin.line_number) +
")");
496 while (pin_str.remaining() > 0)
498 auto next_token = pin_str.consume();
499 if (next_token ==
"pg_type")
501 pin_str.consume(
":",
true);
502 std::string
type = pin_str.consume().string;
503 if (
type ==
"primary_power")
507 else if (
type ==
"primary_ground")
513 return ERR(
"could not parse power/ground pin '" +
name +
"': invalid pin type '" +
type +
"' (line " + std::to_string(pin.line_number) +
")");
515 pin_str.consume(
";",
true);
520 cell.pin_names.insert(
name);
521 pin.pin_names.push_back(std::move(
name));
526 Result<LibertyParser::bus_group> LibertyParser::parse_bus(TokenStream<std::string>& str, cell_group& cell)
529 std::vector<u32> range;
531 bus.line_number = str.peek().number;
532 str.consume(
"(",
true);
533 bus.name = str.consume().string;
534 str.consume(
")",
true);
535 str.consume(
"{",
true);
537 str.consume(
"}",
true);
541 auto next_token = bus_str.consume();
542 if (next_token ==
"bus_type")
544 bus_str.consume(
":",
true);
545 auto bus_type_str = bus_str.consume().string;
546 if (
const auto& it = m_bus_types.find(bus_type_str); it == m_bus_types.end())
548 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus type '" + bus_type_str +
"' (line " + std::to_string(bus.line_number) +
")");
552 auto&
type = it->second;
553 bus.ascending =
type.ascending;
554 bus.start_index =
type.start_index;
555 i32 dir = (
type.ascending ? 1 : -1);
556 for (
i32 i =
type.start_index; i != (
i32)(
type.start_index + dir *
type.width); i += dir)
561 bus_str.consume(
";",
true);
563 else if (next_token ==
"direction")
565 bus_str.consume(
":",
true);
566 auto direction_str = bus_str.consume().string;
567 if (direction_str ==
"input")
571 else if (direction_str ==
"output")
575 else if (direction_str ==
"inout")
579 else if (direction_str ==
"internal")
585 return ERR(
"could not parse bus '" + bus.name +
"': invalid bus direction '" + direction_str +
"' (line " + std::to_string(bus.line_number) +
")");
587 bus_str.consume(
";",
true);
589 else if (next_token ==
"pin")
591 if (
auto res = parse_pin(bus_str, cell, bus.direction, bus.name); res.is_error())
593 return ERR(
"could not parse bus '" + bus.name +
"': failed to parse pin (line " + std::to_string(bus.line_number) +
")");
597 auto pin = res.get();
598 cell.pins.push_back(pin);
599 bus.pins.push_back(std::move(pin));
602 }
while (bus_str.remaining() > 0);
604 for (
const auto&
index : range)
606 auto pin_name = bus.name +
"(" + std::to_string(
index) +
")";
607 bus.pin_names.push_back(pin_name);
608 bus.index_to_pin[
index] = pin_name;
613 return ERR(
"could not parse bus '" + bus.name +
"': no bus direction given (line " + std::to_string(bus.line_number) +
")");
619 Result<LibertyParser::ff_group> LibertyParser::parse_ff(TokenStream<std::string>& str)
623 ff.line_number = str.peek().number;
624 str.consume(
"(",
true);
625 ff.state1 = str.consume().string;
626 str.consume(
",",
true);
627 ff.state2 = str.consume().string;
628 str.consume(
")",
true);
629 str.consume(
"{",
true);
631 str.consume(
"}",
true);
635 auto next_token = ff_str.consume();
636 if (next_token ==
"clocked_on")
638 ff_str.consume(
":",
true);
639 ff.clocked_on = ff_str.consume();
640 ff_str.consume(
";",
true);
642 else if (next_token ==
"next_state")
644 ff_str.consume(
":",
true);
645 ff.next_state = ff_str.consume();
646 ff_str.consume(
";",
true);
648 else if (next_token ==
"clear")
650 ff_str.consume(
":",
true);
651 ff.clear = ff_str.consume();
652 ff_str.consume(
";",
true);
654 else if (next_token ==
"preset")
656 ff_str.consume(
":",
true);
657 ff.preset = ff_str.consume();
658 ff_str.consume(
";",
true);
660 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
662 ff_str.consume(
":",
true);
663 Token<std::string> behav_str = ff_str.consume();
664 ff_str.consume(
";",
true);
668 if (next_token ==
"clear_preset_var1")
670 ff.special_behavior_var1 = behav;
674 ff.special_behavior_var2 = behav;
679 return ERR(
"could not parse 'ff' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
682 }
while (ff_str.remaining() > 0);
687 Result<LibertyParser::latch_group> LibertyParser::parse_latch(TokenStream<std::string>& str)
691 latch.line_number = str.peek().number;
692 str.consume(
"(",
true);
693 latch.state1 = str.consume().string;
694 str.consume(
",",
true);
695 latch.state2 = str.consume().string;
696 str.consume(
")",
true);
697 str.consume(
"{",
true);
699 str.consume(
"}",
true);
703 auto next_token = latch_str.consume();
704 if (next_token ==
"enable")
706 latch_str.consume(
":",
true);
707 latch.enable = latch_str.consume();
708 latch_str.consume(
";",
true);
710 else if (next_token ==
"data_in")
712 latch_str.consume(
":",
true);
713 latch.data_in = latch_str.consume();
714 latch_str.consume(
";",
true);
716 else if (next_token ==
"clear")
718 latch_str.consume(
":",
true);
719 latch.clear = latch_str.consume();
720 latch_str.consume(
";",
true);
722 else if (next_token ==
"preset")
724 latch_str.consume(
":",
true);
725 latch.preset = latch_str.consume();
726 latch_str.consume(
";",
true);
728 else if (next_token ==
"clear_preset_var1" || next_token ==
"clear_preset_var2")
730 latch_str.consume(
":",
true);
731 Token<std::string> behav_str = latch_str.consume();
732 latch_str.consume(
";",
true);
736 if (next_token ==
"clear_preset_var1")
738 latch.special_behavior_var1 = behav;
742 latch.special_behavior_var2 = behav;
747 return ERR(
"could not parse 'latch' group: invalid clear_preset behavior '" + behav_str.string +
"' (line " + std::to_string(behav_str.number) +
")");
750 }
while (latch_str.remaining() > 0);
755 Result<std::monostate> LibertyParser::construct_gate_type(cell_group&& cell)
758 bool has_inputs =
false;
760 std::string output_func;
761 for (
const auto& pin : cell.pins)
765 if (!pin.power && !pin.ground)
772 num_outputs += pin.pin_names.size();
773 output_func = pin.function;
777 std::unique_ptr<GateTypeComponent> parent_component =
nullptr;
778 if (!has_inputs && num_outputs == 1)
780 if (output_func ==
"0")
785 else if (output_func ==
"1")
791 else if (cell.ff.has_value())
793 if (cell.ff->clocked_on.empty() || cell.ff->next_state.empty())
795 return ERR(
"could not construct gate type '" + cell.name +
"': missing 'clocked_on' or 'next_state' function (or both)");
801 if (next_state_function.is_error())
803 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'next_state' function from string");
806 if (clocked_on_function.is_error())
808 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clocked_on' function from string");
812 FFComponent* ff_component = parent_component->convert_to<FFComponent>();
813 if (!cell.ff->clear.empty())
816 if (clear_function.is_error())
818 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
820 ff_component->set_async_reset_function(clear_function.get());
822 if (!cell.ff->preset.empty())
825 if (preset_function.is_error())
827 return ERR_APPEND(next_state_function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
829 ff_component->set_async_set_function(preset_function.get());
832 ff_component->set_async_set_reset_behavior(cell.ff->special_behavior_var1, cell.ff->special_behavior_var2);
834 for (
auto& pin : cell.pins)
836 if (pin.clock ==
true)
840 else if (pin.function == cell.ff->state1)
844 else if (pin.function == cell.ff->state2)
850 else if (cell.latch.has_value())
855 LatchComponent* latch_component = parent_component->convert_to<LatchComponent>();
856 assert(latch_component !=
nullptr);
858 if (!cell.latch->data_in.empty())
863 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'data_in' function from string");
865 latch_component->set_data_in_function(res.get());
867 if (!cell.latch->enable.empty())
872 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'enable' function from string");
874 latch_component->set_enable_function(res.get());
876 if (!cell.latch->clear.empty())
881 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'clear' function from string");
883 latch_component->set_async_reset_function(res.get());
885 if (!cell.latch->preset.empty())
890 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing 'preset' function from string");
892 latch_component->set_async_set_function(res.get());
895 latch_component->set_async_set_reset_behavior(cell.latch->special_behavior_var1, cell.latch->special_behavior_var2);
897 for (
auto& pin : cell.pins)
899 if (pin.clock ==
true)
903 else if (pin.function == cell.latch->state1)
907 else if (pin.function == cell.latch->state2)
914 if (cell.properties.empty())
919 GateType* gt = m_gate_lib->create_gate_type(cell.name, cell.properties, std::move(parent_component));
922 for (
auto& pin : cell.pins)
924 if (pin.power ==
true)
929 if (pin.ground ==
true)
934 for (
const auto& pin_name : pin.pin_names)
936 if (
auto res = gt->create_pin(pin_name, pin.direction, pin.type); res.is_error())
938 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin '" + pin_name +
"'");
943 for (
const auto& [bus_name, bus_info] : cell.buses)
945 std::vector<GatePin*>
pins;
946 for (
const auto& pin_name : bus_info.pin_names)
948 if (
auto res = gt->get_pin_by_name(pin_name); res ==
nullptr)
950 return ERR(
"could not construct gate type '" + cell.name +
"': failed to get pin by name '" + pin_name +
"'");
957 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())
959 return ERR_APPEND(res.get_error(),
"could not construct gate type '" + cell.name +
"': failed to create pin group '" + bus_name +
"'");
963 if (!cell.buses.empty())
965 auto functions = construct_bus_functions(cell);
966 if (functions.is_error())
968 return ERR_APPEND(functions.get_error(),
"could not construct gate type '" + cell.name +
"': failed to construct bus functions");
970 gt->add_boolean_functions(functions.get());
974 for (
const auto& pin : cell.pins)
976 if (!pin.function.empty())
978 for (
const auto&
name : pin.pin_names)
981 if (
function.is_error())
983 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
985 gt->add_boolean_function(
name,
function.get());
989 if (!pin.x_function.empty())
991 for (
const auto&
name : pin.pin_names)
994 if (
function.is_error())
996 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
998 gt->add_boolean_function(
name +
"_undefined",
function.get());
1002 if (!pin.z_function.empty())
1004 for (
const auto&
name : pin.pin_names)
1007 if (
function.is_error())
1009 return ERR_APPEND(
function.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1011 gt->add_boolean_function(
name +
"_tristate",
function.get());
1020 void LibertyParser::remove_comments(std::string& line,
bool& multi_line_comment)
1033 auto multi_line_comment_begin = line.find(
"/*");
1034 auto multi_line_comment_end = line.find(
"*/");
1036 std::string begin =
"";
1037 std::string end =
"";
1039 if (multi_line_comment ==
true)
1041 if (multi_line_comment_end != std::string::npos)
1044 multi_line_comment =
false;
1045 line = line.substr(multi_line_comment_end + 2);
1055 else if (multi_line_comment_begin != std::string::npos)
1057 if (multi_line_comment_end != std::string::npos)
1060 line = line.substr(0, multi_line_comment_begin) + line.substr(multi_line_comment_end + 2);
1066 multi_line_comment =
true;
1067 line = line.substr(0, multi_line_comment_begin);
1073 std::vector<std::string> LibertyParser::tokenize_function(
const std::string&
function)
1075 std::string delimiters =
"()[]:!'^+|&* ";
1076 std::string current_token;
1077 std::vector<std::string> res;
1079 for (
char c :
function)
1081 if (delimiters.find(c) == std::string::npos)
1087 if (!current_token.empty())
1089 res.push_back(current_token);
1090 current_token.clear();
1092 res.push_back(std::string(1, c));
1095 if (!current_token.empty())
1097 res.push_back(current_token);
1098 current_token.clear();
1104 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)
1106 auto tokenized_funtion = tokenize_function(
function);
1107 std::map<std::string, std::string> res;
1109 for (
const auto&
name : pin_names)
1111 res.emplace(
name,
"");
1114 std::string tmp =
"";
1116 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1118 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1120 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[")
1122 if (tokenized_funtion.size() > (i + 5) && tokenized_funtion.at(i + 3) ==
":" && tokenized_funtion.at(i + 5) ==
"]")
1124 i32 start = std::stoul(tokenized_funtion.at(i + 2));
1125 i32 end = std::stoul(tokenized_funtion.at(i + 4));
1128 for (
const auto&
name : pin_names)
1130 res[
name] += tmp + it->second.index_to_pin.at(start);
1136 else if (tokenized_funtion.at(i + 3) ==
"]")
1138 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1140 for (
const auto&
name : pin_names)
1142 res[
name] += tmp + it->second.index_to_pin.at(
index);
1149 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1155 for (
u32 j = 0; j < pin_names.size(); j++)
1157 res[pin_names.at(j)] += tmp + it->second.pin_names.at(j);
1164 tmp += tokenized_funtion.at(i);
1170 for (
const auto&
name : pin_names)
1179 std::string LibertyParser::prepare_pin_function(
const std::map<std::string, bus_group>& buses,
const std::string&
function)
1181 auto tokenized_funtion = tokenize_function(
function);
1182 std::string res =
"";
1184 for (
u32 i = 0; i < tokenized_funtion.size(); i++)
1186 if (
const auto& it = buses.find(tokenized_funtion.at(i)); it != buses.end())
1188 if (tokenized_funtion.size() > (i + 3) && tokenized_funtion.at(i + 1) ==
"[" && tokenized_funtion.at(i + 3) ==
"]")
1190 u32 index = std::stoul(tokenized_funtion.at(i + 2));
1192 res += it->second.index_to_pin.at(
index);
1198 log_warning(
"liberty_parser",
"could not handle bus '{}' in function '{}' near line {}, ignoring function.", it->first,
function, it->second.line_number);
1204 res += tokenized_funtion.at(i);
1211 Result<std::unordered_map<std::string, BooleanFunction>> LibertyParser::construct_bus_functions(
const cell_group& cell)
1213 std::unordered_map<std::string, BooleanFunction> res;
1215 for (
const auto& [bus_name, bus] : cell.buses)
1224 for (
const auto& pin : bus.pins)
1226 if (!pin.function.empty())
1228 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.function))
1233 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1235 res.emplace(pin_name, bf.get());
1239 if (!pin.x_function.empty())
1241 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.x_function))
1246 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1248 res.emplace(pin_name +
"_undefined", bf.get());
1252 if (!pin.z_function.empty())
1254 for (
auto [pin_name,
function] : expand_bus_function(cell.buses, pin.pin_names, pin.z_function))
1259 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1261 res.emplace(pin_name +
"_tristate", bf.get());
1267 for (
const auto& pin : cell.pins)
1269 if (!pin.function.empty())
1271 if (
auto function = prepare_pin_function(cell.buses, pin.function); !
function.empty())
1273 for (
const auto& pin_name : pin.pin_names)
1278 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing output function from string");
1280 res.emplace(pin_name, bf.get());
1285 if (!pin.x_function.empty())
1287 if (
auto function = prepare_pin_function(cell.buses, pin.x_function); !
function.empty())
1289 for (
const auto& pin_name : pin.pin_names)
1294 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing undefined function from string");
1296 res.emplace(pin_name +
"_undefined", bf.get());
1301 if (!pin.z_function.empty())
1303 if (
auto function = prepare_pin_function(cell.buses, pin.z_function); !
function.empty())
1305 for (
const auto& pin_name : pin.pin_names)
1310 return ERR_APPEND(bf.get_error(),
"could not construct gate type '" + cell.name +
"': failed parsing tristate function from string");
1312 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