StanfordAHA/garnet

Tapeout: LVS errors in final gds

Closed this issue · 7 comments

On r7arm-aha machine, see results in e.g. /sim/steveri/tmpdir/lvs_top

  • results summary in ./GarnetSOC_pad_frame/GarnetSOC_pad_frame.lvs.report
  • View results : calibre -rve -lvs ./GarnetSOC_pad_frame/svdb

The actual error relates to 6 random bits in a 20-bit register (??):

  % grep -i err /sim/steveri/tmpdir/lvs_top/GarnetSOC_pad_frame/GarnetSOC_pad_frame.lvs.report
  LVS Netlist Compiler - Errors and Warnings for "GarnetSOC_pad_frame.sp"
  Error: No matching pin name "RC_CG_GCLK_PORT" in subcircuit
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_4"
    in file "../pe/Tile_PE/Tile_PE.sp" at line 26106
  Also:
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_5"
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_9"
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_14"
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_16"
    "Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_18"

You should be able to duplicate the errors by following the instructions in
/sim/steveri/garnet/tapeout_16/lvs/README.txt

# Must be on arm machine
ssh r7arm-aha

# Set up for to run calibre
module load icadv/12.30.712
module load calibre/2019.1
# etc. also see ~ajcars/.cshrc

# Find a place to work
mkdir /sim/$USER/tmpdir; cd /sim/$USER/tmpdir

# top
cd /sim/$USER/tmpdir
mkdir lvs_top; cd lvs_top
lvs=/sim/steveri/garnet/tapeout_16/lvs/lvs.sh
top=GarnetSOC_pad_frame
gds=/sim/steveri/garnet/tapeout_16/synth/ref/final_final.gds
vlg=/sim/steveri/garnet/tapeout_16/synth/ref/pnr.final.lvs.v
ls -l $gds $vlg
echo $lvs $gds $vlg $top
$lvs $gds $vlg $top |& tee lvs_top.log

Are you synthesizing both tiles with power domains enabled?

@THofstee

Are you synthesizing both tiles with power domains enabled?

Yes I think so. Should they be off?

It should be synthesizing with power domains enabled. I'm just wondering because the missing port looks like something related to clock gating.

I have one other idea, I was running into issues with PrimeTime before because the Tile_MemCore and Tile_PE both define the same modules with different implementations/port signatures.

What does Register_has_ce_True_has_reset_False_has_async_reset_False_type_Bits_n_16_4 look like in Tile_PE's pnr.sv and Tile_MemCore's pnr.sv?

Here's a script to rename all modules in a design (requires python3). You would invoke it like python rename_modules.py pnr.sv --exclude Tile_MemCore.

import argparse
import base64
from pathlib import Path
import re
import time
import uuid

re_module_defn = re.compile(r"module\W+(?P<name>\w+)(?P<body>.*?)endmodule", re.DOTALL)

def main(args):
    args.src = Path(args.src)
    # args.dst = Path(args.dst)

    suffix = "".join(base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip(b'=').decode('ascii').split("-"))

    with open(args.src) as f:
        s = f.read()

        names = {}
        modules = []
        for match in re_module_defn.finditer(s):
            name = match.group('name')

            if name not in args.exclude:
                names[name] = name + suffix

            modules.append(match)

        skip_token = False
        tokens = re.split(r"(\s+)", s)

        for k, token in enumerate(tokens):
            # skip whitespace tokens
            if token.strip() == "":
                continue

            if skip_token:
                skip_token = False
                continue

            if token in names:
                tokens[k] = names[token]
                # If a module instance name is the same as the module
                # name we don't want to rename the instance. This is
                # hacky, a better way would be to parse the Verilog
                # into an AST and actually do things correctly.
                skip_token = True

        print("".join(tokens))

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="""
    This is a helper script to rename modules in a Verilog file.
    """)

    parser.add_argument("src", nargs="?", default=".")
    # parser.add_argument("dst", nargs="?", default=".")
    # parser.add_argument("modules", nargs="?", default=".")
    # parser.add_argument("name", nargs="?", default=".")
    parser.add_argument("--exclude", nargs="*", default=[])

    args = parser.parse_args()

    main(args)

Hm you may be onto something here. They do indeed appear to have same-name modules with different interfaces and definitions :( I'll have to look at this more closely when I get back from vacation (unless someone beats me to it...)

I looked at Genus a bit, I think we can work around this in the write_hdl command.

write_hdl
    [-suffix <string>]:
        specifies the string to be appended to the name of all defined modules

This would require the following changes:

  • Tile_PE and Tile_MemCore each get a unique pre-determined suffix that needs to be added in their synthesis scripts
  • Top-level synthesis probably needs to look for the tiles as Tile_MemCore_suffix instead of Tile_MemCore, and similarly for the PE.

Nice! Thanks Teguh I will definitely try this when I get back.

I think it worked, at least I'm not seeing the same errors as before. Unfortunately there is a new problem now, maybe caused by the fix...top-level LVS runs out of memory and crashes while flattening. I will close this issue and file a new one. :(