-
Notifications
You must be signed in to change notification settings - Fork 3
/
set_lvs_env.py
executable file
·138 lines (117 loc) · 4.64 KB
/
set_lvs_env.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#! /usr/bin/env python3
"""
Create environment variables from a hierarchy of configuration files.
Return codes:
0: no error
2: file not found
3: invalid json
4. could not substitute environment variable
"""
import argparse
import logging
import subprocess
import os
import pprint
import sys
from pathlib import Path
from datetime import datetime
import json
import re
lvs_vars = [
'TOP_SOURCE',
'TOP_LAYOUT',
'LAYOUT_FILE',
'EXTRACT_FLATGLOB',
'EXTRACT_ABSTRACT',
'EXTRACT_CREATE_SUBCUT',
'EXTRACT_TYPE',
'LVS_FLATTEN',
'LVS_NOFLATTEN',
'LVS_IGNORE',
'LVS_SPICE_FILES_TO_FIX',
'LVS_SPICE_FILES',
'LVS_VERILOG_FILES'
]
def substitute_env_variables(input_string, env):
""" Return the string after replacing all environment variables ($varname) with the corresponding values from the environment.
Only handles simple variables $[A-Za-z0-9_]*. Does not handle ${varname}, $$, etc.
Missing variables are fatal errors.
"""
string = input_string
if "$" in string:
words = re.findall(r'\$\w+', string) # returns a list of all environment variables used.
for w in words:
env_var = w[1:] # remove leading '$'
if env_var in env:
string = string.replace(w, env.get(env_var), 1) # only replace first occurence. Others will be replaced later.
else:
print(f"ERROR: couldn't find environment variable {w} used in {input_string}", file=sys.stderr)
sys.exit(4)
return string
def parse_config_file(json_file, lvs_env):
""" Parses a json file which may reference other json files and uses the values to set environment variables.
List values are accumulated while scalar values are overwritten when processing sub files.
Duplicate list values are silently ignored.
json syntax errors are fatal errors.
"""
if not os.path.exists(f"{json_file}"):
print(f"ERROR: Could not find configuration file {json_file}", file=sys.stderr)
sys.exit(2)
print(f"Loading LVS environment from {json_file}", file=sys.stderr)
try:
with open(json_file, "r") as f:
data = json.load(f)
for key, value in data.items():
if type(value) == list:
exports = lvs_env[key].split() if key in lvs_env else [] # current environment list values
for val in value:
val = substitute_env_variables(val, lvs_env)
if val not in exports: # only add if not already in list
exports.append(val)
if key == 'INCLUDE_CONFIGS': # load child configs
lvs_env['INCLUDE_CONFIGS'] += " " + val # prevents loading same config twice
parse_config_file(val, lvs_env)
if key != 'INCLUDE_CONFIGS': # the value of the INCLUDE_CONFIGS key is already updated before the recursive call.
lvs_env[key] = ' '.join(exports)
else: # value is not a list. new value overrides any previous value.
value = substitute_env_variables(value, lvs_env)
lvs_env[key] = value
except Exception as err:
print(type(err), file=sys.stderr)
print(err.args, file=sys.stderr)
print(f"ERROR: with file {json_file}", file=sys.stderr)
sys.exit(3)
def clear_env(env, keys):
""" Clear any previous setting for keys in the environment.
"""
for key in keys:
if key in env:
del env[key]
print(f"unset {key}")
def print_env(env, keys):
""" Print assignment statements for keys in env.
"""
for key in keys:
if key in env:
print(f"export {key}='{env[key]}'")
#pprint.pprint({key: env[key]}, stream=sys.stderr)
else:
print(f"export {key}=")
#pprint.pprint({key: ''}, stream=sys.stderr)
def set_lvs_env(config_file, design_name):
""" Print a list of shell export commands to set LVS variables.
Any errors are fatal.
"""
lvs_env = os.environ.copy()
clear_env(lvs_env, lvs_vars)
lvs_env['INCLUDE_CONFIGS'] = f"{config_file}"
lvs_env['DESIGN_NAME'] = design_name
parse_config_file(config_file, lvs_env)
print_env(lvs_env, lvs_vars)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Creates the LVS environment')
parser.add_argument('--config_file', '-c', required=True, help='LVS config file')
parser.add_argument('--design_name', '-d', required=False, help='Top source override')
args = parser.parse_args()
config_file = Path(args.config_file)
set_lvs_env(config_file, args.design_name)