Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
    • Synthesis Flow Overview
    • Synthesizable RTL and Inference
    • Reading Netlists and Reports
      • Cell Counts from stat
      • Area by Cell Type
      • Hierarchy, Fanout and Net Names
      • Longest Path, Write and Read Back
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
  • Sequential, FSM and Memory19
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
Loading lesson

←Reading Netlists and Reports
  1. Topics
  2. Logic Synthesis
  3. Synthesis Foundations
  4. Reading Netlists and Reports
  5. Hierarchy, Fanout and Net Names
On this page

    Part 1 of 9, lesson 13 of 14Part 1 of 9/Synthesis Foundations/Lesson 13 of 14Intermediate

    Hierarchy, Fanout and Net Names

    Hierarchy, fanout, net names, and constant pins in netlists and reports.

    Hierarchy changes how a report looks without changing the gates, and fanout hides in shared nets. Both surprise readers who treat every stat line as a gate count.

    After this lesson you can: compare flattened and hierarchical area, derive per-net fanout from a recorded netlist, and distrust generated net names.

    The question

    Hierarchy, fanout and naming answer three different questions that one report often mixes together: which instances exist, how heavily each net is loaded, and which names survive optimisation. This lesson separates them on a design with two instances of one AND submodule sharing an input, plus an OR at the top. Every count below is a recording from the script, including the fanout table and the mapped comparison, both counted from recorded netlists at build time rather than guessed from the RTL.

    Hierarchy in reports

    A hierarchical netlist keeps submodule instances, so its report counts instances alongside gates: the pre-flatten stat spans both the sub module and the top module, while the flattened report counts one flat module. The script pins the instance count first, flattens, then pins the dissolved result. Flattening moves gates between modules without creating or deleting any, which is exactly what the two reports confirm.

    yosys
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    read_verilog <<EOV
    module sub(input a, b, output y);
    assign y = a & b;
    endmodule
    module top(input a, b, c, output y);
    wire n1, n2;
    sub u1 (.a(a), .b(b), .y(n1));
    sub u2 (.a(a), .b(c), .y(n2));
    assign y = n1 | n2;
    endmodule
    EOV
    hierarchy -check -top top
    proc
    opt
    tee -o stat_hier.txt stat
    write_json net_hier.json
    select -assert-count 2 t:sub
    design -save hier
    flatten
    tee -o stat_flat.txt stat
    write_json net_flat.json
    select -assert-none t:sub
    select -assert-count 2 t:$and
    select -assert-count 1 t:$or
    design -load hier
    synth -top top
    tee -o abc_hier.txt abc -liberty course.lib -constr typical.constr -D 1000
    tee -o stat_hier_map.txt stat -liberty course.lib
    select -assert-count 2 t:sub
    select -assert-none t:$and t:$or t:$_AND_ t:$_OR_
    select -assert-min 1 t:NAND2 t:NOR2 t:AND2 t:OR2 t:INV t:BUF %u
    design -load hier
    synth -top top -flatten
    tee -o abc_flat.txt abc -liberty course.lib -constr typical.constr -D 1000
    tee -o stat_flat_map.txt stat -liberty course.lib
    write_json net_flat_map.json
    select -assert-none t:sub t:$and t:$or t:$_AND_ t:$_OR_
    select -assert-min 1 t:NAND2 t:NOR2 t:AND2 t:OR2 t:INV t:BUF %u
    design -load hier
    read_verilog <<EOV
    module tieconst(input a, b, output y, output z);
    assign y = a & 1'b1;
    assign z = b | 1'b0;
    endmodule
    EOV
    hierarchy -check -top tieconst
    opt
    tee -o stat_const.txt stat
    select -assert-none t:$and
    select -assert-none t:$or
    log PASS: hierarchy, flatten, both mapped areas and folded constants recorded

    Commercial flows call this keep_hierarchy versus flattening: keep the instances for floorplanning and debugging, or dissolve them so optimisation sees across the boundary.

    The hierarchical stat report prints one section per module plus a design-hierarchy total. This page quotes that total, so the hierarchical and flat reports compare like with like.

    Predict first Before reading on: flattening dissolves two sub instances into the top module. Will the flattened gate total match the hierarchical one, and which net will have the highest fanout?

    The gates match: 3 hierarchically ($and 2, $or 1) against 3 flat ($and 2, $or 1). The flat report's cell line reads 5 only because flattening leaves two $scopeinfo markers behind. The highest fanout sits on a with fanout 2: input a feeds both instances, so it drives twice the load of any other net.

    Flattened versus hierarchical area

    Hierarchy keeps the gates, but the mapped area moves a lot: 9 library units hierarchical against 4 flat. Mapped per module, each sub instance becomes one AND2 (area 3 each, counted twice) and the top becomes one OR2 (area 3): ABC's per-module run covers a single AND2 at area 3. Mapped flat, ABC sees the whole cone at once and covers it as OAI21 plus INV, with ABC reporting 2 gates at delay 168.07 ps. Same gates, different covering: flattening lets ABC optimise across the boundary, which is the textbook reason to flatten before mapping.

    Diagram
    8. Printing statistics.
    
    === top ===
    
            +----------Local Count, excluding submodules.
            | 
           12 wires
           12 wire bits
           12 public wires
           12 public wire bits
            4 ports
            4 port bits
            5 cells
            2   $and
    ...

    The flat report above is one module: 5 cells on 12 wires with no sub instances left — 3 gates plus the two $scopeinfo markers. Past the ellipsis the file lists one $or and the two markers. Against 3 cells across two modules before flattening, the gates are unchanged; the grouping and the covering are not.

    Fanout, counted from the netlist

    Fanout counts how many gate inputs one net drives. High fanout means heavy load, which later stages must buffer, so the number belongs to the netlist rather than to anyone's impression of the RTL. The table below is not typed: the lesson reads the recorded generic flat netlist (net_flat.json, before any library cell exists) and counts sinks per net at build time, exactly as a reporting script would.

    Net

    Fanout (loads driven)

    a

    2

    b

    1

    c

    1

    n1

    1

    n2

    1

    Input a leads at fanout 2 because it is shared by both instances, while every other generic net drives exactly one load. Mapping changes the answer: in the recorded mapped flat netlist (net_flat_map.json, one OAI21 plus one INV) input a drives 1 pin, because both ANDs dissolved into a single cell and the sharing vanished. Fanout depends on the stage, so always quote the netlist you counted from.

    Flattened generic three-gate netlist with instance names shown. The loads driven by input a are highlighted.

    Generated names and constant pins

    Nets without a declared name get a tool-generated one, and those names shift with small edits. Scripts and constraints must therefore use stable ports and hierarchical paths, never generated names: anything the tool invents, the next edit may rename. The flat netlist above shows the declared nets n1 and n2 alongside its ports precisely because the RTL declared them; an unnamed net would appear under a generated stand-in instead.

    Constant pins fold away during optimisation rather than building anything. Tying an input to 1 or 0 turns the gate into a wire, so the tied-constant design in the script reports no cells: both gates folded, no $and and no $or left, exactly as the assertions pin. Treat an undriven pin with the same suspicion in reverse: confirm it rather than assuming the tool understood the intent.

    Common mistakes

    Scripting against generated net names breaks on the next edit. Reference stable ports and hierarchical paths, and treat every generated name as temporary. A second trap is reading hierarchy as logic: flattening keeps the gates but can change the mapped area, because the flat cone gets a different covering.

    What survives flattening, and where does fanout come from?

    Weak: flattening simplifies the design and fanout is about outputs. Strong: flattening dissolves the two sub instances into two $and cells while the $or stays put, keeping 3 gates; the mapped area moves from 9 to 4 units because the flat cone is covered as OAI21 plus INV instead of separate AND2s plus an OR2; fanout is loads per net counted from the recorded generic netlist, with input a the maximum at 2 because both instances share it, dropping to 1 pin after mapping; tied constants fold to wires, leaving no cells.

    Follow-up: a script greps the netlist for a generated name and breaks after an RTL edit. What is the fix? Reference the stable port or hierarchical path instead, and never match on a name the tool invented.

    Check yourself Net a is shared by two instances. What is its fanout, and why does the table rather than the RTL settle it?

    Fanout 2 on the generic flat netlist: it drives one input on each of the two $and cells. The table settles it because fanout is a netlist property counted from recorded sinks, and RTL sharing is only a hint until the netlist confirms the loads.

    Check yourself The hierarchical mapped area is larger than the flat one. Does flattening change the design?

    No. The gates are identical: 3 hierarchically ($and 2, $or 1) against 3 flat ($and 2, $or 1). The mapped area gap is the covering — per-module AND2s plus an OR2 against one OAI21 plus INV — not new hardware.

    • Flattening keeps the gates but lets ABC cover logic across instance boundaries: 9 area units hierarchical against 4 flat.

    • Fanout is loads per net counted from the netlist: the shared input leads on the generic netlist and drops to one pin after mapping.

    • Generated net names shift with small edits; scripts must use stable ports and hierarchy.

    Rule of thumb: count fanout from the netlist, never from the RTL text.

    How this was checked

    Every number, both fanout counts and the highlighted netlist on this page come from one Yosys 0.69 run of the script shown, recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): a two-instance hierarchical design read flat and hierarchical, mapped against the teaching library course.lib, plus a tied-constant design folded by opt. The library is fictional, so absolute values are teaching units.

    • Interview: run a mock interview on this topic

    Related topics

    • Longest path, write and read back

    • Synthesizable RTL and Inference

    Previous

    15 / 139

    Next: Longest Path, Write and Read Back

    Up next

    Up nextLongest Path, Write and Read Back

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Cell Counts from stat