HAL
vhdl_parser.cpp
Go to the documentation of this file.
2 
10 
11 #include <fstream>
12 #include <iomanip>
13 #include <queue>
14 
15 namespace hal
16 {
17  namespace
18  {
19 
20  } // namespace
21 
22  Result<std::monostate> VHDLParser::parse(const std::filesystem::path& file_path)
23  {
24  m_path = file_path;
25  m_entities.clear();
26  m_attribute_buffer.clear();
27  m_attribute_types.clear();
28 
29  {
30  std::ifstream ifs;
31  ifs.open(file_path.string(), std::ifstream::in);
32  if (!ifs.is_open())
33  {
34  return ERR("unable to open VHDL file '" + file_path.string() + "'");
35  }
36  m_fs << ifs.rdbuf();
37  ifs.close();
38  }
39 
40  // tokenize file
41  tokenize();
42 
43  // parse tokens into intermediate format
44  try
45  {
46  if (const auto res = parse_tokens(); res.is_error())
47  {
48  return ERR_APPEND(res.get_error(), "could not parse VHDL file '" + m_path.string() + "'");
49  }
50  }
52  {
53  if (e.line_number != (u32)-1)
54  {
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));
56  }
57  else
58  {
59  return ERR("could not parse VHDL file '" + m_path.string() + "': " + core_strings::to<std::string>(e.message));
60  }
61  }
62 
63  if (m_entities.empty())
64  {
65  return ERR("could not parse VHDL file '" + m_path.string() + "': it does not contain any entities");
66  }
67 
68  // expand module port identifiers, signals, and assignments
69  for (auto& [entity_name, vhdl_entity] : m_entities_by_name)
70  {
71  // expand port identifiers
72  for (const auto& port : vhdl_entity->m_ports)
73  {
74  if (!port->m_ranges.empty())
75  {
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());
78  }
79  else
80  {
81  port->m_expanded_identifiers = {port->m_identifier};
82  vhdl_entity->m_expanded_port_identifiers.insert(port->m_identifier);
83  }
84  }
85 
86  // expand signals
87  for (auto& signal : vhdl_entity->m_signals)
88  {
89  if (!signal->m_ranges.empty())
90  {
91  signal->m_expanded_names = expand_ranges(signal->m_name, signal->m_ranges);
92  }
93  else
94  {
95  signal->m_expanded_names = std::vector<ci_string>({signal->m_name});
96  }
97  }
98 
99  // expand assignments
100  for (auto& assignment : vhdl_entity->m_assignments)
101  {
102  auto left_res = expand_assignment_expression(vhdl_entity, assignment.m_variable);
103  if (left_res.is_error())
104  {
105  return ERR_APPEND(left_res.get_error(), "could not parse VHDL file '" + m_path.string() + "': unable to expand signal assignment");
106  }
107  const std::vector<ci_string> left_signals = left_res.get();
108 
109  auto right_res = expand_assignment_expression(vhdl_entity, assignment.m_assignment);
110  if (right_res.is_error())
111  {
112  return ERR_APPEND(right_res.get_error(), "could not parse VHDL file '" + m_path.string() + "': unable to expand signal assignment");
113  }
114  const std::vector<ci_string> right_signals = right_res.get();
115 
116  u32 left_size = left_signals.size();
117  u32 right_size = right_signals.size();
118  if (left_signals.empty() || right_signals.empty())
119  {
120  return ERR("could not parse VHDL file '" + m_path.string() + "': failed to expand assignments within entity '" + core_strings::to<std::string>(entity_name) + "'");
121  }
122  else if (left_size != right_size)
123  {
124  return ERR("could not parse VHDL file '" + m_path.string() + "': assignment width mismatch within entity '" + core_strings::to<std::string>(entity_name) + "'");
125  }
126  else
127  {
128  for (u32 i = 0; i < right_size; i++)
129  {
130  vhdl_entity->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i), right_signals.at(i)));
131  }
132  }
133  }
134  }
135 
136  // expand entity port assignments
137  for (auto& [entity_name, vhdl_entity] : m_entities_by_name)
138  {
139  for (auto& instance : vhdl_entity->m_instances)
140  {
141  if (auto entity_it = m_entities_by_name.find(instance->m_type); entity_it != m_entities_by_name.end())
142  {
143  instance->m_is_entity = true;
144 
145  if (!instance->m_port_assignments.empty())
146  {
147  // all port assignments by name
148  if (instance->m_port_assignments.front().m_port.has_value())
149  {
150  for (const auto& port_assignment : instance->m_port_assignments)
151  {
152  auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
153  if (right_res.is_error())
154  {
155  return ERR_APPEND(right_res.get_error(), "could not parse VHDL file '" + m_path.string() + "': unable to expand entity port assignment");
156  }
157  const std::vector<ci_string> right_port = right_res.get();
158  if (!right_port.empty())
159  {
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)
162  {
163  if (const auto it = entity_it->second->m_ports_by_identifier.find(*identifier); it != entity_it->second->m_ports_by_identifier.end())
164  {
165  left_port = it->second->m_expanded_identifiers;
166  }
167  else
168  {
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) + "'");
171  }
172  }
173  else if (const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier != nullptr)
174  {
175  left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
176  }
177  else
178  {
179  return ERR("could not parse VHDL file '" + m_path.string() + "': unable to expand entity port assignment");
180  }
181 
182  if (left_port.empty())
183  {
184  return ERR("could not parse VHDL file '" + m_path.string() + "': unable to expand entity port assignment");
185  }
186 
187  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
188 
189  for (u32 i = 0; i < max_size; i++)
190  {
191  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
192  }
193  }
194  }
195  }
196  // all port assignments by order
197  else
198  {
199  std::vector<ci_string> ports;
200  for (const auto& port : m_entities_by_name.at(instance->m_type)->m_ports)
201  {
202  ports.insert(ports.end(), port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
203  }
204 
205  auto port_it = ports.begin();
206 
207  for (const auto& port_assignment : instance->m_port_assignments)
208  {
209  auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
210  if (right_res.is_error())
211  {
212  return ERR_APPEND(right_res.get_error(), "could not parse VHDL file '" + m_path.string() + "': unable to expand entity port assignment");
213  }
214  const std::vector<ci_string> right_port = right_res.get();
215  if (!right_port.empty())
216  {
217  std::vector<ci_string> left_port;
218 
219  for (u32 i = 0; i < right_port.size() && port_it != ports.end(); i++)
220  {
221  left_port.push_back(*port_it++);
222  }
223 
224  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
225 
226  for (u32 i = 0; i < max_size; i++)
227  {
228  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
229  }
230  }
231  }
232  }
233  }
234  }
235  }
236  }
237 
238  return OK({});
239  }
240 
242  {
243  // create empty netlist
244  std::unique_ptr<Netlist> result = netlist_factory::create_netlist(gate_library);
245  m_netlist = result.get();
246  if (m_netlist == nullptr)
247  {
248  return ERR("could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create empty netlist");
249  }
250 
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)
261  {
262  for (const auto& instance : vhdl_entity->m_instances)
263  {
264  if (!instance->m_is_entity)
265  {
266  instance->m_expanded_port_assignments.clear();
267  }
268  }
269  }
270 
271  // buffer gate types
272  for (const auto& [gt_name, gt] : gate_library->get_gate_types())
273  {
274  m_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
275  }
276  for (const auto& [gt_name, gt] : gate_library->get_gnd_gate_types())
277  {
278  m_gnd_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
279  }
280  for (const auto& [gt_name, gt] : gate_library->get_vcc_gate_types())
281  {
282  m_vcc_gate_types[core_strings::to<ci_string>(gt_name)] = gt;
283  }
284 
285  // create const 0 and const 1 net, will be removed if unused
286  m_zero_net = m_netlist->create_net("'0'");
287  if (m_zero_net == nullptr)
288  {
289  return ERR("could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create zero net");
290  }
291  m_net_by_name[core_strings::to<ci_string>(m_zero_net->get_name())] = m_zero_net;
292 
293  m_one_net = m_netlist->create_net("'1'");
294  if (m_one_net == nullptr)
295  {
296  return ERR("could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create one net");
297  }
298  m_net_by_name[core_strings::to<ci_string>(m_one_net->get_name())] = m_one_net;
299 
300  // construct the netlist with the last module being considered the top module
301  std::map<ci_string, u32> entity_name_to_refereneces;
302  for (const auto& [_name, vhdl_entity] : m_entities_by_name)
303  {
304  for (const auto& instance : vhdl_entity->m_instances)
305  {
306  if (const auto it = m_entities_by_name.find(instance->m_type); it != m_entities_by_name.end())
307  {
308  entity_name_to_refereneces[it->first]++;
309  }
310  }
311  }
312 
313  std::vector<ci_string> top_module_candidates;
314  for (const auto& [name, _entity] : m_entities_by_name)
315  {
316  if (entity_name_to_refereneces.find(name) == entity_name_to_refereneces.end())
317  {
318  top_module_candidates.push_back(name);
319  }
320  }
321 
322  if (top_module_candidates.empty())
323  {
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");
325  }
326 
327  if (top_module_candidates.size() > 1)
328  {
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");
330  }
331 
332  // construct the netlist with the the top module
333  VhdlEntity* top_entity = m_entities_by_name.at(top_module_candidates.front());
334 
335  if (const auto res = construct_netlist(top_entity); res.is_error())
336  {
337  return ERR_APPEND(res.get_error(), "could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "'");
338  }
339 
340  // add global GND gate if required by any instance
341  if (m_netlist->get_gnd_gates().empty())
342  {
343  if (m_zero_net->get_num_of_destinations() > 0)
344  {
345  GateType* gnd_type = m_gnd_gate_types.begin()->second;
346  GatePin* output_pin = gnd_type->get_output_pins().front();
347  Gate* gnd = m_netlist->create_gate(m_netlist->get_unique_gate_id(), gnd_type, "global_gnd");
348 
349  if (!m_netlist->mark_gnd_gate(gnd))
350  {
351  return ERR("could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to mark GND gate");
352  }
353 
354  if (!m_zero_net->add_source(gnd, output_pin))
355  {
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");
357  }
358  }
359  else
360  {
361  m_netlist->delete_net(m_zero_net);
362  }
363  }
364 
365  // add global VCC gate if required by any instance
366  if (m_netlist->get_vcc_gates().empty())
367  {
368  if (m_one_net->get_num_of_destinations() > 0)
369  {
370  GateType* vcc_type = m_vcc_gate_types.begin()->second;
371  GatePin* output_pin = vcc_type->get_output_pins().front();
372  Gate* vcc = m_netlist->create_gate(m_netlist->get_unique_gate_id(), vcc_type, "global_vcc");
373 
374  if (!m_netlist->mark_vcc_gate(vcc))
375  {
376  return ERR("could not instantiate VHDL netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to mark VCC gate");
377  }
378 
379  if (!m_one_net->add_source(vcc, output_pin))
380  {
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");
382  }
383  }
384  else
385  {
386  m_netlist->delete_net(m_one_net);
387  }
388  }
389 
390  // delete unused nets
391  std::queue<Net*> nets_to_be_deleted;
392 
393  for (auto net : m_netlist->get_nets())
394  {
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)
400  {
401  m_netlist->delete_net(net);
402  }
403  }
404 
405  while (!nets_to_be_deleted.empty())
406  {
407  Net* net = nets_to_be_deleted.front();
408  nets_to_be_deleted.pop();
409  m_netlist->delete_net(net);
410  }
411 
412  m_netlist->load_gate_locations_from_data();
413 
414  return OK(std::move(result));
415  }
416 
417  // ###########################################################################
418  // ########### Parse HDL into Intermediate Format ##########
419  // ###########################################################################
420 
421  void VHDLParser::tokenize()
422  {
423  std::vector<Token<core_strings::CaseInsensitiveString>> parsed_tokens;
424  const std::string delimiters = ",(): ;=><&";
426  u32 line_number = 0;
427 
428  std::string line;
429  bool in_string = false;
430  bool escaped = false;
431 
432  while (std::getline(m_fs, line))
433  {
434  line_number++;
435  if (line.find("--") != std::string::npos)
436  {
437  line = line.substr(0, line.find("--"));
438  }
439  for (char c : utils::trim(line))
440  {
441  if (in_string == false && c == '\\')
442  {
443  escaped = !escaped;
444  continue;
445  }
446  else if (escaped && std::isspace(c))
447  {
448  escaped = false;
449  continue;
450  }
451  else if (!escaped && c == '"')
452  {
453  in_string = !in_string;
454  }
455 
456  if (delimiters.find(c) == std::string::npos || escaped || in_string)
457  {
458  current_token += c;
459  }
460  else
461  {
462  if (!current_token.empty())
463  {
464  if (parsed_tokens.size() > 1 && utils::is_digits(parsed_tokens.at(parsed_tokens.size() - 2).string) && parsed_tokens.at(parsed_tokens.size() - 1) == "."
465  && utils::is_digits(current_token))
466  {
467  parsed_tokens.pop_back();
468  parsed_tokens.back() += "." + current_token;
469  }
470  else
471  {
472  parsed_tokens.emplace_back(line_number, current_token);
473  }
474  current_token.clear();
475  }
476 
477  if (!parsed_tokens.empty())
478  {
479  if (c == '=' && parsed_tokens.back() == "<")
480  {
481  parsed_tokens.back() = "<=";
482  continue;
483  }
484  else if (c == '=' && parsed_tokens.back() == ":")
485  {
486  parsed_tokens.back() = ":=";
487  continue;
488  }
489  else if (c == '>' && parsed_tokens.back() == "=")
490  {
491  parsed_tokens.back() = "=>";
492  continue;
493  }
494  }
495 
496  if (!std::isspace(c))
497  {
498  parsed_tokens.emplace_back(line_number, core_strings::CaseInsensitiveString(1, c));
499  }
500  }
501  }
502  if (!current_token.empty())
503  {
504  parsed_tokens.emplace_back(line_number, current_token);
505  current_token.clear();
506  }
507  }
508  m_token_stream = TokenStream(parsed_tokens, {"("}, {")"});
509  }
510 
511  Result<std::monostate> VHDLParser::parse_tokens()
512  {
513  while (m_token_stream.remaining() > 0)
514  {
515  if (m_token_stream.peek() == "library" || m_token_stream.peek() == "use")
516  {
517  parse_library();
518  }
519  else if (m_token_stream.peek() == "entity")
520  {
521  if (const auto res = parse_entity(); res.is_error())
522  {
523  return ERR_APPEND(res.get_error(), "could not parse tokens");
524  }
525  }
526  else if (m_token_stream.peek() == "architecture")
527  {
528  if (const auto res = parse_architecture(); res.is_error())
529  {
530  return ERR_APPEND(res.get_error(), "could not parse tokens");
531  }
532  }
533  else
534  {
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) + ")");
537  }
538  }
539 
540  return OK({});
541  }
542 
543  void VHDLParser::parse_library()
544  {
545  if (m_token_stream.peek() == "use")
546  {
547  m_token_stream.consume("use", true);
548  auto lib = m_token_stream.consume().string;
549  m_token_stream.consume(";", true);
550 
551  // remove specific import like ".all" but keep the "."
552  lib = utils::trim(lib.substr(0, lib.rfind(".") + 1));
553  m_libraries.insert(lib);
554  }
555  else
556  {
557  m_token_stream.consume_until(";");
558  m_token_stream.consume(";", true);
559  }
560  }
561 
562  Result<std::monostate> VHDLParser::parse_entity()
563  {
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;
567 
568  // verify entity name
569  if (const auto it = m_entities_by_name.find(entity_name); it != m_entities_by_name.end())
570  {
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) + ")");
573  }
574 
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;
580 
581  m_attribute_buffer.clear();
582 
583  Token<ci_string> next_token = m_token_stream.peek();
584  while (next_token != "end")
585  {
586  if (next_token == "generic")
587  {
588  m_token_stream.consume_until(";");
589  m_token_stream.consume(";", true);
590  }
591  else if (next_token == "port")
592  {
593  if (const auto res = parse_port_definitons(vhdl_entity_raw); res.is_error())
594  {
595  return ERR_APPEND(res.get_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) + ")");
597  }
598  }
599  else if (next_token == "attribute")
600  {
601  if (const auto res = parse_attribute(); res.is_error())
602  {
603  return ERR_APPEND(res.get_error(),
604  "could not parse entity '" + core_strings::to<std::string>(entity_name) + "': failed to parse attribute (line " + std::to_string(next_token.number) + ")");
605  }
606  }
607  else
608  {
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) + ")");
611  }
612 
613  next_token = m_token_stream.peek();
614  }
615 
616  m_token_stream.consume("end", true);
617  m_token_stream.consume();
618  m_token_stream.consume(";", true);
619 
620  // add to collection of entities
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;
624 
625  return OK({});
626  }
627 
628  Result<std::monostate> VHDLParser::parse_port_definitons(VhdlEntity* vhdl_entity)
629  {
630  // default port assignments are not supported
631  m_token_stream.consume("port", true);
632  m_token_stream.consume("(", true);
633  auto port_def_stream = m_token_stream.extract_until(")");
634 
635  while (port_def_stream.remaining() > 0)
636  {
637  std::vector<core_strings::CaseInsensitiveString> port_names;
638  // std::set<signal> signals;
639 
640  const auto line_number = port_def_stream.peek().number;
641 
642  // extract names
643  do
644  {
645  port_names.push_back(port_def_stream.consume().string);
646  } while (port_def_stream.consume(",", false));
647 
648  port_def_stream.consume(":", true);
649 
650  // extract direction
652  const ci_string direction_str = port_def_stream.consume().string;
653  if (direction_str == "in")
654  {
656  }
657  else if (direction_str == "out")
658  {
660  }
661  else if (direction_str == "inout")
662  {
664  }
665  else
666  {
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)
668  + ")");
669  }
670 
671  // extract ranges
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())
675  {
676  return ERR_APPEND(res.get_error(), "could not parse port definitions: unable to parse signal ranges (line " + std::to_string(line_number) + ")");
677  }
678  else
679  {
680  ranges = res.get();
681  }
682 
683  port_def_stream.consume(";", port_def_stream.remaining() > 0); // last entry has no semicolon, so no throw in that case
684 
685  for (const ci_string& port_name : port_names)
686  {
687  auto port = std::make_unique<VhdlPort>();
688  port->m_identifier = port_name;
689  port->m_direction = direction;
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));
693 
694  if (vhdl_entity->m_signals_by_name.find(port_name) == vhdl_entity->m_signals_by_name.end())
695  {
696  auto signal = std::make_unique<VhdlSignal>();
697  signal->m_name = port_name;
698  if (!ranges.empty())
699  {
700  signal->m_ranges = ranges;
701  }
702  vhdl_entity->m_signals_by_name[port_name] = signal.get();
703  vhdl_entity->m_signals.push_back(std::move(signal));
704  }
705  }
706  }
707 
708  m_token_stream.consume(")", true);
709  m_token_stream.consume(";", true);
710 
711  return OK({});
712  }
713 
714  Result<std::monostate> VHDLParser::parse_attribute()
715  {
716  const u32 line_number = m_token_stream.peek().number;
717 
718  m_token_stream.consume("attribute", true);
719  const ci_string attribute_name = m_token_stream.consume().string;
720 
721  if (m_token_stream.peek() == ":")
722  {
723  m_token_stream.consume(":", true);
724  m_attribute_types[attribute_name] = m_token_stream.join_until(";", " ");
725  m_token_stream.consume(";", true);
726  }
727  else if (m_token_stream.peek() == "of" && m_token_stream.peek(2) == ":")
728  {
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;
738 
739  if (attribute_value[0] == '\"' && attribute_value.back() == '\"')
740  {
741  attribute_value = attribute_value.substr(1, attribute_value.size() - 2);
742  }
743 
744  if (const auto type_it = m_attribute_types.find(attribute_name); type_it == m_attribute_types.end())
745  {
746  log_warning("vhdl_parser", "attribute {} has unknown base type in line {}.", attribute_name, line_number);
747  attribute_type = "unknown";
748  }
749  else
750  {
751  attribute_type = type_it->second;
752  }
753 
754  if (attribute_class == "entity")
755  {
756  target_class = AttributeTarget::ENTITY;
757  }
758  else if (attribute_class == "label")
759  {
760  target_class = AttributeTarget::INSTANCE;
761  }
762  else if (attribute_class == "signal")
763  {
764  target_class = AttributeTarget::SIGNAL;
765  }
766  else
767  {
768  log_warning("vhdl_parser", "unsupported attribute class '{}' in line {}, ignoring attribute.", attribute_class, line_number);
769  return OK({});
770  }
771 
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);
777  }
778  else
779  {
780  return ERR("could not parse attribute: malformed attribute definition (line " + std::to_string(line_number) + ")");
781  }
782 
783  return OK({});
784  }
785 
786  Result<std::monostate> VHDLParser::parse_architecture()
787  {
788  m_token_stream.consume("architecture", true);
789  m_token_stream.consume();
790  m_token_stream.consume("of", true);
791 
792  u32 line_number = m_token_stream.peek().number;
793  const auto entity_name_token = m_token_stream.consume();
794 
795  if (const auto it = m_entities_by_name.find(entity_name_token.string); it == m_entities_by_name.end())
796  {
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) + ")");
799  }
800  else
801  {
802  VhdlEntity* vhdl_entity = it->second;
803 
804  m_token_stream.consume("is", true);
805 
806  if (const auto res = parse_architecture_header(vhdl_entity); res.is_error())
807  {
808  return ERR_APPEND(res.get_error(), "could not parse architecture: unable to parse architecture header (line " + std::to_string(line_number) + ")");
809  }
810  if (const auto res = parse_architecture_body(vhdl_entity); res.is_error())
811  {
812  return ERR_APPEND(res.get_error(), "could not parse architecture: unable to parse architecture body (line " + std::to_string(line_number) + ")");
813  }
814  if (const auto res = assign_attributes(vhdl_entity); res.is_error())
815  {
816  return ERR_APPEND(res.get_error(), "could not parse architecture: unable to assign attributes (line " + std::to_string(line_number) + ")");
817  }
818 
819  return OK({});
820  }
821  }
822 
823  Result<std::monostate> VHDLParser::parse_architecture_header(VhdlEntity* vhdl_entity)
824  {
825  auto next_token = m_token_stream.peek();
826  while (next_token != "begin")
827  {
828  if (next_token == "signal")
829  {
830  if (const auto res = parse_signal_definition(vhdl_entity); res.is_error())
831  {
832  return ERR_APPEND(res.get_error(), "could not parse architecture header: unable to parse signal definition (line " + std::to_string(next_token.number) + ")");
833  }
834  }
835  else if (next_token == "component")
836  {
837  // components are ignored
838  m_token_stream.consume("component", true);
839  const ci_string component_name = m_token_stream.consume().string;
840  m_token_stream.consume_until("end");
841  m_token_stream.consume("end", true);
842  m_token_stream.consume("component", true);
843  if (m_token_stream.peek() != ";")
844  {
845  m_token_stream.consume(component_name, true); // optional repetition of component name
846  }
847  m_token_stream.consume(";", true);
848  }
849  else if (next_token == "attribute")
850  {
851  if (const auto res = parse_attribute(); res.is_error())
852  {
853  return ERR_APPEND(res.get_error(), "could not parse architecture header: unable to parse attribute (line " + std::to_string(next_token.number) + ")");
854  }
855  }
856  else
857  {
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) + ")");
859  }
860 
861  next_token = m_token_stream.peek();
862  }
863 
864  return OK({});
865  }
866 
867  Result<std::monostate> VHDLParser::parse_signal_definition(VhdlEntity* vhdl_entity)
868  {
869  m_token_stream.consume("signal", true);
870  u32 line_number = m_token_stream.peek().number;
871 
872  // extract names
873  std::vector<ci_string> signal_names;
874  do
875  {
876  signal_names.push_back(m_token_stream.consume().string);
877  } while (m_token_stream.consume(",", false));
878 
879  m_token_stream.consume(":", true);
880 
881  // extract bounds
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())
885  {
886  return ERR_APPEND(res.get_error(), "could not parse signal definition: unable to parse signal ranges (line " + std::to_string(line_number) + ")");
887  }
888  else
889  {
890  ranges = res.get();
891  }
892 
893  m_token_stream.consume(";", true);
894 
895  for (const auto& signal_name : signal_names)
896  {
897  if (vhdl_entity->m_signals_by_name.find(signal_name) == vhdl_entity->m_signals_by_name.end())
898  {
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));
904  }
905  }
906 
907  return OK({});
908  }
909 
910  Result<std::monostate> VHDLParser::parse_architecture_body(VhdlEntity* vhdl_entity)
911  {
912  m_token_stream.consume("begin", true);
913  auto next_token = m_token_stream.peek();
914 
915  while (next_token != "end")
916  {
917  // new instance found
918  if (m_token_stream.peek(1) == ":")
919  {
920  if (const auto res = parse_instance(vhdl_entity); res.is_error())
921  {
922  return ERR_APPEND(res.get_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) + ")");
925  }
926  }
927  // not in instance -> has to be a direct assignment
928  else if (m_token_stream.find_next("<=") < m_token_stream.find_next(";"))
929  {
930  if (const auto res = parse_assignment(vhdl_entity); res.is_error())
931  {
932  return ERR_APPEND(res.get_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) + ")");
935  }
936  }
937  else
938  {
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) + ")");
941  }
942 
943  next_token = m_token_stream.peek();
944  }
945 
946  m_token_stream.consume("end", true);
947  m_token_stream.consume();
948  m_token_stream.consume(";", true);
949 
950  return OK({});
951  }
952 
953  Result<std::monostate> VHDLParser::parse_assignment(VhdlEntity* vhdl_entity)
954  {
955  u32 line_number = m_token_stream.peek().number;
956  VhdlAssignment assignment;
957 
958  if (auto res = parse_assignment_expression(m_token_stream.extract_until("<=")); res.is_error())
959  {
960  return ERR_APPEND(res.get_error(), "could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
961  }
962  else
963  {
964  assignment.m_variable = res.get();
965  }
966  m_token_stream.consume("<=", true);
967  if (auto res = parse_assignment_expression(m_token_stream.extract_until(";")); res.is_error())
968  {
969  return ERR_APPEND(res.get_error(), "could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
970  }
971  else
972  {
973  assignment.m_assignment = res.get();
974  }
975  m_token_stream.consume(";", true);
976 
977  vhdl_entity->m_assignments.push_back(std::move(assignment));
978  return OK({});
979  }
980 
981  Result<std::monostate> VHDLParser::parse_instance(VhdlEntity* vhdl_entity)
982  {
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);
987 
988  // remove prefix from type
989  if (m_token_stream.peek() == "entity")
990  {
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)
994  {
995  instance->m_type = instance->m_type.substr(pos + 1);
996  }
997  if (m_entities_by_name.find(instance->m_type) == m_entities_by_name.end())
998  {
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) + ")");
1001  }
1002  }
1003  else if (m_token_stream.peek() == "component")
1004  {
1005  m_token_stream.consume("component", true);
1006  instance->m_type = m_token_stream.consume();
1007  }
1008  else
1009  {
1010  instance->m_type = m_token_stream.consume();
1011  ci_string prefix;
1012 
1013  // find longest matching library prefix
1014  for (const auto& lib : m_libraries)
1015  {
1016  if (lib.size() > prefix.size() && utils::starts_with(instance->m_type, lib))
1017  {
1018  prefix = lib;
1019  }
1020  }
1021 
1022  // remove prefix
1023  if (!prefix.empty())
1024  {
1025  instance->m_type = instance->m_type.substr(prefix.size());
1026  }
1027  }
1028 
1029  if (m_token_stream.consume("generic"))
1030  {
1031  line_number = m_token_stream.peek().number;
1032  if (const auto res = parse_generic_assign(instance.get()); res.is_error())
1033  {
1034  return ERR_APPEND(res.get_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) + ")");
1037  }
1038  }
1039 
1040  if (m_token_stream.peek() == "port")
1041  {
1042  if (const auto res = parse_port_assign(instance.get()); res.is_error())
1043  {
1044  return ERR_APPEND(res.get_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) + ")");
1047  }
1048  }
1049 
1050  vhdl_entity->m_instances_by_name[instance->m_name] = instance.get();
1051  vhdl_entity->m_instances.push_back(std::move(instance));
1052 
1053  m_token_stream.consume(";", true);
1054 
1055  return OK({});
1056  }
1057 
1058  Result<std::monostate> VHDLParser::parse_port_assign(VhdlInstance* instance)
1059  {
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);
1066 
1067  if (port_stream.find_next("=>") != TokenStream<ci_string>::END_OF_STREAM)
1068  {
1069  while (port_stream.remaining() > 0)
1070  {
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); // last entry has no comma
1075 
1076  if (!right_stream.consume("open"))
1077  {
1078  VhdlPortAssignment port_assignment;
1079 
1080  if (auto res = parse_assignment_expression(std::move(left_stream)); res.is_error())
1081  {
1082  return ERR_APPEND(res.get_error(), "could not parse port assignment: unable to parse port (line " + std::to_string(line_number) + ")");
1083  }
1084  else
1085  {
1086  // vector can only have a single entry for left side of port assignment
1087  port_assignment.m_port = res.get().front();
1088  }
1089 
1090  if (auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1091  {
1092  return ERR_APPEND(res.get_error(), "could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) + ")");
1093  }
1094  else
1095  {
1096  port_assignment.m_assignment = res.get();
1097  }
1098 
1099  instance->m_port_assignments.push_back(std::move(port_assignment));
1100  }
1101  }
1102  }
1103  else
1104  {
1105  while (port_stream.remaining() > 0)
1106  {
1107  TokenStream<ci_string> right_stream = port_stream.extract_until(",");
1108  port_stream.consume(",", port_stream.remaining() > 0); // last entry has no comma
1109 
1110  if (!right_stream.consume("open"))
1111  {
1112  VhdlPortAssignment port_assignment;
1113 
1114  if (auto res = parse_assignment_expression(std::move(right_stream)); res.is_error())
1115  {
1116  return ERR_APPEND(res.get_error(), "could not parse port assignment: unable to parse assignment (line " + std::to_string(line_number) + ")");
1117  }
1118  else
1119  {
1120  port_assignment.m_assignment = res.get();
1121  }
1122 
1123  instance->m_port_assignments.push_back(std::move(port_assignment));
1124  }
1125  else
1126  {
1127  VhdlPortAssignment port_assignment;
1128  port_assignment.m_assignment.push_back("");
1129  instance->m_port_assignments.push_back(std::move(port_assignment));
1130  }
1131  }
1132  }
1133 
1134  return OK({});
1135  }
1136 
1137  Result<std::monostate> VHDLParser::parse_generic_assign(VhdlInstance* instance)
1138  {
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);
1143 
1144  while (generic_stream.remaining() > 0)
1145  {
1146  VhdlDataEntry generic;
1147 
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); // last entry has no comma
1153 
1154  // determine data type
1155  if ((rhs == "true") || (rhs == "false"))
1156  {
1157  generic.m_value = core_strings::to<std::string>(rhs.string);
1158  generic.m_type = "boolean";
1159  }
1160  else if (utils::is_integer(rhs.string))
1161  {
1162  generic.m_value = core_strings::to<std::string>(rhs.string);
1163  generic.m_type = "integer";
1164  }
1165  else if (utils::is_floating_point(rhs.string))
1166  {
1167  generic.m_value = core_strings::to<std::string>(rhs.string);
1168  generic.m_type = "floating_point";
1169  }
1170  else if (utils::ends_with(rhs.string, ci_string("s")) || utils::ends_with(rhs.string, ci_string("sec")) || utils::ends_with(rhs.string, ci_string("min"))
1171  || utils::ends_with(rhs.string, ci_string("hr")))
1172  {
1173  generic.m_value = core_strings::to<std::string>(rhs.string);
1174  generic.m_type = "time";
1175  }
1176  else if (rhs.string.at(0) == '\"' && rhs.string.back() == '\"')
1177  {
1178  generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, rhs.string.size() - 2));
1179  generic.m_type = "string";
1180  }
1181  else if (rhs.string.at(0) == '\'' && rhs.string.at(2) == '\'')
1182  {
1183  generic.m_value = core_strings::to<std::string>(rhs.string.substr(1, 1));
1184  generic.m_type = "bit_value";
1185  }
1186  else if (rhs.string.at(1) == '\"' && rhs.string.back() == '\"')
1187  {
1188  if (auto res = get_hex_from_literal(rhs); res.is_error())
1189  {
1190  return ERR_APPEND(res.get_error(), "could not parse generic assignment: unable to translate token to hexadecimal string");
1191  }
1192  else
1193  {
1194  generic.m_value = core_strings::to<std::string>(res.get());
1195  generic.m_type = "bit_vector";
1196  }
1197  }
1198  else
1199  {
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) + ")");
1202  }
1203 
1204  instance->m_generics.push_back(generic);
1205  }
1206 
1207  return OK({});
1208  }
1209 
1210  Result<std::monostate> VHDLParser::assign_attributes(VhdlEntity* vhdl_entity)
1211  {
1212  for (const auto& [target_class, attributes] : m_attribute_buffer)
1213  {
1214  // entity attributes
1215  if (target_class == AttributeTarget::ENTITY)
1216  {
1217  for (const auto& [target, attribute] : attributes)
1218  {
1219  if (vhdl_entity->m_name != target)
1220  {
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) + ")");
1223  }
1224  else
1225  {
1226  vhdl_entity->m_attributes.push_back(attribute);
1227  }
1228  }
1229  }
1230  // instance attributes
1231  else if (target_class == AttributeTarget::INSTANCE)
1232  {
1233  for (const auto& [target, attribute] : attributes)
1234  {
1235  if (const auto instance_it = vhdl_entity->m_instances_by_name.find(target); instance_it == vhdl_entity->m_instances_by_name.end())
1236  {
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) + ")");
1239  }
1240  else
1241  {
1242  instance_it->second->m_attributes.push_back(attribute);
1243  }
1244  }
1245  }
1246  // signal attributes
1247  else if (target_class == AttributeTarget::SIGNAL)
1248  {
1249  for (const auto& [target, attribute] : attributes)
1250  {
1251  if (const auto signal_it = vhdl_entity->m_signals_by_name.find(target); signal_it != vhdl_entity->m_signals_by_name.end())
1252  {
1253  signal_it->second->m_attributes.push_back(attribute);
1254  }
1255  else
1256  {
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) + ")");
1259  }
1260  }
1261  }
1262  }
1263 
1264  return OK({});
1265  }
1266 
1267  // ###########################################################################
1268  // ########### Assemble Netlist from Intermediate Format ##########
1269  // ###########################################################################
1270 
1271  Result<std::monostate> VHDLParser::construct_netlist(VhdlEntity* top_entity)
1272  {
1273  m_netlist->set_design_name(core_strings::to<std::string>(top_entity->m_name));
1274  m_netlist->enable_automatic_net_checks(false);
1275 
1276  std::unordered_map<ci_string, u32> instantiation_count;
1277 
1278  // preparations for alias: count the occurences of all names
1279  std::queue<VhdlEntity*> q;
1280  q.push(top_entity);
1281 
1282  while (!q.empty())
1283  {
1284  VhdlEntity* entity = q.front();
1285  q.pop();
1286 
1287  instantiation_count[entity->m_name]++;
1288 
1289  // collect and count all net names in the netlist
1290  for (const auto& s : entity->m_signals)
1291  {
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)
1295  {
1296  m_signal_name_occurrences[net_name]++;
1297  }
1298  }
1299 
1300  for (const auto& instance : entity->m_instances)
1301  {
1302  m_instance_name_occurrences[instance->m_name]++;
1303 
1304  // add type of instance to q if it is a module
1305  if (const auto it = m_entities_by_name.find(instance->m_type); it != m_entities_by_name.end())
1306  {
1307  q.push(it->second);
1308  }
1309  }
1310  }
1311 
1312  for (auto& [entity_name, vhdl_entity] : m_entities_by_name)
1313  {
1314  // detect unused entities
1315  if (instantiation_count[entity_name] == 0)
1316  {
1317  log_warning("vhdl_parser", "entity '{}' has been defined in the netlist but is not instantiated.", entity_name);
1318  continue;
1319  }
1320 
1321  // expand gate pin assignments
1322  for (const auto& instance : vhdl_entity->m_instances)
1323  {
1324  if (const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1325  {
1326  if (!instance->m_port_assignments.empty())
1327  {
1328  // all port assignments by name
1329  if (instance->m_port_assignments.front().m_port.has_value())
1330  {
1331  // cache pin groups
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())
1334  {
1335  const auto pins = pin_group->get_pins();
1336  for (auto it = pins.rbegin(); it != pins.rend(); it++)
1337  {
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()));
1340  }
1341  }
1342 
1343  for (const auto& port_assignment : instance->m_port_assignments)
1344  {
1345  auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1346  if (right_res.is_error())
1347  {
1348  return ERR_APPEND(right_res.get_error(), "could not construct netlist: unable to expand gate port assignment");
1349  }
1350  auto right_port = right_res.get();
1351 
1352  if (!right_port.empty())
1353  {
1354  std::vector<ci_string> left_port;
1355 
1356  if (const identifier_t* identifier = std::get_if<identifier_t>(&(port_assignment.m_port.value())); identifier != nullptr)
1357  {
1358  if (const auto group_it = pin_groups.find(*identifier); group_it != pin_groups.end())
1359  {
1360  left_port = group_it->second;
1361  }
1362  else
1363  {
1364  left_port.push_back(*identifier);
1365  }
1366  }
1367  else if (const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&(port_assignment.m_port.value())); ranged_identifier != nullptr)
1368  {
1369  left_port = expand_ranges(ranged_identifier->first, ranged_identifier->second);
1370  }
1371  else
1372  {
1373  return ERR("could not construct netlist: unable to expand gate port assignment");
1374  }
1375 
1376  if (right_port.size() != left_port.size())
1377  {
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) + "'");
1380  }
1381 
1382  for (u32 i = 0; i < left_port.size(); i++)
1383  {
1384  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1385  }
1386  }
1387  }
1388  }
1389  // all port assignments by order
1390  else
1391  {
1392  // cache pins
1393  std::vector<ci_string> pins;
1394  for (const auto pin : gate_type_it->second->get_pins())
1395  {
1396  pins.push_back(core_strings::to<ci_string>(pin->get_name()));
1397  }
1398  auto pin_it = pins.begin();
1399 
1400  for (const auto& port_assignment : instance->m_port_assignments)
1401  {
1402  auto right_res = expand_assignment_expression(vhdl_entity, port_assignment.m_assignment);
1403  if (right_res.is_error())
1404  {
1405  return ERR_APPEND(right_res.get_error(), "could not construct netlist: unable to expand gate port assignment");
1406  }
1407  auto right_port = right_res.get();
1408 
1409  if (!right_port.empty())
1410  {
1411  std::vector<ci_string> left_port;
1412 
1413  for (u32 i = 0; i < right_port.size() && pin_it != pins.end(); i++)
1414  {
1415  left_port.push_back(*pin_it++);
1416  }
1417 
1418  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1419 
1420  for (u32 i = 0; i < max_size; i++)
1421  {
1422  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1423  }
1424  }
1425  }
1426  }
1427  }
1428  }
1429  }
1430  }
1431 
1432  // for the top module, generate global i/o signals for all ports
1433  std::unordered_map<ci_string, ci_string> top_assignments;
1434  for (const auto& port : top_entity->m_ports)
1435  {
1436  for (const auto& expanded_port_identifier : port->m_expanded_identifiers)
1437  {
1438  const auto signal_name = get_unique_alias("", expanded_port_identifier + "__GLOBAL_IO__", m_signal_name_occurrences);
1439 
1440  Net* global_port_net = m_netlist->create_net(core_strings::to<std::string>(signal_name));
1441  if (global_port_net == nullptr)
1442  {
1443  return ERR("could not construct netlist: failed to create global I/O net '" + core_strings::to<std::string>(signal_name) + "'");
1444  }
1445 
1446  m_net_by_name[signal_name] = global_port_net;
1447 
1448  // assign global port nets to ports of top module
1449  top_assignments[expanded_port_identifier] = signal_name;
1450 
1451  if (port->m_direction == PinDirection::input || port->m_direction == PinDirection::inout)
1452  {
1453  if (!global_port_net->mark_global_input_net())
1454  {
1455  return ERR("could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) + "' as global input");
1456  }
1457  }
1458 
1459  if (port->m_direction == PinDirection::output || port->m_direction == PinDirection::inout)
1460  {
1461  if (!global_port_net->mark_global_output_net())
1462  {
1463  return ERR("could not construct netlist: failed to mark global I/O net '" + core_strings::to<std::string>(signal_name) + "' as global output");
1464  }
1465  }
1466  }
1467  }
1468 
1469  if (const auto res = instantiate_entity("top_module", top_entity, nullptr, top_assignments); res.is_error())
1470  {
1471  return ERR_APPEND(res.get_error(), "could not construct netlist: unable to instantiate top module");
1472  }
1473 
1474  // merge nets without gates in between them
1475  std::unordered_map<ci_string, ci_string> merged_nets;
1476  std::unordered_map<ci_string, std::vector<ci_string>> master_to_slaves;
1477 
1478  for (auto& [master, slave] : m_nets_to_merge)
1479  {
1480  // check if master net has already been merged into other net
1481  while (true)
1482  {
1483  if (const auto master_it = merged_nets.find(master); master_it != merged_nets.end())
1484  {
1485  master = master_it->second;
1486  }
1487  else
1488  {
1489  break;
1490  }
1491  }
1492 
1493  // check if slave net has already been merged into other net
1494  while (true)
1495  {
1496  if (const auto slave_it = merged_nets.find(slave); slave_it != merged_nets.end())
1497  {
1498  slave = slave_it->second;
1499  }
1500  else
1501  {
1502  break;
1503  }
1504  }
1505 
1506  auto master_net = m_net_by_name.at(master);
1507  auto slave_net = m_net_by_name.at(slave);
1508 
1509  if (master_net == slave_net)
1510  {
1511  continue;
1512  }
1513  else if (slave_net == m_zero_net || slave_net == m_one_net)
1514  {
1515  auto* tmp_net = master_net;
1516  master_net = slave_net;
1517  slave_net = tmp_net;
1518 
1519  auto tmp_name = master;
1520  master = slave;
1521  slave = tmp_name;
1522  }
1523 
1524  // merge sources
1525  if (slave_net->is_global_input_net())
1526  {
1527  master_net->mark_global_input_net();
1528  }
1529 
1530  for (auto src : slave_net->get_sources())
1531  {
1532  Gate* src_gate = src->get_gate();
1533  GatePin* src_pin = src->get_pin();
1534 
1535  if (!slave_net->remove_source(src))
1536  {
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()));
1538  }
1539 
1540  if (!master_net->is_a_source(src_gate, src_pin))
1541  {
1542  if (!master_net->add_source(src_gate, src_pin))
1543  {
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()));
1545  }
1546  }
1547  }
1548 
1549  // merge destinations
1550  if (slave_net->is_global_output_net())
1551  {
1552  master_net->mark_global_output_net();
1553  }
1554 
1555  for (auto dst : slave_net->get_destinations())
1556  {
1557  Gate* dst_gate = dst->get_gate();
1558  GatePin* dst_pin = dst->get_pin();
1559 
1560  if (!slave_net->remove_destination(dst))
1561  {
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()));
1563  }
1564 
1565  if (!master_net->is_a_destination(dst_gate, dst_pin))
1566  {
1567  if (!master_net->add_destination(dst_gate, dst_pin))
1568  {
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()));
1570  }
1571  }
1572  }
1573 
1574  // merge generics and attributes
1575  for (const auto& [identifier, content] : slave_net->get_data_map())
1576  {
1577  if (!master_net->set_data(std::get<0>(identifier), std::get<1>(identifier), std::get<0>(content), std::get<1>(content)))
1578  {
1579  log_warning("vhdl_parser",
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());
1585  }
1586  }
1587 
1588  // update module ports
1589  if (const auto it = m_module_port_by_net.find(slave_net); it != m_module_port_by_net.end())
1590  {
1591  for (auto [module, index] : it->second)
1592  {
1593  std::get<1>(m_module_ports.at(module).at(index)) = master_net;
1594  }
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);
1597  }
1598 
1599  m_netlist->delete_net(slave_net);
1600  m_net_by_name.erase(slave);
1601  merged_nets[slave] = master;
1602  master_to_slaves[master].push_back(slave);
1603  }
1604 
1605  // annotate all surviving master nets with the net names that where merged into them
1606  for (auto& master_net : m_netlist->get_nets())
1607  {
1608  const auto master_name = master_net->get_name();
1609 
1610  if (const auto m2s_it = master_to_slaves.find(core_strings::to<ci_string>(master_name)); m2s_it != master_to_slaves.end())
1611  {
1612  std::vector<std::vector<ci_string>> merged_slaves;
1613  auto current_slaves = m2s_it->second;
1614 
1615  while (!current_slaves.empty())
1616  {
1617  std::vector<ci_string> next_slaves;
1618  for (const auto& s : current_slaves)
1619  {
1620  if (const auto m2s_inner_it = master_to_slaves.find(s); m2s_inner_it != master_to_slaves.end())
1621  {
1622  next_slaves.insert(next_slaves.end(), m2s_inner_it->second.begin(), m2s_inner_it->second.end());
1623  }
1624  }
1625 
1626  merged_slaves.push_back(current_slaves);
1627  current_slaves = next_slaves;
1628  next_slaves.clear();
1629  }
1630 
1631  // annotate all merged slave wire names as a JSON formatted list of list of strings
1632  // each net can span a tree of "consumed" slave wire names where the nth list represents all wire names that where merged at depth n
1633  ci_string merged_str = "";
1634  bool has_merged_nets = false;
1635  for (const auto& vec : merged_slaves)
1636  {
1637  if (!vec.empty())
1638  {
1639  has_merged_nets = true;
1640  }
1641  // const auto s = utils::join(", ", vec, [](const auto e) { return '"' + e + '"'; });
1642  ci_string s = vec.empty() ? "" : vec.front();
1643  for (u32 idx = 1; idx < vec.size(); idx++)
1644  {
1645  s += ci_string(", ") + vec.at(idx);
1646  }
1647 
1648  merged_str += "[" + s + "], ";
1649  }
1650  merged_str = merged_str.substr(0, merged_str.size() - 2);
1651 
1652  if (has_merged_nets)
1653  {
1654  master_net->set_data("parser_annotation", "merged_nets", "string", "[" + core_strings::to<std::string>(merged_str) + "]");
1655  }
1656  }
1657  }
1658 
1659  // update module nets, internal nets, input nets, and output nets
1660  for (Module* module : m_netlist->get_modules())
1661  {
1662  module->update_nets();
1663  }
1664 
1665  // assign module pins
1666  for (const auto& [module, ports] : m_module_ports)
1667  {
1668  for (const auto& [port_name, port_net] : ports)
1669  {
1670  // check if net is actually a port net
1671  if (!module->is_input_net(port_net) && !module->is_output_net(port_net))
1672  {
1673  continue;
1674  }
1675 
1676  if (auto res = module->create_pin(port_name, port_net); res.is_error())
1677  {
1678  return ERR_APPEND(res.get_error(),
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())
1680  + " within module '" + module->get_name() + "' with ID " + std::to_string(module->get_id()));
1681  }
1682  }
1683  }
1684 
1685  for (Module* module : m_netlist->get_modules())
1686  {
1687  std::unordered_set<Net*> input_nets = module->get_input_nets();
1688  std::unordered_set<Net*> output_nets = module->get_input_nets();
1689 
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()))
1691  {
1692  if (auto res = module->create_pin("'1'", m_one_net); res.is_error())
1693  {
1694  return ERR_APPEND(res.get_error(),
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 '"
1696  + module->get_name() + "' with ID " + std::to_string(module->get_id()));
1697  }
1698  }
1699 
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()))
1701  {
1702  if (auto res = module->create_pin("'0'", m_zero_net); res.is_error())
1703  {
1704  return ERR_APPEND(res.get_error(),
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())
1706  + "within module '" + module->get_name() + "' with ID " + std::to_string(module->get_id()));
1707  }
1708  }
1709  }
1710 
1711  m_netlist->enable_automatic_net_checks(true);
1712  return OK({});
1713  }
1714 
1715  Result<Module*>
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)
1717  {
1718  std::unordered_map<ci_string, ci_string> signal_alias;
1719  std::unordered_map<ci_string, ci_string> instance_alias;
1720 
1721  // TODO check parent module assignments for port aliases
1722 
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);
1725 
1726  // create netlist module
1727  Module* module;
1728  if (parent == nullptr)
1729  {
1730  module = m_netlist->get_top_module();
1731  module->set_name(core_strings::to<std::string>(instance_alias.at(instance_identifier)));
1732  }
1733  else
1734  {
1735  module = m_netlist->create_module(core_strings::to<std::string>(instance_alias.at(instance_identifier)), parent);
1736  }
1737 
1738  ci_string instance_type = vhdl_entity->m_name;
1739  if (module == nullptr)
1740  {
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");
1743  }
1744  module->set_type(core_strings::to<std::string>(instance_type));
1745 
1746  // assign entity-level attributes
1747  for (const VhdlDataEntry& attribute : vhdl_entity->m_attributes)
1748  {
1749  if (!module->set_data("attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1750  {
1751  log_warning("vhdl_parser",
1752  "could not set attribute '{} = {}' of type '{}' for instance '{}' type '{}'.",
1753  attribute.m_name,
1754  attribute.m_value,
1755  attribute.m_type,
1756  instance_identifier,
1757  instance_type);
1758  }
1759  }
1760 
1761  // assign module port names
1762  for (const auto& port : vhdl_entity->m_ports)
1763  {
1764  for (const auto& expanded_port_identifier : port->m_expanded_identifiers)
1765  {
1766  if (const auto it = parent_module_assignments.find(expanded_port_identifier); it != parent_module_assignments.end())
1767  {
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));
1771  }
1772  }
1773  }
1774 
1775  // create internal signals
1776  for (const auto& signal : vhdl_entity->m_signals)
1777  {
1778  for (const auto& expanded_name : signal->m_expanded_names)
1779  {
1780  signal_alias[expanded_name] = get_unique_alias(instance_alias[instance_identifier], expanded_name, m_signal_name_occurrences);
1781 
1782  // create new net for the signal
1783  Net* signal_net = m_netlist->create_net(core_strings::to<std::string>(signal_alias.at(expanded_name)));
1784  if (signal_net == nullptr)
1785  {
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) + "'");
1788  }
1789 
1790  m_net_by_name[signal_alias.at(expanded_name)] = signal_net;
1791 
1792  // assign signal attributes
1793  for (const VhdlDataEntry& attribute : signal->m_attributes)
1794  {
1795  if (!signal_net->set_data("attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1796  {
1797  log_warning("vhdl_parser",
1798  "could not set attribute ({} = {}) for net '{}' of instance '{}' of type '{}'.",
1799  attribute.m_name,
1800  attribute.m_value,
1801  expanded_name,
1802  instance_identifier,
1803  instance_type);
1804  }
1805  }
1806  }
1807  }
1808 
1809  // schedule assigned nets for merging
1810  for (const auto& [left_expanded_signal, right_expanded_signal] : vhdl_entity->m_expanded_assignments)
1811  {
1812  ci_string a = left_expanded_signal;
1813  ci_string b = right_expanded_signal;
1814 
1815  if (const auto alias_it = signal_alias.find(a); alias_it != signal_alias.end())
1816  {
1817  a = alias_it->second;
1818  }
1819  else
1820  {
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) + "'");
1823  }
1824 
1825  if (const auto alias_it = signal_alias.find(b); alias_it != signal_alias.end())
1826  {
1827  b = alias_it->second;
1828  }
1829  else if (b == "'Z'" || b == "'X'")
1830  {
1831  continue;
1832  }
1833  else if (b != "'0'" && b != "'1'")
1834  {
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) + "'");
1837  }
1838 
1839  m_nets_to_merge.push_back(std::make_pair(a, b));
1840  }
1841 
1842  // schedule assigned port nets for merging
1843  for (const auto& [port_expression, net_name] : parent_module_assignments)
1844  {
1845  if (const auto alias_it = signal_alias.find(port_expression); alias_it != signal_alias.end())
1846  {
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));
1849  }
1850  else
1851  {
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) + "'");
1854  }
1855  }
1856 
1857  // process instances i.e. gates or other entities
1858  for (const auto& instance : vhdl_entity->m_instances)
1859  {
1860  // will later hold either module or gate, so attributes can be assigned properly
1861  DataContainer* container = nullptr;
1862 
1863  // assign actual signal names to ports
1864  std::unordered_map<ci_string, ci_string> instance_assignments;
1865 
1866  // if the instance is another entity, recursively instantiate it
1867  if (auto entity_it = m_entities_by_name.find(instance->m_type); entity_it != m_entities_by_name.end())
1868  {
1869  // expand port assignments
1870  for (const auto& [port, assignment] : instance->m_expanded_port_assignments)
1871  {
1872  if (const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1873  {
1874  instance_assignments[port] = alias_it->second;
1875  }
1876  else if (assignment == "'0'" || assignment == "'1'")
1877  {
1878  instance_assignments[port] = assignment;
1879  }
1880  else if (assignment == "'Z'" || assignment == "'X'" || assignment == "")
1881  {
1882  continue;
1883  }
1884  else
1885  {
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");
1888  }
1889  }
1890 
1891  if (auto res = instantiate_entity(instance->m_name, entity_it->second, module, instance_assignments); res.is_error())
1892  {
1893  return ERR_APPEND(res.get_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) + "'");
1897  }
1898  else
1899  {
1900  container = res.get();
1901  }
1902  }
1903  // otherwise it has to be an element from the gate library
1904  else if (const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1905  {
1906  // create the new gate
1907  instance_alias[instance->m_name] = get_unique_alias(instance_alias[instance_identifier], instance->m_name, m_instance_name_occurrences);
1908 
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)
1911  {
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) + "'");
1914  }
1915 
1916  if (!module->is_top_module())
1917  {
1918  module->assign_gate(new_gate);
1919  }
1920 
1921  container = new_gate;
1922 
1923  // if gate is of a GND or VCC gate type, mark it as such
1924  if (m_vcc_gate_types.find(instance->m_type) != m_vcc_gate_types.end() && !new_gate->mark_vcc_gate())
1925  {
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");
1928  }
1929  if (m_gnd_gate_types.find(instance->m_type) != m_gnd_gate_types.end() && !new_gate->mark_gnd_gate())
1930  {
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");
1933  }
1934 
1935  // cache pin names
1936  std::unordered_map<ci_string, GatePin*> pin_names_map;
1937  for (auto* pin : gate_type_it->second->get_pins())
1938  {
1939  pin_names_map[core_strings::to<ci_string>(pin->get_name())] = pin;
1940  }
1941 
1942  // expand pin assignments
1943  for (const auto& [pin, assignment] : instance->m_expanded_port_assignments)
1944  {
1945  ci_string signal;
1946 
1947  if (const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1948  {
1949  signal = alias_it->second;
1950  }
1951  else if (assignment == "'0'" || assignment == "'1'")
1952  {
1953  signal = assignment;
1954  }
1955  else if (assignment == "'Z'" || assignment == "'X'" || assignment == "")
1956  {
1957  continue;
1958  }
1959  else
1960  {
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");
1964  }
1965 
1966  // get the respective net for the assignment
1967  if (const auto net_it = m_net_by_name.find(signal); net_it == m_net_by_name.end())
1968  {
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");
1972  }
1973  else
1974  {
1975  Net* current_net = net_it->second;
1976 
1977  // add net src/dst by pin types
1978  bool is_input = false;
1979  bool is_output = false;
1980 
1981  if (const auto it = pin_names_map.find(pin); it != pin_names_map.end())
1982  {
1983  PinDirection direction = it->second->get_direction();
1985  {
1986  is_input = true;
1987  }
1988 
1990  {
1991  is_output = true;
1992  }
1993  }
1994 
1995  if (!is_input && !is_output)
1996  {
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() + "'");
2000  }
2001 
2002  if (is_output && !current_net->add_source(new_gate, core_strings::to<std::string>(pin)))
2003  {
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) + "'");
2007  }
2008 
2009  if (is_input && !current_net->add_destination(new_gate, core_strings::to<std::string>(pin)))
2010  {
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) + "'");
2014  }
2015  }
2016  }
2017  }
2018  else
2019  {
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() + "'");
2022  }
2023 
2024  // assign instance attributes
2025  for (const auto& attribute : instance->m_attributes)
2026  {
2027  if (!container->set_data("attribute", attribute.m_name, attribute.m_type, attribute.m_value))
2028  {
2029  log_warning("vhdl_parser",
2030  "could not set attribute '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2031  attribute.m_name,
2032  attribute.m_value,
2033  attribute.m_type,
2034  instance->m_name,
2035  instance->m_type,
2036  instance_identifier,
2037  instance_type);
2038  }
2039  }
2040 
2041  // process generics
2042  for (const auto& generic : instance->m_generics)
2043  {
2044  if (!container->set_data("generic", generic.m_name, generic.m_type, generic.m_value))
2045  {
2046  log_warning("vhdl_parser",
2047  "could not set generic '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
2048  generic.m_name,
2049  generic.m_value,
2050  generic.m_type,
2051  instance->m_name,
2052  instance->m_type,
2053  instance_identifier,
2054  instance_type);
2055  }
2056  }
2057  }
2058 
2059  return OK(module);
2060  }
2061 
2062  // ###########################################################################
2063  // ################### Helper Functions ####################
2064  // ###########################################################################
2065 
2066  namespace
2067  {
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}};
2069 
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}};
2074 
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}}};
2085 
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}}};
2105  } // namespace
2106 
2107  // generate a unique name for a gate/module instance
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
2109  {
2110  ci_string unique_alias = name;
2111 
2112  if (!parent_name.empty())
2113  {
2114  // if there is no other instance with that name, we omit the name prefix
2115  if (const auto instance_name_it = name_occurences.find(name); instance_name_it != name_occurences.end() && instance_name_it->second > 1)
2116  {
2117  unique_alias = parent_name + ci_string("/") + unique_alias;
2118  }
2119  }
2120 
2121  return unique_alias;
2122  }
2123 
2124  std::vector<u32> VHDLParser::parse_range(TokenStream<ci_string>& range_stream) const
2125  {
2126  if (range_stream.remaining() == 1)
2127  {
2128  return {(u32)std::stoi(core_strings::to<std::string>(range_stream.consume().string))};
2129  }
2130 
2131  int direction = 1;
2132  const int end = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2133 
2134  if (range_stream.peek() == "downto")
2135  {
2136  range_stream.consume("downto");
2137  }
2138  else
2139  {
2140  range_stream.consume("to", true);
2141  direction = -1;
2142  }
2143 
2144  const int start = std::stoi(core_strings::to<std::string>(range_stream.consume().string));
2145 
2146  std::vector<u32> res;
2147  for (int i = start; i != end + direction; i += direction)
2148  {
2149  res.push_back((u32)i);
2150  }
2151  return res;
2152  }
2153 
2154  Result<std::vector<std::vector<u32>>> VHDLParser::parse_signal_ranges(TokenStream<ci_string>& signal_stream) const
2155  {
2156  std::vector<std::vector<u32>> ranges;
2157  const u32 line_number = signal_stream.peek().number;
2158 
2159  const Token<ci_string> type_name = signal_stream.consume();
2160  if (type_name == "std_logic")
2161  {
2162  return OK(ranges);
2163  }
2164 
2165  signal_stream.consume("(", true);
2166  TokenStream<ci_string> signal_bounds_stream = signal_stream.extract_until(")");
2167 
2168  // process ranges
2169  do
2170  {
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(","));
2174 
2175  signal_stream.consume(")", true);
2176 
2177  if (id_to_dim.find(type_name) != id_to_dim.end())
2178  {
2179  const size_t dimension = id_to_dim.at(type_name);
2180 
2181  if (ranges.size() != dimension)
2182  {
2183  return ERR("could not parse signal ranges: mismatch of dimensions (line " + std::to_string(line_number) + ")");
2184  }
2185  }
2186  else
2187  {
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) + ")");
2189  }
2190 
2191  return OK(ranges);
2192  }
2193 
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
2195  {
2196  // expand signal recursively
2197  if (ranges.size() > dimension)
2198  {
2199  for (const u32 index : ranges[dimension])
2200  {
2201  expand_ranges_recursively(expanded_names, current_name + "(" + core_strings::to<ci_string>(std::to_string(index)) + ")", ranges, dimension + 1);
2202  }
2203  }
2204  else
2205  {
2206  // last dimension
2207  expanded_names.push_back(current_name);
2208  }
2209  }
2210 
2211  std::vector<VHDLParser::ci_string> VHDLParser::expand_ranges(const ci_string& name, const std::vector<std::vector<u32>>& ranges) const
2212  {
2213  std::vector<ci_string> res;
2214 
2215  expand_ranges_recursively(res, name, ranges, 0);
2216 
2217  return res;
2218  }
2219 
2220  Result<std::vector<BooleanFunction::Value>> VHDLParser::get_binary_vector(std::string value) const
2221  {
2222  value = utils::to_upper(utils::replace(value, std::string("_"), std::string("")));
2223 
2224  std::string prefix;
2225  std::string number;
2226  std::vector<BooleanFunction::Value> result;
2227 
2228  // base specified?
2229  if (value.at(0) != '\"')
2230  {
2231  prefix = value.at(0);
2232  number = value.substr(2, value.rfind('\"') - 2);
2233  }
2234  else
2235  {
2236  prefix = "B";
2237  number = value.substr(1, value.rfind('\"') - 1);
2238  }
2239 
2240  // select base
2241  switch (prefix.at(0))
2242  {
2243  case 'B': {
2244  for (auto it = number.rbegin(); it != number.rend(); it++)
2245  {
2246  const char c = *it;
2247  if (c == '0' || c == '1' || c == 'Z' || c == 'X')
2248  {
2249  result.push_back(bin_map.at(c));
2250  }
2251  else
2252  {
2253  return ERR("could not convert string to binary vector: invalid character within binary number literal '" + value + "'");
2254  }
2255  }
2256  break;
2257  }
2258 
2259  case 'O':
2260  for (auto it = number.rbegin(); it != number.rend(); it++)
2261  {
2262  const char c = *it;
2263  if ((c >= '0' && c <= '7') || c == 'X' || c == 'Z')
2264  {
2265  const auto& bits = oct_map.at(c);
2266  result.insert(result.end(), bits.begin(), bits.end());
2267  }
2268  else
2269  {
2270  return ERR("could not convert string to binary vector: invalid character within octal number literal '" + value + "'");
2271  }
2272  }
2273  break;
2274 
2275  case 'D': {
2276  u64 tmp_val = 0;
2277 
2278  for (const char c : number)
2279  {
2280  if ((c >= '0' && c <= '9'))
2281  {
2282  tmp_val = (tmp_val * 10) + (c - '0');
2283  }
2284  else
2285  {
2286  return ERR("could not convert string to binary vector: invalid character within decimal number literal '" + value + "'");
2287  }
2288  }
2289 
2290  do
2291  {
2292  result.push_back(((tmp_val & 1) == 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
2293  tmp_val >>= 1;
2294  } while (tmp_val != 0);
2295  break;
2296  }
2297 
2298  case 'H': {
2299  for (auto it = number.rbegin(); it != number.rend(); it++)
2300  {
2301  const char c = *it;
2302  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || c == 'X' || c == 'Z')
2303  {
2304  const auto& bits = hex_map.at(c);
2305  result.insert(result.end(), bits.begin(), bits.end());
2306  }
2307  else
2308  {
2309  return ERR("could not convert string to binary vector: invalid character within hexadecimal number literal '" + value + "'");
2310  }
2311  }
2312  break;
2313  }
2314 
2315  default: {
2316  return ERR("could not convert string to binary vector: invalid base '" + prefix + "' within number literal '" + value + "'");
2317  }
2318  }
2319 
2320  return OK(result);
2321  }
2322 
2323  Result<std::string> VHDLParser::get_hex_from_literal(const Token<ci_string>& value_token) const
2324  {
2325  const u32 line_number = value_token.number;
2326  const ci_string value = utils::to_upper(utils::replace(value_token.string, ci_string("_"), ci_string("")));
2327 
2328  ci_string prefix;
2329  ci_string number;
2330  u32 base;
2331 
2332  // base specified?
2333  if (value.at(0) != '\"')
2334  {
2335  prefix = value.at(0);
2336  number = value.substr(2, value.rfind('\"') - 2);
2337  }
2338  else
2339  {
2340  prefix = "B";
2341  number = value.substr(1, value.rfind('\"') - 1);
2342  }
2343 
2344  // select base
2345  switch (prefix.at(0))
2346  {
2347  case 'B': {
2348  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '1'); }))
2349  {
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) + ")");
2352  }
2353 
2354  base = 2;
2355  break;
2356  }
2357 
2358  case 'O': {
2359  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '7'); }))
2360  {
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) + ")");
2363  }
2364 
2365  base = 8;
2366  break;
2367  }
2368 
2369  case 'D': {
2370  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '9'); }))
2371  {
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) + ")");
2374  }
2375 
2376  base = 10;
2377  break;
2378  }
2379 
2380  case 'X': {
2381  std::string res;
2382 
2383  for (const char c : number)
2384  {
2385  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
2386  {
2387  res += c;
2388  }
2389  else
2390  {
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) + ")");
2393  }
2394  }
2395 
2396  return OK(res);
2397  }
2398 
2399  default: {
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) + ")");
2402  }
2403  }
2404 
2405  std::stringstream ss;
2406  ss << std::uppercase << std::hex << stoull(core_strings::to<std::string>(number), 0, base);
2407  return OK(ss.str());
2408  }
2409 
2410  Result<std::vector<VHDLParser::assignment_t>> VHDLParser::parse_assignment_expression(TokenStream<ci_string>&& stream) const
2411  {
2412  // PARSE ASSIGNMENT
2413  // assignment can currently be one of the following:
2414  // (1) NAME
2415  // (2) NUMBER
2416  // (3) NAME(INDEX1, INDEX2, ...)
2417  // (4) NAME(BEGIN_INDEX1 to/downto END_INDEX1, BEGIN_INDEX2 to/downto END_INDEX2, ...)
2418  // (5) ((1 - 4), (1 - 4), ...)
2419 
2420  std::vector<TokenStream<ci_string>> parts;
2421 
2422  if (stream.size() == 0)
2423  {
2424  return OK({});
2425  }
2426 
2427  // (5) ((1 - 4), (1 - 4), ...)
2428  if (stream.consume("("))
2429  {
2430  do
2431  {
2432  parts.push_back(stream.extract_until(","));
2433  } while (stream.consume(",", false));
2434 
2435  stream.consume(")", true);
2436  }
2437  else
2438  {
2439  parts.push_back(stream);
2440  }
2441 
2442  std::vector<assignment_t> result;
2443  result.reserve(parts.size());
2444 
2445  for (auto it = parts.rbegin(); it != parts.rend(); it++)
2446  {
2447  TokenStream<ci_string>& part_stream = *it;
2448 
2449  const Token<ci_string> signal_name_token = part_stream.consume();
2450  ci_string signal_name = signal_name_token.string;
2451 
2452  // (2) NUMBER
2455  {
2456  if (auto res = get_binary_vector(core_strings::to<std::string>(signal_name_token.string)); res.is_error())
2457  {
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) + ")");
2459  }
2460  else
2461  {
2462  result.push_back(std::move(res.get()));
2463  }
2464  }
2465  else if (signal_name == "'0'")
2466  {
2467  result.push_back(numeral_t({BooleanFunction::Value::ZERO}));
2468  }
2469  else if (signal_name == "'1'")
2470  {
2471  result.push_back(numeral_t({BooleanFunction::Value::ONE}));
2472  }
2473  else if (signal_name == "'X'")
2474  {
2475  result.push_back(numeral_t({BooleanFunction::Value::X}));
2476  }
2477  else if (signal_name == "'Z'")
2478  {
2479  result.push_back(numeral_t({BooleanFunction::Value::Z}));
2480  }
2481  else
2482  {
2483  // (3) NAME(INDEX1, INDEX2, ...)
2484  // (4) NAME(BEGIN_INDEX1 to/downto END_INDEX1, BEGIN_INDEX2 to/downto END_INDEX2, ...)
2485  if (part_stream.consume("("))
2486  {
2487  std::vector<std::vector<u32>> ranges;
2488  u32 closing_pos = part_stream.find_next(")");
2489  do
2490  {
2491  TokenStream<ci_string> range_stream = part_stream.extract_until(",", closing_pos);
2492  ranges.emplace_back(parse_range(range_stream));
2493 
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)}));
2497  }
2498  else
2499  {
2500  // (1) NAME
2501  result.push_back(std::move(signal_name));
2502  }
2503  }
2504  }
2505 
2506  return OK(result);
2507  }
2508 
2509  Result<std::vector<VHDLParser::ci_string>> VHDLParser::expand_assignment_expression(VhdlEntity* vhdl_entity, const std::vector<assignment_t>& vars) const
2510  {
2511  std::vector<ci_string> result;
2512  for (const auto& var : vars)
2513  {
2514  if (const identifier_t* identifier = std::get_if<identifier_t>(&var); identifier != nullptr)
2515  {
2516  if (identifier->empty())
2517  {
2518  result.push_back(*identifier);
2519  continue;
2520  }
2521  std::vector<std::vector<u32>> ranges;
2522 
2523  if (const auto signal_it = vhdl_entity->m_signals_by_name.find(*identifier); signal_it != vhdl_entity->m_signals_by_name.end())
2524  {
2525  ranges = signal_it->second->m_ranges;
2526  }
2527  else if (const auto port_it = vhdl_entity->m_ports_by_identifier.find(*identifier); port_it != vhdl_entity->m_ports_by_identifier.end())
2528  {
2529  ranges = port_it->second->m_ranges;
2530  }
2531  else
2532  {
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) + "'");
2535  }
2536 
2537  std::vector<ci_string> expanded = expand_ranges(*identifier, ranges);
2538  result.insert(result.end(), expanded.begin(), expanded.end());
2539  }
2540  else if (const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier != nullptr)
2541  {
2542  std::vector<ci_string> expanded = expand_ranges(ranged_identifier->first, ranged_identifier->second);
2543  result.insert(result.end(), expanded.begin(), expanded.end());
2544  }
2545  else if (const numeral_t* numeral = std::get_if<numeral_t>(&var); numeral != nullptr)
2546  {
2547  for (auto value : *numeral)
2548  {
2549  result.push_back(core_strings::to<ci_string>("'" + BooleanFunction::to_string(value) + "'"));
2550  }
2551  }
2552  }
2553 
2554  return OK(result);
2555  }
2556 } // namespace hal
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)
Definition: gate.h:58
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
Definition: gate_type.cpp:285
bool is_input_net(Net *net) const
Definition: module.cpp:555
void set_name(const std::string &name)
Definition: module.cpp:92
void update_nets()
Definition: module.cpp:434
bool is_top_module() const
Definition: module.cpp:312
bool assign_gate(Gate *gate)
Definition: module.cpp:322
bool is_output_net(Net *net) const
Definition: module.cpp:565
std::string get_name() const
Definition: module.cpp:87
const std::unordered_set< Net * > & get_input_nets() const
Definition: module.cpp:540
void set_type(const std::string &type)
Definition: module.cpp:111
ModulePin * get_pin_by_net(Net *net) const
Definition: module.cpp:1017
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)
Definition: module.cpp:787
u32 get_id() const
Definition: module.cpp:82
Definition: net.h:58
u32 get_id() const
Definition: net.cpp:88
Endpoint * add_source(Gate *gate, const std::string &pin_name)
Definition: net.cpp:127
const std::string & get_name() const
Definition: net.cpp:98
u32 get_num_of_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
Definition: net.cpp:408
Module * get_top_module() const
Definition: netlist.cpp:608
u32 get_unique_gate_id()
Definition: netlist.cpp:160
bool mark_vcc_gate(Gate *gate)
Definition: netlist.cpp:228
bool mark_gnd_gate(Gate *gate)
Definition: netlist.cpp:244
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 >())
Definition: netlist.cpp:862
bool delete_net(Net *net)
Definition: netlist.cpp:343
Net * create_net(const u32 net_id, const std::string &name)
Definition: netlist.cpp:333
const std::vector< Gate * > & get_gnd_gates() const
Definition: netlist.cpp:309
void set_design_name(const std::string &name)
Definition: netlist.cpp:109
void enable_automatic_net_checks(bool enable_checks=true)
Definition: netlist.cpp:563
const std::vector< Gate * > & get_vcc_gates() const
Definition: netlist.cpp:304
const std::vector< Module * > & get_modules() const
Definition: netlist.cpp:624
Gate * create_gate(const u32 gate_id, GateType *gate_type, const std::string &name="", i32 x=-1, i32 y=-1)
Definition: netlist.cpp:173
const std::vector< Net * > & get_nets() const
Definition: netlist.cpp:364
const GateLibrary * get_gate_library() const
Definition: netlist.cpp:132
Module * create_module(const u32 module_id, const std::string &name, Module *parent, const std::vector< Gate * > &gates={})
Definition: netlist.cpp:587
u32 remaining() const
Definition: token_stream.h:494
static const u32 END_OF_STREAM
Definition: token_stream.h:147
Token< T > consume_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:266
Token< T > & peek(i32 offset=0)
Definition: token_stream.h:392
u32 find_next(const T &match, u32 end=END_OF_STREAM, bool level_aware=true) const
Definition: token_stream.h:446
Token< T > join_until(const T &match, const T &joiner, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:338
TokenStream< T > extract_until(const T &expected, u32 end=END_OF_STREAM, bool level_aware=true, bool throw_on_error=false)
Definition: token_stream.h:308
Token< T > consume(u32 num=1)
Definition: token_stream.h:216
Result< std::monostate > parse(const std::filesystem::path &file_path) override
Definition: vhdl_parser.cpp:22
Result< std::unique_ptr< Netlist > > instantiate(const GateLibrary *gate_library) override
uint64_t u64
Definition: defines.h:42
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
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)
Definition: utils.h:382
CORE_API bool ends_with(const T &s, const T &end)
Definition: utils.h:147
CORE_API bool is_digits(const T &s)
Definition: utils.h:186
CORE_API bool starts_with(const T &s, const T &start)
Definition: utils.h:167
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
Definition: utils.h:358
CORE_API bool is_integer(const T &s)
Definition: utils.h:198
CORE_API bool is_floating_point(const T &s)
Definition: utils.h:218
CORE_API T to_upper(const T &s)
Definition: utils.h:463
PinDirection
Definition: pin_direction.h:36
quint32 u32
std::vector< PinInformation > pins
Net * net
PinDirection direction
std::string name
This file contains various functions to create and load netlists.