blob: 86441d341759f16bcbae75b7a829704832d9d2d9 [file] [log] [blame]
Tim Edwardsc46b9532021-04-12 14:31:29 -04001#!/bin/env python3
2#-------------------------------------------------------------------------
3# check_antenna.py --- A script to run magic in batch mode and run the
4# antenna violation checks on a layout.
5#
6# Usage:
7#
8# check_antenna.py <layout_name>
9#
10# Results:
11#
12# generates a file "<layout_name>_drc.txt" containing a human-readable
13# list of the DRC errors.
14#
15#-------------------------------------------------------------------------
16
17import subprocess
18import shutil
19import sys
20import os
21import re
22
23# Work in progress
24
25def run_antenna(layout_name, output_file):
26
27 # Remove any extension from layout_name
28 layout_name = os.path.splitext(layout_name)[0]
29
30 # Is the layout file in the current directory, or a full
31 # path, or is this a project directory?
32
33 if layout_name[0] == '/':
34 magpath = os.path.split(layout_name)[0]
35 layout_name = os.path.split(layout_name)[1]
36
37 else:
38 if not os.path.isfile(layout_name + '.mag'):
39 if not os.path.isfile('mag/' + layout_name + '.mag'):
40 print('Error: Cannot find file ' + layout_name + '.mag')
41 return
42 else:
43 magpath = os.getcwd + '/mag'
44 else:
45 magpath = os.getcwd
46
47 if output_file == '':
48 output_file = layout_name + '_ant.txt'
49
50 # Check for presence of a .magicrc file, or else check for environment
51 # variable PDKPATH, or PDK_PATH
52
53 myenv = os.environ.copy()
54 myenv['MAGTYPE'] = 'mag'
55
56 if os.path.isfile(magpath + '/.magicrc'):
57 rcfile = magpath + '/.magicrc'
58 elif os.path.isfile(os.getcwd() + '/.magicrc'):
59 rcfile = os.getcwd() + '/.magicrc'
60 else:
61 if 'PDKPATH' in myenv:
62 rcpathroot = myenv['PDKPATH'] + '/libs.tech/magic'
63 rcfile = glob.glob(rcpathroot + '/*.magicrc')[0]
64 elif 'PDK_PATH' in myenv:
65 rcpathroot = myenv['PDKPATH'] + '/libs.tech/magic'
66 rcfile = glob.glob(rcpathroot + '/*.magicrc')[0]
67 else:
68 print('Error: Cannot get magic rcfile for the technology!')
69 return
70
71 # Generate the antenna check Tcl script
72
73 print('Evaluating antenna rule violations on layout ' + layout_name)
74
75 with open('run_magic_antenna.tcl', 'w') as ofile:
76 print('# run_magic_antenna.tcl ---', file=ofile)
77 print('# batch script for running DRC', file=ofile)
78 print('', file=ofile)
79 print('crashbackups stop', file=ofile)
80 print('drc off', file=ofile)
81 print('snap internal', file=ofile)
82 print('load ' + layout_name + ' -dereference', file=ofile)
83 print('select top cell', file=ofile)
84 print('expand', file=ofile)
85 print('extract do local', file=ofile)
86 print('extract no all', file=ofile)
87 print('extract all', file=ofile)
88 print('antennacheck', file=ofile)
89
90 # Run the DRC Tcl script
91
92 ofile = open(output_file, 'w')
93 print('Antenna violation checks on cell ' + layout_name, file=ofile)
94 print('--------------------------------------------', file=ofile)
95
96 print('Running: magic -dnull -noconsole
97
98 mproc = subprocess.run(['magic', '-dnull', '-noconsole',
99 '-rcfile', rcfile, 'run_magic_antenna.tcl'],
100 env = myenv, cwd = magpath,
101 stdin = subprocess.DEVNULL, stdout = subprocess.PIPE,
102 stderr = subprocess.PIPE, universal_newlines = True)
103 if mproc.stdout:
104 for line in mproc.stdout.splitlines():
105 print(line)
106 print(line, file=ofile)
107 if mproc.stderr:
108 print('\nError message output from magic:')
109 print('\nError message output from magic:', file=ofile)
110 for line in mproc.stderr.splitlines():
111 print(line)
112 print(line, file=ofile)
113 if mproc.returncode != 0:
114 print('\nERROR: Magic exited with status ' + str(mproc.returncode))
115 print('\nERROR: Magic exited with status ' + str(mproc.returncode), file=ofile)
116
117 ofile.close()
118
119 print('Done!')
120
121# If called as main, run all DRC tests
122
123if __name__ == '__main__':
124
125 # Divide up command line into options and arguments
126 options = []
127 arguments = []
128 for item in sys.argv[1:]:
129 if item.find('-', 0) == 0:
130 options.append(item)
131 else:
132 arguments.append(item)
133
134 # Need one argument: path to layout
135 # If two arguments, then 2nd argument is the output file.
136
137 if len(arguments) > 0 and len(arguments) < 3:
138 layout_root = arguments[0]
139
140 if len(arguments) == 1:
141 out_filename = ""
142 elif len(arguments) > 1:
143 out_filename = arguments[1]
144
145 if len(arguments) > 0 and len(arguments) < 3:
146 run_antenna(layout_root, out_filename)
147 else:
148 print("Usage: check_antenna.py <layout_name> [<output_file>] [options]")
149 print("Options:")
150 print(" (none)")
151
152