pyedb 0.2.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 +17 -0
- pyedb/dotnet/__init__.py +0 -0
- pyedb/dotnet/application/Variables.py +2261 -0
- pyedb/dotnet/application/__init__.py +0 -0
- pyedb/dotnet/clr_module.py +103 -0
- pyedb/dotnet/edb.py +4237 -0
- pyedb/dotnet/edb_core/__init__.py +1 -0
- pyedb/dotnet/edb_core/cell/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
- pyedb/dotnet/edb_core/components.py +2669 -0
- pyedb/dotnet/edb_core/configuration.py +423 -0
- pyedb/dotnet/edb_core/definition/__init__.py +0 -0
- pyedb/dotnet/edb_core/definition/component_def.py +166 -0
- pyedb/dotnet/edb_core/definition/component_model.py +30 -0
- pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
- pyedb/dotnet/edb_core/definition/definitions.py +12 -0
- pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
- pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
- pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
- pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
- pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
- pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
- pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
- pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
- pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
- pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
- pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
- pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
- pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
- pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
- pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
- pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
- pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
- pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
- pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
- pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
- pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
- pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
- pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
- pyedb/dotnet/edb_core/general.py +181 -0
- pyedb/dotnet/edb_core/hfss.py +1646 -0
- pyedb/dotnet/edb_core/layout.py +1244 -0
- pyedb/dotnet/edb_core/layout_validation.py +272 -0
- pyedb/dotnet/edb_core/materials.py +939 -0
- pyedb/dotnet/edb_core/net_class.py +335 -0
- pyedb/dotnet/edb_core/nets.py +1215 -0
- pyedb/dotnet/edb_core/padstack.py +1389 -0
- pyedb/dotnet/edb_core/siwave.py +1427 -0
- pyedb/dotnet/edb_core/stackup.py +2703 -0
- pyedb/edb_logger.py +396 -0
- pyedb/generic/__init__.py +0 -0
- pyedb/generic/constants.py +1063 -0
- pyedb/generic/data_handlers.py +320 -0
- pyedb/generic/design_types.py +104 -0
- pyedb/generic/filesystem.py +150 -0
- pyedb/generic/general_methods.py +1535 -0
- pyedb/generic/plot.py +1840 -0
- pyedb/generic/process.py +285 -0
- pyedb/generic/settings.py +224 -0
- pyedb/ipc2581/__init__.py +0 -0
- pyedb/ipc2581/bom/__init__.py +0 -0
- pyedb/ipc2581/bom/bom.py +21 -0
- pyedb/ipc2581/bom/bom_item.py +32 -0
- pyedb/ipc2581/bom/characteristics.py +37 -0
- pyedb/ipc2581/bom/refdes.py +16 -0
- pyedb/ipc2581/content/__init__.py +0 -0
- pyedb/ipc2581/content/color.py +38 -0
- pyedb/ipc2581/content/content.py +55 -0
- pyedb/ipc2581/content/dictionary_color.py +29 -0
- pyedb/ipc2581/content/dictionary_fill.py +28 -0
- pyedb/ipc2581/content/dictionary_line.py +30 -0
- pyedb/ipc2581/content/entry_color.py +13 -0
- pyedb/ipc2581/content/entry_line.py +14 -0
- pyedb/ipc2581/content/fill.py +15 -0
- pyedb/ipc2581/content/layer_ref.py +10 -0
- pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
- pyedb/ipc2581/ecad/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
- pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
- pyedb/ipc2581/ecad/cad_data/component.py +41 -0
- pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
- pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
- pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
- pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
- pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
- pyedb/ipc2581/ecad/cad_data/package.py +104 -0
- pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
- pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
- pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
- pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
- pyedb/ipc2581/ecad/cad_data/path.py +89 -0
- pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
- pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
- pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
- pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
- pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
- pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
- pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
- pyedb/ipc2581/ecad/cad_data/step.py +275 -0
- pyedb/ipc2581/ecad/cad_header.py +33 -0
- pyedb/ipc2581/ecad/ecad.py +19 -0
- pyedb/ipc2581/ecad/spec.py +46 -0
- pyedb/ipc2581/history_record.py +37 -0
- pyedb/ipc2581/ipc2581.py +387 -0
- pyedb/ipc2581/logistic_header.py +25 -0
- pyedb/misc/__init__.py +0 -0
- pyedb/misc/aedtlib_personalib_install.py +14 -0
- pyedb/misc/downloads.py +322 -0
- pyedb/misc/misc.py +67 -0
- pyedb/misc/pyedb.runtimeconfig.json +13 -0
- pyedb/misc/siw_feature_config/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
- pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
- pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
- pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
- pyedb/misc/utilities.py +27 -0
- pyedb/modeler/geometry_operators.py +2082 -0
- pyedb-0.2.0.dist-info/LICENSE +21 -0
- pyedb-0.2.0.dist-info/METADATA +208 -0
- pyedb-0.2.0.dist-info/RECORD +128 -0
- pyedb-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
|
|
3
|
+
from pyedb.generic.general_methods import ET
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HistoryRecord(object):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.number = "1"
|
|
9
|
+
self.origination = date.today()
|
|
10
|
+
self.software = "Ansys PyEDB"
|
|
11
|
+
self.last_changes = date.today()
|
|
12
|
+
self.file_revision = "1"
|
|
13
|
+
self.comment = ""
|
|
14
|
+
self.software_package = "Ansys AEDT"
|
|
15
|
+
self.revision = "R2023.1"
|
|
16
|
+
self.vendor = "Ansys"
|
|
17
|
+
self.certification_status = "CERTIFIED"
|
|
18
|
+
|
|
19
|
+
def write_xml(self, root): # pragma no cover
|
|
20
|
+
history_record = ET.SubElement(root, "HistoryRecord")
|
|
21
|
+
history_record.set("number", self.number)
|
|
22
|
+
history_record.set(
|
|
23
|
+
"origination", "{}_{}_{}".format(self.origination.day, self.origination.month, self.origination.year)
|
|
24
|
+
)
|
|
25
|
+
history_record.set("software", self.software)
|
|
26
|
+
history_record.set(
|
|
27
|
+
"lastChange", "{}_{}_{}".format(self.origination.day, self.origination.month, self.origination.year)
|
|
28
|
+
)
|
|
29
|
+
file_revision = ET.SubElement(history_record, "FileRevision")
|
|
30
|
+
file_revision.set("fileRevisionId", self.file_revision)
|
|
31
|
+
file_revision.set("comment", self.comment)
|
|
32
|
+
software_package = ET.SubElement(file_revision, "SoftwarePackage")
|
|
33
|
+
software_package.set("name", self.software_package)
|
|
34
|
+
software_package.set("revision", self.revision)
|
|
35
|
+
software_package.set("vendor", self.vendor)
|
|
36
|
+
certification = ET.SubElement(software_package, "Certification")
|
|
37
|
+
certification.set("certificationStatus", self.certification_status)
|
pyedb/ipc2581/ipc2581.py
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
|
|
3
|
+
from pyedb.generic.general_methods import ET, pyedb_function_handler
|
|
4
|
+
from pyedb.ipc2581.bom.bom import Bom
|
|
5
|
+
from pyedb.ipc2581.bom.bom_item import BomItem
|
|
6
|
+
from pyedb.ipc2581.content.content import Content
|
|
7
|
+
from pyedb.ipc2581.ecad.cad_data.padstack_def import PadstackDef
|
|
8
|
+
from pyedb.ipc2581.ecad.ecad import Ecad
|
|
9
|
+
from pyedb.ipc2581.history_record import HistoryRecord
|
|
10
|
+
from pyedb.ipc2581.logistic_header import LogisticHeader
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Ipc2581(object):
|
|
14
|
+
"""Manages the Ipc2581 exporter."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, pedb, units):
|
|
17
|
+
self.revision = "C"
|
|
18
|
+
self._pedb = pedb
|
|
19
|
+
self.units = units
|
|
20
|
+
self.content = Content(self)
|
|
21
|
+
self.logistic_header = LogisticHeader()
|
|
22
|
+
self.history_record = HistoryRecord()
|
|
23
|
+
self.bom = Bom(pedb)
|
|
24
|
+
self.ecad = Ecad(self, pedb, units)
|
|
25
|
+
self.file_path = ""
|
|
26
|
+
self.design_name = ""
|
|
27
|
+
self.top_bottom_layers = []
|
|
28
|
+
|
|
29
|
+
@pyedb_function_handler()
|
|
30
|
+
def load_ipc_model(self):
|
|
31
|
+
self.design_name = self._pedb.cell_names[0]
|
|
32
|
+
self.content.step_ref = self.design_name
|
|
33
|
+
self._pedb.logger.info("Parsing Layers...")
|
|
34
|
+
self.add_layers_info()
|
|
35
|
+
self._pedb.logger.info("Parsing BOM...")
|
|
36
|
+
self.add_bom()
|
|
37
|
+
self._pedb.logger.info("Parsing Padstack Definitions...")
|
|
38
|
+
self.add_pdstack_definition()
|
|
39
|
+
self.add_profile()
|
|
40
|
+
self._pedb.logger.info("Parsing Components...")
|
|
41
|
+
self.add_components()
|
|
42
|
+
self._pedb.logger.info("Parsing Logical Nets...")
|
|
43
|
+
self.add_logical_nets()
|
|
44
|
+
self._pedb.logger.info("Parsing Layout Primitives...")
|
|
45
|
+
self.add_layer_features()
|
|
46
|
+
self._pedb.logger.info("Parsing Drills...")
|
|
47
|
+
self.add_drills()
|
|
48
|
+
self._pedb.logger.info("Parsing EDB Completed!")
|
|
49
|
+
|
|
50
|
+
@pyedb_function_handler()
|
|
51
|
+
def add_pdstack_definition(self):
|
|
52
|
+
for padstack_name, padstackdef in self._pedb.padstacks.definitions.items():
|
|
53
|
+
padstack_def = PadstackDef()
|
|
54
|
+
padstack_def.name = padstack_name
|
|
55
|
+
padstack_def.padstack_hole_def.name = padstack_name
|
|
56
|
+
if padstackdef.hole_properties:
|
|
57
|
+
padstack_def.padstack_hole_def.diameter = self.from_meter_to_units(
|
|
58
|
+
padstackdef.hole_properties[0], self.units
|
|
59
|
+
)
|
|
60
|
+
for layer, pad in padstackdef.pad_by_layer.items():
|
|
61
|
+
if pad.parameters_values:
|
|
62
|
+
if pad.geometry_type == 1:
|
|
63
|
+
primitive_ref = "CIRCLE_{}".format(
|
|
64
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units)
|
|
65
|
+
)
|
|
66
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
|
|
67
|
+
self.content.standard_geometries_dict.standard_circ_dict[
|
|
68
|
+
primitive_ref
|
|
69
|
+
] = self.from_meter_to_units(pad.parameters_values[0], self.units)
|
|
70
|
+
elif pad.geometry_type == 2:
|
|
71
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
72
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
73
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
74
|
+
)
|
|
75
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
76
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
77
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
78
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
79
|
+
]
|
|
80
|
+
elif pad.geometry_type == 3:
|
|
81
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
82
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
83
|
+
self.from_meter_to_units(pad.parameters_values[1], self.units),
|
|
84
|
+
)
|
|
85
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
86
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
87
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
88
|
+
self.from_meter_to_units(pad.parameters_values[1], self.units),
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
elif pad.geometry_type == 4:
|
|
92
|
+
primitive_ref = "OVAL_{}_{}_{}".format(
|
|
93
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
94
|
+
self.from_meter_to_units(pad.parameters_values[1], self.units),
|
|
95
|
+
self.from_meter_to_units(pad.parameters_values[2], self.units),
|
|
96
|
+
)
|
|
97
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
|
|
98
|
+
self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
|
|
99
|
+
self.from_meter_to_units(pad.parameters_values[0], self.units),
|
|
100
|
+
self.from_meter_to_units(pad.parameters_values[1], self.units),
|
|
101
|
+
self.from_meter_to_units(pad.parameters_values[2], self.units),
|
|
102
|
+
]
|
|
103
|
+
else:
|
|
104
|
+
primitive_ref = "Default"
|
|
105
|
+
padstack_def.add_padstack_pad_def(layer=layer, pad_use="REGULAR", primitive_ref=primitive_ref)
|
|
106
|
+
for layer, antipad in padstackdef.antipad_by_layer.items():
|
|
107
|
+
if antipad.parameters_values:
|
|
108
|
+
if antipad.geometry_type == 1:
|
|
109
|
+
primitive_ref = "CIRCLE_{}".format(
|
|
110
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units)
|
|
111
|
+
)
|
|
112
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
|
|
113
|
+
self.content.standard_geometries_dict.standard_circ_dict[
|
|
114
|
+
primitive_ref
|
|
115
|
+
] = self.from_meter_to_units(antipad.parameters_values[0], self.units)
|
|
116
|
+
elif antipad.geometry_type == 2:
|
|
117
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
118
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
119
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
120
|
+
)
|
|
121
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
122
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
123
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
124
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
125
|
+
]
|
|
126
|
+
elif antipad.geometry_type == 3:
|
|
127
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
128
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
129
|
+
self.from_meter_to_units(antipad.parameters_values[1], self.units),
|
|
130
|
+
)
|
|
131
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
132
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
133
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
134
|
+
self.from_meter_to_units(antipad.parameters_values[1], self.units),
|
|
135
|
+
]
|
|
136
|
+
elif antipad.geometry_type == 4:
|
|
137
|
+
primitive_ref = "OVAL_{}_{}_{}".format(
|
|
138
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
139
|
+
self.from_meter_to_units(antipad.parameters_values[1], self.units),
|
|
140
|
+
self.from_meter_to_units(antipad.parameters_values[2], self.units),
|
|
141
|
+
)
|
|
142
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
|
|
143
|
+
self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
|
|
144
|
+
self.from_meter_to_units(antipad.parameters_values[0], self.units),
|
|
145
|
+
self.from_meter_to_units(antipad.parameters_values[1], self.units),
|
|
146
|
+
self.from_meter_to_units(antipad.parameters_values[2], self.units),
|
|
147
|
+
]
|
|
148
|
+
else:
|
|
149
|
+
primitive_ref = "Default"
|
|
150
|
+
padstack_def.add_padstack_pad_def(layer=layer, pad_use="ANTIPAD", primitive_ref=primitive_ref)
|
|
151
|
+
for layer, thermalpad in padstackdef.thermalpad_by_layer.items():
|
|
152
|
+
if thermalpad.parameters_values:
|
|
153
|
+
if thermalpad.geometry_type == 1:
|
|
154
|
+
primitive_ref = "CIRCLE_{}".format(
|
|
155
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units)
|
|
156
|
+
)
|
|
157
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
|
|
158
|
+
self.content.standard_geometries_dict[primitive_ref] = self.from_meter_to_units(
|
|
159
|
+
thermalpad.parameters_values[0], self.units
|
|
160
|
+
)
|
|
161
|
+
elif thermalpad.geometry_type == 2:
|
|
162
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
163
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
164
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
165
|
+
)
|
|
166
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
167
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
168
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
169
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
170
|
+
]
|
|
171
|
+
elif thermalpad.geometry_type == 3:
|
|
172
|
+
primitive_ref = "RECT_{}_{}".format(
|
|
173
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
174
|
+
self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
|
|
175
|
+
)
|
|
176
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_rect_dict:
|
|
177
|
+
self.content.standard_geometries_dict.standard_rect_dict[primitive_ref] = [
|
|
178
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
179
|
+
self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
|
|
180
|
+
]
|
|
181
|
+
elif thermalpad.geometry_type == 4:
|
|
182
|
+
primitive_ref = "OVAL_{}_{}_{}".format(
|
|
183
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
184
|
+
self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
|
|
185
|
+
self.from_meter_to_units(thermalpad.parameters_values[2], self.units),
|
|
186
|
+
)
|
|
187
|
+
if not primitive_ref in self.content.standard_geometries_dict.standard_oval_dict:
|
|
188
|
+
self.content.standard_geometries_dict.standard_oval_dict[primitive_ref] = [
|
|
189
|
+
self.from_meter_to_units(thermalpad.parameters_values[0], self.units),
|
|
190
|
+
self.from_meter_to_units(thermalpad.parameters_values[1], self.units),
|
|
191
|
+
self.from_meter_to_units(thermalpad.parameters_values[2], self.units),
|
|
192
|
+
]
|
|
193
|
+
else:
|
|
194
|
+
primitive_ref = "Default"
|
|
195
|
+
padstack_def.add_padstack_pad_def(layer=layer, pad_use="THERMAL", primitive_ref=primitive_ref)
|
|
196
|
+
if not padstack_def.name in self.ecad.cad_data.cad_data_step.padstack_defs:
|
|
197
|
+
self.ecad.cad_data.cad_data_step.padstack_defs[padstack_def.name] = padstack_def
|
|
198
|
+
|
|
199
|
+
@pyedb_function_handler()
|
|
200
|
+
def add_bom(self):
|
|
201
|
+
# Bom
|
|
202
|
+
for part_name, components in self._pedb.components.components_by_partname.items():
|
|
203
|
+
bom_item = BomItem()
|
|
204
|
+
bom_item.part_name = part_name
|
|
205
|
+
bom_item.quantity = len(components)
|
|
206
|
+
bom_item.pin_count = components[0].numpins
|
|
207
|
+
bom_item.category = "ELECTRICAL"
|
|
208
|
+
bom_item.charactistics.device_type = components[0].type
|
|
209
|
+
bom_item.charactistics.category = "ELECTRICAL"
|
|
210
|
+
bom_item.charactistics.component_class = "DISCRETE"
|
|
211
|
+
if components[0].type == "Resistor":
|
|
212
|
+
bom_item.charactistics.value = components[0].res_value
|
|
213
|
+
elif components[0].type == "Capacitor":
|
|
214
|
+
bom_item.charactistics.value = components[0].cap_value
|
|
215
|
+
elif components[0].type == "Inductor":
|
|
216
|
+
bom_item.charactistics.value = components[0].ind_value
|
|
217
|
+
for cmp in components:
|
|
218
|
+
bom_item.add_refdes(
|
|
219
|
+
component_name=cmp.refdes, placement_layer=cmp.placement_layer, package_def="", populate=True
|
|
220
|
+
)
|
|
221
|
+
self.bom.bom_items.append(bom_item)
|
|
222
|
+
|
|
223
|
+
@pyedb_function_handler()
|
|
224
|
+
def add_layers_info(self):
|
|
225
|
+
self.design_name = self._pedb.layout.cell.GetName()
|
|
226
|
+
self.ecad.design_name = self.design_name
|
|
227
|
+
self.ecad.cad_header.units = self.units
|
|
228
|
+
self.ecad.cad_data.stackup.total_thickness = self.from_meter_to_units(
|
|
229
|
+
self._pedb.stackup.get_layout_thickness(), self.units
|
|
230
|
+
)
|
|
231
|
+
self.ecad.cad_data.stackup.stackup_group.thickness = self.ecad.cad_data.stackup.total_thickness
|
|
232
|
+
self.layers_name = list(self._pedb.stackup.signal_layers.keys())
|
|
233
|
+
self.top_bottom_layers = [self.layers_name[0], self.layers_name[-1]]
|
|
234
|
+
sequence = 0
|
|
235
|
+
for layer_name in list(self._pedb.stackup.stackup_layers.keys()):
|
|
236
|
+
sequence += 1
|
|
237
|
+
self.content.add_layer_ref(layer_name)
|
|
238
|
+
layer_color = self._pedb.stackup.layers[layer_name].color
|
|
239
|
+
self.content.dict_colors.add_color(
|
|
240
|
+
"{}".format(layer_name), str(layer_color[0]), str(layer_color[1]), str(layer_color[2])
|
|
241
|
+
)
|
|
242
|
+
# Ecad layers
|
|
243
|
+
layer_type = "CONDUCTOR"
|
|
244
|
+
conductivity = 5e6
|
|
245
|
+
permitivity = 1
|
|
246
|
+
loss_tg = 0
|
|
247
|
+
embedded = "NOT_EMBEDDED"
|
|
248
|
+
# try:
|
|
249
|
+
material_name = self._pedb.stackup.layers[layer_name]._edb_layer.GetMaterial()
|
|
250
|
+
edb_material = self._pedb.edb_api.definition.MaterialDef.FindByName(self._pedb.active_db, material_name)
|
|
251
|
+
material_type = "CONDUCTOR"
|
|
252
|
+
if self._pedb.stackup.layers[layer_name].type == "dielectric":
|
|
253
|
+
layer_type = "DIELPREG"
|
|
254
|
+
material_type = "DIELECTRIC"
|
|
255
|
+
|
|
256
|
+
permitivity = edb_material.GetProperty(self._pedb.edb_api.definition.MaterialPropertyId.Permittivity)[1]
|
|
257
|
+
if not isinstance(permitivity, float):
|
|
258
|
+
permitivity = permitivity.ToDouble()
|
|
259
|
+
loss_tg = edb_material.GetProperty(
|
|
260
|
+
self._pedb.edb_api.definition.MaterialPropertyId.DielectricLossTangent
|
|
261
|
+
)[1]
|
|
262
|
+
if not isinstance(loss_tg, float):
|
|
263
|
+
loss_tg = loss_tg.ToDouble()
|
|
264
|
+
conductivity = 0
|
|
265
|
+
if layer_type == "CONDUCTOR":
|
|
266
|
+
conductivity = edb_material.GetProperty(self._pedb.edb_api.definition.MaterialPropertyId.Conductivity)[
|
|
267
|
+
1
|
|
268
|
+
]
|
|
269
|
+
if not isinstance(conductivity, float):
|
|
270
|
+
conductivity = conductivity.ToDouble()
|
|
271
|
+
self.ecad.cad_header.add_spec(
|
|
272
|
+
name=layer_name,
|
|
273
|
+
material=self._pedb.stackup.layers[layer_name]._edb_layer.GetMaterial(),
|
|
274
|
+
layer_type=material_type,
|
|
275
|
+
conductivity=str(conductivity),
|
|
276
|
+
dielectric_constant=str(permitivity),
|
|
277
|
+
loss_tg=str(loss_tg),
|
|
278
|
+
embedded=embedded,
|
|
279
|
+
)
|
|
280
|
+
layer_position = "INTERNAL"
|
|
281
|
+
if layer_name == self.top_bottom_layers[0]:
|
|
282
|
+
layer_position = "TOP"
|
|
283
|
+
if layer_name == self.top_bottom_layers[1]:
|
|
284
|
+
layer_position = "BOTTOM"
|
|
285
|
+
self.ecad.cad_data.add_layer(
|
|
286
|
+
layer_name=layer_name, layer_function=layer_type, layer_side=layer_position, polarity="POSITIVE"
|
|
287
|
+
)
|
|
288
|
+
layer_thickness_with_units = self.from_meter_to_units(
|
|
289
|
+
self._pedb.stackup.layers[layer_name].thickness, self.units
|
|
290
|
+
)
|
|
291
|
+
self.ecad.cad_data.stackup.stackup_group.add_stackup_layer(
|
|
292
|
+
layer_name=layer_name, thickness=layer_thickness_with_units, sequence=str(sequence)
|
|
293
|
+
)
|
|
294
|
+
# except:
|
|
295
|
+
# pass
|
|
296
|
+
self.ecad.cad_data.add_layer(layer_name="Drill", layer_function="DRILL", layer_side="ALL", polarity="POSITIVE")
|
|
297
|
+
self.content.add_layer_ref("Drill")
|
|
298
|
+
self.content.dict_colors.add_color("{}".format("Drill"), "255", "255", "255")
|
|
299
|
+
|
|
300
|
+
@pyedb_function_handler()
|
|
301
|
+
def add_components(self):
|
|
302
|
+
for item in self._pedb.components.components.values():
|
|
303
|
+
self.ecad.cad_data.cad_data_step.add_component(item)
|
|
304
|
+
|
|
305
|
+
@pyedb_function_handler()
|
|
306
|
+
def add_logical_nets(self):
|
|
307
|
+
nets = [i for i in self._pedb.nets.nets.values()]
|
|
308
|
+
for net in nets:
|
|
309
|
+
self.ecad.cad_data.cad_data_step.add_logical_net(net)
|
|
310
|
+
|
|
311
|
+
@pyedb_function_handler()
|
|
312
|
+
def add_profile(self):
|
|
313
|
+
profile = self._pedb.modeler.primitives_by_layer["Outline"]
|
|
314
|
+
for prim in profile:
|
|
315
|
+
self.ecad.cad_data.cad_data_step.add_profile(prim)
|
|
316
|
+
|
|
317
|
+
@pyedb_function_handler()
|
|
318
|
+
def add_layer_features(self):
|
|
319
|
+
layers = {i: j for i, j in self._pedb.stackup.layers.items()}
|
|
320
|
+
padstack_instances = list(self._pedb.padstacks.instances.values())
|
|
321
|
+
padstack_defs = {i: k for i, k in self._pedb.padstacks.definitions.items()}
|
|
322
|
+
polys = {i: j for i, j in self._pedb.modeler.primitives_by_layer.items()}
|
|
323
|
+
for layer_name, layer in layers.items():
|
|
324
|
+
self.ecad.cad_data.cad_data_step.add_layer_feature(layer, polys[layer_name])
|
|
325
|
+
self.ecad.cad_data.cad_data_step.add_padstack_instances(padstack_instances, padstack_defs)
|
|
326
|
+
|
|
327
|
+
@pyedb_function_handler()
|
|
328
|
+
def add_drills(self):
|
|
329
|
+
via_list = [
|
|
330
|
+
obj for obj in list(self._pedb.padstacks.instances.values()) if not obj.start_layer == obj.stop_layer
|
|
331
|
+
]
|
|
332
|
+
l1 = len(list(self._pedb.stackup.signal_layers.keys()))
|
|
333
|
+
|
|
334
|
+
self.ecad.cad_data.cad_data_step.add_drill_layer_feature(via_list, "DRILL_1-{}".format(l1))
|
|
335
|
+
|
|
336
|
+
@pyedb_function_handler()
|
|
337
|
+
def from_meter_to_units(self, value, units):
|
|
338
|
+
if isinstance(value, str):
|
|
339
|
+
value = float(value)
|
|
340
|
+
if isinstance(value, list):
|
|
341
|
+
returned_list = []
|
|
342
|
+
for val in value:
|
|
343
|
+
if isinstance(val, str):
|
|
344
|
+
val = float(val)
|
|
345
|
+
if units.lower() == "mm":
|
|
346
|
+
returned_list.append(round(val * 1000, 4))
|
|
347
|
+
if units.lower() == "um":
|
|
348
|
+
returned_list.append(round(val * 1e6, 4))
|
|
349
|
+
if units.lower() == "mils":
|
|
350
|
+
returned_list.append(round(val * 39370.079, 4))
|
|
351
|
+
if units.lower() == "inch":
|
|
352
|
+
returned_list.append(round(val * 39.370079, 4))
|
|
353
|
+
if units.lower() == "cm":
|
|
354
|
+
returned_list.append(round(val * 100, 4))
|
|
355
|
+
return returned_list
|
|
356
|
+
else:
|
|
357
|
+
if units.lower() == "millimeter":
|
|
358
|
+
return round(value * 1000, 4)
|
|
359
|
+
if units.lower() == "micrometer":
|
|
360
|
+
return round(value * 1e6, 4)
|
|
361
|
+
if units.lower() == "mils":
|
|
362
|
+
return round(value * 39370.079, 4)
|
|
363
|
+
if units.lower() == "inch":
|
|
364
|
+
return round(value * 39.370079, 4)
|
|
365
|
+
if units.lower() == "centimeter":
|
|
366
|
+
return round(value * 100, 4)
|
|
367
|
+
|
|
368
|
+
@pyedb_function_handler()
|
|
369
|
+
def write_xml(self):
|
|
370
|
+
if self.file_path:
|
|
371
|
+
ipc = ET.Element("IPC-2581")
|
|
372
|
+
ipc.set("revision", self.revision)
|
|
373
|
+
ipc.set("xmlns", "http://webstds.ipc.org/2581")
|
|
374
|
+
ipc.set("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
|
|
375
|
+
ipc.set("xmlns:xsd", "http://www.w3.org/2001/XMLSchema")
|
|
376
|
+
self.content.write_wml(ipc)
|
|
377
|
+
self.logistic_header.write_xml(ipc)
|
|
378
|
+
self.history_record.write_xml(ipc)
|
|
379
|
+
self.bom.write_xml(ipc)
|
|
380
|
+
self.ecad.write_xml(ipc)
|
|
381
|
+
try:
|
|
382
|
+
ET.indent(ipc)
|
|
383
|
+
except AttributeError:
|
|
384
|
+
pass
|
|
385
|
+
tree = ET.ElementTree(ipc)
|
|
386
|
+
tree.write(self.file_path)
|
|
387
|
+
return True if os.path.exists(self.file_path) else False
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LogisticHeader(object):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.owner = "PyEDB"
|
|
7
|
+
self.sender = "Ansys"
|
|
8
|
+
self.enterprise = "Ansys"
|
|
9
|
+
self.code = "UNKNOWN"
|
|
10
|
+
self.person_name = "eba"
|
|
11
|
+
self.enterprise_ref = "UNKNOWN"
|
|
12
|
+
self.role_ref = "PyEDB"
|
|
13
|
+
|
|
14
|
+
def write_xml(self, root): # pragma no cover
|
|
15
|
+
logistic_header = ET.SubElement(root, "LogisticHeader")
|
|
16
|
+
role = ET.SubElement(logistic_header, "Role")
|
|
17
|
+
role.set("id", self.owner)
|
|
18
|
+
role.set("roleFunction", self.sender)
|
|
19
|
+
enterprise = ET.SubElement(logistic_header, "Enterprise")
|
|
20
|
+
enterprise.set("id", self.enterprise)
|
|
21
|
+
enterprise.set("code", self.code)
|
|
22
|
+
person = ET.SubElement(logistic_header, "Person")
|
|
23
|
+
person.set("name", self.person_name)
|
|
24
|
+
person.set("enterpriseRef", self.enterprise_ref)
|
|
25
|
+
person.set("roleRef", self.role_ref)
|
pyedb/misc/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from xml.dom.minidom import parseString
|
|
2
|
+
import xml.etree.ElementTree as ET
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def write_pretty_xml(root, file_path):
|
|
6
|
+
"""Write the XML in a pretty format."""
|
|
7
|
+
# If we use the commented code below, then the previously existing lines will have double lines added. We need to
|
|
8
|
+
# split and ignore the double lines.
|
|
9
|
+
# xml_str = parseString(ET.tostring(root)).toprettyxml(indent=" " * 4)
|
|
10
|
+
lines = [line for line in parseString(ET.tostring(root)).toprettyxml(indent=" " * 4).split("\n") if line.strip()]
|
|
11
|
+
xml_str = "\n".join(lines)
|
|
12
|
+
|
|
13
|
+
with open(file_path, "w") as f:
|
|
14
|
+
f.write(xml_str)
|