libreda_structural_verilog/reader.rs
1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! This module implements a netlist reader for structural Verilog.
7
8use itertools::Itertools;
9use lalrpop_util::lalrpop_mod;
10
11use libreda_db::prelude::NetlistReader;
12
13use libreda_db::netlist::direction::Direction;
14use libreda_db::netlist::traits::NetlistEdit;
15use libreda_db::netlist::util::*;
16use std::collections::{HashMap, HashSet};
17use std::io::Read;
18
19use crate::ast;
20use crate::ast::{Bit, Expr, Module, ModulePortConnections, Port};
21use std::borrow::Borrow;
22
23// Import the parser synthesized by LALRPOP.
24lalrpop_mod!(pub grammar);
25
26/// Error type returned by the Verilog reader.
27#[derive(Debug, Clone, Eq, PartialEq)]
28pub enum ParseError {
29 /// Some unspecified error.
30 UndefinedError(String),
31 /// Modules have a cyclic dependency. (Recursive module instantiation)
32 CyclicDependency,
33 /// The Verilog data is not UTF-8 encoded.
34 InvalidUTF8,
35 /// The syntax is not not accepted.
36 /// Contains an error message string.
37 InvalidVerilog(String),
38 /// Some modules are not known yet. Contains names of the missing modules.
39 MissingModules(Vec<String>),
40 /// Some module ports are neither declared as input nor output.
41 /// Contains module name and list of affected module ports.
42 PortsWithoutDirection(String, Vec<String>),
43 /// Some nets are used but not declared with a `wire`/`input`/`output`/`inout` statement.
44 UndeclaredNets(Vec<String>),
45 /// Bit width is wrong in an assignment.
46 AssignmentWidthMismatch(Vec<(ast::LValue, ast::Expr)>),
47 /// Mismatch of number of ports in port connection of a module instantiation.
48 PortConnectionMismatch,
49 /// Bit-width mismatch in a port connection.
50 PortConnectionWidthMismatch,
51}
52
53#[test]
54fn test_parse_verilog() {
55 let test_verilog_code: &str = r"
56
57/* Header comment ( test ) */
58
59module OR(A, B);
60 input A, B;
61endmodule
62
63module NOT(A);
64 input A;
65endmodule
66
67module blabla(port1, port_2);
68 input [0:1234] asdf;
69 output [1:3] qwer;
70 wire [1234:45] mywire;
71
72 wire \escaped_name[[a]} ;
73
74 assign a = b;
75
76 assign a = 8'h12xX;
77 assign b = 8'h12zZ;
78 assign c = 8'b00010010xxXX;
79 assign d = 8'b00010010zzZZ;
80
81 assign {a, b[1], c[0: 39]} = {x, y[5], z[1:40]};
82 assign {a, b[1], c[0: 39]} = {x, y[5], 1'h0 };
83 (* asdjfasld ajsewkea 3903na ;lds *)
84 wire zero_set;
85 OR _blabla_ ( .A(netname), .B (qwer) );
86 OR blabla2 ( .A(netname), .B (1'b0) );
87
88 wire zero_res;
89 (* src = 'alu_shift.v:23' *)
90 wire zero_set;
91 NOT #(
92 .param1(1'h0),
93 .param2(1'h1)
94 )
95 _072_ (
96 .A(func_i[2]),
97 .Y(_008_)
98 );
99
100 // Use a module before it is defined.
101 DefinedAfterUsage instance_used_before_definition (1'b0);
102
103endmodule
104
105module DefinedAfterUsage(A);
106 input A;
107endmodule
108";
109
110 let parser = grammar::NetlistParser::new();
111
112 log::debug!("Parse structural verilog.");
113 let result: Result<Vec<Module>, _> = parser.parse(test_verilog_code);
114 dbg!(&result);
115 assert!(result.is_ok());
116}
117
118/// Reader for purely structural Verilog.
119/// Only very basic Verilog features are supported.
120pub struct StructuralVerilogReader {
121 /// If set to true cells will be read but not populated with internal instances.
122 load_blackboxes: bool,
123}
124
125impl StructuralVerilogReader {
126 /// Create a default Verilog reader.
127 pub fn new() -> Self {
128 StructuralVerilogReader {
129 load_blackboxes: false,
130 }
131 }
132
133 /// If set to true cells will be read but not populated with internal instances.
134 /// This way the reader will read only cell definitions but does not care about
135 /// the internals of the cell. This is useful for loading libraries of standard-cells
136 /// where the content of the standard-cell is not needed.
137 pub fn load_blackboxes(mut self, load_blackboxes: bool) -> Self {
138 self.load_blackboxes = load_blackboxes;
139 self
140 }
141
142 /// Populate a netlist based on the Verilog abstract syntax tree.
143 fn convert_ast_to_netlist<N: NetlistEdit>(
144 &self,
145 modules: Vec<ast::Module>,
146 netlist: &mut N,
147 ) -> Result<(), ParseError> {
148 log::debug!("Convert Verilog abstract syntax tree into a netlist.");
149
150 // Tells for each module how multi-bit pins have been expanded.
151 // module name -> (port name -> pin position)
152 let mut pin_expansion: HashMap<&String, HashMap<&String, Vec<usize>>> = HashMap::new();
153
154 // Build module dependency tree.
155 // This helps to determine the correct order for creating the circuits in the netlist.
156
157 log::debug!("Build module dependency graph.");
158 let dependency_graph = {
159 let mut dependency_graph: petgraph::graphmap::DiGraphMap<&String, ()> = modules
160 .iter()
161 .flat_map(|v_module| {
162 let module_name = v_module.name.name();
163 // Find all modules that get instanciated in this module.
164 v_module
165 .instantiations()
166 .filter(|_| !self.load_blackboxes) // Ignore instances if flag is set.
167 .map(move |(inst_module_name, _)| (inst_module_name, module_name))
168 })
169 .collect();
170 // Add all modules as nodes. Some might not have appeared in a dependency relation.
171 modules.iter().for_each(|v_module| {
172 dependency_graph.add_node(v_module.name.name());
173 });
174 dependency_graph
175 };
176
177 // Sort modules topologically. Each module is ordered before its successors.
178 log::debug!("Sort modules topologically.");
179 let topo = petgraph::algo::toposort(&dependency_graph, None);
180 let topo_sorted: Vec<&String> = match topo {
181 Ok(sorted) => sorted,
182 Err(cycle) => {
183 log::error!("Modules have a cyclic dependency. ({})", cycle.node_id());
184 return Err(ParseError::CyclicDependency);
185 }
186 };
187
188 // Create lookup table to find modules by name.
189 let modules_by_name: HashMap<_, _> = modules
190 .iter()
191 .map(|module| (module.name.name(), module))
192 .collect();
193
194 // Check that all modules are present.
195 {
196 log::debug!("Check that all required modules are present.");
197 let missing_modules: Vec<String> = topo_sorted
198 .iter()
199 .filter(|&name| {
200 !modules_by_name.contains_key(name)
201 && !netlist.cell_by_name(name.as_str()).is_some()
202 })
203 .map(|&n| n.clone())
204 .collect();
205
206 if !missing_modules.is_empty() {
207 log::error!("Modules are missing: {}", missing_modules.iter().join(", "));
208 return Err(ParseError::MissingModules(missing_modules));
209 }
210 }
211
212 // Create circuits.
213
214 // Create only circuits that appear in this verilog file.
215 // Other circuits might be already present in the netlist.
216 let modules_to_create = topo_sorted
217 .iter()
218 .filter(
219 |&name| {
220 modules_by_name.contains_key(name)
221 && netlist.cell_by_name(name.as_str()).is_none()
222 }, // Do not create a circuit when it already exists.
223 )
224 .collect_vec();
225
226 // Bit-widths of ports for all modules.
227 // This is updated while each module is processed.
228 // Since modules are processed in bottom-up order all required information should
229 // be here on time.
230 // module name -> (port name -> port width)
231 let mut port_widths_by_module: HashMap<&String, HashMap<&String, usize>> = HashMap::new();
232
233 // module name -> port names
234 let mut port_names_by_module: HashMap<&String, Vec<&String>> = HashMap::new();
235
236 for &v_module_name in modules_to_create {
237 let v_module = modules_by_name[v_module_name];
238 log::trace!("Create module: '{}'", v_module_name);
239
240 // Check that no circuit name is used more than once.
241 assert!(
242 netlist.cell_by_name(v_module_name.as_str()).is_none(),
243 "Circuit is already defined."
244 );
245
246 // Find input/output nets and internal nets.
247 let wire_nets: HashSet<_> = v_module.net_declarations().collect();
248 let io_nets: HashSet<_> = v_module
249 .all_io_declarations()
250 .map(|(slice, name, _dir)| (slice, name))
251 .collect();
252
253 let io_net_directions_by_name: HashMap<_, _> = v_module
254 .all_io_declarations()
255 .map(|(_slice, name, dir)| (name, dir))
256 .collect();
257
258 let all_net_declarations = wire_nets
259 .iter()
260 .chain(io_nets.iter())
261 .copied()
262 .collect_vec();
263
264 let net_declaration_by_name: HashMap<_, _> = all_net_declarations
265 .iter()
266 .map(|&(slice, name)| (name, slice))
267 .collect();
268 log::trace!("Number of net names: {}", net_declaration_by_name.len());
269
270 // Find the bit-widths of the module ports.
271 let signal_width = |name: &String| -> usize {
272 net_declaration_by_name[name]
273 .map(|slice| slice.width())
274 .unwrap_or(1)
275 };
276
277 // Get all I/O net names.
278 let io_net_names: HashSet<&String> = io_nets.iter().map(|&(_, name)| name).collect();
279
280 // Get all non-I/O net names.
281 let wire_net_names: HashSet<&String> =
282 wire_nets.iter().map(|&(_, name)| name).collect();
283
284 // Get ordered port names.
285 let port_names = v_module
286 .ports
287 .iter()
288 .map(|port| match port {
289 Port::Ref(ident) => ident.name(),
290 Port::Named(name) => name.0.name(),
291 })
292 .collect_vec();
293
294 // Sanity checks.
295 {
296 let port_names_set: HashSet<_> = port_names.iter().copied().collect();
297
298 {
299 // Sanity check: check that every port name is declared as input, output or inout.
300 log::trace!(
301 "Check that every port name is declared as a input/output/inout signal."
302 );
303
304 let ports_without_direction: HashSet<_> =
305 port_names_set.difference(&io_net_names).copied().collect();
306 if !ports_without_direction.is_empty() {
307 log::error!("Found ports in module {} that are neither declared as input nor output: {}",
308 v_module_name, ports_without_direction.iter().sorted().join(", "));
309 return Err(ParseError::PortsWithoutDirection(
310 v_module_name.clone(),
311 ports_without_direction.into_iter().cloned().collect(),
312 )); // TODO: More specific error type.
313 }
314 }
315
316 {
317 // Sanity check: check that every input/output declaration is actually a port name.
318 log::debug!(
319 "Check that every input/output/inout declaration is actually a port name."
320 );
321
322 let unnecessary_io_declarations: HashSet<_> =
323 io_net_names.difference(&port_names_set).collect();
324
325 if !unnecessary_io_declarations.is_empty() {
326 log::error!(
327 "Net declared as input/output but not in port list: {}",
328 unnecessary_io_declarations.iter().sorted().join(", ")
329 );
330 // TODO: Make configurable to return an Err?
331 }
332 }
333
334 {
335 // Sanity check: All used nets should be declared.
336 log::debug!("Check that all used nets are declared.");
337
338 // Get all nets names that are connected to module instances.
339 let module_instance_nets: HashSet<_> = v_module
340 .instantiations()
341 .flat_map(|(_, inst)| match &inst.1 {
342 ModulePortConnections::Unnamed(unnamed) => {
343 unnamed.iter().collect_vec().into_iter()
344 }
345 ModulePortConnections::Named(named) => {
346 named.iter().map(|named| &named.1).collect_vec().into_iter()
347 }
348 })
349 .flat_map(|expr| expr.flat_concatenation().into_iter())
350 .filter_map(|expr| match expr {
351 Expr::Ref(i) => Some(i.name()),
352 Expr::IdentIndexed(i) => Some(i.name()),
353 Expr::IdentSliced(i) => Some(i.name()),
354 Expr::Num(_) => None, // Ignore constants.
355 Expr::Concatenation(_) => {
356 panic!(
357 "Flattened concatenation should not contain a concatenation."
358 )
359 }
360 })
361 .collect();
362
363 // Find nets that are used but not declared.
364 let undeclared_nets: HashSet<&String> = module_instance_nets
365 .difference(&wire_net_names.union(&io_net_names).copied().collect())
366 .copied()
367 .collect();
368
369 if !undeclared_nets.is_empty() {
370 let nets = undeclared_nets.into_iter().cloned().collect_vec();
371 log::error!("Found undeclared nets: {}.", nets.join(", "));
372 return Err(ParseError::UndeclaredNets(nets));
373 }
374 }
375 }
376
377 // Store the port widths. They are needed when creating instances of this module.
378 let port_widths: HashMap<_, _> = v_module
379 .ports
380 .iter()
381 .map(|port| match port {
382 Port::Ref(i) => (i.name(), signal_width(i.name())),
383 Port::Named(_) => {
384 panic!("Port definition should not be a named port connection.")
385 }
386 })
387 .collect();
388 port_widths_by_module.insert(v_module_name, port_widths);
389
390 // Remember port names. Used for instances of this module in modules that are
391 // processed later.
392 port_names_by_module.insert(v_module_name, port_names);
393
394 // Expand multi-signal nets and create net identifiers.
395 // Generate a unique ID for each bit signal.
396 // IDs 0 and 1 are reserved for constants: 0=LOW, 1=HIGH, will be connected to TIE cells.
397 let net_ids_by_name = {
398 let mut net_id_counter = (2..).into_iter().peekable();
399 let net_ids_by_name: HashMap<_, _> = all_net_declarations
400 .iter()
401 .map(|&(slice, name)| {
402 // Expand a slice into a list of net IDs
403 // or create a single net ID if it is not an array.
404 let indices = slice
405 .map(|s| s.indices_range().collect_vec())
406 .unwrap_or(vec![0]);
407 // Generate net IDs.
408 let nets: Vec<usize> = indices
409 .iter()
410 .map(|_| net_id_counter.next().unwrap())
411 .collect();
412
413 (name, nets)
414 })
415 .collect();
416 log::trace!(
417 "Number of expanded nets: {}",
418 *net_id_counter.peek().unwrap() - 2
419 );
420 net_ids_by_name
421 };
422
423 /// Given a verilog expression (concatenation, identifier (optionally sliced or indexed)
424 /// find the corresponding net IDs.
425 /// Constant integers are translated into a vector of `[0, 1]` with a length
426 /// corresponding to the bit width of the integer literal.
427 fn find_net_ids(
428 lookup_table: &HashMap<&String, Vec<usize>>,
429 expr: &Expr,
430 ) -> Vec<usize> {
431 expr.flat_concatenation()
432 .iter()
433 .flat_map(|expr| {
434 match expr {
435 Expr::Ref(i) => lookup_table[i.name()].clone(),
436 Expr::IdentIndexed(i) => vec![lookup_table[i.name()][i.index()]],
437 Expr::IdentSliced(i) => lookup_table[i.name()]
438 [i.lowest_index()..=i.highest_index()]
439 .to_vec(),
440 Expr::Num(n) => n
441 .to_bits_msb_first()
442 .iter()
443 .map(|&b| match b {
444 Bit::Zero => 0,
445 Bit::One => 1,
446 Bit::DontCare => 0, // Set don't-cares to a constant. TODO: Is this correct?
447 Bit::HighImpedance => {
448 unimplemented!("High-Z nets are not supported.")
449 }
450 })
451 .collect(),
452 Expr::Concatenation(_c) => panic!(
453 "Flattened concatenation should not contain a concatenation."
454 ),
455 }
456 .into_iter()
457 })
458 .collect()
459 }
460
461 // Resolve continuous assigns.
462 // Construct a map that tells which signal is driven by which other signal.
463 let mut bitwidth_mismatches = Vec::new(); // Keep track of errors.
464 let continuous_assign_map: Vec<(usize, usize)> = v_module
465 .continuous_assignments()
466 .flat_map(|ast::Assignment(lvalue, rexpr)| {
467 let lvalues = lvalue.flat_concatenation();
468 let rvalues = rexpr.flat_concatenation();
469
470 // Convert to net IDs.
471 let l_nets: Vec<_> = lvalues
472 .iter()
473 .flat_map(|l| find_net_ids(&net_ids_by_name, &l.to_expr()).into_iter())
474 .collect();
475 let r_nets: Vec<_> = rvalues
476 .iter()
477 .flat_map(|&r| find_net_ids(&net_ids_by_name, r).into_iter())
478 .collect();
479
480 // Bit length must be the same for both sides.
481 if l_nets.len() != r_nets.len() {
482 bitwidth_mismatches.push((lvalue.clone(), rexpr.clone()));
483 }
484
485 l_nets.into_iter().zip(r_nets)
486 })
487 .collect();
488
489 // Check for errors in the assignment.
490 if !bitwidth_mismatches.is_empty() {
491 return Err(ParseError::AssignmentWidthMismatch(bitwidth_mismatches));
492 }
493
494 // Create a mapping from net ids to expanded net name.
495 let expanded_net_names: HashMap<usize, String> = all_net_declarations
496 .iter()
497 .flat_map(|&(_slice, net_name)| {
498 let net_ids = &net_ids_by_name[net_name];
499 let is_single_bit = net_ids.len() == 1;
500 net_ids.iter().enumerate().map(move |(i, &id)| {
501 // Create a name for the bit of the expanded array.
502 let expanded_name = if is_single_bit {
503 debug_assert_eq!(i, 0);
504 net_name.clone()
505 } else {
506 // Append index like `signal_name.0`.
507 format!("{}.{}", net_name, i)
508 };
509 (id, expanded_name)
510 })
511 })
512 .collect();
513
514 // Create pins based on the ports of the verilog module.
515 let pins_with_net: Vec<_> = v_module
516 .ports
517 .iter()
518 .flat_map(|port| {
519 let port_name = match port {
520 Port::Ref(id) => id.name(),
521 Port::Named(_) => panic!("Expected a simple identifier."),
522 };
523
524 let direction = match io_net_directions_by_name[port_name] {
525 ast::Direction::Input => Direction::Input,
526 ast::Direction::Output => Direction::Output,
527 ast::Direction::InOut => Direction::InOut,
528 };
529
530 let net_ids = &net_ids_by_name[port_name];
531
532 let _expanded_net_names = &expanded_net_names;
533
534 net_ids.iter().map(move |id| {
535 let name = &_expanded_net_names[id];
536 (port_name, name, direction, id)
537 })
538 })
539 .collect();
540
541 // Create the circuit.
542 let circuit_id = netlist.create_cell(v_module_name.clone().into());
543 for &(_port_name, name, direction, _id) in &pins_with_net {
544 netlist.create_pin(&circuit_id, name.clone().into(), direction);
545 }
546
547 // Get the mapping from port names to pins of the port.
548 let module_pin_expansion: HashMap<&String, Vec<usize>> = pins_with_net
549 .iter()
550 .enumerate()
551 .map(|(pin_position, &(port_name, _, _, _))| (port_name, pin_position))
552 .into_group_map();
553 pin_expansion.insert(v_module_name, module_pin_expansion);
554
555 // Load circuit content.
556 if !self.load_blackboxes {
557 // Optionally skip loading of the module content.
558 // Create net objects that reside in the namespace of the parent circuit.
559 let nets_by_id: HashMap<usize, N::NetId> = {
560 let mut nets_by_id: HashMap<_, _> = expanded_net_names
561 .iter()
562 .map(|(&id, net_name)| {
563 // Try if net already exists (for __HIGH__ and __LOW__).
564 let net = netlist
565 .net_by_name(&circuit_id, net_name.as_str())
566 .unwrap_or_else(
567 // Otherwise create the net.
568 || {
569 netlist
570 .create_net(&circuit_id, Some(net_name.clone().into()))
571 },
572 );
573 (id, net)
574 })
575 .collect();
576
577 nets_by_id.insert(0, netlist.net_zero(&circuit_id));
578 nets_by_id.insert(1, netlist.net_one(&circuit_id));
579 nets_by_id
580 };
581
582 // Connect all pins of the circuit to the internal nets.
583 netlist
584 .each_pin_vec(&circuit_id)
585 .iter()
586 .zip(pins_with_net)
587 .for_each(|(pin_id, (_, name, _, net_id))| {
588 {
589 let pin_name = netlist.pin_name(&pin_id);
590 let pin_name_str: &String = pin_name.borrow();
591 debug_assert_eq!(name, pin_name_str, "Pin names don't match.");
592 }
593 netlist.connect_pin(pin_id, Some(nets_by_id[net_id].clone()));
594 });
595
596 // Make module instances and connections to them.
597 for (v_template_name, v_inst) in v_module.instantiations() {
598 // Name of the instance that will be created now.
599 let v_inst_name = v_inst.0.name();
600
601 // Find circuit by name.
602 let leaf_circuit = netlist
603 .cell_by_name(v_template_name.as_str())
604 // Existence of all required circuits should be verified already.
605 .expect("Circuit not found by name.");
606
607 log::trace!(
608 "Create instance of '{}' in module '{}'.",
609 v_template_name,
610 v_module_name
611 );
612
613 // Create sub-circuit instance.
614 let inst = netlist.create_cell_instance(
615 &circuit_id,
616 &leaf_circuit,
617 Some(v_inst_name.clone().into()),
618 );
619
620 // Loop over pin instances and attach them to the nets.
621 let all_pin_instances = netlist.each_pin_instance_vec(&inst);
622
623 let port_connections = &v_inst.1;
624
625 if let Some(v_template) = modules_by_name.get(v_template_name).copied() {
626 // The template module was was found and hence is defined in the current verilog file.
627 // Therefore we know the port definitions.
628
629 // Number of ports that are required for this template.
630 let num_ports_expected = v_template.ports.len();
631
632 // Find out what ports need to be connected to which nets.
633 let port_connections_by_name: HashMap<_, _> = match port_connections {
634 ModulePortConnections::Unnamed(conn) => {
635 // Connections by position.
636
637 // Check that the number of connections matches with the number of ports.
638 let num_ports_actual = conn.len();
639 if num_ports_actual != num_ports_expected {
640 log::error!("Mismatch in number of unnamed ports in module '{}', instantiation of '{}'. Found {}, expected {}.",
641 v_template_name, v_inst_name, num_ports_actual, num_ports_expected);
642 return Err(ParseError::PortConnectionMismatch);
643 }
644
645 // Check that the number of previously stored port names is consistent
646 // with the number of expected ports.
647 debug_assert_eq!(
648 port_names_by_module[v_template_name].len(),
649 num_ports_expected
650 );
651
652 // Create (port name, connection) tuples.
653 port_names_by_module[v_template_name]
654 .iter()
655 .zip(conn)
656 .map(|(&port_name, conn)| (port_name, conn))
657 .collect()
658 }
659 ModulePortConnections::Named(conn) => {
660 // Connections by port name.
661 conn.iter()
662 .map(|ast::NamedPortConnection(name, expr)| (name.name(), expr))
663 .collect()
664 }
665 };
666
667 {
668 // Sanity check on number of port connections. Each port must be connected.
669 let num_ports_actual = port_connections_by_name.len();
670 if num_ports_actual != num_ports_expected {
671 log::warn!("Mismatch in number of ports in module '{}', instantiation of '{}'. Found {}, expected {}.",
672 v_template_name, v_inst_name, num_ports_actual, num_ports_expected);
673 // return Err(ParseError::PortConnectionMismatch);
674 }
675 }
676
677 {
678 // Sanity check: bit-width of the port assignments must match.
679 for (&port_name, &expr) in &port_connections_by_name {
680 let bitwidth = port_widths_by_module[v_template_name][port_name];
681
682 // Expand the expression into bit signals and get the associated
683 // nets.
684 let nets: Vec<&N::NetId> = expr
685 .flat_concatenation() // Expand concatenations.
686 .into_iter()
687 .flat_map(|expr|
688 // Translate into net IDs.
689 find_net_ids(&net_ids_by_name, expr).into_iter())
690 .map(|net_id| &nets_by_id[&net_id])
691 .collect();
692
693 if nets.len() != bitwidth {
694 log::error!("Bit-width mismatch of port connection '{}' of instance '{}' in module '{}'.",
695 port_name, v_inst_name, v_module_name);
696 return Err(ParseError::PortConnectionWidthMismatch);
697 }
698 }
699 }
700
701 // Connect instance ports.
702 for (port_name, expr) in port_connections_by_name {
703 // Convert the expression into nets.
704 let flat_net_ids = find_net_ids(&net_ids_by_name, expr);
705 let flat_nets = flat_net_ids
706 .iter()
707 .map(|id| nets_by_id[id].clone())
708 .collect_vec();
709
710 // Find pin positions of this port.
711 let pin_positions = &pin_expansion[v_template_name][port_name];
712
713 let expected_bit_width = pin_positions.len();
714 let actual_bit_width = flat_nets.len();
715
716 // Check that the bit lengths match.
717 if actual_bit_width != expected_bit_width {
718 log::error!("Bit width mismatch in port connection '{}' of instance '{}' in module '{}'.",
719 port_name, v_inst_name, v_module_name);
720 return Err(ParseError::PortConnectionWidthMismatch);
721 }
722
723 // Connect the pin instances with the nets.
724 for (&pin_position, net) in pin_positions.into_iter().zip(flat_nets) {
725 let pin_inst = &all_pin_instances[pin_position];
726 netlist.connect_pin_instance(pin_inst, Some(net));
727 }
728 }
729 } else {
730 // Module was already present in the netlist.
731 // Since the netlist does not support yet the concept of ports, we have
732 // to connect to the flat pin list.
733
734 let num_connections_expected = all_pin_instances.len();
735
736 match port_connections {
737 ModulePortConnections::Unnamed(conn) => {
738 // Connections by position.
739
740 let flat_nets: Vec<&N::NetId> = Expr::Concatenation(conn.clone())
741 .flat_concatenation() // Expand concatenations.
742 .into_iter()
743 .flat_map(|expr|
744 // Translate into net IDs.
745 find_net_ids(&net_ids_by_name, &expr).into_iter())
746 .map(|net_id| &nets_by_id[&net_id])
747 .collect();
748
749 // Check that the number of connections matches with the number of ports.
750 let num_connections_actual = flat_nets.len();
751 if num_connections_actual != num_connections_expected {
752 log::error!("Mismatch in number of bit connections in module '{}', instantiation of '{}'. Found {}, expected {}.",
753 v_template_name, v_inst_name, num_connections_actual, num_connections_expected);
754 return Err(ParseError::PortConnectionMismatch);
755 }
756
757 // Make connections.
758 for (pin_inst, net) in all_pin_instances.iter().zip_eq(flat_nets) {
759 netlist.connect_pin_instance(pin_inst, Some(net.clone()));
760 }
761 }
762 ModulePortConnections::Named(conn) => {
763 // Connections by port name.
764 // TODO FIXME: In this case the ordering of the nets is not guaranteed to be correct.
765 // The ordering of named connections can be different from the actual
766 // ordering of the ports.
767
768 // For each named connection find the module pin (by name) and
769 // attach it to the net.
770 // TODO: Only single-bit connections are supported.
771 for c in conn {
772 let conn_name = c.0.name();
773 let pin = netlist.pin_by_name(&leaf_circuit, conn_name);
774 if let Some(pin) = pin {
775 // Flatten the expression in the port connection.
776 let flat_nets: Vec<_> =
777 find_net_ids(&net_ids_by_name, &c.1)
778 .into_iter()
779 .map(|net_id| &nets_by_id[&net_id])
780 .collect();
781
782 if flat_nets.len() != 1 {
783 let msg = format!("Number of bits in named connection must be exactly 1\
784 when the module is \
785 defined in another file: port '{}', Instance '{}' of '{}' in '{}'",
786 conn_name,
787 v_inst_name,
788 v_template_name,
789 v_module_name);
790 log::error!("{}", &msg);
791 return Err(ParseError::UndefinedError(msg));
792 }
793
794 // Connect the pin to the net.
795 let net = flat_nets[0];
796 let pin_inst = netlist.pin_instance(&inst, &pin);
797 netlist.connect_pin_instance(&pin_inst, Some(net.clone()));
798 } else {
799 let msg = format!(
800 "No such pin in cell '{}': {}",
801 v_module_name, conn_name
802 );
803 log::error!("{}", &msg);
804 return Err(ParseError::UndefinedError(msg));
805 }
806 }
807 }
808 }
809 }
810
811 // Expand the ports.
812 // let flat: Vec<_> = conn.iter()
813 // .flat_map(|e| e.flat_concatenation().into_iter())
814 // .collect();
815 // if all_template_pins.len() != flat.len() {
816 // log::error!("Bit width mismatch in port connection of instance {}. Found {}, expected {}.",
817 // v_inst_name, flat.len(), all_template_pins.len());
818 // }
819 }
820
821 // Process continuous assign statements.
822 // Replace all left-hand side nets by the right-hand side nets.
823 {
824 let mut net_replacements = HashMap::new();
825 for (left, right) in &continuous_assign_map {
826 let mut left_net = nets_by_id[left].clone();
827 while let Some(resolved) = net_replacements.get(&left_net).cloned() {
828 left_net = resolved;
829 }
830 let mut right_net = nets_by_id[right].clone();
831 while let Some(resolved) = net_replacements.get(&right_net).cloned() {
832 right_net = resolved;
833 }
834 netlist.replace_net(&left_net, &right_net);
835 net_replacements.insert(left_net, right_net);
836 }
837 }
838 }
839 }
840
841 Ok(())
842 }
843}
844
845impl NetlistReader for StructuralVerilogReader {
846 type Error = ParseError;
847
848 /// Parse a verilog netlist.
849 fn read_into_netlist<R: Read, N: NetlistEdit>(
850 &self,
851 reader: &mut R,
852 netlist: &mut N,
853 ) -> Result<(), Self::Error> {
854 // Read all data into memory.
855 log::debug!("Read verilog netlist.");
856
857 let verilog_data: Vec<u8> = reader.bytes().map(|b| b.unwrap()).collect();
858
859 let verilog_string = String::from_utf8(verilog_data);
860
861 if let Ok(verilog_string) = verilog_string {
862 let parser = grammar::NetlistParser::new();
863
864 log::debug!("Parse structural verilog.");
865 let result: Result<Vec<Module>, _> = parser.parse(verilog_string.as_str());
866
867 if let Ok(result) = result {
868 self.convert_ast_to_netlist(result, netlist)?;
869 Ok(())
870 } else {
871 log::error!("Error while reading verilog: {:?}", &result);
872 let msg = match result {
873 Err(lalrpop_util::ParseError::UnrecognizedToken {
874 token,
875 expected: exp,
876 }) => {
877 let (start, token, _end) = token;
878 // Find line number of the error.
879 let line_num = 1 + verilog_string
880 .chars()
881 .take(start)
882 .filter(|&c| c == '\n')
883 .count();
884 let msg = format!(
885 "Unrecognized token '{}' on line {}. Expected one of {}.",
886 token,
887 line_num,
888 exp.join(", ")
889 );
890 log::error!("{}", msg);
891 msg
892 }
893 Err(lalrpop_util::ParseError::InvalidToken { location }) => {
894 // Find line number of the error.
895 let line_num = 1 + verilog_string
896 .chars()
897 .take(location)
898 .filter(|&c| c == '\n')
899 .count();
900 let msg = format!("Invalid token on line {}.", line_num);
901 log::error!("{}", msg);
902 msg
903 }
904 _ => "Undefined error".to_string(),
905 };
906
907 Err(ParseError::InvalidVerilog(msg))
908 }
909 } else {
910 Err(ParseError::InvalidUTF8)
911 }
912 }
913}