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())
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)
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() +
"'");
344 if (m_gnd_gate_types.empty())
346 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': the '0' literal is used but the gate library has no GND gate type");
348 GateType* gnd_type = m_gnd_gate_types.begin()->second;
354 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark GND gate");
359 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to GND gate");
369 if (m_vcc_gate_types.empty())
371 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': the '1' literal is used but the gate library has no VCC gate type");
373 GateType* vcc_type = m_vcc_gate_types.begin()->second;
379 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark VCC gate");
384 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to VCC gate");
393 std::queue<Net*> nets_to_be_deleted;
397 const u32 num_of_sources =
net->get_num_of_sources();
398 const u32 num_of_destinations =
net->get_num_of_destinations();
399 const bool no_source = num_of_sources == 0 && !(
net->is_global_input_net() && num_of_destinations != 0);
400 const bool no_destination = num_of_destinations == 0 && !(
net->is_global_output_net() && num_of_sources != 0);
401 if (no_source && no_destination)
403 nets_to_be_deleted.push(
net);
407 while (!nets_to_be_deleted.empty())
409 Net*
net = nets_to_be_deleted.front();
410 nets_to_be_deleted.pop();
416 return OK(std::move(result));
423 void VHDLParser::tokenize()
425 std::vector<Token<core_strings::CaseInsensitiveString>> parsed_tokens;
426 const std::string delimiters =
",(): ;=><&";
431 bool in_string =
false;
432 bool escaped =
false;
434 while (std::getline(m_fs, line))
437 if (line.find(
"--") != std::string::npos)
439 line = line.substr(0, line.find(
"--"));
443 if (in_string ==
false && c ==
'\\')
448 else if (escaped && std::isspace(c))
453 else if (!escaped && c ==
'"')
455 in_string = !in_string;
458 if (delimiters.find(c) == std::string::npos || escaped || in_string)
464 if (!current_token.empty())
466 if (parsed_tokens.size() > 1 &&
utils::is_digits(parsed_tokens.at(parsed_tokens.size() - 2).string) && parsed_tokens.at(parsed_tokens.size() - 1) ==
"."
469 parsed_tokens.pop_back();
470 parsed_tokens.back() +=
"." + current_token;
474 parsed_tokens.emplace_back(line_number, current_token);
476 current_token.clear();
479 if (!parsed_tokens.empty())
481 if (c ==
'=' && parsed_tokens.back() ==
"<")
483 parsed_tokens.back() =
"<=";
486 else if (c ==
'=' && parsed_tokens.back() ==
":")
488 parsed_tokens.back() =
":=";
491 else if (c ==
'>' && parsed_tokens.back() ==
"=")
493 parsed_tokens.back() =
"=>";
498 if (!std::isspace(c))
504 if (!current_token.empty())
506 parsed_tokens.emplace_back(line_number, current_token);
507 current_token.clear();
510 m_token_stream = TokenStream(parsed_tokens, {
"("}, {
")"});
513 Result<std::monostate> VHDLParser::parse_tokens()
517 if (m_token_stream.
peek() ==
"library" || m_token_stream.
peek() ==
"use")
521 else if (m_token_stream.
peek() ==
"entity")
523 if (
const auto res = parse_entity(); res.is_error())
525 return ERR_APPEND(res.get_error(),
"could not parse tokens");
528 else if (m_token_stream.
peek() ==
"architecture")
530 if (
const auto res = parse_architecture(); res.is_error())
532 return ERR_APPEND(res.get_error(),
"could not parse tokens");
537 return ERR(
"could not parse tokens: unexpected token '" + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' in global scope (line "
538 + std::to_string(m_token_stream.
peek().number) +
")");
545 void VHDLParser::parse_library()
547 if (m_token_stream.
peek() ==
"use")
549 m_token_stream.
consume(
"use",
true);
550 auto lib = m_token_stream.
consume().string;
551 m_token_stream.
consume(
";",
true);
554 lib =
utils::trim(lib.substr(0, lib.rfind(
".") + 1));
555 m_libraries.insert(lib);
560 m_token_stream.
consume(
";",
true);
564 Result<std::monostate> VHDLParser::parse_entity()
566 m_token_stream.
consume(
"entity",
true);
567 const u32 line_number = m_token_stream.
peek().number;
568 const ci_string entity_name = m_token_stream.
consume().string;
571 if (
const auto it = m_entities_by_name.find(entity_name); it != m_entities_by_name.end())
573 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"' (line " + std::to_string(line_number) +
"): an entity with name '"
574 + core_strings::to<std::string>(entity_name) +
"' does already exist (line " + std::to_string(it->second->m_line_number) +
")");
577 m_token_stream.
consume(
"is",
true);
578 auto vhdl_entity = std::make_unique<VhdlEntity>();
579 VhdlEntity* vhdl_entity_raw = vhdl_entity.get();
580 vhdl_entity_raw->m_line_number = line_number;
581 vhdl_entity_raw->m_name = entity_name;
583 m_attribute_buffer.clear();
585 Token<ci_string> next_token = m_token_stream.
peek();
586 while (next_token !=
"end")
588 if (next_token ==
"generic")
591 m_token_stream.
consume(
";",
true);
593 else if (next_token ==
"port")
595 if (
const auto res = parse_port_definitons(vhdl_entity_raw); res.is_error())
598 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse port definition (line " + std::to_string(next_token.number) +
")");
601 else if (next_token ==
"attribute")
603 if (
const auto res = parse_attribute(); res.is_error())
606 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse attribute (line " + std::to_string(next_token.number) +
")");
611 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': unexpected token '" + core_strings::to<std::string>(next_token.string)
612 +
"' in entity definition (line " + std::to_string(next_token.number) +
")");
615 next_token = m_token_stream.
peek();
618 m_token_stream.
consume(
"end",
true);
620 m_token_stream.
consume(
";",
true);
623 m_entities.push_back(std::move(vhdl_entity));
624 m_entities_by_name[entity_name] = vhdl_entity_raw;
625 m_last_entity = entity_name;
630 Result<std::monostate> VHDLParser::parse_port_definitons(VhdlEntity* vhdl_entity)
633 m_token_stream.
consume(
"port",
true);
634 m_token_stream.
consume(
"(",
true);
637 while (port_def_stream.remaining() > 0)
639 std::vector<core_strings::CaseInsensitiveString> port_names;
642 const auto line_number = port_def_stream.
peek().number;
647 port_names.push_back(port_def_stream.consume().string);
648 }
while (port_def_stream.consume(
",",
false));
650 port_def_stream.consume(
":",
true);
654 const ci_string direction_str = port_def_stream.consume().string;
655 if (direction_str ==
"in")
659 else if (direction_str ==
"out")
663 else if (direction_str ==
"inout")
669 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)
674 TokenStream<ci_string> port_stream = port_def_stream.extract_until(
";");
675 std::vector<std::vector<u32>> ranges;
676 if (
auto res = parse_signal_ranges(port_stream); res.is_error())
678 return ERR_APPEND(res.get_error(),
"could not parse port definitions: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
685 port_def_stream.consume(
";", port_def_stream.remaining() > 0);
687 for (
const ci_string& port_name : port_names)
689 auto port = std::make_unique<VhdlPort>();
690 port->m_identifier = port_name;
692 port->m_ranges = ranges;
693 vhdl_entity->m_ports_by_identifier[port->m_identifier] = port.get();
694 vhdl_entity->m_ports.push_back(std::move(port));
696 if (vhdl_entity->m_signals_by_name.find(port_name) == vhdl_entity->m_signals_by_name.end())
698 auto signal = std::make_unique<VhdlSignal>();
699 signal->m_name = port_name;
702 signal->m_ranges = ranges;
704 vhdl_entity->m_signals_by_name[port_name] = signal.get();
705 vhdl_entity->m_signals.push_back(std::move(signal));
710 m_token_stream.
consume(
")",
true);
711 m_token_stream.
consume(
";",
true);
716 Result<std::monostate> VHDLParser::parse_attribute()
718 const u32 line_number = m_token_stream.
peek().number;
720 m_token_stream.
consume(
"attribute",
true);
721 const ci_string attribute_name = m_token_stream.
consume().string;
723 if (m_token_stream.
peek() ==
":")
725 m_token_stream.
consume(
":",
true);
726 m_attribute_types[attribute_name] = m_token_stream.
join_until(
";",
" ");
727 m_token_stream.
consume(
";",
true);
729 else if (m_token_stream.
peek() ==
"of" && m_token_stream.
peek(2) ==
":")
731 AttributeTarget target_class;
732 m_token_stream.
consume(
"of",
true);
733 const ci_string attribute_target = m_token_stream.
consume().string;
734 m_token_stream.
consume(
":",
true);
735 const ci_string attribute_class = m_token_stream.
consume().string;
736 m_token_stream.
consume(
"is",
true);
737 ci_string attribute_value = m_token_stream.
join_until(
";",
" ").string;
738 m_token_stream.
consume(
";",
true);
739 ci_string attribute_type;
741 if (attribute_value[0] ==
'\"' && attribute_value.back() ==
'\"')
743 attribute_value = attribute_value.substr(1, attribute_value.size() - 2);
746 if (
const auto type_it = m_attribute_types.find(attribute_name); type_it == m_attribute_types.end())
748 log_warning(
"vhdl_parser",
"attribute {} has unknown base type in line {}.", attribute_name, line_number);
749 attribute_type =
"unknown";
753 attribute_type = type_it->second;
756 if (attribute_class ==
"entity")
758 target_class = AttributeTarget::ENTITY;
760 else if (attribute_class ==
"label")
762 target_class = AttributeTarget::INSTANCE;
764 else if (attribute_class ==
"signal")
766 target_class = AttributeTarget::SIGNAL;
770 log_warning(
"vhdl_parser",
"unsupported attribute class '{}' in line {}, ignoring attribute.", attribute_class, line_number);
774 VhdlDataEntry attribute;
775 attribute.m_name = core_strings::to<std::string>(attribute_name);
776 attribute.m_type = core_strings::to<std::string>(attribute_type);
777 attribute.m_value = core_strings::to<std::string>(attribute_value);
778 m_attribute_buffer[target_class].emplace(attribute_target, attribute);
782 return ERR(
"could not parse attribute: malformed attribute definition (line " + std::to_string(line_number) +
")");
788 Result<std::monostate> VHDLParser::parse_architecture()
790 m_token_stream.
consume(
"architecture",
true);
792 m_token_stream.
consume(
"of",
true);
794 u32 line_number = m_token_stream.
peek().number;
795 const auto entity_name_token = m_token_stream.
consume();
797 if (
const auto it = m_entities_by_name.find(entity_name_token.string); it == m_entities_by_name.end())
799 return ERR(
"could not parse architecture: architecture refers to non-existent entity '" + core_strings::to<std::string>(entity_name_token.string) +
"' (line "
800 + std::to_string(entity_name_token.number) +
")");
804 VhdlEntity* vhdl_entity = it->second;
806 m_token_stream.
consume(
"is",
true);
808 if (
const auto res = parse_architecture_header(vhdl_entity); res.is_error())
810 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture header (line " + std::to_string(line_number) +
")");
812 if (
const auto res = parse_architecture_body(vhdl_entity); res.is_error())
814 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture body (line " + std::to_string(line_number) +
")");
816 if (
const auto res = assign_attributes(vhdl_entity); res.is_error())
818 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to assign attributes (line " + std::to_string(line_number) +
")");
825 Result<std::monostate> VHDLParser::parse_architecture_header(VhdlEntity* vhdl_entity)
827 auto next_token = m_token_stream.
peek();
828 while (next_token !=
"begin")
830 if (next_token ==
"signal")
832 if (
const auto res = parse_signal_definition(vhdl_entity); res.is_error())
834 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse signal definition (line " + std::to_string(next_token.number) +
")");
837 else if (next_token ==
"component")
840 m_token_stream.
consume(
"component",
true);
841 const ci_string component_name = m_token_stream.
consume().string;
843 m_token_stream.
consume(
"end",
true);
844 m_token_stream.
consume(
"component",
true);
845 if (m_token_stream.
peek() !=
";")
847 m_token_stream.
consume(component_name,
true);
849 m_token_stream.
consume(
";",
true);
851 else if (next_token ==
"attribute")
853 if (
const auto res = parse_attribute(); res.is_error())
855 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse attribute (line " + std::to_string(next_token.number) +
")");
860 return ERR(
"could not parse architecture header: unexpected token '" + core_strings::to<std::string>(next_token.string) +
"' (line " + std::to_string(next_token.number) +
")");
863 next_token = m_token_stream.
peek();
869 Result<std::monostate> VHDLParser::parse_signal_definition(VhdlEntity* vhdl_entity)
871 m_token_stream.
consume(
"signal",
true);
872 u32 line_number = m_token_stream.
peek().number;
875 std::vector<ci_string> signal_names;
878 signal_names.push_back(m_token_stream.
consume().string);
879 }
while (m_token_stream.
consume(
",",
false));
881 m_token_stream.
consume(
":",
true);
884 TokenStream<ci_string> signal_stream = m_token_stream.
extract_until(
";");
885 std::vector<std::vector<u32>> ranges;
886 if (
auto res = parse_signal_ranges(signal_stream); res.is_error())
888 return ERR_APPEND(res.get_error(),
"could not parse signal definition: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
895 m_token_stream.
consume(
";",
true);
897 for (
const auto& signal_name : signal_names)
899 if (vhdl_entity->m_signals_by_name.find(signal_name) == vhdl_entity->m_signals_by_name.end())
901 auto signal = std::make_unique<VhdlSignal>();
902 signal->m_name = signal_name;
903 signal->m_ranges = ranges;
904 vhdl_entity->m_signals_by_name[signal_name] = signal.get();
905 vhdl_entity->m_signals.push_back(std::move(signal));
912 Result<std::monostate> VHDLParser::parse_architecture_body(VhdlEntity* vhdl_entity)
914 m_token_stream.
consume(
"begin",
true);
915 auto next_token = m_token_stream.
peek();
917 while (next_token !=
"end")
920 if (m_token_stream.
peek(1) ==
":")
922 if (
const auto res = parse_instance(vhdl_entity); res.is_error())
925 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse instance (line "
926 + std::to_string(next_token.number) +
")");
932 if (
const auto res = parse_assignment(vhdl_entity); res.is_error())
935 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse assignment (line "
936 + std::to_string(next_token.number) +
")");
941 return ERR(
"could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unexpected token '"
942 + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' (line " + std::to_string(next_token.number) +
")");
945 next_token = m_token_stream.
peek();
948 m_token_stream.
consume(
"end",
true);
950 m_token_stream.
consume(
";",
true);
955 Result<std::monostate> VHDLParser::parse_assignment(VhdlEntity* vhdl_entity)
957 u32 line_number = m_token_stream.
peek().number;
958 VhdlAssignment assignment;
960 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
"<=")); res.is_error())
962 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
966 assignment.m_variable = res.get();
968 m_token_stream.
consume(
"<=",
true);
969 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
";")); res.is_error())
971 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
975 assignment.m_assignment = res.get();
977 m_token_stream.
consume(
";",
true);
979 vhdl_entity->m_assignments.push_back(std::move(assignment));
983 Result<std::monostate> VHDLParser::parse_instance(VhdlEntity* vhdl_entity)
985 auto instance = std::make_unique<VhdlInstance>();
986 u32 line_number = m_token_stream.
peek().number;
988 m_token_stream.
consume(
":",
true);
991 if (m_token_stream.
peek() ==
"entity")
993 m_token_stream.
consume(
"entity",
true);
995 if (
const size_t pos =
instance->m_type.find(
'.'); pos != std::string::npos)
999 if (m_entities_by_name.find(
instance->m_type) == m_entities_by_name.end())
1001 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 '"
1002 + core_strings::to<std::string>(
instance->m_type) +
"' does not exist (line " + std::to_string(line_number) +
")");
1005 else if (m_token_stream.
peek() ==
"component")
1007 m_token_stream.
consume(
"component",
true);
1016 for (
const auto& lib : m_libraries)
1025 if (!prefix.empty())
1031 if (m_token_stream.
consume(
"generic"))
1033 line_number = m_token_stream.
peek().number;
1034 if (
const auto res = parse_generic_assign(
instance.get()); res.is_error())
1037 "could not parse instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type)
1038 +
"': unable to parse generic assignment (line " + std::to_string(line_number) +
")");
1042 if (m_token_stream.
peek() ==
"port")
1044 if (
const auto res = parse_port_assign(
instance.get()); res.is_error())
1047 "could not parse instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type)
1048 +
"': unable to parse port assignment (line " + std::to_string(line_number) +
")");
1053 vhdl_entity->m_instances.push_back(std::move(
instance));
1055 m_token_stream.
consume(
";",
true);
1060 Result<std::monostate> VHDLParser::parse_port_assign(VhdlInstance*
instance)
1062 u32 line_number = m_token_stream.
peek().number;
1063 m_token_stream.
consume(
"port",
true);
1064 m_token_stream.
consume(
"map",
true);
1065 m_token_stream.
consume(
"(",
true);
1066 TokenStream<ci_string> port_stream = m_token_stream.
extract_until(
")");
1067 m_token_stream.
consume(
")",
true);
1071 while (port_stream.remaining() > 0)
1073 TokenStream<ci_string> left_stream = port_stream.extract_until(
"=>");
1074 port_stream.consume(
"=>",
true);
1075 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1076 port_stream.consume(
",", port_stream.remaining() > 0);
1078 if (!right_stream.consume(
"open"))
1080 VhdlPortAssignment port_assignment;
1082 if (
auto res = parse_assignment_expression(std::move(left_stream)); res.is_error())
1084 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse port (line " + std::to_string(line_number) +
")");
1089 port_assignment.m_port = res.get().front();
1092 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1094 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1098 port_assignment.m_assignment = res.get();
1101 instance->m_port_assignments.push_back(std::move(port_assignment));
1107 while (port_stream.remaining() > 0)
1109 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1110 port_stream.consume(
",", port_stream.remaining() > 0);
1112 if (!right_stream.consume(
"open"))
1114 VhdlPortAssignment port_assignment;
1116 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1118 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1122 port_assignment.m_assignment = res.get();
1125 instance->m_port_assignments.push_back(std::move(port_assignment));
1129 VhdlPortAssignment port_assignment;
1130 port_assignment.m_assignment.push_back(
"");
1131 instance->m_port_assignments.push_back(std::move(port_assignment));
1139 Result<std::monostate> VHDLParser::parse_generic_assign(VhdlInstance*
instance)
1141 m_token_stream.
consume(
"map",
true);
1142 m_token_stream.
consume(
"(",
true);
1143 TokenStream<ci_string> generic_stream = m_token_stream.
extract_until(
")");
1144 m_token_stream.
consume(
")",
true);
1146 while (generic_stream.remaining() > 0)
1148 VhdlDataEntry
generic;
1150 generic.m_line_number = generic_stream.peek().number;
1151 generic.m_name = core_strings::to<std::string>(generic_stream.join_until(
"=>",
"").string);
1152 generic_stream.consume(
"=>",
true);
1153 const auto rhs = generic_stream.join_until(
",",
"");
1154 generic_stream.consume(
",", generic_stream.remaining() > 0);
1157 if ((rhs ==
"true") || (rhs ==
"false"))
1159 generic.m_value = core_strings::to<std::string>(rhs.string);
1160 generic.m_type =
"boolean";
1164 generic.m_value = core_strings::to<std::string>(rhs.string);
1165 generic.m_type =
"integer";
1169 generic.m_value = core_strings::to<std::string>(rhs.string);
1170 generic.m_type =
"floating_point";
1175 generic.m_value = core_strings::to<std::string>(rhs.string);
1176 generic.m_type =
"time";
1178 else if (rhs.string.at(0) ==
'\"' && rhs.string.back() ==
'\"')
1180 generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, rhs.string.size() - 2));
1181 generic.m_type =
"string";
1183 else if (rhs.string.at(0) ==
'\'' && rhs.string.at(2) ==
'\'')
1185 generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, 1));
1186 generic.m_type =
"bit_value";
1188 else if (rhs.string.at(1) ==
'\"' && rhs.string.back() ==
'\"')
1190 if (
auto res = get_hex_from_literal(rhs); res.is_error())
1192 return ERR_APPEND(res.get_error(),
"could not parse generic assignment: unable to translate token to hexadecimal string");
1196 generic.m_value = core_strings::to<std::string>(res.get());
1197 generic.m_type =
"bit_vector";
1202 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 '"
1203 + core_strings::to<std::string>(
instance->m_name) +
"' (line " + std::to_string(
generic.m_line_number) +
")");
1206 instance->m_generics.push_back(
generic);
1212 Result<std::monostate> VHDLParser::assign_attributes(VhdlEntity* vhdl_entity)
1214 for (
const auto& [target_class, attributes] : m_attribute_buffer)
1217 if (target_class == AttributeTarget::ENTITY)
1219 for (
const auto& [target, attribute] : attributes)
1221 if (vhdl_entity->m_name != target)
1223 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1224 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1228 vhdl_entity->m_attributes.push_back(attribute);
1233 else if (target_class == AttributeTarget::INSTANCE)
1235 for (
const auto& [target, attribute] : attributes)
1237 if (
const auto instance_it = vhdl_entity->m_instances_by_name.find(target); instance_it == vhdl_entity->m_instances_by_name.end())
1239 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1240 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1244 instance_it->second->m_attributes.push_back(attribute);
1249 else if (target_class == AttributeTarget::SIGNAL)
1251 for (
const auto& [target, attribute] : attributes)
1253 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(target); signal_it != vhdl_entity->m_signals_by_name.end())
1255 signal_it->second->m_attributes.push_back(attribute);
1259 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1260 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1273 Result<std::monostate> VHDLParser::construct_netlist(VhdlEntity* top_entity)
1275 m_netlist->
set_design_name(core_strings::to<std::string>(top_entity->m_name));
1278 std::unordered_map<ci_string, u32> instantiation_count;
1281 std::queue<VhdlEntity*> q;
1286 VhdlEntity* entity = q.front();
1289 instantiation_count[entity->m_name]++;
1292 for (
const auto& s : entity->m_signals)
1294 std::vector<ci_string> expanded_names;
1295 expand_ranges_recursively(expanded_names, s->m_name, s->m_ranges, 0);
1296 for (
const auto& net_name : expanded_names)
1298 m_signal_name_occurrences[net_name]++;
1302 for (
const auto&
instance : entity->m_instances)
1304 m_instance_name_occurrences[
instance->m_name]++;
1307 if (
const auto it = m_entities_by_name.find(
instance->m_type); it != m_entities_by_name.end())
1314 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
1317 if (instantiation_count[entity_name] == 0)
1319 log_warning(
"vhdl_parser",
"entity '{}' has been defined in the netlist but is not instantiated.", entity_name);
1324 for (
const auto&
instance : vhdl_entity->m_instances)
1326 if (
const auto gate_type_it = m_gate_types.find(
instance->m_type); gate_type_it != m_gate_types.end())
1328 if (!
instance->m_port_assignments.empty())
1331 if (
instance->m_port_assignments.front().m_port.has_value())
1334 std::unordered_map<ci_string, std::vector<ci_string>> pin_groups;
1335 for (
const auto pin_group : gate_type_it->second->get_pin_groups())
1337 const auto pins = pin_group->get_pins();
1338 for (
auto it =
pins.rbegin(); it !=
pins.rend(); it++)
1340 const auto* pin = *it;
1341 pin_groups[core_strings::to<ci_string>(pin_group->get_name())].push_back(core_strings::to<ci_string>(pin->get_name()));
1345 for (
const auto& port_assignment :
instance->m_port_assignments)
1347 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1348 if (right_res.is_error())
1350 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1352 auto right_port = right_res.get();
1354 if (!right_port.empty())
1356 std::vector<ci_string> left_port;
1358 if (
const identifier_t*
identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value()));
identifier !=
nullptr)
1360 if (
const auto group_it = pin_groups.find(*
identifier); group_it != pin_groups.end())
1362 left_port = group_it->second;
1369 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier !=
nullptr)
1371 left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
1375 return ERR(
"could not construct netlist: unable to expand gate port assignment");
1378 if (right_port.size() != left_port.size())
1380 return ERR(
"could not construct netlist: pin assignment width mismatch at instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of gate type '"
1381 + core_strings::to<std::string>(
instance->m_type) +
"' within entity '" + core_strings::to<std::string>(entity_name) +
"'");
1384 for (
u32 i = 0; i < left_port.size(); i++)
1386 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1395 std::vector<ci_string>
pins;
1396 for (
const auto pin : gate_type_it->second->get_pins())
1398 pins.push_back(core_strings::to<ci_string>(pin->get_name()));
1400 auto pin_it =
pins.begin();
1402 for (
const auto& port_assignment :
instance->m_port_assignments)
1404 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1405 if (right_res.is_error())
1407 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1409 auto right_port = right_res.get();
1411 if (!right_port.empty())
1413 std::vector<ci_string> left_port;
1415 for (
u32 i = 0; i < right_port.size() && pin_it !=
pins.end(); i++)
1417 left_port.push_back(*pin_it++);
1420 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1422 for (
u32 i = 0; i < max_size; i++)
1424 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1435 std::unordered_map<ci_string, ci_string> top_assignments;
1436 for (
const auto& port : top_entity->m_ports)
1438 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1440 const auto signal_name = get_unique_alias(
"", expanded_port_identifier +
"__GLOBAL_IO__", m_signal_name_occurrences);
1442 Net* global_port_net = m_netlist->
create_net(core_strings::to<std::string>(signal_name));
1443 if (global_port_net ==
nullptr)
1445 return ERR(
"could not construct netlist: failed to create global I/O net '" + core_strings::to<std::string>(signal_name) +
"'");
1448 m_net_by_name[signal_name] = global_port_net;
1451 top_assignments[expanded_port_identifier] = signal_name;
1455 if (!global_port_net->mark_global_input_net())
1457 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global input");
1463 if (!global_port_net->mark_global_output_net())
1465 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global output");
1471 if (
const auto res = instantiate_entity(
"top_module", top_entity,
nullptr, top_assignments); res.is_error())
1473 return ERR_APPEND(res.get_error(),
"could not construct netlist: unable to instantiate top module");
1477 std::unordered_map<ci_string, ci_string> merged_nets;
1478 std::unordered_map<ci_string, std::vector<ci_string>> master_to_slaves;
1480 for (
auto& [master, slave] : m_nets_to_merge)
1485 if (
const auto master_it = merged_nets.find(master); master_it != merged_nets.end())
1487 master = master_it->second;
1498 if (
const auto slave_it = merged_nets.find(slave); slave_it != merged_nets.end())
1500 slave = slave_it->second;
1508 auto master_net = m_net_by_name.at(master);
1509 auto slave_net = m_net_by_name.at(slave);
1511 if (master_net == slave_net)
1515 else if (slave_net == m_zero_net || slave_net == m_one_net)
1517 auto* tmp_net = master_net;
1518 master_net = slave_net;
1519 slave_net = tmp_net;
1521 auto tmp_name = master;
1527 if (slave_net->is_global_input_net())
1529 master_net->mark_global_input_net();
1532 for (
auto src : slave_net->get_sources())
1534 Gate* src_gate = src->get_gate();
1535 GatePin* src_pin = src->get_pin();
1537 if (!slave_net->remove_source(src))
1539 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()));
1542 if (!master_net->is_a_source(src_gate, src_pin))
1544 if (!master_net->add_source(src_gate, src_pin))
1546 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()));
1552 if (slave_net->is_global_output_net())
1554 master_net->mark_global_output_net();
1557 for (
auto dst : slave_net->get_destinations())
1559 Gate* dst_gate = dst->get_gate();
1560 GatePin* dst_pin = dst->get_pin();
1562 if (!slave_net->remove_destination(dst))
1564 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()));
1567 if (!master_net->is_a_destination(dst_gate, dst_pin))
1569 if (!master_net->add_destination(dst_gate, dst_pin))
1571 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()));
1577 for (
const auto& [
identifier, content] : slave_net->get_data_map())
1579 if (!master_net->set_data(std::get<0>(
identifier), std::get<1>(
identifier), std::get<0>(content), std::get<1>(content)))
1582 "unable to transfer data from slave net '{}' with ID {} to master net '{}' with ID {}.",
1583 slave_net->get_name(),
1584 slave_net->get_id(),
1585 master_net->get_name(),
1586 master_net->get_id());
1591 if (
const auto it = m_module_port_by_net.find(slave_net); it != m_module_port_by_net.end())
1595 std::get<1>(m_module_ports.at(
module).at(
index)) = master_net;
1597 m_module_port_by_net[master_net].insert(m_module_port_by_net[master_net].end(), it->second.begin(), it->second.end());
1598 m_module_port_by_net.erase(it);
1602 m_net_by_name.erase(slave);
1603 merged_nets[slave] = master;
1604 master_to_slaves[master].push_back(slave);
1608 for (
auto& master_net : m_netlist->
get_nets())
1610 const auto master_name = master_net->get_name();
1612 if (
const auto m2s_it = master_to_slaves.find(core_strings::to<ci_string>(master_name)); m2s_it != master_to_slaves.end())
1614 std::vector<std::vector<ci_string>> merged_slaves;
1615 auto current_slaves = m2s_it->second;
1617 while (!current_slaves.empty())
1619 std::vector<ci_string> next_slaves;
1620 for (
const auto& s : current_slaves)
1622 if (
const auto m2s_inner_it = master_to_slaves.find(s); m2s_inner_it != master_to_slaves.end())
1624 next_slaves.insert(next_slaves.end(), m2s_inner_it->second.begin(), m2s_inner_it->second.end());
1628 merged_slaves.push_back(current_slaves);
1629 current_slaves = next_slaves;
1630 next_slaves.clear();
1635 ci_string merged_str =
"";
1636 bool has_merged_nets =
false;
1637 for (
const auto& vec : merged_slaves)
1641 has_merged_nets =
true;
1644 ci_string s = vec.empty() ?
"" : vec.front();
1645 for (
u32 idx = 1; idx < vec.size(); idx++)
1647 s += ci_string(
", ") + vec.at(idx);
1650 merged_str +=
"[" + s +
"], ";
1652 merged_str = merged_str.substr(0, merged_str.size() - 2);
1654 if (has_merged_nets)
1656 master_net->set_data(
"parser_annotation",
"merged_nets",
"string",
"[" + core_strings::to<std::string>(merged_str) +
"]");
1668 for (
const auto& [
module, ports] : m_module_ports)
1670 for (
const auto& [port_name, port_net] : ports)
1681 "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())
1692 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()))
1697 "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 '"
1702 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()))
1707 "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())
1718 VHDLParser::instantiate_entity(
const ci_string& instance_identifier, VhdlEntity* vhdl_entity, Module* parent,
const std::unordered_map<ci_string, ci_string>& parent_module_assignments)
1720 std::unordered_map<ci_string, ci_string> signal_alias;
1721 std::unordered_map<ci_string, ci_string> instance_alias;
1725 const std::string parent_name = parent == (
nullptr) ?
"" : parent->get_name();
1726 instance_alias[instance_identifier] = get_unique_alias(core_strings::to<ci_string>(parent_name), instance_identifier, m_instance_name_occurrences);
1730 if (parent ==
nullptr)
1733 module->
set_name(core_strings::to<std::string>(instance_alias.at(instance_identifier)));
1737 module = m_netlist->
create_module(core_strings::to<std::string>(instance_alias.at(instance_identifier)), parent);
1740 ci_string instance_type = vhdl_entity->m_name;
1743 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1744 +
"': failed to create module");
1749 for (
const VhdlDataEntry& attribute : vhdl_entity->m_attributes)
1751 if (!
module->
set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1754 "could not set attribute '{} = {}' of type '{}' for instance '{}' type '{}'.",
1758 instance_identifier,
1764 for (
const auto& port : vhdl_entity->m_ports)
1766 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1768 if (
const auto it = parent_module_assignments.find(expanded_port_identifier); it != parent_module_assignments.end())
1770 Net* port_net = m_net_by_name.at(it->second);
1771 m_module_ports[
module].push_back(std::make_pair(core_strings::to<std::string>(expanded_port_identifier), port_net));
1772 m_module_port_by_net[port_net].push_back(std::make_pair(
module, m_module_ports[
module].
size() - 1));
1778 for (
const auto& signal : vhdl_entity->m_signals)
1780 for (
const auto& expanded_name : signal->m_expanded_names)
1782 signal_alias[expanded_name] = get_unique_alias(instance_alias[instance_identifier], expanded_name, m_signal_name_occurrences);
1785 Net* signal_net = m_netlist->
create_net(core_strings::to<std::string>(signal_alias.at(expanded_name)));
1786 if (signal_net ==
nullptr)
1788 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1789 +
"': failed to create net '" + core_strings::to<std::string>(expanded_name) +
"'");
1792 m_net_by_name[signal_alias.at(expanded_name)] = signal_net;
1795 for (
const VhdlDataEntry& attribute : signal->m_attributes)
1797 if (!signal_net->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1800 "could not set attribute ({} = {}) for net '{}' of instance '{}' of type '{}'.",
1804 instance_identifier,
1812 for (
const auto& [left_expanded_signal, right_expanded_signal] : vhdl_entity->m_expanded_assignments)
1814 ci_string a = left_expanded_signal;
1815 ci_string b = right_expanded_signal;
1817 if (
const auto alias_it = signal_alias.find(a); alias_it != signal_alias.end())
1819 a = alias_it->second;
1823 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1824 +
"': failed to find alias for net '" + core_strings::to<std::string>(a) +
"'");
1827 if (
const auto alias_it = signal_alias.find(b); alias_it != signal_alias.end())
1829 b = alias_it->second;
1831 else if (b ==
"'Z'" || b ==
"'X'")
1835 else if (b !=
"'0'" && b !=
"'1'")
1837 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1838 +
"': failed to find alias for net '" + core_strings::to<std::string>(b) +
"'");
1841 m_nets_to_merge.push_back(std::make_pair(a, b));
1845 for (
const auto& [port_expression, net_name] : parent_module_assignments)
1847 if (
const auto alias_it = signal_alias.find(port_expression); alias_it != signal_alias.end())
1849 const bool swap = net_name.find(
"__GLOBAL_IO__") == std::string::npos;
1850 m_nets_to_merge.push_back(swap ? std::make_pair(net_name, alias_it->second) : std::make_pair(alias_it->second, net_name));
1854 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1855 +
"': failed to find alias for net '" + core_strings::to<std::string>(port_expression) +
"'");
1860 for (
const auto&
instance : vhdl_entity->m_instances)
1863 DataContainer* container =
nullptr;
1866 std::unordered_map<ci_string, ci_string> instance_assignments;
1869 if (
auto entity_it = m_entities_by_name.find(
instance->m_type); entity_it != m_entities_by_name.end())
1872 for (
const auto& [port, assignment] :
instance->m_expanded_port_assignments)
1874 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1876 instance_assignments[port] = alias_it->second;
1878 else if (assignment ==
"'0'" || assignment ==
"'1'")
1880 instance_assignments[port] = assignment;
1882 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
1888 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1889 +
"': port assignment '" + core_strings::to<std::string>(port) +
" = " + core_strings::to<std::string>(assignment) +
"' is invalid");
1893 if (
auto res = instantiate_entity(
instance->m_name, entity_it->second,
module, instance_assignments); res.is_error())
1896 "could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1897 +
"': unable to create instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '"
1898 + core_strings::to<std::string>(entity_it->second->m_name) +
"'");
1902 container = res.get();
1906 else if (
const auto gate_type_it = m_gate_types.find(
instance->m_type); gate_type_it != m_gate_types.end())
1909 instance_alias[
instance->m_name] = get_unique_alias(instance_alias[instance_identifier],
instance->m_name, m_instance_name_occurrences);
1911 Gate* new_gate = m_netlist->
create_gate(gate_type_it->second, core_strings::to<std::string>(instance_alias.at(
instance->m_name)));
1912 if (new_gate ==
nullptr)
1914 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1915 +
"': failed to create gate '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1923 container = new_gate;
1926 if (m_vcc_gate_types.find(
instance->m_type) != m_vcc_gate_types.end() && !new_gate->mark_vcc_gate())
1928 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 '"
1929 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as GND gate");
1931 if (m_gnd_gate_types.find(
instance->m_type) != m_gnd_gate_types.end() && !new_gate->mark_gnd_gate())
1933 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 '"
1934 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as VCC gate");
1938 std::unordered_map<ci_string, GatePin*> pin_names_map;
1939 for (
auto* pin : gate_type_it->second->get_pins())
1941 pin_names_map[core_strings::to<ci_string>(pin->get_name())] = pin;
1945 for (
const auto& [pin, assignment] :
instance->m_expanded_port_assignments)
1949 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1951 signal = alias_it->second;
1953 else if (assignment ==
"'0'" || assignment ==
"'1'")
1955 signal = assignment;
1957 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
1963 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1964 +
"': failed to assign '" + core_strings::to<std::string>(assignment) +
"' to pin '" + core_strings::to<std::string>(pin) +
"' of gate '"
1965 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as the assignment is invalid");
1969 if (
const auto net_it = m_net_by_name.find(signal); net_it == m_net_by_name.end())
1971 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1972 +
"': failed to assign signal'" + core_strings::to<std::string>(signal) +
"' to pin '" + core_strings::to<std::string>(pin)
1973 +
"' as the signal has not been declared");
1977 Net* current_net = net_it->second;
1980 bool is_input =
false;
1981 bool is_output =
false;
1983 if (
const auto it = pin_names_map.find(pin); it != pin_names_map.end())
1997 if (!is_input && !is_output)
1999 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2000 +
"': 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 '"
2001 + new_gate->get_name() +
"' of type '" + new_gate->get_type()->get_name() +
"'");
2004 if (is_output && !current_net->add_source(new_gate, core_strings::to<std::string>(pin)))
2006 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2007 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a source to gate '" + new_gate->get_name() +
"' via pin '"
2008 + core_strings::to<std::string>(pin) +
"'");
2011 if (is_input && !current_net->add_destination(new_gate, core_strings::to<std::string>(pin)))
2013 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2014 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a destination to gate '" + new_gate->get_name() +
"' via pin '"
2015 + core_strings::to<std::string>(pin) +
"'");
2022 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2023 +
"': failed to find gate type '" + core_strings::to<std::string>(
instance->m_type) +
"' in gate library '" + m_netlist->
get_gate_library()->
get_name() +
"'");
2027 for (
const auto& attribute :
instance->m_attributes)
2029 if (!container->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
2032 "could not set attribute '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2038 instance_identifier,
2044 for (
const auto&
generic :
instance->m_generics)
2046 if (!container->set_data(
"generic",
generic.m_name,
generic.m_type,
generic.m_value))
2049 "could not set generic '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2055 instance_identifier,
2070 const static std::map<core_strings::CaseInsensitiveString, size_t> id_to_dim = {{
"std_logic_vector", 1}, {
"std_logic_vector2", 2}, {
"std_logic_vector3", 3}};
2072 static const std::map<char, BooleanFunction::Value> bin_map = {{
'0', BooleanFunction::Value::ZERO},
2073 {
'1', BooleanFunction::Value::ONE},
2074 {
'X', BooleanFunction::Value::X},
2075 {
'Z', BooleanFunction::Value::Z}};
2077 static const std::map<char, std::vector<BooleanFunction::Value>> oct_map = {{
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2078 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2079 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2080 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2081 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2082 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2083 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2084 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2085 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2086 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2088 static const std::map<char, std::vector<BooleanFunction::Value>> hex_map = {
2089 {
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2090 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2091 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2092 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2093 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2094 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2095 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2096 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2097 {
'8', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2098 {
'9', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2099 {
'A', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2100 {
'B', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2101 {
'C', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2102 {
'D', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2103 {
'E', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2104 {
'F', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2105 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2106 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2110 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
2112 ci_string unique_alias =
name;
2114 if (!parent_name.empty())
2117 if (
const auto instance_name_it = name_occurences.find(
name); instance_name_it != name_occurences.end() && instance_name_it->second > 1)
2119 unique_alias = parent_name + ci_string(
"/") + unique_alias;
2123 return unique_alias;
2126 std::vector<u32> VHDLParser::parse_range(TokenStream<ci_string>& range_stream)
const
2128 if (range_stream.remaining() == 1)
2130 return {(
u32)std::stoi(core_strings::to<std::string>(range_stream.consume().string))};
2134 const int end = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2136 if (range_stream.peek() ==
"downto")
2138 range_stream.consume(
"downto");
2142 range_stream.consume(
"to",
true);
2146 const int start = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2148 std::vector<u32> res;
2151 res.push_back((
u32)i);
2156 Result<std::vector<std::vector<u32>>> VHDLParser::parse_signal_ranges(TokenStream<ci_string>& signal_stream)
const
2158 std::vector<std::vector<u32>> ranges;
2159 const u32 line_number = signal_stream.peek().number;
2161 const Token<ci_string> type_name = signal_stream.consume();
2162 if (type_name ==
"std_logic")
2167 signal_stream.consume(
"(",
true);
2168 TokenStream<ci_string> signal_bounds_stream = signal_stream.extract_until(
")");
2173 TokenStream<ci_string> bound_stream = signal_bounds_stream.extract_until(
",");
2174 ranges.emplace_back(parse_range(bound_stream));
2175 }
while (signal_bounds_stream.consume(
","));
2177 signal_stream.consume(
")",
true);
2179 if (id_to_dim.find(type_name) != id_to_dim.end())
2181 const size_t dimension = id_to_dim.at(type_name);
2183 if (ranges.size() != dimension)
2185 return ERR(
"could not parse signal ranges: mismatch of dimensions (line " + std::to_string(line_number) +
")");
2190 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) +
")");
2196 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
2199 if (ranges.size() > dimension)
2201 for (
const u32 index : ranges[dimension])
2203 expand_ranges_recursively(expanded_names, current_name +
"(" + core_strings::to<ci_string>(std::to_string(
index)) +
")", ranges, dimension + 1);
2209 expanded_names.push_back(current_name);
2213 std::vector<VHDLParser::ci_string> VHDLParser::expand_ranges(
const ci_string&
name,
const std::vector<std::vector<u32>>& ranges)
const
2215 std::vector<ci_string> res;
2217 expand_ranges_recursively(res,
name, ranges, 0);
2222 Result<std::vector<BooleanFunction::Value>> VHDLParser::get_binary_vector(std::string value)
const
2228 std::vector<BooleanFunction::Value> result;
2231 if (value.at(0) !=
'\"')
2233 prefix = value.at(0);
2234 number = value.substr(2, value.rfind(
'\"') - 2);
2239 number = value.substr(1, value.rfind(
'\"') - 1);
2243 switch (prefix.at(0))
2246 for (
auto it = number.rbegin(); it != number.rend(); it++)
2249 if (c ==
'0' || c ==
'1' || c ==
'Z' || c ==
'X')
2251 result.push_back(bin_map.at(c));
2255 return ERR(
"could not convert string to binary vector: invalid character within binary number literal '" + value +
"'");
2262 for (
auto it = number.rbegin(); it != number.rend(); it++)
2265 if ((c >=
'0' && c <=
'7') || c ==
'X' || c ==
'Z')
2267 const auto& bits = oct_map.at(c);
2268 result.insert(result.end(), bits.begin(), bits.end());
2272 return ERR(
"could not convert string to binary vector: invalid character within octal number literal '" + value +
"'");
2280 for (
const char c : number)
2282 if ((c >=
'0' && c <=
'9'))
2284 tmp_val = (tmp_val * 10) + (c -
'0');
2288 return ERR(
"could not convert string to binary vector: invalid character within decimal number literal '" + value +
"'");
2294 result.push_back(((tmp_val & 1) == 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
2296 }
while (tmp_val != 0);
2301 for (
auto it = number.rbegin(); it != number.rend(); it++)
2304 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F') || c ==
'X' || c ==
'Z')
2306 const auto& bits = hex_map.at(c);
2307 result.insert(result.end(), bits.begin(), bits.end());
2311 return ERR(
"could not convert string to binary vector: invalid character within hexadecimal number literal '" + value +
"'");
2318 return ERR(
"could not convert string to binary vector: invalid base '" + prefix +
"' within number literal '" + value +
"'");
2325 Result<std::string> VHDLParser::get_hex_from_literal(
const Token<ci_string>& value_token)
const
2327 const u32 line_number = value_token.number;
2335 if (value.at(0) !=
'\"')
2337 prefix = value.at(0);
2338 number = value.substr(2, value.rfind(
'\"') - 2);
2343 number = value.substr(1, value.rfind(
'\"') - 1);
2347 switch (prefix.at(0))
2350 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'1'); }))
2352 return ERR(
"could not convert token to hexadecimal string: invalid character within binary number literal '" + core_strings::to<std::string>(value) +
"' (line "
2353 + std::to_string(line_number) +
")");
2361 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'7'); }))
2363 return ERR(
"could not convert token to hexadecimal string: invalid character within ocatl number literal '" + core_strings::to<std::string>(value) +
"' (line "
2364 + std::to_string(line_number) +
")");
2372 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'9'); }))
2374 return ERR(
"could not convert token to hexadecimal string: invalid character within decimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2375 + std::to_string(line_number) +
")");
2385 for (
const char c : number)
2387 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F'))
2393 return ERR(
"could not convert token to hexadecimal string: invalid character within hexadecimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2394 + std::to_string(line_number) +
")");
2402 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)
2403 +
"' (line " + std::to_string(line_number) +
")");
2407 std::stringstream ss;
2408 ss << std::uppercase << std::hex << stoull(core_strings::to<std::string>(number), 0, base);
2409 return OK(ss.str());
2412 Result<std::vector<VHDLParser::assignment_t>> VHDLParser::parse_assignment_expression(TokenStream<ci_string>&& stream)
const
2422 std::vector<TokenStream<ci_string>> parts;
2424 if (stream.size() == 0)
2430 if (stream.consume(
"("))
2434 parts.push_back(stream.extract_until(
","));
2435 }
while (stream.consume(
",",
false));
2437 stream.consume(
")",
true);
2441 parts.push_back(stream);
2444 std::vector<assignment_t> result;
2445 result.reserve(parts.size());
2447 for (
auto it = parts.rbegin(); it != parts.rend(); it++)
2449 TokenStream<ci_string>& part_stream = *it;
2451 const Token<ci_string> signal_name_token = part_stream.consume();
2452 ci_string signal_name = signal_name_token.string;
2458 if (
auto res = get_binary_vector(core_strings::to<std::string>(signal_name_token.string)); res.is_error())
2460 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) +
")");
2464 result.push_back(std::move(res.get()));
2467 else if (signal_name ==
"'0'")
2469 result.push_back(numeral_t({BooleanFunction::Value::ZERO}));
2471 else if (signal_name ==
"'1'")
2473 result.push_back(numeral_t({BooleanFunction::Value::ONE}));
2475 else if (signal_name ==
"'X'")
2477 result.push_back(numeral_t({BooleanFunction::Value::X}));
2479 else if (signal_name ==
"'Z'")
2481 result.push_back(numeral_t({BooleanFunction::Value::Z}));
2487 if (part_stream.consume(
"("))
2489 std::vector<std::vector<u32>> ranges;
2490 u32 closing_pos = part_stream.find_next(
")");
2493 TokenStream<ci_string> range_stream = part_stream.extract_until(
",", closing_pos);
2494 ranges.emplace_back(parse_range(range_stream));
2496 }
while (part_stream.consume(
",",
false));
2497 part_stream.consume(
")",
true);
2498 result.push_back(ranged_identifier_t({std::move(signal_name), std::move(ranges)}));
2503 result.push_back(std::move(signal_name));
2511 Result<std::vector<VHDLParser::ci_string>> VHDLParser::expand_assignment_expression(VhdlEntity* vhdl_entity,
const std::vector<assignment_t>& vars)
const
2513 std::vector<ci_string> result;
2514 for (
const auto& var : vars)
2523 std::vector<std::vector<u32>> ranges;
2525 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(*
identifier); signal_it != vhdl_entity->m_signals_by_name.end())
2527 ranges = signal_it->second->m_ranges;
2529 else if (
const auto port_it = vhdl_entity->m_ports_by_identifier.find(*
identifier); port_it != vhdl_entity->m_ports_by_identifier.end())
2531 ranges = port_it->second->m_ranges;
2535 return ERR(
"could not expand assignment expression': '" + core_strings::to<std::string>(*
identifier) +
"' is neither a signal nor a port of entity '"
2536 + core_strings::to<std::string>(vhdl_entity->m_name) +
"'");
2539 std::vector<ci_string> expanded = expand_ranges(*
identifier, ranges);
2540 result.insert(result.end(), expanded.begin(), expanded.end());
2542 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier !=
nullptr)
2544 std::vector<ci_string> expanded = expand_ranges(ranged_identifier->first, ranged_identifier->second);
2545 result.insert(result.end(), expanded.begin(), expanded.end());
2547 else if (
const numeral_t* numeral = std::get_if<numeral_t>(&var); numeral !=
nullptr)
2549 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)
void set_design_name(const std::string &name)
void enable_automatic_net_checks(bool enable_checks=true)
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.
std::unique_ptr< BasePluginInterface > instance