From bce84437e770f6e4ff6923e0582178c055d495da Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 16:34:43 -0700 Subject: [PATCH 01/10] wip renme --- edg/abstract_parts/PartsTablePart.py | 48 ++++++++++++++++++++++------ edg/abstract_parts/SelectorArea.py | 21 ++++++++++-- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/edg/abstract_parts/PartsTablePart.py b/edg/abstract_parts/PartsTablePart.py index c55c48b47..ef2d47378 100644 --- a/edg/abstract_parts/PartsTablePart.py +++ b/edg/abstract_parts/PartsTablePart.py @@ -1,3 +1,4 @@ +import warnings from abc import abstractmethod from typing import Optional, Union, Any @@ -41,9 +42,17 @@ class PartsTablePart(Block): """An interface mixin for a part that is selected from a table, defining parameters to allow manual part selection as well as matching parts.""" - def __init__(self, *args: Any, part: StringLike = "", excluded_parts: ArrayStringLike = [], **kwargs: Any) -> None: + def __init__( + self, + *args: Any, + filter_parts: ArrayStringLike = [], + excluded_parts: ArrayStringLike = [], + part: StringLike = "", + **kwargs: Any, + ) -> None: super().__init__(*args, **kwargs) - self.part = self.ArgParameter(part) + self.filter_parts = self.ArgParameter(filter_parts) + self.part = self.ArgParameter(part) # deprecated self.excluded_parts = self.ArgParameter(excluded_parts) self.actual_part = self.Parameter(StringExpr()) self.matching_parts = self.Parameter(ArrayStringExpr()) @@ -56,7 +65,7 @@ class PartsTableSelector(PartsTablePart, GeneratorBlock, PartsTableBase): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.generator_param(self.part) + self.generator_param(self.filter_parts, self.part) self.generator_param(self.excluded_parts) def _row_filter(self, row: PartsTableRow) -> bool: @@ -64,8 +73,11 @@ def _row_filter(self, row: PartsTableRow) -> bool: Only called within generate(), so has access to GeneratorParam.get(). Subclasses should chain this by and-ing with a super() call.""" part = self.get(self.part) + filter_parts = self.get(self.filter_parts) + if part: + filter_parts.append(part) excluded_parts = self.get(self.excluded_parts) - return ((not part) or (part == row[self.PART_NUMBER_COL])) and ( + return ((not filter_parts) or (row[self.PART_NUMBER_COL] in filter_parts)) and ( (not excluded_parts) or (row[self.PART_NUMBER_COL] not in excluded_parts) ) @@ -88,6 +100,11 @@ def _row_generate(self, row: PartsTableRow) -> None: @override def generate(self) -> None: + super().generate() + + if self.get(self.part): + warnings.warn(f"part replaced with filter_parts taking an array", DeprecationWarning) + matching_table = self._get_table().filter(lambda row: self._row_filter(row)) postprocessed_table = self._table_postprocess(matching_table) postprocessed_table = postprocessed_table.sort_by(self._row_sort_by) @@ -101,9 +118,12 @@ def generate(self) -> None: class SelectorFootprint(PartsTablePart): """Mixin that allows a specified footprint, for Blocks that automatically select a part.""" - def __init__(self, *args: Any, footprint_spec: StringLike = "", **kwargs: Any) -> None: + def __init__( + self, *args: Any, filter_footprints: ArrayStringLike = [], footprint_spec: StringLike = "", **kwargs: Any + ) -> None: super().__init__(*args, **kwargs) - self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint + self.filter_footprints = self.ArgParameter(filter_footprints) # actual_footprint left to the actual footprint + self.footprint_spec = self.ArgParameter(footprint_spec) # deprecated, named because self.footprint taken @non_library @@ -116,13 +136,21 @@ class PartsTableFootprintFilter(PartsTableSelector, SelectorFootprint): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.generator_param(self.footprint_spec) + self.generator_param(self.filter_footprints, self.footprint_spec) + + @override + def generate(self) -> None: + super().generate() + if self.get(self.footprint_spec): + warnings.warn(f"footprint_spec replaced with filter_footprints taking an array", DeprecationWarning) @override def _row_filter(self, row: PartsTableRow) -> bool: - return super()._row_filter(row) and ( - (not self.get(self.footprint_spec)) or self.get(self.footprint_spec) == row[self.KICAD_FOOTPRINT] - ) + footprint_spec = self.get(self.footprint_spec) + filter_footprints = self.get(self.filter_footprints) + if footprint_spec: + filter_footprints.append(footprint_spec) + return super()._row_filter(row) and ((not filter_footprints or row[self.KICAD_FOOTPRINT] in filter_footprints)) @non_library diff --git a/edg/abstract_parts/SelectorArea.py b/edg/abstract_parts/SelectorArea.py index a0d8f338f..e3c0778b4 100644 --- a/edg/abstract_parts/SelectorArea.py +++ b/edg/abstract_parts/SelectorArea.py @@ -1,3 +1,4 @@ +import warnings from typing import Any from typing_extensions import override @@ -23,8 +24,15 @@ class SelectorArea(PartsTablePart): 2512 R=29.3376 D=29.3376 """ - def __init__(self, *args: Any, footprint_area: RangeLike = RangeExpr.ALL, **kwargs: Any) -> None: + def __init__( + self, + *args: Any, + filter_area: RangeLike = RangeExpr.ALL, + footprint_area: RangeLike = RangeExpr.ALL, + **kwargs: Any, + ) -> None: super().__init__(*args, **kwargs) + self.filter_area = self.ArgParameter(filter_area) self.footprint_area = self.ArgParameter(footprint_area) @classmethod @@ -38,12 +46,19 @@ class PartsTableAreaSelector(PartsTableFootprintFilter, SelectorArea): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.generator_param(self.footprint_area) + self.generator_param(self.filter_area, self.footprint_area) + + @override + def generate(self) -> None: + super().generate() + if self.get(self.filter_area) != Range.all(): + warnings.warn(f"area replaced with filter_area", DeprecationWarning) @override def _row_filter(self, row: PartsTableRow) -> bool: + area = self.get(self.filter_area).intersect(self.get(self.footprint_area)) return super()._row_filter(row) and ( - Range.exact(FootprintDataTable.area_of(row[self.KICAD_FOOTPRINT])).fuzzy_in(self.get(self.footprint_area)) + Range.exact(FootprintDataTable.area_of(row[self.KICAD_FOOTPRINT])).fuzzy_in(area) ) @classmethod From 4560de0cfee52ab9c053d334621fd3ccef3a3108 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 16:51:40 -0700 Subject: [PATCH 02/10] wip --- edg/BoardTop.py | 2 +- edg/abstract_parts/SelectorArea.py | 8 +++---- edg/vendor_parts/generic/GenericCapacitor.py | 22 +++++++++---------- edg/vendor_parts/generic/GenericResistor.py | 10 ++++----- .../generic/test_resistor_generic.py | 2 +- edg/vendor_parts/jlc/test_JlcCapacitor.py | 2 +- examples/test_esp_programmer.py | 2 +- examples/test_iot_led_driver.py | 16 +++++++------- examples/test_swd_debugger.py | 4 ++-- examples/test_usb_key.py | 2 +- 10 files changed, 34 insertions(+), 36 deletions(-) diff --git a/edg/BoardTop.py b/edg/BoardTop.py index 66503c7f6..8b193023f 100644 --- a/edg/BoardTop.py +++ b/edg/BoardTop.py @@ -47,7 +47,7 @@ def refinements(self) -> Refinements: (Neopixel, Ws2812b), ], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(4.0)), # at least 0603 + (SelectorArea, ["filter_area"], Range.from_lower(4.0)), # at least 0603 ], ) diff --git a/edg/abstract_parts/SelectorArea.py b/edg/abstract_parts/SelectorArea.py index e3c0778b4..bc8dc1851 100644 --- a/edg/abstract_parts/SelectorArea.py +++ b/edg/abstract_parts/SelectorArea.py @@ -10,7 +10,7 @@ @abstract_block class SelectorArea(PartsTablePart): - """A base mixin that defines a footprint_area range specification for blocks that automatically select parts. + """A base mixin that defines a filter_area range specification for blocks that automatically select parts. Provides no implementation, only defines the specification parameter. Some common areas for SMD parts: @@ -33,7 +33,7 @@ def __init__( ) -> None: super().__init__(*args, **kwargs) self.filter_area = self.ArgParameter(filter_area) - self.footprint_area = self.ArgParameter(footprint_area) + self.footprint_area = self.ArgParameter(footprint_area) # deprecated @classmethod def _footprint_area(cls, footprint_name: str) -> float: @@ -51,8 +51,8 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: @override def generate(self) -> None: super().generate() - if self.get(self.filter_area) != Range.all(): - warnings.warn(f"area replaced with filter_area", DeprecationWarning) + if self.get(self.footprint_area) != Range.all(): + warnings.warn(f"footprint_area replaced with filter_area", DeprecationWarning) @override def _row_filter(self, row: PartsTableRow) -> bool: diff --git a/edg/vendor_parts/generic/GenericCapacitor.py b/edg/vendor_parts/generic/GenericCapacitor.py index 1633d23b4..f36d0c9a9 100644 --- a/edg/vendor_parts/generic/GenericCapacitor.py +++ b/edg/vendor_parts/generic/GenericCapacitor.py @@ -37,17 +37,17 @@ class GenericMlcc(Capacitor, SelectorArea, FootprintBlock, GeneratorBlock): MAX_CAP_PACKAGE = "Capacitor_SMD:C_1206_3216Metric" # default package for largest possible capacitor def __init__( - self, *args: Any, footprint_spec: StringLike = "", derating_coeff: FloatLike = 1.0, **kwargs: Any + self, *args: Any, filter_footprints: ArrayStringLike = [], derating_coeff: FloatLike = 1.0, **kwargs: Any ) -> None: """ footprint specifies an optional constraint on footprint derating_coeff specifies an optional derating coefficient (1.0 = no derating), that does not scale with package. """ super().__init__(*args, **kwargs) - self.footprint_spec = self.ArgParameter(footprint_spec) + self.filter_footprints = self.ArgParameter(filter_footprints) self.derating_coeff = self.ArgParameter(derating_coeff) self.generator_param( - self.capacitance, self.voltage, self.footprint_spec, self.footprint_area, self.derating_coeff + self.capacitance, self.voltage, self.filter_footprints, self.filter_area, self.derating_coeff ) # Output values @@ -119,18 +119,18 @@ def generate(self) -> None: :param voltage: user-specified voltage :param single_nominal_capacitance: used when no single cap with requested capacitance, must generate multiple parallel caps, actually refers to max capacitance for a given part - :param footprint_spec: user-specified package footprint + :param filter_footprints: user-specified package footprint :param derating_coeff: user-specified derating coefficient, if used then footprint_spec must be specified """ super().generate() - footprint = self.get(self.footprint_spec) + filter_footprints = self.get(self.filter_footprints) def select_package(nominal_capacitance: float, voltage: Range) -> Optional[str]: package_options = [ spec for spec in self.PACKAGE_SPECS - if (not footprint or spec.name == footprint) - and (Range.exact(self._footprint_area(spec.name)).fuzzy_in(self.get(self.footprint_area))) + if (not filter_footprints or spec.name in filter_footprints) + and (Range.exact(self._footprint_area(spec.name)).fuzzy_in(self.get(self.filter_area))) ] for package in package_options: @@ -150,15 +150,13 @@ def select_package(nominal_capacitance: float, voltage: Range) -> Optional[str]: self.assign(self.selected_nominal_capacitance, num_caps * nominal_capacitance) - if footprint == "": - split_package = self.MAX_CAP_PACKAGE - else: - split_package = footprint + valid_footprint = select_package(self.SINGLE_CAP_MAX, self.get(self.voltage)) + assert valid_footprint is not None, "cannot select a valid footprint" cap_model = DummyCapacitorFootprint( capacitance=Range.exact(self.SINGLE_CAP_MAX), voltage=self.voltage, - footprint=split_package, + footprint=valid_footprint, value=f"{UnitUtils.num_to_prefix(self.SINGLE_CAP_MAX, 3)}F", ) self.c = ElementDict[DummyCapacitorFootprint]() diff --git a/edg/vendor_parts/generic/GenericResistor.py b/edg/vendor_parts/generic/GenericResistor.py index c6bc2f50f..8c2196bfc 100644 --- a/edg/vendor_parts/generic/GenericResistor.py +++ b/edg/vendor_parts/generic/GenericResistor.py @@ -22,16 +22,16 @@ def __init__( *args: Any, series: IntLike = 24, tolerance: FloatLike = 0.01, - footprint_spec: StringLike = "", + filter_footprints: ArrayStringLike = [], **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) self.series = self.ArgParameter(series) self.tolerance = self.ArgParameter(tolerance) - self.footprint_spec = self.ArgParameter(footprint_spec) + self.filter_footprints = self.ArgParameter(filter_footprints) self.generator_param( - self.resistance, self.power, self.series, self.tolerance, self.footprint_spec, self.footprint_area + self.resistance, self.power, self.series, self.tolerance, self.filter_footprints, self.filter_area ) @override @@ -58,8 +58,8 @@ def generate(self) -> None: (package_power, package) for package_power, package in self.PACKAGE_POWER if package_power >= self.get(self.power).upper - and (not self.get(self.footprint_spec) or package == self.get(self.footprint_spec)) - and (Range.exact(self._footprint_area(package)).fuzzy_in(self.get(self.footprint_area))) + and (not self.get(self.filter_footprints) or package in self.get(self.filter_footprints)) + and (Range.exact(self._footprint_area(package)).fuzzy_in(self.get(self.filter_area))) ] if not suitable_packages: raise ValueError("no suitable resistor packages") diff --git a/edg/vendor_parts/generic/test_resistor_generic.py b/edg/vendor_parts/generic/test_resistor_generic.py index 4e5cc8f87..11a243dd1 100644 --- a/edg/vendor_parts/generic/test_resistor_generic.py +++ b/edg/vendor_parts/generic/test_resistor_generic.py @@ -50,7 +50,7 @@ def test_non_e12_resistor(self) -> None: def test_min_package(self) -> None: compiled = ScalaCompiler.compile( - ResistorTestTop, Refinements(instance_values=[(["dut", "footprint_area"], Range.from_lower(4.0))]) + ResistorTestTop, Refinements(instance_values=[(["dut", "filter_area"], Range.from_lower(4.0))]) ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Resistor_SMD:R_0603_1608Metric") self.assertEqual(compiled.get_value(["dut", "fp_value"]), "1k, 1%, 0.1 W") diff --git a/edg/vendor_parts/jlc/test_JlcCapacitor.py b/edg/vendor_parts/jlc/test_JlcCapacitor.py index c60d3aecb..fa4ce7fc9 100644 --- a/edg/vendor_parts/jlc/test_JlcCapacitor.py +++ b/edg/vendor_parts/jlc/test_JlcCapacitor.py @@ -34,7 +34,7 @@ def test_capacitor_part(self) -> None: def test_capacitor_min_package(self) -> None: compiled = ScalaCompiler.compile( - JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "footprint_area"], Range.from_lower(4.0))]) + JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "filter_area"], Range.from_lower(4.0))]) ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Capacitor_SMD:C_0603_1608Metric") self.assertEqual(compiled.get_value(["dut", "fp_part"]), "0603B103K500NT") diff --git a/examples/test_esp_programmer.py b/examples/test_esp_programmer.py index 6d4097d06..e34eeda73 100644 --- a/examples/test_esp_programmer.py +++ b/examples/test_esp_programmer.py @@ -85,7 +85,7 @@ def refinements(self) -> Refinements: ], class_refinements=[], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(1.5)), # at least 0402 + (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 (TableBjt, ["part"], "BC846BW 1B"), # default option is OOS ], ) diff --git a/examples/test_iot_led_driver.py b/examples/test_iot_led_driver.py index 97d6f926a..89b06e98f 100644 --- a/examples/test_iot_led_driver.py +++ b/examples/test_iot_led_driver.py @@ -186,15 +186,15 @@ def refinements(self) -> Refinements: (["reg_3v3", "power_path", "in_cap", "cap", "voltage_margin"], 1.25), # use a 1206 25 or 35v part (["qwiic", "pwr", "current_draw"], Range(0.0, 0.08)), # use 1210 inductor ( - ["mcu", "pi", "c1", "footprint_area"], + ["mcu", "pi", "c1", "filter_area"], Range(4.0, float("inf")), ), # use 0603 consistently since that's what's available - (["mcu", "pi", "c2", "footprint_area"], Range(4.0, float("inf"))), - (["mcu", "pi", "l", "footprint_area"], Range(4.0, float("inf"))), - (["reg_3v3", "fb", "div", "top_res", "footprint_area"], Range(4.0, float("inf"))), - (["reg_3v3", "fb", "div", "bottom_res", "footprint_area"], Range(4.0, float("inf"))), - (["v12_sense", "div", "top_res", "footprint_area"], Range(4.0, float("inf"))), - (["v12_sense", "div", "bottom_res", "footprint_area"], Range(4.0, float("inf"))), + (["mcu", "pi", "c2", "filter_area"], Range(4.0, float("inf"))), + (["mcu", "pi", "l", "filter_area"], Range(4.0, float("inf"))), + (["reg_3v3", "fb", "div", "top_res", "filter_area"], Range(4.0, float("inf"))), + (["reg_3v3", "fb", "div", "bottom_res", "filter_area"], Range(4.0, float("inf"))), + (["v12_sense", "div", "top_res", "filter_area"], Range(4.0, float("inf"))), + (["v12_sense", "div", "bottom_res", "filter_area"], Range(4.0, float("inf"))), (["reg_3v3", "en_res", "resistance"], Range(100e3, 1e6)), # wider selection of resistors ], class_refinements=[ @@ -206,7 +206,7 @@ def refinements(self) -> Refinements: (TagConnect, TagConnectNonLegged), ], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(1.5)), # at least 0402 + (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 (CompactKeystone5015, ["lcsc_part"], "C5199798"), # RH-5015, which is actually in stock ], ) diff --git a/examples/test_swd_debugger.py b/examples/test_swd_debugger.py index 923237d54..0f2a98e25 100644 --- a/examples/test_swd_debugger.py +++ b/examples/test_swd_debugger.py @@ -192,7 +192,7 @@ def refinements(self) -> Refinements: (["target_reg", "out_cap", "cap", "capacitance"], Range.from_tolerance(4.7e-6, 0.2)), ], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(1.5)), # at least 0402 + (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 ], ) @@ -309,7 +309,7 @@ def refinements(self) -> Refinements: (TagConnect, TagConnectNonLegged), ], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(1.5)), # at least 0402 + (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 ], ) diff --git a/examples/test_usb_key.py b/examples/test_usb_key.py index 7dd6c3e03..33cf8c393 100644 --- a/examples/test_usb_key.py +++ b/examples/test_usb_key.py @@ -122,7 +122,7 @@ def refinements(self) -> Refinements: (["packed_mcu_vdd1_cap", "cap", "capacitance_minimum_size"], False), ], class_values=[ - (SelectorArea, ["footprint_area"], Range.from_lower(1.5)), # at least 0402 + (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 (Lp5907, ["ic", "footprint_spec"], "Package_DFN_QFN:UDFN-4-1EP_1x1mm_P0.65mm_EP0.48x0.48mm"), ], ) From 688b5b47ebcb539e5c9cc27ace58482b4ca69640 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 16:58:55 -0700 Subject: [PATCH 03/10] wip --- .../generic/test_capacitor_generic.py | 6 +-- .../generic/test_resistor_generic.py | 2 +- edg/vendor_parts/jlc/test_JlcCapacitor.py | 4 +- examples/test_bldc_controller.py | 10 ++-- examples/test_ble_joystick.py | 2 +- examples/test_can_adapter.py | 2 +- examples/test_datalogger.py | 4 +- examples/test_fcml.py | 9 ++-- examples/test_high_switch.py | 46 +++++++++---------- examples/test_iot_blinds.py | 4 +- examples/test_iot_fan.py | 4 +- examples/test_iot_iron.py | 4 +- examples/test_iot_thermal_camera.py | 4 +- examples/test_lora.py | 8 ++-- examples/test_multimeter.py | 2 +- examples/test_pcbbot.py | 5 +- examples/test_robotcrawler.py | 2 +- examples/test_robotdriver.py | 2 +- examples/test_simon.py | 8 ++-- examples/test_usb_source_measure.py | 21 +++++---- 20 files changed, 79 insertions(+), 70 deletions(-) diff --git a/edg/vendor_parts/generic/test_capacitor_generic.py b/edg/vendor_parts/generic/test_capacitor_generic.py index ad3849272..073018ca4 100644 --- a/edg/vendor_parts/generic/test_capacitor_generic.py +++ b/edg/vendor_parts/generic/test_capacitor_generic.py @@ -69,7 +69,7 @@ def test_capacitor(self) -> None: def test_capacitor_footprint(self) -> None: compiled = ScalaCompiler.compile( CapacitorGenericTestTop, - Refinements(instance_values=[(["dut", "footprint_spec"], "Capacitor_SMD:C_1206_3216Metric")]), + Refinements(instance_values=[(["dut", "filter_footprints"], ["Capacitor_SMD:C_1206_3216Metric"])]), ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Capacitor_SMD:C_1206_3216Metric") self.assertEqual(compiled.get_value(["dut", "fp_value"]), "100nF") @@ -104,7 +104,7 @@ def test_derated_capacitor(self) -> None: DeratedCapacitorGenericTestTop, Refinements( instance_values=[ - (["dut", "footprint_spec"], "Capacitor_SMD:C_1206_3216Metric"), + (["dut", "filter_footprints"], ["Capacitor_SMD:C_1206_3216Metric"]), (["dut", "derating_coeff"], 0.5), ] ), @@ -117,7 +117,7 @@ def test_derated_multi_capacitor(self) -> None: BigMultiCapacitorGenericTestTop, Refinements( instance_values=[ - (["dut", "footprint_spec"], "Capacitor_SMD:C_1206_3216Metric"), + (["dut", "filter_footprints"], ["Capacitor_SMD:C_1206_3216Metric"]), (["dut", "derating_coeff"], 0.5), ] ), diff --git a/edg/vendor_parts/generic/test_resistor_generic.py b/edg/vendor_parts/generic/test_resistor_generic.py index 11a243dd1..271c58198 100644 --- a/edg/vendor_parts/generic/test_resistor_generic.py +++ b/edg/vendor_parts/generic/test_resistor_generic.py @@ -58,7 +58,7 @@ def test_min_package(self) -> None: def test_footprint(self) -> None: compiled = ScalaCompiler.compile( ResistorTestTop, - Refinements(instance_values=[(["dut", "footprint_spec"], "Resistor_SMD:R_1206_3216Metric")]), + Refinements(instance_values=[(["dut", "filter_footprints"], ["Resistor_SMD:R_1206_3216Metric"])]), ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Resistor_SMD:R_1206_3216Metric") self.assertEqual(compiled.get_value(["dut", "fp_value"]), "1k, 1%, 0.25 W") diff --git a/edg/vendor_parts/jlc/test_JlcCapacitor.py b/edg/vendor_parts/jlc/test_JlcCapacitor.py index fa4ce7fc9..ca711dee2 100644 --- a/edg/vendor_parts/jlc/test_JlcCapacitor.py +++ b/edg/vendor_parts/jlc/test_JlcCapacitor.py @@ -27,7 +27,7 @@ def test_capacitor(self) -> None: def test_capacitor_part(self) -> None: compiled = ScalaCompiler.compile( - JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "part"], "CL21B103KBANNNC")]) + JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "filter_parts"], ["CL21B103KBANNNC"])]) ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Capacitor_SMD:C_0805_2012Metric") self.assertEqual(compiled.get_value(["dut", "fp_part"]), "CL21B103KBANNNC") @@ -43,7 +43,7 @@ def test_capacitor_min_package(self) -> None: def test_capacitor_footprint(self) -> None: compiled = ScalaCompiler.compile( JlcCapacitorTestTop, - Refinements(instance_values=[(["dut", "footprint_spec"], "Capacitor_SMD:C_0805_2012Metric")]), + Refinements(instance_values=[(["dut", "filter_footprints"], ["Capacitor_SMD:C_0805_2012Metric"])]), ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Capacitor_SMD:C_0805_2012Metric") diff --git a/examples/test_bldc_controller.py b/examples/test_bldc_controller.py index 28afe6038..165cf14fc 100644 --- a/examples/test_bldc_controller.py +++ b/examples/test_bldc_controller.py @@ -230,22 +230,22 @@ def refinements(self) -> Refinements: ), (["isense", "sense", "res", "res", "require_basic_part"], False), (["bldc_drv", "pgnd_res[1]", "res", "res", "require_basic_part"], False), - (["bldc_drv", "pgnd_res[1]", "res", "res", "footprint_spec"], "Resistor_SMD:R_2512_6332Metric"), + (["bldc_drv", "pgnd_res[1]", "res", "res", "filter_footprints"], ["Resistor_SMD:R_2512_6332Metric"]), ( ["bldc_drv", "pgnd_res[2]", "res", "res", "require_basic_part"], ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "require_basic_part"]), ), ( - ["bldc_drv", "pgnd_res[2]", "res", "res", "footprint_spec"], - ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "footprint_spec"]), + ["bldc_drv", "pgnd_res[2]", "res", "res", "filter_footprints"], + ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "filter_footprints"]), ), ( ["bldc_drv", "pgnd_res[3]", "res", "res", "require_basic_part"], ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "require_basic_part"]), ), ( - ["bldc_drv", "pgnd_res[3]", "res", "res", "footprint_spec"], - ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "footprint_spec"]), + ["bldc_drv", "pgnd_res[3]", "res", "res", "filter_footprints"], + ParamValue(["bldc_drv", "pgnd_res[1]", "res", "res", "filter_footprints"]), ), (["bldc_drv", "vm_cap_bulk", "cap", "voltage_margin"], 1.5), # allow using a 50V cap (["bldc_drv", "cp_cap", "voltage_margin"], 1.5), # allow using a 50V cap diff --git a/examples/test_ble_joystick.py b/examples/test_ble_joystick.py index 4939c79dd..c58ef4610 100644 --- a/examples/test_ble_joystick.py +++ b/examples/test_ble_joystick.py @@ -304,7 +304,7 @@ def refinements(self) -> Refinements: (Switch, SmtSwitch), ], class_values=[ - (ProtectionZenerDiode, ["diode", "footprint_spec"], "Diode_SMD:D_SOD-123"), + (ProtectionZenerDiode, ["diode", "filter_footprints"], ["Diode_SMD:D_SOD-123"]), (CompactKeystone5015, ["lcsc_part"], "C5199798"), ], ) diff --git a/examples/test_can_adapter.py b/examples/test_can_adapter.py index 831807299..818a75536 100644 --- a/examples/test_can_adapter.py +++ b/examples/test_can_adapter.py @@ -96,7 +96,7 @@ def refinements(self) -> Refinements: (["mcu", "programming"], "uart-auto"), (["reg_3v3", "power_path", "inductor", "manual_frequency_rating"], Range(0, 9e6)), (["reg_3v3", "power_path", "in_cap", "cap", "voltage_margin"], 1.0), - (["reg_3v3", "power_path", "inductor", "footprint_spec"], "Inductor_SMD:L_1210_3225Metric"), + (["reg_3v3", "power_path", "inductor", "filter_footprints"], ["Inductor_SMD:L_1210_3225Metric"]), ], class_refinements=[ (EspProgrammingHeader, EspProgrammingTc2030), diff --git a/examples/test_datalogger.py b/examples/test_datalogger.py index 9e95c42bd..21e52ed00 100644 --- a/examples/test_datalogger.py +++ b/examples/test_datalogger.py @@ -302,7 +302,7 @@ def refinements(self) -> Refinements: "swd_swo=PIO0_8", ], ), - (["pwr_5v", "power_path", "inductor", "part"], "NR5040T220M"), # peg to prior part selection + (["pwr_5v", "power_path", "inductor", "filter_parts"], ["NR5040T220M"]), # peg to prior part selection ( ["pwr_5v", "power_path", "inductor_current_ripple"], Range(0.01, 0.6), @@ -312,7 +312,7 @@ def refinements(self) -> Refinements: # JLC does not have frequency specs, must be checked TODO (["pwr_5v", "power_path", "inductor", "manual_frequency_rating"], Range.all()), # keep netlist footprints as libraries change - (["buffer", "fet", "footprint_spec"], "Package_TO_SOT_SMD:SOT-223-3_TabPin2"), + (["buffer", "fet", "filter_footprints"], ["Package_TO_SOT_SMD:SOT-223-3_TabPin2"]), (["eink", "boost", "sense", "resistance"], Range.from_tolerance(3.3, 0.05)), # 3R not standard ], class_refinements=[(Fuse, CanFuse)], diff --git a/examples/test_fcml.py b/examples/test_fcml.py index b059721b1..6d97780b2 100644 --- a/examples/test_fcml.py +++ b/examples/test_fcml.py @@ -574,8 +574,11 @@ def refinements(self) -> Refinements: ], ), # flying caps need to be beefier for high current rating (which isn't modeled) - (["conv", "sw[1]", "cap", "footprint_spec"], "Capacitor_SMD:C_1206_3216Metric"), - (["conv", "sw[2]", "cap", "footprint_spec"], ParamValue(["conv", "sw[1]", "cap", "footprint_spec"])), + (["conv", "sw[1]", "cap", "filter_footprints"], ["Capacitor_SMD:C_1206_3216Metric"]), + ( + ["conv", "sw[2]", "cap", "filter_footprints"], + ParamValue(["conv", "sw[1]", "cap", "filter_footprints"]), + ), # JLC does not have frequency specs, must be checked TODO (["conv", "power_path", "inductor", "manual_frequency_rating"], Range.all()), (["reg_vgate", "power_path", "inductor", "manual_frequency_rating"], Range.all()), @@ -592,7 +595,7 @@ def refinements(self) -> Refinements: (UsbEsdDiode, Pgb102st23), # for common parts with the rest of the panel ], class_values=[ - (Fet, ["footprint_spec"], "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm"), # don't seem to be alternatives + (Fet, ["filter_footprints"], ["Package_SO:SOIC-8_3.9x4.9mm_P1.27mm"]), # don't seem to be alternatives (CompactKeystone5015, ["lcsc_part"], "C5199798"), # RH-5015, which is actually in stock # for compatibility, this board was laid out before derating was supported and does not compile otherwise (Capacitor, ["voltage_margin"], 1.0), diff --git a/examples/test_high_switch.py b/examples/test_high_switch.py index c8f66c90c..b16338e78 100644 --- a/examples/test_high_switch.py +++ b/examples/test_high_switch.py @@ -368,50 +368,50 @@ def refinements(self) -> Refinements: (["light[5]", "drv[0]", "drv", "frequency"], Range(0, 0)), (["light[5]", "drv[1]", "drv", "frequency"], Range(0, 0)), # keep netlist footprints as libraries change - (["light[0]", "drv[0]", "drv", "footprint_spec"], "Package_TO_SOT_SMD:TO-252-2"), + (["light[0]", "drv[0]", "drv", "filter_footprints"], ["Package_TO_SOT_SMD:TO-252-2"]), ( - ["light[0]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[0]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[1]", "drv[0]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[1]", "drv[0]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[1]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[1]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[2]", "drv[0]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[2]", "drv[0]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[2]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[2]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[3]", "drv[0]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[3]", "drv[0]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[3]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[3]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[4]", "drv[0]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[4]", "drv[0]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[4]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[4]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[5]", "drv[0]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[5]", "drv[0]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ( - ["light[5]", "drv[1]", "drv", "footprint_spec"], - ParamValue(["light[0]", "drv[0]", "drv", "footprint_spec"]), + ["light[5]", "drv[1]", "drv", "filter_footprints"], + ParamValue(["light[0]", "drv[0]", "drv", "filter_footprints"]), ), ], class_refinements=[(Fuse, CanFuse)], diff --git a/examples/test_iot_blinds.py b/examples/test_iot_blinds.py index 7e31a8338..2d649ada9 100644 --- a/examples/test_iot_blinds.py +++ b/examples/test_iot_blinds.py @@ -165,7 +165,7 @@ def refinements(self) -> Refinements: ), (["mcu", "programming"], "uart-auto"), (["reg_3v3", "power_path", "inductor", "manual_frequency_rating"], Range(0, 9e6)), - (["drv", "isen_res", "res", "footprint_spec"], "Resistor_SMD:R_1206_3216Metric"), + (["drv", "isen_res", "res", "filter_footprints"], ["Resistor_SMD:R_1206_3216Metric"]), (["drv", "isen_res", "res", "require_basic_part"], False), (["reg_3v3", "power_path", "in_cap", "cap", "voltage_margin"], 1.0), # 15uH inductors are more common @@ -317,7 +317,7 @@ def refinements(self) -> Refinements: ), (["mcu", "programming"], "uart-auto"), (["reg_3v3", "power_path", "inductor", "manual_frequency_rating"], Range(0, 9e6)), - (["drv", "isen_res", "res", "footprint_spec"], "Resistor_SMD:R_1206_3216Metric"), + (["drv", "isen_res", "res", "filter_footprints"], ["Resistor_SMD:R_1206_3216Metric"]), (["drv", "isen_res", "res", "require_basic_part"], False), (["reg_3v3", "power_path", "in_cap", "cap", "voltage_margin"], 1.0), # 15uH inductors are more common diff --git a/examples/test_iot_fan.py b/examples/test_iot_fan.py index 51f59dc33..dd74d4a51 100644 --- a/examples/test_iot_fan.py +++ b/examples/test_iot_fan.py @@ -241,7 +241,7 @@ def refinements(self) -> Refinements: "i2c2.sda=6", # LP_I2C_SDA on -C6 ], ), - (["fan_drv", "drv", "footprint_spec"], "Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"), + (["fan_drv", "drv", "filter_footprints"], ["Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"]), # gate voltage limit parsing is very unreliable (["fan_drv", "drv", "gate_voltage"], Range(0, 0)), (["vin_sense", "Rs", "res", "res", "require_basic_part"], False), # current sense resistor @@ -267,7 +267,7 @@ def refinements(self) -> Refinements: (Esp32s3_Wroom_1, ["programming"], "uart-auto"), (JlcInductor, ["manual_frequency_rating"], Range(0, 9e6)), (CompactKeystone5015, ["lcsc_part"], "C5199798"), - (ProtectionZenerDiode, ["diode", "footprint_spec"], "Diode_SMD:D_SOD-123"), + (ProtectionZenerDiode, ["diode", "filter_footprints"], ["Diode_SMD:D_SOD-123"]), (Fusb302b, ["ic", "vbus", "voltage_limits"], Range(4.0, 28.0)), # abs max ratings ], ) diff --git a/examples/test_iot_iron.py b/examples/test_iot_iron.py index 26aa3e978..ec9b7f796 100644 --- a/examples/test_iot_iron.py +++ b/examples/test_iot_iron.py @@ -230,8 +230,8 @@ def refinements(self) -> Refinements: ), (["mcu", "programming"], "uart-auto"), ( - ["iron", "isense_res", "res", "res", "footprint_spec"], - "Resistor_SMD:R_2512_6332Metric", + ["iron", "isense_res", "res", "res", "filter_footprints"], + ["Resistor_SMD:R_2512_6332Metric"], ), # more power headroom (["iron", "isense_res", "res", "res", "require_basic_part"], False), # these will be enforced by the firmware control mechanism diff --git a/examples/test_iot_thermal_camera.py b/examples/test_iot_thermal_camera.py index fd47f25e4..39f8c8e84 100644 --- a/examples/test_iot_thermal_camera.py +++ b/examples/test_iot_thermal_camera.py @@ -768,13 +768,13 @@ def refinements(self) -> Refinements: (["reg_poe", "hf_cap", "cap", "voltage_margin"], 1.5), (["eth", "cap", "voltage_margin"], 1.0), # 1kV rated only (["reg_poe", "power_path", "in_cap", "cap", "voltage_margin"], 1.5), - (["poe", "prot", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), + (["poe", "prot", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), (["poe", "den", "resistance"], Range.from_tolerance(25000, 0.05)), # find a basic part (["phy", "exres1", "res", "require_basic_part"], False), ], class_values=[ (CompactKeystone5015, ["lcsc_part"], "C5199798"), - (ProtectionZenerDiode, ["diode", "footprint_spec"], "Diode_SMD:D_SOD-123"), + (ProtectionZenerDiode, ["diode", "filter_footprints"], ["Diode_SMD:D_SOD-123"]), (JlcInductor, ["manual_frequency_rating"], Range(0, 9e6)), ], ) diff --git a/examples/test_lora.py b/examples/test_lora.py index 36045c325..d529b25ec 100644 --- a/examples/test_lora.py +++ b/examples/test_lora.py @@ -198,10 +198,10 @@ def refinements(self) -> Refinements: (["nfc", "damp", "r2", "require_basic_part"], False), (["nfc", "match", "cp1", "require_basic_part"], False), (["nfc", "match", "cp2", "require_basic_part"], False), - (["nfc", "cvdd1", "cap", "footprint_spec"], "Capacitor_SMD:C_0805_2012Metric"), - (["nfc", "cvdd2", "cap", "footprint_spec"], "Capacitor_SMD:C_0805_2012Metric"), - (["nfc", "ctvdd1", "cap", "footprint_spec"], "Capacitor_SMD:C_0805_2012Metric"), - (["nfc", "ctvdd2", "cap", "footprint_spec"], "Capacitor_SMD:C_0805_2012Metric"), + (["nfc", "cvdd1", "cap", "filter_footprints"], ["Capacitor_SMD:C_0805_2012Metric"]), + (["nfc", "cvdd2", "cap", "filter_footprints"], ["Capacitor_SMD:C_0805_2012Metric"]), + (["nfc", "ctvdd1", "cap", "filter_footprints"], ["Capacitor_SMD:C_0805_2012Metric"]), + (["nfc", "ctvdd2", "cap", "filter_footprints"], ["Capacitor_SMD:C_0805_2012Metric"]), (["nfc", "cvdd1", "cap", "require_basic_part"], False), (["nfc", "cvdd2", "cap", "require_basic_part"], False), (["nfc", "ctvdd1", "cap", "require_basic_part"], False), diff --git a/examples/test_multimeter.py b/examples/test_multimeter.py index 201cad1ab..c066995a8 100644 --- a/examples/test_multimeter.py +++ b/examples/test_multimeter.py @@ -398,7 +398,7 @@ def refinements(self) -> Refinements: Range(float("-inf"), float("inf")), ), # allow the regulator to go into tracking mode (["reg_5v", "fb", "div", "series"], 12), # JLC has limited resistors - (["measure", "res", "footprint_spec"], "Resistor_SMD:R_2512_6332Metric"), # beefy input resistor + (["measure", "res", "filter_footprints"], ["Resistor_SMD:R_2512_6332Metric"]), # beefy input resistor (["measure", "res", "fp_mfr"], "Bourns Inc."), (["measure", "res", "fp_part"], "CHV2512-F*-1004***"), # IMPORTANT! Most 2512 resistors are rated to ~200V working voltage, this one is up to 3kV. diff --git a/examples/test_pcbbot.py b/examples/test_pcbbot.py index 49a7e26dc..f4ba23ef9 100644 --- a/examples/test_pcbbot.py +++ b/examples/test_pcbbot.py @@ -207,7 +207,10 @@ def refinements(self) -> Refinements: ], ), (["expander", "pin_assigns"], []), - (["prot_batt", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), # big diodes to dissipate more power + ( + ["prot_batt", "diode", "filter_footprints"], + ["Diode_SMD:D_SMA"], + ), # big diodes to dissipate more power (["reg_3v3", "ic", "actual_dropout"], Range(0.0, 0.3)), # tighter dropout from lower current draw ], class_refinements=[ diff --git a/examples/test_robotcrawler.py b/examples/test_robotcrawler.py index d68e6c5e8..dd03c084e 100644 --- a/examples/test_robotcrawler.py +++ b/examples/test_robotcrawler.py @@ -258,7 +258,7 @@ def refinements(self) -> Refinements: ], ), (["mcu", "programming"], "uart-auto"), - (["reg_14v", "inductor", "part"], "CBC3225T220KR"), + (["reg_14v", "inductor", "filter_parts"], ["CBC3225T220KR"]), (["reg_14v", "inductor", "manual_frequency_rating"], Range(0, 17e6)), # 17MHz self-resonant (["reg_14v", "out_cap", "cap", "voltage_margin"], 1.1), ], diff --git a/examples/test_robotdriver.py b/examples/test_robotdriver.py index fda67cce4..9e56781fe 100644 --- a/examples/test_robotdriver.py +++ b/examples/test_robotdriver.py @@ -225,7 +225,7 @@ def refinements(self) -> Refinements: ], ), (["isense", "out", "signal"], Range(0.1, 2.45)), # trade range for resolution - (["isense", "sense", "res", "res", "footprint_spec"], "Resistor_SMD:R_2512_6332Metric"), + (["isense", "sense", "res", "res", "filter_footprints"], ["Resistor_SMD:R_2512_6332Metric"]), (["isense", "sense", "res", "res", "require_basic_part"], False), # JLC does not have frequency specs, must be checked TODO (["reg_3v3", "power_path", "inductor", "frequency"], Range(0, 0)), diff --git a/examples/test_simon.py b/examples/test_simon.py index 764e50795..c3b240940 100644 --- a/examples/test_simon.py +++ b/examples/test_simon.py @@ -124,10 +124,10 @@ def refinements(self) -> Refinements: # JLC does not have frequency specs, must be checked TODO (["pwr", "power_path", "inductor", "manual_frequency_rating"], Range.all()), # keep netlist footprints as libraries change - (["btn_drv[0]", "drv", "footprint_spec"], "Package_TO_SOT_SMD:TO-252-2"), - (["btn_drv[1]", "drv", "footprint_spec"], ParamValue(["btn_drv[0]", "drv", "footprint_spec"])), - (["btn_drv[2]", "drv", "footprint_spec"], ParamValue(["btn_drv[0]", "drv", "footprint_spec"])), - (["btn_drv[3]", "drv", "footprint_spec"], ParamValue(["btn_drv[0]", "drv", "footprint_spec"])), + (["btn_drv[0]", "drv", "filter_footprints"], ["Package_TO_SOT_SMD:TO-252-2"]), + (["btn_drv[1]", "drv", "filter_footprints"], ParamValue(["btn_drv[0]", "drv", "filter_footprints"])), + (["btn_drv[2]", "drv", "filter_footprints"], ParamValue(["btn_drv[0]", "drv", "filter_footprints"])), + (["btn_drv[3]", "drv", "filter_footprints"], ParamValue(["btn_drv[0]", "drv", "filter_footprints"])), ], instance_refinements=[ (["mcu"], Nucleo_F303k8), diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index 45c82a8c4..3dd7ffa39 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1010,12 +1010,12 @@ def refinements(self) -> Refinements: (["reg_v12", "power_path", "inductor", "manual_frequency_rating"], Range.all()), (["conv", "power_path", "inductor", "manual_frequency_rating"], Range.all()), (["reg_vcontrol", "power_path", "inductor", "manual_frequency_rating"], Range.all()), - (["vusb_sense", "Rs", "res", "res", "footprint_spec"], "Resistor_SMD:R_1206_3216Metric"), + (["vusb_sense", "Rs", "res", "res", "filter_footprints"], ["Resistor_SMD:R_1206_3216Metric"]), ( - ["convin_sense", "Rs", "res", "res", "footprint_spec"], - ParamValue(["vusb_sense", "Rs", "res", "res", "footprint_spec"]), + ["convin_sense", "Rs", "res", "res", "filter_footprints"], + ParamValue(["vusb_sense", "Rs", "res", "res", "filter_footprints"]), ), - (["ramp", "drv", "footprint_spec"], "Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"), + (["ramp", "drv", "filter_footprints"], ["Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"]), # less aggressive derating for smaller part (["control", "driver", "cap_in1", "cap", "voltage_margin"], 1.25), # ignore derating on 20v - it's really broken =( @@ -1038,8 +1038,11 @@ def refinements(self) -> Refinements: ), # TODO model is broken for unknown reasons (["boot", "c_fly_pos", "voltage_margin"], 1.1), (["boot", "c_fly_neg", "voltage_margin"], 1.1), - (["conv", "boost_sw", "low_fet", "footprint_spec"], "Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"), - (["conv", "boost_sw", "low_fet", "part"], "BSC093N04LSG"), # lower total power + ( + ["conv", "boost_sw", "low_fet", "filter_footprints"], + ["Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"], + ), + (["conv", "boost_sw", "low_fet", "filter_parts"], ["BSC093N04LSG"]), # lower total power # require all FETs to be the same; note boost must elaborate first (["conv", "buck_sw", "low_fet", "part"], ParamValue(["conv", "boost_sw", "low_fet", "actual_part"])), (["conv", "buck_sw", "high_fet", "part"], ParamValue(["conv", "boost_sw", "low_fet", "actual_part"])), @@ -1055,9 +1058,9 @@ def refinements(self) -> Refinements: (["control", "driver", "high_fet", "part_spec"], "IRF540N"), (["control", "driver", "low_fet", "footprint_spec"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), (["control", "driver", "low_fet", "part_spec"], "IRF9540"), # has a 30V/4A SOA - (["prot_vusb", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), - (["prot_conv", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), - (["prot_3v3", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), + (["prot_vusb", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), + (["prot_conv", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), + (["prot_3v3", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), # reduce maximum SSR drive current to be within the IO expander limit (["control", "isense", "ranges[0]", "pwr_sw", "ic", "led_current_recommendation"], Range(0.002, 0.010)), (["control", "isense", "ranges[1]", "pwr_sw", "ic", "led_current_recommendation"], Range(0.002, 0.010)), From 4b28409c0fd532357cf8469405b396251561ea9a Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 16:59:56 -0700 Subject: [PATCH 04/10] wip --- examples/test_esp_programmer.py | 2 +- examples/test_iot_display.py | 2 +- examples/test_usb_source_measure.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/test_esp_programmer.py b/examples/test_esp_programmer.py index e34eeda73..f19474c6c 100644 --- a/examples/test_esp_programmer.py +++ b/examples/test_esp_programmer.py @@ -86,7 +86,7 @@ def refinements(self) -> Refinements: class_refinements=[], class_values=[ (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 - (TableBjt, ["part"], "BC846BW 1B"), # default option is OOS + (TableBjt, ["filter_parts"], ["BC846BW 1B"]), # default option is OOS ], ) diff --git a/examples/test_iot_display.py b/examples/test_iot_display.py index 420bfed47..4ee5b4d75 100644 --- a/examples/test_iot_display.py +++ b/examples/test_iot_display.py @@ -196,7 +196,7 @@ def refinements(self) -> Refinements: (["reg_3v3", "power_path", "inductor", "manual_frequency_rating"], Range(0, 10e6)), (["reg_3v3", "fb", "impedance"], Range(20000.0, 100000.0)), (["epd", "boost", "sense", "require_basic_part"], False), # 3R is not a basic part - (["epd", "boost", "inductor", "part"], "CBC3225T680KR"), # automated selection OOS + (["epd", "boost", "inductor", "filter_parts"], ["CBC3225T680KR"]), # automated selection OOS ], class_refinements=[ (EspProgrammingHeader, EspProgrammingTc2030), diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index 3dd7ffa39..e59d00f0b 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1105,7 +1105,7 @@ def refinements(self) -> Refinements: ParamValue(["control", "tvs_n", "lcsc_part"]), ), # note, 5v zener diode # out of stock / unassembleable parts - (["conv", "power_path", "out_cap", "cap", "part"], "C3216X5R1V226MTJ00E"), + (["conv", "power_path", "out_cap", "cap", "filter_parts"], ["C3216X5R1V226MTJ00E"]), ], class_values=[ (CompactKeystone5015, ["lcsc_part"], "C5199798"), From 7cb85547daa93b73f8b91167234191a882db0601 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:13:57 -0700 Subject: [PATCH 05/10] wip --- edg/abstract_parts/PartsTablePart.py | 23 ++++++------------- .../SpeakerDriver_Max98357a.py | 18 ++++++--------- edg/parts/power/converter/LinearRegulators.py | 6 ++--- edg/vendor_parts/generic/GenericCapacitor.py | 2 +- edg/vendor_parts/jlc/test_JlcCapacitor.py | 2 +- examples/test_datalogger.py | 2 +- examples/test_esp_programmer.py | 2 +- examples/test_iot_display.py | 2 +- examples/test_robotcrawler.py | 2 +- examples/test_usb_key.py | 2 +- examples/test_usb_source_measure.py | 4 ++-- 11 files changed, 26 insertions(+), 39 deletions(-) diff --git a/edg/abstract_parts/PartsTablePart.py b/edg/abstract_parts/PartsTablePart.py index ef2d47378..2b66bd422 100644 --- a/edg/abstract_parts/PartsTablePart.py +++ b/edg/abstract_parts/PartsTablePart.py @@ -45,14 +45,12 @@ class PartsTablePart(Block): def __init__( self, *args: Any, - filter_parts: ArrayStringLike = [], - excluded_parts: ArrayStringLike = [], part: StringLike = "", + excluded_parts: ArrayStringLike = [], **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) - self.filter_parts = self.ArgParameter(filter_parts) - self.part = self.ArgParameter(part) # deprecated + self.part = self.ArgParameter(part) self.excluded_parts = self.ArgParameter(excluded_parts) self.actual_part = self.Parameter(StringExpr()) self.matching_parts = self.Parameter(ArrayStringExpr()) @@ -65,7 +63,7 @@ class PartsTableSelector(PartsTablePart, GeneratorBlock, PartsTableBase): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.generator_param(self.filter_parts, self.part) + self.generator_param(self.part) self.generator_param(self.excluded_parts) def _row_filter(self, row: PartsTableRow) -> bool: @@ -73,11 +71,8 @@ def _row_filter(self, row: PartsTableRow) -> bool: Only called within generate(), so has access to GeneratorParam.get(). Subclasses should chain this by and-ing with a super() call.""" part = self.get(self.part) - filter_parts = self.get(self.filter_parts) - if part: - filter_parts.append(part) excluded_parts = self.get(self.excluded_parts) - return ((not filter_parts) or (row[self.PART_NUMBER_COL] in filter_parts)) and ( + return ((not part) or (row[self.PART_NUMBER_COL] == part)) and ( (not excluded_parts) or (row[self.PART_NUMBER_COL] not in excluded_parts) ) @@ -102,9 +97,6 @@ def _row_generate(self, row: PartsTableRow) -> None: def generate(self) -> None: super().generate() - if self.get(self.part): - warnings.warn(f"part replaced with filter_parts taking an array", DeprecationWarning) - matching_table = self._get_table().filter(lambda row: self._row_filter(row)) postprocessed_table = self._table_postprocess(matching_table) postprocessed_table = postprocessed_table.sort_by(self._row_sort_by) @@ -128,7 +120,7 @@ def __init__( @non_library class PartsTableFootprintFilter(PartsTableSelector, SelectorFootprint): - """A combination of PartsTableSelector with SelectorFootprint, with row filtering on footprint_spec. + """A combination of PartsTableSelector with SelectorFootprint, with row filtering on filter_footprints. Does not create the footprint itself, this can be used as a base class where footprint filtering is desired but an internal block is created instead.""" @@ -146,10 +138,9 @@ def generate(self) -> None: @override def _row_filter(self, row: PartsTableRow) -> bool: - footprint_spec = self.get(self.footprint_spec) filter_footprints = self.get(self.filter_footprints) - if footprint_spec: - filter_footprints.append(footprint_spec) + if self.get(self.footprint_spec): + filter_footprints.append(self.get(self.footprint_spec)) return super()._row_filter(row) and ((not filter_footprints or row[self.KICAD_FOOTPRINT] in filter_footprints)) diff --git a/edg/parts/human_interface/SpeakerDriver_Max98357a.py b/edg/parts/human_interface/SpeakerDriver_Max98357a.py index 82cdfb8c2..eb7e8e28a 100644 --- a/edg/parts/human_interface/SpeakerDriver_Max98357a.py +++ b/edg/parts/human_interface/SpeakerDriver_Max98357a.py @@ -6,10 +6,12 @@ from ...vendor_parts.jlc.JlcPart import JlcPart -class Max98357a_Device(InternalSubcircuit, JlcPart, SelectorFootprint, PartsTablePart, GeneratorBlock, FootprintBlock): - def __init__(self) -> None: +class Max98357a_Device(InternalSubcircuit, JlcPart, GeneratorBlock, FootprintBlock): + def __init__(self, *, part: StringLike = "") -> None: super().__init__() + self.part = self.ArgParameter(part) + self.vdd = self.Port( VoltageSink( voltage_limits=(2.5, 5.5) * Volt, @@ -28,15 +30,12 @@ def __init__(self) -> None: self.out = self.Port(SpeakerDriverPort(AnalogSource()), [Output]) - self.generator_param(self.part, self.footprint_spec) + self.generator_param(self.part) @override def generate(self) -> None: super().generate() - if ( - not self.get(self.footprint_spec) - or self.get(self.footprint_spec) == "Package_DFN_QFN:QFN-16-1EP_3x3mm_P0.5mm_EP1.45x1.45mm" - ): + if not self.get(self.part) or self.get(self.part) == "MAX98357AETE+T": footprint = "Package_DFN_QFN:QFN-16-1EP_3x3mm_P0.5mm_EP1.45x1.45mm" pinning: Dict[str, Union[Passive, HasPassivePort]] = { "4": self.vdd, # hard tied to left mode only TODO selectable SD_MODE @@ -56,10 +55,7 @@ def generate(self) -> None: part = "MAX98357AETE+T" jlc_part = "C910544" pnp_rot = -90 - elif ( - self.get(self.footprint_spec) - == "Package_BGA:Maxim_WLP-9_1.595x1.415_Layout3x3_P0.4mm_Ball0.27mm_Pad0.25mm_NSMD" - ): + elif self.get(self.part) == "MAX98357AEWL+T": footprint = "Package_BGA:Maxim_WLP-9_1.595x1.415_Layout3x3_P0.4mm_Ball0.27mm_Pad0.25mm_NSMD" pinning = { "A1": self.vdd, # hard tied to left mode only TODO selectable SD_MODE diff --git a/edg/parts/power/converter/LinearRegulators.py b/edg/parts/power/converter/LinearRegulators.py index fcb77db5f..f948c1bcc 100644 --- a/edg/parts/power/converter/LinearRegulators.py +++ b/edg/parts/power/converter/LinearRegulators.py @@ -587,7 +587,7 @@ def __init__(self, output_voltage: RangeLike): self.assign(self.actual_dropout, (50, 250) * mVolt) self.output_voltage = self.ArgParameter(output_voltage) - self.generator_param(self.output_voltage, self.part, self.footprint_spec) + self.generator_param(self.output_voltage, self.part, self.filter_footprints) self.en = self.Port( DigitalSink( @@ -638,11 +638,11 @@ def generate(self) -> None: ] # TODO should prefer parts by closeness to nominal (center) specified voltage output_voltage_spec = self.get(self.output_voltage) - footprint_spec = self.get(self.footprint_spec) + filter_footprints = self.get(self.filter_footprints) suitable_parts = [ part for part in parts - if part[0] in output_voltage_spec and (not footprint_spec or footprint_spec == part[2]) + if part[0] in output_voltage_spec and (not filter_footprints or part[2] in filter_footprints) ] assert suitable_parts, "no regulator with compatible output" part_output_voltage, part_number, footprint, jlc_number = suitable_parts[0] diff --git a/edg/vendor_parts/generic/GenericCapacitor.py b/edg/vendor_parts/generic/GenericCapacitor.py index f36d0c9a9..08978977c 100644 --- a/edg/vendor_parts/generic/GenericCapacitor.py +++ b/edg/vendor_parts/generic/GenericCapacitor.py @@ -120,7 +120,7 @@ def generate(self) -> None: :param single_nominal_capacitance: used when no single cap with requested capacitance, must generate multiple parallel caps, actually refers to max capacitance for a given part :param filter_footprints: user-specified package footprint - :param derating_coeff: user-specified derating coefficient, if used then footprint_spec must be specified + :param derating_coeff: user-specified derating coefficient """ super().generate() filter_footprints = self.get(self.filter_footprints) diff --git a/edg/vendor_parts/jlc/test_JlcCapacitor.py b/edg/vendor_parts/jlc/test_JlcCapacitor.py index ca711dee2..f7617db55 100644 --- a/edg/vendor_parts/jlc/test_JlcCapacitor.py +++ b/edg/vendor_parts/jlc/test_JlcCapacitor.py @@ -27,7 +27,7 @@ def test_capacitor(self) -> None: def test_capacitor_part(self) -> None: compiled = ScalaCompiler.compile( - JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "filter_parts"], ["CL21B103KBANNNC"])]) + JlcCapacitorTestTop, Refinements(instance_values=[(["dut", "part"], "CL21B103KBANNNC")]) ) self.assertEqual(compiled.get_value(["dut", "fp_footprint"]), "Capacitor_SMD:C_0805_2012Metric") self.assertEqual(compiled.get_value(["dut", "fp_part"]), "CL21B103KBANNNC") diff --git a/examples/test_datalogger.py b/examples/test_datalogger.py index 21e52ed00..a33007d00 100644 --- a/examples/test_datalogger.py +++ b/examples/test_datalogger.py @@ -302,7 +302,7 @@ def refinements(self) -> Refinements: "swd_swo=PIO0_8", ], ), - (["pwr_5v", "power_path", "inductor", "filter_parts"], ["NR5040T220M"]), # peg to prior part selection + (["pwr_5v", "power_path", "inductor", "part"], "NR5040T220M"), # peg to prior part selection ( ["pwr_5v", "power_path", "inductor_current_ripple"], Range(0.01, 0.6), diff --git a/examples/test_esp_programmer.py b/examples/test_esp_programmer.py index f19474c6c..c1c6aff28 100644 --- a/examples/test_esp_programmer.py +++ b/examples/test_esp_programmer.py @@ -86,7 +86,7 @@ def refinements(self) -> Refinements: class_refinements=[], class_values=[ (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 - (TableBjt, ["filter_parts"], ["BC846BW 1B"]), # default option is OOS + (TableBjt, "part", "BC846BW 1B"), # default option is OOS ], ) diff --git a/examples/test_iot_display.py b/examples/test_iot_display.py index 4ee5b4d75..420bfed47 100644 --- a/examples/test_iot_display.py +++ b/examples/test_iot_display.py @@ -196,7 +196,7 @@ def refinements(self) -> Refinements: (["reg_3v3", "power_path", "inductor", "manual_frequency_rating"], Range(0, 10e6)), (["reg_3v3", "fb", "impedance"], Range(20000.0, 100000.0)), (["epd", "boost", "sense", "require_basic_part"], False), # 3R is not a basic part - (["epd", "boost", "inductor", "filter_parts"], ["CBC3225T680KR"]), # automated selection OOS + (["epd", "boost", "inductor", "part"], "CBC3225T680KR"), # automated selection OOS ], class_refinements=[ (EspProgrammingHeader, EspProgrammingTc2030), diff --git a/examples/test_robotcrawler.py b/examples/test_robotcrawler.py index dd03c084e..d68e6c5e8 100644 --- a/examples/test_robotcrawler.py +++ b/examples/test_robotcrawler.py @@ -258,7 +258,7 @@ def refinements(self) -> Refinements: ], ), (["mcu", "programming"], "uart-auto"), - (["reg_14v", "inductor", "filter_parts"], ["CBC3225T220KR"]), + (["reg_14v", "inductor", "part"], "CBC3225T220KR"), (["reg_14v", "inductor", "manual_frequency_rating"], Range(0, 17e6)), # 17MHz self-resonant (["reg_14v", "out_cap", "cap", "voltage_margin"], 1.1), ], diff --git a/examples/test_usb_key.py b/examples/test_usb_key.py index 33cf8c393..1fb66d9f5 100644 --- a/examples/test_usb_key.py +++ b/examples/test_usb_key.py @@ -123,7 +123,7 @@ def refinements(self) -> Refinements: ], class_values=[ (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 - (Lp5907, ["ic", "footprint_spec"], "Package_DFN_QFN:UDFN-4-1EP_1x1mm_P0.65mm_EP0.48x0.48mm"), + (Lp5907, ["ic", "filter_footprints"], ["Package_DFN_QFN:UDFN-4-1EP_1x1mm_P0.65mm_EP0.48x0.48mm"]), ], ) diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index e59d00f0b..b494027d8 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1042,7 +1042,7 @@ def refinements(self) -> Refinements: ["conv", "boost_sw", "low_fet", "filter_footprints"], ["Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic"], ), - (["conv", "boost_sw", "low_fet", "filter_parts"], ["BSC093N04LSG"]), # lower total power + (["conv", "boost_sw", "low_fet", "part"], "BSC093N04LSG"), # lower total power # require all FETs to be the same; note boost must elaborate first (["conv", "buck_sw", "low_fet", "part"], ParamValue(["conv", "boost_sw", "low_fet", "actual_part"])), (["conv", "buck_sw", "high_fet", "part"], ParamValue(["conv", "boost_sw", "low_fet", "actual_part"])), @@ -1105,7 +1105,7 @@ def refinements(self) -> Refinements: ParamValue(["control", "tvs_n", "lcsc_part"]), ), # note, 5v zener diode # out of stock / unassembleable parts - (["conv", "power_path", "out_cap", "cap", "filter_parts"], ["C3216X5R1V226MTJ00E"]), + (["conv", "power_path", "out_cap", "cap", "part"], "C3216X5R1V226MTJ00E"), ], class_values=[ (CompactKeystone5015, ["lcsc_part"], "C5199798"), From b64b8f21d411b95967edcb17bf4003dd99cc47e3 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:21:48 -0700 Subject: [PATCH 06/10] fix --- .../EspProgrammer/EspProgrammer.svgpcb.js | 189 ------------------ examples/test_esp_programmer.py | 2 +- 2 files changed, 1 insertion(+), 190 deletions(-) delete mode 100644 examples/EspProgrammer/EspProgrammer.svgpcb.js diff --git a/examples/EspProgrammer/EspProgrammer.svgpcb.js b/examples/EspProgrammer/EspProgrammer.svgpcb.js deleted file mode 100644 index c7ba0a390..000000000 --- a/examples/EspProgrammer/EspProgrammer.svgpcb.js +++ /dev/null @@ -1,189 +0,0 @@ -const board = new PCB(); - -// jlc_th.th1 -const UH1 = board.add(JlcToolingHole_1_152mm, { - translate: pt(0.670, 1.198), rotate: 0, - id: 'UH1' -}) -// jlc_th.th2 -const UH2 = board.add(JlcToolingHole_1_152mm, { - translate: pt(0.709, 1.198), rotate: 0, - id: 'UH2' -}) -// jlc_th.th3 -const UH3 = board.add(JlcToolingHole_1_152mm, { - translate: pt(0.670, 1.237), rotate: 0, - id: 'UH3' -}) -// usb_uart.conn -const UJ1 = board.add(USB_C_Receptacle_XKB_U262_16XN_4BVC11, { - translate: pt(0.857, 0.165), rotate: 0, - id: 'UJ1' -}) -// usb_uart.cc_pull.cc1 -const UR1 = board.add(R_0402_1005Metric, { - translate: pt(1.142, 0.019), rotate: 0, - id: 'UR1' -}) -// usb_uart.cc_pull.cc2 -const UR2 = board.add(R_0402_1005Metric, { - translate: pt(1.142, 0.095), rotate: 0, - id: 'UR2' -}) -// vusb_protect.diode -const UD1 = board.add(D_SOD_323, { - translate: pt(0.298, 1.235), rotate: 0, - id: 'UD1' -}) -// usbconv.ic -const UU1 = board.add(QFN_28_1EP_5x5mm_P0_5mm_EP3_35x3_35mm, { - translate: pt(0.850, 0.881), rotate: 0, - id: 'UU1' -}) -// usbconv.regin_cap0.cap -const UC1 = board.add(C_0402_1005Metric, { - translate: pt(1.047, 0.778), rotate: 0, - id: 'UC1' -}) -// usbconv.regin_cap1.cap -const UC2 = board.add(C_0402_1005Metric, { - translate: pt(1.047, 0.853), rotate: 0, - id: 'UC2' -}) -// usbconv.vdd_cap.cap -const UC3 = board.add(C_0402_1005Metric, { - translate: pt(1.047, 0.929), rotate: 0, - id: 'UC3' -}) -// usb_esd -const UU2 = board.add(SOT_23, { - translate: pt(0.555, 1.265), rotate: 0, - id: 'UU2' -}) -// reg_3v3.ic -const UU3 = board.add(SOT_23_5, { - translate: pt(0.445, 0.826), rotate: 0, - id: 'UU3' -}) -// reg_3v3.in_cap.cap -const UC4 = board.add(C_0402_1005Metric, { - translate: pt(0.574, 0.951), rotate: 0, - id: 'UC4' -}) -// reg_3v3.out_cap.cap -const UC5 = board.add(C_0805_2012Metric, { - translate: pt(0.431, 0.971), rotate: 0, - id: 'UC5' -}) -// out.conn -const UJ2 = board.add(PinHeader_2x03_P2_54mm_EdgeInline, { - translate: pt(0.159, 0.321), rotate: 0, - id: 'UJ2' -}) -// auto.q_en -const UQ1 = board.add(SOT_323_SC_70, { - translate: pt(0.067, 0.811), rotate: 0, - id: 'UQ1' -}) -// auto.q_boot -const UQ2 = board.add(SOT_323_SC_70, { - translate: pt(0.067, 0.952), rotate: 0, - id: 'UQ2' -}) -// auto.dtr_res -const UR3 = board.add(R_0402_1005Metric, { - translate: pt(0.210, 0.920), rotate: 0, - id: 'UR3' -}) -// auto.rts_res -const UR4 = board.add(R_0402_1005Metric, { - translate: pt(0.037, 1.061), rotate: 0, - id: 'UR4' -}) -// led.package -const UD2 = board.add(LED_0603_1608Metric, { - translate: pt(1.259, 0.788), rotate: 0, - id: 'UD2' -}) -// led.res -const UR5 = board.add(R_0402_1005Metric, { - translate: pt(1.237, 0.875), rotate: 0, - id: 'UR5' -}) -// led_en.package -const UD3 = board.add(LED_0603_1608Metric, { - translate: pt(0.058, 1.227), rotate: 0, - id: 'UD3' -}) -// led_en.res -const UR6 = board.add(R_0402_1005Metric, { - translate: pt(0.037, 1.314), rotate: 0, - id: 'UR6' -}) - -board.setNetlist([ - {name: "vusb", pads: [["UJ1", "A4"], ["UJ1", "A9"], ["UJ1", "B4"], ["UJ1", "B9"], ["UD1", "1"], ["UU1", "7"], ["UU1", "8"], ["UC1", "1"], ["UC2", "1"], ["UU3", "1"], ["UU3", "3"], ["UC4", "1"]]}, - {name: "gnd", pads: [["UJ1", "A1"], ["UJ1", "A12"], ["UJ1", "B1"], ["UJ1", "B12"], ["UJ1", "S1"], ["UR1", "1"], ["UR2", "1"], ["UD1", "2"], ["UU1", "29"], ["UU1", "3"], ["UC1", "2"], ["UC2", "2"], ["UC3", "2"], ["UU2", "3"], ["UU3", "2"], ["UC4", "2"], ["UC5", "2"], ["UJ2", "5"]]}, - {name: "v3v3", pads: [["UU3", "5"], ["UC5", "1"], ["UJ2", "1"], ["UD2", "2"], ["UD3", "2"]]}, - {name: "usb_chain_0.d_P", pads: [["UJ1", "A6"], ["UJ1", "B6"], ["UU1", "4"], ["UU2", "2"]]}, - {name: "usb_chain_0.d_N", pads: [["UJ1", "A7"], ["UJ1", "B7"], ["UU1", "5"], ["UU2", "1"]]}, - {name: "usb_uart.conn.cc.cc1", pads: [["UJ1", "A5"], ["UR1", "2"]]}, - {name: "usb_uart.conn.cc.cc2", pads: [["UJ1", "B5"], ["UR2", "2"]]}, - {name: "usbconv.suspend", pads: [["UU1", "12"], ["UR5", "2"]]}, - {name: "usbconv.nsuspend", pads: [["UU1", "11"]]}, - {name: "usbconv.uart.tx", pads: [["UU1", "26"], ["UJ2", "4"]]}, - {name: "usbconv.uart.rx", pads: [["UU1", "25"], ["UJ2", "3"]]}, - {name: "usbconv.ri", pads: [["UU1", "2"]]}, - {name: "usbconv.dcd", pads: [["UU1", "1"]]}, - {name: "usbconv.dtr", pads: [["UU1", "28"], ["UQ2", "2"], ["UR3", "1"]]}, - {name: "usbconv.dsr", pads: [["UU1", "27"]]}, - {name: "usbconv.rts", pads: [["UU1", "24"], ["UQ1", "2"], ["UR4", "1"], ["UR6", "2"]]}, - {name: "usbconv.cts", pads: [["UU1", "23"]]}, - {name: "usbconv.ic.vdd", pads: [["UU1", "6"], ["UU1", "9"], ["UC3", "1"]]}, - {name: "out.en", pads: [["UJ2", "6"], ["UQ1", "3"]]}, - {name: "out.boot", pads: [["UJ2", "2"], ["UQ2", "3"]]}, - {name: "auto.q_en.base", pads: [["UQ1", "1"], ["UR3", "2"]]}, - {name: "auto.q_boot.base", pads: [["UQ2", "1"], ["UR4", "2"]]}, - {name: "led.package.k", pads: [["UD2", "1"], ["UR5", "1"]]}, - {name: "led_en.package.k", pads: [["UD3", "1"], ["UR6", "1"]]} -]) - -const limit0 = pt(-0.07874015748031496, -0.07874015748031496); -const limit1 = pt(1.4356299212598427, 1.4503937007874017); -const xMin = Math.min(limit0[0], limit1[0]); -const xMax = Math.max(limit0[0], limit1[0]); -const yMin = Math.min(limit0[1], limit1[1]); -const yMax = Math.max(limit0[1], limit1[1]); - -const filletRadius = 0.1; -const outline = path( - [(xMin+xMax/2), yMax], - ["fillet", filletRadius, [xMax, yMax]], - ["fillet", filletRadius, [xMax, yMin]], - ["fillet", filletRadius, [xMin, yMin]], - ["fillet", filletRadius, [xMin, yMax]], - [(xMin+xMax/2), yMax], -); -board.addShape("outline", outline); - -renderPCB({ - pcb: board, - layerColors: { - "F.Paste": "#000000ff", - "F.Mask": "#000000ff", - "B.Mask": "#000000ff", - "componentLabels": "#00e5e5e5", - "outline": "#002d00ff", - "padLabels": "#ffff99e5", - "B.Cu": "#ef4e4eff", - "F.Cu": "#ff8c00cc", - }, - limits: { - x: [xMin, xMax], - y: [yMin, yMax] - }, - background: "#00000000", - mmPerUnit: 25.4 -}) - - diff --git a/examples/test_esp_programmer.py b/examples/test_esp_programmer.py index c1c6aff28..e34eeda73 100644 --- a/examples/test_esp_programmer.py +++ b/examples/test_esp_programmer.py @@ -86,7 +86,7 @@ def refinements(self) -> Refinements: class_refinements=[], class_values=[ (SelectorArea, ["filter_area"], Range.from_lower(1.5)), # at least 0402 - (TableBjt, "part", "BC846BW 1B"), # default option is OOS + (TableBjt, ["part"], "BC846BW 1B"), # default option is OOS ], ) From 249f8eba5ccff590fbc22f3031d5e4c34c727457 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:24:38 -0700 Subject: [PATCH 07/10] cleaning --- edg/vendor_parts/generic/CustomDiode.py | 15 +- edg/vendor_parts/generic/CustomFet.py | 14 +- .../EspProgrammer/EspProgrammer.svgpcb.js | 189 ++++++++++++++++++ examples/test_multimeter.py | 4 +- examples/test_usb_source_measure.py | 4 +- 5 files changed, 204 insertions(+), 22 deletions(-) create mode 100644 examples/EspProgrammer/EspProgrammer.svgpcb.js diff --git a/edg/vendor_parts/generic/CustomDiode.py b/edg/vendor_parts/generic/CustomDiode.py index 69ce04941..bc7a8982c 100644 --- a/edg/vendor_parts/generic/CustomDiode.py +++ b/edg/vendor_parts/generic/CustomDiode.py @@ -6,19 +6,19 @@ class CustomDiode(Diode, FootprintBlock, GeneratorBlock): + """Generic diode that automatically assigns footprint pinning.""" + def __init__( self, *args: Any, + part: StringLike = "", footprint_spec: StringLike = "", - manufacturer_spec: StringLike = "", - part_spec: StringLike = "", **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) - self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint - self.manufacturer_spec = self.ArgParameter(manufacturer_spec) - self.part_spec = self.ArgParameter(part_spec) + self.part = self.ArgParameter(part) + self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint self.generator_param(self.footprint_spec) # use ideal specs, which can be overridden with refinements @@ -33,8 +33,5 @@ def generate(self) -> None: self._standard_footprint().REFDES_PREFIX, self.footprint_spec, self._standard_footprint()._make_pinning(self, self.get(self.footprint_spec)), - mfr=self.manufacturer_spec, - part=self.part_spec, - value=self.part_spec, - datasheet="", + part=self.part, ) diff --git a/edg/vendor_parts/generic/CustomFet.py b/edg/vendor_parts/generic/CustomFet.py index fc5fc60cd..a4aaf2a00 100644 --- a/edg/vendor_parts/generic/CustomFet.py +++ b/edg/vendor_parts/generic/CustomFet.py @@ -6,19 +6,18 @@ class CustomFet(SwitchFet, FootprintBlock, GeneratorBlock): + def __init__( self, *args: Any, + part: StringLike = "", footprint_spec: StringLike = "", - manufacturer_spec: StringLike = "", - part_spec: StringLike = "", **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) - self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint - self.manufacturer_spec = self.ArgParameter(manufacturer_spec) - self.part_spec = self.ArgParameter(part_spec) + self.part = self.ArgParameter(part) + self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint self.generator_param(self.footprint_spec) # use ideal specs, which can be overridden with refinements @@ -36,8 +35,5 @@ def generate(self) -> None: self._standard_footprint().REFDES_PREFIX, self.footprint_spec, self._standard_footprint()._make_pinning(self, self.get(self.footprint_spec)), - mfr=self.manufacturer_spec, - part=self.part_spec, - value=self.part_spec, - datasheet="", + part=self.part, ) diff --git a/examples/EspProgrammer/EspProgrammer.svgpcb.js b/examples/EspProgrammer/EspProgrammer.svgpcb.js new file mode 100644 index 000000000..c7ba0a390 --- /dev/null +++ b/examples/EspProgrammer/EspProgrammer.svgpcb.js @@ -0,0 +1,189 @@ +const board = new PCB(); + +// jlc_th.th1 +const UH1 = board.add(JlcToolingHole_1_152mm, { + translate: pt(0.670, 1.198), rotate: 0, + id: 'UH1' +}) +// jlc_th.th2 +const UH2 = board.add(JlcToolingHole_1_152mm, { + translate: pt(0.709, 1.198), rotate: 0, + id: 'UH2' +}) +// jlc_th.th3 +const UH3 = board.add(JlcToolingHole_1_152mm, { + translate: pt(0.670, 1.237), rotate: 0, + id: 'UH3' +}) +// usb_uart.conn +const UJ1 = board.add(USB_C_Receptacle_XKB_U262_16XN_4BVC11, { + translate: pt(0.857, 0.165), rotate: 0, + id: 'UJ1' +}) +// usb_uart.cc_pull.cc1 +const UR1 = board.add(R_0402_1005Metric, { + translate: pt(1.142, 0.019), rotate: 0, + id: 'UR1' +}) +// usb_uart.cc_pull.cc2 +const UR2 = board.add(R_0402_1005Metric, { + translate: pt(1.142, 0.095), rotate: 0, + id: 'UR2' +}) +// vusb_protect.diode +const UD1 = board.add(D_SOD_323, { + translate: pt(0.298, 1.235), rotate: 0, + id: 'UD1' +}) +// usbconv.ic +const UU1 = board.add(QFN_28_1EP_5x5mm_P0_5mm_EP3_35x3_35mm, { + translate: pt(0.850, 0.881), rotate: 0, + id: 'UU1' +}) +// usbconv.regin_cap0.cap +const UC1 = board.add(C_0402_1005Metric, { + translate: pt(1.047, 0.778), rotate: 0, + id: 'UC1' +}) +// usbconv.regin_cap1.cap +const UC2 = board.add(C_0402_1005Metric, { + translate: pt(1.047, 0.853), rotate: 0, + id: 'UC2' +}) +// usbconv.vdd_cap.cap +const UC3 = board.add(C_0402_1005Metric, { + translate: pt(1.047, 0.929), rotate: 0, + id: 'UC3' +}) +// usb_esd +const UU2 = board.add(SOT_23, { + translate: pt(0.555, 1.265), rotate: 0, + id: 'UU2' +}) +// reg_3v3.ic +const UU3 = board.add(SOT_23_5, { + translate: pt(0.445, 0.826), rotate: 0, + id: 'UU3' +}) +// reg_3v3.in_cap.cap +const UC4 = board.add(C_0402_1005Metric, { + translate: pt(0.574, 0.951), rotate: 0, + id: 'UC4' +}) +// reg_3v3.out_cap.cap +const UC5 = board.add(C_0805_2012Metric, { + translate: pt(0.431, 0.971), rotate: 0, + id: 'UC5' +}) +// out.conn +const UJ2 = board.add(PinHeader_2x03_P2_54mm_EdgeInline, { + translate: pt(0.159, 0.321), rotate: 0, + id: 'UJ2' +}) +// auto.q_en +const UQ1 = board.add(SOT_323_SC_70, { + translate: pt(0.067, 0.811), rotate: 0, + id: 'UQ1' +}) +// auto.q_boot +const UQ2 = board.add(SOT_323_SC_70, { + translate: pt(0.067, 0.952), rotate: 0, + id: 'UQ2' +}) +// auto.dtr_res +const UR3 = board.add(R_0402_1005Metric, { + translate: pt(0.210, 0.920), rotate: 0, + id: 'UR3' +}) +// auto.rts_res +const UR4 = board.add(R_0402_1005Metric, { + translate: pt(0.037, 1.061), rotate: 0, + id: 'UR4' +}) +// led.package +const UD2 = board.add(LED_0603_1608Metric, { + translate: pt(1.259, 0.788), rotate: 0, + id: 'UD2' +}) +// led.res +const UR5 = board.add(R_0402_1005Metric, { + translate: pt(1.237, 0.875), rotate: 0, + id: 'UR5' +}) +// led_en.package +const UD3 = board.add(LED_0603_1608Metric, { + translate: pt(0.058, 1.227), rotate: 0, + id: 'UD3' +}) +// led_en.res +const UR6 = board.add(R_0402_1005Metric, { + translate: pt(0.037, 1.314), rotate: 0, + id: 'UR6' +}) + +board.setNetlist([ + {name: "vusb", pads: [["UJ1", "A4"], ["UJ1", "A9"], ["UJ1", "B4"], ["UJ1", "B9"], ["UD1", "1"], ["UU1", "7"], ["UU1", "8"], ["UC1", "1"], ["UC2", "1"], ["UU3", "1"], ["UU3", "3"], ["UC4", "1"]]}, + {name: "gnd", pads: [["UJ1", "A1"], ["UJ1", "A12"], ["UJ1", "B1"], ["UJ1", "B12"], ["UJ1", "S1"], ["UR1", "1"], ["UR2", "1"], ["UD1", "2"], ["UU1", "29"], ["UU1", "3"], ["UC1", "2"], ["UC2", "2"], ["UC3", "2"], ["UU2", "3"], ["UU3", "2"], ["UC4", "2"], ["UC5", "2"], ["UJ2", "5"]]}, + {name: "v3v3", pads: [["UU3", "5"], ["UC5", "1"], ["UJ2", "1"], ["UD2", "2"], ["UD3", "2"]]}, + {name: "usb_chain_0.d_P", pads: [["UJ1", "A6"], ["UJ1", "B6"], ["UU1", "4"], ["UU2", "2"]]}, + {name: "usb_chain_0.d_N", pads: [["UJ1", "A7"], ["UJ1", "B7"], ["UU1", "5"], ["UU2", "1"]]}, + {name: "usb_uart.conn.cc.cc1", pads: [["UJ1", "A5"], ["UR1", "2"]]}, + {name: "usb_uart.conn.cc.cc2", pads: [["UJ1", "B5"], ["UR2", "2"]]}, + {name: "usbconv.suspend", pads: [["UU1", "12"], ["UR5", "2"]]}, + {name: "usbconv.nsuspend", pads: [["UU1", "11"]]}, + {name: "usbconv.uart.tx", pads: [["UU1", "26"], ["UJ2", "4"]]}, + {name: "usbconv.uart.rx", pads: [["UU1", "25"], ["UJ2", "3"]]}, + {name: "usbconv.ri", pads: [["UU1", "2"]]}, + {name: "usbconv.dcd", pads: [["UU1", "1"]]}, + {name: "usbconv.dtr", pads: [["UU1", "28"], ["UQ2", "2"], ["UR3", "1"]]}, + {name: "usbconv.dsr", pads: [["UU1", "27"]]}, + {name: "usbconv.rts", pads: [["UU1", "24"], ["UQ1", "2"], ["UR4", "1"], ["UR6", "2"]]}, + {name: "usbconv.cts", pads: [["UU1", "23"]]}, + {name: "usbconv.ic.vdd", pads: [["UU1", "6"], ["UU1", "9"], ["UC3", "1"]]}, + {name: "out.en", pads: [["UJ2", "6"], ["UQ1", "3"]]}, + {name: "out.boot", pads: [["UJ2", "2"], ["UQ2", "3"]]}, + {name: "auto.q_en.base", pads: [["UQ1", "1"], ["UR3", "2"]]}, + {name: "auto.q_boot.base", pads: [["UQ2", "1"], ["UR4", "2"]]}, + {name: "led.package.k", pads: [["UD2", "1"], ["UR5", "1"]]}, + {name: "led_en.package.k", pads: [["UD3", "1"], ["UR6", "1"]]} +]) + +const limit0 = pt(-0.07874015748031496, -0.07874015748031496); +const limit1 = pt(1.4356299212598427, 1.4503937007874017); +const xMin = Math.min(limit0[0], limit1[0]); +const xMax = Math.max(limit0[0], limit1[0]); +const yMin = Math.min(limit0[1], limit1[1]); +const yMax = Math.max(limit0[1], limit1[1]); + +const filletRadius = 0.1; +const outline = path( + [(xMin+xMax/2), yMax], + ["fillet", filletRadius, [xMax, yMax]], + ["fillet", filletRadius, [xMax, yMin]], + ["fillet", filletRadius, [xMin, yMin]], + ["fillet", filletRadius, [xMin, yMax]], + [(xMin+xMax/2), yMax], +); +board.addShape("outline", outline); + +renderPCB({ + pcb: board, + layerColors: { + "F.Paste": "#000000ff", + "F.Mask": "#000000ff", + "B.Mask": "#000000ff", + "componentLabels": "#00e5e5e5", + "outline": "#002d00ff", + "padLabels": "#ffff99e5", + "B.Cu": "#ef4e4eff", + "F.Cu": "#ff8c00cc", + }, + limits: { + x: [xMin, xMax], + y: [yMin, yMax] + }, + background: "#00000000", + mmPerUnit: 25.4 +}) + + diff --git a/examples/test_multimeter.py b/examples/test_multimeter.py index c066995a8..85a4e0715 100644 --- a/examples/test_multimeter.py +++ b/examples/test_multimeter.py @@ -405,10 +405,10 @@ def refinements(self) -> Refinements: # pin footprints to re-select parts with newer parts tables (["driver", "fet", "footprint_spec"], "Package_TO_SOT_SMD:SOT-23"), # Q3 (["driver", "fet", "manufacturer_spec"], "Infineon Technologies"), - (["driver", "fet", "part_spec"], "BSR92PH6327XTSA1"), + (["driver", "fet", "part"], "BSR92PH6327XTSA1"), (["driver", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), (["driver", "diode", "manufacturer_spec"], "Micro Commercial Co"), - (["driver", "diode", "part_spec"], "GS1G-LTP"), + (["driver", "diode", "part"], "GS1G-LTP"), # (['reg_5v', 'power_path', 'inductor', 'footprint_spec'], 'Inductor_SMD:L_0805_2012Metric'), # L1 # JLC does not have frequency specs, must be checked TODO (["reg_5v", "power_path", "inductor", "manual_frequency_rating"], Range.all()), diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index b494027d8..07b5ce1ba 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1055,9 +1055,9 @@ def refinements(self) -> Refinements: (["control", "isense", "ranges[2]", "isense", "res", "res", "require_basic_part"], False), (["control", "driver", "res", "count"], 10), (["control", "driver", "high_fet", "footprint_spec"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), - (["control", "driver", "high_fet", "part_spec"], "IRF540N"), + (["control", "driver", "high_fet", "part"], "IRF540N"), (["control", "driver", "low_fet", "footprint_spec"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), - (["control", "driver", "low_fet", "part_spec"], "IRF9540"), # has a 30V/4A SOA + (["control", "driver", "low_fet", "part"], "IRF9540"), # has a 30V/4A SOA (["prot_vusb", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), (["prot_conv", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), (["prot_3v3", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), From 03a1419f23763426fe087a69c4a2682683387971 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:30:54 -0700 Subject: [PATCH 08/10] wip --- edg/circuits/test_diodemerge.py | 2 +- edg/circuits/test_power_circuits.py | 4 ++-- edg/vendor_parts/generic/CustomDiode.py | 10 +++++----- edg/vendor_parts/generic/CustomFet.py | 10 +++++----- examples/test_multimeter.py | 7 ++----- examples/test_usb_source_measure.py | 4 ++-- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/edg/circuits/test_diodemerge.py b/edg/circuits/test_diodemerge.py index 214762d40..a173f41f7 100644 --- a/edg/circuits/test_diodemerge.py +++ b/edg/circuits/test_diodemerge.py @@ -21,7 +21,7 @@ def refinements(self) -> Refinements: (Diode, CustomDiode), ], class_values=[ - (CustomDiode, ["footprint_spec"], "Diode_SMD:D_SOD-123"), + (CustomDiode, ["part_footprint"], "Diode_SMD:D_SOD-123"), ], ) diff --git a/edg/circuits/test_power_circuits.py b/edg/circuits/test_power_circuits.py index 8d6dd5f4e..858140eca 100644 --- a/edg/circuits/test_power_circuits.py +++ b/edg/circuits/test_power_circuits.py @@ -27,8 +27,8 @@ def refinements(self) -> Refinements: (SwitchFet, CustomFet), ], instance_values=[ - (["dut", "drv", "footprint_spec"], "Package_TO_SOT_SMD:SOT-23"), - (["dut", "ctl_fet", "footprint_spec"], "Package_TO_SOT_SMD:SOT-23"), + (["dut", "drv", "part_footprint"], "Package_TO_SOT_SMD:SOT-23"), + (["dut", "ctl_fet", "part_footprint"], "Package_TO_SOT_SMD:SOT-23"), (["dut", "drv", "actual_gate_drive"], Range(1.0, 12)), ], ) diff --git a/edg/vendor_parts/generic/CustomDiode.py b/edg/vendor_parts/generic/CustomDiode.py index bc7a8982c..2709753f4 100644 --- a/edg/vendor_parts/generic/CustomDiode.py +++ b/edg/vendor_parts/generic/CustomDiode.py @@ -12,14 +12,14 @@ def __init__( self, *args: Any, part: StringLike = "", - footprint_spec: StringLike = "", + part_footprint: StringLike = "", **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) self.part = self.ArgParameter(part) - self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint - self.generator_param(self.footprint_spec) + self.part_footprint = self.ArgParameter(part_footprint) # actual_footprint left to the actual footprint + self.generator_param(self.part_footprint) # use ideal specs, which can be overridden with refinements self.assign(self.actual_voltage_rating, Range.all()) @@ -31,7 +31,7 @@ def __init__( def generate(self) -> None: self.footprint( self._standard_footprint().REFDES_PREFIX, - self.footprint_spec, - self._standard_footprint()._make_pinning(self, self.get(self.footprint_spec)), + self.part_footprint, + self._standard_footprint()._make_pinning(self, self.get(self.part_footprint)), part=self.part, ) diff --git a/edg/vendor_parts/generic/CustomFet.py b/edg/vendor_parts/generic/CustomFet.py index a4aaf2a00..96fd35af3 100644 --- a/edg/vendor_parts/generic/CustomFet.py +++ b/edg/vendor_parts/generic/CustomFet.py @@ -11,14 +11,14 @@ def __init__( self, *args: Any, part: StringLike = "", - footprint_spec: StringLike = "", + part_footprint: StringLike = "", **kwargs: Any, ) -> None: super().__init__(*args, **kwargs) self.part = self.ArgParameter(part) - self.footprint_spec = self.ArgParameter(footprint_spec) # actual_footprint left to the actual footprint - self.generator_param(self.footprint_spec) + self.part_footprint = self.ArgParameter(part_footprint) # actual_footprint left to the actual footprint + self.generator_param(self.part_footprint) # use ideal specs, which can be overridden with refinements self.assign(self.actual_drain_voltage_rating, Range.all()) @@ -33,7 +33,7 @@ def __init__( def generate(self) -> None: self.footprint( self._standard_footprint().REFDES_PREFIX, - self.footprint_spec, - self._standard_footprint()._make_pinning(self, self.get(self.footprint_spec)), + self.part_footprint, + self._standard_footprint()._make_pinning(self, self.get(self.part_footprint)), part=self.part, ) diff --git a/examples/test_multimeter.py b/examples/test_multimeter.py index 85a4e0715..19389c9b4 100644 --- a/examples/test_multimeter.py +++ b/examples/test_multimeter.py @@ -403,13 +403,10 @@ def refinements(self) -> Refinements: (["measure", "res", "fp_part"], "CHV2512-F*-1004***"), # IMPORTANT! Most 2512 resistors are rated to ~200V working voltage, this one is up to 3kV. # pin footprints to re-select parts with newer parts tables - (["driver", "fet", "footprint_spec"], "Package_TO_SOT_SMD:SOT-23"), # Q3 - (["driver", "fet", "manufacturer_spec"], "Infineon Technologies"), + (["driver", "fet", "part_footprint"], "Package_TO_SOT_SMD:SOT-23"), # Q3 (["driver", "fet", "part"], "BSR92PH6327XTSA1"), - (["driver", "diode", "footprint_spec"], "Diode_SMD:D_SMA"), - (["driver", "diode", "manufacturer_spec"], "Micro Commercial Co"), + (["driver", "diode", "part_footprint"], "Diode_SMD:D_SMA"), (["driver", "diode", "part"], "GS1G-LTP"), - # (['reg_5v', 'power_path', 'inductor', 'footprint_spec'], 'Inductor_SMD:L_0805_2012Metric'), # L1 # JLC does not have frequency specs, must be checked TODO (["reg_5v", "power_path", "inductor", "manual_frequency_rating"], Range.all()), ], diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index 07b5ce1ba..bba60278d 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1054,9 +1054,9 @@ def refinements(self) -> Refinements: (["control", "isense", "ranges[1]", "isense", "res", "res", "require_basic_part"], False), (["control", "isense", "ranges[2]", "isense", "res", "res", "require_basic_part"], False), (["control", "driver", "res", "count"], 10), - (["control", "driver", "high_fet", "footprint_spec"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), + (["control", "driver", "high_fet", "part_footprint"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), (["control", "driver", "high_fet", "part"], "IRF540N"), - (["control", "driver", "low_fet", "footprint_spec"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), + (["control", "driver", "low_fet", "part_footprint"], "Package_TO_SOT_THT:TO-220-3_Horizontal_TabUp"), (["control", "driver", "low_fet", "part"], "IRF9540"), # has a 30V/4A SOA (["prot_vusb", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), (["prot_conv", "diode", "filter_footprints"], ["Diode_SMD:D_SMA"]), From 44b58f598fd5ea8e11d3122ce1ae140abe3c59e2 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:38:20 -0700 Subject: [PATCH 09/10] update --- examples/Multimeter/Multimeter.net.ref | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Multimeter/Multimeter.net.ref b/examples/Multimeter/Multimeter.net.ref index 3b983edc7..860a12070 100644 --- a/examples/Multimeter/Multimeter.net.ref +++ b/examples/Multimeter/Multimeter.net.ref @@ -1076,7 +1076,7 @@ (property (name "edg_path") (value "driver.fet")) (property (name "edg_short_path") (value "driver.fet")) (property (name "edg_refdes") (value "Q3")) - (property (name "edg_part") (value "BSR92PH6327XTSA1 (Infineon Technologies)")) + (property (name "edg_part") (value "BSR92PH6327XTSA1")) (property (name "edg_value") (value "BSR92PH6327XTSA1")) (sheetpath (names "/driver/") (tstamps "/08da028d/")) (tstamps "02730140")) @@ -1256,7 +1256,7 @@ (property (name "edg_path") (value "driver.diode")) (property (name "edg_short_path") (value "driver.diode")) (property (name "edg_refdes") (value "D7")) - (property (name "edg_part") (value "GS1G-LTP (Micro Commercial Co)")) + (property (name "edg_part") (value "GS1G-LTP")) (property (name "edg_value") (value "GS1G-LTP")) (sheetpath (names "/driver/") (tstamps "/08da028d/")) (tstamps "06170206")) From fc5591de8437c19d0197047b589117a4d956f964 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Sat, 4 Jul 2026 17:59:39 -0700 Subject: [PATCH 10/10] Update PartsTablePart.py --- edg/abstract_parts/PartsTablePart.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/edg/abstract_parts/PartsTablePart.py b/edg/abstract_parts/PartsTablePart.py index 2b66bd422..558d4a46e 100644 --- a/edg/abstract_parts/PartsTablePart.py +++ b/edg/abstract_parts/PartsTablePart.py @@ -42,13 +42,7 @@ class PartsTablePart(Block): """An interface mixin for a part that is selected from a table, defining parameters to allow manual part selection as well as matching parts.""" - def __init__( - self, - *args: Any, - part: StringLike = "", - excluded_parts: ArrayStringLike = [], - **kwargs: Any, - ) -> None: + def __init__(self, *args: Any, part: StringLike = "", excluded_parts: ArrayStringLike = [], **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.part = self.ArgParameter(part) self.excluded_parts = self.ArgParameter(excluded_parts) @@ -63,8 +57,7 @@ class PartsTableSelector(PartsTablePart, GeneratorBlock, PartsTableBase): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.generator_param(self.part) - self.generator_param(self.excluded_parts) + self.generator_param(self.part, self.excluded_parts) def _row_filter(self, row: PartsTableRow) -> bool: """Returns whether the candidate row satisfies the requirements (should be kept). @@ -72,7 +65,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: Subclasses should chain this by and-ing with a super() call.""" part = self.get(self.part) excluded_parts = self.get(self.excluded_parts) - return ((not part) or (row[self.PART_NUMBER_COL] == part)) and ( + return ((not part) or (part == row[self.PART_NUMBER_COL])) and ( (not excluded_parts) or (row[self.PART_NUMBER_COL] not in excluded_parts) )