blob: 21b7771b6cb48069d1c5fc6d6378ffae51c03fe8 [file] [log] [blame]
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# SPDX-License-Identifier: Apache-2.0
#
#---------------------------------------------------------
# LVS failure check
#
# This is a Python script that parses the comp.json
# output from netgen and reports on the number of
# errors in the top-level netlist.
#
#---------------------------------------------------------
# Written by Tim Edwards
# efabless, inc.
# Pulled from qflow GUI as standalone script Aug 20, 2018
#---------------------------------------------------------
import os
import re
import sys
import json
import argparse
def count_LVS_failures(filename):
with open(filename, 'r') as cfile:
lvsdata = json.load(cfile)
# Count errors in the JSON file
failures = 0
devfail = 0
netfail = 0
pinfail = 0
propfail = 0
netdiff = 0
devdiff = 0
ncells = len(lvsdata)
for c in range(0, ncells):
cellrec = lvsdata[c]
if c == ncells - 1:
topcell = True
else:
topcell = False
# Most errors must only be counted for the top cell, because individual
# failing cells are flattened and the matching attempted again on the
# flattened netlist.
if topcell:
if 'devices' in cellrec:
devices = cellrec['devices']
devlist = [val for pair in zip(devices[0], devices[1]) for val in pair]
devpair = list(devlist[p:p + 2] for p in range(0, len(devlist), 2))
for dev in devpair:
c1dev = dev[0]
c2dev = dev[1]
diffdevs = abs(c1dev[1] - c2dev[1])
failures += diffdevs
devdiff += diffdevs
if 'nets' in cellrec:
nets = cellrec['nets']
diffnets = abs(nets[0] - nets[1])
failures += diffnets
netdiff += diffnets
if 'badnets' in cellrec:
badnets = cellrec['badnets']
failures += len(badnets)
netfail += len(badnets)
if 'badelements' in cellrec:
badelements = cellrec['badelements']
failures += len(badelements)
devfail += len(badelements)
if 'pins' in cellrec:
pins = cellrec['pins']
pinlist = [val for pair in zip(pins[0], pins[1]) for val in pair]
pinpair = list(pinlist[p:p + 2] for p in range(0, len(pinlist), 2))
for pin in pinpair:
# Avoid flagging global vs. local names, e.g., "gnd" vs. "gnd!,"
# and ignore case when comparing pins.
pin0 = re.sub('!$', '', pin[0].lower())
pin1 = re.sub('!$', '', pin[1].lower())
if pin0 != pin1:
failures += 1
pinfail += 1
# Property errors must be counted for every cell
if 'properties' in cellrec:
properties = cellrec['properties']
failures += len(properties)
propfail += len(properties)
return [failures, netfail, devfail, pinfail, propfail, netdiff, devdiff]
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Parses netgen lvs')
parser.add_argument('--file', '-f', required=True)
args = parser.parse_args()
failures = count_LVS_failures(args.file)
total = failures[0]
if total > 0:
failed = True
print('LVS reports:')
print(' net count difference = ' + str(failures[5]))
print(' device count difference = ' + str(failures[6]))
print(' unmatched nets = ' + str(failures[1]))
print(' unmatched devices = ' + str(failures[2]))
print(' unmatched pins = ' + str(failures[3]))
print(' property failures = ' + str(failures[4]))
else:
print('LVS reports no net, device, pin, or property mismatches.')
print('')
print('Total errors = ' + str(total))