26 m_attribute_buffer.clear();
27 m_attribute_types.clear();
31 ifs.open(file_path.string(), std::ifstream::in);
34 return ERR(
"unable to open VHDL file '" + file_path.string() +
"'");
46 if (
const auto res = parse_tokens(); res.is_error())
48 return ERR_APPEND(res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"'");
53 if (e.line_number != (
u32)-1)
55 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': " + core_strings::to<std::string>(e.message) +
" near line " + std::to_string(e.line_number));
59 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': " + core_strings::to<std::string>(e.message));
63 if (m_entities.empty())
65 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': it does not contain any entities");
69 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
72 for (
const auto& port : vhdl_entity->m_ports)
74 if (!port->m_ranges.empty())
76 port->m_expanded_identifiers = expand_ranges(port->m_identifier, port->m_ranges);
77 vhdl_entity->m_expanded_port_identifiers.insert(port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
81 port->m_expanded_identifiers = {port->m_identifier};
82 vhdl_entity->m_expanded_port_identifiers.insert(port->m_identifier);
87 for (
auto& signal : vhdl_entity->m_signals)
89 if (!signal->m_ranges.empty())
91 signal->m_expanded_names = expand_ranges(signal->m_name, signal->m_ranges);
95 signal->m_expanded_names = std::vector<ci_string>({signal->m_name});
100 for (
auto& assignment : vhdl_entity->m_assignments)
102 auto left_res = expand_assignment_expression(vhdl_entity, assignment.m_variable);
103 if (left_res.is_error())
105 return ERR_APPEND(left_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand signal assignment");
107 const std::vector<ci_string> left_signals = left_res.get();
109 auto right_res = expand_assignment_expression(vhdl_entity, assignment.m_assignment);
110 if (right_res.is_error())
112 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand signal assignment");
114 const std::vector<ci_string> right_signals = right_res.get();
116 u32 left_size = left_signals.size();
117 u32 right_size = right_signals.size();
118 if (left_signals.empty() || right_signals.empty())
120 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': failed to expand assignments within entity '" + core_strings::to<std::string>(entity_name) +
"'");
122 else if (left_size != right_size)
124 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': assignment width mismatch within entity '" + core_strings::to<std::string>(entity_name) +
"'");
128 for (
u32 i = 0; i < right_size; i++)
130 vhdl_entity->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i), right_signals.at(i)));
137 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
139 for (
auto& instance : vhdl_entity->m_instances)
141 if (
auto entity_it = m_entities_by_name.find(instance->m_type); entity_it != m_entities_by_name.end())
143 instance->m_is_entity =
true;
145 if (!instance->m_port_assignments.empty())
148 if (instance->m_port_assignments.front().m_port.has_value())
150 for (
const auto& port_assignment : instance->m_port_assignments)
152 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
153 if (right_res.is_error())
155 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
157 const std::vector<ci_string> right_port = right_res.get();
158 if (!right_port.empty())
160 std::vector<ci_string> left_port;
161 if (
const identifier_t*
identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value()));
identifier !=
nullptr)
163 if (
const auto it = entity_it->second->m_ports_by_identifier.find(*
identifier); it != entity_it->second->m_ports_by_identifier.end())
165 left_port = it->second->m_expanded_identifiers;
169 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to assign signal to port '" + core_strings::to<std::string>(*
identifier)
170 +
"' as it is not a port of entity '" + core_strings::to<std::string>(entity_it->first) +
"'");
173 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier !=
nullptr)
175 left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
179 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
182 if (left_port.empty())
184 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
187 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
189 for (
u32 i = 0; i < max_size; i++)
191 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
199 std::vector<ci_string> ports;
200 for (
const auto& port : m_entities_by_name.at(instance->m_type)->m_ports)
202 ports.insert(ports.end(), port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
205 auto port_it = ports.begin();
207 for (
const auto& port_assignment : instance->m_port_assignments)
209 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
210 if (right_res.is_error())
212 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
214 const std::vector<ci_string> right_port = right_res.get();
215 if (!right_port.empty())
217 std::vector<ci_string> left_port;
219 for (
u32 i = 0; i < right_port.size() && port_it != ports.end(); i++)
221 left_port.push_back(*port_it++);
224 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
226 for (
u32 i = 0; i < max_size; i++)
228 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
245 m_netlist = result.get();
246 if (m_netlist ==
nullptr)
248 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create empty netlist");
251 m_gate_types.clear();
252 m_gnd_gate_types.clear();
253 m_vcc_gate_types.clear();
254 m_instance_name_occurrences.clear();
255 m_signal_name_occurrences.clear();
256 m_net_by_name.clear();
257 m_nets_to_merge.clear();
258 m_module_ports.clear();
259 m_module_port_by_net.clear();
260 for (
const auto& vhdl_entity : m_entities)
262 for (
const auto& instance : vhdl_entity->m_instances)
264 if (!instance->m_is_entity)
266 instance->m_expanded_port_assignments.clear();
274 m_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
278 m_gnd_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
282 m_vcc_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
287 if (m_zero_net ==
nullptr)
289 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create zero net");
291 m_net_by_name[core_strings::to<ci_string>(m_zero_net->
get_name())] = m_zero_net;
294 if (m_one_net ==
nullptr)
296 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create one net");
298 m_net_by_name[core_strings::to<ci_string>(m_one_net->
get_name())] = m_one_net;
301 std::map<ci_string, u32> entity_name_to_refereneces;
302 for (
const auto& [_name, vhdl_entity] : m_entities_by_name)
304 for (
const auto& instance : vhdl_entity->m_instances)
306 if (
const auto it = m_entities_by_name.find(instance->m_type); it != m_entities_by_name.end())
308 entity_name_to_refereneces[it->first]++;
313 std::vector<ci_string> top_module_candidates;
314 for (
const auto& [
name, _entity] : m_entities_by_name)
316 if (entity_name_to_refereneces.find(
name) == entity_name_to_refereneces.end())
318 top_module_candidates.push_back(
name);
322 if (top_module_candidates.empty())
324 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': unable to find any top module candidates");
327 if (top_module_candidates.size() > 1)
329 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': found multiple entities as candidates for the top module");
333 VhdlEntity* top_entity = m_entities_by_name.at(top_module_candidates.front());
335 if (
const auto res = construct_netlist(top_entity); res.is_error())
337 return ERR_APPEND(res.get_error(),
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"'");
345 GateType* gnd_type = m_gnd_gate_types.begin()->second;
351 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark GND gate");
356 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to GND gate");
370 GateType* vcc_type = m_vcc_gate_types.begin()->second;
376 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark VCC gate");
381 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to VCC gate");
391 std::queue<Net*> nets_to_be_deleted;
395 const u32 num_of_sources =
net->get_num_of_sources();
396 const u32 num_of_destinations =
net->get_num_of_destinations();
397 const bool no_source = num_of_sources == 0 && !(
net->is_global_input_net() && num_of_destinations != 0);
398 const bool no_destination = num_of_destinations == 0 && !(
net->is_global_output_net() && num_of_sources != 0);
399 if (no_source && no_destination)
405 while (!nets_to_be_deleted.empty())
407 Net*
net = nets_to_be_deleted.front();
408 nets_to_be_deleted.pop();
414 return OK(std::move(result));
421 void VHDLParser::tokenize()
423 std::vector<Token<core_strings::CaseInsensitiveString>> parsed_tokens;
424 const std::string delimiters =
",(): ;=><&";
429 bool in_string =
false;
430 bool escaped =
false;
432 while (std::getline(m_fs, line))
435 if (line.find(
"--") != std::string::npos)
437 line = line.substr(0, line.find(
"--"));
441 if (in_string ==
false && c ==
'\\')
446 else if (escaped && std::isspace(c))
451 else if (!escaped && c ==
'"')
453 in_string = !in_string;
456 if (delimiters.find(c) == std::string::npos || escaped || in_string)
462 if (!current_token.empty())
464 if (parsed_tokens.size() > 1 &&
utils::is_digits(parsed_tokens.at(parsed_tokens.size() - 2).string) && parsed_tokens.at(parsed_tokens.size() - 1) ==
"."
467 parsed_tokens.pop_back();
468 parsed_tokens.back() +=
"." + current_token;
472 parsed_tokens.emplace_back(line_number, current_token);
474 current_token.clear();
477 if (!parsed_tokens.empty())
479 if (c ==
'=' && parsed_tokens.back() ==
"<")
481 parsed_tokens.back() =
"<=";
484 else if (c ==
'=' && parsed_tokens.back() ==
":")
486 parsed_tokens.back() =
":=";
489 else if (c ==
'>' && parsed_tokens.back() ==
"=")
491 parsed_tokens.back() =
"=>";
496 if (!std::isspace(c))
502 if (!current_token.empty())
504 parsed_tokens.emplace_back(line_number, current_token);
505 current_token.clear();
508 m_token_stream = TokenStream(parsed_tokens, {
"("}, {
")"});
511 Result<std::monostate> VHDLParser::parse_tokens()
515 if (m_token_stream.
peek() ==
"library" || m_token_stream.
peek() ==
"use")
519 else if (m_token_stream.
peek() ==
"entity")
521 if (
const auto res = parse_entity(); res.is_error())
523 return ERR_APPEND(res.get_error(),
"could not parse tokens");
526 else if (m_token_stream.
peek() ==
"architecture")
528 if (
const auto res = parse_architecture(); res.is_error())
530 return ERR_APPEND(res.get_error(),
"could not parse tokens");
535 return ERR(
"could not parse tokens: unexpected token '" + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' in global scope (line "
536 + std::to_string(m_token_stream.
peek().number) +
")");
543 void VHDLParser::parse_library()
545 if (m_token_stream.
peek() ==
"use")
547 m_token_stream.
consume(
"use",
true);
548 auto lib = m_token_stream.
consume().string;
549 m_token_stream.
consume(
";",
true);
552 lib =
utils::trim(lib.substr(0, lib.rfind(
".") + 1));
553 m_libraries.insert(lib);
558 m_token_stream.
consume(
";",
true);
562 Result<std::monostate> VHDLParser::parse_entity()
564 m_token_stream.
consume(
"entity",
true);
565 const u32 line_number = m_token_stream.
peek().number;
566 const ci_string entity_name = m_token_stream.
consume().string;
569 if (
const auto it = m_entities_by_name.find(entity_name); it != m_entities_by_name.end())
571 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"' (line " + std::to_string(line_number) +
"): an entity with name '"
572 + core_strings::to<std::string>(entity_name) +
"' does already exist (line " + std::to_string(it->second->m_line_number) +
")");
575 m_token_stream.
consume(
"is",
true);
576 auto vhdl_entity = std::make_unique<VhdlEntity>();
577 VhdlEntity* vhdl_entity_raw = vhdl_entity.get();
578 vhdl_entity_raw->m_line_number = line_number;
579 vhdl_entity_raw->m_name = entity_name;
581 m_attribute_buffer.clear();
583 Token<ci_string> next_token = m_token_stream.
peek();
584 while (next_token !=
"end")
586 if (next_token ==
"generic")
589 m_token_stream.
consume(
";",
true);
591 else if (next_token ==
"port")
593 if (
const auto res = parse_port_definitons(vhdl_entity_raw); res.is_error())
596 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse port definition (line " + std::to_string(next_token.number) +
")");
599 else if (next_token ==
"attribute")
601 if (
const auto res = parse_attribute(); res.is_error())
604 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse attribute (line " + std::to_string(next_token.number) +
")");
609 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': unexpected token '" + core_strings::to<std::string>(next_token.string)
610 +
"' in entity definition (line " + std::to_string(next_token.number) +
")");
613 next_token = m_token_stream.
peek();
616 m_token_stream.
consume(
"end",
true);
618 m_token_stream.
consume(
";",
true);
621 m_entities.push_back(std::move(vhdl_entity));
622 m_entities_by_name[entity_name] = vhdl_entity_raw;
623 m_last_entity = entity_name;
628 Result<std::monostate> VHDLParser::parse_port_definitons(VhdlEntity* vhdl_entity)
631 m_token_stream.
consume(
"port",
true);
632 m_token_stream.
consume(
"(",
true);
635 while (port_def_stream.remaining() > 0)
637 std::vector<core_strings::CaseInsensitiveString> port_names;
640 const auto line_number = port_def_stream.
peek().number;
645 port_names.push_back(port_def_stream.consume().string);
646 }
while (port_def_stream.consume(
",",
false));
648 port_def_stream.consume(
":",
true);
652 const ci_string direction_str = port_def_stream.consume().string;
653 if (direction_str ==
"in")
657 else if (direction_str ==
"out")
661 else if (direction_str ==
"inout")
667 return ERR(
"could not parse port definitions: invalid direction '" + core_strings::to<std::string>(direction_str) +
"' for port declaration (line " + std::to_string(line_number)
672 TokenStream<ci_string> port_stream = port_def_stream.extract_until(
";");
673 std::vector<std::vector<u32>> ranges;
674 if (
auto res = parse_signal_ranges(port_stream); res.is_error())
676 return ERR_APPEND(res.get_error(),
"could not parse port definitions: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
683 port_def_stream.consume(
";", port_def_stream.remaining() > 0);
685 for (
const ci_string& port_name : port_names)
687 auto port = std::make_unique<VhdlPort>();
688 port->m_identifier = port_name;
690 port->m_ranges = ranges;
691 vhdl_entity->m_ports_by_identifier[port->m_identifier] = port.get();
692 vhdl_entity->m_ports.push_back(std::move(port));
694 if (vhdl_entity->m_signals_by_name.find(port_name) == vhdl_entity->m_signals_by_name.end())
696 auto signal = std::make_unique<VhdlSignal>();
697 signal->m_name = port_name;
700 signal->m_ranges = ranges;
702 vhdl_entity->m_signals_by_name[port_name] = signal.get();
703 vhdl_entity->m_signals.push_back(std::move(signal));
708 m_token_stream.
consume(
")",
true);
709 m_token_stream.
consume(
";",
true);
714 Result<std::monostate> VHDLParser::parse_attribute()
716 const u32 line_number = m_token_stream.
peek().number;
718 m_token_stream.
consume(
"attribute",
true);
719 const ci_string attribute_name = m_token_stream.
consume().string;
721 if (m_token_stream.
peek() ==
":")
723 m_token_stream.
consume(
":",
true);
724 m_attribute_types[attribute_name] = m_token_stream.
join_until(
";",
" ");
725 m_token_stream.
consume(
";",
true);
727 else if (m_token_stream.
peek() ==
"of" && m_token_stream.
peek(2) ==
":")
729 AttributeTarget target_class;
730 m_token_stream.
consume(
"of",
true);
731 const ci_string attribute_target = m_token_stream.
consume().string;
732 m_token_stream.
consume(
":",
true);
733 const ci_string attribute_class = m_token_stream.
consume().string;
734 m_token_stream.
consume(
"is",
true);
735 ci_string attribute_value = m_token_stream.
join_until(
";",
" ").string;
736 m_token_stream.
consume(
";",
true);
737 ci_string attribute_type;
739 if (attribute_value[0] ==
'\"' && attribute_value.back() ==
'\"')
741 attribute_value = attribute_value.substr(1, attribute_value.size() - 2);
744 if (
const auto type_it = m_attribute_types.find(attribute_name); type_it == m_attribute_types.end())
746 log_warning(
"vhdl_parser",
"attribute {} has unknown base type in line {}.", attribute_name, line_number);
747 attribute_type =
"unknown";
751 attribute_type = type_it->second;
754 if (attribute_class ==
"entity")
756 target_class = AttributeTarget::ENTITY;
758 else if (attribute_class ==
"label")
760 target_class = AttributeTarget::INSTANCE;
762 else if (attribute_class ==
"signal")
764 target_class = AttributeTarget::SIGNAL;
768 log_warning(
"vhdl_parser",
"unsupported attribute class '{}' in line {}, ignoring attribute.", attribute_class, line_number);
772 VhdlDataEntry attribute;
773 attribute.m_name = core_strings::to<std::string>(attribute_name);
774 attribute.m_type = core_strings::to<std::string>(attribute_type);
775 attribute.m_value = core_strings::to<std::string>(attribute_value);
776 m_attribute_buffer[target_class].emplace(attribute_target, attribute);
780 return ERR(
"could not parse attribute: malformed attribute definition (line " + std::to_string(line_number) +
")");
786 Result<std::monostate> VHDLParser::parse_architecture()
788 m_token_stream.
consume(
"architecture",
true);
790 m_token_stream.
consume(
"of",
true);
792 u32 line_number = m_token_stream.
peek().number;
793 const auto entity_name_token = m_token_stream.
consume();
795 if (
const auto it = m_entities_by_name.find(entity_name_token.string); it == m_entities_by_name.end())
797 return ERR(
"could not parse architecture: architecture refers to non-existent entity '" + core_strings::to<std::string>(entity_name_token.string) +
"' (line "
798 + std::to_string(entity_name_token.number) +
")");
802 VhdlEntity* vhdl_entity = it->second;
804 m_token_stream.
consume(
"is",
true);
806 if (
const auto res = parse_architecture_header(vhdl_entity); res.is_error())
808 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture header (line " + std::to_string(line_number) +
")");
810 if (
const auto res = parse_architecture_body(vhdl_entity); res.is_error())
812 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture body (line " + std::to_string(line_number) +
")");
814 if (
const auto res = assign_attributes(vhdl_entity); res.is_error())
816 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to assign attributes (line " + std::to_string(line_number) +
")");
823 Result<std::monostate> VHDLParser::parse_architecture_header(VhdlEntity* vhdl_entity)
825 auto next_token = m_token_stream.
peek();
826 while (next_token !=
"begin")
828 if (next_token ==
"signal")
830 if (
const auto res = parse_signal_definition(vhdl_entity); res.is_error())
832 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse signal definition (line " + std::to_string(next_token.number) +
")");
835 else if (next_token ==
"component")
838 m_token_stream.
consume(
"component",
true);
839 const ci_string component_name = m_token_stream.
consume().string;
841 m_token_stream.
consume(
"end",
true);
842 m_token_stream.
consume(
"component",
true);
843 if (m_token_stream.
peek() !=
";")
845 m_token_stream.
consume(component_name,
true);
847 m_token_stream.
consume(
";",
true);
849 else if (next_token ==
"attribute")
851 if (
const auto res = parse_attribute(); res.is_error())
853 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse attribute (line " + std::to_string(next_token.number) +
")");
858 return ERR(
"could not parse architecture header: unexpected token '" + core_strings::to<std::string>(next_token.string) +
"' (line " + std::to_string(next_token.number) +
")");
861 next_token = m_token_stream.
peek();
867 Result<std::monostate> VHDLParser::parse_signal_definition(VhdlEntity* vhdl_entity)
869 m_token_stream.
consume(
"signal",
true);
870 u32 line_number = m_token_stream.
peek().number;
873 std::vector<ci_string> signal_names;
876 signal_names.push_back(m_token_stream.
consume().string);
877 }
while (m_token_stream.
consume(
",",
false));
879 m_token_stream.
consume(
":",
true);
882 TokenStream<ci_string> signal_stream = m_token_stream.
extract_until(
";");
883 std::vector<std::vector<u32>> ranges;
884 if (
auto res = parse_signal_ranges(signal_stream); res.is_error())
886 return ERR_APPEND(res.get_error(),
"could not parse signal definition: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
893 m_token_stream.
consume(
";",
true);
895 for (
const auto& signal_name : signal_names)
897 if (vhdl_entity->m_signals_by_name.find(signal_name) == vhdl_entity->m_signals_by_name.end())
899 auto signal = std::make_unique<VhdlSignal>();
900 signal->m_name = signal_name;
901 signal->m_ranges = ranges;
902 vhdl_entity->m_signals_by_name[signal_name] = signal.get();
903 vhdl_entity->m_signals.push_back(std::move(signal));
910 Result<std::monostate> VHDLParser::parse_architecture_body(VhdlEntity* vhdl_entity)
912 m_token_stream.
consume(
"begin",
true);
913 auto next_token = m_token_stream.
peek();
915 while (next_token !=
"end")
918 if (m_token_stream.
peek(1) ==
":")
920 if (
const auto res = parse_instance(vhdl_entity); res.is_error())
923 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse instance (line "
924 + std::to_string(next_token.number) +
")");
930 if (
const auto res = parse_assignment(vhdl_entity); res.is_error())
933 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse assignment (line "
934 + std::to_string(next_token.number) +
")");
939 return ERR(
"could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unexpected token '"
940 + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' (line " + std::to_string(next_token.number) +
")");
943 next_token = m_token_stream.
peek();
946 m_token_stream.
consume(
"end",
true);
948 m_token_stream.
consume(
";",
true);
953 Result<std::monostate> VHDLParser::parse_assignment(VhdlEntity* vhdl_entity)
955 u32 line_number = m_token_stream.
peek().number;
956 VhdlAssignment assignment;
958 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
"<=")); res.is_error())
960 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
964 assignment.m_variable = res.get();
966 m_token_stream.
consume(
"<=",
true);
967 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
";")); res.is_error())
969 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
973 assignment.m_assignment = res.get();
975 m_token_stream.
consume(
";",
true);
977 vhdl_entity->m_assignments.push_back(std::move(assignment));
981 Result<std::monostate> VHDLParser::parse_instance(VhdlEntity* vhdl_entity)
983 auto instance = std::make_unique<VhdlInstance>();
984 u32 line_number = m_token_stream.
peek().number;
985 instance->m_name = m_token_stream.
consume();
986 m_token_stream.
consume(
":",
true);
989 if (m_token_stream.
peek() ==
"entity")
991 m_token_stream.
consume(
"entity",
true);
992 instance->m_type = m_token_stream.
consume();
993 if (
const size_t pos = instance->m_type.find(
'.'); pos != std::string::npos)
995 instance->m_type = instance->m_type.substr(pos + 1);
997 if (m_entities_by_name.find(instance->m_type) == m_entities_by_name.end())
999 return ERR(
"could not parse instance '" + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type) +
"': entity with name '"
1000 + core_strings::to<std::string>(instance->m_type) +
"' does not exist (line " + std::to_string(line_number) +
")");
1003 else if (m_token_stream.
peek() ==
"component")
1005 m_token_stream.
consume(
"component",
true);
1006 instance->m_type = m_token_stream.
consume();
1010 instance->m_type = m_token_stream.
consume();
1014 for (
const auto& lib : m_libraries)
1023 if (!prefix.empty())
1025 instance->m_type = instance->m_type.substr(prefix.size());
1029 if (m_token_stream.
consume(
"generic"))
1031 line_number = m_token_stream.
peek().number;
1032 if (
const auto res = parse_generic_assign(instance.get()); res.is_error())
1035 "could not parse instance '" + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type)
1036 +
"': unable to parse generic assignment (line " + std::to_string(line_number) +
")");
1040 if (m_token_stream.
peek() ==
"port")
1042 if (
const auto res = parse_port_assign(instance.get()); res.is_error())
1045 "could not parse instance '" + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type)
1046 +
"': unable to parse port assignment (line " + std::to_string(line_number) +
")");
1050 vhdl_entity->m_instances_by_name[instance->m_name] = instance.get();
1051 vhdl_entity->m_instances.push_back(std::move(instance));
1053 m_token_stream.
consume(
";",
true);
1058 Result<std::monostate> VHDLParser::parse_port_assign(VhdlInstance* instance)
1060 u32 line_number = m_token_stream.
peek().number;
1061 m_token_stream.
consume(
"port",
true);
1062 m_token_stream.
consume(
"map",
true);
1063 m_token_stream.
consume(
"(",
true);
1064 TokenStream<ci_string> port_stream = m_token_stream.
extract_until(
")");
1065 m_token_stream.
consume(
")",
true);
1069 while (port_stream.remaining() > 0)
1071 TokenStream<ci_string> left_stream = port_stream.extract_until(
"=>");
1072 port_stream.consume(
"=>",
true);
1073 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1074 port_stream.consume(
",", port_stream.remaining() > 0);
1076 if (!right_stream.consume(
"open"))
1078 VhdlPortAssignment port_assignment;
1080 if (
auto res = parse_assignment_expression(std::move(left_stream)); res.is_error())
1082 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse port (line " + std::to_string(line_number) +
")");
1087 port_assignment.m_port = res.get().front();
1090 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1092 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1096 port_assignment.m_assignment = res.get();
1099 instance->m_port_assignments.push_back(std::move(port_assignment));
1105 while (port_stream.remaining() > 0)
1107 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1108 port_stream.consume(
",", port_stream.remaining() > 0);
1110 if (!right_stream.consume(
"open"))
1112 VhdlPortAssignment port_assignment;
1114 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1116 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1120 port_assignment.m_assignment = res.get();
1123 instance->m_port_assignments.push_back(std::move(port_assignment));
1127 VhdlPortAssignment port_assignment;
1128 port_assignment.m_assignment.push_back(
"");
1129 instance->m_port_assignments.push_back(std::move(port_assignment));
1137 Result<std::monostate> VHDLParser::parse_generic_assign(VhdlInstance* instance)
1139 m_token_stream.
consume(
"map",
true);
1140 m_token_stream.
consume(
"(",
true);
1141 TokenStream<ci_string> generic_stream = m_token_stream.
extract_until(
")");
1142 m_token_stream.
consume(
")",
true);
1144 while (generic_stream.remaining() > 0)
1146 VhdlDataEntry
generic;
1148 generic.m_line_number = generic_stream.peek().number;
1149 generic.m_name = core_strings::to<std::string>(generic_stream.join_until(
"=>",
"").string);
1150 generic_stream.consume(
"=>",
true);
1151 const auto rhs = generic_stream.join_until(
",",
"");
1152 generic_stream.consume(
",", generic_stream.remaining() > 0);
1155 if ((rhs ==
"true") || (rhs ==
"false"))
1157 generic.m_value = core_strings::to<std::string>(rhs.string);
1158 generic.m_type =
"boolean";
1162 generic.m_value = core_strings::to<std::string>(rhs.string);
1163 generic.m_type =
"integer";
1167 generic.m_value = core_strings::to<std::string>(rhs.string);
1168 generic.m_type =
"floating_point";
1173 generic.m_value = core_strings::to<std::string>(rhs.string);
1174 generic.m_type =
"time";
1176 else if (rhs.string.at(0) ==
'\"' && rhs.string.back() ==
'\"')
1178 generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, rhs.string.size() - 2));
1179 generic.m_type =
"string";
1181 else if (rhs.string.at(0) ==
'\'' && rhs.string.at(2) ==
'\'')
1183 generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, 1));
1184 generic.m_type =
"bit_value";
1186 else if (rhs.string.at(1) ==
'\"' && rhs.string.back() ==
'\"')
1188 if (
auto res = get_hex_from_literal(rhs); res.is_error())
1190 return ERR_APPEND(res.get_error(),
"could not parse generic assignment: unable to translate token to hexadecimal string");
1194 generic.m_value = core_strings::to<std::string>(res.get());
1195 generic.m_type =
"bit_vector";
1200 return ERR(
"could not parse generic assignment: unable to identify data type of generic map value '" + core_strings::to<std::string>(rhs.string) +
"' in instance '"
1201 + core_strings::to<std::string>(instance->m_name) +
"' (line " + std::to_string(
generic.m_line_number) +
")");
1204 instance->m_generics.push_back(
generic);
1210 Result<std::monostate> VHDLParser::assign_attributes(VhdlEntity* vhdl_entity)
1212 for (
const auto& [target_class, attributes] : m_attribute_buffer)
1215 if (target_class == AttributeTarget::ENTITY)
1217 for (
const auto& [target, attribute] : attributes)
1219 if (vhdl_entity->m_name != target)
1221 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1222 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1226 vhdl_entity->m_attributes.push_back(attribute);
1231 else if (target_class == AttributeTarget::INSTANCE)
1233 for (
const auto& [target, attribute] : attributes)
1235 if (
const auto instance_it = vhdl_entity->m_instances_by_name.find(target); instance_it == vhdl_entity->m_instances_by_name.end())
1237 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1238 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1242 instance_it->second->m_attributes.push_back(attribute);
1247 else if (target_class == AttributeTarget::SIGNAL)
1249 for (
const auto& [target, attribute] : attributes)
1251 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(target); signal_it != vhdl_entity->m_signals_by_name.end())
1253 signal_it->second->m_attributes.push_back(attribute);
1257 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1258 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1271 Result<std::monostate> VHDLParser::construct_netlist(VhdlEntity* top_entity)
1273 m_netlist->
set_design_name(core_strings::to<std::string>(top_entity->m_name));
1276 std::unordered_map<ci_string, u32> instantiation_count;
1279 std::queue<VhdlEntity*> q;
1284 VhdlEntity* entity = q.front();
1287 instantiation_count[entity->m_name]++;
1290 for (
const auto& s : entity->m_signals)
1292 std::vector<ci_string> expanded_names;
1293 expand_ranges_recursively(expanded_names, s->m_name, s->m_ranges, 0);
1294 for (
const auto& net_name : expanded_names)
1296 m_signal_name_occurrences[net_name]++;
1300 for (
const auto& instance : entity->m_instances)
1302 m_instance_name_occurrences[instance->m_name]++;
1305 if (
const auto it = m_entities_by_name.find(instance->m_type); it != m_entities_by_name.end())
1312 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
1315 if (instantiation_count[entity_name] == 0)
1317 log_warning(
"vhdl_parser",
"entity '{}' has been defined in the netlist but is not instantiated.", entity_name);
1322 for (
const auto& instance : vhdl_entity->m_instances)
1324 if (
const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1326 if (!instance->m_port_assignments.empty())
1329 if (instance->m_port_assignments.front().m_port.has_value())
1332 std::unordered_map<ci_string, std::vector<ci_string>> pin_groups;
1333 for (
const auto pin_group : gate_type_it->second->get_pin_groups())
1335 const auto pins = pin_group->get_pins();
1336 for (
auto it =
pins.rbegin(); it !=
pins.rend(); it++)
1338 const auto* pin = *it;
1339 pin_groups[core_strings::to<ci_string>(pin_group->get_name())].push_back(core_strings::to<ci_string>(pin->get_name()));
1343 for (
const auto& port_assignment : instance->m_port_assignments)
1345 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1346 if (right_res.is_error())
1348 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1350 auto right_port = right_res.get();
1352 if (!right_port.empty())
1354 std::vector<ci_string> left_port;
1356 if (
const identifier_t*
identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value()));
identifier !=
nullptr)
1358 if (
const auto group_it = pin_groups.find(*
identifier); group_it != pin_groups.end())
1360 left_port = group_it->second;
1367 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier !=
nullptr)
1369 left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
1373 return ERR(
"could not construct netlist: unable to expand gate port assignment");
1376 if (right_port.size() != left_port.size())
1378 return ERR(
"could not construct netlist: pin assignment width mismatch at instance '" + core_strings::to<std::string>(instance->m_name) +
"' of gate type '"
1379 + core_strings::to<std::string>(instance->m_type) +
"' within entity '" + core_strings::to<std::string>(entity_name) +
"'");
1382 for (
u32 i = 0; i < left_port.size(); i++)
1384 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1393 std::vector<ci_string>
pins;
1394 for (
const auto pin : gate_type_it->second->get_pins())
1396 pins.push_back(core_strings::to<ci_string>(pin->get_name()));
1398 auto pin_it =
pins.begin();
1400 for (
const auto& port_assignment : instance->m_port_assignments)
1402 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1403 if (right_res.is_error())
1405 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1407 auto right_port = right_res.get();
1409 if (!right_port.empty())
1411 std::vector<ci_string> left_port;
1413 for (
u32 i = 0; i < right_port.size() && pin_it !=
pins.end(); i++)
1415 left_port.push_back(*pin_it++);
1418 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1420 for (
u32 i = 0; i < max_size; i++)
1422 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1433 std::unordered_map<ci_string, ci_string> top_assignments;
1434 for (
const auto& port : top_entity->m_ports)
1436 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1438 const auto signal_name = get_unique_alias(
"", expanded_port_identifier +
"__GLOBAL_IO__", m_signal_name_occurrences);
1440 Net* global_port_net = m_netlist->
create_net(core_strings::to<std::string>(signal_name));
1441 if (global_port_net ==
nullptr)
1443 return ERR(
"could not construct netlist: failed to create global I/O net '" + core_strings::to<std::string>(signal_name) +
"'");
1446 m_net_by_name[signal_name] = global_port_net;
1449 top_assignments[expanded_port_identifier] = signal_name;
1453 if (!global_port_net->mark_global_input_net())
1455 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global input");
1461 if (!global_port_net->mark_global_output_net())
1463 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global output");
1469 if (
const auto res = instantiate_entity(
"top_module", top_entity,
nullptr, top_assignments); res.is_error())
1471 return ERR_APPEND(res.get_error(),
"could not construct netlist: unable to instantiate top module");
1475 std::unordered_map<ci_string, ci_string> merged_nets;
1476 std::unordered_map<ci_string, std::vector<ci_string>> master_to_slaves;
1478 for (
auto& [master, slave] : m_nets_to_merge)
1483 if (
const auto master_it = merged_nets.find(master); master_it != merged_nets.end())
1485 master = master_it->second;
1496 if (
const auto slave_it = merged_nets.find(slave); slave_it != merged_nets.end())
1498 slave = slave_it->second;
1506 auto master_net = m_net_by_name.at(master);
1507 auto slave_net = m_net_by_name.at(slave);
1509 if (master_net == slave_net)
1513 else if (slave_net == m_zero_net || slave_net == m_one_net)
1515 auto* tmp_net = master_net;
1516 master_net = slave_net;
1517 slave_net = tmp_net;
1519 auto tmp_name = master;
1525 if (slave_net->is_global_input_net())
1527 master_net->mark_global_input_net();
1530 for (
auto src : slave_net->get_sources())
1532 Gate* src_gate = src->get_gate();
1533 GatePin* src_pin = src->get_pin();
1535 if (!slave_net->remove_source(src))
1537 return ERR(
"could not construct netlist: failed to remove source from net '" + slave_net->get_name() +
"' with ID " + std::to_string(slave_net->get_id()));
1540 if (!master_net->is_a_source(src_gate, src_pin))
1542 if (!master_net->add_source(src_gate, src_pin))
1544 return ERR(
"could not construct netlist: failed to add source to net '" + master_net->get_name() +
"' with ID " + std::to_string(master_net->get_id()));
1550 if (slave_net->is_global_output_net())
1552 master_net->mark_global_output_net();
1555 for (
auto dst : slave_net->get_destinations())
1557 Gate* dst_gate = dst->get_gate();
1558 GatePin* dst_pin = dst->get_pin();
1560 if (!slave_net->remove_destination(dst))
1562 return ERR(
"could not construct netlist: failed to remove destination from net '" + slave_net->get_name() +
"' with ID " + std::to_string(slave_net->get_id()));
1565 if (!master_net->is_a_destination(dst_gate, dst_pin))
1567 if (!master_net->add_destination(dst_gate, dst_pin))
1569 return ERR(
"could not construct netlist: failed to add destination to net '" + master_net->get_name() +
"' with ID " + std::to_string(master_net->get_id()));
1575 for (
const auto& [
identifier, content] : slave_net->get_data_map())
1577 if (!master_net->set_data(std::get<0>(
identifier), std::get<1>(
identifier), std::get<0>(content), std::get<1>(content)))
1580 "unable to transfer data from slave net '{}' with ID {} to master net '{}' with ID {}.",
1581 slave_net->get_name(),
1582 slave_net->get_id(),
1583 master_net->get_name(),
1584 master_net->get_id());
1589 if (
const auto it = m_module_port_by_net.find(slave_net); it != m_module_port_by_net.end())
1593 std::get<1>(m_module_ports.at(
module).at(
index)) = master_net;
1595 m_module_port_by_net[master_net].insert(m_module_port_by_net[master_net].end(), it->second.begin(), it->second.end());
1596 m_module_port_by_net.erase(it);
1600 m_net_by_name.erase(slave);
1601 merged_nets[slave] = master;
1602 master_to_slaves[master].push_back(slave);
1606 for (
auto& master_net : m_netlist->
get_nets())
1608 const auto master_name = master_net->get_name();
1610 if (
const auto m2s_it = master_to_slaves.find(core_strings::to<ci_string>(master_name)); m2s_it != master_to_slaves.end())
1612 std::vector<std::vector<ci_string>> merged_slaves;
1613 auto current_slaves = m2s_it->second;
1615 while (!current_slaves.empty())
1617 std::vector<ci_string> next_slaves;
1618 for (
const auto& s : current_slaves)
1620 if (
const auto m2s_inner_it = master_to_slaves.find(s); m2s_inner_it != master_to_slaves.end())
1622 next_slaves.insert(next_slaves.end(), m2s_inner_it->second.begin(), m2s_inner_it->second.end());
1626 merged_slaves.push_back(current_slaves);
1627 current_slaves = next_slaves;
1628 next_slaves.clear();
1633 ci_string merged_str =
"";
1634 bool has_merged_nets =
false;
1635 for (
const auto& vec : merged_slaves)
1639 has_merged_nets =
true;
1642 ci_string s = vec.empty() ?
"" : vec.front();
1643 for (
u32 idx = 1; idx < vec.size(); idx++)
1645 s += ci_string(
", ") + vec.at(idx);
1648 merged_str +=
"[" + s +
"], ";
1650 merged_str = merged_str.substr(0, merged_str.size() - 2);
1652 if (has_merged_nets)
1654 master_net->set_data(
"parser_annotation",
"merged_nets",
"string",
"[" + core_strings::to<std::string>(merged_str) +
"]");
1666 for (
const auto& [
module, ports] : m_module_ports)
1668 for (
const auto& [port_name, port_net] : ports)
1679 "could not construct netlist: failed to create pin '" + port_name +
"' at net '" + port_net->get_name() +
"' with ID " + std::to_string(port_net->get_id())
1690 if ((
module->
get_pin_by_net(m_one_net) ==
nullptr) && (input_nets.find(m_one_net) != input_nets.end() || output_nets.find(m_one_net) != input_nets.end()))
1695 "could not construct netlist: failed to create pin '1' at net '" + m_one_net->
get_name() +
"' with ID " + std::to_string(m_one_net->
get_id()) +
"within module '"
1700 if ((
module->
get_pin_by_net(m_zero_net) ==
nullptr) && (input_nets.find(m_zero_net) != input_nets.end() || output_nets.find(m_zero_net) != input_nets.end()))
1705 "could not construct netlist: failed to create pin '0' at net '" + m_zero_net->
get_name() +
"' with ID " + std::to_string(m_zero_net->
get_id())
1716 VHDLParser::instantiate_entity(
const ci_string& instance_identifier, VhdlEntity* vhdl_entity, Module* parent,
const std::unordered_map<ci_string, ci_string>& parent_module_assignments)
1718 std::unordered_map<ci_string, ci_string> signal_alias;
1719 std::unordered_map<ci_string, ci_string> instance_alias;
1723 const std::string parent_name = parent == (
nullptr) ?
"" : parent->get_name();
1724 instance_alias[instance_identifier] = get_unique_alias(core_strings::to<ci_string>(parent_name), instance_identifier, m_instance_name_occurrences);
1728 if (parent ==
nullptr)
1731 module->
set_name(core_strings::to<std::string>(instance_alias.at(instance_identifier)));
1735 module = m_netlist->
create_module(core_strings::to<std::string>(instance_alias.at(instance_identifier)), parent);
1738 ci_string instance_type = vhdl_entity->m_name;
1741 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1742 +
"': failed to create module");
1747 for (
const VhdlDataEntry& attribute : vhdl_entity->m_attributes)
1749 if (!
module->
set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1752 "could not set attribute '{} = {}' of type '{}' for instance '{}' type '{}'.",
1756 instance_identifier,
1762 for (
const auto& port : vhdl_entity->m_ports)
1764 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1766 if (
const auto it = parent_module_assignments.find(expanded_port_identifier); it != parent_module_assignments.end())
1768 Net* port_net = m_net_by_name.at(it->second);
1769 m_module_ports[
module].push_back(std::make_pair(core_strings::to<std::string>(expanded_port_identifier), port_net));
1770 m_module_port_by_net[port_net].push_back(std::make_pair(
module, m_module_ports[
module].
size() - 1));
1776 for (
const auto& signal : vhdl_entity->m_signals)
1778 for (
const auto& expanded_name : signal->m_expanded_names)
1780 signal_alias[expanded_name] = get_unique_alias(instance_alias[instance_identifier], expanded_name, m_signal_name_occurrences);
1783 Net* signal_net = m_netlist->
create_net(core_strings::to<std::string>(signal_alias.at(expanded_name)));
1784 if (signal_net ==
nullptr)
1786 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1787 +
"': failed to create net '" + core_strings::to<std::string>(expanded_name) +
"'");
1790 m_net_by_name[signal_alias.at(expanded_name)] = signal_net;
1793 for (
const VhdlDataEntry& attribute : signal->m_attributes)
1795 if (!signal_net->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1798 "could not set attribute ({} = {}) for net '{}' of instance '{}' of type '{}'.",
1802 instance_identifier,
1810 for (
const auto& [left_expanded_signal, right_expanded_signal] : vhdl_entity->m_expanded_assignments)
1812 ci_string a = left_expanded_signal;
1813 ci_string b = right_expanded_signal;
1815 if (
const auto alias_it = signal_alias.find(a); alias_it != signal_alias.end())
1817 a = alias_it->second;
1821 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1822 +
"': failed to find alias for net '" + core_strings::to<std::string>(a) +
"'");
1825 if (
const auto alias_it = signal_alias.find(b); alias_it != signal_alias.end())
1827 b = alias_it->second;
1829 else if (b ==
"'Z'" || b ==
"'X'")
1833 else if (b !=
"'0'" && b !=
"'1'")
1835 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1836 +
"': failed to find alias for net '" + core_strings::to<std::string>(b) +
"'");
1839 m_nets_to_merge.push_back(std::make_pair(a, b));
1843 for (
const auto& [port_expression, net_name] : parent_module_assignments)
1845 if (
const auto alias_it = signal_alias.find(port_expression); alias_it != signal_alias.end())
1847 const bool swap = net_name.find(
"__GLOBAL_IO__") == std::string::npos;
1848 m_nets_to_merge.push_back(swap ? std::make_pair(net_name, alias_it->second) : std::make_pair(alias_it->second, net_name));
1852 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1853 +
"': failed to find alias for net '" + core_strings::to<std::string>(port_expression) +
"'");
1858 for (
const auto& instance : vhdl_entity->m_instances)
1861 DataContainer* container =
nullptr;
1864 std::unordered_map<ci_string, ci_string> instance_assignments;
1867 if (
auto entity_it = m_entities_by_name.find(instance->m_type); entity_it != m_entities_by_name.end())
1870 for (
const auto& [port, assignment] : instance->m_expanded_port_assignments)
1872 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1874 instance_assignments[port] = alias_it->second;
1876 else if (assignment ==
"'0'" || assignment ==
"'1'")
1878 instance_assignments[port] = assignment;
1880 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
1886 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1887 +
"': port assignment '" + core_strings::to<std::string>(port) +
" = " + core_strings::to<std::string>(assignment) +
"' is invalid");
1891 if (
auto res = instantiate_entity(instance->m_name, entity_it->second,
module, instance_assignments); res.is_error())
1894 "could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1895 +
"': unable to create instance '" + core_strings::to<std::string>(instance->m_name) +
"' of type '"
1896 + core_strings::to<std::string>(entity_it->second->m_name) +
"'");
1900 container = res.get();
1904 else if (
const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1907 instance_alias[instance->m_name] = get_unique_alias(instance_alias[instance_identifier], instance->m_name, m_instance_name_occurrences);
1909 Gate* new_gate = m_netlist->
create_gate(gate_type_it->second, core_strings::to<std::string>(instance_alias.at(instance->m_name)));
1910 if (new_gate ==
nullptr)
1912 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1913 +
"': failed to create gate '" + core_strings::to<std::string>(instance->m_name) +
"'");
1921 container = new_gate;
1924 if (m_vcc_gate_types.find(instance->m_type) != m_vcc_gate_types.end() && !new_gate->mark_vcc_gate())
1926 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type) +
"': failed to mark '"
1927 + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type) +
"' as GND gate");
1929 if (m_gnd_gate_types.find(instance->m_type) != m_gnd_gate_types.end() && !new_gate->mark_gnd_gate())
1931 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type) +
"': failed to mark '"
1932 + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type) +
"' as VCC gate");
1936 std::unordered_map<ci_string, GatePin*> pin_names_map;
1937 for (
auto* pin : gate_type_it->second->get_pins())
1939 pin_names_map[core_strings::to<ci_string>(pin->get_name())] = pin;
1943 for (
const auto& [pin, assignment] : instance->m_expanded_port_assignments)
1947 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1949 signal = alias_it->second;
1951 else if (assignment ==
"'0'" || assignment ==
"'1'")
1953 signal = assignment;
1955 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
1961 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1962 +
"': failed to assign '" + core_strings::to<std::string>(assignment) +
"' to pin '" + core_strings::to<std::string>(pin) +
"' of gate '"
1963 + core_strings::to<std::string>(instance->m_name) +
"' of type '" + core_strings::to<std::string>(instance->m_type) +
"' as the assignment is invalid");
1967 if (
const auto net_it = m_net_by_name.find(signal); net_it == m_net_by_name.end())
1969 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1970 +
"': failed to assign signal'" + core_strings::to<std::string>(signal) +
"' to pin '" + core_strings::to<std::string>(pin)
1971 +
"' as the signal has not been declared");
1975 Net* current_net = net_it->second;
1978 bool is_input =
false;
1979 bool is_output =
false;
1981 if (
const auto it = pin_names_map.find(pin); it != pin_names_map.end())
1995 if (!is_input && !is_output)
1997 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1998 +
"': failed to assign net '" + core_strings::to<std::string>(signal) +
"' to pin '" + core_strings::to<std::string>(pin) +
"' as it is not a pin of gate '"
1999 + new_gate->get_name() +
"' of type '" + new_gate->get_type()->get_name() +
"'");
2002 if (is_output && !current_net->add_source(new_gate, core_strings::to<std::string>(pin)))
2004 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2005 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a source to gate '" + new_gate->get_name() +
"' via pin '"
2006 + core_strings::to<std::string>(pin) +
"'");
2009 if (is_input && !current_net->add_destination(new_gate, core_strings::to<std::string>(pin)))
2011 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2012 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a destination to gate '" + new_gate->get_name() +
"' via pin '"
2013 + core_strings::to<std::string>(pin) +
"'");
2020 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2021 +
"': failed to find gate type '" + core_strings::to<std::string>(instance->m_type) +
"' in gate library '" + m_netlist->
get_gate_library()->
get_name() +
"'");
2025 for (
const auto& attribute : instance->m_attributes)
2027 if (!container->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
2030 "could not set attribute '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2036 instance_identifier,
2042 for (
const auto&
generic : instance->m_generics)
2044 if (!container->set_data(
"generic",
generic.m_name,
generic.m_type,
generic.m_value))
2047 "could not set generic '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2053 instance_identifier,
2068 const static std::map<core_strings::CaseInsensitiveString, size_t> id_to_dim = {{
"std_logic_vector", 1}, {
"std_logic_vector2", 2}, {
"std_logic_vector3", 3}};
2070 static const std::map<char, BooleanFunction::Value> bin_map = {{
'0', BooleanFunction::Value::ZERO},
2071 {
'1', BooleanFunction::Value::ONE},
2072 {
'X', BooleanFunction::Value::X},
2073 {
'Z', BooleanFunction::Value::Z}};
2075 static const std::map<char, std::vector<BooleanFunction::Value>> oct_map = {{
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2076 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2077 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2078 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2079 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2080 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2081 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2082 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2083 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2084 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2086 static const std::map<char, std::vector<BooleanFunction::Value>> hex_map = {
2087 {
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2088 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2089 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2090 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2091 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2092 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2093 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2094 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2095 {
'8', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2096 {
'9', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2097 {
'A', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2098 {
'B', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2099 {
'C', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2100 {
'D', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2101 {
'E', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2102 {
'F', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2103 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2104 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2108 VHDLParser::ci_string VHDLParser::get_unique_alias(
const ci_string& parent_name,
const ci_string&
name,
const std::unordered_map<ci_string, u32>& name_occurences)
const
2110 ci_string unique_alias =
name;
2112 if (!parent_name.empty())
2115 if (
const auto instance_name_it = name_occurences.find(
name); instance_name_it != name_occurences.end() && instance_name_it->second > 1)
2117 unique_alias = parent_name + ci_string(
"/") + unique_alias;
2121 return unique_alias;
2124 std::vector<u32> VHDLParser::parse_range(TokenStream<ci_string>& range_stream)
const
2126 if (range_stream.remaining() == 1)
2128 return {(
u32)std::stoi(core_strings::to<std::string>(range_stream.consume().string))};
2132 const int end = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2134 if (range_stream.peek() ==
"downto")
2136 range_stream.consume(
"downto");
2140 range_stream.consume(
"to",
true);
2144 const int start = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2146 std::vector<u32> res;
2149 res.push_back((
u32)i);
2154 Result<std::vector<std::vector<u32>>> VHDLParser::parse_signal_ranges(TokenStream<ci_string>& signal_stream)
const
2156 std::vector<std::vector<u32>> ranges;
2157 const u32 line_number = signal_stream.peek().number;
2159 const Token<ci_string> type_name = signal_stream.consume();
2160 if (type_name ==
"std_logic")
2165 signal_stream.consume(
"(",
true);
2166 TokenStream<ci_string> signal_bounds_stream = signal_stream.extract_until(
")");
2171 TokenStream<ci_string> bound_stream = signal_bounds_stream.extract_until(
",");
2172 ranges.emplace_back(parse_range(bound_stream));
2173 }
while (signal_bounds_stream.consume(
","));
2175 signal_stream.consume(
")",
true);
2177 if (id_to_dim.find(type_name) != id_to_dim.end())
2179 const size_t dimension = id_to_dim.at(type_name);
2181 if (ranges.size() != dimension)
2183 return ERR(
"could not parse signal ranges: mismatch of dimensions (line " + std::to_string(line_number) +
")");
2188 return ERR(
"could not parse signal ranges: type name '" + core_strings::to<std::string>(type_name.string) +
"' is invalid (line " + std::to_string(line_number) +
")");
2194 void VHDLParser::expand_ranges_recursively(std::vector<ci_string>& expanded_names,
const ci_string& current_name,
const std::vector<std::vector<u32>>& ranges,
u32 dimension)
const
2197 if (ranges.size() > dimension)
2199 for (
const u32 index : ranges[dimension])
2201 expand_ranges_recursively(expanded_names, current_name +
"(" + core_strings::to<ci_string>(std::to_string(
index)) +
")", ranges, dimension + 1);
2207 expanded_names.push_back(current_name);
2211 std::vector<VHDLParser::ci_string> VHDLParser::expand_ranges(
const ci_string&
name,
const std::vector<std::vector<u32>>& ranges)
const
2213 std::vector<ci_string> res;
2215 expand_ranges_recursively(res,
name, ranges, 0);
2220 Result<std::vector<BooleanFunction::Value>> VHDLParser::get_binary_vector(std::string value)
const
2226 std::vector<BooleanFunction::Value> result;
2229 if (value.at(0) !=
'\"')
2231 prefix = value.at(0);
2232 number = value.substr(2, value.rfind(
'\"') - 2);
2237 number = value.substr(1, value.rfind(
'\"') - 1);
2241 switch (prefix.at(0))
2244 for (
auto it = number.rbegin(); it != number.rend(); it++)
2247 if (c ==
'0' || c ==
'1' || c ==
'Z' || c ==
'X')
2249 result.push_back(bin_map.at(c));
2253 return ERR(
"could not convert string to binary vector: invalid character within binary number literal '" + value +
"'");
2260 for (
auto it = number.rbegin(); it != number.rend(); it++)
2263 if ((c >=
'0' && c <=
'7') || c ==
'X' || c ==
'Z')
2265 const auto& bits = oct_map.at(c);
2266 result.insert(result.end(), bits.begin(), bits.end());
2270 return ERR(
"could not convert string to binary vector: invalid character within octal number literal '" + value +
"'");
2278 for (
const char c : number)
2280 if ((c >=
'0' && c <=
'9'))
2282 tmp_val = (tmp_val * 10) + (c -
'0');
2286 return ERR(
"could not convert string to binary vector: invalid character within decimal number literal '" + value +
"'");
2292 result.push_back(((tmp_val & 1) == 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
2294 }
while (tmp_val != 0);
2299 for (
auto it = number.rbegin(); it != number.rend(); it++)
2302 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F') || c ==
'X' || c ==
'Z')
2304 const auto& bits = hex_map.at(c);
2305 result.insert(result.end(), bits.begin(), bits.end());
2309 return ERR(
"could not convert string to binary vector: invalid character within hexadecimal number literal '" + value +
"'");
2316 return ERR(
"could not convert string to binary vector: invalid base '" + prefix +
"' within number literal '" + value +
"'");
2323 Result<std::string> VHDLParser::get_hex_from_literal(
const Token<ci_string>& value_token)
const
2325 const u32 line_number = value_token.number;
2333 if (value.at(0) !=
'\"')
2335 prefix = value.at(0);
2336 number = value.substr(2, value.rfind(
'\"') - 2);
2341 number = value.substr(1, value.rfind(
'\"') - 1);
2345 switch (prefix.at(0))
2348 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'1'); }))
2350 return ERR(
"could not convert token to hexadecimal string: invalid character within binary number literal '" + core_strings::to<std::string>(value) +
"' (line "
2351 + std::to_string(line_number) +
")");
2359 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'7'); }))
2361 return ERR(
"could not convert token to hexadecimal string: invalid character within ocatl number literal '" + core_strings::to<std::string>(value) +
"' (line "
2362 + std::to_string(line_number) +
")");
2370 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'9'); }))
2372 return ERR(
"could not convert token to hexadecimal string: invalid character within decimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2373 + std::to_string(line_number) +
")");
2383 for (
const char c : number)
2385 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F'))
2391 return ERR(
"could not convert token to hexadecimal string: invalid character within hexadecimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2392 + std::to_string(line_number) +
")");
2400 return ERR(
"could not convert token to hexadecimal string: invalid base '" + core_strings::to<std::string>(prefix) +
"' within number literal '" + core_strings::to<std::string>(value)
2401 +
"' (line " + std::to_string(line_number) +
")");
2405 std::stringstream ss;
2406 ss << std::uppercase << std::hex << stoull(core_strings::to<std::string>(number), 0, base);
2407 return OK(ss.str());
2410 Result<std::vector<VHDLParser::assignment_t>> VHDLParser::parse_assignment_expression(TokenStream<ci_string>&& stream)
const
2420 std::vector<TokenStream<ci_string>> parts;
2422 if (stream.size() == 0)
2428 if (stream.consume(
"("))
2432 parts.push_back(stream.extract_until(
","));
2433 }
while (stream.consume(
",",
false));
2435 stream.consume(
")",
true);
2439 parts.push_back(stream);
2442 std::vector<assignment_t> result;
2443 result.reserve(parts.size());
2445 for (
auto it = parts.rbegin(); it != parts.rend(); it++)
2447 TokenStream<ci_string>& part_stream = *it;
2449 const Token<ci_string> signal_name_token = part_stream.consume();
2450 ci_string signal_name = signal_name_token.string;
2456 if (
auto res = get_binary_vector(core_strings::to<std::string>(signal_name_token.string)); res.is_error())
2458 return ERR_APPEND(res.get_error(),
"could not expand assignment signal: unable to convert literal to binary string (line " + std::to_string(signal_name_token.number) +
")");
2462 result.push_back(std::move(res.get()));
2465 else if (signal_name ==
"'0'")
2467 result.push_back(numeral_t({BooleanFunction::Value::ZERO}));
2469 else if (signal_name ==
"'1'")
2471 result.push_back(numeral_t({BooleanFunction::Value::ONE}));
2473 else if (signal_name ==
"'X'")
2475 result.push_back(numeral_t({BooleanFunction::Value::X}));
2477 else if (signal_name ==
"'Z'")
2479 result.push_back(numeral_t({BooleanFunction::Value::Z}));
2485 if (part_stream.consume(
"("))
2487 std::vector<std::vector<u32>> ranges;
2488 u32 closing_pos = part_stream.find_next(
")");
2491 TokenStream<ci_string> range_stream = part_stream.extract_until(
",", closing_pos);
2492 ranges.emplace_back(parse_range(range_stream));
2494 }
while (part_stream.consume(
",",
false));
2495 part_stream.consume(
")",
true);
2496 result.push_back(ranged_identifier_t({std::move(signal_name), std::move(ranges)}));
2501 result.push_back(std::move(signal_name));
2509 Result<std::vector<VHDLParser::ci_string>> VHDLParser::expand_assignment_expression(VhdlEntity* vhdl_entity,
const std::vector<assignment_t>& vars)
const
2511 std::vector<ci_string> result;
2512 for (
const auto& var : vars)
2521 std::vector<std::vector<u32>> ranges;
2523 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(*
identifier); signal_it != vhdl_entity->m_signals_by_name.end())
2525 ranges = signal_it->second->m_ranges;
2527 else if (
const auto port_it = vhdl_entity->m_ports_by_identifier.find(*
identifier); port_it != vhdl_entity->m_ports_by_identifier.end())
2529 ranges = port_it->second->m_ranges;
2533 return ERR(
"could not expand assignment expression': '" + core_strings::to<std::string>(*
identifier) +
"' is neither a signal nor a port of entity '"
2534 + core_strings::to<std::string>(vhdl_entity->m_name) +
"'");
2537 std::vector<ci_string> expanded = expand_ranges(*
identifier, ranges);
2538 result.insert(result.end(), expanded.begin(), expanded.end());
2540 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier !=
nullptr)
2542 std::vector<ci_string> expanded = expand_ranges(ranged_identifier->first, ranged_identifier->second);
2543 result.insert(result.end(), expanded.begin(), expanded.end());
2545 else if (
const numeral_t* numeral = std::get_if<numeral_t>(&var); numeral !=
nullptr)
2547 for (
auto value : *numeral)
static std::string to_string(Value value)
bool set_data(const std::string &category, const std::string &key, const std::string &data_type, const std::string &value, const bool log_with_info_level=false)
std::unordered_map< std::string, GateType * > get_gate_types(const std::function< bool(const GateType *)> &filter=nullptr) const
std::unordered_map< std::string, GateType * > get_vcc_gate_types() const
std::unordered_map< std::string, GateType * > get_gnd_gate_types() const
std::string get_name() const
std::vector< GatePin * > get_output_pins() const
bool is_input_net(Net *net) const
void set_name(const std::string &name)
bool is_top_module() const
bool assign_gate(Gate *gate)
bool is_output_net(Net *net) const
std::string get_name() const
const std::unordered_set< Net * > & get_input_nets() const
void set_type(const std::string &type)
ModulePin * get_pin_by_net(Net *net) const
Result< ModulePin * > create_pin(const u32 id, const std::string &name, Net *net, PinType type=PinType::none, bool create_group=true, bool force_name=false)
Endpoint * add_source(Gate *gate, const std::string &pin_name)
const std::string & get_name() const
u32 get_num_of_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
Module * get_top_module() const
bool mark_vcc_gate(Gate *gate)
bool mark_gnd_gate(Gate *gate)
bool load_gate_locations_from_data(const std::string &data_category="", const std::pair< std::string, std::string > &data_identifiers=std::pair< std::string, std::string >())
bool delete_net(Net *net)
Net * create_net(const u32 net_id, const std::string &name)
const std::vector< Gate * > & get_gnd_gates() const
void set_design_name(const std::string &name)
void enable_automatic_net_checks(bool enable_checks=true)
const std::vector< Gate * > & get_vcc_gates() const
const std::vector< Module * > & get_modules() const
Gate * create_gate(const u32 gate_id, GateType *gate_type, const std::string &name="", i32 x=-1, i32 y=-1)
const std::vector< Net * > & get_nets() const
const GateLibrary * get_gate_library() const
Module * create_module(const u32 module_id, const std::string &name, Module *parent, const std::vector< Gate * > &gates={})
static const u32 END_OF_STREAM
Token< T > consume_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Token< T > & peek(i32 offset=0)
u32 find_next(const T &match, u32 end=END_OF_STREAM, bool level_aware=true) const
Token< T > join_until(const T &match, const T &joiner, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
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)
Result< std::monostate > parse(const std::filesystem::path &file_path) override
Result< std::unique_ptr< Netlist > > instantiate(const GateLibrary *gate_library) override
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
const Module * module(const Gate *g, const NodeBoxes &boxes)
std::basic_string< char, CaseInsensitiveCharTraits > CaseInsensitiveString
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
T replace(const T &str, const T &search, const T &replace)
bool is_digits(const T &s)
bool starts_with(const T &s, const T &start)
bool is_floating_point(const T &s)
bool ends_with(const T &s, const T &end)
bool is_integer(const T &s)
T trim(const T &s, const char *to_remove=" \t\r\n")
std::vector< PinInformation > pins
This file contains various functions to create and load netlists.