blob: 21b7771b6cb48069d1c5fc6d6378ffae51c03fe8 [file] [log] [blame]
S Skandha Deepsita6d195b62021-06-24 23:39:43 +05301#!/usr/bin/python3
2# SPDX-FileCopyrightText: 2020 Efabless Corporation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15# SPDX-License-Identifier: Apache-2.0
16
17#
18#---------------------------------------------------------
19# LVS failure check
20#
21# This is a Python script that parses the comp.json
22# output from netgen and reports on the number of
23# errors in the top-level netlist.
24#
25#---------------------------------------------------------
26# Written by Tim Edwards
27# efabless, inc.
28# Pulled from qflow GUI as standalone script Aug 20, 2018
29#---------------------------------------------------------
30
31import os
32import re
33import sys
34import json
35import argparse
36
37def count_LVS_failures(filename):
38 with open(filename, 'r') as cfile:
39 lvsdata = json.load(cfile)
40
41 # Count errors in the JSON file
42 failures = 0
43 devfail = 0
44 netfail = 0
45 pinfail = 0
46 propfail = 0
47 netdiff = 0
48 devdiff = 0
49 ncells = len(lvsdata)
50 for c in range(0, ncells):
51 cellrec = lvsdata[c]
52
53 if c == ncells - 1:
54 topcell = True
55 else:
56 topcell = False
57
58 # Most errors must only be counted for the top cell, because individual
59 # failing cells are flattened and the matching attempted again on the
60 # flattened netlist.
61
62 if topcell:
63 if 'devices' in cellrec:
64 devices = cellrec['devices']
65 devlist = [val for pair in zip(devices[0], devices[1]) for val in pair]
66 devpair = list(devlist[p:p + 2] for p in range(0, len(devlist), 2))
67 for dev in devpair:
68 c1dev = dev[0]
69 c2dev = dev[1]
70 diffdevs = abs(c1dev[1] - c2dev[1])
71 failures += diffdevs
72 devdiff += diffdevs
73
74 if 'nets' in cellrec:
75 nets = cellrec['nets']
76 diffnets = abs(nets[0] - nets[1])
77 failures += diffnets
78 netdiff += diffnets
79
80 if 'badnets' in cellrec:
81 badnets = cellrec['badnets']
82 failures += len(badnets)
83 netfail += len(badnets)
84
85 if 'badelements' in cellrec:
86 badelements = cellrec['badelements']
87 failures += len(badelements)
88 devfail += len(badelements)
89
90 if 'pins' in cellrec:
91 pins = cellrec['pins']
92 pinlist = [val for pair in zip(pins[0], pins[1]) for val in pair]
93 pinpair = list(pinlist[p:p + 2] for p in range(0, len(pinlist), 2))
94 for pin in pinpair:
95 # Avoid flagging global vs. local names, e.g., "gnd" vs. "gnd!,"
96 # and ignore case when comparing pins.
97 pin0 = re.sub('!$', '', pin[0].lower())
98 pin1 = re.sub('!$', '', pin[1].lower())
99 if pin0 != pin1:
100 failures += 1
101 pinfail += 1
102
103 # Property errors must be counted for every cell
104 if 'properties' in cellrec:
105 properties = cellrec['properties']
106 failures += len(properties)
107 propfail += len(properties)
108
109 return [failures, netfail, devfail, pinfail, propfail, netdiff, devdiff]
110
111if __name__ == '__main__':
112
113 parser = argparse.ArgumentParser(description='Parses netgen lvs')
114 parser.add_argument('--file', '-f', required=True)
115 args = parser.parse_args()
116 failures = count_LVS_failures(args.file)
117 total = failures[0]
118 if total > 0:
119 failed = True
120 print('LVS reports:')
121 print(' net count difference = ' + str(failures[5]))
122 print(' device count difference = ' + str(failures[6]))
123 print(' unmatched nets = ' + str(failures[1]))
124 print(' unmatched devices = ' + str(failures[2]))
125 print(' unmatched pins = ' + str(failures[3]))
126 print(' property failures = ' + str(failures[4]))
127 else:
128 print('LVS reports no net, device, pin, or property mismatches.')
129
130 print('')
131 print('Total errors = ' + str(total))
132