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