blob: b6616d73f0e60d5bf8e36036deada52fb5eff7bf [file] [log] [blame]
Tim Edwards9fdf5f02021-05-03 16:15:03 -04001#!/usr/bin/env python3
2#
3#--------------------------------------------------------------------
4# Parse the SPICE model files from sky130 and use the (commented out)
5# statistics block to generate the correct monte carlo expressions
6# in the device models for mismatch.
7#--------------------------------------------------------------------
8
9import os
10import re
11import sys
12
13mm_switch_param = 'MC_MM_SWITCH'
14
15walkpath = 'sky130A/libs.ref/sky130_fd_pr/spice'
16
17if len(sys.argv) > 1:
18 walkpath = sys.argv[1]
19
20mismatch_params = []
21
22mmrex = re.compile('^\*[ \t]*mismatch[ \t]+\{')
23endrex = re.compile('^\*[ \t]*\}')
24
25filelist = []
26
27#--------------------------------------------------------------------
28# Step 1. Gather variables
29#--------------------------------------------------------------------
30
31for dirpath, dirnames, filenames in os.walk(walkpath):
32 for filename in filenames:
33 if os.path.splitext(filename)[1] == '.spice':
34 infile_name = os.path.join(dirpath, filename)
35 filelist.append(infile_name)
36
37 infile = open(infile_name, 'r')
38
39 state = 'before_mismatch'
40 line_number = 0
41 replaced_something = False
42
43 for line in infile:
44 line_number += 1
45
46 if state == 'before_mismatch':
47 mmatch = mmrex.match(line)
48 if mmatch:
49 state = 'in_mismatch'
50 elif state == 'in_mismatch':
51 ematch = endrex.match(line)
52 if ematch:
53 state = 'after_mismatch'
54 else:
55 tokens = line.split()
56 if 'vary' in tokens:
57 if ('dist=gauss' in tokens) or ('gauss' in tokens):
58 mismatch_param = tokens[2]
59 std_dev = float(tokens[-1].split('=')[-1])
60 replacement = '{}*AGAUSS(0,{!s},1)'.format(mm_switch_param, std_dev)
61 mismatch_params.append((mismatch_param, replacement))
62
63 infile.close()
64
65print('')
66print('Mismatch parameters found:')
67for (mismatch_param, replacement) in mismatch_params:
68 print(mismatch_param + ' : ' + replacement)
69print('')
70
71#--------------------------------------------------------------------
Tim Edwards1c74f852021-06-09 16:46:50 -040072# Create regexp for the alternative PSPICE "dev/gauss" syntax used in
73# a number of places in the models.
74#--------------------------------------------------------------------
75
76gaussrex = re.compile('\'[ \t]+dev\/gauss=\'', re.IGNORECASE)
77
78#--------------------------------------------------------------------
Tim Edwards9fdf5f02021-05-03 16:15:03 -040079# Step 2. Make replacements
80#--------------------------------------------------------------------
81
82for infile_name in filelist:
83
84 filepath = os.path.split(infile_name)[0]
85 outfile_name = os.path.join(filepath, 'temp')
86
87 infile = open(infile_name, 'r')
88 outfile = open(outfile_name, 'w')
89
90 state = 'before_mismatch'
91 line_number = 0
92 replaced_something = False
93
94 for line in infile:
95 line_number += 1
Tim Edwards1c74f852021-06-09 16:46:50 -040096 newline = line
97
98 gmatch = gaussrex.search(newline)
99 if gmatch:
100 newline = gaussrex.sub('+' + mm_switch_param + '*AGAUSS(0,1.0,1)*', newline)
101 replaced_something = True
102 print(" Line {}: Found PSPICE dev/gauss and replaced.".format(line_number))
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400103
104 if state == 'before_mismatch':
Tim Edwards1c74f852021-06-09 16:46:50 -0400105 outfile.write(newline)
106 mmatch = mmrex.match(newline)
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400107 if mmatch:
108 state = 'in_mismatch'
109 elif state == 'in_mismatch':
Tim Edwards1c74f852021-06-09 16:46:50 -0400110 outfile.write(newline)
111 ematch = endrex.match(newline)
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400112 if ematch:
113 state = 'after_mismatch'
114 elif state == 'after_mismatch':
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400115 for (param, replacement) in mismatch_params:
116 if param in newline:
117 newline = newline.replace(param, replacement)
118 replaced_something = True
119 print(" Line {}: Found mismatch parameter '{}' and replaced with '{}'.".format(line_number, param, replacement))
120 outfile.write(newline)
121
122 infile.close()
123 outfile.close()
124 if replaced_something:
Tim Edwards00bfca52021-05-04 10:48:46 -0400125 # print("Something was replaced in '{}', backed up original file"
126 # + " and replaced with processed one.".format(infile_name))
127 print("Something was replaced in '{}'.".format(infile_name))
128 # os.rename(infile_name, infile_name + '.orig')
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400129 os.rename(outfile_name, infile_name)
130 else:
131 print("Nothing was replaced in '{}'.".format(infile_name))
132 os.remove(outfile_name)
133