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}