pyedb 0.10.0__py3-none-any.whl → 0.11.0__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.
Potentially problematic release.
This version of pyedb might be problematic. Click here for more details.
- pyedb/__init__.py +1 -1
- pyedb/configuration/cfg_boundaries.py +115 -0
- pyedb/configuration/cfg_components.py +205 -0
- pyedb/configuration/cfg_data.py +38 -15
- pyedb/configuration/cfg_general.py +34 -0
- pyedb/{dotnet/sim_setup_data/data/siw_dc_ir_settings.py → configuration/cfg_nets.py} +18 -21
- pyedb/configuration/cfg_padstacks.py +125 -0
- pyedb/configuration/cfg_pin_groups.py +58 -0
- pyedb/configuration/cfg_ports_sources.py +164 -0
- pyedb/configuration/cfg_s_parameter_models.py +60 -0
- pyedb/configuration/cfg_setup.py +201 -0
- pyedb/configuration/cfg_spice_models.py +49 -0
- pyedb/configuration/configuration.py +37 -532
- pyedb/dotnet/edb.py +32 -4
- pyedb/dotnet/edb_core/components.py +43 -0
- pyedb/dotnet/edb_core/edb_data/hfss_pi_simulation_setup_data.py +465 -0
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +17 -1
- pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py +0 -4
- pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +4 -2
- pyedb/dotnet/edb_core/edb_data/sources.py +21 -5
- pyedb/dotnet/edb_core/edb_data/terminals.py +2 -1
- pyedb/dotnet/edb_core/layout.py +13 -8
- pyedb/dotnet/edb_core/padstack.py +23 -3
- pyedb/dotnet/edb_core/sim_setup_data/__init__.py +3 -0
- pyedb/dotnet/edb_core/sim_setup_data/data/__init__.py +3 -0
- pyedb/dotnet/edb_core/sim_setup_data/data/siw_dc_ir_settings.py +235 -0
- pyedb/dotnet/edb_core/siwave.py +2 -1
- pyedb/dotnet/edb_core/stackup.py +38 -29
- pyedb/dotnet/edb_core/utilities/simulation_setup.py +16 -7
- pyedb/siwave.py +32 -6
- pyedb/siwave_core/icepak.py +153 -0
- {pyedb-0.10.0.dist-info → pyedb-0.11.0.dist-info}/METADATA +2 -2
- {pyedb-0.10.0.dist-info → pyedb-0.11.0.dist-info}/RECORD +35 -22
- pyedb/configuration/cfg_ports.py +0 -149
- {pyedb-0.10.0.dist-info → pyedb-0.11.0.dist-info}/LICENSE +0 -0
- {pyedb-0.10.0.dist-info → pyedb-0.11.0.dist-info}/WHEEL +0 -0
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
|
|
23
23
|
import json
|
|
24
24
|
import os
|
|
25
|
-
from pathlib import Path
|
|
26
25
|
|
|
27
26
|
import toml
|
|
28
27
|
|
|
29
28
|
from pyedb.configuration.cfg_data import CfgData
|
|
30
29
|
from pyedb.dotnet.edb_core.definition.package_def import PackageDef
|
|
30
|
+
from pyedb.dotnet.edb_core.stackup import LayerCollection
|
|
31
31
|
from pyedb.generic.general_methods import pyedb_function_handler
|
|
32
32
|
|
|
33
33
|
|
|
@@ -40,7 +40,7 @@ class Configuration:
|
|
|
40
40
|
self.data = {}
|
|
41
41
|
self._s_parameter_library = ""
|
|
42
42
|
self._spice_model_library = ""
|
|
43
|
-
self.cfg_data =
|
|
43
|
+
self.cfg_data = CfgData(self._pedb)
|
|
44
44
|
|
|
45
45
|
@pyedb_function_handler
|
|
46
46
|
def load(self, config_file, append=True, apply_file=False, output_file=None, open_at_the_end=True):
|
|
@@ -89,7 +89,7 @@ class Configuration:
|
|
|
89
89
|
else:
|
|
90
90
|
self.data[k] = v
|
|
91
91
|
|
|
92
|
-
self.cfg_data = CfgData(self._pedb, **data)
|
|
92
|
+
self.cfg_data = CfgData(self._pedb, **self.data)
|
|
93
93
|
|
|
94
94
|
if apply_file:
|
|
95
95
|
original_file = self._pedb.edbpath
|
|
@@ -101,64 +101,58 @@ class Configuration:
|
|
|
101
101
|
self._pedb.close_edb()
|
|
102
102
|
self._pedb.edbpath = original_file
|
|
103
103
|
self._pedb.open_edb()
|
|
104
|
-
return self.
|
|
104
|
+
return self.cfg_data
|
|
105
105
|
|
|
106
106
|
@pyedb_function_handler()
|
|
107
107
|
def run(self):
|
|
108
108
|
"""Apply configuration settings to the current design"""
|
|
109
109
|
|
|
110
|
-
# Configure components
|
|
111
|
-
if not self.data:
|
|
112
|
-
self._pedb.logger.error("No data loaded. Please load a configuration file.")
|
|
113
|
-
return False
|
|
114
|
-
|
|
115
|
-
# Configure general settings
|
|
116
|
-
if "general" in self.data:
|
|
117
|
-
self._load_general()
|
|
118
|
-
|
|
119
110
|
# Configure boundary settings
|
|
120
|
-
if
|
|
121
|
-
self.
|
|
111
|
+
if self.cfg_data.boundaries:
|
|
112
|
+
self.cfg_data.boundaries.apply()
|
|
122
113
|
|
|
123
114
|
# Configure nets
|
|
124
|
-
if
|
|
125
|
-
self.
|
|
115
|
+
if self.cfg_data.nets:
|
|
116
|
+
self.cfg_data.nets.apply()
|
|
126
117
|
|
|
127
118
|
# Configure components
|
|
128
|
-
if
|
|
129
|
-
self.
|
|
119
|
+
if self.cfg_data.components:
|
|
120
|
+
for comp in self.cfg_data.components:
|
|
121
|
+
comp.apply()
|
|
130
122
|
|
|
131
123
|
# Configure padstacks
|
|
132
|
-
if
|
|
133
|
-
self.
|
|
124
|
+
if self.cfg_data.padstacks:
|
|
125
|
+
self.cfg_data.padstacks.apply()
|
|
134
126
|
|
|
135
127
|
# Configure pin groups
|
|
136
|
-
|
|
137
|
-
|
|
128
|
+
for pin_group in self.cfg_data.pin_groups:
|
|
129
|
+
pin_group.apply()
|
|
138
130
|
|
|
139
131
|
# Configure ports
|
|
140
|
-
for port in self.cfg_data.
|
|
132
|
+
for port in self.cfg_data.ports:
|
|
141
133
|
port.create()
|
|
142
134
|
|
|
143
135
|
# Configure sources
|
|
144
|
-
if "sources" in self.data:
|
|
145
|
-
self._load_sources()
|
|
136
|
+
"""if "sources" in self.data:
|
|
137
|
+
self._load_sources()"""
|
|
138
|
+
for source in self.cfg_data.sources:
|
|
139
|
+
source.create()
|
|
146
140
|
|
|
147
141
|
# Configure HFSS setup
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
for setup in self.cfg_data.setups:
|
|
143
|
+
setup.apply()
|
|
150
144
|
|
|
151
145
|
# Configure stackup
|
|
152
146
|
if "stackup" in self.data:
|
|
153
147
|
self._load_stackup()
|
|
154
148
|
|
|
155
149
|
# Configure S-parameter
|
|
156
|
-
|
|
157
|
-
|
|
150
|
+
for s_parameter_model in self.cfg_data.s_parameters:
|
|
151
|
+
s_parameter_model.apply()
|
|
158
152
|
|
|
159
153
|
# Configure SPICE models
|
|
160
|
-
|
|
161
|
-
|
|
154
|
+
for spice_model in self.cfg_data.spice_models:
|
|
155
|
+
spice_model.apply()
|
|
162
156
|
|
|
163
157
|
# Configure package definitions
|
|
164
158
|
if "package_definitions" in self.data:
|
|
@@ -170,314 +164,6 @@ class Configuration:
|
|
|
170
164
|
|
|
171
165
|
return True
|
|
172
166
|
|
|
173
|
-
@pyedb_function_handler
|
|
174
|
-
def _load_components(self):
|
|
175
|
-
"""Imports component information from json."""
|
|
176
|
-
|
|
177
|
-
for comp in self.data["components"]:
|
|
178
|
-
ref_designator = comp["reference_designator"]
|
|
179
|
-
part_type = comp["part_type"].lower()
|
|
180
|
-
if part_type == "resistor":
|
|
181
|
-
part_type = "Resistor"
|
|
182
|
-
elif part_type == "capacitor":
|
|
183
|
-
part_type = "Capacitor"
|
|
184
|
-
elif part_type == "inductor":
|
|
185
|
-
part_type = "Inductor"
|
|
186
|
-
elif part_type == "io":
|
|
187
|
-
part_type = "IO"
|
|
188
|
-
elif part_type == "ic":
|
|
189
|
-
part_type = "IC"
|
|
190
|
-
else:
|
|
191
|
-
part_type = "Other"
|
|
192
|
-
|
|
193
|
-
comp_layout = self._components[ref_designator]
|
|
194
|
-
comp_layout.type = part_type
|
|
195
|
-
|
|
196
|
-
if part_type in ["Resistor", "Capacitor", "Inductor"]:
|
|
197
|
-
comp_layout.is_enabled = comp["enabled"]
|
|
198
|
-
rlc_model = comp["rlc_model"] if "rlc_model" in comp else None
|
|
199
|
-
# n_port_model = comp["NPortModel"] if "NPortModel" in comp else None
|
|
200
|
-
# netlist_model = comp["NetlistModel"] if "NetlistModel" in comp else None
|
|
201
|
-
# spice_model = comp["SpiceModel"] if "SpiceModel" in comp else None
|
|
202
|
-
|
|
203
|
-
if rlc_model:
|
|
204
|
-
model_layout = comp_layout.model
|
|
205
|
-
|
|
206
|
-
pin_pairs = rlc_model["pin_pairs"] if "pin_pairs" in rlc_model else None
|
|
207
|
-
if pin_pairs:
|
|
208
|
-
for pp in model_layout.pin_pairs:
|
|
209
|
-
model_layout.delete_pin_pair_rlc(pp)
|
|
210
|
-
|
|
211
|
-
for pp in pin_pairs:
|
|
212
|
-
rlc_model_type = pp["type"]
|
|
213
|
-
p1 = pp["p1"]
|
|
214
|
-
p2 = pp["p2"]
|
|
215
|
-
|
|
216
|
-
r = pp["resistance"] if "resistance" in pp else None
|
|
217
|
-
l = pp["inductance"] if "inductance" in pp else None
|
|
218
|
-
c = pp["capacitance"] if "capacitance" in pp else None
|
|
219
|
-
|
|
220
|
-
pin_pair = self._pedb.edb_api.utility.PinPair(p1, p2)
|
|
221
|
-
rlc = self._pedb.edb_api.utility.Rlc()
|
|
222
|
-
|
|
223
|
-
rlc.IsParallel = False if rlc_model_type == "series" else True
|
|
224
|
-
if not r is None:
|
|
225
|
-
rlc.REnabled = True
|
|
226
|
-
rlc.R = self._pedb.edb_value(r)
|
|
227
|
-
else:
|
|
228
|
-
rlc.REnabled = False
|
|
229
|
-
|
|
230
|
-
if not l is None:
|
|
231
|
-
rlc.LEnabled = True
|
|
232
|
-
rlc.L = self._pedb.edb_value(l)
|
|
233
|
-
else:
|
|
234
|
-
rlc.LEnabled = False
|
|
235
|
-
|
|
236
|
-
if not c is None:
|
|
237
|
-
rlc.CEnabled = True
|
|
238
|
-
rlc.C = self._pedb.edb_value(c)
|
|
239
|
-
else:
|
|
240
|
-
rlc.CEnabled = False
|
|
241
|
-
|
|
242
|
-
model_layout._set_pin_pair_rlc(pin_pair, rlc)
|
|
243
|
-
comp_layout.model = model_layout
|
|
244
|
-
|
|
245
|
-
# Configure port properties
|
|
246
|
-
port_properties = comp["port_properties"] if "port_properties" in comp else None
|
|
247
|
-
if port_properties:
|
|
248
|
-
ref_offset = port_properties["reference_offset"]
|
|
249
|
-
ref_size_auto = port_properties["reference_size_auto"]
|
|
250
|
-
ref_size_x = port_properties["reference_size_x"]
|
|
251
|
-
ref_size_y = port_properties["reference_size_y"]
|
|
252
|
-
else:
|
|
253
|
-
ref_offset = 0
|
|
254
|
-
ref_size_auto = True
|
|
255
|
-
ref_size_x = 0
|
|
256
|
-
ref_size_y = 0
|
|
257
|
-
|
|
258
|
-
# Configure solder ball properties
|
|
259
|
-
solder_ball_properties = comp["solder_ball_properties"] if "solder_ball_properties" in comp else None
|
|
260
|
-
if solder_ball_properties:
|
|
261
|
-
shape = solder_ball_properties["shape"]
|
|
262
|
-
diameter = solder_ball_properties["diameter"]
|
|
263
|
-
mid_diameter = (
|
|
264
|
-
solder_ball_properties["mid_diameter"] if "mid_diameter" in solder_ball_properties else diameter
|
|
265
|
-
)
|
|
266
|
-
height = solder_ball_properties["height"]
|
|
267
|
-
|
|
268
|
-
self._pedb.components.set_solder_ball(
|
|
269
|
-
component=ref_designator,
|
|
270
|
-
sball_diam=diameter,
|
|
271
|
-
sball_mid_diam=mid_diameter,
|
|
272
|
-
sball_height=height,
|
|
273
|
-
shape=shape,
|
|
274
|
-
auto_reference_size=ref_size_auto,
|
|
275
|
-
reference_height=ref_offset,
|
|
276
|
-
reference_size_x=ref_size_x,
|
|
277
|
-
reference_size_y=ref_size_y,
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
@pyedb_function_handler
|
|
281
|
-
def _load_ports(self):
|
|
282
|
-
"""Imports port information from json."""
|
|
283
|
-
|
|
284
|
-
for port in self.data["ports"]:
|
|
285
|
-
port_type = port["type"]
|
|
286
|
-
|
|
287
|
-
positive_terminal_json = port["positive_terminal"]
|
|
288
|
-
pos_terminal = ""
|
|
289
|
-
if "pin_group" in positive_terminal_json:
|
|
290
|
-
pin_group = self._pedb.siwave.pin_groups[positive_terminal_json["pin_group"]]
|
|
291
|
-
port_name = pin_group.name if "name" not in port else port["name"]
|
|
292
|
-
pos_terminal = pin_group.get_terminal(port_name, True)
|
|
293
|
-
|
|
294
|
-
else:
|
|
295
|
-
ref_designator = port["reference_designator"]
|
|
296
|
-
comp_layout = self._components[ref_designator]
|
|
297
|
-
|
|
298
|
-
if "pin" in positive_terminal_json:
|
|
299
|
-
pin_name = positive_terminal_json["pin"]
|
|
300
|
-
port_name = "{}_{}".format(ref_designator, pin_name) if "name" not in port else port["name"]
|
|
301
|
-
pos_terminal = comp_layout.pins[pin_name].get_terminal(port_name, True)
|
|
302
|
-
else: # Net
|
|
303
|
-
net_name = positive_terminal_json["net"]
|
|
304
|
-
port_name = "{}_{}".format(ref_designator, net_name) if "name" not in port else port["name"]
|
|
305
|
-
if port_type == "circuit":
|
|
306
|
-
pg_name = "pg_{}".format(port_name)
|
|
307
|
-
_, pg = self._pedb.siwave.create_pin_group_on_net(ref_designator, net_name, pg_name)
|
|
308
|
-
pos_terminal = pg.get_terminal(port_name, True)
|
|
309
|
-
else: # Coax port
|
|
310
|
-
for _, p in comp_layout.pins.items():
|
|
311
|
-
if p.net_name == net_name:
|
|
312
|
-
pos_terminal = p.get_terminal(port_name, True)
|
|
313
|
-
break
|
|
314
|
-
|
|
315
|
-
if port_type == "circuit":
|
|
316
|
-
negative_terminal_json = port["negative_terminal"]
|
|
317
|
-
if "pin_group" in negative_terminal_json:
|
|
318
|
-
pin_group = self._pedb.siwave.pin_groups[negative_terminal_json["pin_group"]]
|
|
319
|
-
neg_terminal = pin_group.get_terminal(pin_group.name + "_ref", True)
|
|
320
|
-
elif "pin" in negative_terminal_json:
|
|
321
|
-
pin_name = negative_terminal_json["pin"]
|
|
322
|
-
port_name = "{}_{}_ref".format(ref_designator, pin_name)
|
|
323
|
-
neg_terminal = comp_layout.pins[pin_name].get_terminal(port_name, True)
|
|
324
|
-
elif "net" in negative_terminal_json:
|
|
325
|
-
net_name = negative_terminal_json["net"]
|
|
326
|
-
port_name = "{}_{}_ref".format(ref_designator, net_name)
|
|
327
|
-
pg_name = "pg_{}".format(port_name)
|
|
328
|
-
if pg_name not in self._pedb.siwave.pin_groups:
|
|
329
|
-
_, pg = self._pedb.siwave.create_pin_group_on_net(ref_designator, net_name, pg_name)
|
|
330
|
-
else:
|
|
331
|
-
pg = self._pedb.siwave.pin_groups[pg_name]
|
|
332
|
-
neg_terminal = pg.get_terminal(port_name, True)
|
|
333
|
-
|
|
334
|
-
self._pedb.create_port(pos_terminal, neg_terminal, True)
|
|
335
|
-
else:
|
|
336
|
-
self._pedb.create_port(pos_terminal)
|
|
337
|
-
|
|
338
|
-
@pyedb_function_handler
|
|
339
|
-
def _load_sources(self):
|
|
340
|
-
"""Imports source information from json."""
|
|
341
|
-
|
|
342
|
-
for src in self.data["sources"]:
|
|
343
|
-
src_type = src["type"]
|
|
344
|
-
name = src["name"]
|
|
345
|
-
|
|
346
|
-
positive_terminal_json = src["positive_terminal"]
|
|
347
|
-
if "pin_group" in positive_terminal_json:
|
|
348
|
-
pin_group = self._pedb.siwave.pin_groups[positive_terminal_json["pin_group"]]
|
|
349
|
-
pos_terminal = pin_group.get_terminal(pin_group.name, True)
|
|
350
|
-
else:
|
|
351
|
-
ref_designator = src["reference_designator"]
|
|
352
|
-
comp_layout = self._components[ref_designator]
|
|
353
|
-
|
|
354
|
-
if "pin" in positive_terminal_json:
|
|
355
|
-
pin_name = positive_terminal_json["pin"]
|
|
356
|
-
src_name = name
|
|
357
|
-
pos_terminal = comp_layout.pins[pin_name].get_terminal(src_name, True)
|
|
358
|
-
elif "net" in positive_terminal_json: # Net
|
|
359
|
-
net_name = positive_terminal_json["net"]
|
|
360
|
-
src_name = "{}_{}".format(ref_designator, net_name)
|
|
361
|
-
pg_name = "pg_{}".format(src_name)
|
|
362
|
-
_, pg = self._pedb.siwave.create_pin_group_on_net(ref_designator, net_name, pg_name)
|
|
363
|
-
pos_terminal = pg.get_terminal(src_name, True)
|
|
364
|
-
|
|
365
|
-
negative_terminal_json = src["negative_terminal"]
|
|
366
|
-
if "pin_group" in negative_terminal_json:
|
|
367
|
-
pin_group = self._pedb.siwave.pin_groups[negative_terminal_json["pin_group"]]
|
|
368
|
-
neg_terminal = pin_group.get_terminal(pin_group.name + "_ref", True)
|
|
369
|
-
else:
|
|
370
|
-
ref_designator = src["reference_designator"]
|
|
371
|
-
comp_layout = self._components[ref_designator]
|
|
372
|
-
if "pin" in negative_terminal_json:
|
|
373
|
-
pin_name = negative_terminal_json["pin"]
|
|
374
|
-
src_name = name + "_ref"
|
|
375
|
-
neg_terminal = comp_layout.pins[pin_name].get_terminal(src_name, True)
|
|
376
|
-
elif "net" in negative_terminal_json:
|
|
377
|
-
net_name = negative_terminal_json["net"]
|
|
378
|
-
src_name = name + "_ref"
|
|
379
|
-
pg_name = "pg_{}".format(src_name)
|
|
380
|
-
if pg_name not in self._pedb.siwave.pin_groups:
|
|
381
|
-
_, pg = self._pedb.siwave.create_pin_group_on_net(ref_designator, net_name, pg_name)
|
|
382
|
-
else: # pragma no cover
|
|
383
|
-
pg = self._pedb.siwave.pin_groups[pg_name]
|
|
384
|
-
neg_terminal = pg.get_terminal(src_name, True)
|
|
385
|
-
|
|
386
|
-
if src_type == "voltage":
|
|
387
|
-
src_obj = self._pedb.create_voltage_source(pos_terminal, neg_terminal)
|
|
388
|
-
src_obj.magnitude = src["magnitude"]
|
|
389
|
-
elif src_type == "current":
|
|
390
|
-
src_obj = self._pedb.create_current_source(pos_terminal, neg_terminal)
|
|
391
|
-
src_obj.magnitude = src["magnitude"]
|
|
392
|
-
src_obj.name = name
|
|
393
|
-
|
|
394
|
-
@pyedb_function_handler
|
|
395
|
-
def _load_setups(self):
|
|
396
|
-
"""Imports setup information from json."""
|
|
397
|
-
for setup in self.data["setups"]:
|
|
398
|
-
setup_type = setup["type"]
|
|
399
|
-
|
|
400
|
-
edb_setup = None
|
|
401
|
-
name = setup["name"]
|
|
402
|
-
|
|
403
|
-
if setup_type.lower() == "siwave_dc":
|
|
404
|
-
if name not in self._pedb.setups:
|
|
405
|
-
self._pedb.logger.info("Setup {} created.".format(name))
|
|
406
|
-
edb_setup = self._pedb.create_siwave_dc_setup(name)
|
|
407
|
-
else:
|
|
408
|
-
self._pedb.logger.warning("Setup {} already existing. Editing it.".format(name))
|
|
409
|
-
edb_setup = self._pedb.setups[name]
|
|
410
|
-
edb_setup.set_dc_slider(setup["dc_slider_position"])
|
|
411
|
-
dc_ir_settings = setup.get("dc_ir_settings", None)
|
|
412
|
-
if dc_ir_settings:
|
|
413
|
-
for k, v in dc_ir_settings.items():
|
|
414
|
-
if k not in dir(edb_setup.dc_ir_settings):
|
|
415
|
-
self._pedb.logger.error(f"Invalid keyword {k}")
|
|
416
|
-
else:
|
|
417
|
-
setattr(edb_setup.dc_ir_settings, k, v)
|
|
418
|
-
else:
|
|
419
|
-
if setup_type.lower() == "hfss":
|
|
420
|
-
if name not in self._pedb.setups:
|
|
421
|
-
self._pedb.logger.info("Setup {} created.".format(name))
|
|
422
|
-
edb_setup = self._pedb.create_hfss_setup(name)
|
|
423
|
-
else:
|
|
424
|
-
self._pedb.logger.warning("Setup {} already existing. Editing it.".format(name))
|
|
425
|
-
edb_setup = self._pedb.setups[name]
|
|
426
|
-
edb_setup.set_solution_single_frequency(
|
|
427
|
-
setup["f_adapt"], max_num_passes=setup["max_num_passes"], max_delta_s=setup["max_mag_delta_s"]
|
|
428
|
-
)
|
|
429
|
-
elif setup_type.lower() == "siwave_syz":
|
|
430
|
-
name = setup["name"]
|
|
431
|
-
if name not in self._pedb.setups:
|
|
432
|
-
self._pedb.logger.info("Setup {} created.".format(name))
|
|
433
|
-
edb_setup = self._pedb.create_siwave_syz_setup(name)
|
|
434
|
-
else:
|
|
435
|
-
self._pedb.logger.warning("Setup {} already existing. Editing it.".format(name))
|
|
436
|
-
edb_setup = self._pedb.setups[name]
|
|
437
|
-
if "si_slider_position" in setup:
|
|
438
|
-
edb_setup.si_slider_position = setup["si_slider_position"]
|
|
439
|
-
if "pi_slider_position" in setup:
|
|
440
|
-
edb_setup.pi_slider_position = setup["pi_slider_position"]
|
|
441
|
-
|
|
442
|
-
if "freq_sweep" in setup:
|
|
443
|
-
for fsweep in setup["freq_sweep"]:
|
|
444
|
-
frequencies = fsweep["frequencies"]
|
|
445
|
-
freqs = []
|
|
446
|
-
|
|
447
|
-
for d in frequencies:
|
|
448
|
-
if d["distribution"] == "linear step":
|
|
449
|
-
freqs.append(
|
|
450
|
-
[
|
|
451
|
-
"linear scale",
|
|
452
|
-
self._pedb.edb_value(d["start"]).ToString(),
|
|
453
|
-
self._pedb.edb_value(d["stop"]).ToString(),
|
|
454
|
-
self._pedb.edb_value(d["step"]).ToString(),
|
|
455
|
-
]
|
|
456
|
-
)
|
|
457
|
-
elif d["distribution"] == "linear count":
|
|
458
|
-
freqs.append(
|
|
459
|
-
[
|
|
460
|
-
"linear count",
|
|
461
|
-
self._pedb.edb_value(d["start"]).ToString(),
|
|
462
|
-
self._pedb.edb_value(d["stop"]).ToString(),
|
|
463
|
-
int(d["points"]),
|
|
464
|
-
]
|
|
465
|
-
)
|
|
466
|
-
elif d["distribution"] == "log scale":
|
|
467
|
-
freqs.append(
|
|
468
|
-
[
|
|
469
|
-
"log scale",
|
|
470
|
-
self._pedb.edb_value(d["start"]).ToString(),
|
|
471
|
-
self._pedb.edb_value(d["stop"]).ToString(),
|
|
472
|
-
int(d["samples"]),
|
|
473
|
-
]
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
edb_setup.add_frequency_sweep(
|
|
477
|
-
fsweep["name"],
|
|
478
|
-
frequency_sweep=freqs,
|
|
479
|
-
)
|
|
480
|
-
|
|
481
167
|
@pyedb_function_handler
|
|
482
168
|
def _load_stackup(self):
|
|
483
169
|
"""Imports stackup information from json."""
|
|
@@ -510,8 +196,9 @@ class Configuration:
|
|
|
510
196
|
layer_clones.append(obj)
|
|
511
197
|
else:
|
|
512
198
|
doc_layer_clones.append(obj)
|
|
513
|
-
lc.remove_layer(name)
|
|
514
199
|
|
|
200
|
+
lc_new = LayerCollection(self._pedb)
|
|
201
|
+
lc_new.auto_refresh = False
|
|
515
202
|
signal_layer_ids = {}
|
|
516
203
|
top_layer_clone = None
|
|
517
204
|
|
|
@@ -520,12 +207,12 @@ class Configuration:
|
|
|
520
207
|
if l["type"] == "signal":
|
|
521
208
|
clone = layer_clones.pop(0)
|
|
522
209
|
clone.update(**l)
|
|
523
|
-
|
|
210
|
+
lc_new.add_layer_bottom(name=clone.name, layer_clone=clone)
|
|
524
211
|
signal_layer_ids[clone.name] = clone.id
|
|
525
212
|
|
|
526
213
|
# add all document layers at bottom
|
|
527
214
|
for l in doc_layer_clones:
|
|
528
|
-
doc_layer =
|
|
215
|
+
doc_layer = lc_new.add_document_layer(name=l.name, layer_clone=l)
|
|
529
216
|
first_doc_layer_name = doc_layer.name
|
|
530
217
|
|
|
531
218
|
# add all dielectric layers. Dielectric layers must be added last. Otherwise,
|
|
@@ -533,165 +220,18 @@ class Configuration:
|
|
|
533
220
|
prev_layer_clone = None
|
|
534
221
|
l = layers.pop(0)
|
|
535
222
|
if l["type"] == "signal":
|
|
536
|
-
prev_layer_clone =
|
|
223
|
+
prev_layer_clone = lc_new.layers[l["name"]]
|
|
537
224
|
else:
|
|
538
|
-
prev_layer_clone =
|
|
225
|
+
prev_layer_clone = lc_new.add_layer_top(**l)
|
|
539
226
|
for idx, l in enumerate(layers):
|
|
540
227
|
if l["type"] == "dielectric":
|
|
541
|
-
prev_layer_clone =
|
|
542
|
-
else:
|
|
543
|
-
prev_layer_clone = lc.layers[l["name"]]
|
|
544
|
-
|
|
545
|
-
@pyedb_function_handler
|
|
546
|
-
def _load_s_parameter(self):
|
|
547
|
-
"""Imports s-parameter information from json."""
|
|
548
|
-
|
|
549
|
-
for sp in self.data["s_parameters"]:
|
|
550
|
-
fpath = sp["file_path"]
|
|
551
|
-
if not Path(fpath).anchor:
|
|
552
|
-
fpath = str(Path(self._s_parameter_library) / fpath)
|
|
553
|
-
sp_name = sp["name"]
|
|
554
|
-
comp_def_name = sp["component_definition"]
|
|
555
|
-
comp_def = self._pedb.definitions.component[comp_def_name]
|
|
556
|
-
comp_def.add_n_port_model(fpath, sp_name)
|
|
557
|
-
comp_list = dict()
|
|
558
|
-
if sp["apply_to_all"]:
|
|
559
|
-
comp_list.update(
|
|
560
|
-
{refdes: comp for refdes, comp in comp_def.components.items() if refdes not in sp["components"]}
|
|
561
|
-
)
|
|
562
|
-
else:
|
|
563
|
-
comp_list.update(
|
|
564
|
-
{refdes: comp for refdes, comp in comp_def.components.items() if refdes in sp["components"]}
|
|
565
|
-
)
|
|
566
|
-
|
|
567
|
-
for refdes, comp in comp_list.items():
|
|
568
|
-
if "reference_net_per_component" in sp:
|
|
569
|
-
ref_net_per_comp = sp["reference_net_per_component"]
|
|
570
|
-
ref_net = ref_net_per_comp[refdes] if refdes in ref_net_per_comp else sp["reference_net"]
|
|
228
|
+
prev_layer_clone = lc_new.add_layer_below(base_layer_name=prev_layer_clone.name, **l)
|
|
571
229
|
else:
|
|
572
|
-
|
|
573
|
-
comp.use_s_parameter_model(sp_name, reference_net=ref_net)
|
|
574
|
-
|
|
575
|
-
@pyedb_function_handler
|
|
576
|
-
def _load_spice_models(self):
|
|
577
|
-
"""Imports SPICE information from json."""
|
|
578
|
-
|
|
579
|
-
for sp in self.data["spice_models"]:
|
|
580
|
-
fpath = sp["file_path"]
|
|
581
|
-
if not Path(fpath).anchor:
|
|
582
|
-
fpath = str(Path(self._spice_model_library) / fpath)
|
|
583
|
-
sp_name = sp["name"]
|
|
584
|
-
sub_circuit_name = sp.get("sub_circuit_name", None)
|
|
585
|
-
comp_def_name = sp["component_definition"]
|
|
586
|
-
comp_def = self._pedb.definitions.component[comp_def_name]
|
|
587
|
-
comps = comp_def.components
|
|
588
|
-
if sp["apply_to_all"]:
|
|
589
|
-
for refdes, comp in comps.items():
|
|
590
|
-
if refdes not in sp["components"]:
|
|
591
|
-
comp.assign_spice_model(fpath, sp_name, sub_circuit_name)
|
|
592
|
-
else:
|
|
593
|
-
for refdes, comp in comps.items():
|
|
594
|
-
if refdes in sp["components"]:
|
|
595
|
-
comp.assign_spice_model(fpath, sp_name, sub_circuit_name)
|
|
596
|
-
|
|
597
|
-
@pyedb_function_handler
|
|
598
|
-
def _load_pin_groups(self):
|
|
599
|
-
"""Imports pin groups information from JSON."""
|
|
600
|
-
comps = self._pedb.components.components
|
|
601
|
-
for pg in self.data["pin_groups"]:
|
|
602
|
-
name = pg["name"]
|
|
603
|
-
ref_designator = pg["reference_designator"]
|
|
604
|
-
if "pins" in pg:
|
|
605
|
-
self._pedb.siwave.create_pin_group(ref_designator, pg["pins"], name)
|
|
606
|
-
elif "net" in pg:
|
|
607
|
-
nets = pg["net"]
|
|
608
|
-
nets = nets if isinstance(nets, list) else [nets]
|
|
609
|
-
comp = comps[ref_designator]
|
|
610
|
-
pins = [p for p, obj in comp.pins.items() if obj.net_name in nets]
|
|
611
|
-
self._pedb.siwave.create_pin_group(ref_designator, pins, name)
|
|
612
|
-
else:
|
|
613
|
-
pins = [i for i in comps[ref_designator].pins.keys()]
|
|
614
|
-
self._pedb.siwave.create_pin_group(ref_designator, pins, name)
|
|
615
|
-
|
|
616
|
-
@pyedb_function_handler
|
|
617
|
-
def _load_nets(self):
|
|
618
|
-
"""Imports nets information from JSON."""
|
|
619
|
-
nets = self._pedb.nets.nets
|
|
620
|
-
for i in self.data["nets"]["power_ground_nets"]:
|
|
621
|
-
nets[i].is_power_ground = True
|
|
622
|
-
|
|
623
|
-
for i in self.data["nets"]["signal_nets"]:
|
|
624
|
-
nets[i].is_power_ground = False
|
|
625
|
-
|
|
626
|
-
@pyedb_function_handler
|
|
627
|
-
def _load_general(self):
|
|
628
|
-
"""Imports general information from JSON."""
|
|
629
|
-
general = self.data["general"]
|
|
630
|
-
if "s_parameter_library" in general:
|
|
631
|
-
self._s_parameter_library = general["s_parameter_library"]
|
|
632
|
-
if "spice_model_library" in general:
|
|
633
|
-
self._spice_model_library = general["spice_model_library"]
|
|
230
|
+
prev_layer_clone = lc_new.layers[l["name"]]
|
|
634
231
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
boundaries = self.data["boundaries"]
|
|
639
|
-
|
|
640
|
-
open_region = boundaries.get("open_region", None)
|
|
641
|
-
if open_region:
|
|
642
|
-
self._pedb.hfss.hfss_extent_info.use_open_region = open_region
|
|
643
|
-
|
|
644
|
-
open_region_type = boundaries.get("open_region_type", None)
|
|
645
|
-
if open_region_type:
|
|
646
|
-
self._pedb.hfss.hfss_extent_info.open_region_type = open_region_type
|
|
647
|
-
|
|
648
|
-
pml_visible = boundaries.get("pml_visible", None)
|
|
649
|
-
if pml_visible:
|
|
650
|
-
self._pedb.hfss.hfss_extent_info.is_pml_visible = pml_visible
|
|
651
|
-
|
|
652
|
-
pml_operation_frequency = boundaries.get("pml_operation_frequency", None)
|
|
653
|
-
if pml_operation_frequency:
|
|
654
|
-
self._pedb.hfss.hfss_extent_info.operating_freq = pml_operation_frequency
|
|
655
|
-
|
|
656
|
-
pml_radiation_factor = boundaries.get("pml_radiation_factor", None)
|
|
657
|
-
if pml_radiation_factor:
|
|
658
|
-
self._pedb.hfss.hfss_extent_info.radiation_level = pml_radiation_factor
|
|
659
|
-
|
|
660
|
-
dielectric_extents_type = boundaries.get("dielectric_extents_type", None)
|
|
661
|
-
if dielectric_extents_type:
|
|
662
|
-
self._pedb.hfss.hfss_extent_info.extent_type = dielectric_extents_type
|
|
663
|
-
|
|
664
|
-
dielectric_base_polygon = boundaries.get("dielectric_base_polygon", None)
|
|
665
|
-
if dielectric_base_polygon:
|
|
666
|
-
self._pedb.hfss.hfss_extent_info.dielectric_base_polygon = dielectric_base_polygon
|
|
667
|
-
|
|
668
|
-
horizontal_padding = boundaries.get("horizontal_padding", None)
|
|
669
|
-
if horizontal_padding:
|
|
670
|
-
self._pedb.hfss.hfss_extent_info.dielectric_extent_size = horizontal_padding
|
|
671
|
-
|
|
672
|
-
honor_primitives_on_dielectric_layers = boundaries.get("honor_primitives_on_dielectric_layers", None)
|
|
673
|
-
if honor_primitives_on_dielectric_layers:
|
|
674
|
-
self._pedb.hfss.hfss_extent_info.honor_user_dielectric = honor_primitives_on_dielectric_layers
|
|
675
|
-
|
|
676
|
-
air_box_extents_type = boundaries.get("air_box_extents_type", None)
|
|
677
|
-
if air_box_extents_type:
|
|
678
|
-
self._pedb.hfss.hfss_extent_info.extent_type = air_box_extents_type
|
|
679
|
-
|
|
680
|
-
air_box_truncate_model_ground_layers = boundaries.get("air_box_truncate_model_ground_layers", None)
|
|
681
|
-
if air_box_truncate_model_ground_layers:
|
|
682
|
-
self._pedb.hfss.hfss_extent_info.truncate_air_box_at_ground = air_box_truncate_model_ground_layers
|
|
683
|
-
|
|
684
|
-
air_box_horizontal_padding = boundaries.get("air_box_horizontal_padding", None)
|
|
685
|
-
if air_box_horizontal_padding:
|
|
686
|
-
self._pedb.hfss.hfss_extent_info.air_box_horizontal_extent = air_box_horizontal_padding
|
|
687
|
-
|
|
688
|
-
air_box_positive_vertical_padding = boundaries.get("air_box_positive_vertical_padding", None)
|
|
689
|
-
if air_box_positive_vertical_padding:
|
|
690
|
-
self._pedb.hfss.hfss_extent_info.air_box_positive_vertical_extent = air_box_positive_vertical_padding
|
|
691
|
-
|
|
692
|
-
air_box_negative_vertical_padding = boundaries.get("air_box_negative_vertical_padding", None)
|
|
693
|
-
if air_box_positive_vertical_padding:
|
|
694
|
-
self._pedb.hfss.hfss_extent_info.air_box_negative_vertical_extent = air_box_negative_vertical_padding
|
|
232
|
+
lc._edb_object = lc_new._edb_object
|
|
233
|
+
lc_new.auto_refresh = True
|
|
234
|
+
lc.update_layout()
|
|
695
235
|
|
|
696
236
|
@pyedb_function_handler
|
|
697
237
|
def _load_operations(self):
|
|
@@ -701,41 +241,6 @@ class Configuration:
|
|
|
701
241
|
if cutout:
|
|
702
242
|
self._pedb.cutout(**cutout)
|
|
703
243
|
|
|
704
|
-
@pyedb_function_handler
|
|
705
|
-
def _load_padstacks(self):
|
|
706
|
-
"""Imports padstack information from JSON."""
|
|
707
|
-
padstacks = self.data["padstacks"]
|
|
708
|
-
definitions = padstacks.get("definitions", None)
|
|
709
|
-
if definitions:
|
|
710
|
-
padstack_defs = self._pedb.padstacks.definitions
|
|
711
|
-
for value in definitions:
|
|
712
|
-
pdef = padstack_defs[value["name"]]
|
|
713
|
-
if "hole_diameter" in value:
|
|
714
|
-
pdef.hole_diameter = value["hole_diameter"]
|
|
715
|
-
if "hole_plating_thickness" in value:
|
|
716
|
-
pdef.hole_plating_thickness = value["hole_plating_thickness"]
|
|
717
|
-
if "hole_material" in value:
|
|
718
|
-
pdef.material = value["hole_material"]
|
|
719
|
-
if "hole_range" in value:
|
|
720
|
-
pdef.hole_range = value["hole_range"]
|
|
721
|
-
instances = padstacks.get("instances", None)
|
|
722
|
-
if instances:
|
|
723
|
-
padstack_instances = self._pedb.padstacks.instances_by_name
|
|
724
|
-
for value in instances:
|
|
725
|
-
inst = padstack_instances[value["name"]]
|
|
726
|
-
backdrill_top = value.get("backdrill_top", None)
|
|
727
|
-
if backdrill_top:
|
|
728
|
-
inst.set_backdrill_top(
|
|
729
|
-
backdrill_top["drill_to_layer"], backdrill_top["drill_diameter"], backdrill_top["stub_length"]
|
|
730
|
-
)
|
|
731
|
-
backdrill_bottom = value.get("backdrill_bottom", None)
|
|
732
|
-
if backdrill_top:
|
|
733
|
-
inst.set_backdrill_bottom(
|
|
734
|
-
backdrill_bottom["drill_to_layer"],
|
|
735
|
-
backdrill_bottom["drill_diameter"],
|
|
736
|
-
backdrill_bottom["stub_length"],
|
|
737
|
-
)
|
|
738
|
-
|
|
739
244
|
@pyedb_function_handler
|
|
740
245
|
def _load_package_def(self):
|
|
741
246
|
"""Imports package definition information from JSON."""
|