21 bool is_std_logic_state_char(
char c)
23 const char l = (c ==
'-') ?
'-' :
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
24 return l ==
'x' || l ==
'z' || l ==
'u' || l ==
'l' || l ==
'h' || l ==
'w' || l ==
'-';
28 bool is_double_strict(
const std::string& s)
37 (void)std::stod(s, &consumed);
38 return consumed == s.size();
52 m_attribute_buffer.clear();
53 m_attribute_types.clear();
57 ifs.open(file_path.string(), std::ifstream::in);
60 return ERR(
"unable to open VHDL file '" + file_path.string() +
"'");
72 if (
const auto res = parse_tokens(); res.is_error())
74 return ERR_APPEND(res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"'");
79 if (e.line_number != (
u32)-1)
81 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));
85 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': " + core_strings::to<std::string>(e.message));
89 if (m_entities.empty())
91 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': it does not contain any entities");
95 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
98 for (
const auto& port : vhdl_entity->m_ports)
100 if (!port->m_ranges.empty())
102 port->m_expanded_identifiers = expand_ranges(port->m_identifier, port->m_ranges);
103 vhdl_entity->m_expanded_port_identifiers.insert(port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
107 port->m_expanded_identifiers = {port->m_identifier};
108 vhdl_entity->m_expanded_port_identifiers.insert(port->m_identifier);
113 for (
auto& signal : vhdl_entity->m_signals)
115 if (!signal->m_ranges.empty())
117 signal->m_expanded_names = expand_ranges(signal->m_name, signal->m_ranges);
121 signal->m_expanded_names = std::vector<ci_string>({signal->m_name});
126 for (
auto& assignment : vhdl_entity->m_assignments)
128 auto left_res = expand_assignment_expression(vhdl_entity, assignment.m_variable);
129 if (left_res.is_error())
131 return ERR_APPEND(left_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand signal assignment");
133 const std::vector<ci_string> left_signals = left_res.get();
135 auto right_res = expand_assignment_expression(vhdl_entity, assignment.m_assignment);
136 if (right_res.is_error())
138 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand signal assignment");
140 const std::vector<ci_string> right_signals = right_res.get();
142 u32 left_size = left_signals.size();
143 u32 right_size = right_signals.size();
144 if (left_signals.empty() || right_signals.empty())
146 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': failed to expand assignments within entity '" + core_strings::to<std::string>(entity_name) +
"'");
148 else if (left_size != right_size)
150 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': assignment width mismatch within entity '" + core_strings::to<std::string>(entity_name) +
"'");
154 for (
u32 i = 0; i < right_size; i++)
156 vhdl_entity->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i), right_signals.at(i)));
163 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
165 for (
auto&
instance : vhdl_entity->m_instances)
167 if (
auto entity_it = m_entities_by_name.find(
instance->m_type); entity_it != m_entities_by_name.end())
171 if (!
instance->m_port_assignments.empty())
174 if (
instance->m_port_assignments.front().m_port.has_value())
176 for (
const auto& port_assignment :
instance->m_port_assignments)
178 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
179 if (right_res.is_error())
181 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
183 const std::vector<ci_string> right_port = right_res.get();
184 if (!right_port.empty())
186 std::vector<ci_string> left_port;
187 if (
const identifier_t*
identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value()));
identifier !=
nullptr)
189 if (
const auto it = entity_it->second->m_ports_by_identifier.find(*
identifier); it != entity_it->second->m_ports_by_identifier.end())
191 left_port = it->second->m_expanded_identifiers;
195 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to assign signal to port '" + core_strings::to<std::string>(*
identifier)
196 +
"' as it is not a port of entity '" + core_strings::to<std::string>(entity_it->first) +
"'");
199 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier !=
nullptr)
201 left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
205 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
208 if (left_port.empty())
210 return ERR(
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
213 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
215 for (
u32 i = 0; i < max_size; i++)
217 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
225 std::vector<ci_string> ports;
226 for (
const auto& port : m_entities_by_name.at(
instance->m_type)->m_ports)
228 ports.insert(ports.end(), port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
231 auto port_it = ports.begin();
233 for (
const auto& port_assignment :
instance->m_port_assignments)
235 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
236 if (right_res.is_error())
238 return ERR_APPEND(right_res.get_error(),
"could not parse VHDL file '" + m_path.string() +
"': unable to expand entity port assignment");
240 const std::vector<ci_string> right_port = right_res.get();
241 if (!right_port.empty())
243 std::vector<ci_string> left_port;
245 for (
u32 i = 0; i < right_port.size() && port_it != ports.end(); i++)
247 left_port.push_back(*port_it++);
250 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
252 for (
u32 i = 0; i < max_size; i++)
254 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
271 m_netlist = result.get();
272 if (m_netlist ==
nullptr)
274 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create empty netlist");
277 m_gate_types.clear();
278 m_gnd_gate_types.clear();
279 m_vcc_gate_types.clear();
280 m_instance_name_occurrences.clear();
281 m_signal_name_occurrences.clear();
282 m_net_by_name.clear();
283 m_nets_to_merge.clear();
284 m_module_ports.clear();
285 m_module_port_by_net.clear();
286 for (
const auto& vhdl_entity : m_entities)
288 for (
const auto&
instance : vhdl_entity->m_instances)
292 instance->m_expanded_port_assignments.clear();
300 m_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
304 m_gnd_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
308 m_vcc_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
313 if (m_zero_net ==
nullptr)
315 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create zero net");
317 m_net_by_name[core_strings::to<ci_string>(m_zero_net->
get_name())] = m_zero_net;
320 if (m_one_net ==
nullptr)
322 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to create one net");
324 m_net_by_name[core_strings::to<ci_string>(m_one_net->
get_name())] = m_one_net;
327 std::map<ci_string, u32> entity_name_to_refereneces;
328 for (
const auto& [_name, vhdl_entity] : m_entities_by_name)
330 for (
const auto&
instance : vhdl_entity->m_instances)
332 if (
const auto it = m_entities_by_name.find(
instance->m_type); it != m_entities_by_name.end())
334 entity_name_to_refereneces[it->first]++;
339 std::vector<ci_string> top_module_candidates;
340 for (
const auto& [
name, _entity] : m_entities_by_name)
342 if (entity_name_to_refereneces.find(
name) == entity_name_to_refereneces.end())
344 top_module_candidates.push_back(
name);
348 if (top_module_candidates.empty())
350 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': unable to find any top module candidates");
353 if (top_module_candidates.size() > 1)
355 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");
359 VhdlEntity* top_entity = m_entities_by_name.at(top_module_candidates.front());
361 if (
const auto res = construct_netlist(top_entity); res.is_error())
363 return ERR_APPEND(res.get_error(),
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"'");
370 if (m_gnd_gate_types.empty())
372 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");
374 GateType* gnd_type = m_gnd_gate_types.begin()->second;
380 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark GND gate");
385 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to GND gate");
395 if (m_vcc_gate_types.empty())
397 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");
399 GateType* vcc_type = m_vcc_gate_types.begin()->second;
405 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': failed to mark VCC gate");
410 return ERR(
"could not instantiate VHDL netlist '" + m_path.string() +
"' with gate library '" + gate_library->
get_name() +
"': could not add source to VCC gate");
419 std::queue<Net*> nets_to_be_deleted;
423 const u32 num_of_sources =
net->get_num_of_sources();
424 const u32 num_of_destinations =
net->get_num_of_destinations();
425 const bool no_source = num_of_sources == 0 && !(
net->is_global_input_net() && num_of_destinations != 0);
426 const bool no_destination = num_of_destinations == 0 && !(
net->is_global_output_net() && num_of_sources != 0);
427 if (no_source && no_destination)
429 nets_to_be_deleted.push(
net);
433 while (!nets_to_be_deleted.empty())
435 Net*
net = nets_to_be_deleted.front();
436 nets_to_be_deleted.pop();
442 return OK(std::move(result));
449 void VHDLParser::tokenize()
451 std::vector<Token<core_strings::CaseInsensitiveString>> parsed_tokens;
452 const std::string delimiters =
",(): ;=><&";
457 bool in_string =
false;
458 bool escaped =
false;
460 while (std::getline(m_fs, line))
463 if (line.find(
"--") != std::string::npos)
465 line = line.substr(0, line.find(
"--"));
469 if (in_string ==
false && c ==
'\\')
474 else if (escaped && std::isspace(c))
479 else if (!escaped && c ==
'"')
481 in_string = !in_string;
484 if (delimiters.find(c) == std::string::npos || escaped || in_string)
490 if (!current_token.empty())
492 if (parsed_tokens.size() > 1 &&
utils::is_digits(parsed_tokens.at(parsed_tokens.size() - 2).string) && parsed_tokens.at(parsed_tokens.size() - 1) ==
"."
495 parsed_tokens.pop_back();
496 parsed_tokens.back() +=
"." + current_token;
500 parsed_tokens.emplace_back(line_number, current_token);
502 current_token.clear();
505 if (!parsed_tokens.empty())
507 if (c ==
'=' && parsed_tokens.back() ==
"<")
509 parsed_tokens.back() =
"<=";
512 else if (c ==
'=' && parsed_tokens.back() ==
":")
514 parsed_tokens.back() =
":=";
517 else if (c ==
'>' && parsed_tokens.back() ==
"=")
519 parsed_tokens.back() =
"=>";
524 if (!std::isspace(c))
530 if (!current_token.empty())
532 parsed_tokens.emplace_back(line_number, current_token);
533 current_token.clear();
536 m_token_stream = TokenStream(parsed_tokens, {
"("}, {
")"});
539 Result<std::monostate> VHDLParser::parse_tokens()
543 if (m_token_stream.
peek() ==
"library" || m_token_stream.
peek() ==
"use")
547 else if (m_token_stream.
peek() ==
"entity")
549 if (
const auto res = parse_entity(); res.is_error())
551 return ERR_APPEND(res.get_error(),
"could not parse tokens");
554 else if (m_token_stream.
peek() ==
"architecture")
556 if (
const auto res = parse_architecture(); res.is_error())
558 return ERR_APPEND(res.get_error(),
"could not parse tokens");
563 return ERR(
"could not parse tokens: unexpected token '" + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' in global scope (line "
564 + std::to_string(m_token_stream.
peek().number) +
")");
571 void VHDLParser::parse_library()
573 if (m_token_stream.
peek() ==
"use")
575 m_token_stream.
consume(
"use",
true);
576 auto lib = m_token_stream.
consume().string;
577 m_token_stream.
consume(
";",
true);
580 lib =
utils::trim(lib.substr(0, lib.rfind(
".") + 1));
581 m_libraries.insert(lib);
586 m_token_stream.
consume(
";",
true);
590 Result<std::monostate> VHDLParser::parse_entity()
592 m_token_stream.
consume(
"entity",
true);
593 const u32 line_number = m_token_stream.
peek().number;
594 const ci_string entity_name = m_token_stream.
consume().string;
597 if (
const auto it = m_entities_by_name.find(entity_name); it != m_entities_by_name.end())
599 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"' (line " + std::to_string(line_number) +
"): an entity with name '"
600 + core_strings::to<std::string>(entity_name) +
"' does already exist (line " + std::to_string(it->second->m_line_number) +
")");
603 m_token_stream.
consume(
"is",
true);
604 auto vhdl_entity = std::make_unique<VhdlEntity>();
605 VhdlEntity* vhdl_entity_raw = vhdl_entity.get();
606 vhdl_entity_raw->m_line_number = line_number;
607 vhdl_entity_raw->m_name = entity_name;
609 m_attribute_buffer.clear();
611 Token<ci_string> next_token = m_token_stream.
peek();
612 while (next_token !=
"end")
614 if (next_token ==
"generic")
617 m_token_stream.
consume(
";",
true);
619 else if (next_token ==
"port")
621 if (
const auto res = parse_port_definitons(vhdl_entity_raw); res.is_error())
624 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse port definition (line " + std::to_string(next_token.number) +
")");
627 else if (next_token ==
"attribute")
629 if (
const auto res = parse_attribute(); res.is_error())
632 "could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': failed to parse attribute (line " + std::to_string(next_token.number) +
")");
637 return ERR(
"could not parse entity '" + core_strings::to<std::string>(entity_name) +
"': unexpected token '" + core_strings::to<std::string>(next_token.string)
638 +
"' in entity definition (line " + std::to_string(next_token.number) +
")");
641 next_token = m_token_stream.
peek();
644 m_token_stream.
consume(
"end",
true);
646 m_token_stream.
consume(
";",
true);
649 m_entities.push_back(std::move(vhdl_entity));
650 m_entities_by_name[entity_name] = vhdl_entity_raw;
651 m_last_entity = entity_name;
656 Result<std::monostate> VHDLParser::parse_port_definitons(VhdlEntity* vhdl_entity)
659 m_token_stream.
consume(
"port",
true);
660 m_token_stream.
consume(
"(",
true);
663 while (port_def_stream.remaining() > 0)
665 std::vector<core_strings::CaseInsensitiveString> port_names;
668 const auto line_number = port_def_stream.
peek().number;
673 port_names.push_back(port_def_stream.consume().string);
674 }
while (port_def_stream.consume(
",",
false));
676 port_def_stream.consume(
":",
true);
680 const ci_string direction_str = port_def_stream.consume().string;
681 if (direction_str ==
"in")
685 else if (direction_str ==
"out")
689 else if (direction_str ==
"inout")
695 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)
700 TokenStream<ci_string> port_stream = port_def_stream.extract_until(
";");
701 std::vector<std::vector<u32>> ranges;
702 if (
auto res = parse_signal_ranges(port_stream); res.is_error())
704 return ERR_APPEND(res.get_error(),
"could not parse port definitions: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
711 port_def_stream.consume(
";", port_def_stream.remaining() > 0);
713 for (
const ci_string& port_name : port_names)
715 auto port = std::make_unique<VhdlPort>();
716 port->m_identifier = port_name;
718 port->m_ranges = ranges;
719 vhdl_entity->m_ports_by_identifier[port->m_identifier] = port.get();
720 vhdl_entity->m_ports.push_back(std::move(port));
722 if (vhdl_entity->m_signals_by_name.find(port_name) == vhdl_entity->m_signals_by_name.end())
724 auto signal = std::make_unique<VhdlSignal>();
725 signal->m_name = port_name;
728 signal->m_ranges = ranges;
730 vhdl_entity->m_signals_by_name[port_name] = signal.get();
731 vhdl_entity->m_signals.push_back(std::move(signal));
736 m_token_stream.
consume(
")",
true);
737 m_token_stream.
consume(
";",
true);
742 Result<std::monostate> VHDLParser::parse_attribute()
744 const u32 line_number = m_token_stream.
peek().number;
746 m_token_stream.
consume(
"attribute",
true);
747 const ci_string attribute_name = m_token_stream.
consume().string;
749 if (m_token_stream.
peek() ==
":")
751 m_token_stream.
consume(
":",
true);
752 m_attribute_types[attribute_name] = m_token_stream.
join_until(
";",
" ");
753 m_token_stream.
consume(
";",
true);
755 else if (m_token_stream.
peek() ==
"of" && m_token_stream.
peek(2) ==
":")
757 AttributeTarget target_class;
758 m_token_stream.
consume(
"of",
true);
759 const ci_string attribute_target = m_token_stream.
consume().string;
760 m_token_stream.
consume(
":",
true);
761 const ci_string attribute_class = m_token_stream.
consume().string;
762 m_token_stream.
consume(
"is",
true);
763 ci_string attribute_value = m_token_stream.
join_until(
";",
" ").string;
764 m_token_stream.
consume(
";",
true);
765 ci_string attribute_type;
767 if (attribute_value[0] ==
'\"' && attribute_value.back() ==
'\"')
769 attribute_value = attribute_value.substr(1, attribute_value.size() - 2);
772 if (
const auto type_it = m_attribute_types.find(attribute_name); type_it == m_attribute_types.end())
774 log_warning(
"vhdl_parser",
"attribute {} has unknown base type in line {}.", attribute_name, line_number);
775 attribute_type =
"unknown";
779 attribute_type = type_it->second;
782 if (attribute_class ==
"entity")
784 target_class = AttributeTarget::ENTITY;
786 else if (attribute_class ==
"label")
788 target_class = AttributeTarget::INSTANCE;
790 else if (attribute_class ==
"signal")
792 target_class = AttributeTarget::SIGNAL;
796 log_warning(
"vhdl_parser",
"unsupported attribute class '{}' in line {}, ignoring attribute.", attribute_class, line_number);
800 VhdlDataEntry attribute;
801 attribute.m_name = core_strings::to<std::string>(attribute_name);
802 attribute.m_type = core_strings::to<std::string>(attribute_type);
803 attribute.m_value = core_strings::to<std::string>(attribute_value);
804 m_attribute_buffer[target_class].emplace(attribute_target, attribute);
808 return ERR(
"could not parse attribute: malformed attribute definition (line " + std::to_string(line_number) +
")");
814 Result<std::monostate> VHDLParser::parse_architecture()
816 m_token_stream.
consume(
"architecture",
true);
818 m_token_stream.
consume(
"of",
true);
820 u32 line_number = m_token_stream.
peek().number;
821 const auto entity_name_token = m_token_stream.
consume();
823 if (
const auto it = m_entities_by_name.find(entity_name_token.string); it == m_entities_by_name.end())
825 return ERR(
"could not parse architecture: architecture refers to non-existent entity '" + core_strings::to<std::string>(entity_name_token.string) +
"' (line "
826 + std::to_string(entity_name_token.number) +
")");
830 VhdlEntity* vhdl_entity = it->second;
832 m_token_stream.
consume(
"is",
true);
834 if (
const auto res = parse_architecture_header(vhdl_entity); res.is_error())
836 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture header (line " + std::to_string(line_number) +
")");
838 if (
const auto res = parse_architecture_body(vhdl_entity); res.is_error())
840 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to parse architecture body (line " + std::to_string(line_number) +
")");
842 if (
const auto res = assign_attributes(vhdl_entity); res.is_error())
844 return ERR_APPEND(res.get_error(),
"could not parse architecture: unable to assign attributes (line " + std::to_string(line_number) +
")");
851 Result<std::monostate> VHDLParser::parse_architecture_header(VhdlEntity* vhdl_entity)
853 auto next_token = m_token_stream.
peek();
854 while (next_token !=
"begin")
856 if (next_token ==
"signal")
858 if (
const auto res = parse_signal_definition(vhdl_entity); res.is_error())
860 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse signal definition (line " + std::to_string(next_token.number) +
")");
863 else if (next_token ==
"component")
866 m_token_stream.
consume(
"component",
true);
867 const ci_string component_name = m_token_stream.
consume().string;
869 m_token_stream.
consume(
"end",
true);
870 m_token_stream.
consume(
"component",
true);
871 if (m_token_stream.
peek() !=
";")
873 m_token_stream.
consume(component_name,
true);
875 m_token_stream.
consume(
";",
true);
877 else if (next_token ==
"attribute")
879 if (
const auto res = parse_attribute(); res.is_error())
881 return ERR_APPEND(res.get_error(),
"could not parse architecture header: unable to parse attribute (line " + std::to_string(next_token.number) +
")");
886 return ERR(
"could not parse architecture header: unexpected token '" + core_strings::to<std::string>(next_token.string) +
"' (line " + std::to_string(next_token.number) +
")");
889 next_token = m_token_stream.
peek();
895 Result<std::monostate> VHDLParser::parse_signal_definition(VhdlEntity* vhdl_entity)
897 m_token_stream.
consume(
"signal",
true);
898 u32 line_number = m_token_stream.
peek().number;
901 std::vector<ci_string> signal_names;
904 signal_names.push_back(m_token_stream.
consume().string);
905 }
while (m_token_stream.
consume(
",",
false));
907 m_token_stream.
consume(
":",
true);
910 TokenStream<ci_string> signal_stream = m_token_stream.
extract_until(
";");
911 std::vector<std::vector<u32>> ranges;
912 if (
auto res = parse_signal_ranges(signal_stream); res.is_error())
914 return ERR_APPEND(res.get_error(),
"could not parse signal definition: unable to parse signal ranges (line " + std::to_string(line_number) +
")");
921 m_token_stream.
consume(
";",
true);
923 for (
const auto& signal_name : signal_names)
925 if (vhdl_entity->m_signals_by_name.find(signal_name) == vhdl_entity->m_signals_by_name.end())
927 auto signal = std::make_unique<VhdlSignal>();
928 signal->m_name = signal_name;
929 signal->m_ranges = ranges;
930 vhdl_entity->m_signals_by_name[signal_name] = signal.get();
931 vhdl_entity->m_signals.push_back(std::move(signal));
938 Result<std::monostate> VHDLParser::parse_architecture_body(VhdlEntity* vhdl_entity)
940 m_token_stream.
consume(
"begin",
true);
941 auto next_token = m_token_stream.
peek();
943 while (next_token !=
"end")
946 if (m_token_stream.
peek(1) ==
":")
948 if (
const auto res = parse_instance(vhdl_entity); res.is_error())
951 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse instance (line "
952 + std::to_string(next_token.number) +
")");
958 if (
const auto res = parse_assignment(vhdl_entity); res.is_error())
961 "could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unable to parse assignment (line "
962 + std::to_string(next_token.number) +
")");
967 return ERR(
"could not parse architecture body of entity '" + core_strings::to<std::string>(vhdl_entity->m_name) +
"': unexpected token '"
968 + core_strings::to<std::string>(m_token_stream.
peek().string) +
"' (line " + std::to_string(next_token.number) +
")");
971 next_token = m_token_stream.
peek();
974 m_token_stream.
consume(
"end",
true);
976 m_token_stream.
consume(
";",
true);
981 Result<std::monostate> VHDLParser::parse_assignment(VhdlEntity* vhdl_entity)
983 u32 line_number = m_token_stream.
peek().number;
984 VhdlAssignment assignment;
986 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
"<=")); res.is_error())
988 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
992 assignment.m_variable = res.get();
994 m_token_stream.
consume(
"<=",
true);
995 if (
auto res = parse_assignment_expression(m_token_stream.
extract_until(
";")); res.is_error())
997 return ERR_APPEND(res.get_error(),
"could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) +
")");
1001 assignment.m_assignment = res.get();
1003 m_token_stream.
consume(
";",
true);
1005 vhdl_entity->m_assignments.push_back(std::move(assignment));
1009 Result<std::monostate> VHDLParser::parse_instance(VhdlEntity* vhdl_entity)
1011 auto instance = std::make_unique<VhdlInstance>();
1012 u32 line_number = m_token_stream.
peek().number;
1014 m_token_stream.
consume(
":",
true);
1017 if (m_token_stream.
peek() ==
"entity")
1019 m_token_stream.
consume(
"entity",
true);
1021 if (
const size_t pos =
instance->m_type.find(
'.'); pos != std::string::npos)
1025 if (m_entities_by_name.find(
instance->m_type) == m_entities_by_name.end())
1027 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 '"
1028 + core_strings::to<std::string>(
instance->m_type) +
"' does not exist (line " + std::to_string(line_number) +
")");
1031 else if (m_token_stream.
peek() ==
"component")
1033 m_token_stream.
consume(
"component",
true);
1042 for (
const auto& lib : m_libraries)
1051 if (!prefix.empty())
1057 if (m_token_stream.
consume(
"generic"))
1059 line_number = m_token_stream.
peek().number;
1060 if (
const auto res = parse_generic_assign(
instance.get()); res.is_error())
1063 "could not parse instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type)
1064 +
"': unable to parse generic assignment (line " + std::to_string(line_number) +
")");
1068 if (m_token_stream.
peek() ==
"port")
1070 if (
const auto res = parse_port_assign(
instance.get()); res.is_error())
1073 "could not parse instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type)
1074 +
"': unable to parse port assignment (line " + std::to_string(line_number) +
")");
1079 vhdl_entity->m_instances.push_back(std::move(
instance));
1081 m_token_stream.
consume(
";",
true);
1086 Result<std::monostate> VHDLParser::parse_port_assign(VhdlInstance*
instance)
1088 u32 line_number = m_token_stream.
peek().number;
1089 m_token_stream.
consume(
"port",
true);
1090 m_token_stream.
consume(
"map",
true);
1091 m_token_stream.
consume(
"(",
true);
1092 TokenStream<ci_string> port_stream = m_token_stream.
extract_until(
")");
1093 m_token_stream.
consume(
")",
true);
1097 while (port_stream.remaining() > 0)
1099 TokenStream<ci_string> left_stream = port_stream.extract_until(
"=>");
1100 port_stream.consume(
"=>",
true);
1101 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1102 port_stream.consume(
",", port_stream.remaining() > 0);
1104 if (!right_stream.consume(
"open"))
1106 VhdlPortAssignment port_assignment;
1108 if (
auto res = parse_assignment_expression(std::move(left_stream)); res.is_error())
1110 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse port (line " + std::to_string(line_number) +
")");
1115 port_assignment.m_port = res.get().front();
1118 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1120 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1124 port_assignment.m_assignment = res.get();
1127 instance->m_port_assignments.push_back(std::move(port_assignment));
1133 while (port_stream.remaining() > 0)
1135 TokenStream<ci_string> right_stream = port_stream.extract_until(
",");
1136 port_stream.consume(
",", port_stream.remaining() > 0);
1138 if (!right_stream.consume(
"open"))
1140 VhdlPortAssignment port_assignment;
1142 if (
auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1144 return ERR_APPEND(res.get_error(),
"could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) +
")");
1148 port_assignment.m_assignment = res.get();
1151 instance->m_port_assignments.push_back(std::move(port_assignment));
1155 VhdlPortAssignment port_assignment;
1156 port_assignment.m_assignment.push_back(
"");
1157 instance->m_port_assignments.push_back(std::move(port_assignment));
1165 Result<std::monostate> VHDLParser::parse_generic_assign(VhdlInstance*
instance)
1167 m_token_stream.
consume(
"map",
true);
1168 m_token_stream.
consume(
"(",
true);
1169 TokenStream<ci_string> generic_stream = m_token_stream.
extract_until(
")");
1170 m_token_stream.
consume(
")",
true);
1174 static const std::vector<std::pair<std::string, std::string>> vhdl_time_units = {
1185 while (generic_stream.remaining() > 0)
1187 VhdlDataEntry
generic;
1189 generic.m_line_number = generic_stream.peek().number;
1190 generic.m_name = core_strings::to<std::string>(generic_stream.join_until(
"=>",
"").string);
1191 generic_stream.consume(
"=>",
true);
1192 const auto rhs = generic_stream.join_until(
",",
"");
1193 generic_stream.consume(
",", generic_stream.remaining() > 0);
1194 const std::string rhs_str = core_strings::to<std::string>(rhs.string);
1196 bool classified =
false;
1200 if (rhs ==
"true" || rhs ==
"false")
1202 const std::string norm = (rhs ==
"true") ?
"true" :
"false";
1204 if (param_res.is_error())
1206 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1208 generic.m_value = norm;
1209 generic.m_type =
"boolean";
1210 generic.m_parameter = param_res.get();
1217 if (param_res.is_error())
1219 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1221 generic.m_value = rhs_str;
1222 generic.m_type =
"integer";
1223 generic.m_parameter = param_res.get();
1227 else if (is_double_strict(rhs_str))
1230 if (param_res.is_error())
1232 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1234 generic.m_value = rhs_str;
1235 generic.m_type =
"floating_point";
1236 generic.m_parameter = param_res.get();
1242 for (
const auto& [vhdl_unit, param_unit] : vhdl_time_units)
1244 if (rhs_str.size() <= vhdl_unit.size() || !
utils::ends_with(rhs.string, ci_string(vhdl_unit.c_str())))
1248 const std::string num_part = rhs_str.substr(0, rhs_str.size() - vhdl_unit.size());
1254 if (param_res.is_error())
1256 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1258 generic.m_value = num_part + param_unit;
1259 generic.m_type =
"time";
1260 generic.m_parameter = param_res.get();
1267 if (!classified && rhs_str.size() >= 2 && rhs_str.front() ==
'"' && rhs_str.back() ==
'"')
1270 if (param_res.is_error())
1272 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1274 generic.m_value = rhs_str.substr(1, rhs_str.size() - 2);
1275 generic.m_type =
"string";
1276 generic.m_parameter = param_res.get();
1283 if (!classified && rhs_str.size() == 3 && rhs_str.front() ==
'\'' && rhs_str.back() ==
'\'')
1285 const char c = rhs_str[1];
1286 if (c ==
'0' || c ==
'1')
1289 if (param_res.is_error())
1291 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1293 generic.m_value = std::string(
"0b") + c;
1294 generic.m_type =
"bit_value";
1295 generic.m_parameter = param_res.get();
1298 else if (is_std_logic_state_char(c))
1301 if (param_res.is_error())
1303 return ERR_APPEND(param_res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1305 generic.m_value = std::string(
"0b") + c;
1306 generic.m_type =
"std_logic";
1307 generic.m_parameter = param_res.get();
1312 return ERR(
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"': character literal '" + rhs_str
1313 +
"' is not a valid bit or std_logic value (line " + std::to_string(
generic.m_line_number) +
")");
1322 if (!classified && rhs_str.size() >= 4 && rhs_str.back() ==
'"' && rhs_str[1] ==
'"')
1324 const char base_char =
static_cast<char>(std::toupper(
static_cast<unsigned char>(rhs_str[0])));
1325 const std::string raw = rhs_str.substr(2, rhs_str.size() - 3);
1327 digits.reserve(raw.size());
1337 return ERR(
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"': base-prefixed literal '" + rhs_str
1338 +
"' has no digits (line " + std::to_string(
generic.m_line_number) +
")");
1341 const auto classify_base = [&](
int bits_per_digit,
const std::string& numeric_set,
char param_prefix) -> Result<std::monostate> {
1342 bool has_state =
false;
1343 for (
char c : digits)
1345 const char l = (c ==
'-') ?
'-' :
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
1346 if (numeric_set.find(l) != std::string::npos)
1350 if (is_std_logic_state_char(c))
1355 return ERR(
"base-prefixed literal '" + rhs_str +
"' contains invalid digit '" + std::string(1, c) +
"'");
1357 const u16 total_bits =
static_cast<u16>(digits.size() * bits_per_digit);
1358 const std::string value_with_prefix = std::string(
"0") + param_prefix + digits;
1362 if (param_res.is_error())
1364 return ERR(param_res.get_error());
1366 generic.m_value = value_with_prefix;
1367 generic.m_type =
"std_logic_vector";
1368 generic.m_parameter = param_res.get();
1373 if (param_res.is_error())
1375 return ERR(param_res.get_error());
1377 generic.m_value = value_with_prefix;
1378 generic.m_type =
"bit_vector";
1379 generic.m_parameter = param_res.get();
1384 if (base_char ==
'B')
1386 if (
auto res = classify_base(1,
"01",
'b'); res.is_error())
1388 return ERR_APPEND(res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1391 else if (base_char ==
'O')
1393 if (
auto res = classify_base(3,
"01234567",
'o'); res.is_error())
1395 return ERR_APPEND(res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1398 else if (base_char ==
'X')
1400 if (
auto res = classify_base(4,
"0123456789abcdef",
'x'); res.is_error())
1402 return ERR_APPEND(res.get_error(),
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"'");
1409 return ERR(
"could not parse generic assignment '" +
generic.m_name +
"' in instance '" + core_strings::to<std::string>(
instance->m_name) +
"': base-prefixed literal '" + rhs_str
1410 +
"' has unsupported base '" + std::string(1, base_char) +
"' (line " + std::to_string(
generic.m_line_number) +
")");
1417 return ERR(
"could not parse generic assignment: unable to identify data type of generic map value '" + rhs_str +
"' in instance '" + core_strings::to<std::string>(
instance->m_name)
1418 +
"' (line " + std::to_string(
generic.m_line_number) +
")");
1421 instance->m_generics.push_back(
generic);
1427 Result<std::monostate> VHDLParser::assign_attributes(VhdlEntity* vhdl_entity)
1429 for (
const auto& [target_class, attributes] : m_attribute_buffer)
1432 if (target_class == AttributeTarget::ENTITY)
1434 for (
const auto& [target, attribute] : attributes)
1436 if (vhdl_entity->m_name != target)
1438 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1439 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1443 vhdl_entity->m_attributes.push_back(attribute);
1448 else if (target_class == AttributeTarget::INSTANCE)
1450 for (
const auto& [target, attribute] : attributes)
1452 if (
const auto instance_it = vhdl_entity->m_instances_by_name.find(target); instance_it == vhdl_entity->m_instances_by_name.end())
1454 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1455 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1459 instance_it->second->m_attributes.push_back(attribute);
1464 else if (target_class == AttributeTarget::SIGNAL)
1466 for (
const auto& [target, attribute] : attributes)
1468 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(target); signal_it != vhdl_entity->m_signals_by_name.end())
1470 signal_it->second->m_attributes.push_back(attribute);
1474 return ERR(
"could not assign attributes: invalid attribute target '" + core_strings::to<std::string>(target) +
"' within entity '"
1475 + core_strings::to<std::string>(vhdl_entity->m_name) +
"' (line " + std::to_string(attribute.m_line_number) +
")");
1488 Result<std::monostate> VHDLParser::construct_netlist(VhdlEntity* top_entity)
1490 m_netlist->
set_design_name(core_strings::to<std::string>(top_entity->m_name));
1493 std::unordered_map<ci_string, u32> instantiation_count;
1496 std::queue<VhdlEntity*> q;
1501 VhdlEntity* entity = q.front();
1504 instantiation_count[entity->m_name]++;
1507 for (
const auto& s : entity->m_signals)
1509 std::vector<ci_string> expanded_names;
1510 expand_ranges_recursively(expanded_names, s->m_name, s->m_ranges, 0);
1511 for (
const auto& net_name : expanded_names)
1513 m_signal_name_occurrences[net_name]++;
1517 for (
const auto&
instance : entity->m_instances)
1519 m_instance_name_occurrences[
instance->m_name]++;
1522 if (
const auto it = m_entities_by_name.find(
instance->m_type); it != m_entities_by_name.end())
1529 for (
auto& [entity_name, vhdl_entity] : m_entities_by_name)
1532 if (instantiation_count[entity_name] == 0)
1534 log_warning(
"vhdl_parser",
"entity '{}' has been defined in the netlist but is not instantiated.", entity_name);
1539 for (
const auto&
instance : vhdl_entity->m_instances)
1541 if (
const auto gate_type_it = m_gate_types.find(
instance->m_type); gate_type_it != m_gate_types.end())
1543 if (!
instance->m_port_assignments.empty())
1546 if (
instance->m_port_assignments.front().m_port.has_value())
1549 std::unordered_map<ci_string, std::vector<ci_string>> pin_groups;
1550 for (
const auto pin_group : gate_type_it->second->get_pin_groups())
1552 const auto pins = pin_group->get_pins();
1553 for (
auto it =
pins.rbegin(); it !=
pins.rend(); it++)
1555 const auto* pin = *it;
1556 pin_groups[core_strings::to<ci_string>(pin_group->get_name())].push_back(core_strings::to<ci_string>(pin->get_name()));
1560 for (
const auto& port_assignment :
instance->m_port_assignments)
1562 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1563 if (right_res.is_error())
1565 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1567 auto right_port = right_res.get();
1569 if (!right_port.empty())
1571 std::vector<ci_string> left_port;
1573 if (
const identifier_t*
identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value()));
identifier !=
nullptr)
1575 if (
const auto group_it = pin_groups.find(*
identifier); group_it != pin_groups.end())
1577 left_port = group_it->second;
1584 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier !=
nullptr)
1586 left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
1590 return ERR(
"could not construct netlist: unable to expand gate port assignment");
1593 if (right_port.size() != left_port.size())
1595 return ERR(
"could not construct netlist: pin assignment width mismatch at instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of gate type '"
1596 + core_strings::to<std::string>(
instance->m_type) +
"' within entity '" + core_strings::to<std::string>(entity_name) +
"'");
1599 for (
u32 i = 0; i < left_port.size(); i++)
1601 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1610 std::vector<ci_string>
pins;
1611 for (
const auto pin : gate_type_it->second->get_pins())
1613 pins.push_back(core_strings::to<ci_string>(pin->get_name()));
1615 auto pin_it =
pins.begin();
1617 for (
const auto& port_assignment :
instance->m_port_assignments)
1619 auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1620 if (right_res.is_error())
1622 return ERR_APPEND(right_res.get_error(),
"could not construct netlist: unable to expand gate port assignment");
1624 auto right_port = right_res.get();
1626 if (!right_port.empty())
1628 std::vector<ci_string> left_port;
1630 for (
u32 i = 0; i < right_port.size() && pin_it !=
pins.end(); i++)
1632 left_port.push_back(*pin_it++);
1635 u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1637 for (
u32 i = 0; i < max_size; i++)
1639 instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1650 std::unordered_map<ci_string, ci_string> top_assignments;
1651 for (
const auto& port : top_entity->m_ports)
1653 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1655 const auto signal_name = get_unique_alias(
"", expanded_port_identifier +
"__GLOBAL_IO__", m_signal_name_occurrences);
1657 Net* global_port_net = m_netlist->
create_net(core_strings::to<std::string>(signal_name));
1658 if (global_port_net ==
nullptr)
1660 return ERR(
"could not construct netlist: failed to create global I/O net '" + core_strings::to<std::string>(signal_name) +
"'");
1663 m_net_by_name[signal_name] = global_port_net;
1666 top_assignments[expanded_port_identifier] = signal_name;
1670 if (!global_port_net->mark_global_input_net())
1672 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global input");
1678 if (!global_port_net->mark_global_output_net())
1680 return ERR(
"could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) +
"' as global output");
1686 if (
const auto res = instantiate_entity(
"top_module", top_entity,
nullptr, top_assignments); res.is_error())
1688 return ERR_APPEND(res.get_error(),
"could not construct netlist: unable to instantiate top module");
1692 std::unordered_map<ci_string, ci_string> merged_nets;
1693 std::unordered_map<ci_string, std::vector<ci_string>> master_to_slaves;
1695 for (
auto& [master, slave] : m_nets_to_merge)
1700 if (
const auto master_it = merged_nets.find(master); master_it != merged_nets.end())
1702 master = master_it->second;
1713 if (
const auto slave_it = merged_nets.find(slave); slave_it != merged_nets.end())
1715 slave = slave_it->second;
1723 auto master_net = m_net_by_name.at(master);
1724 auto slave_net = m_net_by_name.at(slave);
1726 if (master_net == slave_net)
1730 else if (slave_net == m_zero_net || slave_net == m_one_net)
1732 auto* tmp_net = master_net;
1733 master_net = slave_net;
1734 slave_net = tmp_net;
1736 auto tmp_name = master;
1742 if (slave_net->is_global_input_net())
1744 master_net->mark_global_input_net();
1747 for (
auto src : slave_net->get_sources())
1749 Gate* src_gate = src->get_gate();
1750 GatePin* src_pin = src->get_pin();
1752 if (!slave_net->remove_source(src))
1754 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()));
1757 if (!master_net->is_a_source(src_gate, src_pin))
1759 if (!master_net->add_source(src_gate, src_pin))
1761 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()));
1767 if (slave_net->is_global_output_net())
1769 master_net->mark_global_output_net();
1772 for (
auto dst : slave_net->get_destinations())
1774 Gate* dst_gate = dst->get_gate();
1775 GatePin* dst_pin = dst->get_pin();
1777 if (!slave_net->remove_destination(dst))
1779 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()));
1782 if (!master_net->is_a_destination(dst_gate, dst_pin))
1784 if (!master_net->add_destination(dst_gate, dst_pin))
1786 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()));
1792 for (
const auto& [
identifier, content] : slave_net->get_data_map())
1794 if (!master_net->set_data(std::get<0>(
identifier), std::get<1>(
identifier), std::get<0>(content), std::get<1>(content)))
1797 "unable to transfer data from slave net '{}' with ID {} to master net '{}' with ID {}.",
1798 slave_net->get_name(),
1799 slave_net->get_id(),
1800 master_net->get_name(),
1801 master_net->get_id());
1806 if (
const auto it = m_module_port_by_net.find(slave_net); it != m_module_port_by_net.end())
1810 std::get<1>(m_module_ports.at(
module).at(
index)) = master_net;
1812 m_module_port_by_net[master_net].insert(m_module_port_by_net[master_net].end(), it->second.begin(), it->second.end());
1813 m_module_port_by_net.erase(it);
1817 m_net_by_name.erase(slave);
1818 merged_nets[slave] = master;
1819 master_to_slaves[master].push_back(slave);
1823 for (
auto& master_net : m_netlist->
get_nets())
1825 const auto master_name = master_net->get_name();
1827 if (
const auto m2s_it = master_to_slaves.find(core_strings::to<ci_string>(master_name)); m2s_it != master_to_slaves.end())
1829 std::vector<std::vector<ci_string>> merged_slaves;
1830 auto current_slaves = m2s_it->second;
1832 while (!current_slaves.empty())
1834 std::vector<ci_string> next_slaves;
1835 for (
const auto& s : current_slaves)
1837 if (
const auto m2s_inner_it = master_to_slaves.find(s); m2s_inner_it != master_to_slaves.end())
1839 next_slaves.insert(next_slaves.end(), m2s_inner_it->second.begin(), m2s_inner_it->second.end());
1843 merged_slaves.push_back(current_slaves);
1844 current_slaves = next_slaves;
1845 next_slaves.clear();
1850 ci_string merged_str =
"";
1851 bool has_merged_nets =
false;
1852 for (
const auto& vec : merged_slaves)
1856 has_merged_nets =
true;
1859 ci_string s = vec.empty() ?
"" : vec.front();
1860 for (
u32 idx = 1; idx < vec.size(); idx++)
1862 s += ci_string(
", ") + vec.at(idx);
1865 merged_str +=
"[" + s +
"], ";
1867 merged_str = merged_str.substr(0, merged_str.size() - 2);
1869 if (has_merged_nets)
1871 master_net->set_data(
"parser_annotation",
"merged_nets",
"string",
"[" + core_strings::to<std::string>(merged_str) +
"]");
1883 for (
const auto& [
module, ports] : m_module_ports)
1885 for (
const auto& [port_name, port_net] : ports)
1896 "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())
1907 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()))
1912 "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 '"
1917 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()))
1922 "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())
1933 VHDLParser::instantiate_entity(
const ci_string& instance_identifier, VhdlEntity* vhdl_entity, Module* parent,
const std::unordered_map<ci_string, ci_string>& parent_module_assignments)
1935 std::unordered_map<ci_string, ci_string> signal_alias;
1936 std::unordered_map<ci_string, ci_string> instance_alias;
1940 const std::string parent_name = parent == (
nullptr) ?
"" : parent->get_name();
1941 instance_alias[instance_identifier] = get_unique_alias(core_strings::to<ci_string>(parent_name), instance_identifier, m_instance_name_occurrences);
1945 if (parent ==
nullptr)
1948 module->
set_name(core_strings::to<std::string>(instance_alias.at(instance_identifier)));
1952 module = m_netlist->
create_module(core_strings::to<std::string>(instance_alias.at(instance_identifier)), parent);
1955 ci_string instance_type = vhdl_entity->m_name;
1958 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
1959 +
"': failed to create module");
1964 for (
const VhdlDataEntry& attribute : vhdl_entity->m_attributes)
1966 if (!
module->
set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1969 "could not set attribute '{} = {}' of type '{}' for instance '{}' type '{}'.",
1973 instance_identifier,
1979 for (
const auto& port : vhdl_entity->m_ports)
1981 for (
const auto& expanded_port_identifier : port->m_expanded_identifiers)
1983 if (
const auto it = parent_module_assignments.find(expanded_port_identifier); it != parent_module_assignments.end())
1985 Net* port_net = m_net_by_name.at(it->second);
1986 m_module_ports[
module].push_back(std::make_pair(core_strings::to<std::string>(expanded_port_identifier), port_net));
1987 m_module_port_by_net[port_net].push_back(std::make_pair(
module, m_module_ports[
module].
size() - 1));
1993 for (
const auto& signal : vhdl_entity->m_signals)
1995 for (
const auto& expanded_name : signal->m_expanded_names)
1997 signal_alias[expanded_name] = get_unique_alias(instance_alias[instance_identifier], expanded_name, m_signal_name_occurrences);
2000 Net* signal_net = m_netlist->
create_net(core_strings::to<std::string>(signal_alias.at(expanded_name)));
2001 if (signal_net ==
nullptr)
2003 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2004 +
"': failed to create net '" + core_strings::to<std::string>(expanded_name) +
"'");
2007 m_net_by_name[signal_alias.at(expanded_name)] = signal_net;
2010 for (
const VhdlDataEntry& attribute : signal->m_attributes)
2012 if (!signal_net->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
2015 "could not set attribute ({} = {}) for net '{}' of instance '{}' of type '{}'.",
2019 instance_identifier,
2027 for (
const auto& [left_expanded_signal, right_expanded_signal] : vhdl_entity->m_expanded_assignments)
2029 ci_string a = left_expanded_signal;
2030 ci_string b = right_expanded_signal;
2032 if (
const auto alias_it = signal_alias.find(a); alias_it != signal_alias.end())
2034 a = alias_it->second;
2038 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2039 +
"': failed to find alias for net '" + core_strings::to<std::string>(a) +
"'");
2042 if (
const auto alias_it = signal_alias.find(b); alias_it != signal_alias.end())
2044 b = alias_it->second;
2046 else if (b ==
"'Z'" || b ==
"'X'")
2050 else if (b !=
"'0'" && b !=
"'1'")
2052 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2053 +
"': failed to find alias for net '" + core_strings::to<std::string>(b) +
"'");
2056 m_nets_to_merge.push_back(std::make_pair(a, b));
2060 for (
const auto& [port_expression, net_name] : parent_module_assignments)
2062 if (
const auto alias_it = signal_alias.find(port_expression); alias_it != signal_alias.end())
2064 const bool swap = net_name.find(
"__GLOBAL_IO__") == std::string::npos;
2065 m_nets_to_merge.push_back(swap ? std::make_pair(net_name, alias_it->second) : std::make_pair(alias_it->second, net_name));
2069 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2070 +
"': failed to find alias for net '" + core_strings::to<std::string>(port_expression) +
"'");
2075 for (
const auto&
instance : vhdl_entity->m_instances)
2078 DataContainer* container =
nullptr;
2081 std::unordered_map<ci_string, ci_string> instance_assignments;
2084 if (
auto entity_it = m_entities_by_name.find(
instance->m_type); entity_it != m_entities_by_name.end())
2087 for (
const auto& [port, assignment] :
instance->m_expanded_port_assignments)
2089 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
2091 instance_assignments[port] = alias_it->second;
2093 else if (assignment ==
"'0'" || assignment ==
"'1'")
2095 instance_assignments[port] = assignment;
2097 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
2103 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2104 +
"': port assignment '" + core_strings::to<std::string>(port) +
" = " + core_strings::to<std::string>(assignment) +
"' is invalid");
2108 if (
auto res = instantiate_entity(
instance->m_name, entity_it->second,
module, instance_assignments); res.is_error())
2111 "could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2112 +
"': unable to create instance '" + core_strings::to<std::string>(
instance->m_name) +
"' of type '"
2113 + core_strings::to<std::string>(entity_it->second->m_name) +
"'");
2117 container = res.get();
2121 else if (
const auto gate_type_it = m_gate_types.find(
instance->m_type); gate_type_it != m_gate_types.end())
2124 instance_alias[
instance->m_name] = get_unique_alias(instance_alias[instance_identifier],
instance->m_name, m_instance_name_occurrences);
2126 Gate* new_gate = m_netlist->
create_gate(gate_type_it->second, core_strings::to<std::string>(instance_alias.at(
instance->m_name)));
2127 if (new_gate ==
nullptr)
2129 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2130 +
"': failed to create gate '" + core_strings::to<std::string>(
instance->m_name) +
"'");
2138 container = new_gate;
2141 if (m_vcc_gate_types.find(
instance->m_type) != m_vcc_gate_types.end() && !new_gate->mark_vcc_gate())
2143 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 '"
2144 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as GND gate");
2146 if (m_gnd_gate_types.find(
instance->m_type) != m_gnd_gate_types.end() && !new_gate->mark_gnd_gate())
2148 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 '"
2149 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as VCC gate");
2153 std::unordered_map<ci_string, GatePin*> pin_names_map;
2154 for (
auto* pin : gate_type_it->second->get_pins())
2156 pin_names_map[core_strings::to<ci_string>(pin->get_name())] = pin;
2160 for (
const auto& [pin, assignment] :
instance->m_expanded_port_assignments)
2164 if (
const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
2166 signal = alias_it->second;
2168 else if (assignment ==
"'0'" || assignment ==
"'1'")
2170 signal = assignment;
2172 else if (assignment ==
"'Z'" || assignment ==
"'X'" || assignment ==
"")
2178 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2179 +
"': failed to assign '" + core_strings::to<std::string>(assignment) +
"' to pin '" + core_strings::to<std::string>(pin) +
"' of gate '"
2180 + core_strings::to<std::string>(
instance->m_name) +
"' of type '" + core_strings::to<std::string>(
instance->m_type) +
"' as the assignment is invalid");
2184 if (
const auto net_it = m_net_by_name.find(signal); net_it == m_net_by_name.end())
2186 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2187 +
"': failed to assign signal'" + core_strings::to<std::string>(signal) +
"' to pin '" + core_strings::to<std::string>(pin)
2188 +
"' as the signal has not been declared");
2192 Net* current_net = net_it->second;
2195 bool is_input =
false;
2196 bool is_output =
false;
2198 if (
const auto it = pin_names_map.find(pin); it != pin_names_map.end())
2212 if (!is_input && !is_output)
2214 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2215 +
"': 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 '"
2216 + new_gate->get_name() +
"' of type '" + new_gate->get_type()->get_name() +
"'");
2219 if (is_output && !current_net->add_source(new_gate, core_strings::to<std::string>(pin)))
2221 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2222 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a source to gate '" + new_gate->get_name() +
"' via pin '"
2223 + core_strings::to<std::string>(pin) +
"'");
2226 if (is_input && !current_net->add_destination(new_gate, core_strings::to<std::string>(pin)))
2228 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2229 +
"': failed to add net '" + core_strings::to<std::string>(signal) +
"' as a destination to gate '" + new_gate->get_name() +
"' via pin '"
2230 + core_strings::to<std::string>(pin) +
"'");
2237 return ERR(
"could not create instance '" + core_strings::to<std::string>(instance_identifier) +
"' of type '" + core_strings::to<std::string>(instance_type)
2238 +
"': failed to find gate type '" + core_strings::to<std::string>(
instance->m_type) +
"' in gate library '" + m_netlist->
get_gate_library()->
get_name() +
"'");
2242 for (
const auto& attribute :
instance->m_attributes)
2244 if (!container->set_data(
"attribute", attribute.m_name, attribute.m_type, attribute.m_value))
2247 "could not set attribute '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2253 instance_identifier,
2262 const GateType* gt =
nullptr;
2263 if (
const Gate* g =
dynamic_cast<const Gate*
>(container))
2268 for (
const auto&
generic :
instance->m_generics)
2270 if (!
generic.m_parameter.has_value())
2273 "could not set generic '{} = {}' for instance '{}' of type '{}' within instance '{}' of type '{}': parser did not produce a parameter declaration.",
2278 instance_identifier,
2282 Parameter effective_param =
generic.m_parameter.value();
2285 if (
auto decl = gt->get_parameter(core_strings::to<std::string>(
generic.m_name)); decl.is_ok())
2287 effective_param = decl.get();
2290 if (
auto res = container->set_parameter(effective_param,
generic.m_value); res.is_error())
2293 "could not set generic '{} = {}' for instance '{}' of type '{}' within instance '{}' of type '{}': {}",
2298 instance_identifier,
2300 res.get_error().get());
2314 const static std::map<core_strings::CaseInsensitiveString, size_t> id_to_dim = {{
"std_logic_vector", 1}, {
"std_logic_vector2", 2}, {
"std_logic_vector3", 3}};
2316 static const std::map<char, BooleanFunction::Value> bin_map = {{
'0', BooleanFunction::Value::ZERO},
2317 {
'1', BooleanFunction::Value::ONE},
2318 {
'X', BooleanFunction::Value::X},
2319 {
'Z', BooleanFunction::Value::Z}};
2321 static const std::map<char, std::vector<BooleanFunction::Value>> oct_map = {{
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2322 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2323 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2324 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2325 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2326 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2327 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2328 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2329 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2330 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2332 static const std::map<char, std::vector<BooleanFunction::Value>> hex_map = {
2333 {
'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2334 {
'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2335 {
'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2336 {
'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2337 {
'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2338 {
'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2339 {
'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2340 {
'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2341 {
'8', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2342 {
'9', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2343 {
'A', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2344 {
'B', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2345 {
'C', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2346 {
'D', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2347 {
'E', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2348 {
'F', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2349 {
'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2350 {
'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2354 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
2356 ci_string unique_alias =
name;
2358 if (!parent_name.empty())
2361 if (
const auto instance_name_it = name_occurences.find(
name); instance_name_it != name_occurences.end() && instance_name_it->second > 1)
2363 unique_alias = parent_name + ci_string(
"/") + unique_alias;
2367 return unique_alias;
2370 std::vector<u32> VHDLParser::parse_range(TokenStream<ci_string>& range_stream)
const
2372 if (range_stream.remaining() == 1)
2374 return {(
u32)std::stoi(core_strings::to<std::string>(range_stream.consume().string))};
2378 const int end = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2380 if (range_stream.peek() ==
"downto")
2382 range_stream.consume(
"downto");
2386 range_stream.consume(
"to",
true);
2390 const int start = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2392 std::vector<u32> res;
2395 res.push_back((
u32)i);
2400 Result<std::vector<std::vector<u32>>> VHDLParser::parse_signal_ranges(TokenStream<ci_string>& signal_stream)
const
2402 std::vector<std::vector<u32>> ranges;
2403 const u32 line_number = signal_stream.peek().number;
2405 const Token<ci_string> type_name = signal_stream.consume();
2406 if (type_name ==
"std_logic")
2411 signal_stream.consume(
"(",
true);
2412 TokenStream<ci_string> signal_bounds_stream = signal_stream.extract_until(
")");
2417 TokenStream<ci_string> bound_stream = signal_bounds_stream.extract_until(
",");
2418 ranges.emplace_back(parse_range(bound_stream));
2419 }
while (signal_bounds_stream.consume(
","));
2421 signal_stream.consume(
")",
true);
2423 if (id_to_dim.find(type_name) != id_to_dim.end())
2425 const size_t dimension = id_to_dim.at(type_name);
2427 if (ranges.size() != dimension)
2429 return ERR(
"could not parse signal ranges: mismatch of dimensions (line " + std::to_string(line_number) +
")");
2434 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) +
")");
2440 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
2443 if (ranges.size() > dimension)
2445 for (
const u32 index : ranges[dimension])
2447 expand_ranges_recursively(expanded_names, current_name +
"(" + core_strings::to<ci_string>(std::to_string(
index)) +
")", ranges, dimension + 1);
2453 expanded_names.push_back(current_name);
2457 std::vector<VHDLParser::ci_string> VHDLParser::expand_ranges(
const ci_string&
name,
const std::vector<std::vector<u32>>& ranges)
const
2459 std::vector<ci_string> res;
2461 expand_ranges_recursively(res,
name, ranges, 0);
2466 Result<std::vector<BooleanFunction::Value>> VHDLParser::get_binary_vector(std::string value)
const
2472 std::vector<BooleanFunction::Value> result;
2475 if (value.at(0) !=
'\"')
2477 prefix = value.at(0);
2478 number = value.substr(2, value.rfind(
'\"') - 2);
2483 number = value.substr(1, value.rfind(
'\"') - 1);
2487 switch (prefix.at(0))
2490 for (
auto it = number.rbegin(); it != number.rend(); it++)
2493 if (c ==
'0' || c ==
'1' || c ==
'Z' || c ==
'X')
2495 result.push_back(bin_map.at(c));
2499 return ERR(
"could not convert string to binary vector: invalid character within binary number literal '" + value +
"'");
2506 for (
auto it = number.rbegin(); it != number.rend(); it++)
2509 if ((c >=
'0' && c <=
'7') || c ==
'X' || c ==
'Z')
2511 const auto& bits = oct_map.at(c);
2512 result.insert(result.end(), bits.begin(), bits.end());
2516 return ERR(
"could not convert string to binary vector: invalid character within octal number literal '" + value +
"'");
2524 for (
const char c : number)
2526 if ((c >=
'0' && c <=
'9'))
2528 tmp_val = (tmp_val * 10) + (c -
'0');
2532 return ERR(
"could not convert string to binary vector: invalid character within decimal number literal '" + value +
"'");
2538 result.push_back(((tmp_val & 1) == 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
2540 }
while (tmp_val != 0);
2545 for (
auto it = number.rbegin(); it != number.rend(); it++)
2548 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F') || c ==
'X' || c ==
'Z')
2550 const auto& bits = hex_map.at(c);
2551 result.insert(result.end(), bits.begin(), bits.end());
2555 return ERR(
"could not convert string to binary vector: invalid character within hexadecimal number literal '" + value +
"'");
2562 return ERR(
"could not convert string to binary vector: invalid base '" + prefix +
"' within number literal '" + value +
"'");
2569 Result<std::string> VHDLParser::get_hex_from_literal(
const Token<ci_string>& value_token)
const
2571 const u32 line_number = value_token.number;
2579 if (value.at(0) !=
'\"')
2581 prefix = value.at(0);
2582 number = value.substr(2, value.rfind(
'\"') - 2);
2587 number = value.substr(1, value.rfind(
'\"') - 1);
2591 switch (prefix.at(0))
2594 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'1'); }))
2596 return ERR(
"could not convert token to hexadecimal string: invalid character within binary number literal '" + core_strings::to<std::string>(value) +
"' (line "
2597 + std::to_string(line_number) +
")");
2605 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'7'); }))
2607 return ERR(
"could not convert token to hexadecimal string: invalid character within ocatl number literal '" + core_strings::to<std::string>(value) +
"' (line "
2608 + std::to_string(line_number) +
")");
2616 if (!std::all_of(number.begin(), number.end(), [](
const char& c) { return (c >=
'0' && c <=
'9'); }))
2618 return ERR(
"could not convert token to hexadecimal string: invalid character within decimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2619 + std::to_string(line_number) +
")");
2629 for (
const char c : number)
2631 if ((c >=
'0' && c <=
'9') || (c >=
'A' && c <=
'F'))
2637 return ERR(
"could not convert token to hexadecimal string: invalid character within hexadecimal number literal '" + core_strings::to<std::string>(value) +
"' (line "
2638 + std::to_string(line_number) +
")");
2646 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)
2647 +
"' (line " + std::to_string(line_number) +
")");
2651 std::stringstream ss;
2652 ss << std::uppercase << std::hex << stoull(core_strings::to<std::string>(number), 0, base);
2653 return OK(ss.str());
2656 Result<std::vector<VHDLParser::assignment_t>> VHDLParser::parse_assignment_expression(TokenStream<ci_string>&& stream)
const
2666 std::vector<TokenStream<ci_string>> parts;
2668 if (stream.size() == 0)
2674 if (stream.consume(
"("))
2678 parts.push_back(stream.extract_until(
","));
2679 }
while (stream.consume(
",",
false));
2681 stream.consume(
")",
true);
2685 parts.push_back(stream);
2688 std::vector<assignment_t> result;
2689 result.reserve(parts.size());
2691 for (
auto it = parts.rbegin(); it != parts.rend(); it++)
2693 TokenStream<ci_string>& part_stream = *it;
2695 const Token<ci_string> signal_name_token = part_stream.consume();
2696 ci_string signal_name = signal_name_token.string;
2702 if (
auto res = get_binary_vector(core_strings::to<std::string>(signal_name_token.string)); res.is_error())
2704 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) +
")");
2708 result.push_back(std::move(res.get()));
2711 else if (signal_name ==
"'0'")
2713 result.push_back(numeral_t({BooleanFunction::Value::ZERO}));
2715 else if (signal_name ==
"'1'")
2717 result.push_back(numeral_t({BooleanFunction::Value::ONE}));
2719 else if (signal_name ==
"'X'")
2721 result.push_back(numeral_t({BooleanFunction::Value::X}));
2723 else if (signal_name ==
"'Z'")
2725 result.push_back(numeral_t({BooleanFunction::Value::Z}));
2731 if (part_stream.consume(
"("))
2733 std::vector<std::vector<u32>> ranges;
2734 u32 closing_pos = part_stream.find_next(
")");
2737 TokenStream<ci_string> range_stream = part_stream.extract_until(
",", closing_pos);
2738 ranges.emplace_back(parse_range(range_stream));
2740 }
while (part_stream.consume(
",",
false));
2741 part_stream.consume(
")",
true);
2742 result.push_back(ranged_identifier_t({std::move(signal_name), std::move(ranges)}));
2747 result.push_back(std::move(signal_name));
2755 Result<std::vector<VHDLParser::ci_string>> VHDLParser::expand_assignment_expression(VhdlEntity* vhdl_entity,
const std::vector<assignment_t>& vars)
const
2757 std::vector<ci_string> result;
2758 for (
const auto& var : vars)
2767 std::vector<std::vector<u32>> ranges;
2769 if (
const auto signal_it = vhdl_entity->m_signals_by_name.find(*
identifier); signal_it != vhdl_entity->m_signals_by_name.end())
2771 ranges = signal_it->second->m_ranges;
2773 else if (
const auto port_it = vhdl_entity->m_ports_by_identifier.find(*
identifier); port_it != vhdl_entity->m_ports_by_identifier.end())
2775 ranges = port_it->second->m_ranges;
2779 return ERR(
"could not expand assignment expression': '" + core_strings::to<std::string>(*
identifier) +
"' is neither a signal nor a port of entity '"
2780 + core_strings::to<std::string>(vhdl_entity->m_name) +
"'");
2783 std::vector<ci_string> expanded = expand_ranges(*
identifier, ranges);
2784 result.insert(result.end(), expanded.begin(), expanded.end());
2786 else if (
const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier !=
nullptr)
2788 std::vector<ci_string> expanded = expand_ranges(ranged_identifier->first, ranged_identifier->second);
2789 result.insert(result.end(), expanded.begin(), expanded.end());
2791 else if (
const numeral_t* numeral = std::get_if<numeral_t>(&var); numeral !=
nullptr)
2793 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 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
static Result< Parameter > Boolean(const std::string &name, const std::string &default_value)
static Result< Parameter > BitVector(const std::string &name, u16 size, const std::string &default_value)
static Result< Parameter > Integer(const std::string &name, const std::string &default_value)
static Result< Parameter > String(const std::string &name, const std::string &default_value)
static Result< Parameter > LogicVector(const std::string &name, u16 size, const std::string &default_value)
static Result< Parameter > Time(const std::string &name, const std::string &default_value)
static Result< Parameter > Float(const std::string &name, const std::string &default_value)