lambdapdk 0.1.56__py3-none-any.whl → 0.2.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,9 @@
1
+ from pathlib import Path
1
2
 
2
- import siliconcompiler
3
- from lambdapdk import register_data_source
3
+ from lambdapdk import LambdaPDK
4
4
 
5
5
 
6
- ####################################################
7
- # PDK Setup
8
- ####################################################
9
- def setup():
6
+ class _GF180PDK(LambdaPDK):
10
7
  '''
11
8
  The 'gf180' Open Source PDK is a collaboration between Google and
12
9
  Global Foundries to provide a fully open source Process
@@ -32,60 +29,104 @@ def setup():
32
29
 
33
30
  * https://github.com/google/gf180mcu-pdk
34
31
  '''
32
+ def __init__(self, stackup, libtype):
33
+ super().__init__()
34
+ self.set_name(f"GF180_{stackup}_{libtype}")
35
+
36
+ self.set_foundry("globalfoundries")
37
+ self.set_node(180)
38
+ self.set_stackup(stackup)
39
+ self.set_wafersize(200)
40
+
41
+ pdk_path = Path("lambdapdk", "gf180", "base")
35
42
 
36
- foundry = 'globalfoundries'
37
- process = 'gf180'
38
-
39
- node = 180
40
-
41
- pdkdir = "lambdapdk/gf180/base/"
42
-
43
- pdk = siliconcompiler.PDK(process, package='lambdapdk')
44
- register_data_source(pdk)
45
-
46
- # process name
47
- pdk.set('pdk', process, 'foundry', foundry)
48
- pdk.set('pdk', process, 'node', node)
49
- pdk.set('pdk', process, 'wafersize', 200)
50
-
51
- for stackup in ("3LM_1TM_6K",
52
- "3LM_1TM_9K",
53
- "3LM_1TM_11K",
54
- "3LM_1TM_30K",
55
- "4LM_1TM_6K",
56
- "4LM_1TM_9K",
57
- "4LM_1TM_11K",
58
- "4LM_1TM_30K",
59
- "5LM_1TM_9K",
60
- "5LM_1TM_11K",
61
- "6LM_1TM_9K"):
62
- pdk.add('pdk', process, 'stackup', stackup)
63
- for libtype in ("7t", "9t"):
64
- # APR Setup
65
- for tool in ('openroad', 'klayout', 'magic'):
66
- pdk.set('pdk', process, 'aprtech', tool, stackup, libtype, 'lef',
67
- pdkdir + f'/apr/gf180mcu_{stackup}_{libtype}_tech.lef')
68
- if stackup in ('6LM_1TM_9K', '5LM_1TM_9K'):
69
- pdk.set('pdk', process, 'layermap', 'klayout', 'def', 'gds', stackup,
70
- pdkdir + f'/apr/gf180mcu_{stackup}_9t_edi2gds.layermap')
71
43
  max_layer = int(stackup[0])
72
44
 
73
- pdk.set('pdk', process, 'minlayer', stackup, 'Metal1')
74
- pdk.set('pdk', process, 'maxlayer', stackup, f'Metal{max_layer}')
45
+ with self.active_dataroot("lambdapdk"):
46
+ # APR Setup
47
+ with self.active_fileset("views.lef"):
48
+ self.add_file(pdk_path / "apr" / f"gf180mcu_{stackup}_{libtype}_tech.lef")
49
+ for tool in ('openroad', 'klayout', 'magic'):
50
+ self.add_aprtechfileset(tool)
51
+
52
+ self.set_aprroutinglayers(min="metal2", max="metal7")
53
+
54
+ if stackup in ('6LM_1TM_9K', '5LM_1TM_9K'):
55
+ with self.active_fileset("layermap"):
56
+ self.add_file(pdk_path / "apr" / f"gf180mcu_{stackup}_9t_edi2gds.layermap",
57
+ filetype="layermap")
58
+ self.add_layermapfileset("klayout", "def", "gds")
59
+
60
+ with self.active_fileset("models.spice"):
61
+ self.add_file(pdk_path / "spice" / "xyce" / "design.xyce", filetype="xyce")
62
+ self.add_file(pdk_path / "spice" / "xyce" / "sm141064.xyce", filetype="xyce")
63
+ self.add_file(pdk_path / "spice" / "xyce" / "smbb000149.xyce", filetype="xyce")
64
+ self.add_devmodelfileset("xyce", "spice")
65
+
66
+ self.set_aprroutinglayers(min="Metal1", max=f"Metal{max_layer}")
67
+
68
+ # Klayout setup
69
+ with self.active_dataroot("lambdapdk"), self.active_fileset("klayout.techmap"):
70
+ self.add_file(pdk_path / "setup" / "klayout" / "tech" / "gf180mcu.lyt",
71
+ filetype="layermap")
72
+ self.add_file(pdk_path / "setup" / "klayout" / "tech" / "gf180mcu.lyp",
73
+ filetype="display")
74
+ self.add_layermapfileset("klayout", "def", "klayout")
75
+ self.add_displayfileset("klayout")
76
+
77
+ # KLayout DRC
78
+ metal_level, _, metal_top = stackup.split('_')
79
+ drcs = {
80
+ "drc": pdk_path / "setup" / "klayout" / "drc" / "gf180mcu.drc",
81
+ "drc_feol": pdk_path / "setup" / "klayout" / "drc" / "gf180mcu.drc",
82
+ "drc_beol": pdk_path / "setup" / "klayout" / "drc" / "gf180mcu.drc",
83
+ "antenna": pdk_path / "setup" / "klayout" / "drc" / "gf180mcu_antenna.drc",
84
+ "density": pdk_path / "setup" / "klayout" / "drc" / "gf180mcu_density.drc"
85
+ }
86
+ for drc, runset in drcs.items():
87
+ with self.active_dataroot("lambdapdk"), self.active_fileset(f"klayout.drc.{drc}"):
88
+ self.add_file(runset, filetype="drc")
89
+ self.add_runsetfileset("drc", "klayout", drc)
90
+
91
+ self.add_klayout_drcparam(drc, "input=<input>")
92
+ self.add_klayout_drcparam(drc, "topcell=<topcell>")
93
+ self.add_klayout_drcparam(drc, "thr=<threads>")
94
+ self.add_klayout_drcparam(drc, "run_mode=flat")
95
+ self.add_klayout_drcparam(drc, "offgrid=true")
96
+
97
+ if drc in ("drc", "drc_feol", "drc_beol"):
98
+ feol = "true"
99
+ beol = "true"
100
+ if drc == "drc_feol":
101
+ beol = "false"
102
+ if drc == "drc_beol":
103
+ feol = "false"
104
+
105
+ self.add_klayout_drcparam(drc, f"feol={feol}")
106
+ self.add_klayout_drcparam(drc, f"beol={beol}")
107
+
108
+ self.add_klayout_drcparam(drc, f"metal_top={metal_top}")
109
+ self.add_klayout_drcparam(drc, f"metal_level={metal_level}")
110
+ if max_layer == 3:
111
+ self.add_klayout_drcparam(drc, "mim_option=A")
112
+ elif max_layer == 4 or max_layer == 5:
113
+ self.add_klayout_drcparam(drc, "mim_option=B")
114
+
115
+ self.add_klayout_hidelayers('Dualgate')
116
+ self.add_klayout_hidelayers('V5_XTOR')
117
+ self.add_klayout_hidelayers('PR_bndry')
75
118
 
76
- # Layer map and display file
77
- pdk.set('pdk', process, 'layermap', 'klayout', 'def', 'klayout', stackup,
78
- pdkdir + '/setup/klayout/tech/gf180mcu.lyt')
79
- pdk.set('pdk', process, 'display', 'klayout', stackup,
80
- pdkdir + '/setup/klayout/tech/gf180mcu.lyp')
119
+ # OpenROAD setup
81
120
 
82
- # Device models
83
- pdk.add('pdk', process, 'devmodel', 'xyce', 'spice', stackup,
84
- pdkdir + '/spice/xyce/design.xyce')
85
- pdk.add('pdk', process, 'devmodel', 'xyce', 'spice', stackup,
86
- pdkdir + '/spice/xyce/sm141064.xyce')
87
- pdk.add('pdk', process, 'devmodel', 'xyce', 'spice', stackup,
88
- pdkdir + '/spice/xyce/smbb000149.xyce')
121
+ if max_layer == 3:
122
+ self.set_openroad_rclayers(signal="Metal2", clock="Metal2")
123
+ self.add_openroad_pinlayers(vertical="Metal2", horizontal="Metal3")
124
+ elif max_layer == 4:
125
+ self.set_openroad_rclayers(signal="Metal2", clock="Metal3")
126
+ self.add_openroad_pinlayers(vertical="Metal4", horizontal="Metal3")
127
+ elif max_layer >= 5:
128
+ self.set_openroad_rclayers(signal="Metal3", clock="Metal4")
129
+ self.add_openroad_pinlayers(vertical="Metal4", horizontal="Metal3")
89
130
 
90
131
  # Openroad global routing grid derating
91
132
  openroad_layer_adjustments = {
@@ -98,89 +139,134 @@ def setup():
98
139
  'MetalTop': 1.0
99
140
  }
100
141
  for layer, adj in openroad_layer_adjustments.items():
101
- pdk.set('pdk', process, 'var', 'openroad', f'{layer}_adjustment', stackup, str(adj))
102
- if layer == pdk.get('pdk', process, 'maxlayer', stackup):
142
+ self.set_openroad_globalroutingderating(layer, adj)
143
+ if layer == f"Metal{max_layer}":
103
144
  break
104
145
 
105
- if max_layer == 3:
106
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_signal', stackup, 'Metal2')
107
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_clock', stackup, 'Metal2')
146
+ # PEX
147
+ with self.active_dataroot("lambdapdk"):
148
+ for corner in ["bst", "typ", "wst"]:
149
+ if stackup in ('3LM_1TM_6K', '3LM_1TM_9K', '3LM_1TM_11K', '3LM_1TM_30K',
150
+ '4LM_1TM_6K'):
151
+ continue
108
152
 
109
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_vertical', stackup, 'Metal2')
110
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_horizontal', stackup, 'Metal3')
111
- elif max_layer == 4:
112
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_signal', stackup, 'Metal2')
113
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_clock', stackup, 'Metal3')
153
+ base_name = f'gf180mcu_1p{stackup.replace("L", "").lower()}_sp_smim_OPTB_{corner}'
114
154
 
115
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_vertical', stackup, 'Metal4')
116
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_horizontal', stackup, 'Metal3')
117
- elif max_layer >= 5:
118
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_signal', stackup, 'Metal3')
119
- pdk.set('pdk', process, 'var', 'openroad', 'rclayer_clock', stackup, 'Metal4')
155
+ with self.active_fileset(f"openroad.pex.{corner}"):
156
+ self.add_file(pdk_path / "pex" / "openroad" / f"{base_name}.tcl",
157
+ filetype="tcl")
158
+ self.add_file(pdk_path / "pex" / "openroad" / f"{base_name}.rules",
159
+ filetype="openrcx")
120
160
 
121
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_vertical', stackup, 'Metal4')
122
- pdk.set('pdk', process, 'var', 'openroad', 'pin_layer_horizontal', stackup, 'Metal3')
161
+ self.add_pexmodelfileset("openroad", "typical")
162
+ self.add_pexmodelfileset("openroad-openrcx", "typical")
123
163
 
124
- # PEX
125
- for corner in ["bst", "typ", "wst"]:
126
- if stackup in ('3LM_1TM_6K', '3LM_1TM_9K', '3LM_1TM_11K', '3LM_1TM_30K', '4LM_1TM_6K'):
127
- continue
128
- base_name = f'gf180mcu_1p{stackup.replace("L", "").lower()}_sp_smim_OPTB_{corner}'
129
- pdk.set('pdk', process, 'pexmodel', 'openroad', stackup, corner,
130
- pdkdir + '/pex/openroad/' + base_name + '.tcl')
131
- pdk.set('pdk', process, 'pexmodel', 'openroad-openrcx', stackup, corner,
132
- pdkdir + '/pex/openroad/' + base_name + '.rules')
133
-
134
- # DRC
135
- metal_level, _, metal_top = stackup.split('_')
136
- drcs = {
137
- "drc": pdkdir + '/setup/klayout/drc/gf180mcu.drc',
138
- "drc_feol": pdkdir + '/setup/klayout/drc/gf180mcu.drc',
139
- "drc_beol": pdkdir + '/setup/klayout/drc/gf180mcu.drc',
140
- "antenna": pdkdir + '/setup/klayout/drc/gf180mcu_antenna.drc',
141
- "density": pdkdir + '/setup/klayout/drc/gf180mcu_density.drc'
142
- }
143
- for drc, runset in drcs.items():
144
- pdk.set('pdk', process, 'drc', 'runset', 'klayout', stackup, drc, runset)
145
-
146
- key = f'drc_params:{drc}'
147
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'input=<input>')
148
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'topcell=<topcell>')
149
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'report=<report>')
150
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'thr=<threads>')
151
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'run_mode=flat')
152
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'offgrid=true')
153
-
154
- if drc in ('drc', 'drc_feol', 'drc_beol'):
155
- feol = 'true'
156
- beol = 'true'
157
- if drc == 'drc_feol':
158
- beol = 'false'
159
- if drc == 'drc_beol':
160
- feol = 'false'
161
- pdk.add('pdk', process, 'var', 'klayout', stackup, key,
162
- f'feol={feol}')
163
- pdk.add('pdk', process, 'var', 'klayout', stackup, key,
164
- f'beol={beol}')
165
-
166
- pdk.add('pdk', process, 'var', 'klayout', stackup, key,
167
- f'metal_top={metal_top}')
168
- pdk.add('pdk', process, 'var', 'klayout', stackup, key,
169
- f'metal_level={metal_level}')
170
- if max_layer == 3:
171
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'mim_option=A')
172
- elif max_layer == 4 or max_layer == 5:
173
- pdk.add('pdk', process, 'var', 'klayout', stackup, key, 'mim_option=B')
174
164
 
175
- pdk.add('pdk', process, 'var', 'klayout', 'hide_layers', stackup, 'Dualgate')
176
- pdk.add('pdk', process, 'var', 'klayout', 'hide_layers', stackup, 'V5_XTOR')
177
- pdk.add('pdk', process, 'var', 'klayout', 'hide_layers', stackup, 'PR_bndry')
165
+ class GF180_3LM_1TM_6K_7t(_GF180PDK):
166
+ def __init__(self):
167
+ super().__init__("3LM_1TM_6K", "7t")
168
+
169
+
170
+ class GF180_3LM_1TM_6K_9t(_GF180PDK):
171
+ def __init__(self):
172
+ super().__init__("3LM_1TM_6K", "9t")
173
+
174
+
175
+ class GF180_3LM_1TM_9K_7t(_GF180PDK):
176
+ def __init__(self):
177
+ super().__init__("3LM_1TM_9K", "7t")
178
+
179
+
180
+ class GF180_3LM_1TM_9K_9t(_GF180PDK):
181
+ def __init__(self):
182
+ super().__init__("3LM_1TM_9K", "9t")
183
+
184
+
185
+ class GF180_3LM_1TM_11K_7t(_GF180PDK):
186
+ def __init__(self):
187
+ super().__init__("3LM_1TM_11K", "7t")
188
+
189
+
190
+ class GF180_3LM_1TM_11K_9t(_GF180PDK):
191
+ def __init__(self):
192
+ super().__init__("3LM_1TM_11K", "9t")
193
+
194
+
195
+ class GF180_3LM_1TM_30K_7t(_GF180PDK):
196
+ def __init__(self):
197
+ super().__init__("3LM_1TM_30K", "7t")
198
+
199
+
200
+ class GF180_3LM_1TM_30K_9t(_GF180PDK):
201
+ def __init__(self):
202
+ super().__init__("3LM_1TM_30K", "9t")
203
+
204
+
205
+ class GF180_4LM_1TM_6K_7t(_GF180PDK):
206
+ def __init__(self):
207
+ super().__init__("4LM_1TM_6K", "7t")
208
+
209
+
210
+ class GF180_4LM_1TM_6K_9t(_GF180PDK):
211
+ def __init__(self):
212
+ super().__init__("4LM_1TM_6K", "9t")
213
+
214
+
215
+ class GF180_4LM_1TM_9K_7t(_GF180PDK):
216
+ def __init__(self):
217
+ super().__init__("4LM_1TM_9K", "7t")
218
+
219
+
220
+ class GF180_4LM_1TM_9K_9t(_GF180PDK):
221
+ def __init__(self):
222
+ super().__init__("4LM_1TM_9K", "9t")
223
+
224
+
225
+ class GF180_4LM_1TM_11K_7t(_GF180PDK):
226
+ def __init__(self):
227
+ super().__init__("4LM_1TM_11K", "7t")
228
+
229
+
230
+ class GF180_4LM_1TM_11K_9t(_GF180PDK):
231
+ def __init__(self):
232
+ super().__init__("4LM_1TM_11K", "9t")
233
+
234
+
235
+ class GF180_4LM_1TM_30K_7t(_GF180PDK):
236
+ def __init__(self):
237
+ super().__init__("4LM_1TM_30K", "7t")
238
+
239
+
240
+ class GF180_4LM_1TM_30K_9t(_GF180PDK):
241
+ def __init__(self):
242
+ super().__init__("4LM_1TM_30K", "9t")
243
+
244
+
245
+ class GF180_5LM_1TM_9K_7t(_GF180PDK):
246
+ def __init__(self):
247
+ super().__init__("5LM_1TM_9K", "7t")
248
+
249
+
250
+ class GF180_5LM_1TM_9K_9t(_GF180PDK):
251
+ def __init__(self):
252
+ super().__init__("5LM_1TM_9K", "9t")
253
+
254
+
255
+ class GF180_5LM_1TM_11K_7t(_GF180PDK):
256
+ def __init__(self):
257
+ super().__init__("5LM_1TM_11K", "7t")
258
+
259
+
260
+ class GF180_5LM_1TM_11K_9t(_GF180PDK):
261
+ def __init__(self):
262
+ super().__init__("5LM_1TM_11K", "9t")
263
+
178
264
 
179
- return pdk
265
+ class GF180_6LM_1TM_9K_7t(_GF180PDK):
266
+ def __init__(self):
267
+ super().__init__("6LM_1TM_9K", "7t")
180
268
 
181
269
 
182
- #########################
183
- if __name__ == "__main__":
184
- pdk = setup()
185
- pdk.write_manifest(f'{pdk.top()}.json')
186
- pdk.check_filepaths()
270
+ class GF180_6LM_1TM_9K_9t(_GF180PDK):
271
+ def __init__(self):
272
+ super().__init__("6LM_1TM_9K", "9t")
@@ -1,73 +1,108 @@
1
- import os
2
- import siliconcompiler
3
- from lambdapdk import register_data_source
1
+ from pathlib import Path
4
2
 
3
+ from lambdapdk import LambdaLibrary
4
+ from lambdapdk.gf180 import GF180_3LM_1TM_6K_7t, \
5
+ GF180_3LM_1TM_6K_9t, \
6
+ GF180_3LM_1TM_9K_7t, \
7
+ GF180_3LM_1TM_9K_9t, \
8
+ GF180_3LM_1TM_11K_7t, \
9
+ GF180_3LM_1TM_11K_9t, \
10
+ GF180_3LM_1TM_30K_7t, \
11
+ GF180_3LM_1TM_30K_9t, \
12
+ GF180_4LM_1TM_6K_7t, \
13
+ GF180_4LM_1TM_6K_9t, \
14
+ GF180_4LM_1TM_9K_7t, \
15
+ GF180_4LM_1TM_9K_9t, \
16
+ GF180_4LM_1TM_11K_7t, \
17
+ GF180_4LM_1TM_11K_9t, \
18
+ GF180_4LM_1TM_30K_7t, \
19
+ GF180_4LM_1TM_30K_9t, \
20
+ GF180_5LM_1TM_9K_7t, \
21
+ GF180_5LM_1TM_9K_9t, \
22
+ GF180_5LM_1TM_11K_7t, \
23
+ GF180_5LM_1TM_11K_9t
5
24
 
6
- def setup():
25
+
26
+ class _GF180IOLibrary(LambdaLibrary):
7
27
  '''
8
28
  GloabalFoundries 180 I/O library.
9
29
  '''
10
- libdir = "lambdapdk/gf180/libs/gf180mcu_fd_io/"
11
-
12
- libs = []
13
- for substack in ("3LM", "4LM", "5LM"):
14
- lib = siliconcompiler.Library(f'gf180mcu_fd_io_{substack}', package='lambdapdk')
15
- register_data_source(lib)
16
-
17
- # pdk
18
- lib.set('option', 'pdk', 'gf180')
19
-
20
- lib.set('output', 'slow', 'nldm',
21
- os.path.join(libdir, 'nldm/gf180mcu_fd_io__ss_125C_2v97.lib.gz'))
22
- lib.set('output', 'typical', 'nldm',
23
- os.path.join(libdir, 'nldm/gf180mcu_fd_io__tt_025C_3v30.lib.gz'))
24
- lib.set('output', 'fast', 'nldm',
25
- os.path.join(libdir, 'nldm/gf180mcu_fd_io__ff_125C_3v63.lib.gz'))
26
-
27
- for corner in ('slow', 'typical', 'fast'):
28
- lib.set('output', corner, 'spice',
29
- os.path.join(libdir, f'spice/{substack}/gf180mcu_fd_io.spice'))
30
-
31
- for stackup in ("3LM_1TM_6K",
32
- "3LM_1TM_9K",
33
- "3LM_1TM_11K",
34
- "3LM_1TM_30K",
35
- "4LM_1TM_6K",
36
- "4LM_1TM_9K",
37
- "4LM_1TM_11K",
38
- "4LM_1TM_30K",
39
- "5LM_1TM_9K",
40
- "5LM_1TM_11K"):
41
- stackup_start = stackup[0:3]
42
- if substack != stackup_start:
43
- continue
44
- lib.set('output', stackup, 'lef',
45
- os.path.join(libdir, f'lef/{stackup_start}/gf180mcu_fd_io.lef'))
46
- lib.set('output', stackup, 'cdl', os.path.join(libdir, 'cdl/gf180mcu_fd_io.cdl'))
47
-
48
- lib.add('output', stackup, 'gds',
49
- os.path.join(libdir, f'gds/{stackup_start}/gf180mcu_fd_io.gds.gz'))
50
-
51
- lib.set('asic', 'cells', 'filler', ['gf180mcu_fd_io__fill1',
52
- 'gf180mcu_fd_io__fill5',
53
- 'gf180mcu_fd_io__fill10',
54
- 'gf180mcu_fd_io__fillnc'])
55
-
56
- lib.set('output', 'blackbox', 'verilog',
57
- os.path.join(libdir, 'blackbox', f'{stackup_start}.v'))
58
-
59
- libs.append(lib)
60
-
61
- lambda_lib = siliconcompiler.Library('lambdalib_gf180mcu_fd_io', package='lambdapdk')
62
- register_data_source(lambda_lib)
63
- lambda_lib.add('option', 'ydir', 'lambdapdk/gf180/libs/gf180mcu_fd_io/lambda')
64
- lambda_lib.use(lib)
65
- lambda_lib.set('asic', 'macrolib', lib.design)
66
-
67
- return [*libs, lambda_lib]
68
-
69
-
70
- #########################
71
- if __name__ == "__main__":
72
- for lib in setup(siliconcompiler.Chip('<lib>')):
73
- lib.write_manifest(f'{lib.top()}.json')
30
+ def __init__(self, stackup):
31
+ super().__init__()
32
+ self.set_name(f"gf180mcu_fd_io_{stackup}")
33
+
34
+ path_base = Path("lambdapdk", "gf180", "libs", "gf180mcu_fd_io")
35
+
36
+ if stackup == "3LM":
37
+ self.add_asic_pdk(GF180_3LM_1TM_6K_7t(), default=False)
38
+ self.add_asic_pdk(GF180_3LM_1TM_6K_9t(), default=False)
39
+ self.add_asic_pdk(GF180_3LM_1TM_9K_7t(), default=False)
40
+ self.add_asic_pdk(GF180_3LM_1TM_9K_9t(), default=False)
41
+ self.add_asic_pdk(GF180_3LM_1TM_11K_7t(), default=False)
42
+ self.add_asic_pdk(GF180_3LM_1TM_11K_9t(), default=False)
43
+ self.add_asic_pdk(GF180_3LM_1TM_30K_7t(), default=False)
44
+ self.add_asic_pdk(GF180_3LM_1TM_30K_9t(), default=False)
45
+ elif stackup == "4LM":
46
+ self.add_asic_pdk(GF180_4LM_1TM_6K_7t(), default=False)
47
+ self.add_asic_pdk(GF180_4LM_1TM_6K_9t(), default=False)
48
+ self.add_asic_pdk(GF180_4LM_1TM_9K_7t(), default=False)
49
+ self.add_asic_pdk(GF180_4LM_1TM_9K_9t(), default=False)
50
+ self.add_asic_pdk(GF180_4LM_1TM_11K_7t(), default=False)
51
+ self.add_asic_pdk(GF180_4LM_1TM_11K_9t(), default=False)
52
+ self.add_asic_pdk(GF180_4LM_1TM_30K_7t(), default=False)
53
+ self.add_asic_pdk(GF180_4LM_1TM_30K_9t(), default=False)
54
+ elif stackup == "5LM":
55
+ self.add_asic_pdk(GF180_5LM_1TM_9K_7t(), default=False)
56
+ self.add_asic_pdk(GF180_5LM_1TM_9K_9t(), default=False)
57
+ self.add_asic_pdk(GF180_5LM_1TM_11K_7t(), default=False)
58
+ self.add_asic_pdk(GF180_5LM_1TM_11K_9t(), default=False)
59
+ else:
60
+ raise ValueError(f"{stackup} is not supported")
61
+
62
+ with self.active_dataroot("lambdapdk"):
63
+ for corner_name, filename in [
64
+ ('slow', 'gf180mcu_fd_io__ss_125C_2v97.lib.gz'),
65
+ ('typical', 'gf180mcu_fd_io__tt_025C_3v30.lib.gz'),
66
+ ('fast', 'gf180mcu_fd_io__ff_125C_3v63.lib.gz')]:
67
+ with self.active_fileset(f"models.timing.{corner_name}.nldm"):
68
+ self.add_file(path_base / "nldm" / filename)
69
+ self.add_asic_libcornerfileset(corner_name, "nldm")
70
+
71
+ with self.active_fileset("models.spice"):
72
+ self.add_file(path_base / "spice" / stackup / "gf180mcu_fd_io.spice")
73
+
74
+ with self.active_dataroot("lambdapdk"):
75
+ with self.active_fileset("models.physical"):
76
+ self.add_file(path_base / "lef" / stackup / "gf180mcu_fd_io.lef")
77
+ self.add_file(path_base / "gds" / stackup / "gf180mcu_fd_io.gds.gz")
78
+ self.add_asic_aprfileset()
79
+
80
+ with self.active_fileset("models.lvs"):
81
+ self.add_file(path_base / "cdl" / "gf180mcu_fd_io.cdl")
82
+ self.add_asic_aprfileset()
83
+
84
+ self.add_asic_celllist("filler", [
85
+ 'gf180mcu_fd_io__fill1',
86
+ 'gf180mcu_fd_io__fill5',
87
+ 'gf180mcu_fd_io__fill10',
88
+ 'gf180mcu_fd_io__fillnc'])
89
+
90
+ with self.active_dataroot("lambdapdk"):
91
+ with self.active_fileset("models.blackbox"):
92
+ self.add_file(path_base / "blackbox" / f"{stackup}.v")
93
+ self.add_yosys_blackbox_fileset("models.blackbox")
94
+
95
+
96
+ class GF180_IO_3LM(_GF180IOLibrary):
97
+ def __init__(self):
98
+ super().__init__("3LM")
99
+
100
+
101
+ class GF180_IO_4LM(_GF180IOLibrary):
102
+ def __init__(self):
103
+ super().__init__("4LM")
104
+
105
+
106
+ class GF180_IO_5LM(_GF180IOLibrary):
107
+ def __init__(self):
108
+ super().__init__("5LM")