HAL  v4.5.0-254-g8f9f6a423
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
verilog_parser.cpp
Go to the documentation of this file.
2 
10 
11 #include <fstream>
12 #include <iomanip>
13 #include <numeric>
14 #include <queue>
15 
16 namespace hal
17 {
18  namespace
19  {
20  // Strict double parse: must consume the full string (no trailing junk).
21  bool is_double_strict(const std::string& s)
22  {
23  if (s.empty())
24  {
25  return false;
26  }
27  try
28  {
29  size_t idx;
30  std::stod(s, &idx);
31  return idx == s.size();
32  }
33  catch (...)
34  {
35  return false;
36  }
37  }
38  } // namespace
39 
40  Result<std::monostate> VerilogParser::parse(const std::filesystem::path& file_path)
41  {
42  m_path = file_path;
43  m_modules.clear();
44  m_modules_by_name.clear();
45 
46  {
47  std::ifstream ifs;
48  ifs.open(file_path.string(), std::ifstream::in);
49  if (!ifs.is_open())
50  {
51  return ERR("could not parse Verilog file '" + m_path.string() + "' : unable to open file");
52  }
53  m_fs << ifs.rdbuf();
54  ifs.close();
55  }
56 
57  // tokenize file
58  tokenize();
59 
60  // parse tokens into intermediate format
61  try
62  {
63  if (auto res = parse_tokens(); res.is_error())
64  {
65  return ERR_APPEND(res.get_error(), "could not parse Verilog file '" + file_path.string() + "': unable to parse tokens");
66  }
67  }
69  {
70  if (e.line_number != (u32)-1)
71  {
72  return ERR("could not parse Verilog file '" + m_path.string() + "': " + e.message + " (line " + std::to_string(e.line_number) + ")");
73  }
74  else
75  {
76  return ERR("could not parse Verilog file '" + m_path.string() + "': " + e.message);
77  }
78  }
79 
80  if (m_modules.empty())
81  {
82  return ERR("could not parse Verilog file '" + m_path.string() + "': does not contain any modules");
83  }
84 
85  // expand module port identifiers, signals, and assignments
86  for (auto& [module_name, verilog_module] : m_modules_by_name)
87  {
88  // expand port identifiers
89  for (const auto& port : verilog_module->m_ports)
90  {
91  const bool stands_for_one_signal = port->m_expression_parts.size() == 1 && std::holds_alternative<identifier_t>(port->m_expression_parts.front());
92  if (!stands_for_one_signal)
93  {
94  // the width of the port is the width of its expression, whose signals are declared by now
95  const std::vector<std::string> expanded_expression = expand_assignment_expression(verilog_module, port->m_expression_parts);
96  if (expanded_expression.empty())
97  {
98  return ERR("could not parse Verilog file '" + m_path.string() + "': unable to expand the expression of port '" + port->m_identifier + "' of module '" + verilog_module->m_name + "'");
99  }
100  if (expanded_expression.size() == 1)
101  {
102  port->m_expanded_identifiers = {port->m_identifier};
103  }
104  else
105  {
106  std::vector<u32> range(expanded_expression.size());
107  std::iota(range.begin(), range.end(), 0);
108  port->m_ranges = {range};
109  port->m_expanded_identifiers = expand_ranges(port->m_identifier, port->m_ranges);
110  }
111  for (u32 i = 0; i < expanded_expression.size(); i++)
112  {
113  verilog_module->m_expanded_port_identifiers_to_expressions[port->m_expanded_identifiers.at(i)] = expanded_expression.at(i);
114  }
115  }
116  else if (const identifier_t& signal = std::get<identifier_t>(port->m_expression_parts.front()); signal != port->m_identifier)
117  {
118  // the port stands for one whole signal of another name, bit for bit
119  port->m_expanded_identifiers = port->m_ranges.empty() ? std::vector<std::string>{port->m_identifier} : expand_ranges(port->m_identifier, port->m_ranges);
120  const std::vector<std::string> expanded_expression = port->m_ranges.empty() ? std::vector<std::string>{signal} : expand_ranges(signal, port->m_ranges);
121  for (u32 i = 0; i < expanded_expression.size(); i++)
122  {
123  verilog_module->m_expanded_port_identifiers_to_expressions[port->m_expanded_identifiers.at(i)] = expanded_expression.at(i);
124  }
125  }
126  else
127  {
128  port->m_expanded_identifiers = port->m_ranges.empty() ? std::vector<std::string>{port->m_identifier} : expand_ranges(port->m_identifier, port->m_ranges);
129  }
130  }
131 
132  // expand signals
133  for (auto& signal : verilog_module->m_signals)
134  {
135  if (!signal->m_ranges.empty())
136  {
137  signal->m_expanded_names = expand_ranges(signal->m_name, signal->m_ranges);
138  }
139  else
140  {
141  signal->m_expanded_names = std::vector<std::string>({signal->m_name});
142  }
143  }
144 
145  // expand assignments
146  for (auto& assignment : verilog_module->m_assignments)
147  {
148  const std::vector<std::string> left_signals = expand_assignment_expression(verilog_module, assignment.m_variable);
149  const std::vector<std::string> right_signals = expand_assignment_expression(verilog_module, assignment.m_assignment);
150  if (left_signals.empty() || right_signals.empty())
151  {
152  return ERR("could not parse Verilog file '" + m_path.string() + "': unable to expand assignments within module '" + verilog_module->m_name + "'");
153  }
154 
155  u32 left_size = left_signals.size();
156  u32 right_size = right_signals.size();
157  if (left_size <= right_size)
158  {
159  // cut off redundant bits
160  for (u32 i = 0; i < left_size; i++)
161  {
162  verilog_module->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i), right_signals.at(i)));
163  }
164  }
165  else
166  {
167  for (u32 i = 0; i < right_size; i++)
168  {
169  verilog_module->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i), right_signals.at(i)));
170  }
171 
172  // implicit "0"
173  for (u32 i = 0; i < left_size - right_size; i++)
174  {
175  verilog_module->m_expanded_assignments.push_back(std::make_pair(left_signals.at(i + right_size), "'0'"));
176  }
177  }
178  }
179  }
180 
181  // expand module port assignments
182  for (auto& [module_name, verilog_module] : m_modules_by_name)
183  {
184  for (auto& instance : verilog_module->m_instances)
185  {
186  if (auto module_it = m_modules_by_name.find(instance->m_type); module_it != m_modules_by_name.end())
187  {
188  instance->m_is_module = true;
189  if (!instance->m_port_assignments.empty())
190  {
191  // all port assignments by name
192  if (instance->m_port_assignments.front().m_port_name.has_value())
193  {
194  for (const auto& port_assignment : instance->m_port_assignments)
195  {
196  const std::vector<std::string> right_port = expand_assignment_expression(verilog_module, port_assignment.m_assignment);
197  if (!right_port.empty())
198  {
199  VerilogPort* port;
200  if (const auto port_it = module_it->second->m_ports_by_identifier.find(port_assignment.m_port_name.value());
201  port_it == module_it->second->m_ports_by_identifier.end())
202  {
203  return ERR("could not parse Verilog file '" + m_path.string() + "': unable to assign signal to port '" + port_assignment.m_port_name.value()
204  + "' as it is not a port of module '" + module_it->first + "'");
205  }
206  else
207  {
208  port = port_it->second;
209  }
210  const std::vector<std::string>& left_port = port->m_expanded_identifiers;
211  if (left_port.empty())
212  {
213  return ERR("could not parse Verilog file '" + m_path.string() + "': unable to expand port assignment");
214  }
215 
216  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
217 
218  for (u32 i = 0; i < max_size; i++)
219  {
220  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
221  }
222  }
223  }
224  }
225  // all port assignments by order
226  else
227  {
228  std::vector<std::string> ports;
229  for (const auto& port : m_modules_by_name.at(instance->m_type)->m_ports)
230  {
231  ports.insert(ports.end(), port->m_expanded_identifiers.begin(), port->m_expanded_identifiers.end());
232  }
233 
234  auto port_it = ports.begin();
235 
236  for (const auto& port_assignment : instance->m_port_assignments)
237  {
238  std::vector<std::string> right_port = expand_assignment_expression(verilog_module, port_assignment.m_assignment);
239  if (!right_port.empty())
240  {
241  std::vector<std::string> left_port;
242 
243  for (u32 i = 0; i < right_port.size() && port_it != ports.end(); i++)
244  {
245  left_port.push_back(*port_it++);
246  }
247 
248  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
249 
250  for (u32 i = 0; i < max_size; i++)
251  {
252  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
253  }
254  }
255  }
256  }
257  }
258  }
259  }
260  }
261 
262  return OK({});
263  }
264 
266  {
267  // create empty netlist
268  std::unique_ptr<Netlist> result = netlist_factory::create_netlist(gate_library);
269  m_netlist = result.get();
270  if (m_netlist == nullptr)
271  {
272  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create empty netlist");
273  }
274 
275  m_gate_types.clear();
276  m_gnd_gate_types.clear();
277  m_vcc_gate_types.clear();
278  m_module_instantiation_count.clear();
279  m_instance_name_occurences.clear();
280  m_net_name_occurences.clear();
281  m_net_by_name.clear();
282  m_nets_to_merge.clear();
283  m_module_ports.clear();
284  m_module_port_by_net.clear();
285  for (const auto& verilog_module : m_modules)
286  {
287  for (const auto& instance : verilog_module->m_instances)
288  {
289  if (!instance->m_is_module)
290  {
291  instance->m_expanded_port_assignments.clear();
292  }
293  }
294  }
295 
296  // buffer gate types
297  m_gate_types = gate_library->get_gate_types();
298  m_gnd_gate_types = gate_library->get_gnd_gate_types();
299  m_vcc_gate_types = gate_library->get_vcc_gate_types();
300 
301  // create const 0 and const 1 net, will be removed if unused
302  m_zero_net = m_netlist->create_net("'0'");
303  if (m_zero_net == nullptr)
304  {
305  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create zero net");
306  }
307  m_net_by_name[m_zero_net->get_name()] = m_zero_net;
308 
309  m_one_net = m_netlist->create_net("'1'");
310  if (m_one_net == nullptr)
311  {
312  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': failed to create one net");
313  }
314  m_net_by_name[m_one_net->get_name()] = m_one_net;
315 
316  // a module marked (* top = 1 *), as Yosys does, is the top module; otherwise it is the one module nobody instantiates
317  std::vector<std::string> marked_top_modules;
318  for (const auto& [name, module] : m_modules_by_name)
319  {
320  for (const VerilogDataEntry& attribute : module->m_attributes)
321  {
322  if (attribute.m_name == "top" && utils::trim(attribute.m_value) == "1")
323  {
324  marked_top_modules.push_back(name);
325  break;
326  }
327  }
328  }
329  if (marked_top_modules.size() > 1)
330  {
331  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': several modules carry the top attribute: "
332  + utils::join(", ", marked_top_modules));
333  }
334 
335  std::map<std::string, u32> module_name_to_refereneces;
336  for (const auto& [_name, module] : m_modules_by_name)
337  {
338  for (const auto& instance : module->m_instances)
339  {
340  if (const auto it = m_modules_by_name.find(instance->m_type); it != m_modules_by_name.end())
341  {
342  module_name_to_refereneces[it->first]++;
343  }
344  }
345  }
346 
347  std::vector<std::string> top_module_candidates = marked_top_modules;
348  if (top_module_candidates.empty())
349  {
350  for (const auto& [name, module] : m_modules_by_name)
351  {
352  if (module_name_to_refereneces.find(name) == module_name_to_refereneces.end())
353  {
354  top_module_candidates.push_back(name);
355  }
356  }
357  }
358 
359  if (top_module_candidates.empty())
360  {
361  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': unable to find any top module candidates");
362  }
363 
364  if (top_module_candidates.size() > 1)
365  {
366  return ERR("could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name()
367  + "': found multiple modules as candidates for the top module, none of them marked (* top = 1 *): " + utils::join(", ", top_module_candidates));
368  }
369 
370  // construct the netlist with the the top module
371  VerilogModule* top_module = m_modules_by_name.at(top_module_candidates.front());
372 
373  if (const auto res = construct_netlist(top_module); res.is_error())
374  {
375  return ERR_APPEND(res.get_error(), "could not instantiate Verilog netlist '" + m_path.string() + "' with gate library '" + gate_library->get_name() + "': unable to construct netlist");
376  }
377 
378  // delete unused nets
379  std::queue<Net*> nets_to_be_deleted;
380 
381  for (auto net : m_netlist->get_nets())
382  {
383  const u32 num_of_sources = net->get_num_of_sources();
384  const u32 num_of_destinations = net->get_num_of_destinations();
385  const bool no_source = num_of_sources == 0 && !(net->is_global_input_net() && num_of_destinations != 0);
386  const bool no_destination = num_of_destinations == 0 && !(net->is_global_output_net() && num_of_sources != 0);
387  if (no_source && no_destination)
388  {
389  nets_to_be_deleted.push(net);
390  }
391  }
392 
393  while (!nets_to_be_deleted.empty())
394  {
395  Net* net = nets_to_be_deleted.front();
396  nets_to_be_deleted.pop();
397  m_netlist->delete_net(net);
398  }
399 
400  m_netlist->load_gate_locations_from_data();
401 
402  return OK(std::move(result));
403  }
404 
405  // ###########################################################################
406  // ########### Parse HDL into Intermediate Format ##########
407  // ###########################################################################
408 
409  void VerilogParser::tokenize()
410  {
411  const std::string delimiters = "`,()[]{}\\#*: ;=./";
412  std::string current_token;
413  u32 line_number = 0;
414 
415  std::string line;
416  char prev_char = 0;
417  bool in_string = false;
418  bool escaped = false;
419  bool in_comment = false;
420 
421  std::vector<Token<std::string>> parsed_tokens;
422  while (std::getline(m_fs, line))
423  {
424  line_number++;
425  // this->remove_comments(line, multi_line_comment);
426 
427  for (char c : line)
428  {
429  // deal with comments
430  if (in_comment)
431  {
432  if (c == '/' && prev_char == '*')
433  {
434  in_comment = false;
435  }
436 
437  prev_char = c;
438  continue;
439  }
440 
441  // deal with escaping and strings
442  if (!in_string && c == '\\')
443  {
444  escaped = true;
445  continue;
446  }
447  else if (escaped && std::isspace(c))
448  {
449  escaped = false;
450  continue;
451  }
452  else if (!escaped && c == '"')
453  {
454  in_string = !in_string;
455  }
456 
457  if (!in_comment && ((!std::isspace(c) && delimiters.find(c) == std::string::npos) || escaped || in_string))
458  {
459  current_token += c;
460  }
461  else
462  {
463  // deal with floats
464  if (!current_token.empty())
465  {
466  if (parsed_tokens.size() > 1 && utils::is_digits(parsed_tokens.at(parsed_tokens.size() - 2).string) && parsed_tokens.at(parsed_tokens.size() - 1) == "."
467  && utils::is_digits(current_token))
468  {
469  parsed_tokens.pop_back();
470  parsed_tokens.back() += "." + current_token;
471  }
472  else
473  {
474  parsed_tokens.emplace_back(line_number, current_token);
475  }
476  current_token.clear();
477  }
478 
479  if (!parsed_tokens.empty())
480  {
481  // deal with multi-character tokens
482  if (c == '(' && parsed_tokens.back() == "#")
483  {
484  parsed_tokens.back() = "#(";
485  continue;
486  }
487  else if (c == '*' && parsed_tokens.back() == "(")
488  {
489  parsed_tokens.back() = "(*";
490  continue;
491  }
492  else if (c == ')' && parsed_tokens.back() == "*")
493  {
494  parsed_tokens.back() = "*)";
495  continue;
496  }
497  // start a comment
498  else if (c == '/' && parsed_tokens.back() == "/")
499  {
500  parsed_tokens.pop_back();
501  break;
502  }
503  else if (c == '*' && parsed_tokens.back() == "/")
504  {
505  in_comment = true;
506  parsed_tokens.pop_back();
507  continue;
508  }
509  }
510 
511  if (!std::isspace(c))
512  {
513  parsed_tokens.emplace_back(line_number, std::string(1, c));
514  }
515  }
516  }
517  if (!current_token.empty())
518  {
519  parsed_tokens.emplace_back(line_number, current_token);
520  current_token.clear();
521  }
522  }
523 
524  m_token_stream = TokenStream(parsed_tokens, {"(", "["}, {")", "]"});
525  }
526 
527  Result<std::monostate> VerilogParser::parse_tokens()
528  {
529  std::vector<VerilogDataEntry> attributes;
530  u32 line_number;
531 
532  while (m_token_stream.remaining() > 0)
533  {
534  if (m_token_stream.peek() == "(*")
535  {
536  parse_attribute(attributes);
537  }
538  else if (m_token_stream.peek() == "`")
539  {
540  m_token_stream.consume_current_line();
541  log_warning("verilog_parser", "could not parse compiler directives.");
542  }
543  else
544  {
545  line_number = m_token_stream.peek().number;
546  if (auto res = parse_module(attributes); res.is_error())
547  {
548  return ERR_APPEND(res.get_error(), "could not parse tokens: unable to parse module (line " + std::to_string(line_number) + ")");
549  }
550  }
551  }
552 
553  return OK({});
554  }
555 
556  Result<std::monostate> VerilogParser::parse_module(std::vector<VerilogDataEntry>& attributes)
557  {
558  std::set<std::string> port_names;
559  std::vector<VerilogDataEntry> internal_attributes;
560 
561  m_token_stream.consume("module", true);
562  const u32 line_number = m_token_stream.peek().number;
563  const std::string module_name = m_token_stream.consume();
564 
565  // verify entity name
566  if (const auto it = m_modules_by_name.find(module_name); it != m_modules_by_name.end())
567  {
568  return ERR("could not parse module '" + module_name + "' (line " + std::to_string(line_number) + "): a module with the same name already exists (line "
569  + std::to_string(it->second->m_line_number) + ")");
570  }
571 
572  auto verilog_module = std::make_unique<VerilogModule>();
573  VerilogModule* verilog_module_raw = verilog_module.get();
574  verilog_module_raw->m_line_number = line_number;
575  verilog_module_raw->m_name = module_name;
576 
577  // parse parameter list
578  if (m_token_stream.consume("#("))
579  {
580  // TODO add support for parameter parsing
581  m_token_stream.consume_until(")");
582  m_token_stream.consume(")", true);
583  log_warning("verilog_parser", "could not parse parameter list provided for module '{}'.", module_name);
584  }
585 
586  // parse port (declaration) list
587  m_token_stream.consume("(", true);
588  Token<std::string> next_token = m_token_stream.peek();
589  if (next_token == "input" || next_token == "output" || next_token == "inout")
590  {
591  if (auto res = parse_port_declaration_list(verilog_module_raw); res.is_error())
592  {
593  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse port declaration list (line " + std::to_string(line_number) + ")");
594  }
595  }
596  else
597  {
598  if (auto res = parse_port_list(verilog_module_raw); res.is_error())
599  {
600  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "' (line " + std::to_string(line_number) + "): unable to parse port list");
601  }
602  }
603 
604  m_token_stream.consume(";", true);
605 
606  next_token = m_token_stream.peek();
607  while (next_token != "endmodule")
608  {
609  if (next_token == "input" || next_token == "output" || next_token == "inout")
610  {
611  if (auto res = parse_port_definition(verilog_module_raw, internal_attributes); res.is_error())
612  {
613  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse port definition (line " + std::to_string(line_number) + ")");
614  }
615  }
616  else if (next_token == "wire" || next_token == "tri")
617  {
618  if (auto res = parse_signal_definition(verilog_module_raw, internal_attributes); res.is_error())
619  {
620  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse signal definition (line " + std::to_string(line_number) + ")");
621  }
622  }
623  else if (next_token == "parameter")
624  {
625  // TODO add support for parameter parsing
626  m_token_stream.consume_until(";");
627  m_token_stream.consume(";", true);
628  log_warning("verilog_parser", "could not parse parameter provided for module '{}'.", module_name);
629  }
630  else if (next_token == "assign")
631  {
632  if (auto res = parse_assignment(verilog_module_raw); res.is_error())
633  {
634  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse assignment (line " + std::to_string(line_number) + ")");
635  }
636  }
637  else if (next_token == "defparam")
638  {
639  if (auto res = parse_defparam(verilog_module_raw); res.is_error())
640  {
641  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse defparam (line " + std::to_string(line_number) + ")");
642  }
643  }
644  else if (next_token == "(*")
645  {
646  parse_attribute(internal_attributes);
647  }
648  else
649  {
650  if (auto res = parse_instance(verilog_module_raw, internal_attributes); res.is_error())
651  {
652  return ERR_APPEND(res.get_error(), "could not parse module '" + module_name + "': unable to parse instance (line " + std::to_string(line_number) + ")");
653  }
654  }
655 
656  next_token = m_token_stream.peek();
657  }
658 
659  m_token_stream.consume("endmodule", true);
660 
661  // assign attributes to entity
662  if (!attributes.empty())
663  {
664  verilog_module->m_attributes.insert(verilog_module->m_attributes.end(), attributes.begin(), attributes.end());
665  attributes.clear();
666  }
667 
668  // add to collection of entities
669  m_modules.push_back(std::move(verilog_module));
670  m_modules_by_name[module_name] = verilog_module_raw;
671  m_last_module = module_name;
672 
673  return OK({});
674  }
675 
676  Result<std::monostate> VerilogParser::parse_port_list(VerilogModule* verilog_module)
677  {
678  TokenStream<std::string> ports_stream = m_token_stream.extract_until(")");
679  m_token_stream.consume(")", true);
680 
681  while (ports_stream.remaining() > 0)
682  {
683  Token<std::string> next_token = ports_stream.consume();
684  auto port = std::make_unique<VerilogPort>();
685 
686  if (next_token == ".")
687  {
688  port->m_identifier = ports_stream.consume().string;
689  ports_stream.consume("(", true);
690  TokenStream<std::string> expression_stream = ports_stream.extract_until(")");
691  ports_stream.consume(")", true);
692 
693  // a port expression is anything a right-hand side may be: a signal, a slice of one, or a concatenation
694  // of those, which Vivado writes for a port that is partly constant, e.g. .sum({<const0> ,\^sum [1:0]})
695  auto parts_res = parse_assignment_expression(std::move(expression_stream));
696  if (parts_res.is_error())
697  {
698  return ERR_APPEND(parts_res.get_error(), "could not parse port list: invalid expression of port '" + port->m_identifier + "' (line " + std::to_string(next_token.number) + ")");
699  }
700  port->m_expression_parts = parts_res.get();
701  }
702  else
703  {
704  port->m_identifier = next_token.string;
705  port->m_expression_parts = {identifier_t(next_token.string)};
706  }
707 
708  // the body declares direction and width on the signals the port stands for, so each of them has to find the port
709  for (const auto& part : port->m_expression_parts)
710  {
711  if (const identifier_t* identifier = std::get_if<identifier_t>(&part); identifier != nullptr)
712  {
713  verilog_module->m_ports_by_expression[*identifier] = port.get();
714  }
715  else if (const ranged_identifier_t* ranged = std::get_if<ranged_identifier_t>(&part); ranged != nullptr)
716  {
717  verilog_module->m_ports_by_expression[ranged->first] = port.get();
718  }
719  }
720 
721  verilog_module->m_ports_by_identifier[port->m_identifier] = port.get();
722  verilog_module->m_ports.push_back(std::move(port));
723 
724  ports_stream.consume(",", ports_stream.remaining() > 0);
725  }
726 
727  return OK({});
728  }
729 
730  Result<std::monostate> VerilogParser::parse_port_declaration_list(VerilogModule* verilog_module)
731  {
732  TokenStream<std::string> ports_stream = m_token_stream.extract_until(")");
733  m_token_stream.consume(")", true);
734 
735  while (ports_stream.remaining() > 0)
736  {
737  // direction
738  const Token<std::string> direction_token = ports_stream.consume();
739  PinDirection direction = enum_from_string<PinDirection>(direction_token.string, PinDirection::none);
741  {
742  return ERR("could not parse port declaration list: invalid direction '" + direction_token.string + "' (line " + std::to_string(direction_token.number) + ")");
743  }
744 
745  // ranges
746  std::vector<std::vector<u32>> ranges;
747  while (ports_stream.consume("["))
748  {
749  const std::vector<u32> range = parse_range(ports_stream);
750  ports_stream.consume("]", true);
751 
752  ranges.emplace_back(range);
753  }
754 
755  // port expressions
756  do
757  {
758  const Token<std::string> next_token = ports_stream.peek();
759  if (next_token == "input" || next_token == "output" || next_token == "inout")
760  {
761  break;
762  }
763  ports_stream.consume();
764 
765  auto port = std::make_unique<VerilogPort>();
766  const std::string& port_expression = next_token.string;
767  port->m_identifier = port_expression;
768  port->m_expression_parts = {identifier_t(port_expression)};
769  port->m_direction = direction;
770  if (!ranges.empty())
771  {
772  port->m_ranges = ranges;
773  }
774  verilog_module->m_ports_by_identifier[port_expression] = port.get();
775  verilog_module->m_ports_by_expression[port_expression] = port.get();
776  verilog_module->m_ports.push_back(std::move(port));
777 
778  // every port implicitly creates a wire, so create signal if not already declared explicitly
779  if (verilog_module->m_signals_by_name.find(port_expression) == verilog_module->m_signals_by_name.end())
780  {
781  auto signal = std::make_unique<VerilogSignal>();
782  signal->m_name = port_expression;
783  if (!ranges.empty())
784  {
785  signal->m_ranges = ranges;
786  }
787  verilog_module->m_signals_by_name[port_expression] = signal.get();
788  verilog_module->m_signals.push_back(std::move(signal));
789  }
790  } while (ports_stream.consume(",", ports_stream.remaining() > 0));
791  }
792 
793  return OK({});
794  }
795 
796  Result<std::monostate> VerilogParser::parse_port_definition(VerilogModule* verilog_module, std::vector<VerilogDataEntry>& attributes)
797  {
798  // port direction
799  const Token<std::string> direction_token = m_token_stream.consume();
800  PinDirection direction = enum_from_string<PinDirection>(direction_token.string, PinDirection::none);
802  {
803  return ERR("could not parse port definition: invalid direction '" + direction_token.string + "' (line " + std::to_string(direction_token.number) + ")");
804  }
805 
806  // ranges
807  std::vector<std::vector<u32>> ranges;
808  while (m_token_stream.consume("["))
809  {
810  const std::vector<u32> range = parse_range(m_token_stream);
811  m_token_stream.consume("]", true);
812 
813  ranges.emplace_back(range);
814  }
815 
816  // port expressions
817  do
818  {
819  Token<std::string> port_expression_token = m_token_stream.consume();
820  std::string port_expression = port_expression_token.string;
821 
822  VerilogPort* port;
823  if (const auto it = verilog_module->m_ports_by_expression.find(port_expression); it == verilog_module->m_ports_by_expression.end())
824  {
825  return ERR("could not parse port definition: a port with name '" + port_expression + "' does not exist for module '" + verilog_module->m_name + "' (line "
826  + std::to_string(direction_token.number) + ")");
827  }
828  else
829  {
830  port = it->second;
831  }
832 
833  port->m_direction = direction;
834  // the ranges of a concatenation's signals belong to those signals, the port's width follows from the expression
835  const bool stands_for_one_signal = port->m_expression_parts.size() == 1 && std::holds_alternative<identifier_t>(port->m_expression_parts.front());
836  if (!ranges.empty() && stands_for_one_signal)
837  {
838  port->m_ranges = ranges;
839  }
840 
841  // every port implicitly creates a wire, so create signal if not already declared explicitly
842  if (const auto signal_it = verilog_module->m_signals_by_name.find(port_expression); signal_it == verilog_module->m_signals_by_name.end())
843  {
844  auto signal = std::make_unique<VerilogSignal>();
845  signal->m_name = port_expression;
846  if (!ranges.empty())
847  {
848  signal->m_ranges = ranges;
849  }
850  signal->m_attributes.insert(signal->m_attributes.end(), attributes.begin(), attributes.end());
851  verilog_module->m_signals_by_name[port_expression] = signal.get();
852  verilog_module->m_signals.push_back(std::move(signal));
853  }
854  else
855  {
856  auto* signal = signal_it->second;
857  signal->m_attributes.insert(signal->m_attributes.end(), attributes.begin(), attributes.end());
858  }
859  } while (m_token_stream.consume(",", false));
860 
861  m_token_stream.consume(";", true);
862  attributes.clear();
863 
864  return OK({});
865  }
866 
867  Result<std::monostate> VerilogParser::parse_signal_definition(VerilogModule* verilog_module, std::vector<VerilogDataEntry>& attributes)
868  {
869  // consume "wire" or "tri"
870  u32 line_number = m_token_stream.consume().number;
871 
872  TokenStream<std::string> signal_stream = m_token_stream.extract_until(";");
873  m_token_stream.consume(";", true);
874 
875  // extract bounds
876  std::vector<std::vector<u32>> ranges;
877  while (signal_stream.consume("["))
878  {
879  const std::vector<u32> range = parse_range(signal_stream);
880  signal_stream.consume("]", true);
881 
882  ranges.emplace_back(range);
883  }
884 
885  // extract names
886  do
887  {
888  Token<std::string> signal_name = signal_stream.consume();
889  if (signal_stream.remaining() > 0 && signal_stream.peek() == "=")
890  {
891  VerilogAssignment assignment;
892  assignment.m_variable.push_back(signal_name);
893  signal_stream.consume("=", true);
894  if (auto res = parse_assignment_expression(signal_stream.extract_until(",")); res.is_error())
895  {
896  return ERR_APPEND(res.get_error(), "could not parse signal definition: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
897  }
898  else
899  {
900  assignment.m_assignment = res.get();
901  }
902  verilog_module->m_assignments.push_back(std::move(assignment));
903  }
904 
905  // create signal if not already implicitly declared otherwise
906  if (const auto signal_it = verilog_module->m_signals_by_name.find(signal_name.string); signal_it == verilog_module->m_signals_by_name.end())
907  {
908  auto signal = std::make_unique<VerilogSignal>();
909  signal->m_name = signal_name.string;
910  if (!ranges.empty())
911  {
912  signal->m_ranges = ranges;
913  }
914  signal->m_attributes.insert(signal->m_attributes.end(), attributes.begin(), attributes.end());
915  verilog_module->m_signals_by_name[signal_name.string] = signal.get();
916  verilog_module->m_signals.push_back(std::move(signal));
917  }
918  else
919  {
920  auto* signal = signal_it->second;
921  signal->m_attributes.insert(signal->m_attributes.end(), attributes.begin(), attributes.end());
922  }
923 
924  } while (signal_stream.consume(",", false));
925 
926  attributes.clear();
927 
928  return OK({});
929  }
930 
931  Result<std::monostate> VerilogParser::parse_assignment(VerilogModule* verilog_module)
932  {
933  m_token_stream.consume("assign", true);
934  u32 line_number = m_token_stream.peek().number;
935  VerilogAssignment assignment;
936 
937  if (auto res = parse_assignment_expression(m_token_stream.extract_until("=")); res.is_error())
938  {
939  return ERR_APPEND(res.get_error(), "could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
940  }
941  else
942  {
943  assignment.m_variable = res.get();
944  }
945  m_token_stream.consume("=", true);
946 
947  if (auto res = parse_assignment_expression(m_token_stream.extract_until(";")); res.is_error())
948  {
949  return ERR_APPEND(res.get_error(), "could not parse assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
950  }
951  else
952  {
953  assignment.m_assignment = res.get();
954  }
955 
956  // every assignment implicitly creates a wire, so create signal if not already declared explicitly
957  for (const auto& var : assignment.m_variable)
958  {
959  if (const auto* identifier = std::get_if<identifier_t>(&var); identifier != nullptr)
960  {
961  if (verilog_module->m_signals_by_name.find(*identifier) == verilog_module->m_signals_by_name.end())
962  {
963  auto signal = std::make_unique<VerilogSignal>();
964  signal->m_name = *identifier;
965  verilog_module->m_signals_by_name[*identifier] = signal.get();
966  verilog_module->m_signals.push_back(std::move(signal));
967  }
968  }
969  else if (const auto* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier != nullptr)
970  {
971  const auto& signal_name = std::get<0>(*ranged_identifier);
972  if (verilog_module->m_signals_by_name.find(signal_name) == verilog_module->m_signals_by_name.end())
973  {
974  auto signal = std::make_unique<VerilogSignal>();
975  signal->m_name = signal_name;
976  signal->m_ranges = std::get<1>(*ranged_identifier);
977  verilog_module->m_signals_by_name[signal_name] = signal.get();
978  verilog_module->m_signals.push_back(std::move(signal));
979  }
980  }
981  }
982  m_token_stream.consume(";", true);
983 
984  verilog_module->m_assignments.push_back(std::move(assignment));
985  return OK({});
986  }
987 
988  Result<std::monostate> VerilogParser::parse_defparam(VerilogModule* module)
989  {
990  m_token_stream.consume("defparam", true);
991  std::string instance_name = m_token_stream.consume().string;
992  m_token_stream.consume(".", true);
993 
994  if (const auto inst_it = module->m_instances_by_name.find(instance_name); inst_it != module->m_instances_by_name.end())
995  {
996  VerilogDataEntry param;
997  param.m_name = m_token_stream.consume().string;
998  m_token_stream.consume("=", true);
999 
1000  if (const auto res = parse_parameter_value(param.m_name, m_token_stream.consume()); res.is_ok())
1001  {
1002  const auto& [parsed_param, value_str] = res.get();
1003  param.m_value = value_str;
1004  param.m_parameter = parsed_param;
1005  inst_it->second->m_parameters.push_back(std::move(param));
1006  }
1007  else
1008  {
1009  log_warning("verilog_parser", "{}", res.get_error().get());
1010  }
1011  }
1012  else
1013  {
1014  m_token_stream.consume(";", true);
1015  return ERR("could not parse defparam: no instance with name '" + instance_name + "' exists within module '" + module->m_name + "'");
1016  }
1017 
1018  m_token_stream.consume(";", true);
1019  return OK({});
1020  }
1021 
1022  void VerilogParser::parse_attribute(std::vector<VerilogDataEntry>& attributes)
1023  {
1024  m_token_stream.consume("(*", true);
1025 
1026  // extract attributes
1027  do
1028  {
1029  VerilogDataEntry attribute;
1030  attribute.m_name = m_token_stream.consume().string;
1031 
1032  // attribute value specified?
1033  if (m_token_stream.consume("="))
1034  {
1035  attribute.m_value = m_token_stream.consume();
1036 
1037  // remove "
1038  if (attribute.m_value[0] == '\"' && attribute.m_value.back() == '\"')
1039  {
1040  attribute.m_value = attribute.m_value.substr(1, attribute.m_value.size() - 2);
1041  }
1042  }
1043 
1044  attributes.push_back(std::move(attribute));
1045 
1046  } while (m_token_stream.consume(",", false));
1047 
1048  m_token_stream.consume("*)", true);
1049  }
1050 
1051  Result<std::monostate> VerilogParser::parse_instance(VerilogModule* verilog_module, std::vector<VerilogDataEntry>& attributes)
1052  {
1053  auto instance = std::make_unique<VerilogInstance>();
1054  u32 line_number = m_token_stream.peek().number;
1055  instance->m_type = m_token_stream.consume().string;
1056 
1057  // parse generics map
1058  if (m_token_stream.consume("#("))
1059  {
1060  if (auto res = parse_parameter_assign(); res.is_error())
1061  {
1062  return ERR_APPEND(res.get_error(), "could not parse instance of type '" + instance->m_type + "': unable to parse parameter assignment (line " + std::to_string(line_number) + ")");
1063  }
1064  else
1065  {
1066  instance->m_parameters = res.get();
1067  }
1068  }
1069 
1070  // parse instance name
1071  instance->m_name = m_token_stream.consume().string;
1072 
1073  // parse port map
1074  if (auto res = parse_port_assign(instance.get()); res.is_error())
1075  {
1076  return ERR_APPEND(res.get_error(),
1077  "could not parse instance '" + instance->m_name + "' of type '" + instance->m_type + "': unable to parse port assignment (line " + std::to_string(line_number) + ")");
1078  }
1079 
1080  // assign attributes to instance
1081  instance->m_attributes = attributes;
1082  attributes.clear();
1083 
1084  verilog_module->m_instances_by_name[instance->m_name] = instance.get();
1085  verilog_module->m_instances.push_back(std::move(instance));
1086 
1087  return OK({});
1088  }
1089 
1090  Result<std::monostate> VerilogParser::parse_port_assign(VerilogInstance* instance)
1091  {
1092  u32 line_number = m_token_stream.peek().number;
1093  m_token_stream.consume("(", true);
1094  u32 line_end = m_token_stream.find_next(";");
1095  if (m_token_stream.peek() == ".")
1096  {
1097  do
1098  {
1099  m_token_stream.consume(".");
1100  VerilogPortAssignment port_assignment;
1101  port_assignment.m_port_name = m_token_stream.consume().string;
1102  m_token_stream.consume("(", true);
1103  if (auto res = parse_assignment_expression(m_token_stream.extract_until(")")); res.is_error())
1104  {
1105  return ERR_APPEND(res.get_error(), "could not parse port assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
1106  }
1107  else
1108  {
1109  port_assignment.m_assignment = res.get();
1110  }
1111  m_token_stream.consume(")", true);
1112  if (port_assignment.m_assignment.empty())
1113  {
1114  continue;
1115  }
1116  instance->m_port_assignments.push_back(std::move(port_assignment));
1117  } while (m_token_stream.consume(",", false));
1118  }
1119  else
1120  {
1121  do
1122  {
1123  VerilogPortAssignment port_assignment;
1124  if (auto res = parse_assignment_expression(m_token_stream.extract_until(",", line_end - 1)); res.is_error())
1125  {
1126  return ERR_APPEND(res.get_error(), "could not parse port assignment: unable to parse assignment expression (line " + std::to_string(line_number) + ")");
1127  }
1128  else
1129  {
1130  port_assignment.m_assignment = res.get();
1131  }
1132  if (port_assignment.m_assignment.empty())
1133  {
1134  continue;
1135  }
1136  instance->m_port_assignments.push_back(std::move(port_assignment));
1137  } while (m_token_stream.consume(",", false));
1138  }
1139 
1140  m_token_stream.consume(")", true);
1141  m_token_stream.consume(";", true);
1142 
1143  return OK({});
1144  }
1145 
1146  Result<std::vector<VerilogParser::VerilogDataEntry>> VerilogParser::parse_parameter_assign()
1147  {
1148  std::vector<VerilogDataEntry> generics;
1149 
1150  do
1151  {
1152  if (m_token_stream.consume(".", false))
1153  {
1154  const Token<std::string> lhs = m_token_stream.join_until("(", "");
1155  m_token_stream.consume("(", true);
1156  const Token<std::string> rhs = m_token_stream.join_until(")", "");
1157  m_token_stream.consume(")", true);
1158 
1159  if (const auto res = parse_parameter_value(lhs.string, rhs); res.is_ok())
1160  {
1161  const auto& [param, value_str] = res.get();
1162  VerilogDataEntry entry;
1163  entry.m_name = lhs.string;
1164  entry.m_value = value_str;
1165  entry.m_parameter = param;
1166  generics.push_back(std::move(entry));
1167  }
1168  else
1169  {
1170  log_warning("verilog_parser", "{}", res.get_error().get());
1171  }
1172  }
1173  } while (m_token_stream.consume(",", false));
1174 
1175  m_token_stream.consume(")", true);
1176 
1177  return OK(generics);
1178  }
1179 
1180  // ###########################################################################
1181  // ########### Assemble Netlist from Intermediate Format ##########
1182  // ###########################################################################
1183 
1184  Result<std::monostate> VerilogParser::construct_netlist(VerilogModule* top_module)
1185  {
1186  m_netlist->set_design_name(top_module->m_name);
1187  m_netlist->enable_automatic_net_checks(false);
1188 
1189  // preparations for alias: count the occurences of all names
1190  std::queue<VerilogModule*> q;
1191  q.push(top_module);
1192 
1193  while (!q.empty())
1194  {
1195  VerilogModule* module = q.front();
1196  q.pop();
1197 
1198  m_module_instantiation_count[module->m_name]++;
1199 
1200  // collect and count all net names in the netlist
1201  for (const auto& s : module->m_signals)
1202  {
1203  std::vector<std::string> expanded_names;
1204  expand_ranges_recursively(expanded_names, s->m_name, s->m_ranges, 0);
1205  for (const auto& net_name : expanded_names)
1206  {
1207  m_net_name_occurences[net_name]++;
1208  }
1209  }
1210 
1211  for (const auto& instance : module->m_instances)
1212  {
1213  m_instance_name_occurences[instance->m_name]++;
1214 
1215  // add type of instance to q if it is a module
1216  if (const auto it = m_modules_by_name.find(instance->m_type); it != m_modules_by_name.end())
1217  {
1218  q.push(it->second);
1219  }
1220  }
1221  }
1222 
1223  for (auto& [module_name, verilog_module] : m_modules_by_name)
1224  {
1225  // detect unused modules
1226  if (m_module_instantiation_count[module_name] == 0)
1227  {
1228  log_warning("verilog_parser", "module '{}' has been defined in the netlist but is not instantiated.", module_name);
1229  continue;
1230  }
1231 
1232  // expand gate pin assignments
1233  for (const auto& instance : verilog_module->m_instances)
1234  {
1235  if (const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1236  {
1237  if (!instance->m_port_assignments.empty())
1238  {
1239  // all port assignments by name
1240  if (instance->m_port_assignments.front().m_port_name.has_value())
1241  {
1242  // cache pin groups
1243  std::unordered_map<std::string, std::vector<std::string>> pin_groups;
1244  for (const auto pin_group : gate_type_it->second->get_pin_groups())
1245  {
1246  const auto pins = pin_group->get_pins();
1247  for (auto it = pins.rbegin(); it != pins.rend(); it++)
1248  {
1249  const auto* pin = *it;
1250  pin_groups[pin_group->get_name()].push_back(pin->get_name());
1251  }
1252  }
1253 
1254  for (const auto& port_assignment : instance->m_port_assignments)
1255  {
1256  std::vector<std::string> right_port = expand_assignment_expression(verilog_module, port_assignment.m_assignment);
1257  if (!right_port.empty())
1258  {
1259  std::vector<std::string> left_port;
1260 
1261  const auto& port_name = port_assignment.m_port_name.value();
1262  if (const auto group_it = pin_groups.find(port_name); group_it != pin_groups.end())
1263  {
1264  left_port = group_it->second;
1265  }
1266  else
1267  {
1268  left_port.push_back(port_name);
1269  }
1270 
1271  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1272 
1273  for (u32 i = 0; i < max_size; i++)
1274  {
1275  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1276  }
1277  }
1278  }
1279  }
1280  // all port assignments by order
1281  else
1282  {
1283  // cache pins
1284  std::vector<std::string> pins = gate_type_it->second->get_pin_names();
1285  auto pin_it = pins.begin();
1286 
1287  for (const auto& port_assignment : instance->m_port_assignments)
1288  {
1289  std::vector<std::string> right_port = expand_assignment_expression(verilog_module, port_assignment.m_assignment);
1290  if (!right_port.empty())
1291  {
1292  std::vector<std::string> left_port;
1293 
1294  for (u32 i = 0; i < right_port.size() && pin_it != pins.end(); i++)
1295  {
1296  left_port.push_back(*pin_it++);
1297  }
1298 
1299  u32 max_size = right_port.size() <= left_port.size() ? right_port.size() : left_port.size();
1300 
1301  for (u32 i = 0; i < max_size; i++)
1302  {
1303  instance->m_expanded_port_assignments.push_back(std::make_pair(left_port.at(i), right_port.at(i)));
1304  }
1305  }
1306  }
1307  }
1308  }
1309  }
1310  }
1311  }
1312 
1313  // for the top module, generate global i/o signals for all ports
1314  std::unordered_map<std::string, std::string> top_assignments;
1315  for (const auto& port : top_module->m_ports)
1316  {
1317  for (const auto& expanded_port_identifier : port->m_expanded_identifiers)
1318  {
1319  const auto signal_name = get_unique_alias("", expanded_port_identifier + "__GLOBAL_IO__", m_net_name_occurences);
1320  m_net_name_occurences[signal_name]++;
1321 
1322  Net* global_port_net = m_netlist->create_net(signal_name);
1323  if (global_port_net == nullptr)
1324  {
1325  return ERR("could not construct netlist: failed to create global I/O net '" + signal_name + "'");
1326  }
1327 
1328  m_net_by_name[signal_name] = global_port_net;
1329 
1330  // assign global port nets to ports of top module
1331  top_assignments[expanded_port_identifier] = signal_name;
1332 
1333  if (port->m_direction == PinDirection::input || port->m_direction == PinDirection::inout)
1334  {
1335  if (!global_port_net->mark_global_input_net())
1336  {
1337  return ERR("could not construct netlist: failed to mark global I/O net '" + signal_name + "' as global input");
1338  }
1339  }
1340 
1341  if (port->m_direction == PinDirection::output || port->m_direction == PinDirection::inout)
1342  {
1343  if (!global_port_net->mark_global_output_net())
1344  {
1345  return ERR("could not construct netlist: failed to mark global I/O net '" + signal_name + "' as global output");
1346  }
1347  }
1348  }
1349  }
1350 
1351  if (auto res = instantiate_module("top_module", top_module, nullptr, top_assignments); res.is_error())
1352  {
1353  return ERR_APPEND(res.get_error(), "could not construct netlist: unable to instantiate top module");
1354  }
1355 
1356  // merge nets without gates in between them
1357  std::unordered_map<std::string, std::string> merged_nets;
1358  std::unordered_map<std::string, std::vector<std::string>> master_to_slaves;
1359 
1360  for (auto& [master, slave] : m_nets_to_merge)
1361  {
1362  // check if master net has already been merged into other net
1363  while (true)
1364  {
1365  if (const auto master_it = merged_nets.find(master); master_it != merged_nets.end())
1366  {
1367  master = master_it->second;
1368  }
1369  else
1370  {
1371  break;
1372  }
1373  }
1374 
1375  // check if slave net has already been merged into other net
1376  while (true)
1377  {
1378  if (const auto slave_it = merged_nets.find(slave); slave_it != merged_nets.end())
1379  {
1380  slave = slave_it->second;
1381  }
1382  else
1383  {
1384  break;
1385  }
1386  }
1387 
1388  auto master_net = m_net_by_name.at(master);
1389  auto slave_net = m_net_by_name.at(slave);
1390 
1391  if (master_net == slave_net)
1392  {
1393  continue;
1394  }
1395  else if (slave_net == m_zero_net || slave_net == m_one_net)
1396  {
1397  auto* tmp_net = master_net;
1398  master_net = slave_net;
1399  slave_net = tmp_net;
1400 
1401  auto tmp_name = master;
1402  master = slave;
1403  slave = tmp_name;
1404  }
1405 
1406  // merge sources
1407  if (slave_net->is_global_input_net())
1408  {
1409  master_net->mark_global_input_net();
1410  }
1411 
1412  for (auto src : slave_net->get_sources())
1413  {
1414  Gate* src_gate = src->get_gate();
1415  GatePin* src_pin = src->get_pin();
1416 
1417  if (!slave_net->remove_source(src))
1418  {
1419  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()));
1420  }
1421 
1422  if (!master_net->is_a_source(src_gate, src_pin))
1423  {
1424  if (!master_net->add_source(src_gate, src_pin))
1425  {
1426  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()));
1427  }
1428  }
1429  }
1430 
1431  // merge destinations
1432  if (slave_net->is_global_output_net())
1433  {
1434  master_net->mark_global_output_net();
1435  }
1436 
1437  for (auto dst : slave_net->get_destinations())
1438  {
1439  Gate* dst_gate = dst->get_gate();
1440  GatePin* dst_pin = dst->get_pin();
1441 
1442  if (!slave_net->remove_destination(dst))
1443  {
1444  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()));
1445  }
1446 
1447  if (!master_net->is_a_destination(dst_gate, dst_pin))
1448  {
1449  if (!master_net->add_destination(dst_gate, dst_pin))
1450  {
1451  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()));
1452  }
1453  }
1454  }
1455 
1456  // merge generics and attributes
1457  for (const auto& [identifier, content] : slave_net->get_data_map())
1458  {
1459  if (!master_net->set_data(std::get<0>(identifier), std::get<1>(identifier), std::get<0>(content), std::get<1>(content)))
1460  {
1461  log_warning("verilog_parser",
1462  "unable to transfer data from slave net '{}' with ID {} to master net '{}' with ID {}.",
1463  slave_net->get_name(),
1464  slave_net->get_id(),
1465  master_net->get_name(),
1466  master_net->get_id());
1467  }
1468  }
1469 
1470  // update module ports
1471  if (const auto it = m_module_port_by_net.find(slave_net); it != m_module_port_by_net.end())
1472  {
1473  for (auto [module, index] : it->second)
1474  {
1475  std::get<1>(m_module_ports.at(module).at(index)) = master_net;
1476  }
1477  m_module_port_by_net[master_net].insert(m_module_port_by_net[master_net].end(), it->second.begin(), it->second.end());
1478  m_module_port_by_net.erase(it);
1479  }
1480 
1481  m_netlist->delete_net(slave_net);
1482  m_net_by_name.erase(slave);
1483  merged_nets[slave] = master;
1484  master_to_slaves[master].push_back(slave);
1485  }
1486 
1487  // annotate all surviving master nets with the net names that where merged into them
1488  for (auto& master_net : m_netlist->get_nets())
1489  {
1490  const auto master_name = master_net->get_name();
1491 
1492  if (const auto m2s_it = master_to_slaves.find(master_name); m2s_it != master_to_slaves.end())
1493  {
1494  std::vector<std::vector<std::string>> merged_slaves;
1495  auto current_slaves = m2s_it->second;
1496 
1497  while (!current_slaves.empty())
1498  {
1499  std::vector<std::string> next_slaves;
1500  for (const auto& s : current_slaves)
1501  {
1502  if (const auto m2s_inner_it = master_to_slaves.find(s); m2s_inner_it != master_to_slaves.end())
1503  {
1504  next_slaves.insert(next_slaves.end(), m2s_inner_it->second.begin(), m2s_inner_it->second.end());
1505  }
1506  }
1507 
1508  merged_slaves.push_back(current_slaves);
1509  current_slaves = next_slaves;
1510  next_slaves.clear();
1511  }
1512 
1513  // annotate all merged slave wire names as a JSON formatted list of list of strings
1514  // 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
1515  std::string merged_str = "";
1516  bool has_merged_nets = false;
1517  for (const auto& vec : merged_slaves)
1518  {
1519  if (!vec.empty())
1520  {
1521  has_merged_nets = true;
1522  }
1523  const auto s = utils::join(", ", vec, [](const auto e) { return '"' + e + '"'; });
1524  merged_str += "[" + s + "], ";
1525  }
1526  merged_str = merged_str.substr(0, merged_str.size() - 2);
1527 
1528  if (has_merged_nets)
1529  {
1530  master_net->set_data("parser_annotation", "merged_nets", "string", "[" + merged_str + "]");
1531  }
1532  }
1533  }
1534 
1535  // add global GND gate if required by any instance
1536  if (m_netlist->get_gnd_gates().empty())
1537  {
1538  if (m_zero_net->get_num_of_destinations() > 0)
1539  {
1540  GateType* gnd_type = m_gnd_gate_types.begin()->second;
1541  GatePin* output_pin = gnd_type->get_output_pins().front();
1542  Gate* gnd = m_netlist->create_gate(m_netlist->get_unique_gate_id(), gnd_type, "global_gnd");
1543 
1544  if (!m_netlist->mark_gnd_gate(gnd))
1545  {
1546  return ERR("failed to mark GND gate");
1547  }
1548 
1549  if (m_zero_net->add_source(gnd, output_pin) == nullptr)
1550  {
1551  return ERR("failed to add source to GND gate");
1552  }
1553  }
1554  else
1555  {
1556  m_netlist->delete_net(m_zero_net);
1557  m_zero_net = nullptr;
1558  }
1559  }
1560 
1561  // add global VCC gate if required by any instance
1562  if (m_netlist->get_vcc_gates().empty())
1563  {
1564  if (m_one_net->get_num_of_destinations() > 0)
1565  {
1566  GateType* vcc_type = m_vcc_gate_types.begin()->second;
1567  GatePin* output_pin = vcc_type->get_output_pins().front();
1568  Gate* vcc = m_netlist->create_gate(m_netlist->get_unique_gate_id(), vcc_type, "global_vcc");
1569 
1570  if (!m_netlist->mark_vcc_gate(vcc))
1571  {
1572  return ERR("failed to mark VCC gate");
1573  }
1574 
1575  if (m_one_net->add_source(vcc, output_pin) == nullptr)
1576  {
1577  return ERR("failed to add source to VCC gate");
1578  }
1579  }
1580  else
1581  {
1582  m_netlist->delete_net(m_one_net);
1583  m_one_net = nullptr;
1584  }
1585  }
1586 
1587  // update module nets, internal nets, input nets, and output nets
1588  for (Module* module : m_netlist->get_modules())
1589  {
1590  module->update_nets();
1591  }
1592 
1593  // assign module pins
1594  for (const auto& [module, ports] : m_module_ports)
1595  {
1596  std::unordered_set<Net*> input_nets = module->get_input_nets();
1597  std::unordered_set<Net*> output_nets = module->get_output_nets();
1598 
1599  for (const auto& [port_name, port_net] : ports)
1600  {
1601  if (!module->is_input_net(port_net) && !module->is_output_net(port_net))
1602  {
1603  continue;
1604  }
1605 
1606  if (auto res = module->create_pin(port_name, port_net); res.is_error())
1607  {
1608  return ERR_APPEND(res.get_error(),
1609  "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())
1610  + " within module '" + module->get_name() + "' with ID " + std::to_string(module->get_id()));
1611  }
1612  }
1613  }
1614 
1615  m_netlist->enable_automatic_net_checks(true);
1616  return OK({});
1617  }
1618 
1619  Result<Module*> VerilogParser::instantiate_module(const std::string& instance_identifier,
1620  VerilogModule* verilog_module,
1621  Module* parent,
1622  const std::unordered_map<std::string, std::string>& parent_module_assignments)
1623  {
1624  std::unordered_map<std::string, std::string> signal_alias;
1625  std::unordered_map<std::string, std::string> instance_alias;
1626 
1627  // TODO check parent module assignments for port aliases
1628 
1629  const std::string parent_name = (parent == nullptr) ? "" : parent->get_name();
1630  instance_alias[instance_identifier] = get_unique_alias(parent_name, instance_identifier, m_instance_name_occurences);
1631 
1632  // create netlist module
1633  Module* module;
1634  if (parent == nullptr)
1635  {
1636  module = m_netlist->get_top_module();
1637  module->set_name(instance_alias.at(instance_identifier));
1638  }
1639  else
1640  {
1641  module = m_netlist->create_module(instance_alias.at(instance_identifier), parent);
1642  }
1643 
1644  std::string instance_type = verilog_module->m_name;
1645  if (module == nullptr)
1646  {
1647  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to create module");
1648  }
1649  module->set_type(instance_type);
1650 
1651  // assign entity-level attributes
1652  for (const VerilogDataEntry& attribute : verilog_module->m_attributes)
1653  {
1654  if (!module->set_data("attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1655  {
1656  log_warning("verilog_parser",
1657  "could not set attribute '{} = {}' of type '{}' for instance '{}' type '{}'.",
1658  attribute.m_name,
1659  attribute.m_value,
1660  attribute.m_type,
1661  instance_identifier,
1662  instance_type);
1663  }
1664  }
1665 
1666  // assign module port names
1667  for (const auto& port : verilog_module->m_ports)
1668  {
1669  for (const auto& expanded_port_identifier : port->m_expanded_identifiers)
1670  {
1671  if (const auto it = parent_module_assignments.find(expanded_port_identifier); it != parent_module_assignments.end())
1672  {
1673  Net* port_net = m_net_by_name.at(it->second);
1674  m_module_ports[module].push_back(std::make_tuple(expanded_port_identifier, port_net));
1675  m_module_port_by_net[port_net].push_back(std::make_pair(module, m_module_ports[module].size() - 1));
1676  }
1677  }
1678  }
1679 
1680  // create internal signals
1681  for (const auto& signal : verilog_module->m_signals)
1682  {
1683  for (const auto& expanded_name : signal->m_expanded_names)
1684  {
1685  std::string unique_net_name = get_unique_alias(module->get_name(), expanded_name, m_net_name_occurences);
1686  if (unique_net_name != expanded_name)
1687  {
1688  m_net_name_occurences[unique_net_name]++;
1689  }
1690  signal_alias[expanded_name] = unique_net_name;
1691 
1692  // create new net for the signal
1693  Net* signal_net = m_netlist->create_net(signal_alias.at(expanded_name));
1694  if (signal_net == nullptr)
1695  {
1696  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to create net '" + expanded_name + "'");
1697  }
1698 
1699  m_net_by_name[signal_alias.at(expanded_name)] = signal_net;
1700 
1701  // assign signal attributes
1702  for (const VerilogDataEntry& attribute : signal->m_attributes)
1703  {
1704  if (!signal_net->set_data("attribute", attribute.m_name, "unknown", attribute.m_value))
1705  {
1706  log_warning("verilog_parser",
1707  "could not set attribute ({} = {}) for net '{}' of instance '{}' of type '{}'.",
1708  attribute.m_name,
1709  attribute.m_value,
1710  expanded_name,
1711  instance_identifier,
1712  instance_type);
1713  }
1714  }
1715  }
1716  }
1717 
1718  // schedule assigned nets for merging
1719  for (const auto& [left_expanded_signal, right_expanded_signal] : verilog_module->m_expanded_assignments)
1720  {
1721  std::string a = left_expanded_signal;
1722  std::string b = right_expanded_signal;
1723 
1724  if (const auto alias_it = signal_alias.find(a); alias_it != signal_alias.end())
1725  {
1726  a = alias_it->second;
1727  }
1728  else
1729  {
1730  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to find alias for net '" + a + "'");
1731  }
1732 
1733  if (const auto alias_it = signal_alias.find(b); alias_it != signal_alias.end())
1734  {
1735  b = alias_it->second;
1736  }
1737  else if (b == "'Z'" || b == "'X'")
1738  {
1739  continue;
1740  }
1741  else if (b != "'0'" && b != "'1'")
1742  {
1743  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to find alias for net '" + b + "'");
1744  }
1745 
1746  m_nets_to_merge.push_back(std::make_pair(a, b));
1747  }
1748 
1749  // schedule assigned port nets for merging
1750  for (const auto& [port_identifier, net_name] : parent_module_assignments)
1751  {
1752  std::string signal_name;
1753  if (const auto expr_it = verilog_module->m_expanded_port_identifiers_to_expressions.find(port_identifier); expr_it == verilog_module->m_expanded_port_identifiers_to_expressions.end())
1754  {
1755  signal_name = port_identifier;
1756  }
1757  else
1758  {
1759  signal_name = expr_it->second;
1760  }
1761 
1762  // TODO handle identifier != expression
1763  if (const auto alias_it = signal_alias.find(signal_name); alias_it != signal_alias.end())
1764  {
1765  const bool swap = net_name.find("__GLOBAL_IO__") == std::string::npos;
1766  m_nets_to_merge.push_back(swap ? std::make_pair(net_name, alias_it->second) : std::make_pair(alias_it->second, net_name));
1767  }
1768  else
1769  {
1770  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to find alias for net '" + signal_name + "'");
1771  }
1772  }
1773 
1774  // process instances i.e. gates or other entities
1775  for (const auto& instance : verilog_module->m_instances)
1776  {
1777  // will later hold either module or gate, so attributes can be assigned properly
1778  DataContainer* container = nullptr;
1779 
1780  // assign actual signal names to ports
1781  std::unordered_map<std::string, std::string> instance_assignments;
1782 
1783  // if the instance is another entity, recursively instantiate it
1784  if (auto module_it = m_modules_by_name.find(instance->m_type); module_it != m_modules_by_name.end())
1785  {
1786  // expand port assignments
1787  for (const auto& [port, assignment] : instance->m_expanded_port_assignments)
1788  {
1789  if (const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1790  {
1791  instance_assignments[port] = alias_it->second;
1792  }
1793  else if (assignment == "'0'" || assignment == "'1'")
1794  {
1795  instance_assignments[port] = assignment;
1796  }
1797  else if (assignment == "'Z'" || assignment == "'X'" || assignment.empty())
1798  {
1799  continue;
1800  }
1801  else
1802  {
1803  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': port assignment '" + port + " = " + assignment + "' is invalid");
1804  }
1805  }
1806 
1807  if (auto res = instantiate_module(instance->m_name, module_it->second, module, instance_assignments); res.is_error())
1808  {
1809  return ERR_APPEND(res.get_error(),
1810  "could not create instance '" + instance_identifier + "' of type '" + instance_type + "': unable to create instance '" + instance->m_name + "' of type '"
1811  + module_it->second->m_name + "'");
1812  }
1813  else
1814  {
1815  container = res.get();
1816  }
1817  }
1818  // otherwise it has to be an element from the gate library
1819  else if (const auto gate_type_it = m_gate_types.find(instance->m_type); gate_type_it != m_gate_types.end())
1820  {
1821  // create the new gate
1822  instance_alias[instance->m_name] = get_unique_alias(module->get_name(), instance->m_name, m_instance_name_occurences);
1823  Gate* new_gate = m_netlist->create_gate(gate_type_it->second, instance_alias.at(instance->m_name));
1824  if (new_gate == nullptr)
1825  {
1826  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to create gate '" + instance->m_name + "'");
1827  }
1828 
1829  if (!module->is_top_module())
1830  {
1831  module->assign_gate(new_gate);
1832  }
1833 
1834  container = new_gate;
1835 
1836  // if gate is of a GND or VCC gate type, mark it as such
1837  if (m_vcc_gate_types.find(instance->m_type) != m_vcc_gate_types.end() && !new_gate->mark_vcc_gate())
1838  {
1839  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to mark '" + instance->m_name + "' of type '" + instance->m_type
1840  + "' as GND gate");
1841  }
1842  if (m_gnd_gate_types.find(instance->m_type) != m_gnd_gate_types.end() && !new_gate->mark_gnd_gate())
1843  {
1844  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to mark '" + instance->m_name + "' of type '" + instance->m_type
1845  + "' as VCC gate");
1846  }
1847 
1848  // cache pin names
1849  std::unordered_map<std::string, GatePin*> pin_names_map;
1850  for (auto* pin : gate_type_it->second->get_pins())
1851  {
1852  pin_names_map[pin->get_name()] = pin;
1853  }
1854 
1855  // expand pin assignments
1856  for (const auto& [pin, assignment] : instance->m_expanded_port_assignments)
1857  {
1858  std::string signal;
1859 
1860  if (const auto alias_it = signal_alias.find(assignment); alias_it != signal_alias.end())
1861  {
1862  signal = alias_it->second;
1863  }
1864  else if (assignment == "'0'" || assignment == "'1'")
1865  {
1866  signal = assignment;
1867  }
1868  else if (assignment == "'Z'" || assignment == "'X'")
1869  {
1870  continue;
1871  }
1872  else
1873  {
1874  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to assign '" + assignment + "' to pin '" + pin + "' of gate '"
1875  + instance->m_name + "' of type '" + instance->m_type + "' as the assignment is invalid");
1876  }
1877 
1878  // get the respective net for the assignment
1879  if (const auto net_it = m_net_by_name.find(signal); net_it == m_net_by_name.end())
1880  {
1881  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to assign signal'" + signal + "' to pin '" + pin
1882  + "' as the signal has not been declared");
1883  }
1884  else
1885  {
1886  Net* current_net = net_it->second;
1887 
1888  // add net src/dst by pin types
1889  bool is_input = false;
1890  bool is_output = false;
1891 
1892  if (const auto it = pin_names_map.find(pin); it != pin_names_map.end())
1893  {
1894  PinDirection direction = it->second->get_direction();
1896  {
1897  is_input = true;
1898  }
1899 
1901  {
1902  is_output = true;
1903  }
1904  }
1905 
1906  if (!is_input && !is_output)
1907  {
1908  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to assign net '" + signal + "' to pin '" + pin
1909  + "' as it is not a pin of gate '" + new_gate->get_name() + "' of type '" + new_gate->get_type()->get_name() + "'");
1910  }
1911 
1912  if (is_output && !current_net->add_source(new_gate, pin))
1913  {
1914  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to add net '" + signal + "' as a source to gate '"
1915  + new_gate->get_name() + "' via pin '" + pin + "'");
1916  }
1917 
1918  if (is_input && !current_net->add_destination(new_gate, pin))
1919  {
1920  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to add net '" + signal + "' as a destination to gate '"
1921  + new_gate->get_name() + "' via pin '" + pin + "'");
1922  }
1923  }
1924  }
1925  }
1926  else
1927  {
1928  return ERR("could not create instance '" + instance_identifier + "' of type '" + instance_type + "': failed to find gate type '" + instance->m_type + "' in gate library '"
1929  + m_netlist->get_gate_library()->get_name() + "'");
1930  }
1931 
1932  // assign instance attributes
1933  for (const auto& attribute : instance->m_attributes)
1934  {
1935  if (!container->set_data("attribute", attribute.m_name, attribute.m_type, attribute.m_value))
1936  {
1937  log_warning("verilog_parser",
1938  "could not set attribute '{} = {}' of type '{}' for instance '{}' of type '{}' within instance '{}' of type '{}'.",
1939  attribute.m_name,
1940  attribute.m_value,
1941  attribute.m_type,
1942  instance->m_name,
1943  instance->m_type,
1944  instance_identifier,
1945  instance_type);
1946  }
1947  }
1948 
1949  // For gate instances, prefer the gate type's own parameter declaration over
1950  // the parser-inferred one — this is the only way Enum parameters can be set.
1951  const GateType* gt = nullptr;
1952  if (const Gate* g = dynamic_cast<const Gate*>(container))
1953  {
1954  gt = g->get_type();
1955  }
1956 
1957  for (const auto& parameter : instance->m_parameters)
1958  {
1959  if (!parameter.m_parameter.has_value())
1960  {
1961  log_warning(
1962  "verilog_parser", "could not set generic '{}' for instance '{}' of type '{}': no typed parameter declaration available.", parameter.m_name, instance->m_name, instance->m_type);
1963  continue;
1964  }
1965  Parameter effective_param = parameter.m_parameter.value();
1966  if (gt != nullptr)
1967  {
1968  if (auto decl = gt->get_parameter(parameter.m_name); decl.is_ok())
1969  {
1970  effective_param = decl.get();
1971  }
1972  }
1973  if (auto res = container->set_parameter(effective_param, parameter.m_value); res.is_error())
1974  {
1975  log_warning("verilog_parser",
1976  "could not set parameter '{} = {}' for instance '{}' of type '{}' within instance '{}' of type '{}': {}",
1977  parameter.m_name,
1978  parameter.m_value,
1979  instance->m_name,
1980  instance->m_type,
1981  instance_identifier,
1982  instance_type,
1983  res.get_error().get());
1984  }
1985  }
1986  }
1987 
1988  return OK(module);
1989  }
1990 
1991  // ###########################################################################
1992  // ################### Helper Functions ####################
1993  // ###########################################################################
1994 
1995  namespace
1996  {
1997  static const std::map<char, BooleanFunction::Value> bin_map = {{'0', BooleanFunction::Value::ZERO},
1998  {'1', BooleanFunction::Value::ONE},
1999  {'X', BooleanFunction::Value::X},
2000  {'Z', BooleanFunction::Value::Z}};
2001 
2002  static const std::map<char, std::vector<BooleanFunction::Value>> oct_map = {{'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2003  {'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2004  {'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2005  {'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2006  {'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2007  {'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2008  {'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2009  {'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2010  {'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2011  {'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2012 
2013  static const std::map<char, std::vector<BooleanFunction::Value>> hex_map = {
2014  {'0', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2015  {'1', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2016  {'2', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2017  {'3', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO}},
2018  {'4', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2019  {'5', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2020  {'6', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2021  {'7', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO}},
2022  {'8', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2023  {'9', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2024  {'A', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2025  {'B', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE}},
2026  {'C', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2027  {'D', {BooleanFunction::Value::ONE, BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2028  {'E', {BooleanFunction::Value::ZERO, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2029  {'F', {BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE, BooleanFunction::Value::ONE}},
2030  {'X', {BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X, BooleanFunction::Value::X}},
2031  {'Z', {BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z, BooleanFunction::Value::Z}}};
2032  } // namespace
2033 
2034  // generate a unique name for a gate/module instance
2035  std::string VerilogParser::get_unique_alias(const std::string& parent_name, const std::string& name, const std::unordered_map<std::string, u32>& name_occurences) const
2036  {
2037  std::string unique_alias = name;
2038 
2039  if (!parent_name.empty())
2040  {
2041  // if there is no other instance with that name, we omit the name prefix
2042 
2043  auto instance_name_it = name_occurences.find(name);
2044 
2045  int cnt = 0;
2046 
2047  // it is OK if base name (first loop cnt=0) is already in name_occurences once
2048  // unique_alias (cnt > 0) must not be in name_occurences
2049  while (instance_name_it != name_occurences.end() && (cnt || instance_name_it->second > 1))
2050  {
2051  std::string extension;
2052  if (cnt++)
2053  {
2054  extension = "_u" + std::to_string(cnt);
2055  }
2056  unique_alias = parent_name + instance_name_seperator + unique_alias + extension;
2057  instance_name_it = name_occurences.find(unique_alias);
2058  }
2059  }
2060 
2061  return unique_alias;
2062  }
2063 
2064  std::vector<u32> VerilogParser::parse_range(TokenStream<std::string>& stream) const
2065  {
2066  if (stream.remaining() == 1)
2067  {
2068  return {(u32)std::stoi(stream.consume().string)};
2069  }
2070 
2071  // MSB to LSB
2072  const int end = std::stoi(stream.consume().string);
2073  stream.consume(":", true);
2074  const int start = std::stoi(stream.consume().string);
2075 
2076  const int direction = (start <= end) ? 1 : -1;
2077 
2078  std::vector<u32> result;
2079  for (int i = start; i != end + direction; i += direction)
2080  {
2081  result.push_back((u32)i);
2082  }
2083  return result;
2084  }
2085 
2086  void VerilogParser::expand_ranges_recursively(std::vector<std::string>& expanded_names, const std::string& current_name, const std::vector<std::vector<u32>>& ranges, u32 dimension) const
2087  {
2088  // expand signal recursively
2089  if (ranges.size() > dimension)
2090  {
2091  for (const u32 index : ranges[dimension])
2092  {
2093  expand_ranges_recursively(expanded_names, current_name + "(" + std::to_string(index) + ")", ranges, dimension + 1);
2094  }
2095  }
2096  else
2097  {
2098  // last dimension
2099  expanded_names.push_back(current_name);
2100  }
2101  }
2102 
2103  std::vector<std::string> VerilogParser::expand_ranges(const std::string& name, const std::vector<std::vector<u32>>& ranges) const
2104  {
2105  std::vector<std::string> res;
2106 
2107  expand_ranges_recursively(res, name, ranges, 0);
2108 
2109  return res;
2110  }
2111 
2112  Result<std::vector<BooleanFunction::Value>> VerilogParser::get_binary_vector(std::string value) const
2113  {
2114  value = utils::to_upper(utils::replace(value, std::string("_"), std::string("")));
2115 
2116  i32 len = -1;
2117  std::string prefix;
2118  std::string number;
2119  std::vector<BooleanFunction::Value> result;
2120 
2121  // base specified?
2122  if (value.find('\'') == std::string::npos)
2123  {
2124  prefix = "D";
2125  number = value;
2126  }
2127  else
2128  {
2129  if (value.at(0) != '\'')
2130  {
2131  len = std::stoi(value.substr(0, value.find('\'')));
2132  }
2133  prefix = value.substr(value.find('\'') + 1, 1);
2134  number = value.substr(value.find('\'') + 2);
2135  }
2136 
2137  // select base
2138  switch (prefix.at(0))
2139  {
2140  case 'B': {
2141  for (auto it = number.rbegin(); it != number.rend(); it++)
2142  {
2143  const char c = *it;
2144  if (c == '0' || c == '1' || c == 'Z' || c == 'X')
2145  {
2146  result.push_back(bin_map.at(c));
2147  }
2148  else
2149  {
2150  return ERR("could not convert string to binary vector: invalid character within binary number literal '" + value + "'");
2151  }
2152  }
2153  break;
2154  }
2155 
2156  case 'O':
2157  for (auto it = number.rbegin(); it != number.rend(); it++)
2158  {
2159  const char c = *it;
2160  if ((c >= '0' && c <= '7') || c == 'X' || c == 'Z')
2161  {
2162  const auto& bits = oct_map.at(c);
2163  result.insert(result.end(), bits.begin(), bits.end());
2164  }
2165  else
2166  {
2167  return ERR("could not convert string to binary vector: invalid character within octal number literal '" + value + "'");
2168  }
2169  }
2170  break;
2171 
2172  case 'D': {
2173  u64 tmp_val = 0;
2174 
2175  for (const char c : number)
2176  {
2177  if ((c >= '0' && c <= '9'))
2178  {
2179  tmp_val = (tmp_val * 10) + (c - '0');
2180  }
2181  else
2182  {
2183  return ERR("could not convert string to binary vector: invalid character within decimal number literal '" + value + "'");
2184  }
2185  }
2186 
2187  do
2188  {
2189  result.push_back(((tmp_val & 1) == 1) ? BooleanFunction::Value::ONE : BooleanFunction::Value::ZERO);
2190  tmp_val >>= 1;
2191  } while (tmp_val != 0);
2192  break;
2193  }
2194 
2195  case 'H': {
2196  for (auto it = number.rbegin(); it != number.rend(); it++)
2197  {
2198  const char c = *it;
2199  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || c == 'X' || c == 'Z')
2200  {
2201  const auto& bits = hex_map.at(c);
2202  result.insert(result.end(), bits.begin(), bits.end());
2203  }
2204  else
2205  {
2206  return ERR("could not convert string to binary vector: invalid character within hexadecimal number literal '" + value + "'");
2207  }
2208  }
2209  break;
2210  }
2211 
2212  default: {
2213  return ERR("could not convert string to binary vector: invalid base '" + prefix + "' within number literal '" + value + "'");
2214  }
2215  }
2216 
2217  if (len != -1)
2218  {
2219  i32 result_size = result.size();
2220 
2221  if (len > result_size)
2222  {
2223  // fill with '0'
2224  for (i32 i = 0; i < (len - result_size); i++)
2225  {
2226  result.push_back(BooleanFunction::Value::ZERO);
2227  }
2228  }
2229  else
2230  {
2231  // drop trailing bits
2232  for (i32 i = 0; i < (result_size - len); i++)
2233  {
2234  result.pop_back();
2235  }
2236  }
2237  }
2238 
2239  return OK(result);
2240  }
2241 
2242  Result<std::string> VerilogParser::get_hex_from_literal(const Token<std::string>& value_token) const
2243  {
2244  const u32 line_number = value_token.number;
2245  const std::string value = utils::to_upper(utils::replace(value_token.string, std::string("_"), std::string("")));
2246 
2247  i32 len = -1;
2248  std::string prefix;
2249  std::string number;
2250  u32 base;
2251 
2252  // base specified?
2253  if (value.find('\'') == std::string::npos)
2254  {
2255  prefix = "D";
2256  number = value;
2257  }
2258  else
2259  {
2260  if (value.at(0) != '\'')
2261  {
2262  len = std::stoi(value.substr(0, value.find('\'')));
2263  }
2264  prefix = value.substr(value.find('\'') + 1, 1);
2265  number = value.substr(value.find('\'') + 2);
2266  }
2267 
2268  // select base
2269  switch (prefix.at(0))
2270  {
2271  case 'B': {
2272  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '1'); }))
2273  {
2274  return ERR("could not convert token to hexadecimal string: invalid character within binary number literal '" + value + "' (line " + std::to_string(line_number) + ")");
2275  }
2276 
2277  base = 2;
2278  break;
2279  }
2280 
2281  case 'O': {
2282  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '7'); }))
2283  {
2284  return ERR("could not convert token to hexadecimal string: invalid character within ocatl number literal '" + value + "' (line " + std::to_string(line_number) + ")");
2285  }
2286 
2287  base = 8;
2288  break;
2289  }
2290 
2291  case 'D': {
2292  if (!std::all_of(number.begin(), number.end(), [](const char& c) { return (c >= '0' && c <= '9'); }))
2293  {
2294  return ERR("could not convert token to hexadecimal string: invalid character within decimal number literal '" + value + "' (line " + std::to_string(line_number) + ")");
2295  }
2296 
2297  base = 10;
2298  break;
2299  }
2300 
2301  case 'H': {
2302  std::string res;
2303 
2304  for (const char c : number)
2305  {
2306  if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))
2307  {
2308  res += c;
2309  }
2310  else
2311  {
2312  return ERR("could not convert token to hexadecimal string: invalid character within hexadecimal number literal '" + value + "' (line " + std::to_string(line_number) + ")");
2313  }
2314  }
2315 
2316  return OK(res);
2317  }
2318 
2319  default: {
2320  return ERR("could not convert token to hexadecimal string: invalid base '" + prefix + "' within number literal '" + value + "' (line " + std::to_string(line_number) + ")");
2321  }
2322  }
2323 
2324  std::stringstream ss;
2325  if (len != -1)
2326  {
2327  // fill with '0'
2328  ss << std::uppercase << std::setfill('0') << std::setw((len + 3) / 4) << std::hex << stoull(number, 0, base);
2329  }
2330  else
2331  {
2332  ss << std::uppercase << std::hex << stoull(number, 0, base);
2333  }
2334  return OK(ss.str());
2335  }
2336 
2337  Result<std::pair<Parameter, std::string>> VerilogParser::parse_parameter_value(const std::string& name, const Token<std::string>& value_token) const
2338  {
2339  const std::string& raw = value_token.string;
2340  const u32 line_number = value_token.number;
2341  const std::string loc_str = " (line " + std::to_string(line_number) + ")";
2342 
2343  // integer (plain decimal, no Verilog base prefix)
2344  if (utils::is_integer(raw))
2345  {
2346  auto param_res = Parameter::Integer(name, "");
2347  if (param_res.is_error())
2348  {
2349  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2350  }
2351  return OK(std::make_pair(param_res.get(), raw));
2352  }
2353 
2354  // floating-point (double precision, full-consume)
2355  if (is_double_strict(raw))
2356  {
2357  auto param_res = Parameter::Float(name, "");
2358  if (param_res.is_error())
2359  {
2360  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2361  }
2362  return OK(std::make_pair(param_res.get(), raw));
2363  }
2364 
2365  // boolean: case-insensitive 'true' / 'false'
2366  {
2367  const std::string lower = utils::to_lower(raw);
2368  if (lower == "true" || lower == "false")
2369  {
2370  auto param_res = Parameter::Boolean(name, "");
2371  if (param_res.is_error())
2372  {
2373  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2374  }
2375  return OK(std::make_pair(param_res.get(), lower));
2376  }
2377  }
2378 
2379  // time literal: <number><unit> with unit in {min, fs, ps, ns, us, ms, s, h}
2380  // longest units listed first to avoid partial suffix matches
2381  {
2382  static const std::vector<std::string> time_units = {"min", "fs", "ps", "ns", "us", "ms", "s", "h"};
2383  for (const auto& unit : time_units)
2384  {
2385  if (raw.size() <= unit.size() || !utils::ends_with(raw, unit))
2386  {
2387  continue;
2388  }
2389  const std::string num_part = raw.substr(0, raw.size() - unit.size());
2390  if (!utils::is_integer(num_part) && !is_double_strict(num_part))
2391  {
2392  continue;
2393  }
2394  auto param_res = Parameter::Time(name, "");
2395  if (param_res.is_error())
2396  {
2397  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2398  }
2399  return OK(std::make_pair(param_res.get(), raw));
2400  }
2401  }
2402 
2403  // string literal: strip outer quotes, no escape processing
2404  if (raw.size() >= 2 && raw.front() == '"' && raw.back() == '"')
2405  {
2406  auto param_res = Parameter::String(name, "");
2407  if (param_res.is_error())
2408  {
2409  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2410  }
2411  return OK(std::make_pair(param_res.get(), raw.substr(1, raw.size() - 2)));
2412  }
2413 
2414  // bit/logic vector literal: [N]'[b|o|h|d][digits]
2415  if (!raw.empty() && (isdigit(static_cast<unsigned char>(raw[0])) || raw[0] == '\''))
2416  {
2417  const size_t tick_pos = raw.find('\'');
2418  if (tick_pos == std::string::npos)
2419  {
2420  return ERR("could not parse parameter value: no base prefix in literal '" + raw + "'" + loc_str);
2421  }
2422 
2423  // optional explicit width before the tick
2424  u16 explicit_width = 0;
2425  bool has_width = false;
2426  if (tick_pos > 0)
2427  {
2428  try
2429  {
2430  explicit_width = static_cast<u16>(std::stoul(raw.substr(0, tick_pos)));
2431  }
2432  catch (...)
2433  {
2434  return ERR("could not parse parameter value: invalid width in literal '" + raw + "'" + loc_str);
2435  }
2436  has_width = true;
2437  }
2438 
2439  if (tick_pos + 1 >= raw.size())
2440  {
2441  return ERR("could not parse parameter value: missing base char in literal '" + raw + "'" + loc_str);
2442  }
2443  const char base_upper = static_cast<char>(std::toupper(static_cast<unsigned char>(raw[tick_pos + 1])));
2444 
2445  // resolve all base properties in one place; bits_per_digit == 0 flags decimal (needs conversion)
2446  std::string numeric_set;
2447  std::string out_prefix;
2448  int bits_per_digit = 0;
2449  bool allow_state = true;
2450  switch (base_upper)
2451  {
2452  case 'B':
2453  numeric_set = "01";
2454  out_prefix = "0b";
2455  bits_per_digit = 1;
2456  break;
2457  case 'O':
2458  numeric_set = "01234567";
2459  out_prefix = "0o";
2460  bits_per_digit = 3;
2461  break;
2462  case 'H':
2463  numeric_set = "0123456789abcdef";
2464  out_prefix = "0x";
2465  bits_per_digit = 4;
2466  break;
2467  case 'D':
2468  numeric_set = "0123456789";
2469  out_prefix = "0x";
2470  bits_per_digit = 0;
2471  allow_state = false;
2472  break;
2473  default:
2474  return ERR("could not parse parameter value: unsupported base '" + std::string(1, base_upper) + "' in literal '" + raw + "'" + loc_str);
2475  }
2476 
2477  // single pass: strip underscores, map '?' to '-', validate, detect state chars
2478  std::string digits;
2479  digits.reserve(raw.size());
2480  bool has_state = false;
2481  for (size_t i = tick_pos + 2; i < raw.size(); ++i)
2482  {
2483  const char c = raw[i];
2484  if (c == '_')
2485  {
2486  continue;
2487  }
2488  const char mapped = (c == '?') ? '-' : c;
2489  const char l = (mapped == '-') ? '-' : static_cast<char>(std::tolower(static_cast<unsigned char>(mapped)));
2490  const bool is_num = numeric_set.find(l) != std::string::npos;
2491  const bool is_state = (l == 'x' || l == 'z' || l == '-');
2492  if (!is_num && (!allow_state || !is_state))
2493  {
2494  return ERR("could not parse parameter value: literal '" + raw + "' contains invalid digit '" + std::string(1, c) + "'" + loc_str);
2495  }
2496  if (is_state)
2497  {
2498  has_state = true;
2499  }
2500  digits += mapped;
2501  }
2502 
2503  if (digits.empty())
2504  {
2505  return ERR("could not parse parameter value: no digits in literal '" + raw + "'" + loc_str);
2506  }
2507 
2508  // helper: build the right Parameter type and return
2509  const auto make_param = [&](u16 size, const std::string& value) -> Result<std::pair<Parameter, std::string>> {
2510  if (has_state)
2511  {
2512  auto param_res = Parameter::LogicVector(name, size, "");
2513  if (param_res.is_error())
2514  {
2515  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2516  }
2517  return OK(std::make_pair(param_res.get(), value));
2518  }
2519  else
2520  {
2521  auto param_res = Parameter::BitVector(name, size, "");
2522  if (param_res.is_error())
2523  {
2524  return ERR_APPEND(param_res.get_error(), "could not parse parameter value '" + raw + "'" + loc_str);
2525  }
2526  return OK(std::make_pair(param_res.get(), value));
2527  }
2528  };
2529 
2530  // decimal needs a stoull to hex conversion; all other bases use digits directly
2531  if (bits_per_digit == 0)
2532  {
2533  u64 num = 0;
2534  try
2535  {
2536  num = std::stoull(digits);
2537  }
2538  catch (...)
2539  {
2540  return ERR("could not parse parameter value: decimal literal '" + raw + "' overflows" + loc_str);
2541  }
2542  std::stringstream ss;
2543  ss << std::hex << num;
2544  const std::string hex_digits = ss.str();
2545  const u16 size = has_width ? explicit_width : static_cast<u16>(hex_digits.size() * 4);
2546  return make_param(size, out_prefix + hex_digits);
2547  }
2548  const u16 size = (has_width && !has_state) ? explicit_width : static_cast<u16>(digits.size() * bits_per_digit);
2549  return make_param(size, out_prefix + digits);
2550  }
2551 
2552  return ERR("could not parse parameter value: failed to identify data type of '" + raw + "'" + loc_str);
2553  }
2554 
2555  Result<std::vector<VerilogParser::assignment_t>> VerilogParser::parse_assignment_expression(TokenStream<std::string>&& stream) const
2556  {
2557  std::vector<TokenStream<std::string>> parts;
2558 
2559  if (stream.size() == 0)
2560  {
2561  return OK({});
2562  }
2563 
2564  if (stream.peek() == "{")
2565  {
2566  stream.consume("{", true);
2567 
2568  TokenStream<std::string> assignment_list_str = stream.extract_until("}");
2569  stream.consume("}", true);
2570 
2571  do
2572  {
2573  parts.push_back(assignment_list_str.extract_until(","));
2574  } while (assignment_list_str.consume(",", false));
2575  }
2576  else
2577  {
2578  parts.push_back(stream);
2579  }
2580 
2581  std::vector<assignment_t> result;
2582  result.reserve(parts.size());
2583 
2584  for (auto it = parts.rbegin(); it != parts.rend(); it++)
2585  {
2586  TokenStream<std::string>& part_stream = *it;
2587 
2588  const Token<std::string> signal_name_token = part_stream.consume();
2589  std::string signal_name = signal_name_token.string;
2590 
2591  // (3) NUMBER
2592  if (isdigit(signal_name[0]) || signal_name[0] == '\'')
2593  {
2594  if (auto res = get_binary_vector(signal_name_token); res.is_error())
2595  {
2596  return ERR_APPEND(res.get_error(), "could not parse assignment expression: unable to convert token to binary vector");
2597  }
2598  else
2599  {
2600  result.push_back(std::move(res.get()));
2601  }
2602  }
2603  else
2604  {
2605  // any bounds specified?
2606  if (part_stream.consume("["))
2607  {
2608  // (4) NAME[INDEX1][INDEX2]...
2609  // (5) NAME[BEGIN_INDEX1:END_INDEX1][BEGIN_INDEX2:END_INDEX2]...
2610 
2611  std::vector<std::vector<u32>> ranges;
2612  do
2613  {
2614  TokenStream<std::string> range_str = part_stream.extract_until("]");
2615  ranges.emplace_back(parse_range(range_str));
2616  part_stream.consume("]", true);
2617  } while (part_stream.consume("[", false));
2618 
2619  result.push_back(ranged_identifier_t({std::move(signal_name), std::move(ranges)}));
2620  }
2621  else
2622  {
2623  // (1) NAME *single-dimensional*
2624  // (2) NAME *multi-dimensional*
2625  result.push_back(std::move(signal_name));
2626  }
2627  }
2628  }
2629 
2630  return OK(result);
2631  }
2632 
2633  std::vector<std::string> VerilogParser::expand_assignment_expression(VerilogModule* verilog_module, const std::vector<assignment_t>& vars) const
2634  {
2635  std::vector<std::string> result;
2636  for (const auto& var : vars)
2637  {
2638  if (const identifier_t* identifier = std::get_if<identifier_t>(&var); identifier != nullptr)
2639  {
2640  std::vector<std::vector<u32>> ranges;
2641 
2642  if (const auto signal_it = verilog_module->m_signals_by_name.find(*identifier); signal_it != verilog_module->m_signals_by_name.end())
2643  {
2644  ranges = signal_it->second->m_ranges;
2645  }
2646  else if (const auto port_it = verilog_module->m_ports_by_expression.find(*identifier); port_it != verilog_module->m_ports_by_expression.end())
2647  {
2648  ranges = port_it->second->m_ranges;
2649  }
2650 
2651  std::vector<std::string> expanded = expand_ranges(*identifier, ranges);
2652  result.insert(result.end(), expanded.begin(), expanded.end());
2653  }
2654  else if (const ranged_identifier_t* ranged_identifier = std::get_if<ranged_identifier_t>(&var); ranged_identifier != nullptr)
2655  {
2656  std::vector<std::string> expanded = expand_ranges(ranged_identifier->first, ranged_identifier->second);
2657  result.insert(result.end(), expanded.begin(), expanded.end());
2658  }
2659  else if (const numeral_t* numeral = std::get_if<numeral_t>(&var); numeral != nullptr)
2660  {
2661  for (auto value : *numeral)
2662  {
2663  result.push_back("'" + BooleanFunction::to_string(value) + "'");
2664  }
2665  }
2666  }
2667 
2668  return result;
2669  }
2670 } // namespace hal
u32 size
static std::string to_string(Value value)
bool set_data(const std::string &category, const std::string &key, const std::string &data_type, const std::string &value, const bool log_with_info_level=false)
std::unordered_map< std::string, GateType * > get_gate_types(const std::function< bool(const GateType *)> &filter=nullptr) const
std::unordered_map< std::string, GateType * > get_vcc_gate_types() const
std::unordered_map< std::string, GateType * > get_gnd_gate_types() const
std::string get_name() const
bool is_input_net(Net *net) const
Definition: module.cpp:564
void set_name(const std::string &name)
Definition: module.cpp:93
void update_nets()
Definition: module.cpp:443
bool is_top_module() const
Definition: module.cpp:321
bool assign_gate(Gate *gate)
Definition: module.cpp:331
bool is_output_net(Net *net) const
Definition: module.cpp:574
std::string get_name() const
Definition: module.cpp:88
const std::unordered_set< Net * > & get_input_nets() const
Definition: module.cpp:549
void set_type(const std::string &type)
Definition: module.cpp:112
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:796
const std::unordered_set< Net * > & get_output_nets() const
Definition: module.cpp:554
u32 get_id() const
Definition: module.cpp:83
Definition: net.h:58
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:432
Module * get_top_module() const
Definition: netlist.cpp:610
u32 get_unique_gate_id()
Definition: netlist.cpp:162
bool mark_vcc_gate(Gate *gate)
Definition: netlist.cpp:230
bool mark_gnd_gate(Gate *gate)
Definition: netlist.cpp:246
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:864
bool delete_net(Net *net)
Definition: netlist.cpp:345
Net * create_net(const u32 net_id, const std::string &name)
Definition: netlist.cpp:335
const std::vector< Gate * > & get_gnd_gates() const
Definition: netlist.cpp:311
void set_design_name(const std::string &name)
Definition: netlist.cpp:111
void enable_automatic_net_checks(bool enable_checks=true)
Definition: netlist.cpp:565
const std::vector< Gate * > & get_vcc_gates() const
Definition: netlist.cpp:306
const std::vector< Module * > & get_modules() const
Definition: netlist.cpp:626
Gate * create_gate(const u32 gate_id, GateType *gate_type, const std::string &name="", i32 x=-1, i32 y=-1)
Definition: netlist.cpp:175
const std::vector< Net * > & get_nets() const
Definition: netlist.cpp:366
const GateLibrary * get_gate_library() const
Definition: netlist.cpp:134
Module * create_module(const u32 module_id, const std::string &name, Module *parent, const std::vector< Gate * > &gates={})
Definition: netlist.cpp:589
u32 remaining() const
Definition: token_stream.h:494
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 > consume_current_line()
Definition: token_stream.h:282
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
Result< std::unique_ptr< Netlist > > instantiate(const GateLibrary *gate_library) override
uint64_t u64
Definition: defines.h:42
uint16_t u16
Definition: defines.h:40
uint32_t u32
Definition: defines.h:41
int32_t i32
Definition: defines.h:36
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
#define ERR_APPEND(prev_error, message)
Definition: result.h:64
const Module * module(const Gate *g, const NodeBoxes &boxes)
std::unique_ptr< Netlist > create_netlist(const GateLibrary *gate_library)
Create a new empty netlist using the specified gate library.
T replace(const T &str, const T &search, const T &replace)
Definition: utils.h:428
bool is_digits(const T &s)
Definition: utils.h:232
std::string join(const std::string &joiner, const Iterator &begin, const Iterator &end, const Transform &transform)
Definition: utils.h:458
bool ends_with(const T &s, const T &end)
Definition: utils.h:193
T to_upper(const T &s)
Definition: utils.h:509
T to_lower(const T &s)
Definition: utils.h:523
bool is_integer(const T &s)
Definition: utils.h:244
T trim(const T &s, const char *to_remove=" \t\r\n")
Definition: utils.h:404
Definition: defines.h:45
PinDirection
Definition: pin_direction.h:36
std::vector< PinInformation > pins
Net * net
PinDirection direction
std::string name
This file contains various functions to create and load netlists.
std::string identifier
std::unique_ptr< BasePluginInterface > instance
static Result< Parameter > Boolean(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:319
static Result< Parameter > BitVector(const std::string &name, u16 size, const std::string &default_value)
Definition: parameter.cpp:340
static Result< Parameter > Integer(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:390
static Result< Parameter > String(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:411
static Result< Parameter > LogicVector(const std::string &name, u16 size, const std::string &default_value)
Definition: parameter.cpp:365
static Result< Parameter > Time(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:448
static Result< Parameter > Float(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:427