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;
1364 left_port.push_back(*identifier);
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())
1591 for (
auto [
module, index] : it->second)
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)
2514 if (
const identifier_t* identifier = std::get_if<identifier_t>(&var); identifier !=
nullptr)
2516 if (identifier->empty())
2518 result.push_back(*identifier);
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)
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such entity
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.
CORE_API T replace(const T &str, const T &search, const T &replace)
CORE_API bool ends_with(const T &s, const T &end)
CORE_API bool is_digits(const T &s)
CORE_API bool starts_with(const T &s, const T &start)
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
CORE_API bool is_integer(const T &s)
CORE_API bool is_floating_point(const T &s)
CORE_API T to_upper(const T &s)
std::vector< PinInformation > pins
This file contains various functions to create and load netlists.