blob: 1c0e44af9ef039741351b4448ba7767b66fa4c86 [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 parameters for process variation.
7#--------------------------------------------------------------------
8
9import os
10import re
11import sys
12
13pr_switch_param = 'MC_PR_SWITCH'
14
15walkpath = 'sky130A/libs.tech/ngspice'
16
17if len(sys.argv) > 1:
18 walkpath = sys.argv[1]
19
20process_params = []
21
22parmrex = re.compile('^\.param[ \t]+')
23prrex = re.compile('^\*[ \t]*process[ \t]+\{')
24endrex = re.compile('^\*[ \t]*\}')
25
26filelist = []
27
28#--------------------------------------------------------------------
29# Step 1. Gather variables
30#--------------------------------------------------------------------
31
32for dirpath, dirnames, filenames in os.walk(walkpath):
33 for filename in filenames:
34 if os.path.splitext(filename)[1] == '.spice':
35 infile_name = os.path.join(dirpath, filename)
36 filelist.append(infile_name)
37
38 infile = open(infile_name, 'r')
39
40 state = 'before_process'
41 line_number = 0
42 replaced_something = False
43
44 for line in infile:
45 line_number += 1
46
47 if state == 'before_process':
48 pmatch = prrex.match(line)
49 if pmatch:
50 state = 'in_process'
51 elif state == 'in_process':
52 ematch = endrex.match(line)
53 if ematch:
54 state = 'after_process'
55 else:
56 tokens = line.split()
57 if 'vary' in tokens:
58 if ('dist=gauss' in tokens) or ('gauss' in tokens):
59 process_param = tokens[2]
Tim Edwards33ce97a2021-05-24 20:51:28 -040060 std_dev = float(tokens[-1].split('=')[-1])
61 replacement = ' + {}*AGAUSS(0,{!s},1)'.format(pr_switch_param, std_dev)
Tim Edwards9fdf5f02021-05-03 16:15:03 -040062 process_params.append((process_param, replacement))
63
64 infile.close()
65
Tim Edwards41000e62021-05-24 16:27:22 -040066# Sort the process parameters so that names that are subsets of other
67# names appear later in the list.
68
69def getKey(item):
70 return item[0]
71
72process_params.sort(reverse=True, key=getKey)
73
Tim Edwards9fdf5f02021-05-03 16:15:03 -040074print('')
75print('Process parameters found:')
76for (process_param, addendum) in process_params:
77 print(process_param + ' :' + addendum)
78print('')
79
80#--------------------------------------------------------------------
81# Step 2. Make replacements
82#--------------------------------------------------------------------
83
84for infile_name in filelist:
85
86 filepath = os.path.split(infile_name)[0]
87 outfile_name = os.path.join(filepath, 'temp')
88
89 infile = open(infile_name, 'r')
90 outfile = open(outfile_name, 'w')
91
92 state = 'before_process'
93 line_number = 0
94 replaced_something = False
95
96 for line in infile:
97 line_number += 1
98
99 if state == 'before_process':
100 pmatch = prrex.match(line)
101 if pmatch:
102 state = 'in_process'
103 outfile.write(line)
104 else:
105 pmatch = parmrex.match(line)
106 if pmatch:
107 newline = line
108 for (param, replacement) in process_params:
Tim Edwards41000e62021-05-24 16:27:22 -0400109 if ' ' + param + ' ' in newline:
Tim Edwards33ce97a2021-05-24 20:51:28 -0400110 newline = newline.strip('\n') + replacement + '\n'
111 print(" Line {}: Found process parameter '{}' and appended '{}'.".format(line_number, param, replacement))
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400112 replaced_something = True
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400113 outfile.write(newline)
114 else:
115 outfile.write(line)
116 elif state == 'in_process':
117 outfile.write(line)
118 ematch = endrex.match(line)
119 if ematch:
120 state = 'after_process'
121 elif state == 'after_process':
122 outfile.write(line)
123
124 infile.close()
125 outfile.close()
126 if replaced_something:
Tim Edwards00bfca52021-05-04 10:48:46 -0400127 # print("Something was replaced in '{}', backed up original file"
128 # + " and replaced with processed one.".format(infile_name))
129 print("Something was replaced in '{}'".format(infile_name))
130 # os.rename(infile_name, infile_name + '.orig')
Tim Edwards9fdf5f02021-05-03 16:15:03 -0400131 os.rename(outfile_name, infile_name)
132 else:
133 print("Nothing was replaced in '{}'.".format(infile_name))
134 os.remove(outfile_name)
135