diff --git a/blinky_skeleton.py b/blinky_skeleton.py index 3f93c1ba9..a5a463d2a 100644 --- a/blinky_skeleton.py +++ b/blinky_skeleton.py @@ -1,7 +1,10 @@ +from typing_extensions import override + from edg import * class BlinkyExample(SimpleBoardTop): + @override def contents(self) -> None: super().contents() # your implementation here diff --git a/edg/BoardTop.py b/edg/BoardTop.py index f42ed7d41..65e374b72 100644 --- a/edg/BoardTop.py +++ b/edg/BoardTop.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from .parts import * @@ -8,6 +10,7 @@ def __init__(self) -> None: self.refdes_prefix = self.Parameter(StringExpr()) self.assign(self.refdes_prefix, "") # override with refinements + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ @@ -52,6 +55,7 @@ class BoardTop(BaseBoardTop): class JlcToolingHole(InternalSubcircuit, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -62,6 +66,7 @@ def contents(self) -> None: class JlcToolingHoles(InternalSubcircuit, Block): + @override def contents(self) -> None: super().contents() self.th1 = self.Block(JlcToolingHole()) @@ -71,6 +76,7 @@ def contents(self) -> None: class JlcTopRefinements(BaseBoardTop): """Design top with refinements to use parts from JLC's assembly service""" + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ @@ -111,6 +117,7 @@ def refinements(self) -> Refinements: class JlcBoardTop(JlcTopRefinements): """Design top with refinements to use parts from JLC's assembly service and including the tooling holes""" + @override def contents(self) -> None: super().contents() self.jlc_th = self.Block(JlcToolingHoles()) @@ -118,6 +125,7 @@ def contents(self) -> None: class SimpleBoardTop(JlcTopRefinements): """A BoardTop with refinements that make getting started easier but may not be desirable everywhere.""" + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ diff --git a/edg/abstract_parts/AbstractAnalogSwitch.py b/edg/abstract_parts/AbstractAnalogSwitch.py index aba05c034..e5156d560 100644 --- a/edg/abstract_parts/AbstractAnalogSwitch.py +++ b/edg/abstract_parts/AbstractAnalogSwitch.py @@ -1,5 +1,7 @@ from typing import List, cast, Optional, Dict +from typing_extensions import override + from ..electronics_model import * from .Categories import Interface @@ -7,6 +9,7 @@ @abstract_block class AnalogSwitch(Interface, KiCadImportableBlock, Block): """Base class for a n-ported analog switch with passive-typed ports.""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name.startswith('edg_importable:Mux') # can be any Mux count = int(symbol_name.removeprefix('edg_importable:Mux')) @@ -43,6 +46,7 @@ def __init__(self, switch_size: IntLike = 0): self.switch_size = self.ArgParameter(switch_size) self.generator_param(self.switch_size, self.inputs.requested(), self.control_gnd.is_connected()) + @override def generate(self) -> None: import math super().generate() @@ -104,6 +108,7 @@ def generate(self) -> None: class AnalogMuxer(Interface, KiCadImportableBlock, GeneratorBlock): """Wrapper around AnalogSwitch that provides muxing functionality - multiple sink ports, one source port. """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name.startswith('edg_importable:Mux') # can be any Mux count = int(symbol_name.removeprefix('edg_importable:Mux')) @@ -132,6 +137,7 @@ def __init__(self) -> None: self.generator_param(self.inputs.requested(), self.control_gnd.is_connected()) + @override def generate(self) -> None: super().generate() self.inputs.defined() @@ -175,6 +181,7 @@ def __init__(self) -> None: self.generator_param(self.outputs.requested()) + @override def generate(self) -> None: super().generate() self.outputs.defined() diff --git a/edg/abstract_parts/AbstractAntenna.py b/edg/abstract_parts/AbstractAntenna.py index 752a9087f..60501f180 100644 --- a/edg/abstract_parts/AbstractAntenna.py +++ b/edg/abstract_parts/AbstractAntenna.py @@ -36,12 +36,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.frequency, self.power, self.impedance) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ self.get(self.frequency).fuzzy_in(row[self.FREQUENCY_RATING]) and \ row[self.IMPEDANCE].fuzzy_in(self.get(self.impedance)) and\ self.get(self.power).fuzzy_in(row[self.POWER_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_frequency_rating, row[self.FREQUENCY_RATING]) diff --git a/edg/abstract_parts/AbstractBjt.py b/edg/abstract_parts/AbstractBjt.py index 060db1a12..4e5db0df5 100644 --- a/edg/abstract_parts/AbstractBjt.py +++ b/edg/abstract_parts/AbstractBjt.py @@ -13,6 +13,7 @@ class Bjt(KiCadImportableBlock, DiscreteSemiconductor, HasStandardFootprint): """ _STANDARD_FOOTPRINT = lambda: BjtStandardFootprint + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: # TODO actually check that the device channel corresponds with the schematic? assert symbol_name.startswith('Device:Q_NPN_') or symbol_name.startswith('Device:Q_PNP_') @@ -48,6 +49,7 @@ def __init__(self, collector_voltage: RangeLike, collector_current: RangeLike, * self.actual_power_rating = self.Parameter(RangeExpr()) self.actual_gain = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -94,6 +96,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.collector_voltage, self.collector_current, self.gain, self.power, self.channel) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.CHANNEL] == self.get(self.channel) and \ @@ -102,6 +105,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: row[self.GAIN].fuzzy_in(self.get(self.gain)) and \ self.get(self.power).fuzzy_in(row[self.POWER_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_collector_voltage_rating, row[self.VCE_RATING]) diff --git a/edg/abstract_parts/AbstractCapacitor.py b/edg/abstract_parts/AbstractCapacitor.py index d44c40a99..16dee5d8e 100644 --- a/edg/abstract_parts/AbstractCapacitor.py +++ b/edg/abstract_parts/AbstractCapacitor.py @@ -3,6 +3,8 @@ from typing import Optional, cast, Dict, Any, Tuple, Mapping import math +from typing_extensions import override + from ..electronics_model import * from .ESeriesUtil import ESeriesUtil from .PartsTable import PartsTableColumn, PartsTableRow, PartsTable @@ -35,6 +37,7 @@ def __init__(self, capacitance: RangeLike, voltage: RangeLike, *, self.actual_capacitance = self.Parameter(RangeExpr()) self.actual_voltage_rating = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -55,6 +58,7 @@ class Capacitor(UnpolarizedCapacitor, KiCadInstantiableBlock, HasStandardFootpri "\s*" + f"([\d.{PartParserUtil.SI_PREFIXES}]+\s*V)" + "$") CAPACITOR_DEFAULT_TOL = 0.20 # TODO this should be unified elsewhere + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:C', 'Device:C_Small', 'Device:C_Polarized', 'Device:C_Polarized_Small') return {'1': self.pos, '2': self.neg} @@ -75,6 +79,7 @@ def parse_capacitor(cls, value: str) -> Tuple[Range, Range]: return (capacitance, Range.zero_to_upper(voltage)) @classmethod + @override def block_from_symbol(cls, symbol_name: str, properties: Mapping[str, str]) -> 'Capacitor': return Capacitor(*cls.parse_capacitor(properties['Value'])) @@ -180,11 +185,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.capacitance, self.voltage, self.voltage_rating_derating, self.exact_capacitance) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_voltage_rating, row[self.VOLTAGE_RATING]) self.assign(self.actual_capacitance, row[self.CAPACITANCE]) + @override def _row_filter(self, row: PartsTableRow) -> bool: derated_voltage = self.get(self.voltage) / self.get(self.voltage_rating_derating) return super()._row_filter(row) and \ @@ -195,6 +202,7 @@ def _row_filter_capacitance(self, row: PartsTableRow) -> bool: return row[self.CAPACITANCE].fuzzy_in(self.get(self.capacitance)) @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return (ESeriesUtil.series_of(row[cls.NOMINAL_CAPACITANCE], default=ESeriesUtil.SERIES_MAX + 1), super()._row_sort_by(row)) @@ -224,10 +232,12 @@ def __init__(self, *args: Any, single_nominal_capacitance: RangeLike = (0, 22)*u self.actual_derated_capacitance = self.Parameter(RangeExpr()) + @override def _row_filter_capacitance(self, row: PartsTableRow) -> bool: # post-derating capacitance filtering is in _table_postprocess return Range.exact(row[self.NOMINAL_CAPACITANCE]).fuzzy_in(self.get(self.single_nominal_capacitance)) + @override def _table_postprocess(self, table: PartsTable) -> PartsTable: def add_derated_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if not self.get(self.exact_capacitance): @@ -264,6 +274,7 @@ def add_derated_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]] row[self.PARALLEL_DERATED_CAPACITANCE].fuzzy_in(self.get(self.capacitance)) )) + @override def _row_generate(self, row: PartsTableRow) -> None: """This one is weird. Because this is the last in the class order, this is called last. So the top subclass needs explicit logic to handle parallel capacitors.""" @@ -307,6 +318,7 @@ def __init__(self, footprint: StringLike = "", manufacturer: StringLike = "", pa class DecouplingCapacitor(DiscreteApplication, KiCadImportableBlock): """Optionally polarized capacitor used for DC decoupling, with VoltageSink connections with voltage inference. Implemented as a shim block.""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:C', 'Device:C_Small', 'Device:C_Polarized', 'Device:C_Polarized_Small') return {'1': self.pwr, '2': self.gnd} @@ -339,6 +351,7 @@ def connected(self, gnd: Optional[Port[GroundLink]] = None, pwr: Optional[Port[V class AnalogCapacitor(DiscreteApplication, KiCadImportableBlock): """Capacitor attached to an analog line, that presents as an open model-wise. """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:C', 'Device:C_Small', 'Device:C_Polarized', 'Device:C_Polarized_Small') return {'1': self.io, '2': self.gnd} @@ -363,6 +376,7 @@ def connected(self, gnd: Optional[Port[GroundLink]] = None, io: Optional[Port[An class CombinedCapacitorElement(Capacitor): # to avoid an abstract part error + @override def contents(self) -> None: super().contents() self.assign(self.actual_capacitance, self.capacitance) # fake it, since a combined capacitance is handwavey @@ -391,6 +405,7 @@ def __init__(self, *, extend_upper: BoolLike = False) -> None: self.generator_param(self.pos.requested(), self.neg.requested(), self.extend_upper) + @override def generate(self) -> None: super().generate() capacitance = self.capacitances.sum() diff --git a/edg/abstract_parts/AbstractComparator.py b/edg/abstract_parts/AbstractComparator.py index 88a673d4b..d03ab4c64 100644 --- a/edg/abstract_parts/AbstractComparator.py +++ b/edg/abstract_parts/AbstractComparator.py @@ -1,5 +1,7 @@ from typing import Mapping +from typing_extensions import override + from .ResistiveDivider import FeedbackVoltageDivider, VoltageDivider from ..abstract_parts import Analog from ..electronics_model import * @@ -7,11 +9,13 @@ class Comparator(KiCadInstantiableBlock, Analog): """Abstract comparator interface, output goes high when inp > inn.""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name in ('Simulation_SPICE:OPAMP', 'edg_importable:Opamp') return {'+': self.inp, '-': self.inn, '3': self.out, 'V+': self.pwr, 'V-': self.gnd} @classmethod + @override def block_from_symbol(cls, symbol_name: str, properties: Mapping[str, str]) -> 'Comparator': return Comparator() @@ -55,6 +59,7 @@ def __init__(self, trip_voltage: RangeLike, *, invert: BoolLike = False, self.actual_trip_voltage = self.Parameter(RangeExpr()) + @override def generate(self) -> None: super().generate() diff --git a/edg/abstract_parts/AbstractCrystal.py b/edg/abstract_parts/AbstractCrystal.py index 56746ec57..9a667f682 100644 --- a/edg/abstract_parts/AbstractCrystal.py +++ b/edg/abstract_parts/AbstractCrystal.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from . import PartsTableSelector, PartsTableColumn, Capacitor, PartsTableRow from .Categories import * @@ -21,6 +23,7 @@ def __init__(self, frequency: RangeLike) -> None: self.crystal = self.Port(CrystalPort(self.actual_frequency), [InOut]) # set by subclass self.gnd = self.Port(Ground(), [Common]) + @override def contents(self) -> None: super().contents() @@ -66,10 +69,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.frequency) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ (row[self.FREQUENCY] in self.get(self.frequency)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_frequency, row[self.FREQUENCY]) @@ -103,6 +108,7 @@ class OscillatorCrystal(OscillatorReference): # TODO rename to disambiguate fro # TODO this should be formalized better. CAPACITOR_TOLERANCE = 0.38 + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/AbstractDiodes.py b/edg/abstract_parts/AbstractDiodes.py index e22b32c6e..d2aa1e79c 100644 --- a/edg/abstract_parts/AbstractDiodes.py +++ b/edg/abstract_parts/AbstractDiodes.py @@ -1,5 +1,6 @@ from typing import Dict, Any from deprecated import deprecated +from typing_extensions import override from ..electronics_model import * from .DummyDevices import ForcedAnalogVoltage @@ -54,6 +55,7 @@ class Diode(KiCadImportableBlock, BaseDiode): TODO power? capacitance? leakage current? """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:D', 'Device:D_Small') return {'A': self.anode, 'K': self.cathode} @@ -73,6 +75,7 @@ def __init__(self, reverse_voltage: RangeLike, current: RangeLike, *, self.actual_voltage_drop = self.Parameter(RangeExpr()) self.actual_reverse_recovery_time = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -97,6 +100,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.reverse_voltage, self.current, self.voltage_drop, self.reverse_recovery_time) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ self.get(self.reverse_voltage).fuzzy_in(row[self.VOLTAGE_RATING]) and \ @@ -104,6 +108,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: row[self.FORWARD_VOLTAGE].fuzzy_in(self.get(self.voltage_drop)) and \ row[self.REVERSE_RECOVERY].fuzzy_in(self.get(self.reverse_recovery_time)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_voltage_rating, row[self.VOLTAGE_RATING]) @@ -118,6 +123,7 @@ class ZenerDiode(KiCadImportableBlock, BaseDiode, DiscreteSemiconductor): TODO power? capacitance? leakage current? """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:D_Zener', 'Device:D_Zener_Small') return {'A': self.anode, 'K': self.cathode} @@ -130,6 +136,7 @@ def __init__(self, zener_voltage: RangeLike) -> None: self.actual_zener_voltage = self.Parameter(RangeExpr()) self.actual_power_rating = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -149,10 +156,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.zener_voltage) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.ZENER_VOLTAGE].fuzzy_in(self.get(self.zener_voltage)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_zener_voltage, row[self.ZENER_VOLTAGE]) @@ -170,6 +179,7 @@ def __init__(self, voltage: RangeLike): self.voltage = self.ArgParameter(voltage) + @override def contents(self) -> None: super().contents() self.diode = self.Block(ZenerDiode(zener_voltage=self.voltage)) @@ -191,6 +201,7 @@ def __init__(self, voltage: RangeLike): self.voltage = self.ArgParameter(voltage) + @override def contents(self) -> None: super().contents() @@ -204,6 +215,7 @@ def contents(self) -> None: self.connect(self.signal_out, self.forced.signal_out, self.diode.cathode.adapt_to(AnalogSink())) self.connect(self.diode.anode.adapt_to(Ground()), self.gnd) + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]: assert symbol_name == 'edg_importable:AnalogClampZenerDiode' return {'IN': self.signal_in, 'OUT': self.signal_out, 'GND': self.gnd} diff --git a/edg/abstract_parts/AbstractFerriteBead.py b/edg/abstract_parts/AbstractFerriteBead.py index a43f34717..a8eedd32c 100644 --- a/edg/abstract_parts/AbstractFerriteBead.py +++ b/edg/abstract_parts/AbstractFerriteBead.py @@ -1,5 +1,7 @@ from typing import Optional, cast, Dict, Any +from typing_extensions import override + from ..electronics_model import * from .PartsTable import PartsTableColumn, PartsTableRow from .PartsTablePart import PartsTableSelector @@ -11,6 +13,7 @@ class FerriteBead(PassiveComponent, KiCadImportableBlock, HasStandardFootprint): _STANDARD_FOOTPRINT = lambda: FerriteBeadStandardFootprint + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:L_Ferrite', 'Device:L_Ferrite_Small') return {'1': self.a, '2': self.b} @@ -30,6 +33,7 @@ def __init__(self, *, current: RangeLike = RangeExpr.ZERO, self.actual_hf_impedance = self.Parameter(RangeExpr()) self.actual_dc_resistance = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -74,12 +78,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.current, self.hf_impedance, self.dc_resistance) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ self.get(self.current).fuzzy_in(row[self.CURRENT_RATING]) and \ row[self.HF_IMPEDANCE].fuzzy_in(self.get(self.hf_impedance)) and \ row[self.DC_RESISTANCE].fuzzy_in(self.get(self.dc_resistance)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_current_rating, row[self.CURRENT_RATING]) @@ -89,6 +95,7 @@ def _row_generate(self, row: PartsTableRow) -> None: class SeriesPowerFerriteBead(DiscreteApplication, KiCadImportableBlock): """Series ferrite bead for power applications""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:L_Ferrite', 'Device:L_Ferrite_Small') return {'1': self.pwr_in, '2': self.pwr_out} diff --git a/edg/abstract_parts/AbstractFets.py b/edg/abstract_parts/AbstractFets.py index db03eb734..f18ee6da2 100644 --- a/edg/abstract_parts/AbstractFets.py +++ b/edg/abstract_parts/AbstractFets.py @@ -1,5 +1,7 @@ from typing import Optional, Any, Dict +from typing_extensions import override + from ..electronics_model import * from .PartsTable import PartsTableColumn, PartsTableRow, PartsTable from .PartsTablePart import PartsTableSelector @@ -29,6 +31,7 @@ class Fet(KiCadImportableBlock, DiscreteSemiconductor, HasStandardFootprint): """ _STANDARD_FOOTPRINT = lambda: FetStandardFootprint + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: # TODO actually check that the device channel corresponds with the schematic? assert symbol_name.startswith('Device:Q_NMOS_') or symbol_name.startswith('Device:Q_PMOS_') @@ -72,6 +75,7 @@ def __init__(self, drain_voltage: RangeLike, drain_current: RangeLike, *, self.actual_rds_on = self.Parameter(RangeExpr()) self.actual_gate_charge = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -163,6 +167,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.generator_param(self.drain_voltage, self.drain_current, self.gate_voltage, self.gate_threshold_voltage, self.rds_on, self.gate_charge, self.power, self.channel) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.CHANNEL] == self.get(self.channel) and \ @@ -174,6 +179,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: row[self.GATE_CHARGE].fuzzy_in(self.get(self.gate_charge)) and \ self.get(self.power).fuzzy_in(row[self.POWER_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_drain_voltage_rating, row[self.VDS_RATING]) @@ -194,10 +200,12 @@ class SwitchFet(Fet): # TODO ideally this would just instantaite a Fet internally, but the parts selection becomes more complex b/c # parameters are cross-dependent @staticmethod + @override def NFet(*args: Any, **kwargs: Any) -> 'SwitchFet': return SwitchFet(*args, **kwargs, channel='N') @staticmethod + @override def PFet(*args: Any, **kwargs: Any) -> 'SwitchFet': return SwitchFet(*args, **kwargs, channel='P') @@ -225,6 +233,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.actual_switching_power = self.Parameter(RangeExpr()) self.actual_total_power = self.Parameter(RangeExpr()) + @override def _row_filter(self, row: PartsTableRow) -> bool: # here this is just a pre-filter step return super()._row_filter(row) and \ row[self.CHANNEL] == self.get(self.channel) and \ @@ -236,6 +245,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: # here this is just a pre-fi row[self.GATE_CHARGE].fuzzy_in(self.get(self.gate_charge)) and \ self.get(self.power).fuzzy_in(row[self.POWER_RATING]) + @override def _table_postprocess(self, table: PartsTable) -> PartsTable: drive_current = self.get(self.drive_current) gate_drive_rise, gate_drive_fall = drive_current.upper, -drive_current.lower @@ -263,6 +273,7 @@ def process_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: return super()._table_postprocess(table).map_new_columns(process_row) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_drain_voltage_rating, row[self.VDS_RATING]) diff --git a/edg/abstract_parts/AbstractFuse.py b/edg/abstract_parts/AbstractFuse.py index 23215bf99..644c54823 100644 --- a/edg/abstract_parts/AbstractFuse.py +++ b/edg/abstract_parts/AbstractFuse.py @@ -1,6 +1,7 @@ from typing import Optional, cast, Any from deprecated import deprecated +from typing_extensions import override from ..electronics_model import * from .Categories import * @@ -28,6 +29,7 @@ def __init__(self, trip_current: RangeLike, *, hold_current: RangeLike = RangeEx self.voltage = self.ArgParameter(voltage) # operating voltage self.actual_voltage_rating = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -118,12 +120,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.trip_current, self.hold_current, self.voltage) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.TRIP_CURRENT].fuzzy_in(self.get(self.trip_current)) and \ row[self.HOLD_CURRENT].fuzzy_in(self.get(self.hold_current)) and \ self.get(self.voltage).fuzzy_in(row[self.VOLTAGE_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_trip_current, row[self.TRIP_CURRENT]) diff --git a/edg/abstract_parts/AbstractInductor.py b/edg/abstract_parts/AbstractInductor.py index 45241005a..b4b2c70f9 100644 --- a/edg/abstract_parts/AbstractInductor.py +++ b/edg/abstract_parts/AbstractInductor.py @@ -1,5 +1,7 @@ from typing import Dict, Optional, cast, Any +from typing_extensions import override + from ..electronics_model import * from .PartsTable import PartsTableColumn, PartsTableRow, ExperimentalUserFnPartsTable from .PartsTablePart import PartsTableSelector @@ -11,6 +13,7 @@ class Inductor(PassiveComponent, KiCadImportableBlock, HasStandardFootprint): _STANDARD_FOOTPRINT = lambda: InductorStandardFootprint + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name in ('Device:L', 'Device:L_Small') return {'1': self.a, '2': self.b} @@ -38,6 +41,7 @@ def __init__(self, inductance: RangeLike, self.actual_frequency_rating = self.Parameter(RangeExpr()) self.actual_resistance_dc = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -140,6 +144,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.generator_param(self.inductance, self.current, self.frequency, self.resistance_dc, self.experimental_filter_fn) + @override def _row_filter(self, row: PartsTableRow) -> bool: filter_fn_str = self.get(self.experimental_filter_fn) if filter_fn_str: @@ -154,6 +159,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: self.get(self.frequency).fuzzy_in(row[self.FREQUENCY_RATING]) and\ (filter_fn is None or filter_fn(row)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_inductance, row[self.INDUCTANCE]) @@ -162,6 +168,7 @@ def _row_generate(self, row: PartsTableRow) -> None: self.assign(self.actual_resistance_dc, row[self.DC_RESISTANCE]) @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return row[cls.DC_RESISTANCE].center() diff --git a/edg/abstract_parts/AbstractJumper.py b/edg/abstract_parts/AbstractJumper.py index 3ca2421dc..2b5d02a46 100644 --- a/edg/abstract_parts/AbstractJumper.py +++ b/edg/abstract_parts/AbstractJumper.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import DiscreteComponent, TypedJumper @@ -20,6 +22,7 @@ def __init__(self) -> None: self.input = self.Port(DigitalSink.empty(), [Input]) self.output = self.Port(DigitalSource.empty(), [Output]) + @override def contents(self) -> None: super().contents() self.device = self.Block(Jumper()) diff --git a/edg/abstract_parts/AbstractLed.py b/edg/abstract_parts/AbstractLed.py index 37fc1621e..758d45510 100644 --- a/edg/abstract_parts/AbstractLed.py +++ b/edg/abstract_parts/AbstractLed.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .Categories import * from .AbstractResistor import Resistor @@ -60,10 +62,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.color) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ (not self.get(self.color) or row[self.COLOR] == self.get(self.color)) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_color, row[self.COLOR]) @@ -125,6 +129,7 @@ def __init__(self, count: IntLike, color: LedColorLike = Led.Any, *, self.count = self.ArgParameter(count) self.generator_param(self.count) + @override def generate(self) -> None: super().generate() self.led = ElementDict[IndicatorLed]() @@ -185,6 +190,7 @@ def __init__(self, count: IntLike, color: LedColorLike = Led.Any, *, self.count = self.ArgParameter(count) self.generator_param(self.count) + @override def generate(self) -> None: super().generate() self.led = ElementDict[IndicatorSinkLed]() diff --git a/edg/abstract_parts/AbstractOpamp.py b/edg/abstract_parts/AbstractOpamp.py index 3feafab42..215a14272 100644 --- a/edg/abstract_parts/AbstractOpamp.py +++ b/edg/abstract_parts/AbstractOpamp.py @@ -1,5 +1,7 @@ from typing import Mapping, Tuple, List, NamedTuple +from typing_extensions import override + from ..electronics_model import * from .Categories import Analog, MultipackDevice @@ -8,11 +10,13 @@ class Opamp(Analog, KiCadInstantiableBlock, Block): """Base class for opamps. Parameters need to be more restricted in subclasses. """ + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name in ('Simulation_SPICE:OPAMP', 'edg_importable:Opamp') return {'+': self.inp, '-': self.inn, '3': self.out, 'V+': self.pwr, 'V-': self.gnd} @classmethod + @override def block_from_symbol(cls, symbol_name: str, properties: Mapping[str, str]) -> 'Opamp': return Opamp() @@ -64,6 +68,7 @@ def _make_multipack_opamp(self) -> OpampPorts: Returns (gnd, pwr, [(in-, in+, out)]).""" raise NotImplementedError # implement me + @override def generate(self) -> None: super().generate() amp_ports = self._make_multipack_opamp() diff --git a/edg/abstract_parts/AbstractOscillator.py b/edg/abstract_parts/AbstractOscillator.py index 87c73355a..1654e5c05 100644 --- a/edg/abstract_parts/AbstractOscillator.py +++ b/edg/abstract_parts/AbstractOscillator.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from . import PartsTableColumn, PartsTableRow, PartsTableSelector from .Categories import * @@ -18,6 +20,7 @@ def __init__(self, frequency: RangeLike) -> None: self.pwr = self.Port(VoltageSink.empty(), [Power]) self.out = self.Port(DigitalSource.empty(), [Output]) + @override def contents(self) -> None: super().contents() @@ -38,10 +41,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.frequency) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.FREQUENCY] in self.get(self.frequency) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_frequency, row[self.FREQUENCY]) diff --git a/edg/abstract_parts/AbstractPowerConverters.py b/edg/abstract_parts/AbstractPowerConverters.py index eab3dcf23..5f9fc3803 100644 --- a/edg/abstract_parts/AbstractPowerConverters.py +++ b/edg/abstract_parts/AbstractPowerConverters.py @@ -2,6 +2,7 @@ from typing import Optional, NamedTuple, Any, Callable from deprecated import deprecated +from typing_extensions import override from .AbstractCapacitor import DecouplingCapacitor from .AbstractInductor import Inductor, TableInductor @@ -29,6 +30,7 @@ def __init__(self, output_voltage: RangeLike) -> None: self.pwr_out = self.Port(VoltageSource.empty(), [Output]) self.gnd = self.Port(Ground.empty(), [Common]) + @override def contents(self) -> None: super().contents() @@ -52,10 +54,12 @@ def _generator_inner_reset_pin(self) -> Port[DigitalLink]: """Returns the inner device's reset pin, to be connected in the generator. Only called within a generator.""" + @override def contents(self) -> None: super().contents() self.generator_param(self.reset.is_connected()) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): @@ -81,6 +85,7 @@ class VoltageReference(LinearRegulator): class IdealLinearRegulator(Resettable, LinearRegulator, IdealModel): """Ideal linear regulator, draws the output current and produces spec output voltage limited by input voltage""" + @override def contents(self) -> None: super().contents() effective_output_voltage = self.output_voltage.intersect((0, self.pwr_in.link().voltage.upper())) @@ -178,6 +183,7 @@ class DiscreteBuckConverter(BuckConverter): class IdealBuckConverter(Resettable, DiscreteBuckConverter, IdealModel): """Ideal buck converter producing the spec output voltage (buck-boost) limited by input voltage and drawing input current from conversation of power""" + @override def contents(self) -> None: super().contents() effective_output_voltage = self.output_voltage.intersect((0, self.pwr_in.link().voltage.upper())) @@ -360,6 +366,7 @@ def __init__(self, input_voltage: RangeLike, output_voltage: RangeLike, frequenc self.actual_inductor_current_ripple = self.Parameter(RangeExpr()) self.actual_inductor_current_peak = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -370,6 +377,7 @@ def contents(self) -> None: ", ripple: ", DescriptionString.FormatUnits(self.actual_inductor_current_ripple, "A") ) + @override def generate(self) -> None: super().generate() values = self._calculate_parameters(self.get(self.input_voltage), self.get(self.output_voltage), @@ -428,6 +436,7 @@ class DiscreteBoostConverter(BoostConverter): class IdealBoostConverter(Resettable, DiscreteBoostConverter, IdealModel): """Ideal boost converter producing the spec output voltage (buck-boost) limited by input voltage and drawing input current from conversation of power""" + @override def contents(self) -> None: super().contents() effective_output_voltage = self.output_voltage.intersect((self.pwr_in.link().voltage.lower(), float('inf'))) @@ -553,6 +562,7 @@ def __init__(self, input_voltage: RangeLike, output_voltage: RangeLike, frequenc self.actual_inductor_current_ripple = self.Parameter(RangeExpr()) self.actual_inductor_current_peak = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -563,6 +573,7 @@ def contents(self) -> None: ", ripple: ", DescriptionString.FormatUnits(self.actual_inductor_current_ripple, "A") ) + @override def generate(self) -> None: super().generate() values = self._calculate_parameters(self.get(self.input_voltage), self.get(self.output_voltage), @@ -620,6 +631,7 @@ class DiscreteBuckBoostConverter(BuckBoostConverter): class IdealVoltageRegulator(Resettable, DiscreteBuckBoostConverter, IdealModel): """Ideal buck-boost / general DC-DC converter producing the spec output voltage and drawing input current from conversation of power""" + @override def contents(self) -> None: super().contents() self.gnd.init_from(Ground()) @@ -675,6 +687,7 @@ def __init__(self, input_voltage: RangeLike, output_voltage: RangeLike, frequenc self.actual_inductor_current_ripple = self.Parameter(RangeExpr()) self.actual_inductor_current_peak = self.Parameter(RangeExpr()) # inductor current accounting for ripple (upper is peak) + @override def contents(self) -> None: super().contents() @@ -685,6 +698,7 @@ def contents(self) -> None: ", ripple: ", DescriptionString.FormatUnits(self.actual_inductor_current_ripple, "A") ) + @override def generate(self) -> None: super().generate() buck_values = BuckConverterPowerPath._calculate_parameters( diff --git a/edg/abstract_parts/AbstractResistor.py b/edg/abstract_parts/AbstractResistor.py index 9b96e186a..693304773 100644 --- a/edg/abstract_parts/AbstractResistor.py +++ b/edg/abstract_parts/AbstractResistor.py @@ -1,6 +1,8 @@ import re from typing import Optional, cast, Mapping, Dict, Any +from typing_extensions import override + from ..electronics_model import * from .ESeriesUtil import ESeriesUtil from .PartsTable import PartsTableColumn, PartsTableRow @@ -17,6 +19,7 @@ class Resistor(PassiveComponent, KiCadInstantiableBlock, HasStandardFootprint): "\s*" + "((?:\+-|\+/-|±)?\s*[\d.]+\s*%?)?" + "$") RESISTOR_DEFAULT_TOL = 0.05 # TODO this should be unified elsewhere + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name in ('Device:R', 'Device:R_Small') return {'1': self.a, '2': self.b} @@ -35,6 +38,7 @@ def parse_resistor(cls, value: str) -> Range: return Range.from_tolerance(center, (-cls.RESISTOR_DEFAULT_TOL, cls.RESISTOR_DEFAULT_TOL)) @classmethod + @override def block_from_symbol(cls, symbol_name: str, properties: Mapping[str, str]) -> 'Resistor': return Resistor(resistance=cls.parse_resistor(properties['Value'])) @@ -52,6 +56,7 @@ def __init__(self, resistance: RangeLike, power: RangeLike = RangeExpr.ZERO, self.actual_power_rating = self.Parameter(RangeExpr()) self.actual_voltage_rating = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -107,12 +112,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.resistance, self.power, self.voltage) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ row[self.RESISTANCE].fuzzy_in(self.get(self.resistance)) and \ self.get(self.power).fuzzy_in(row[self.POWER_RATING]) and \ self.get(self.voltage).fuzzy_in(row[self.VOLTAGE_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.actual_resistance, row[self.RESISTANCE]) @@ -120,6 +127,7 @@ def _row_generate(self, row: PartsTableRow) -> None: self.assign(self.actual_voltage_rating, row[self.VOLTAGE_RATING]) @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return (ESeriesUtil.series_of(row[cls.RESISTANCE].center(), default=ESeriesUtil.SERIES_MAX + 1), super()._row_sort_by(row)) @@ -137,6 +145,7 @@ def __init__(self, *args: Any, count: IntLike = 2, **kwargs: Any) -> None: self.count = self.ArgParameter(count) self.generator_param(self.count, self.resistance) + @override def generate(self) -> None: super().generate() count = self.get(self.count) @@ -225,6 +234,7 @@ def __init__(self, resistance: RangeLike): self.generator_param(self.io.requested()) self.resistance = self.ArgParameter(resistance) + @override def generate(self) -> None: super().generate() self.res = ElementDict[PullupResistor]() @@ -243,6 +253,7 @@ def __init__(self, resistance: RangeLike): self.generator_param(self.io.requested()) self.resistance = self.ArgParameter(resistance) + @override def generate(self) -> None: super().generate() self.res = ElementDict[PulldownResistor]() @@ -254,6 +265,7 @@ def generate(self) -> None: class SeriesPowerResistor(DiscreteApplication, KiCadImportableBlock): """Series resistor for power applications""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name in ('Device:R', 'Device:R_Small') return {'1': self.pwr_in, '2': self.pwr_out} @@ -314,6 +326,7 @@ def __init__(self, resistance: RangeLike, sense_in_reqd: BoolLike = True) -> Non self.actual_resistance = self.Parameter(RangeExpr(self.res.actual_resistance)) + @override def generate(self) -> None: super().generate() @@ -330,6 +343,7 @@ def connected(self, pwr_in: Optional[Port[VoltageLink]] = None, pwr_out: Optiona cast(Block, builder.get_enclosing_block()).connect(pwr_out, self.pwr_out) return self + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]: assert symbol_name == 'edg_importable:CurrentSenseResistor' return {'1': self.pwr_in, '2': self.pwr_out, 'sense_in': self.sense_in, 'sense_out': self.sense_out} @@ -357,6 +371,7 @@ def __init__(self, clamp_target: RangeLike = (0, 3)*Volt, clamp_current: RangeLi self.protection_voltage = self.ArgParameter(protection_voltage) self.zero_out = self.ArgParameter(zero_out) + @override def contents(self) -> None: super().contents() @@ -372,6 +387,7 @@ def contents(self) -> None: impedance=self.signal_in.link().source_impedance + self.res.actual_resistance )), self.signal_out) + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]: assert symbol_name == 'Device:R' return {'1': self.signal_in, '2': self.signal_out} @@ -399,6 +415,7 @@ def __init__(self, clamp_target: RangeLike = (0, 3)*Volt, clamp_current: RangeLi self.protection_voltage = self.ArgParameter(protection_voltage) self.zero_out = self.ArgParameter(zero_out) + @override def contents(self) -> None: super().contents() @@ -413,6 +430,7 @@ def contents(self) -> None: output_thresholds=self.signal_in.link().output_thresholds )), self.signal_out) + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]: assert symbol_name == 'Device:R' return {'1': self.signal_in, '2': self.signal_out} diff --git a/edg/abstract_parts/AbstractResistorArray.py b/edg/abstract_parts/AbstractResistorArray.py index 95f65a121..bdfed3bb0 100644 --- a/edg/abstract_parts/AbstractResistorArray.py +++ b/edg/abstract_parts/AbstractResistorArray.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .AbstractResistor import Resistor from .PartsTable import PartsTableColumn, PartsTableRow @@ -36,6 +38,7 @@ def __init__(self, count: IntLike = 0) -> None: # 0 means 'size automatically' self.unpacked_assign(self.elements.params(lambda x: x.actual_resistance), self.actual_resistance) self.unpacked_assign(self.elements.params(lambda x: x.actual_power_rating), self.actual_power_rating) + @override def contents(self) -> None: super().contents() @@ -96,6 +99,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.count, self.a.requested(), self.b.requested(), self.resistances, self.powers) + @override def _row_filter(self, row: PartsTableRow) -> bool: # TODO some kind of range intersect construct? resistances_min = max([resistance.lower for resistance in self.get(self.resistances)]) @@ -114,6 +118,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: row[self.RESISTANCE].fuzzy_in(resistance_intersect) and \ powers_hull.fuzzy_in(row[self.POWER_RATING]) + @override def _row_generate(self, row: PartsTableRow) -> None: for i in range(row[self.COUNT]): # must generate ports before creating the footprint self.a.append_elt(Passive(), str(i)) diff --git a/edg/abstract_parts/AbstractSolidStateRelay.py b/edg/abstract_parts/AbstractSolidStateRelay.py index 0484246a9..6654d78e8 100644 --- a/edg/abstract_parts/AbstractSolidStateRelay.py +++ b/edg/abstract_parts/AbstractSolidStateRelay.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..electronics_model import * from .MergedBlocks import MergedAnalogSource from .AbstractResistor import Resistor @@ -38,6 +40,7 @@ class VoltageIsolatedSwitch(Interface, KiCadImportableBlock, Block): The ports are not tagged with Input/Output/InOut, because of potential for confusion between the digital side and the analog side. """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:VoltageIsolatedSwitch' return {'in': self.signal, 'gnd': self.gnd, 'ain': self.pwr_in, 'aout': self.pwr_out} @@ -82,6 +85,7 @@ class AnalogIsolatedSwitch(Interface, KiCadImportableBlock, Block): A separate output-side pull port allows modeling the output switch standoff voltage when the switch is off. """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:AnalogIsolatedSwitch' return {'in': self.signal, 'gnd': self.gnd, diff --git a/edg/abstract_parts/AbstractSwitch.py b/edg/abstract_parts/AbstractSwitch.py index e1c86aa0a..eaacab234 100644 --- a/edg/abstract_parts/AbstractSwitch.py +++ b/edg/abstract_parts/AbstractSwitch.py @@ -1,5 +1,7 @@ from typing import Dict, Any +from typing_extensions import override + from ..electronics_model import * from .Categories import * @@ -7,6 +9,7 @@ @abstract_block class Switch(KiCadImportableBlock, DiscreteComponent): """Two-ported device that closes a circuit when pressed.""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'Switch:SW_SPST' return {'1': self.sw, '2': self.com} @@ -88,6 +91,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground.empty(), [Common]) self.out = self.Port(DigitalSource.empty(), [Output]) + @override def contents(self) -> None: super().contents() self.package = self.Block(Switch(current=self.out.link().current_drawn, @@ -110,6 +114,7 @@ def __init__(self) -> None: class DigitalWrapperRotaryEncoder(DigitalRotaryEncoder): """Basic implementation for DigitalRotaryEncoder as a wrapper around a passive-typed RotaryEncoder.""" + @override def contents(self) -> None: super().contents() self.package = self.Block(RotaryEncoder(current=self.a.link().current_drawn.hull(self.b.link().current_drawn), @@ -131,10 +136,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class DigitalWrapperRotaryEncoderWithSwitch(DigitalRotaryEncoderSwitch, DigitalWrapperRotaryEncoder, GeneratorBlock): + @override def contents(self) -> None: super().contents() self.generator_param(self.sw.is_connected()) + @override def generate(self) -> None: super().generate() if self.get(self.sw.is_connected()): @@ -158,6 +165,7 @@ def __init__(self) -> None: class DigitalWrapperDirectionSwitch(DigitalDirectionSwitch): """Basic implementation for DigitalDirectionSwitch as a wrapper around a passive-typed DirectionSwitch.""" + @override def contents(self) -> None: super().contents() self.package = self.Block(DirectionSwitch(current=self.a.link().current_drawn.hull(self.b.link().current_drawn), @@ -182,10 +190,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class DigitalWrapperDirectionSwitchWithCenter(DigitalDirectionSwitchCenter, DigitalWrapperDirectionSwitch, GeneratorBlock): + @override def contents(self) -> None: super().contents() self.generator_param(self.center.is_connected()) + @override def generate(self) -> None: super().generate() if self.get(self.center.is_connected()): diff --git a/edg/abstract_parts/AbstractTestPoint.py b/edg/abstract_parts/AbstractTestPoint.py index 3c9c067be..9fa38c335 100644 --- a/edg/abstract_parts/AbstractTestPoint.py +++ b/edg/abstract_parts/AbstractTestPoint.py @@ -1,5 +1,7 @@ from typing import cast, Any +from typing_extensions import override + from ..electronics_model import * from ..electronics_model.CanPort import CanLogicLink from ..electronics_model.I2cPort import I2cLink @@ -27,6 +29,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.tp_name = self.ArgParameter(tp_name) self.tp = self.Block(TestPoint(tp_name=StringExpr())) + @override def contents(self) -> None: super().contents() self.assign(self.tp.tp_name, (self.tp_name == "").then_else(self.io.link().name(), self.tp_name)) @@ -42,6 +45,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.gnd = self.Export(self.conn.gnd, [Common]) self.io: Port + @override def contents(self) -> None: super().contents() conn_tp = self.conn.with_mixin(RfConnectorTestPoint(StringExpr())) @@ -92,6 +96,7 @@ def __init__(self, tp_name: StringLike = '') -> None: self.tp_name = self.ArgParameter(tp_name) self.generator_param(self.io.requested(), self.tp_name) + @override def generate(self) -> None: super().generate() self.tp = ElementDict[DigitalTestPoint]() @@ -136,6 +141,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.io = self.Port(I2cTarget(DigitalBidir.empty()), [InOut]) self.tp_name = self.ArgParameter(tp_name) + @override def contents(self) -> None: super().contents() name_prefix = (self.tp_name == '').then_else(self.io.link().name(), self.tp_name) @@ -156,6 +162,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.io = self.Port(SpiPeripheral(DigitalBidir.empty()), [InOut]) self.tp_name = self.ArgParameter(tp_name) + @override def contents(self) -> None: super().contents() name_prefix = (self.tp_name == '').then_else(self.io.link().name(), self.tp_name) @@ -178,6 +185,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.io = self.Port(CanPassivePort(DigitalBidir.empty()), [InOut]) self.tp_name = self.ArgParameter(tp_name) + @override def contents(self) -> None: super().contents() name_prefix = (self.tp_name == '').then_else(self.io.link().name(), self.tp_name) @@ -198,6 +206,7 @@ def __init__(self, tp_name: StringLike = "") -> None: self.io = self.Port(CanDiffPort(DigitalBidir.empty()), [InOut]) self.tp_name = self.ArgParameter(tp_name) + @override def contents(self) -> None: super().contents() name_prefix = (self.tp_name == '').then_else(self.io.link().name(), self.tp_name) diff --git a/edg/abstract_parts/AbstractTvsDiode.py b/edg/abstract_parts/AbstractTvsDiode.py index bcc018ad6..aa4b455bd 100644 --- a/edg/abstract_parts/AbstractTvsDiode.py +++ b/edg/abstract_parts/AbstractTvsDiode.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import * from .AbstractDiodes import BaseDiode @@ -39,6 +41,7 @@ def __init__(self, working_voltage: RangeLike): self.working_voltage = self.ArgParameter(working_voltage) + @override def contents(self) -> None: super().contents() self.diode = self.Block(TvsDiode(working_voltage=self.working_voltage)) @@ -59,6 +62,7 @@ def __init__(self, working_voltage: RangeLike, *, capacitance: RangeLike = Range self.working_voltage = self.ArgParameter(working_voltage) self.capacitance = self.ArgParameter(capacitance) + @override def contents(self) -> None: super().contents() self.diode = self.Block(TvsDiode(working_voltage=self.working_voltage, capacitance=self.capacitance)) diff --git a/edg/abstract_parts/Categories.py b/edg/abstract_parts/Categories.py index fb5c8e38e..f027c6939 100644 --- a/edg/abstract_parts/Categories.py +++ b/edg/abstract_parts/Categories.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..core import BoolLike, init_in_parent from ..electronics_model import Block, abstract_block, InternalBlock @@ -353,6 +355,7 @@ def __init__(self, *args: Any, allow_ideal: BoolLike = False, **kwargs: Any) -> super().__init__(*args, **kwargs) self.allow_ideal = self.ArgParameter(allow_ideal) + @override def contents(self) -> None: super().contents() self.require(self.allow_ideal, "ideal model") diff --git a/edg/abstract_parts/CustomDiode.py b/edg/abstract_parts/CustomDiode.py index e4c87fff0..3b5e4cda6 100644 --- a/edg/abstract_parts/CustomDiode.py +++ b/edg/abstract_parts/CustomDiode.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .AbstractDiodes import Diode @@ -20,6 +22,7 @@ def __init__(self, *args: Any, footprint_spec: StringLike = "", self.assign(self.actual_voltage_drop, Range.zero_to_upper(0)) self.assign(self.actual_reverse_recovery_time, Range.zero_to_upper(0)) + @override def generate(self) -> None: self.footprint( self._standard_footprint().REFDES_PREFIX, self.footprint_spec, diff --git a/edg/abstract_parts/CustomFet.py b/edg/abstract_parts/CustomFet.py index 4cb706d2b..1bfdcdf64 100644 --- a/edg/abstract_parts/CustomFet.py +++ b/edg/abstract_parts/CustomFet.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .AbstractFets import SwitchFet @@ -23,6 +25,7 @@ def __init__(self, *args: Any, footprint_spec: StringLike = "", self.assign(self.actual_rds_on, Range.zero_to_upper(0)) self.assign(self.actual_gate_charge, Range.zero_to_upper(0)) + @override def generate(self) -> None: self.footprint( self._standard_footprint().REFDES_PREFIX, self.footprint_spec, diff --git a/edg/abstract_parts/DigitalAmplifiers.py b/edg/abstract_parts/DigitalAmplifiers.py index b9fc3c185..0d11cdbf9 100644 --- a/edg/abstract_parts/DigitalAmplifiers.py +++ b/edg/abstract_parts/DigitalAmplifiers.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..electronics_model import * from .AbstractFets import SwitchFet from .AbstractResistor import Resistor @@ -33,6 +35,7 @@ def __init__(self, pull_resistance: RangeLike = 10*kOhm(tol=0.05), max_rds: Floa self.clamp_resistance_ratio = self.ArgParameter(clamp_resistance_ratio) self.generator_param(self.clamp_voltage) + @override def generate(self) -> None: super().generate() @@ -114,6 +117,7 @@ def __init__(self, max_rds: FloatLike = 1*Ohm, frequency: RangeLike = RangeExpr. self.max_rds = self.ArgParameter(max_rds) self.frequency = self.ArgParameter(frequency) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/DigitalIsolator.py b/edg/abstract_parts/DigitalIsolator.py index f4333c3de..764957baf 100644 --- a/edg/abstract_parts/DigitalIsolator.py +++ b/edg/abstract_parts/DigitalIsolator.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import Interface @@ -23,6 +25,7 @@ def __init__(self) -> None: self.generator_param(self.in_a.requested(), self.out_b.requested(), self.in_b.requested(), self.out_a.requested()) + @override def generate(self) -> None: # validity checks super().generate() assert self.get(self.in_a.requested()) == self.get(self.out_b.requested()), \ diff --git a/edg/abstract_parts/DummyDevices.py b/edg/abstract_parts/DummyDevices.py index 815f44c1f..b5b4ddc15 100644 --- a/edg/abstract_parts/DummyDevices.py +++ b/edg/abstract_parts/DummyDevices.py @@ -192,6 +192,7 @@ def __init__(self, forced_signal: RangeLike = RangeExpr()) -> None: self.assign(self.signal_in.current_draw, self.signal_out.link().current_drawn) + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:Adapter' return {'1': self.signal_in, '2': self.signal_out} diff --git a/edg/abstract_parts/GenericCapacitor.py b/edg/abstract_parts/GenericCapacitor.py index 598acc084..11ee086d7 100644 --- a/edg/abstract_parts/GenericCapacitor.py +++ b/edg/abstract_parts/GenericCapacitor.py @@ -1,6 +1,8 @@ from typing import NamedTuple, Dict, Optional, Any import math +from typing_extensions import override + from ..electronics_model import * from .AbstractCapacitor import Capacitor, DummyCapacitorFootprint from .SelectorArea import SelectorArea @@ -99,6 +101,7 @@ class SmtCeramicCapacitorGenericPackageSpecs(NamedTuple): ), ] + @override def generate(self) -> None: """ Selects a generic capacitor without using product tables diff --git a/edg/abstract_parts/GenericResistor.py b/edg/abstract_parts/GenericResistor.py index 46d095974..e68664bb1 100644 --- a/edg/abstract_parts/GenericResistor.py +++ b/edg/abstract_parts/GenericResistor.py @@ -1,5 +1,7 @@ from typing import List, Tuple, Any +from typing_extensions import override + from ..electronics_model import * from .AbstractResistor import Resistor from .ESeriesUtil import ESeriesUtil @@ -27,6 +29,7 @@ def __init__(self, *args: Any, series: IntLike = 24, tolerance: FloatLike = 0.01 self.generator_param(self.resistance, self.power, self.series, self.tolerance, self.footprint_spec, self.footprint_area) + @override def generate(self) -> None: super().generate() diff --git a/edg/abstract_parts/I2cBitBang.py b/edg/abstract_parts/I2cBitBang.py index d98c2e888..dedfe7a03 100644 --- a/edg/abstract_parts/I2cBitBang.py +++ b/edg/abstract_parts/I2cBitBang.py @@ -1,5 +1,7 @@ from typing import cast +from typing_extensions import override + from ..electronics_model import * from .Categories import * @@ -12,6 +14,7 @@ def __init__(self) -> None: self.scl = self.Port(DigitalBidir.empty()) self.sda = self.Port(DigitalBidir.empty()) + @override def contents(self) -> None: super().contents() self.connect(self.i2c.scl, self.scl) diff --git a/edg/abstract_parts/I2cPullup.py b/edg/abstract_parts/I2cPullup.py index 1e22f1f7e..32f766199 100644 --- a/edg/abstract_parts/I2cPullup.py +++ b/edg/abstract_parts/I2cPullup.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import * from .AbstractResistor import PullupResistor @@ -12,6 +14,7 @@ def __init__(self) -> None: self.i2c = self.Port(I2cPullupPort.empty(), [InOut]) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/IdealIoController.py b/edg/abstract_parts/IdealIoController.py index ea0a276ae..f347b7e31 100644 --- a/edg/abstract_parts/IdealIoController.py +++ b/edg/abstract_parts/IdealIoController.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import IdealModel from .IoController import IoController @@ -16,6 +18,7 @@ def __init__(self) -> None: self.spi_peripheral.requested(), self.i2c.requested(), self.i2c_target.requested(), self.uart.requested(), self.usb.requested(), self.can.requested(), self.i2s.requested()) + @override def generate(self) -> None: self.pwr.init_from(VoltageSink( current_draw=RangeExpr() diff --git a/edg/abstract_parts/IoController.py b/edg/abstract_parts/IoController.py index cc4613416..b4691e030 100644 --- a/edg/abstract_parts/IoController.py +++ b/edg/abstract_parts/IoController.py @@ -2,6 +2,7 @@ from typing import List, Dict, Tuple, Type, Optional, Any from deprecated import deprecated +from typing_extensions import override from ..electronics_model import * from .PinMappable import AllocatedResource, PinMappable, PinMapUtil @@ -150,6 +151,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.pin_assigns) + @override def contents(self) -> None: super().contents() for io_port in self._io_ports: # defined in contents() so subclass __init__ can define additional _io_ports diff --git a/edg/abstract_parts/IoControllerExportable.py b/edg/abstract_parts/IoControllerExportable.py index 22a9f1174..bc993f1e7 100644 --- a/edg/abstract_parts/IoControllerExportable.py +++ b/edg/abstract_parts/IoControllerExportable.py @@ -1,5 +1,7 @@ from typing import List, Optional, TypeVar, cast, Any +from typing_extensions import override + from ..electronics_model import * from .IoController import BaseIoController @@ -17,6 +19,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.ic: BaseIoController self.generator_param(self.pin_assigns) + @override def contents(self) -> None: # TODO can this be deduplicated w/ BaseIoControllerPinmapGenerator? super().contents() for io_port in self._io_ports: # defined in contents() so subclass __init__ can define additional _io_ports @@ -48,6 +51,7 @@ def _inner_pin_assigns(self, assigns: List[str]) -> List[str]: Called within generate (has access to generator params), and after modifications from make_export_*.""" return assigns + @override def generate(self) -> None: super().generate() inner_ios_by_type = {self._type_of_io(io_port): io_port for io_port in self.ic._io_ports} diff --git a/edg/abstract_parts/IoControllerMixins.py b/edg/abstract_parts/IoControllerMixins.py index a2592081c..3aa684e16 100644 --- a/edg/abstract_parts/IoControllerMixins.py +++ b/edg/abstract_parts/IoControllerMixins.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from .IoController import IoController from .AbstractCrystal import OscillatorReference from ..electronics_model import * @@ -17,6 +19,7 @@ def _crystal_required(self) -> bool: Called within generate, has access to generator params.""" return False + @override def generate(self) -> None: super().generate() if self._crystal_required(): diff --git a/edg/abstract_parts/IoControllerProgramming.py b/edg/abstract_parts/IoControllerProgramming.py index 1fd6d40b5..f27633d2f 100644 --- a/edg/abstract_parts/IoControllerProgramming.py +++ b/edg/abstract_parts/IoControllerProgramming.py @@ -1,5 +1,7 @@ from typing import List +from typing_extensions import override + from ..electronics_model import * from .AbstractDebugHeaders import SwdCortexTargetConnector, SwdCortexTargetConnectorReset, SwdCortexTargetConnectorSwo, \ SwdCortexTargetConnectorTdi @@ -24,6 +26,7 @@ def __init__(self, swd_swo_pin: StringLike = "NC", swd_tdi_pin: StringLike = "NC self.swd_node = self.connect() # connect this internal node to the microcontroller self.reset_node = self.connect() # connect this internal node to the microcontroller + @override def contents(self) -> None: super().contents() self.swd = self.Block(SwdCortexTargetConnector()) @@ -31,6 +34,7 @@ def contents(self) -> None: self.connect(self.swd.pwr, self.pwr) self.connect(self.swd_node, self.swd.swd) + @override def _inner_pin_assigns(self, assigns: List[str]) -> List[str]: assigns = super()._inner_pin_assigns(assigns) if self.get(self.swd_swo_pin) != 'NC': @@ -39,6 +43,7 @@ def _inner_pin_assigns(self, assigns: List[str]) -> List[str]: assigns.append(f'swd_tdi={self.get(self.swd_tdi_pin)}') return assigns + @override def generate(self) -> None: super().generate() if self.get(self.swd_swo_pin) != 'NC': diff --git a/edg/abstract_parts/LevelShifter.py b/edg/abstract_parts/LevelShifter.py index d762a82e3..164f5fe11 100644 --- a/edg/abstract_parts/LevelShifter.py +++ b/edg/abstract_parts/LevelShifter.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import * from .AbstractResistor import PullupResistor @@ -32,6 +34,7 @@ def __init__(self, lv_res: RangeLike = 4.7*kOhm(tol=0.05), hv_res: RangeLike = 4 self.src_hint = self.ArgParameter(src_hint) self.generator_param(self.lv_res, self.hv_res, self.src_hint) + @override def generate(self) -> None: super().generate() diff --git a/edg/abstract_parts/MergedBlocks.py b/edg/abstract_parts/MergedBlocks.py index f4cdddf60..1364d02f4 100644 --- a/edg/abstract_parts/MergedBlocks.py +++ b/edg/abstract_parts/MergedBlocks.py @@ -1,5 +1,7 @@ from typing import List, cast, Dict +from typing_extensions import override + from ..electronics_model import * from .Categories import * @@ -15,6 +17,7 @@ def __init__(self) -> None: )) self.generator_param(self.pwr_ins.requested()) + @override def generate(self) -> None: super().generate() self.pwr_ins.defined() @@ -45,6 +48,7 @@ def __init__(self) -> None: )) self.generator_param(self.ins.requested()) + @override def generate(self) -> None: super().generate() self.ins.defined() @@ -69,6 +73,7 @@ def connected_from(self, *ins: Port[DigitalLink]) -> 'MergedDigitalSource': class MergedAnalogSource(KiCadImportableBlock, DummyDevice, NetBlock, GeneratorBlock): + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name.startswith('edg_importable:Merge') # can be any merge count = int(symbol_name.removeprefix('edg_importable:Merge')) @@ -86,6 +91,7 @@ def __init__(self) -> None: self.inputs = self.Port(Vector(AnalogSink.empty())) self.generator_param(self.inputs.requested()) + @override def generate(self) -> None: super().generate() self.inputs.defined() @@ -114,6 +120,7 @@ def __init__(self) -> None: self.out = self.Port(SpiController.empty()) self.generator_param(self.ins.requested()) + @override def generate(self) -> None: super().generate() self.sck_merge = self.Block(MergedDigitalSource()) diff --git a/edg/abstract_parts/OpampCircuits.py b/edg/abstract_parts/OpampCircuits.py index 3e899f7c8..938e5955e 100644 --- a/edg/abstract_parts/OpampCircuits.py +++ b/edg/abstract_parts/OpampCircuits.py @@ -1,6 +1,8 @@ from math import ceil, log10 from typing import List, Tuple, Dict, Mapping +from typing_extensions import override + from ..electronics_model import * from .AbstractResistor import Resistor from .AbstractCapacitor import Capacitor @@ -13,6 +15,7 @@ class OpampFollower(OpampApplication, KiCadSchematicBlock, KiCadImportableBlock): """Opamp follower circuit, outputs the same signal as the input (but probably stronger).""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'edg_importable:Follower' return { @@ -27,6 +30,7 @@ def __init__(self) -> None: self.input = self.Port(AnalogSink.empty(), [Input]) self.output = self.Port(AnalogSource.empty(), [Output]) + @override def contents(self) -> None: super().contents() @@ -42,6 +46,7 @@ def __init__(self, amplification: Range, parallel_impedance: Range): self.parallel_impedance = parallel_impedance # parallel impedance into the opamp negative pin @staticmethod + @override def from_resistors(r1_range: Range, r2_range: Range) -> 'AmplifierValues': """r2 is the low-side resistor (Vin- to GND) and r1 is the high-side resistor (Vin- to Vout).""" return AmplifierValues( @@ -49,10 +54,12 @@ def from_resistors(r1_range: Range, r2_range: Range) -> 'AmplifierValues': 1 / (1 / r1_range + 1 / r2_range) ) + @override def initial_test_decades(self) -> Tuple[int, int]: decade = ceil(log10(self.parallel_impedance.center())) return decade, decade + @override def distance_to(self, spec: 'AmplifierValues') -> List[float]: if self.amplification in spec.amplification and self.parallel_impedance in spec.parallel_impedance: return [] @@ -62,6 +69,7 @@ def distance_to(self, spec: 'AmplifierValues') -> List[float]: abs(self.parallel_impedance.center() - spec.parallel_impedance.center()) ] + @override def intersects(self, spec: 'AmplifierValues') -> bool: return self.amplification.intersects(spec.amplification) and \ self.parallel_impedance.intersects(spec.parallel_impedance) @@ -76,6 +84,7 @@ class Amplifier(OpampApplication, KiCadSchematicBlock, KiCadImportableBlock, Gen The input and output impedances given are a bit more complex, so this simplifies it to the opamp's specified pin impedances - TODO: is this correct(ish)? """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: mapping: Dict[str, Dict[str, BasePort]] = { 'Simulation_SPICE:OPAMP': { @@ -106,6 +115,7 @@ def __init__(self, amplification: RangeLike, impedance: RangeLike = (10, 100)*kO self.actual_amplification = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -114,6 +124,7 @@ def contents(self) -> None: " of spec: ", DescriptionString.FormatUnits(self.amplification, "") ) + @override def generate(self) -> None: super().generate() @@ -164,6 +175,7 @@ def __init__(self, ratio: Range, input_impedance: Range): self.input_impedance = input_impedance # resistance of the input resistor @staticmethod + @override def from_resistors(r1_range: Range, r2_range: Range) -> 'DifferentialValues': """r1 is the input side resistance and r2 is the feedback or ground resistor.""" return DifferentialValues( @@ -171,11 +183,13 @@ def from_resistors(r1_range: Range, r2_range: Range) -> 'DifferentialValues': r1_range ) + @override def initial_test_decades(self) -> Tuple[int, int]: r1_decade = ceil(log10(self.input_impedance.center())) r2_decade = ceil(log10((self.input_impedance * self.ratio).center())) return r1_decade, r2_decade + @override def distance_to(self, spec: 'DifferentialValues') -> List[float]: if self.ratio in spec.ratio and self.input_impedance in spec.input_impedance: return [] @@ -185,6 +199,7 @@ def distance_to(self, spec: 'DifferentialValues') -> List[float]: abs(self.input_impedance.center() - spec.input_impedance.center()) ] + @override def intersects(self, spec: 'DifferentialValues') -> bool: return self.ratio.intersects(spec.ratio) and \ self.input_impedance.intersects(spec.input_impedance) @@ -206,6 +221,7 @@ class DifferentialAmplifier(OpampApplication, KiCadSchematicBlock, KiCadImportab ratio specifies Rf/R1, the amplification ratio. """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: mapping: Dict[str, Dict[str, BasePort]] = { 'Simulation_SPICE:OPAMP': { # reference pin not supported @@ -241,6 +257,7 @@ def __init__(self, ratio: RangeLike, input_impedance: RangeLike, *, self.actual_ratio = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -249,6 +266,7 @@ def contents(self) -> None: " of spec: ", DescriptionString.FormatUnits(self.ratio, "") ) + @override def generate(self) -> None: super().generate() @@ -321,6 +339,7 @@ class IntegratorInverting(OpampApplication, KiCadSchematicBlock, KiCadImportable Series is lower and tolerance is higher because there's a cap involved TODO - separate series for cap, and series and tolerance by decade? """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: mapping: Dict[str, Dict[str, BasePort]] = { 'Simulation_SPICE:OPAMP': { @@ -349,6 +368,7 @@ def __init__(self, factor: RangeLike, capacitance: RangeLike, *, self.actual_factor = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/OpampCurrentSensor.py b/edg/abstract_parts/OpampCurrentSensor.py index 566dd1f51..fd2f8c576 100644 --- a/edg/abstract_parts/OpampCurrentSensor.py +++ b/edg/abstract_parts/OpampCurrentSensor.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..electronics_model import * from .Categories import CurrentSensor from .DummyDevices import ForcedAnalogSignal @@ -34,6 +36,7 @@ def __init__(self, resistance: RangeLike, ratio: RangeLike, input_impedance: Ran self.out = self.Port(AnalogSource.empty()) + @override def contents(self) -> None: self.connect(self.amp.input_positive, self.sense.sense_in) self.connect(self.amp.input_negative, self.sense.sense_out) @@ -43,6 +46,7 @@ def contents(self) -> None: self.connect(self.amp.output, self.force_signal.signal_in) self.connect(self.force_signal.signal_out, self.out) + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, Port]: assert symbol_name == 'edg_importable:OpampCurrentSensor' return {'+': self.pwr_in, '-': self.pwr_out, 'R': self.ref, '3': self.out, diff --git a/edg/abstract_parts/PartsTable.py b/edg/abstract_parts/PartsTable.py index ecc17874a..8bf4b5829 100644 --- a/edg/abstract_parts/PartsTable.py +++ b/edg/abstract_parts/PartsTable.py @@ -5,13 +5,14 @@ from typing import Generic, Type, overload, Union, Callable, List, Dict, Any, KeysView, Optional, \ cast, Tuple, Sequence, Protocol -from typing_extensions import ParamSpec, TypeVar +from typing_extensions import ParamSpec, TypeVar, override from ..core.Range import Range # from https://stackoverflow.com/questions/47965083/comparable-types-with-mypy class Comparable(Protocol): + @override def __eq__(self, other: Any) -> bool: ... def __lt__(self, other: Any) -> bool: ... diff --git a/edg/abstract_parts/PartsTablePart.py b/edg/abstract_parts/PartsTablePart.py index 7a0c117c0..256d1fbe2 100644 --- a/edg/abstract_parts/PartsTablePart.py +++ b/edg/abstract_parts/PartsTablePart.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import Optional, Union, Any, ClassVar, Type, Protocol +from typing_extensions import override + from ..electronics_model import * from .PartsTable import PartsTable, PartsTableColumn, PartsTableRow from .StandardFootprint import HasStandardFootprint @@ -75,6 +77,7 @@ def _row_generate(self, row: PartsTableRow) -> None: If there is no matching row, this is not called.""" self.assign(self.actual_part, row[self.PART_NUMBER_COL]) + @override def generate(self) -> None: matching_table = self._get_table().filter(lambda row: self._row_filter(row)) postprocessed_table = self._table_postprocess(matching_table) @@ -104,6 +107,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.footprint_spec) + @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]) @@ -113,6 +117,7 @@ def _row_filter(self, row: PartsTableRow) -> bool: class PartsTableSelectorFootprint(PartsTableFootprintFilter, FootprintBlock, HasStandardFootprint): """PartsTableFootprintFilter, but also with footprint creation. Must define a standard pinning. """ + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.footprint( diff --git a/edg/abstract_parts/PassiveConnector.py b/edg/abstract_parts/PassiveConnector.py index 5f1a94e03..069cd00e9 100644 --- a/edg/abstract_parts/PassiveConnector.py +++ b/edg/abstract_parts/PassiveConnector.py @@ -1,4 +1,7 @@ from typing import Tuple, Iterable + +from typing_extensions import override + from ..abstract_parts import * @@ -26,6 +29,7 @@ class FootprintPassiveConnector(PassiveConnector, GeneratorBlock, FootprintBlock """PassiveConnector that is a footprint and provides some base functionality for generation.""" allowed_pins: Iterable[int] + @override def contents(self) -> None: super().contents() self.generator_param(self.length, self.pins.requested()) @@ -35,6 +39,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: Implementing classes must implement this method.""" raise NotImplementedError + @override def generate(self) -> None: super().generate() max_pin_index = 0 diff --git a/edg/abstract_parts/PassiveFilters.py b/edg/abstract_parts/PassiveFilters.py index 1acb7a96f..fa45e24ba 100644 --- a/edg/abstract_parts/PassiveFilters.py +++ b/edg/abstract_parts/PassiveFilters.py @@ -1,6 +1,8 @@ from math import pi from typing import Optional, cast, Mapping +from typing_extensions import override + from ..electronics_model import * from .AbstractResistor import Resistor from .AbstractCapacitor import Capacitor @@ -19,6 +21,7 @@ def __init__(self, impedance: RangeLike, cutoff_freq: RangeLike, voltage: RangeL self.cutoff_freq = self.ArgParameter(cutoff_freq) self.voltage = self.ArgParameter(voltage) + @override def contents(self) -> None: super().contents() @@ -116,6 +119,7 @@ def __init__(self, impedance: RangeLike, cutoff_freq: RangeLike): self.generator_param(self.output.requested()) + @override def generate(self) -> None: super().generate() self.elts = ElementDict[DigitalLowPassRc]() @@ -156,6 +160,7 @@ def __init__(self, impedance: RangeLike, cutoff_freq: RangeLike): class LowPassAnalogDifferentialRc(AnalogFilter, KiCadImportableBlock): """Analog-typed low-pass differential RC filter, with cutoff frequency specified at the -3dB (~70%) point. Impedance is the single-ended resistor value.""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'edg_importable:DifferentialRC' return { @@ -172,6 +177,7 @@ def __init__(self, impedance: RangeLike, cutoff_freq: RangeLike): self.impedance = self.ArgParameter(impedance) self.cutoff_freq = self.ArgParameter(cutoff_freq) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/PinMappable.py b/edg/abstract_parts/PinMappable.py index 0fb59c226..9a0b83e1c 100644 --- a/edg/abstract_parts/PinMappable.py +++ b/edg/abstract_parts/PinMappable.py @@ -1,6 +1,8 @@ import itertools from typing import List, Type, Tuple, Optional, Union, NamedTuple, Callable, Dict, Set, Any, Mapping +from typing_extensions import override + from ..electronics_model import * @@ -55,9 +57,11 @@ def __init__(self, pin: str, name_models: Dict[str, CircuitPort]): self.pin = pin self.name_models = name_models + @override def __repr__(self) -> str: return f"PinResource({self.pin}, {self.name_models})" + @override def __eq__(self, other: Any) -> bool: # TODO avoid using is if we can compare port model equality return isinstance(other, PinResource) and self.pin == other.pin and self.name_models is other.name_models @@ -77,9 +81,11 @@ def __init__(self, name: str, port_model: Bundle, inner_allowed_pins: Dict[str, self.port_model = port_model self.inner_allowed_pins = inner_allowed_pins + @override def __repr__(self) -> str: return f"PeripheralFixedPin({self.name}, {self.port_model.__class__.__name__} {self.inner_allowed_pins})" + @override def __eq__(self, other: Any) -> bool: # TODO avoid using is if we can compare port model equality return isinstance(other, PeripheralFixedPin) and self.name == other.name and \ @@ -95,9 +101,11 @@ def __init__(self, name: str, port_model: Bundle): self.name = name self.port_model = port_model + @override def __repr__(self) -> str: return f"PeripheralAnyResource({self.name}, {self.port_model.__class__.__name__})" + @override def __eq__(self, other: Any) -> bool: # TODO avoid using is if we can compare port model equality return isinstance(other, PeripheralAnyResource) and self.name == other.name and \ @@ -115,9 +123,11 @@ def __init__(self, name: str, port_model: Bundle, inner_allowed_names: Dict[str, self.port_model = port_model self.inner_allowed_names = inner_allowed_names + @override def __repr__(self) -> str: return f"PeripheralFixedResource({self.name}, {self.port_model.__class__.__name__}, {self.inner_allowed_names})" + @override def __eq__(self, other: Any) -> bool: # TODO avoid using is if we can compare port model equality return isinstance(other, PeripheralFixedResource) and self.name == other.name and \ @@ -132,6 +142,7 @@ class AllocatedResource(NamedTuple): pin: Union[str, None, Dict[str, Tuple[str, Optional[str]]]] # pin number if port is leaf, or # recursive definition for bundles (pin, resource) + @override def __eq__(self, other: Any) -> bool: # TODO better port model check, perhaps by initializer return self.port_model is other.port_model and self.name == other.name and \ diff --git a/edg/abstract_parts/PowerCircuits.py b/edg/abstract_parts/PowerCircuits.py index 4795ed1f0..9a03324be 100644 --- a/edg/abstract_parts/PowerCircuits.py +++ b/edg/abstract_parts/PowerCircuits.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .Resettable import Resettable from .AbstractResistor import Resistor, SeriesPowerResistor @@ -54,6 +56,7 @@ def __init__(self, frequency: RangeLike, fet_rds: RangeLike = (0, 1)*Ohm, self.actual_current_limits = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() self.driver = self.Block(HalfBridgeDriver(has_boot_diode=True)) @@ -107,6 +110,7 @@ def contents(self) -> None: class FetHalfBridgeIndependent(FetHalfBridge, HalfBridgeIndependent): + @override def contents(self) -> None: super().contents() driver_mixin = self.driver.with_mixin(HalfBridgeDriverIndependent()) @@ -119,6 +123,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.reset.is_connected()) + @override def generate(self) -> None: super().generate() self.connect(self.pwm_ctl, self.driver.with_mixin(HalfBridgeDriverPwm()).pwm_in) @@ -178,6 +183,7 @@ def __init__(self, *, cgd: RangeLike = 10*nFarad(tol=0.5), target_ramp: RangeLik self.max_rds = self.ArgParameter(max_rds) self._cdiv_vgs_factor = self.ArgParameter(_cdiv_vgs_factor) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/ResistiveDivider.py b/edg/abstract_parts/ResistiveDivider.py index affd2d5fd..d38b0388d 100644 --- a/edg/abstract_parts/ResistiveDivider.py +++ b/edg/abstract_parts/ResistiveDivider.py @@ -3,6 +3,8 @@ from math import log10, ceil from typing import List, Tuple, Mapping +from typing_extensions import override + from ..electronics_model import * from . import Analog, Resistor from .Categories import InternalSubcircuit @@ -27,6 +29,7 @@ def __init__(self, ratio: Range, parallel_impedance: Range): self.parallel_impedance = parallel_impedance # parallel impedance into the opamp negative pin @staticmethod + @override def from_resistors(r1_range: Range, r2_range: Range) -> 'DividerValues': """This uses a slight rewriting of terms to avoid duplication of terms and not double-count tolerances: ratio = R2 / (R1 + R2) => divide through by R2 / R2 @@ -37,10 +40,12 @@ def from_resistors(r1_range: Range, r2_range: Range) -> 'DividerValues': 1 / (1 / r1_range + 1 / r2_range) ) + @override def initial_test_decades(self) -> Tuple[int, int]: decade = ceil(log10(self.parallel_impedance.center())) return decade, decade + @override def distance_to(self, spec: 'DividerValues') -> List[float]: if self.ratio in spec.ratio and self.parallel_impedance in spec.parallel_impedance: return [] @@ -50,6 +55,7 @@ def distance_to(self, spec: 'DividerValues') -> List[float]: abs(self.parallel_impedance.center() - spec.parallel_impedance.center()) ] + @override def intersects(self, spec: 'DividerValues') -> bool: return self.ratio.intersects(spec.ratio) and \ self.parallel_impedance.intersects(spec.parallel_impedance) @@ -57,6 +63,7 @@ def intersects(self, spec: 'DividerValues') -> bool: class ResistiveDivider(InternalSubcircuit, KiCadImportableBlock, GeneratorBlock): """Abstract, untyped (Passive) resistive divider, that takes in a ratio and parallel impedance spec.""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'Device:VoltageDivider' return {'1': self.top, '2': self.center, '3': self.bottom} @@ -92,6 +99,7 @@ def __init__(self, ratio: RangeLike, impedance: RangeLike, *, self.center = self.Port(Passive.empty()) self.bottom = self.Port(Passive.empty()) + @override def contents(self) -> None: super().contents() @@ -102,6 +110,7 @@ def contents(self) -> None: " of spec: ", DescriptionString.FormatUnits(self.impedance, "Ω")) + @override def generate(self) -> None: """Generates a resistive divider meeting the required specifications, with the lowest E-series resistors possible. """ @@ -140,6 +149,7 @@ class BaseVoltageDivider(KiCadImportableBlock): The actual output voltage is defined as a ratio of the input voltage, and the divider is specified by ratio and impedance. Subclasses should define the ratio and impedance spec.""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'Device:VoltageDivider' return {'1': self.input, '2': self.output, '3': self.gnd} @@ -206,6 +216,7 @@ def __init__(self, *, output_voltage: RangeLike, impedance: RangeLike, self.assumed_input_voltage = self.ArgParameter(assumed_input_voltage) self.actual_input_voltage = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -221,6 +232,7 @@ def contents(self) -> None: class SignalDivider(Analog, KiCadImportableBlock, Block): """Specialization of ResistiveDivider for Analog signals""" + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'Device:VoltageDivider' return {'1': self.input, '2': self.output, '3': self.gnd} diff --git a/edg/abstract_parts/RfNetworks.py b/edg/abstract_parts/RfNetworks.py index c6bdf8ca9..7c7a38b12 100644 --- a/edg/abstract_parts/RfNetworks.py +++ b/edg/abstract_parts/RfNetworks.py @@ -1,6 +1,8 @@ from math import pi, sqrt from typing import Tuple, Any +from typing_extensions import override + from ..electronics_model import * from .AbstractCapacitor import Capacitor from .AbstractInductor import Inductor @@ -17,6 +19,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.discrete_rf_warning = self.Parameter(BoolExpr(False)) + @override def contents(self) -> None: super().contents() self.require(self.discrete_rf_warning == False, "warning: discrete RF circuit, design may be tricky") @@ -94,6 +97,7 @@ def __init__(self, frequency: FloatLike, src_resistance: FloatLike, src_reactanc self.generator_param(self.frequency, self.src_resistance, self.src_reactance, self.load_resistance, self.tolerance) + @override def generate(self) -> None: super().generate() @@ -190,6 +194,7 @@ def __init__(self, frequency: RangeLike, src_resistance: FloatLike, src_reactanc self.generator_param(self.frequency, self.src_resistance, self.src_reactance, self.load_resistance, self.tolerance) + @override def generate(self) -> None: super().generate() diff --git a/edg/abstract_parts/SelectorArea.py b/edg/abstract_parts/SelectorArea.py index 6b0da220e..97e11263c 100644 --- a/edg/abstract_parts/SelectorArea.py +++ b/edg/abstract_parts/SelectorArea.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..electronics_model import * from .PartsTable import PartsTableRow from .PartsTablePart import PartsTableFootprintFilter, PartsTablePart @@ -36,6 +38,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.footprint_area) + @override def _row_filter(self, row: PartsTableRow) -> bool: return super()._row_filter(row) and \ (Range.exact(FootprintDataTable.area_of(row[self.KICAD_FOOTPRINT])).fuzzy_in(self.get(self.footprint_area))) diff --git a/edg/abstract_parts/TouchPad.py b/edg/abstract_parts/TouchPad.py index a2709bb10..f7cac2adb 100644 --- a/edg/abstract_parts/TouchPad.py +++ b/edg/abstract_parts/TouchPad.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import * from .Categories import HumanInterface @@ -8,6 +10,7 @@ def __init__(self, touch_footprint: StringLike): self.pad = self.Port(TouchPadPort(), [Input]) self.touch_footprint = self.ArgParameter(touch_footprint) + @override def contents(self) -> None: super().contents() self.footprint('U', self.touch_footprint, {'1': self.pad}) diff --git a/edg/abstract_parts/UsbBitBang.py b/edg/abstract_parts/UsbBitBang.py index ef62fb906..3004b7a6f 100644 --- a/edg/abstract_parts/UsbBitBang.py +++ b/edg/abstract_parts/UsbBitBang.py @@ -1,5 +1,7 @@ from typing import cast +from typing_extensions import override + from ..electronics_model import * from .Categories import * from .AbstractResistor import Resistor @@ -38,6 +40,7 @@ def __init__(self) -> None: self.dm = self.Port(DigitalBidir.empty()) self.dp_pull = self.Port(DigitalSink.empty()) + @override def contents(self) -> None: super().contents() diff --git a/edg/abstract_parts/test_opamp.py b/edg/abstract_parts/test_opamp.py index bee67a609..4128dc4c0 100644 --- a/edg/abstract_parts/test_opamp.py +++ b/edg/abstract_parts/test_opamp.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .DummyDevices import DummyVoltageSource, DummyAnalogSink from .AbstractOpamp import Opamp @@ -13,6 +15,7 @@ def __init__(self) -> None: class TestOpamp(Opamp): + @override def contents(self) -> None: super().contents() self.pwr.init_from(VoltageSink()) @@ -23,6 +26,7 @@ def contents(self) -> None: class TestResistor(Resistor): + @override def contents(self) -> None: super().contents() self.assign(self.actual_resistance, self.resistance) diff --git a/edg/abstract_parts/test_parts_table.py b/edg/abstract_parts/test_parts_table.py index 1aecec500..2c56bbf08 100644 --- a/edg/abstract_parts/test_parts_table.py +++ b/edg/abstract_parts/test_parts_table.py @@ -1,6 +1,8 @@ import os import unittest +from typing_extensions import override + from .PartsTable import * @@ -8,6 +10,7 @@ class PartsTableTest(unittest.TestCase): INT_COLUMN = PartsTableColumn(int) # TODO don't test using internal variables + @override def setUp(self) -> None: path = os.path.join(os.path.dirname(__file__), 'resources', 'test_table.csv') with open(path, newline='') as csvfile: diff --git a/edg/abstract_parts/test_power_circuits.py b/edg/abstract_parts/test_power_circuits.py index 4d8f1bc16..7bccbc55f 100644 --- a/edg/abstract_parts/test_power_circuits.py +++ b/edg/abstract_parts/test_power_circuits.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .DummyDevices import DummyVoltageSource from .PowerCircuits import RampLimiter @@ -15,6 +17,7 @@ def __init__(self) -> None: (self.dummyctl, ), _ = self.chain(self.dut.control, self.Block(DummyDigitalSource(voltage_out=3.3*Volt(tol=0)))) (self.dummygnd, ), _ = self.chain(self.dut.gnd, self.Block(DummyGround())) + @override def refinements(self) -> Refinements: return Refinements( class_refinements=[ diff --git a/edg/abstract_parts/test_switching_converters.py b/edg/abstract_parts/test_switching_converters.py index 15a71910f..9a193c4ce 100644 --- a/edg/abstract_parts/test_switching_converters.py +++ b/edg/abstract_parts/test_switching_converters.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .AbstractPowerConverters import BuckConverterPowerPath, BoostConverterPowerPath from ..electronics_model import * from .AbstractInductor import Inductor @@ -93,6 +95,7 @@ def test_boost_converter_example(self) -> None: class TestCapacitor(Capacitor): + @override def contents(self) -> None: super().contents() self.assign(self.actual_capacitance, self.capacitance) @@ -100,6 +103,7 @@ def contents(self) -> None: class TestInductor(Inductor): + @override def contents(self) -> None: super().contents() self.assign(self.actual_inductance, self.inductance) @@ -126,6 +130,7 @@ def __init__(self) -> None: self.require(self.dut.pwr_out.current_limits.contains(Range(0.0, 1.260))) self.require(self.dut.switch.current_draw.contains(Range(0.067, 0.832))) + @override def refinements(self) -> Refinements: return Refinements( class_refinements=[ @@ -157,6 +162,7 @@ def __init__(self) -> None: self.require(self.dut.pwr_in.current_draw.contains(Range(0.334, 2.185))) self.require(self.dut.switch.current_limits.contains(Range(0.0, 0.280))) + @override def refinements(self) -> Refinements: return Refinements( class_refinements=[ diff --git a/edg/core/Array.py b/edg/core/Array.py index 9a67173d0..88179bc21 100644 --- a/edg/core/Array.py +++ b/edg/core/Array.py @@ -6,7 +6,7 @@ ItemsView, Callable, Dict from deprecated import deprecated -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .ArrayExpr import ArrayExpr, ArrayRangeExpr, ArrayStringExpr, ArrayBoolExpr, ArrayFloatExpr, ArrayIntExpr from .Binding import LengthBinding, AllocatedBinding @@ -24,9 +24,11 @@ def __init__(self, container: BaseVector, elt: ConstraintExpr): self.container = container self.elt = elt + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.container] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: contained_map = self.container._get_elt_sample()._create_ref_map(edgir.LocalPath()) @@ -41,9 +43,11 @@ def __init__(self, elts: ConstraintExpr): super().__init__() self.elts = elts + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.elts] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.unary_set.op = edgir.UnarySetExpr.Op.FLATTEN @@ -78,18 +82,23 @@ def __init__(self, base: BaseVector, target: VectorType) -> None: assert base._parent is not None # to satisfy type checker, though kind of duplicates _is_bound self._bind_in_place(base._parent) + @override def _type_of(self) -> Hashable: return (self.target._type_of(),) + @override def _get_elt_sample(self) -> BasePort: return self.target + @override def _instance_to_proto(self) -> edgir.PortLike: raise RuntimeError() # this doesn't generate into a library element + @override def _def_to_proto(self) -> edgir.PortTypes: raise RuntimeError() # this doesn't generate into a library element + @override def _get_initializers(self, path_prefix: List[str]) -> List[Tuple[ConstraintExpr, List[str], ConstraintExpr]]: raise RuntimeError() # should never happen @@ -115,6 +124,7 @@ def __init__(self, tpe: VectorType) -> None: self._length = IntExpr()._bind(LengthBinding(self)) self._requested = ArrayStringExpr()._bind(AllocatedBinding(self)) + @override def __repr__(self) -> str: # TODO dedup w/ Core.__repr__ # but this can't depend on get_def_name since that crashes @@ -134,6 +144,7 @@ def items(self) -> ItemsView[str, VectorType]: return self._elts.items() # unlike most other LibraryElement types, the names are stored in _elts and _allocates + @override def _name_of_child(self, subelt: Any, context: Any, allow_unknown: bool = False) -> str: from .HierarchyBlock import Block block_parent = self._block_parent() @@ -164,12 +175,15 @@ def _name_of_child(self, subelt: Any, context: Any, allow_unknown: bool = False) else: raise ValueError(f"unknown context of array") + @override def _get_elt_sample(self) -> BasePort: return self._elt_sample + @override def _get_def_name(self) -> str: raise RuntimeError() # this doesn't generate into a library element + @override def _instance_to_proto(self) -> edgir.PortLike: pb = edgir.PortLike() pb.array.self_class.target.name = self._elt_sample._get_def_name() @@ -179,9 +193,11 @@ def _instance_to_proto(self) -> edgir.PortLike: edgir.add_pair(pb.array.ports.ports, name).CopyFrom(elt._instance_to_proto()) return pb + @override def _def_to_proto(self) -> edgir.PortTypes: raise RuntimeError() # this doesn't generate into a library element + @override def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) -> None: super()._build_ref_map(ref_map, prefix) ref_map[self._length] = edgir.localpath_concat(prefix, edgir.LENGTH) @@ -192,6 +208,7 @@ def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) - for suggested_name, request in self._requests: request._build_ref_map(ref_map, edgir.localpath_concat(prefix, edgir.Allocate(suggested_name))) + @override def _get_initializers(self, path_prefix: List[str]) -> List[Tuple[ConstraintExpr, List[str], ConstraintExpr]]: if self._elts is not None: return list(itertools.chain(*[ @@ -283,6 +300,7 @@ def allocated(self) -> ArrayStringExpr: def requested(self) -> ArrayStringExpr: return self._requested + @override def _type_of(self) -> Hashable: return (self._elt_sample._type_of(),) diff --git a/edg/core/ArrayExpr.py b/edg/core/ArrayExpr.py index 87eefac9a..d51d4855e 100644 --- a/edg/core/ArrayExpr.py +++ b/edg/core/ArrayExpr.py @@ -2,7 +2,7 @@ from typing import Generic, Any, Type, Optional, Union, Iterable, Sequence, List -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .Binding import EqOp, ArrayBinding, UnarySetOpBinding, BinarySetOpBinding from .ConstraintExpr import ConstraintExpr, IntLike, FloatExpr, FloatLike, RangeExpr, RangeLike, \ @@ -18,9 +18,11 @@ class SampleElementBinding(Binding): def __init__(self) -> None: super().__init__() + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: # element should be returned by the containing ConstraintExpr return [] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: raise ValueError # can't be used directly @@ -40,11 +42,13 @@ class ArrayExpr(ConstraintExpr[ArrayWrappedType, ArrayCastableType], _elt_type: Type[ArrayEltType] @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> ArrayWrappedType: assert pb.HasField('array') return [cls._elt_type._from_lit(sub_pb) for sub_pb in pb.array.elts] # type: ignore @classmethod + @override def _to_expr_type(cls: Type[SelfType], input: ArrayCastableType) -> SelfType: if isinstance(input, cls): assert input._is_bound() @@ -56,6 +60,7 @@ def _to_expr_type(cls: Type[SelfType], input: ArrayCastableType) -> SelfType: raise TypeError(f"arg to {cls.__name__} must be ArrayCastableType, got {input} of type {type(input)}") @classmethod + @override def _decl_to_proto(cls) -> edgir.ValInit: pb = edgir.ValInit() pb.array.CopyFrom(cls._elt_type._decl_to_proto()) diff --git a/edg/core/Binding.py b/edg/core/Binding.py index 1abff5cfc..d3e53927a 100644 --- a/edg/core/Binding.py +++ b/edg/core/Binding.py @@ -5,6 +5,8 @@ from itertools import chain from typing import * +from typing_extensions import override + from .. import edgir from .Core import Refable from .IdentityDict import IdentityDict @@ -82,6 +84,7 @@ def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: ... ParamParentTypes = Union['Port', 'BaseBlock'] # creates a circular module dependency on Core class ParamBinding(Binding): """Binding that indicates this is a parameter""" + @override def __repr__(self) -> str: return f"Param({self.parent})" @@ -89,9 +92,11 @@ def __init__(self, parent: ParamParentTypes): super().__init__() self.parent = parent + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: # element should be returned by the containing ConstraintExpr return [] + @override def is_bound(self) -> bool: # TODO clarify binding logic from .Ports import Port @@ -100,6 +105,7 @@ def is_bound(self) -> bool: else: return True + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ref.CopyFrom(ref_map[expr]) @@ -116,11 +122,13 @@ def __init__(self, parent: ParamParentTypes, value: Optional[Any] = None): class LiteralBinding(Binding): """Base class for literal bindings""" + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [] class BoolLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.value})" @@ -128,6 +136,7 @@ def __init__(self, value: bool): super().__init__() self.value = value + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.boolean.val = self.value @@ -135,12 +144,14 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class IntLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.value})" def __init__(self, value: int): self.value = value + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.integer.val = self.value @@ -148,12 +159,14 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class FloatLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.value})" def __init__(self, value: Union[float, int]): self.value: float = float(value) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.floating.val = self.value @@ -161,12 +174,14 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class RangeLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.value})" def __init__(self, value: Range): self.value = value + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.range.minimum.floating.val = self.value.lower @@ -175,6 +190,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class StringLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.value})" @@ -182,6 +198,7 @@ def __init__(self, value: str): super().__init__() self.value = value + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.text.val = self.value @@ -189,6 +206,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class ArrayLiteralBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Lit({self.values})" @@ -196,6 +214,7 @@ def __init__(self, values: Sequence[LiteralBinding]): super().__init__() self.values = values + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.literal.array.SetInParent() @@ -207,6 +226,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class RangeBuilderBinding(Binding): + @override def __repr__(self) -> str: return f"RangeBuilder({self.lower}, {self.upper})" @@ -215,9 +235,11 @@ def __init__(self, lower: FloatExpr, upper: FloatExpr): self.lower = lower self.upper = upper + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.lower._get_exprs(), self.lower._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.binary.op = edgir.BinaryExpr.RANGE @@ -227,6 +249,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class ArrayBinding(LiteralBinding): + @override def __repr__(self) -> str: return f"Array({self.values})" @@ -234,6 +257,7 @@ def __init__(self, values: Sequence[ConstraintExpr]): super().__init__() self.values = values + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.array.SetInParent() @@ -243,6 +267,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class UnaryOpBinding(Binding): + @override def __repr__(self) -> str: return f"UnaryOp({self.op}, ...)" @@ -263,9 +288,11 @@ def __init__(self, self.src = src self.op = op + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.src._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() @@ -274,6 +301,7 @@ def expr_to_proto(self, expr: ConstraintExpr, return pb class UnarySetOpBinding(Binding): + @override def __repr__(self) -> str: return f"UnarySetOp({self.op}, ...)" @@ -299,9 +327,11 @@ def __init__(self, self.src = src self.op = op + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.src._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() @@ -310,6 +340,7 @@ def expr_to_proto(self, expr: ConstraintExpr, return pb class BinaryOpBinding(Binding): + @override def __repr__(self) -> str: return f"BinaryOp({self.op}, ...)" @@ -349,9 +380,11 @@ def __init__(self, self.rhs = rhs self.op = op + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.lhs._get_exprs(), self.rhs._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.binary.op = self.op_map[self.op] @@ -360,6 +393,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed return pb class BinarySetOpBinding(Binding): + @override def __repr__(self) -> str: return f"BinaryOp({self.op}, ...)" @@ -378,9 +412,11 @@ def __init__(self, self.rhs = rhs self.op = op + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.lhset._get_exprs(), self.rhs._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.binary_set.op = self.op_map[self.op] @@ -390,6 +426,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class IfThenElseBinding(Binding): + @override def __repr__(self) -> str: return f"IfThenElse(...)" @@ -399,9 +436,11 @@ def __init__(self, cond: BoolExpr, then_val: ConstraintExpr, else_val: Constrain self.then_val = then_val self.else_val = else_val + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return chain(self.cond._get_exprs(), self.then_val._get_exprs(), self.else_val._get_exprs()) + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ifThenElse.cond.CopyFrom(self.cond._expr_to_proto(ref_map)) @@ -411,6 +450,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class IsConnectedBinding(Binding): + @override def __repr__(self) -> str: return f"IsConnected" @@ -418,9 +458,11 @@ def __init__(self, src: Port): super().__init__() self.src = src + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.src] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ref.CopyFrom(ref_map[self.src]) @@ -428,6 +470,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed return pb class NameBinding(Binding): + @override def __repr__(self) -> str: return f"Name" @@ -435,9 +478,11 @@ def __init__(self, src: Union[BaseBlock, BasePort]): super().__init__() self.src = src + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ref.CopyFrom(ref_map[self.src]) @@ -446,6 +491,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class LengthBinding(Binding): + @override def __repr__(self) -> str: return f"Length" @@ -453,9 +499,11 @@ def __init__(self, src: BaseVector): super().__init__() self.src = src + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.src] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ref.CopyFrom(ref_map[self.src]) @@ -464,6 +512,7 @@ def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> ed class AllocatedBinding(Binding): + @override def __repr__(self) -> str: return f"Allocated" @@ -471,9 +520,11 @@ def __init__(self, src: BaseVector): super().__init__() self.src = src + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.src] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: pb = edgir.ValueExpr() pb.ref.CopyFrom(ref_map[self.src]) @@ -490,6 +541,7 @@ def make_assign(target: ConstraintExpr, value: ConstraintExpr, ref_map: Refable. pb.assign.src.CopyFrom(value._expr_to_proto(ref_map)) return pb + @override def __repr__(self) -> str: return f"Assign({self.target}, ...)" @@ -498,8 +550,10 @@ def __init__(self, target: ConstraintExpr, value: ConstraintExpr): self.target = target self.value = value + @override def get_subexprs(self) -> Iterable[Union[ConstraintExpr, BasePort]]: return [self.value] + @override def expr_to_proto(self, expr: ConstraintExpr, ref_map: Refable.RefMapType) -> edgir.ValueExpr: return self.make_assign(self.target, self.value, ref_map) diff --git a/edg/core/BlockInterfaceMixin.py b/edg/core/BlockInterfaceMixin.py index ab7b0da50..4ebb0239b 100644 --- a/edg/core/BlockInterfaceMixin.py +++ b/edg/core/BlockInterfaceMixin.py @@ -1,5 +1,5 @@ from typing import Generic, Type, List, Optional, get_args, get_origin, Tuple, Callable, Any -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .Core import non_library, HasMetadata from .Blocks import AbstractBlockProperty @@ -30,6 +30,7 @@ class BlockInterfaceMixin(Block, Generic[MixinBaseType]): """ BaseType = TypeVar('BaseType', bound=HasMetadata) @classmethod + @override def _get_bases_of(cls, base_type: Type[BaseType]) -> Tuple[List[Type[BaseType]], List[Type[BaseType]]]: ordered_direct_bases, ordered_indirect_bases = super()._get_bases_of(base_type) if cls._is_mixin(): # adds the mixin base defined in MixinBaseType to the list of bases diff --git a/edg/core/Blocks.py b/edg/core/Blocks.py index ad86b7495..d44571e1f 100644 --- a/edg/core/Blocks.py +++ b/edg/core/Blocks.py @@ -6,6 +6,8 @@ from enum import Enum from typing import * +from typing_extensions import override + from .. import edgir from .Array import BaseVector, Vector from .Binding import AssignBinding, NameBinding @@ -22,6 +24,7 @@ class BaseBlockMeta(type): """Adds a hook to set the post-init elaboration state""" + @override def __call__(cls, *args: Any, **kwargs: Any) -> Any: block_context = builder.get_enclosing_block() obj = super().__call__(*args, **kwargs) @@ -232,6 +235,7 @@ def __init__(self, ref: ConstraintExpr, units: str): self.ref = ref self.units = units + @override def set_elt_proto(self, pb: edgir.BlockLikeTypes, ref_map: Refable.RefMapType) -> None: new_phrase = pb.description.add() new_phrase.param.path.CopyFrom(ref_map[self.ref]) @@ -294,7 +298,7 @@ def name(self) -> StringExpr: def contents(self) -> None: pass - @abstractmethod + @override def _def_to_proto(self) -> edgir.BlockLikeTypes: raise NotImplementedError @@ -331,7 +335,7 @@ def _populate_def_proto_block_base(self, pb: edgir.BlockLikeTypes) -> None: pb.self_class.target.name = self._get_def_name() - direct_bases, indirect_bases = self._get_bases_of(BaseBlock) # type: ignore + direct_bases, indirect_bases = self._get_bases_of(BaseBlock) for cls in direct_bases: pb.superclasses.add().target.name = cls._static_def_name() for cls in indirect_bases: @@ -392,6 +396,7 @@ def _populate_def_proto_description(self, pb: edgir.BlockLikeTypes, ref_map: Ref if isinstance(description, DescriptionString): description.add_to_proto(pb, ref_map) + @override def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) -> None: super()._build_ref_map(ref_map, prefix) ref_map[self.name()] = edgir.localpath_concat(prefix, edgir.NAME) diff --git a/edg/core/ConstraintExpr.py b/edg/core/ConstraintExpr.py index 21d86ccd2..59b229ed5 100644 --- a/edg/core/ConstraintExpr.py +++ b/edg/core/ConstraintExpr.py @@ -5,7 +5,7 @@ from deprecated import deprecated from itertools import chain -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .Binding import Binding, ParamBinding, BoolLiteralBinding, IntLiteralBinding, \ FloatLiteralBinding, RangeLiteralBinding, StringLiteralBinding, RangeBuilderBinding, \ @@ -30,6 +30,7 @@ class ConstraintExpr(Refable, Generic[WrappedType, CastableType]): """ _CASTABLE_TYPES: Tuple[Type[CastableType], ...] # for use in ininstance(), excluding self-cls + @override def __repr__(self) -> str: if self.binding is not None and self.initializer is not None: return f"{super().__repr__()}({self.binding})={self.initializer}" @@ -97,6 +98,7 @@ def _expr_to_proto(self, ref_map: Refable.RefMapType) -> edgir.ValueExpr: return self.binding.expr_to_proto(self, ref_map) # for now we define that all constraints can be checked for equivalence + @override def __eq__(self: SelfType, other: ConstraintExprCastable) -> BoolExpr: #type: ignore # TODO: avoid creating excess BoolExpr return BoolExpr()._bind(BinaryOpBinding(self, self._to_expr_type(other), EqOp.eq)) @@ -109,6 +111,7 @@ class BoolExpr(ConstraintExpr[bool, BoolLike]): _CASTABLE_TYPES = (bool, ) @classmethod + @override def _to_expr_type(cls, input: BoolLike) -> BoolExpr: if isinstance(input, BoolExpr): assert input._is_bound() @@ -119,12 +122,14 @@ def _to_expr_type(cls, input: BoolLike) -> BoolExpr: raise ValueError("unexpected type for %s of %s, expected BoolLike" % (input, type(input))) @classmethod + @override def _decl_to_proto(self) -> edgir.ValInit: pb = edgir.ValInit() pb.boolean.CopyFrom(edgir.Empty()) return pb @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> bool: assert pb.HasField('boolean') return pb.boolean.val @@ -194,6 +199,7 @@ class NumLikeExpr(ConstraintExpr[WrappedType, NumLikeCastable], Generic[WrappedT @classmethod @abstractmethod + @override def _to_expr_type(cls: Type[NumLikeSelfType], input: Union[NumLikeSelfType, WrappedType, NumLikeCastable]) -> NumLikeSelfType: """Casts the input from an equivalent-type to the self-type.""" @@ -310,6 +316,7 @@ class IntExpr(NumLikeExpr[int, IntLike]): _CASTABLE_TYPES = (int, ) @classmethod + @override def _to_expr_type(cls, input: IntLike) -> IntExpr: if isinstance(input, IntExpr): assert input._is_bound() @@ -320,12 +327,14 @@ def _to_expr_type(cls, input: IntLike) -> IntExpr: raise TypeError(f"op arg to IntExpr must be IntLike, got {input} of type {type(input)}") @classmethod + @override def _decl_to_proto(cls) -> edgir.ValInit: pb = edgir.ValInit() pb.integer.CopyFrom(edgir.Empty()) return pb @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> int: assert pb.HasField('integer') return pb.integer.val @@ -337,6 +346,7 @@ class FloatExpr(NumLikeExpr[float, Union[FloatLike, IntExpr]]): _CASTABLE_TYPES = (float, int) @classmethod + @override def _to_expr_type(cls, input: Union[FloatLike, IntExpr]) -> FloatExpr: if isinstance(input, FloatExpr): assert input._is_bound() @@ -350,12 +360,14 @@ def _to_expr_type(cls, input: Union[FloatLike, IntExpr]) -> FloatExpr: raise TypeError(f"op arg to FloatExpr must be FloatLike, got {input} of type {type(input)}") @classmethod + @override def _decl_to_proto(cls) -> edgir.ValInit: pb = edgir.ValInit() pb.floating.CopyFrom(edgir.Empty()) return pb @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> float: assert pb.HasField('floating') return pb.floating.val @@ -381,6 +393,7 @@ class RangeExpr(NumLikeExpr[Range, Union[RangeLike, FloatLike, IntExpr]]): EMPTY = Range(float('NaN'), float('NaN')) # special marker to define an empty range, which is subset-eq of any range @classmethod + @override def _to_expr_type(cls, input: Union[RangeLike, FloatLike, IntLike]) -> RangeExpr: if isinstance(input, RangeExpr): assert input._is_bound() @@ -403,12 +416,14 @@ def _to_expr_type(cls, input: Union[RangeLike, FloatLike, IntLike]) -> RangeExpr raise TypeError(f"op arg to RangeExpr must be RangeLike, got {input} of type {type(input)}") @classmethod + @override def _decl_to_proto(cls) -> edgir.ValInit: pb = edgir.ValInit() pb.range.CopyFrom(edgir.Empty()) return pb @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> Range: assert pb.HasField('range') and pb.range.minimum.HasField('floating') and pb.range.maximum.HasField('floating') return Range(pb.range.minimum.floating.val, pb.range.maximum.floating.val) @@ -500,6 +515,7 @@ class StringExpr(ConstraintExpr[str, StringLike]): _CASTABLE_TYPES = (str, ) @classmethod + @override def _to_expr_type(cls, input: StringLike) -> StringExpr: if isinstance(input, StringExpr): assert input._is_bound() @@ -510,12 +526,14 @@ def _to_expr_type(cls, input: StringLike) -> StringExpr: raise ValueError("unexpected type for %s of %s, expected StringLike" % (input, type(input))) @classmethod + @override def _decl_to_proto(cls) -> edgir.ValInit: pb = edgir.ValInit() pb.text.CopyFrom(edgir.Empty()) return pb @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> str: assert pb.HasField('text') return pb.text.val @@ -538,14 +556,17 @@ def __radd__(self, lhs: StringLike) -> StringExpr: class AssignExpr(ConstraintExpr[None, None]): """Assignment expression, should be an internal type""" @classmethod + @override def _to_expr_type(cls, input: Any) -> NoReturn: raise ValueError("can't convert to AssignExpr") @classmethod + @override def _decl_to_proto(self) -> NoReturn: raise ValueError("can't create parameter from AssignExpr") @classmethod + @override def _from_lit(cls, pb: edgir.ValueLit) -> NoReturn: raise ValueError("can't unpack AssignExpr") diff --git a/edg/core/Core.py b/edg/core/Core.py index 58a5ba5cb..dfec52055 100644 --- a/edg/core/Core.py +++ b/edg/core/Core.py @@ -3,6 +3,8 @@ from typing import * from abc import abstractmethod +from typing_extensions import override + from .. import edgir from .Builder import builder from .IdentityDict import IdentityDict @@ -146,9 +148,11 @@ class Refable(): """Object that could be referenced into a edgir.LocalPath""" RefMapType = IdentityDict['Refable', edgir.LocalPath] + @override def __repr__(self) -> str: return "%s@%02x" % (self.__class__.__name__, (id(self)//4)&0xff) + @override def __eq__(self, other: Any) -> None: # type: ignore raise NotImplementedError(f"__eq__ reserved for DSL, attempted to compare {self} and {other}") @@ -184,6 +188,7 @@ class LibraryElement(Refable): """Defines a library element, which optionally contains other library elements.""" _elt_properties: Dict[Tuple[Type[LibraryElement], EltPropertiesBase], Any] = {} + @override def __repr__(self) -> str: return "%s@%02x" % (self._get_def_name(), (id(self) // 4) & 0xff) @@ -193,6 +198,7 @@ def __init__(self) -> None: self.manager = SubElementManager() self.manager_ignored: Set[str] = set(['_parent']) + @override def __setattr__(self, name: str, value: Any) -> None: if hasattr(self, 'manager_ignored') and name not in self.manager_ignored: self.manager.add_element(name, value) diff --git a/edg/core/DesignTop.py b/edg/core/DesignTop.py index ee09b2010..26f6a0eb6 100644 --- a/edg/core/DesignTop.py +++ b/edg/core/DesignTop.py @@ -1,5 +1,7 @@ from typing import TypeVar, Union, List, Tuple, Dict, Type, Any +from typing_extensions import override + from .Core import Refable from .. import edgir from .Builder import builder @@ -22,9 +24,11 @@ def __init__(self) -> None: self._packed_blocks = IdentityDict[ Union[Block, PackedBlockAllocate], DesignPath]() # multipack part -> packed block (as path) + @override def Port(self, *args: Any, **kwargs: Any) -> Any: raise ValueError("Can't create ports on design top") + @override def Export(self, *args: Any, **kwargs: Any) -> Any: raise ValueError("Can't create ports on design top") @@ -53,6 +57,7 @@ def multipack(self) -> None: pass # TODO make this non-overriding? - this needs to call multipack after contents + @override def _elaborated_def_to_proto(self) -> edgir.HierarchyBlock: prev_element = builder.push_element(self) assert prev_element is None @@ -66,6 +71,7 @@ def _elaborated_def_to_proto(self) -> edgir.HierarchyBlock: builder.pop_to(prev_element) return self._def_to_proto() + @override def _populate_def_proto_block_contents(self, pb: edgir.BlockLikeTypes, ref_map: Refable.RefMapType) -> None: """Add multipack constraints""" super()._populate_def_proto_block_contents(pb, ref_map) diff --git a/edg/core/Generator.py b/edg/core/Generator.py index 07d8c1da0..ceefa8aaa 100644 --- a/edg/core/Generator.py +++ b/edg/core/Generator.py @@ -3,6 +3,7 @@ from typing import * from deprecated import deprecated +from typing_extensions import override from .. import edgir from .Builder import builder @@ -82,6 +83,7 @@ def generate(self) -> None: # Generator serialization and parsing # + @override def _def_to_proto(self) -> edgir.HierarchyBlock: if self._elaboration_state != BlockElaborationState.post_generate: # only write generator on the stub definition ref_map = self._create_ref_map() @@ -151,6 +153,7 @@ def __init__(self) -> None: self._default_exports: List[Tuple[BasePort, Port, Port]] = [] # internal, exported, default ExportType = TypeVar('ExportType', bound=BasePort) + @override def Export(self, port: ExportType, *args: Any, default: Optional[Port] = None, **kwargs: Any) -> ExportType: """A generator-only variant of Export that supports an optional default (either internal or external) to connect the (internal) port being exported to, if the external exported port is not connected.""" @@ -164,6 +167,7 @@ def Export(self, port: ExportType, *args: Any, default: Optional[Port] = None, * self._default_exports.append((port, new_port, default)) return new_port + @override def generate(self) -> None: super().generate() for (internal, exported, default) in self._default_exports: diff --git a/edg/core/HierarchyBlock.py b/edg/core/HierarchyBlock.py index c0a687dac..132f62c1f 100644 --- a/edg/core/HierarchyBlock.py +++ b/edg/core/HierarchyBlock.py @@ -6,6 +6,8 @@ from types import TracebackType from typing import * +from typing_extensions import override + from .. import edgir from .Builder import builder from . import ArrayStringExpr, ArrayRangeExpr, ArrayFloatExpr, ArrayIntExpr, ArrayBoolExpr, ArrayBoolLike, ArrayIntLike, \ @@ -111,6 +113,7 @@ def __init__(self, tpe: Type[BlockPrototypeType], args: Tuple[Any, ...], kwargs: self._args = args self._kwargs = kwargs + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self._tpe}, args={self._args}, kwargs={self._kwargs})" @@ -121,12 +124,14 @@ def _bind(self, parent: Union[BaseBlock, Port]) -> BlockPrototypeType: block._bind_in_place(parent) return block + @override def __getattribute__(self, item: str) -> Any: if item.startswith("_"): return super().__getattribute__(item) else: raise AttributeError(f"{self.__class__.__name__} has no attributes, must bind to get a concrete instance, tried to get {item}") + @override def __setattr__(self, key: str, value: Any) -> None: if key.startswith("_"): super().__setattr__(key, value) @@ -309,6 +314,7 @@ def _get_ports_by_tag(self, tags: Set[PortTag]) -> List[BasePort]: out.append(block_port) return out + @override def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath, *, interface_only: bool = False) -> None: super()._build_ref_map(ref_map, prefix) @@ -319,6 +325,7 @@ def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath, * assert isinstance(block, Block) block._build_ref_map(ref_map, edgir.localpath_concat(prefix, name), interface_only=True) + @override def _populate_def_proto_block_base(self, pb: edgir.BlockLikeTypes) -> None: super()._populate_def_proto_block_base(pb) assert isinstance(pb, edgir.HierarchyBlock) @@ -436,6 +443,7 @@ def _populate_def_proto_hierarchy(self, pb: edgir.HierarchyBlock, ref_map: Refab ) # TODO make this non-overriding? + @override def _def_to_proto(self) -> edgir.HierarchyBlock: assert not self._mixins # blocks with mixins can only be instantiated anonymously ref_map = self._create_ref_map() @@ -453,6 +461,7 @@ def _def_to_proto(self) -> edgir.HierarchyBlock: return pb + @override def _elaborated_def_to_proto(self) -> edgir.HierarchyBlock: return cast(edgir.HierarchyBlock, super()._elaborated_def_to_proto()) @@ -540,6 +549,7 @@ def implicit_connect(self, *implicits: ImplicitConnect) -> ImplicitScope: return ImplicitScope(self, implicits) + @override def connect(self, *connects: Union[BasePort, Connection], flatten: bool=False) -> Connection: assert not flatten, "flatten only allowed in links" return super().connect(*connects, flatten=flatten) @@ -584,6 +594,7 @@ def ArgParameter(self, param: CastableType, *, doc: Optional[str] = None) -> Con return param T = TypeVar('T', bound=BasePort) + @override def Port(self, tpe: T, tags: Iterable[PortTag]=[], *, optional: bool = False, doc: Optional[str] = None) -> T: """Registers a port for this Block""" if not isinstance(tpe, (Port, Vector)): diff --git a/edg/core/IdentityDict.py b/edg/core/IdentityDict.py index fc22ea7f1..5ca62df7b 100644 --- a/edg/core/IdentityDict.py +++ b/edg/core/IdentityDict.py @@ -2,6 +2,8 @@ from typing import * +from typing_extensions import override + KeyType = TypeVar('KeyType') ValueType = TypeVar('ValueType') class IdentityDict(Generic[KeyType, ValueType]): # TODO this should implement Mapping[KeyType, ValueType] @@ -35,6 +37,7 @@ def setdefault(self, key: KeyType, default: ValueType) -> ValueType: self.keys_dict[key_id] = key return self.dict[key_id] + @override def __repr__(self) -> str: return "IdentityDict" + str(self.items()) diff --git a/edg/core/IdentitySet.py b/edg/core/IdentitySet.py index 1354b41c8..ad83b95cd 100644 --- a/edg/core/IdentitySet.py +++ b/edg/core/IdentitySet.py @@ -2,6 +2,8 @@ from typing import * +from typing_extensions import override + EltType = TypeVar('EltType') # TODO maybe should be covariant? but is mutable so maybe not? class IdentitySet(Generic[EltType]): # TODO this should implement some kind of set base class def __init__(self, *args: EltType) -> None: @@ -17,6 +19,7 @@ def __iter__(self) -> Iterator[EltType]: def __len__(self) -> int: return len(self.set) + @override def __repr__(self) -> str: return "IdentitySet" + str(self.dict.values()) diff --git a/edg/core/Link.py b/edg/core/Link.py index 20df5bf31..ecacc75e6 100644 --- a/edg/core/Link.py +++ b/edg/core/Link.py @@ -3,6 +3,8 @@ import functools from typing import * +from typing_extensions import override + from .. import edgir from .Array import BaseVector, DerivedVector from .Blocks import BaseBlock, Connection, BaseBlockMeta @@ -37,6 +39,7 @@ def __init__(self) -> None: super().__init__() self.parent: Optional[Port] = None + @override def _def_to_proto(self) -> edgir.Link: ref_map = self._create_ref_map() @@ -86,5 +89,6 @@ def _def_to_proto(self) -> edgir.Link: return pb + @override def _elaborated_def_to_proto(self) -> edgir.Link: return cast(edgir.Link, super()._elaborated_def_to_proto()) diff --git a/edg/core/PortBlocks.py b/edg/core/PortBlocks.py index 4dbac8698..605ef23e6 100644 --- a/edg/core/PortBlocks.py +++ b/edg/core/PortBlocks.py @@ -1,7 +1,7 @@ from __future__ import annotations from typing import Any, Generic -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .Categories import InternalBlock from .HierarchyBlock import Block, abstract_block @@ -24,6 +24,7 @@ def __init__(self) -> None: self.outer_port: Any self.inner_link: Any + @override def __setattr__(self, name: str, value: Any) -> None: if isinstance(value, Port): assert name == '_parent' or name == "outer_port" or name == "inner_link", \ @@ -31,6 +32,7 @@ def __setattr__(self, name: str, value: Any) -> None: super().__setattr__(name, value) T = TypeVar('T', bound=BasePort) + @override def Port(self, tpe: T, *args: Any, **kwargs: Any) -> T: assert 'optional' not in kwargs, f"Ports in PortBridge are optional by default, required should be set by enclosing block, in {kwargs}" return super().Port(tpe, *args, optional=True, **kwargs) @@ -47,6 +49,7 @@ def __init__(self) -> None: self.src: Any self.dst: AdapterDstType + @override def __setattr__(self, name: str, value: Any) -> None: if isinstance(value, Port): assert name == '_parent' or name == "src" or name == "dst", \ @@ -54,6 +57,7 @@ def __setattr__(self, name: str, value: Any) -> None: super().__setattr__(name, value) T = TypeVar('T', bound=BasePort) + @override def Port(self, tpe: T, *args: Any, **kwargs: Any) -> T: assert 'optional' not in kwargs, "Ports in PortBridge are optional by default, required should be set by enclosing block" return super().Port(tpe, *args, optional=True, **kwargs) diff --git a/edg/core/Ports.py b/edg/core/Ports.py index ba3508830..7795077a9 100644 --- a/edg/core/Ports.py +++ b/edg/core/Ports.py @@ -4,7 +4,7 @@ from abc import abstractmethod from typing import Generic, Optional, Dict, Hashable, List -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .Binding import ParamBinding, IsConnectedBinding, NameBinding from .Builder import builder @@ -21,6 +21,7 @@ class InitializerContextMeta(type): + @override def __call__(cls, *args: Any, **kwargs: Any) -> Any: """Hook on construction to store some metadata about its creation. This hooks the top-level __init__ only.""" @@ -55,6 +56,7 @@ def _block_parent(self) -> Optional[BaseBlock]: raise ValueError(f"Unknown parent type {self._parent}") @abstractmethod + @override def _def_to_proto(self) -> edgir.PortTypes: # TODO: this might not be valid for Vector types? raise NotImplementedError @@ -155,6 +157,7 @@ def _clear_initializers(self) -> None: for (name, param) in self._parameters.items(): param.initializer = None + @override def _cloned_from(self: SelfType, other: SelfType) -> None: super()._cloned_from(other) self._parameters.finalize() @@ -205,11 +208,13 @@ def _convert(self, adapter: PortAdapter[ConvertTargetType]) -> ConvertTargetType self._adapter_count += 1 return adapter_inst.dst + @override def _instance_to_proto(self) -> edgir.PortLike: pb = edgir.PortLike() pb.lib_elem.target.name = self._get_def_name() return pb + @override def _def_to_proto(self) -> edgir.PortTypes: self._parameters.finalize() @@ -230,9 +235,11 @@ def _def_to_proto(self) -> edgir.PortTypes: return pb + @override def _type_of(self) -> Hashable: return type(self) + @override def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) -> None: super()._build_ref_map(ref_map, prefix) ref_map[self.is_connected()] = edgir.localpath_concat(prefix, edgir.IS_CONNECTED) @@ -242,6 +249,7 @@ def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) - if self._link_instance is not None: self._link_instance._build_ref_map(ref_map, edgir.localpath_concat(prefix, edgir.CONNECTED_LINK)) + @override def _get_initializers(self, path_prefix: List[str]) -> List[Tuple[ConstraintExpr, List[str], ConstraintExpr]]: self._parameters.finalize() return [(param, path_prefix + [name], param.initializer) for (name, param) in self._parameters.items() @@ -281,12 +289,14 @@ def __init__(self) -> None: self._ports: SubElementDict[Port] = self.manager.new_dict(Port) + @override def _clear_initializers(self) -> None: super()._clear_initializers() self._ports.finalize() for (name, port) in self._ports.items(): port._clear_initializers() + @override def _cloned_from(self: SelfType, other: SelfType) -> None: super()._cloned_from(other) for (name, port) in self._ports.items(): @@ -307,6 +317,7 @@ def with_elt_initializers(self: SelfType, replace_elts: dict[str, Port]) -> Self cloned_port._cloned_from(replace_port) return cloned + @override def _def_to_proto(self) -> edgir.Bundle: self._parameters.finalize() self._ports.finalize() @@ -330,11 +341,13 @@ def _def_to_proto(self) -> edgir.Bundle: return pb + @override def _build_ref_map(self, ref_map: Refable.RefMapType, prefix: edgir.LocalPath) -> None: super()._build_ref_map(ref_map, prefix) for name, field in self._ports.items(): field._build_ref_map(ref_map, edgir.localpath_concat(prefix, name)) + @override def _get_initializers(self, path_prefix: List[str]) -> List[Tuple[ConstraintExpr, List[str], ConstraintExpr]]: self_initializers = super()._get_initializers(path_prefix) self._ports.finalize() diff --git a/edg/core/Range.py b/edg/core/Range.py index 147562cff..d1251c369 100644 --- a/edg/core/Range.py +++ b/edg/core/Range.py @@ -1,6 +1,7 @@ import math from typing import Tuple, Union, Any from deprecated import deprecated +from typing_extensions import override class Range: @@ -118,6 +119,7 @@ def all() -> 'Range': """Creates a Range that is a superset of every range""" return Range(float('-inf'), float('inf')) + @override def __repr__(self) -> str: return f"Range({self.lower, self.upper})" @@ -127,6 +129,7 @@ def __init__(self, lower: float, upper: float) -> None: self.lower = float(lower) self.upper = float(upper) + @override def __eq__(self, other: Any) -> bool: if not isinstance(other, Range): return False diff --git a/edg/core/TransformUtil.py b/edg/core/TransformUtil.py index 7cb5de39f..8b2c1bc8e 100644 --- a/edg/core/TransformUtil.py +++ b/edg/core/TransformUtil.py @@ -2,6 +2,8 @@ from typing import * import sys # for exception chaining +from typing_extensions import override + from .. import edgir @@ -15,13 +17,16 @@ class Path(NamedTuple): # internal helper type ports: Tuple[str, ...] params: Tuple[str, ...] + @override def __hash__(self) -> int: return hash((self.blocks, self.links, self.ports, self.params)) + @override def __eq__(self, other: Any) -> bool: return isinstance(other, Path) and self.blocks == other.blocks and self.links == other.links and \ self.ports == other.ports and self.params == other.params + @override def __repr__(self) -> str: if not self.blocks and not self.links and not self.ports and not self.params: return '(root)' @@ -150,6 +155,7 @@ class TransformContext(NamedTuple): path: Path design: edgir.Design + @override def __repr__(self) -> str: return f"TransformContext(path={self.path}, design=...)" diff --git a/edg/core/test_block.py b/edg/core/test_block.py index ba343a41a..362a07e08 100644 --- a/edg/core/test_block.py +++ b/edg/core/test_block.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_elaboration_common import TestPortBase @@ -37,6 +39,7 @@ def __init__(self) -> None: class BlockBaseProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockBase()._elaborated_def_to_proto() @@ -69,6 +72,7 @@ def test_port_init(self) -> None: class BlockSecondBaseProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockSecondBase()._elaborated_def_to_proto() @@ -80,6 +84,7 @@ def test_default(self) -> None: class BlockProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlock()._elaborated_def_to_proto() diff --git a/edg/core/test_block_eltdict.py b/edg/core/test_block_eltdict.py index 13dac845d..65c7b536a 100644 --- a/edg/core/test_block_eltdict.py +++ b/edg/core/test_block_eltdict.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from . import * from .test_common import TestBlockSource, TestBlockSink, TestPortSource, TestPortSink class EltDictBlock(Block): """Block with an EltDict of sub-blocks""" + @override def contents(self) -> None: super().contents() self.sink = ElementDict[Block]() diff --git a/edg/core/test_block_errors.py b/edg/core/test_block_errors.py index 0881d32a7..3efd4148b 100644 --- a/edg/core/test_block_errors.py +++ b/edg/core/test_block_errors.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .HdlUserExceptions import * from .test_common import TestPortSource, TestBlockSource, TestBlockSink @@ -10,6 +12,7 @@ class BadLinkTestCase(unittest.TestCase): class OverconnectedHierarchyBlock(Block): """A block with connections that don't fit the link (2 sources connected vs. one in the link)""" + @override def contents(self) -> None: super().contents() self.source1 = self.Block(TestBlockSource()) @@ -29,6 +32,7 @@ def __init__(self) -> None: super().__init__() self.source_port = self.Port(TestPortSource()) + @override def contents(self) -> None: super().contents() self.source = self.Block(TestBlockSource()) @@ -54,6 +58,7 @@ def test_unbound_link(self) -> None: class AmbiguousJoinBlock(Block): """A block with a connect join that merges two names""" + @override def contents(self) -> None: super().contents() self.source = self.Block(TestBlockSource()) diff --git a/edg/core/test_block_portvector.py b/edg/core/test_block_portvector.py index 499fa383a..17a579671 100644 --- a/edg/core/test_block_portvector.py +++ b/edg/core/test_block_portvector.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_elaboration_common import TestPortSink, TestBlockSink, TestBlockSource @@ -63,6 +65,7 @@ def __init__(self) -> None: class BlockVectorBaseProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorBase()._elaborated_def_to_proto() @@ -76,6 +79,7 @@ def test_port_init(self) -> None: class BlockVectorProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorConcrete()._elaborated_def_to_proto() @@ -92,6 +96,7 @@ def test_port_def(self) -> None: class BlockVectorEmptyProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorEmpty()._elaborated_def_to_proto() @@ -104,6 +109,7 @@ def test_port_def(self) -> None: class VectorExportProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorExport()._elaborated_def_to_proto() @@ -127,6 +133,7 @@ def test_export(self) -> None: class VectorBridgedProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorBridged()._elaborated_def_to_proto() @@ -166,6 +173,7 @@ def test_bridged(self) -> None: class VectorConnectProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorConnect()._elaborated_def_to_proto() @@ -207,6 +215,7 @@ def test_export(self) -> None: class VectorConstraintProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBlockPortVectorConstraint()._elaborated_def_to_proto() diff --git a/edg/core/test_bundle.py b/edg/core/test_bundle.py index e22bf4f0b..fe457b16b 100644 --- a/edg/core/test_bundle.py +++ b/edg/core/test_bundle.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .test_elaboration_common import TestPortSink @@ -16,6 +18,7 @@ def __init__(self, float_param: FloatLike = FloatExpr(), class BundleProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBundle()._def_to_proto() diff --git a/edg/core/test_chain_connect.py b/edg/core/test_chain_connect.py index 5e0c26c9f..11e0f43be 100644 --- a/edg/core/test_chain_connect.py +++ b/edg/core/test_chain_connect.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestPortSink, TestPortSource @@ -32,6 +34,7 @@ def __init__(self) -> None: class ChainConnectUnpackNamedBlock(Block): """Block with chain connect, where those blocks are declared inline and named by unpack""" + @override def contents(self) -> None: super().contents() (self.output, self.inout, self.inputoutput, self.input), self.test_chain = self.chain( @@ -44,6 +47,7 @@ def contents(self) -> None: class ChainConnectExplicitNamedBlock(Block): """Block with chain connect, where those blocks are explicitly (separately) declared and named""" + @override def contents(self) -> None: super().contents() self.output = self.Block(TestBlockChainOutput()) diff --git a/edg/core/test_connect_array.py b/edg/core/test_connect_array.py index 3bce8eb6f..4a514e887 100644 --- a/edg/core/test_connect_array.py +++ b/edg/core/test_connect_array.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestPortSource, TestPortSink @@ -19,6 +21,7 @@ def __init__(self) -> None: self.sinks = self.Port(Vector(TestPortSink())) self.generator_param(self.sinks.requested()) + @override def generate(self) -> None: super().generate() for request in self.get(self.sinks.requested()): @@ -26,6 +29,7 @@ def generate(self) -> None: class ArrayConnectBlock(Block): + @override def contents(self) -> None: super().contents() @@ -36,6 +40,7 @@ def contents(self) -> None: class ArrayConnectProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = ArrayConnectBlock()._elaborated_def_to_proto() @@ -73,6 +78,7 @@ def test_connectivity(self) -> None: class ArrayAllocatedConnectBlock(Block): + @override def contents(self) -> None: super().contents() @@ -84,6 +90,7 @@ def contents(self) -> None: class ArrayAllocatedConnectProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = ArrayAllocatedConnectBlock()._elaborated_def_to_proto() diff --git a/edg/core/test_generator.py b/edg/core/test_generator.py index c386a4a1d..7a0c77922 100644 --- a/edg/core/test_generator.py +++ b/edg/core/test_generator.py @@ -2,6 +2,8 @@ from os import devnull from contextlib import redirect_stderr +from typing_extensions import override + from . import * from .ScalaCompilerInterface import ScalaCompiler @@ -18,6 +20,7 @@ def __init__(self) -> None: # Because this doesn't have dependency parameters, this is the top-level design self.float_param = self.Parameter(FloatExpr()) + @override def generate(self) -> None: self.assign(self.float_param, 2.0) @@ -35,6 +38,7 @@ def __init__(self, float_preset: FloatLike) -> None: self.float_preset = self.ArgParameter(float_preset) self.generator_param(self.float_preset) + @override def generate(self) -> None: self.assign(self.float_param, self.get(self.float_preset) * 2) @@ -54,6 +58,7 @@ def __init__(self, float_preset1: FloatLike, float_preset2: FloatLike) -> None: self.float_preset2 = self.ArgParameter(float_preset2) self.generator_param(self.float_preset1, self.float_preset2) + @override def generate(self) -> None: self.assign1 = self.assign(self.float_param1, self.get(self.float_preset1) * 3) self.assign2 = self.assign(self.float_param2, self.get(self.float_preset2) + 7) @@ -122,6 +127,7 @@ def __init__(self) -> None: self.generator_param(self.port.is_connected()) self.connected = self.Parameter(BoolExpr()) + @override def generate(self) -> None: if self.get(self.port.is_connected()): self.assign(self.connected, True) @@ -148,6 +154,7 @@ def __init__(self) -> None: super().__init__() self.port = self.Port(TestPortSource(), optional=True) + @override def generate(self) -> None: self.inner = self.Block(TestBlockSource(4.5)) self.connect(self.inner.port, self.port) @@ -195,6 +202,7 @@ class GeneratorFailure(GeneratorBlock): def __init__(self) -> None: super().__init__() + @override def generate(self) -> None: def helperfn() -> None: raise TestGeneratorException("test text") diff --git a/edg/core/test_generator_error.py b/edg/core/test_generator_error.py index 171234e32..2cafe196c 100644 --- a/edg/core/test_generator_error.py +++ b/edg/core/test_generator_error.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .HdlUserExceptions import BlockDefinitionError @@ -21,6 +23,7 @@ def __init__(self) -> None: self.param = self.Parameter(FloatExpr()) self.generator_param(self.param) + @override def generate(self) -> None: super().generate() diff --git a/edg/core/test_generator_portvector.py b/edg/core/test_generator_portvector.py index c11c48db8..7de880c07 100644 --- a/edg/core/test_generator_portvector.py +++ b/edg/core/test_generator_portvector.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .ScalaCompilerInterface import ScalaCompiler @@ -12,6 +14,7 @@ def __init__(self) -> None: self.ports = self.Port(Vector(TestPortSink())) self.generator_param(self.ports.requested()) + @override def generate(self) -> None: assert self.get(self.ports.requested()) == ['0', 'named', '1'] self.ports.append_elt(TestPortSink((-1, 1))) @@ -117,6 +120,7 @@ def __init__(self, param: ArrayRangeLike) -> None: self.param = self.ArgParameter(param) self.generator_param(self.param) + @override def generate(self) -> None: for elt in self.get(self.param): created_port = self.ports.append_elt(TestPortSink(elt)) # any port diff --git a/edg/core/test_hierarchy_block.py b/edg/core/test_hierarchy_block.py index a38f4758d..fdcd26df5 100644 --- a/edg/core/test_hierarchy_block.py +++ b/edg/core/test_hierarchy_block.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestBlockSource, TestBlockSink, TestPortSink class TopHierarchyBlock(Block): + @override def contents(self) -> None: super().contents() @@ -16,6 +19,7 @@ def contents(self) -> None: class TopHierarchyBlockProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TopHierarchyBlock()._elaborated_def_to_proto() @@ -64,6 +68,7 @@ def test_connectivity(self) -> None: class MultiConnectBlock(Block): + @override def contents(self) -> None: super().contents() @@ -78,6 +83,7 @@ def contents(self) -> None: class MultiConnectBlockProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = MultiConnectBlock()._elaborated_def_to_proto() @@ -118,6 +124,7 @@ def test_connectivity(self) -> None: class ConnectJoinBlock(Block): + @override def contents(self) -> None: super().contents() @@ -134,6 +141,7 @@ def contents(self) -> None: class ConnectJoinBlockProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = ConnectJoinBlock()._elaborated_def_to_proto() @@ -189,6 +197,7 @@ def __init__(self) -> None: class ExportPortHierarchyBlockTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = ExportPortHierarchyBlock()._elaborated_def_to_proto() @@ -213,6 +222,7 @@ def __init__(self) -> None: super().__init__() self.exported = self.Port(TestPortSink(), optional=True) # avoid required constraint + @override def contents(self) -> None: super().contents() self.sink = self.Block(TestBlockSink()) @@ -220,6 +230,7 @@ def contents(self) -> None: class IndirectExportPortHierarchyBlockTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = IndirectExportPortHierarchyBlock()._elaborated_def_to_proto() @@ -244,6 +255,7 @@ def __init__(self) -> None: super().__init__() self.source_port = self.Port(TestPortSink(), optional=True) + @override def contents(self) -> None: super().contents() self.sink1 = self.Block(TestBlockSink()) @@ -252,6 +264,7 @@ def contents(self) -> None: class PortBridgeHierarchyBlockTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = PortBridgeHierarchyBlock()._elaborated_def_to_proto() diff --git a/edg/core/test_implicit_connect.py b/edg/core/test_implicit_connect.py index e0f3d80d5..749722a12 100644 --- a/edg/core/test_implicit_connect.py +++ b/edg/core/test_implicit_connect.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestBlockSource, TestBlockSink, TestPortSink, ImplicitSink, TestBlockImplicitSink @@ -8,6 +10,7 @@ class ImplicitConnectBlock(Block): """Block with implicit scope containing some blocks""" + @override def contents(self) -> None: super().contents() self.block_source = self.Block(TestBlockSource()) @@ -50,6 +53,7 @@ def __init__(self) -> None: super().__init__() self.sink_in = self.Port(TestPortSink()) + @override def contents(self) -> None: super().contents() self.implicit_net = self.connect(self.sink_in) @@ -89,6 +93,7 @@ def test_connectivity(self) -> None: class ImplicitConnectOutsideScopeErrorBlock(Block): """Block with implicit scope containing some blocks""" + @override def contents(self) -> None: super().contents() self.block_source = self.Block(TestBlockSource()) diff --git a/edg/core/test_initializer.py b/edg/core/test_initializer.py index a28df5aa6..74ff7000b 100644 --- a/edg/core/test_initializer.py +++ b/edg/core/test_initializer.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_bundle import TestBundle @@ -23,18 +25,21 @@ def __init__(self) -> None: super().__init__() self.outer_bundle = self.Port(TestBundle(21, 1, -1), optional=True) + @override def contents(self) -> None: super().contents() self.inner = self.Block(TestInternalBlock(62, 31)) class TestDefaultBlock(Block): + @override def contents(self) -> None: super().contents() self.inner = self.Block(TestInternalBlock()) class TestMultipleInstantiationBlock(Block): + @override def contents(self) -> None: super().contents() model = TestInternalBlock() diff --git a/edg/core/test_inner_link.py b/edg/core/test_inner_link.py index 1cd05374d..63a48d995 100644 --- a/edg/core/test_inner_link.py +++ b/edg/core/test_inner_link.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_elaboration_common import TestPortSource, TestPortSink @@ -39,6 +41,7 @@ def __init__(self) -> None: class InnerLinkTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestBundleLink()._elaborated_def_to_proto() diff --git a/edg/core/test_link.py b/edg/core/test_link.py index 9197db79c..0a8f3e4b5 100644 --- a/edg/core/test_link.py +++ b/edg/core/test_link.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_elaboration_common import TestLink class LinkTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestLink()._elaborated_def_to_proto() diff --git a/edg/core/test_mixin.py b/edg/core/test_mixin.py index 7b9e75dac..7c33a51eb 100644 --- a/edg/core/test_mixin.py +++ b/edg/core/test_mixin.py @@ -1,6 +1,8 @@ import unittest from typing import Any +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestPortSink @@ -21,6 +23,7 @@ def __init__(self, *args: Any, mixin_float: FloatLike = 1.0, **kwargs: Any) -> N class MixinProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: cls = TestMixin() self.assertEqual(cls._is_mixin(), True) @@ -60,6 +63,7 @@ class TestMixinSubclass(TestMixin): class MixinSubclassProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: cls = TestMixinSubclass() self.assertEqual(cls._is_mixin(), True) @@ -101,6 +105,7 @@ class TestMixinConcreteBlock(TestMixin, TestMixinBase): class MixinConcreteBlockProtoTestCase(unittest.TestCase): # pretty straightforward test of Python inheritance + @override def setUp(self) -> None: cls = TestMixinConcreteBlock() self.assertEqual(cls._is_mixin(), False) diff --git a/edg/core/test_mixin_errors.py b/edg/core/test_mixin_errors.py index 9834c6917..e44b4b423 100644 --- a/edg/core/test_mixin_errors.py +++ b/edg/core/test_mixin_errors.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from . import * from .HdlUserExceptions import BlockDefinitionError, EdgTypeError from .test_block import TestBlock @@ -32,6 +34,7 @@ class UnrelatedAbstractBlock(Block): class BadMixinUsageTestCase(unittest.TestCase): class StandaloneMixinBlock(Block): + @override def contents(self) -> None: super().contents() self.block = self.Block(TestMixin()) @@ -41,6 +44,7 @@ def test_standalone_mixin(self) -> None: self.StandaloneMixinBlock()._elaborated_def_to_proto() class ConcreteMixinBlock(Block): + @override def contents(self) -> None: super().contents() self.block = self.Block(TestMixinConcreteBlock()) @@ -51,6 +55,7 @@ def test_concrete_mixin(self) -> None: self.ConcreteMixinBlock()._elaborated_def_to_proto() class BadBaseMixin(Block): + @override def contents(self) -> None: super().contents() self.block = self.Block(UnrelatedAbstractBlock()) diff --git a/edg/core/test_mixin_usage.py b/edg/core/test_mixin_usage.py index e8175ddd5..1256f1664 100644 --- a/edg/core/test_mixin_usage.py +++ b/edg/core/test_mixin_usage.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_common import TestBlockSource @@ -8,6 +10,7 @@ class MixinUsageTestCase(unittest.TestCase): class MixinBlock(Block): + @override def contents(self) -> None: super().contents() @@ -20,6 +23,7 @@ def contents(self) -> None: self.mixin_source = self.Block(TestBlockSource()) self.mixin_net = self.connect(self.mixin.mixin_port, self.mixin_source.source) + @override def setUp(self) -> None: self.pb = self.MixinBlock()._elaborated_def_to_proto() diff --git a/edg/core/test_multipack.py b/edg/core/test_multipack.py index bd561d7c1..bbf278e3c 100644 --- a/edg/core/test_multipack.py +++ b/edg/core/test_multipack.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * from .test_elaboration_common import TestPortSink, TestBlockSink, TestBlockSource @@ -40,11 +42,13 @@ def __init__(self) -> None: class TopMultipackDesign(DesignTop): + @override def contents(self) -> None: super().contents() self.sink1 = self.Block(PartSink()) self.sink2 = self.Block(TestBlockContainerSink()) + @override def multipack(self) -> None: self.packed = self.Block(MultipackBlockSink()) self.pack(self.packed.sink1, ['sink1']) @@ -52,6 +56,7 @@ def multipack(self) -> None: class TopMultipackDesignTestCase(unittest.TestCase): + @override def setUp(self) -> None: pb = TopMultipackDesign()._elaborated_def_to_proto() self.constraints = list(map(lambda pair: pair.value, pb.constraints)) @@ -121,11 +126,13 @@ def __init__(self) -> None: class TopMultipackArrayDesign(DesignTop): + @override def contents(self) -> None: super().contents() self.sink1 = self.Block(PartSink()) self.sink2 = self.Block(TestBlockContainerSink()) + @override def multipack(self) -> None: self.packed = self.Block(MultipackArrayBlockSink()) self.pack(self.packed.sinks.request('1'), ['sink1']) @@ -133,6 +140,7 @@ def multipack(self) -> None: class TopMultipackArrayDesignTestCase(unittest.TestCase): + @override def setUp(self) -> None: pb = TopMultipackArrayDesign()._elaborated_def_to_proto() self.constraints = list(map(lambda pair: pair.value, pb.constraints)) diff --git a/edg/core/test_port.py b/edg/core/test_port.py index a961d7ccf..a790a6b01 100644 --- a/edg/core/test_port.py +++ b/edg/core/test_port.py @@ -1,11 +1,14 @@ import unittest from typing import cast +from typing_extensions import override + from .. import edgir from .test_elaboration_common import TestPortBase, TestPortSource class PortProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = cast(edgir.Port, TestPortBase()._def_to_proto()) # TODO eliminate cast @@ -16,6 +19,7 @@ def test_contains_param(self) -> None: class PortSourceProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = cast(edgir.Port, TestPortSource()._def_to_proto()) diff --git a/edg/core/test_port_bridge.py b/edg/core/test_port_bridge.py index 88de86b3c..44b9c5a3d 100644 --- a/edg/core/test_port_bridge.py +++ b/edg/core/test_port_bridge.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from .. import edgir from .test_elaboration_common import TestPortBridge, TestPortSink from . import * class PortBridgeProtoTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = TestPortBridge()._elaborated_def_to_proto() diff --git a/edg/core/test_simple_const_prop.py b/edg/core/test_simple_const_prop.py index bc0411cd0..c4103517c 100644 --- a/edg/core/test_simple_const_prop.py +++ b/edg/core/test_simple_const_prop.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * @@ -22,6 +24,7 @@ def __init__(self) -> None: self.range_const = self.Parameter(RangeExpr()) self.range_param = self.Parameter(RangeExpr()) + @override def contents(self) -> None: self.assign(self.float_const, 2.0) self.assign(self.float_param, self.float_const) @@ -35,6 +38,7 @@ def contents(self) -> None: class ConstPropTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestParameterConstProp) @@ -93,6 +97,7 @@ def __init__(self) -> None: class ConstPropPortTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestPortConstPropTopBlock) @@ -115,6 +120,7 @@ def __init__(self) -> None: class DisconnectedPortTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestDisconnectedTopBlock) @@ -152,6 +158,7 @@ class TestPortConstPropBundleTopBlock(Block): def __init__(self) -> None: super().__init__() + @override def contents(self) -> None: self.block1 = self.Block(TestPortConstPropBundleInnerBlock()) self.block2 = self.Block(TestPortConstPropBundleInnerBlock()) # dummy, just to infer a connection @@ -162,6 +169,7 @@ def contents(self) -> None: class ConstPropBundleTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestPortConstPropBundleTopBlock) diff --git a/edg/core/test_simple_expr_eval.py b/edg/core/test_simple_expr_eval.py index dc06211b1..61a0a0753 100644 --- a/edg/core/test_simple_expr_eval.py +++ b/edg/core/test_simple_expr_eval.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from .. import edgir from . import * @@ -11,11 +13,13 @@ def __init__(self) -> None: self.sum_float = self.Parameter(FloatExpr(2 * LiteralConstructor(1) + 3 * LiteralConstructor(1))) self.sum_range = self.Parameter(RangeExpr()) + @override def contents(self) -> None: self.assign(self.sum_range, (2, 6) * LiteralConstructor(1) + (7, 8) * LiteralConstructor(1)) class EvalExprTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestEvalExprBlock) @@ -57,6 +61,7 @@ def __init__(self) -> None: class EvalReductionTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.compiled = ScalaCompiler.compile(TestEvalReductionBlock) diff --git a/edg/electronics_model/AnalogPort.py b/edg/electronics_model/AnalogPort.py index 18d10530d..6faad0055 100644 --- a/edg/electronics_model/AnalogPort.py +++ b/edg/electronics_model/AnalogPort.py @@ -2,6 +2,8 @@ from typing import Optional, Tuple +from typing_extensions import override + from ..core import * from .CircuitBlock import CircuitLink, CircuitPortAdapter from .GroundPort import GroundLink @@ -27,6 +29,7 @@ def __init__(self) -> None: self.signal_limits = self.Parameter(RangeExpr()) self.current_limits = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -75,6 +78,7 @@ def __init__(self) -> None: self.inner_link = self.Port(AnalogSource(voltage_out=RangeExpr(), signal_out=RangeExpr(), current_limits=RangeExpr.ALL)) + @override def contents(self) -> None: super().contents() @@ -105,6 +109,7 @@ def __init__(self) -> None: signal_limits=RangeExpr.ALL, impedance=RangeExpr())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/BomBackend.py b/edg/electronics_model/BomBackend.py index 36231ae84..1a47b125f 100644 --- a/edg/electronics_model/BomBackend.py +++ b/edg/electronics_model/BomBackend.py @@ -1,6 +1,8 @@ import io from typing import List, Tuple, Dict, NamedTuple +from typing_extensions import override + from .. import edgir from ..core import BaseBackend, CompiledDesign, TransformUtil @@ -16,6 +18,7 @@ class BomItem(NamedTuple): class GenerateBom(BaseBackend): # creates and populates .csv file + @override def run(self, design: CompiledDesign, args: Dict[str, str]= {}) -> List[Tuple[edgir.LocalPath, str]]: assert not args bom_list = BomTransform(design).run() @@ -42,6 +45,7 @@ def __init__(self, design: CompiledDesign): self.design = design self.bom_list: Dict[BomItem, List[str]] = {} # BomItem -> list of refdes + @override def visit_block(self, context: TransformUtil.TransformContext, block: edgir.BlockTypes) -> None: footprint = self.design.get_value(context.path.to_tuple() + ('fp_footprint',)) refdes = self.design.get_value(context.path.to_tuple() + ('fp_refdes',)) diff --git a/edg/electronics_model/CanPort.py b/edg/electronics_model/CanPort.py index 0e14393dc..3587a1f03 100644 --- a/edg/electronics_model/CanPort.py +++ b/edg/electronics_model/CanPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir, DigitalBidirBridge @@ -15,6 +17,7 @@ def __init__(self) -> None: # TODO write custom top level digital constraints # TODO model frequency ... somewhere + @override def contents(self) -> None: super().contents() # TODO future: digital constraints through link inference @@ -67,6 +70,7 @@ def __init__(self) -> None: # TODO write custom top level digital constraints # TODO future: digital constraints through link inference + @override def contents(self) -> None: super().contents() @@ -83,6 +87,7 @@ def __init__(self) -> None: self.outer_port = self.Port(CanDiffPort(DigitalBidir.empty())) self.inner_link = self.Port(CanDiffPort(DigitalBidir.empty())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/CircuitBlock.py b/edg/electronics_model/CircuitBlock.py index 79197956d..c0174e97f 100644 --- a/edg/electronics_model/CircuitBlock.py +++ b/edg/electronics_model/CircuitBlock.py @@ -2,7 +2,7 @@ from typing import Generic, Any, Optional, List, Mapping, Dict -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from .KiCadImportableBlock import KiCadImportableBlock from ..core import * @@ -103,6 +103,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: @abstract_block class NetBlock(InternalBlock, NetBaseBlock, Block): + @override def contents(self) -> None: super().contents() self.net() @@ -110,6 +111,7 @@ def contents(self) -> None: @abstract_block class CircuitPortBridge(NetBaseBlock, PortBridge): + @override def contents(self) -> None: super().contents() self.net() @@ -118,10 +120,12 @@ def contents(self) -> None: AdapterDstType = TypeVar('AdapterDstType', covariant=True, bound='CircuitPort', default='CircuitPort') @abstract_block class CircuitPortAdapter(KiCadImportableBlock, NetBaseBlock, PortAdapter[AdapterDstType], Generic[AdapterDstType]): + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:Adapter' return {'1': self.src, '2': self.dst} + @override def contents(self) -> None: super().contents() self.net() @@ -129,6 +133,7 @@ def contents(self) -> None: @non_library # TODO make abstract instead? class CircuitLink(NetBaseBlock, Link): + @override def contents(self) -> None: super().contents() self.net() diff --git a/edg/electronics_model/CircuitPackingBlock.py b/edg/electronics_model/CircuitPackingBlock.py index 927a9205f..822cccc1d 100644 --- a/edg/electronics_model/CircuitPackingBlock.py +++ b/edg/electronics_model/CircuitPackingBlock.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing_extensions import override + from ..core import * from .PassivePort import Passive from .GroundPort import Ground, GroundReference @@ -24,6 +26,7 @@ def __init__(self) -> None: self.generator_param(self.elts.requested()) self.packed(self.elts, self.merged) + @override def generate(self) -> None: super().generate() self.elts.defined() @@ -43,6 +46,7 @@ def __init__(self) -> None: self.generator_param(self.gnd_ins.requested()) self.packed(self.gnd_ins, self.gnd_out) + @override def generate(self) -> None: super().generate() self.gnd_ins.defined() @@ -67,6 +71,7 @@ def __init__(self) -> None: self.generator_param(self.pwr_ins.requested()) self.packed(self.pwr_ins, self.pwr_out) + @override def generate(self) -> None: super().generate() self.pwr_ins.defined() diff --git a/edg/electronics_model/ConnectedGenerator.py b/edg/electronics_model/ConnectedGenerator.py index 78a808cd6..573f9aff7 100644 --- a/edg/electronics_model/ConnectedGenerator.py +++ b/edg/electronics_model/ConnectedGenerator.py @@ -1,5 +1,5 @@ from typing import Type, Generic -from typing_extensions import TypeVar +from typing_extensions import TypeVar, override from ..core import * from .VoltagePorts import VoltageLink, VoltageSink, VoltageSource @@ -37,6 +37,7 @@ def __init__(self, in_is_connected: BoolLike = BoolExpr()) -> None: self.in_is_connected = self.ArgParameter(in_is_connected) self.generator_param(self.in_is_connected) + @override def generate(self) -> None: super().generate() if self.get(self.in_is_connected): diff --git a/edg/electronics_model/CrystalPort.py b/edg/electronics_model/CrystalPort.py index c2d6c3418..a7d599b86 100644 --- a/edg/electronics_model/CrystalPort.py +++ b/edg/electronics_model/CrystalPort.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..core import * from .PassivePort import Passive @@ -11,6 +13,7 @@ def __init__(self) -> None: self.drive_voltage = self.Parameter(RangeExpr(self.driver.voltage_out)) self.frequency = self.Parameter(RangeExpr(self.crystal.frequency)) + @override def contents(self) -> None: super().contents() self.require(self.driver.frequency_limits.contains(self.frequency)) diff --git a/edg/electronics_model/DebugPorts.py b/edg/electronics_model/DebugPorts.py index 87f1c0715..2457a559e 100644 --- a/edg/electronics_model/DebugPorts.py +++ b/edg/electronics_model/DebugPorts.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir @@ -12,6 +14,7 @@ def __init__(self) -> None: self.device = self.Port(SwdTargetPort.empty()) self.pull = self.Port(Vector(SwdPullPort.empty()), optional=True) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/DigitalPorts.py b/edg/electronics_model/DigitalPorts.py index 0c344240c..94b05796b 100644 --- a/edg/electronics_model/DigitalPorts.py +++ b/edg/electronics_model/DigitalPorts.py @@ -3,6 +3,7 @@ from typing import Optional, Tuple from deprecated import deprecated +from typing_extensions import override from ..core import * from .CircuitBlock import CircuitLink, CircuitPortBridge, CircuitPortAdapter @@ -51,6 +52,7 @@ def __init__(self) -> None: self._has_low_signal_driver = self.Parameter(BoolExpr()) self._has_high_signal_driver = self.Parameter(BoolExpr()) + @override def contents(self) -> None: super().contents() @@ -140,6 +142,7 @@ def __init__(self) -> None: pullup_capable=False, pulldown_capable=False, # don't create a loop _bridged_internal=True)) + @override def contents(self) -> None: super().contents() @@ -234,6 +237,7 @@ def __init__(self) -> None: pullup_capable=False, pulldown_capable=False, # don't create a loop _bridged_internal=True)) + @override def contents(self) -> None: super().contents() @@ -366,6 +370,7 @@ def __init__(self) -> None: _bridged_internal=True )) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/DvpPort.py b/edg/electronics_model/DvpPort.py index 951fc6b88..9efded8af 100644 --- a/edg/electronics_model/DvpPort.py +++ b/edg/electronics_model/DvpPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir @@ -12,6 +14,7 @@ def __init__(self) -> None: self.host = self.Port(Dvp8Host(DigitalBidir.empty())) self.cam = self.Port(Dvp8Camera(DigitalBidir.empty())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/GroundPort.py b/edg/electronics_model/GroundPort.py index 1e08a940c..a529b3438 100644 --- a/edg/electronics_model/GroundPort.py +++ b/edg/electronics_model/GroundPort.py @@ -1,6 +1,9 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any + +from typing_extensions import override + from ..core import * from .CircuitBlock import CircuitPortBridge, CircuitPortAdapter, CircuitLink, CircuitPort from .Units import Volt, Ohm @@ -31,6 +34,7 @@ def __init__(self) -> None: self.voltage = self.Parameter(RangeExpr()) self.voltage_limits = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -52,6 +56,7 @@ def __init__(self) -> None: self.outer_port = self.Port(Ground()) self.inner_link = self.Port(GroundReference(voltage_out=RangeExpr())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/I2cPort.py b/edg/electronics_model/I2cPort.py index 641e6e4aa..8bec62d73 100644 --- a/edg/electronics_model/I2cPort.py +++ b/edg/electronics_model/I2cPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir, DigitalBidirBridge, DigitalSinkBridge @@ -23,6 +25,7 @@ def __init__(self) -> None: self.has_pull = self.Parameter(BoolExpr(self.pull.any_connected())) + @override def contents(self) -> None: super().contents() self.require(self.pull.any_connected() | self.controller.has_pullup) @@ -66,6 +69,7 @@ def __init__(self) -> None: self.outer_port = self.Port(I2cTarget.empty()) self.inner_link = self.Port(I2cController(DigitalBidir.empty(), self.outer_port.link().has_pull)) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/I2sPort.py b/edg/electronics_model/I2sPort.py index 81b7634b1..edce955bf 100644 --- a/edg/electronics_model/I2sPort.py +++ b/edg/electronics_model/I2sPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir @@ -11,6 +13,7 @@ def __init__(self) -> None: self.target_receiver = self.Port(I2sTargetReceiver(DigitalSink.empty())) # TODO: multiple receivers, target transmitters, eg microphones + @override def contents(self) -> None: super().contents() self.sck = self.connect(self.controller.sck, self.target_receiver.sck) diff --git a/edg/electronics_model/KiCadImportableBlock.py b/edg/electronics_model/KiCadImportableBlock.py index 9f18f9bc4..c76b1609d 100644 --- a/edg/electronics_model/KiCadImportableBlock.py +++ b/edg/electronics_model/KiCadImportableBlock.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import TypeVar, Type, Mapping +from typing_extensions import override + from ..core import * diff --git a/edg/electronics_model/KiCadSchematicBlock.py b/edg/electronics_model/KiCadSchematicBlock.py index d3f0881cc..36c3a4831 100644 --- a/edg/electronics_model/KiCadSchematicBlock.py +++ b/edg/electronics_model/KiCadSchematicBlock.py @@ -3,6 +3,8 @@ from abc import abstractmethod from typing import Type, Any, Optional, Mapping, Dict, List, Callable, Tuple, TypeVar, cast +from typing_extensions import override + from ..core import * from .CircuitBlock import FootprintBlock from .VoltagePorts import CircuitPort @@ -31,6 +33,7 @@ class KiCadBlackbox(KiCadBlackboxBase, FootprintBlock, GeneratorBlock, InternalB and has all passive ports. """ @classmethod + @override def block_from_symbol(cls, symbol: KiCadSymbol, lib: KiCadLibSymbol) -> \ Tuple['KiCadBlackbox', Callable[['KiCadBlackbox'], Mapping[str, BasePort]]]: pin_numbers = [pin.number for pin in lib.pins] @@ -56,6 +59,7 @@ def __init__(self, kicad_pins: ArrayStringLike, kicad_refdes_prefix: StringLike, self.kicad_pins = self.ArgParameter(kicad_pins) self.generator_param(self.kicad_pins) + @override def generate(self) -> None: super().generate() mapping = {pin_name: self.ports.append_elt(Passive(), pin_name) diff --git a/edg/electronics_model/KiCadSchematicParser.py b/edg/electronics_model/KiCadSchematicParser.py index afed1d01f..c318e5bb2 100644 --- a/edg/electronics_model/KiCadSchematicParser.py +++ b/edg/electronics_model/KiCadSchematicParser.py @@ -4,7 +4,7 @@ import math import sexpdata # type: ignore - +from typing_extensions import override # This defines the minimum resolvable grid, so all coordinates are rounded to integer # coordinates to exact position equality checks can be made without worrying about @@ -56,6 +56,7 @@ def parse_symbol(sexp: Any) -> str: class KiCadLibPin: """Pin in a library symbol""" + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.number} @ {self.pos})" @@ -69,6 +70,7 @@ def __init__(self, sexp: List[Any]): class KiCadLibSymbol: """Symbol in a library""" + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.name})" @@ -86,6 +88,7 @@ def __init__(self, sexp: List[Any]): class KiCadWire: + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.pt1}, {self.pt2})" @@ -99,6 +102,7 @@ def __init__(self, sexp: List[Any]): class KiCadTunnel: + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.name} @ {self.pt})" @@ -108,6 +112,7 @@ def __init__(self) -> None: class KiCadBaseLabel(KiCadTunnel): + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.name} @ {self.pt})" @@ -145,6 +150,7 @@ def __init__(self, name: str, pt: PointType): class KiCadMarker: + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.pt})" @@ -161,6 +167,7 @@ def __init__(self, sexp: List[Any]): class KiCadSymbol: + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.refdes}, {self.lib} @ {self.pos})" @@ -186,6 +193,7 @@ def __init__(self, sexp: List[Any]): class KiCadPin: + @override def __repr__(self) -> str: return f"{self.__class__.__name__}({self.refdes}.{self.pin_number} @ {self.pt})" @@ -220,6 +228,7 @@ class ParsedNet(NamedTuple): labels: List[KiCadTunnel] pins: List[KiCadPin] + @override def __repr__(self) -> str: return f"{self.__class__.__name__}(labels={self.labels}, pins={self.pins})" diff --git a/edg/electronics_model/NetlistBackend.py b/edg/electronics_model/NetlistBackend.py index 57e6f86c3..bc4c7843c 100644 --- a/edg/electronics_model/NetlistBackend.py +++ b/edg/electronics_model/NetlistBackend.py @@ -1,5 +1,7 @@ from typing import List, Tuple, Dict +from typing_extensions import override + from .. import edgir from ..core import * from . import footprint as kicad @@ -7,6 +9,7 @@ class NetlistBackend(BaseBackend): + @override def run(self, design: CompiledDesign, args: Dict[str, str] = {}) -> List[Tuple[edgir.LocalPath, str]]: if set(args.keys()) - {'RefdesMode'} != set(): raise ValueError("Invalid argument found in args") diff --git a/edg/electronics_model/NetlistGenerator.py b/edg/electronics_model/NetlistGenerator.py index 28a5ac512..a62a357eb 100644 --- a/edg/electronics_model/NetlistGenerator.py +++ b/edg/electronics_model/NetlistGenerator.py @@ -2,6 +2,8 @@ from itertools import chain from typing import * +from typing_extensions import override + from .. import edgir from ..core import * @@ -247,12 +249,15 @@ def connect_ports(self, scope: BoardScope, elt1: Tuple[TransformUtil.Path, edgir else: raise ValueError(f"can't connect types {elt1}, {elt2}") + @override def visit_block(self, context: TransformUtil.TransformContext, block: edgir.BlockTypes) -> None: self.process_blocklike(context.path, block) + @override def visit_link(self, context: TransformUtil.TransformContext, link: edgir.Link) -> None: self.process_blocklike(context.path, link) + @override def visit_linkarray(self, context: TransformUtil.TransformContext, link: edgir.LinkArray) -> None: self.process_blocklike(context.path, link) diff --git a/edg/electronics_model/PinAssignmentUtil.py b/edg/electronics_model/PinAssignmentUtil.py index 6ece27530..f836f1f32 100644 --- a/edg/electronics_model/PinAssignmentUtil.py +++ b/edg/electronics_model/PinAssignmentUtil.py @@ -2,6 +2,8 @@ from abc import abstractmethod from itertools import chain +from typing_extensions import override + from ..core import * from .VoltagePorts import CircuitPort @@ -50,9 +52,11 @@ def __init__(self, ports: Iterable[Port], pins: Iterable[Union[str, int]]) -> No self.all_ports = list(ports) self.pins = set(str(pin) for pin in pins) + @override def get_assignable_ports(self) -> Iterable[Port]: return self.all_ports + @override def assign(self, port: Port, preassigns: IdentityDict[CircuitPort, PinName], assigned: Set[ConcretePinName]) ->\ Optional[AssignedPins]: assignments: Dict[ConcretePinName, CircuitPort] = {} @@ -91,9 +95,11 @@ def process_assignable_pin(leaf_pins: Union[List[Union[int, str]], int, str]) -> [process_assignable_pin(leaf_pins) for leaf_pins in pin_group] for pin_group in pin_groups ] + @override def get_assignable_ports(self) -> Iterable[Port]: return self.all_ports + @override def assign(self, port: Port, preassigns: IdentityDict[CircuitPort, PinName], assigned: Set[ConcretePinName]) -> \ Optional[AssignedPins]: leaf_name_ports = list(leaf_circuit_ports("", port)) diff --git a/edg/electronics_model/RefdesRefinementPass.py b/edg/electronics_model/RefdesRefinementPass.py index 5eea99f64..9dded55a8 100644 --- a/edg/electronics_model/RefdesRefinementPass.py +++ b/edg/electronics_model/RefdesRefinementPass.py @@ -1,11 +1,14 @@ from typing import List, Tuple, Dict, Set, Optional +from typing_extensions import override + from .. import edgir from ..core import CompiledDesign, TransformUtil from ..core.BaseRefinementPass import BaseRefinementPass class RefdesRefinementPass(BaseRefinementPass): + @override def run(self, design: CompiledDesign) -> List[Tuple[edgir.LocalPath, edgir.ValueLit]]: block_refdes_list = RefdesTransform(design).run() return [(block_path.append_param('fp_refdes').to_local_path(), edgir.lit_to_valuelit(block_refdes)) @@ -30,6 +33,7 @@ def __init__(self, design: CompiledDesign): self.block_refdes_list: List[Tuple[TransformUtil.Path, str]] = [] # populated in traversal order self.refdes_last: Dict[Tuple[TransformUtil.Path, str], int] = {} # (scope, prefix) -> num + @override def visit_block(self, context: TransformUtil.TransformContext, block: edgir.BlockTypes) -> None: scope = self.scopes[context.path] internal_scope = scope diff --git a/edg/electronics_model/SpeakerPort.py b/edg/electronics_model/SpeakerPort.py index 57d4e6e1f..7e237ac70 100644 --- a/edg/electronics_model/SpeakerPort.py +++ b/edg/electronics_model/SpeakerPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .AnalogPort import AnalogSource, AnalogSink @@ -10,6 +12,7 @@ def __init__(self) -> None: self.source = self.Port(SpeakerDriverPort()) self.sink = self.Port(SpeakerPort()) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/SpiPort.py b/edg/electronics_model/SpiPort.py index 945cfcf13..4cf8d5bee 100644 --- a/edg/electronics_model/SpiPort.py +++ b/edg/electronics_model/SpiPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir @@ -18,6 +20,7 @@ def __init__(self) -> None: self.controller = self.Port(SpiController(DigitalBidir.empty())) self.peripherals = self.Port(Vector(SpiPeripheral(DigitalBidir.empty()))) + @override def contents(self) -> None: super().contents() self.sck = self.connect(self.controller.sck, self.peripherals.map_extract(lambda device: device.sck), diff --git a/edg/electronics_model/SvgPcbBackend.py b/edg/electronics_model/SvgPcbBackend.py index 95015fc42..64c879a13 100644 --- a/edg/electronics_model/SvgPcbBackend.py +++ b/edg/electronics_model/SvgPcbBackend.py @@ -3,6 +3,8 @@ import math from typing import List, Tuple, NamedTuple, Dict, Union, Set +from typing_extensions import override + from .. import edgir from .KicadFootprintData import FootprintDataTable from ..core import * @@ -151,6 +153,7 @@ def __init__(self, design: CompiledDesign, netlist: Netlist): self.netlist = netlist self._svgpcb_blocks: List[SvgPcbGeneratedBlock] = [] + @override def visit_block(self, context: TransformUtil.TransformContext, block: edgir.BlockTypes) -> None: # ignore root, bit of a heuristic hack since importing the toplevel script can be brittle if context.path == TransformUtil.Path.empty(): @@ -176,6 +179,7 @@ def run(self) -> List[SvgPcbGeneratedBlock]: class SvgPcbBackend(BaseBackend): + @override def run(self, design: CompiledDesign, args: Dict[str, str] = {}) -> List[Tuple[edgir.LocalPath, str]]: netlist = NetlistTransform(design).run() result = self._generate(design, netlist) diff --git a/edg/electronics_model/UartPort.py b/edg/electronics_model/UartPort.py index a30cae8f6..686b730ef 100644 --- a/edg/electronics_model/UartPort.py +++ b/edg/electronics_model/UartPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalSink, DigitalSource, DigitalBidir @@ -10,6 +12,7 @@ def __init__(self) -> None: self.a = self.Port(UartPort(DigitalBidir.empty())) self.b = self.Port(UartPort(DigitalBidir.empty())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/UsbPort.py b/edg/electronics_model/UsbPort.py index 73b07cec1..815c5087e 100644 --- a/edg/electronics_model/UsbPort.py +++ b/edg/electronics_model/UsbPort.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..core import * from .DigitalPorts import DigitalBidir @@ -11,6 +13,7 @@ def __init__(self) -> None: self.device = self.Port(UsbDevicePort()) self.passive = self.Port(Vector(UsbPassivePort()), optional=True) + @override def contents(self) -> None: super().contents() # TODO write protocol-level signal constraints? @@ -36,6 +39,7 @@ def __init__(self) -> None: self.outer_port = self.Port(UsbDevicePort.empty()) self.inner_link = self.Port(UsbHostPort.empty()) + @override def contents(self) -> None: from .DigitalPorts import DigitalBidirBridge super().contents() @@ -78,6 +82,7 @@ def __init__(self) -> None: self.a = self.Port(UsbCcPort()) self.b = self.Port(UsbCcPort()) + @override def contents(self) -> None: super().contents() # TODO perhaps enable crossover connections as optional layout optimization? diff --git a/edg/electronics_model/VoltagePorts.py b/edg/electronics_model/VoltagePorts.py index 77d33f0f0..fc4c2c178 100644 --- a/edg/electronics_model/VoltagePorts.py +++ b/edg/electronics_model/VoltagePorts.py @@ -1,6 +1,9 @@ from __future__ import annotations from typing import * + +from typing_extensions import override + from ..core import * from .CircuitBlock import CircuitPort, CircuitPortBridge, CircuitLink, CircuitPortAdapter from .GroundPort import GroundLink, GroundReference @@ -38,6 +41,7 @@ def __init__(self) -> None: self.current_drawn = self.Parameter(RangeExpr()) self.current_limits = self.Parameter(RangeExpr()) + @override def contents(self) -> None: super().contents() @@ -70,6 +74,7 @@ def __init__(self) -> None: self.inner_link = self.Port(VoltageSource(current_limits=RangeExpr.ALL, voltage_out=RangeExpr())) + @override def contents(self) -> None: super().contents() @@ -93,6 +98,7 @@ def __init__(self) -> None: self.inner_link = self.Port(VoltageSink(voltage_limits=RangeExpr.ALL, current_draw=RangeExpr())) + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/test_bundle_netlist.py b/edg/electronics_model/test_bundle_netlist.py index 9533479e2..5dad96c43 100644 --- a/edg/electronics_model/test_bundle_netlist.py +++ b/edg/electronics_model/test_bundle_netlist.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + # to avoid re-defining NetBlock, this makes specific imports instead of 'from . import *' from ..core import * from .CircuitBlock import FootprintBlock @@ -18,6 +20,7 @@ def __init__(self) -> None: self.cs_out_1 = self.Port(DigitalSource()) self.cs_out_2 = self.Port(DigitalSource()) + @override def contents(self) -> None: super().contents() self.footprint( # it's anyone's guess why the resistor array is a SPI controller @@ -40,6 +43,7 @@ def __init__(self) -> None: self.spi = self.Port(SpiPeripheral()) self.cs_in = self.Port(DigitalSink()) + @override def contents(self) -> None: super().contents() self.footprint( # it's anyone's guess why this resistor array has a different pinning in peripheral mode @@ -55,6 +59,7 @@ def contents(self) -> None: class TestSpiCircuit(DesignTop): + @override def contents(self) -> None: super().contents() @@ -73,6 +78,7 @@ def __init__(self) -> None: self.port = self.Port(UartPort()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -86,6 +92,7 @@ def contents(self) -> None: class TestUartCircuit(DesignTop): + @override def contents(self) -> None: super().contents() @@ -101,6 +108,7 @@ def __init__(self) -> None: self.port = self.Port(CanDiffPort()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -114,6 +122,7 @@ def contents(self) -> None: class TestCanCircuit(DesignTop): + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/test_multipack_netlist.py b/edg/electronics_model/test_multipack_netlist.py index 6ab9f802c..e990499cb 100644 --- a/edg/electronics_model/test_multipack_netlist.py +++ b/edg/electronics_model/test_multipack_netlist.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from ..core import * from .CircuitPackingBlock import PackedVoltageSource from .test_netlist import TestFakeSource, TestFakeSink, TestBaseFakeSink @@ -19,6 +21,7 @@ def __init__(self) -> None: self.pos = self.PackedExport(self.elements.ports_array(lambda x: x.pos)) self.neg = self.PackedExport(self.elements.ports_array(lambda x: x.neg)) + @override def contents(self) -> None: super().contents() @@ -33,6 +36,7 @@ def contents(self) -> None: class TestPackedDevices(DesignTop): + @override def contents(self) -> None: super().contents() @@ -43,6 +47,7 @@ def contents(self) -> None: self.vpos = self.connect(self.source.pos, self.sink1.pos, self.sink2.pos) self.gnd = self.connect(self.source.neg, self.sink1.neg, self.sink2.neg) + @override def multipack(self) -> None: self.sink = self.PackedBlock(TestPackedSink()) self.pack(self.sink.elements.request('1'), ['sink1']) @@ -50,6 +55,7 @@ def multipack(self) -> None: class TestInvalidPackedDevices(DesignTop): + @override def contents(self) -> None: super().contents() @@ -63,6 +69,7 @@ def contents(self) -> None: self.vpos2 = self.connect(self.source2.pos, self.sink2.pos) self.gnd2 = self.connect(self.source2.neg, self.sink2.neg) + @override def multipack(self) -> None: self.sink = self.PackedBlock(TestPackedSink()) self.pack(self.sink.elements.request('1'), ['sink1']) diff --git a/edg/electronics_model/test_netlist.py b/edg/electronics_model/test_netlist.py index 896d5d189..ffffd9ad0 100644 --- a/edg/electronics_model/test_netlist.py +++ b/edg/electronics_model/test_netlist.py @@ -1,6 +1,8 @@ import unittest from typing import Type, List +from typing_extensions import override + from .. import edgir # to avoid re-defining NetBlock, this makes specific imports instead of 'from . import *' from ..core import * @@ -28,6 +30,7 @@ def __init__(self) -> None: self.pos = self.Port(VoltageSource(), optional=True) self.neg = self.Port(VoltageSource(), optional=True) + @override def contents(self) -> None: super().contents() self.footprint( # beefy (ok, not really) capacitor @@ -50,6 +53,7 @@ def __init__(self) -> None: class TestFakeSink(TestBaseFakeSink, FootprintBlock): + @override def contents(self) -> None: super().contents() self.pos.init_from(VoltageSink()) @@ -65,6 +69,7 @@ def contents(self) -> None: class TestSinglePart(Block): + @override def contents(self) -> None: super().contents() @@ -72,6 +77,7 @@ def contents(self) -> None: class TestBasicCircuit(Block): + @override def contents(self) -> None: super().contents() @@ -83,6 +89,7 @@ def contents(self) -> None: class TestMultisinkCircuit(Block): + @override def contents(self) -> None: super().contents() @@ -102,6 +109,7 @@ def __init__(self) -> None: self.pos_out = self.Port(VoltageSource()) self.neg = self.Port(VoltageSink()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -116,6 +124,7 @@ def contents(self) -> None: class TestMultinetCircuit(Block): + @override def contents(self) -> None: super().contents() @@ -135,6 +144,7 @@ def __init__(self) -> None: self.pos = self.Port(VoltageSink.empty()) self.neg = self.Port(VoltageSink.empty()) + @override def contents(self) -> None: super().contents() @@ -145,6 +155,7 @@ def contents(self) -> None: class TestHierarchyCircuit(Block): + @override def contents(self) -> None: super().contents() @@ -162,6 +173,7 @@ def __init__(self) -> None: self.pos = self.Port(VoltageSink.empty()) self.neg = self.Port(VoltageSink.empty()) + @override def contents(self) -> None: super().contents() @@ -173,6 +185,7 @@ def contents(self) -> None: class TestDualHierarchyCircuit(Block): + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/test_netlist_wrapper.py b/edg/electronics_model/test_netlist_wrapper.py index 383dc41ff..50ab8fbf8 100644 --- a/edg/electronics_model/test_netlist_wrapper.py +++ b/edg/electronics_model/test_netlist_wrapper.py @@ -1,4 +1,7 @@ import unittest + +from typing_extensions import override + from ..core import Block, TransformUtil from .test_netlist import NetlistTestCase, TestFakeSource, TestFakeSink, NetBlock, Net, NetPin from . import WrapperFootprintBlock, VoltageSink @@ -12,6 +15,7 @@ def __init__(self) -> None: self.pos = self.Port(VoltageSink.empty()) self.neg = self.Port(VoltageSink.empty()) + @override def contents(self) -> None: super().contents() @@ -31,6 +35,7 @@ def contents(self) -> None: class TestWrapperCircuit(Block): + @override def contents(self) -> None: super().contents() diff --git a/edg/electronics_model/test_voltage_bridge.py b/edg/electronics_model/test_voltage_bridge.py index fb40a4d89..828804407 100644 --- a/edg/electronics_model/test_voltage_bridge.py +++ b/edg/electronics_model/test_voltage_bridge.py @@ -1,10 +1,13 @@ import unittest +from typing_extensions import override + from ..core import * from .VoltagePorts import VoltageSinkBridge class VoltageBridgeTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = VoltageSinkBridge()._elaborated_def_to_proto() diff --git a/edg/electronics_model/test_voltage_link.py b/edg/electronics_model/test_voltage_link.py index e5d56d779..7cba76232 100644 --- a/edg/electronics_model/test_voltage_link.py +++ b/edg/electronics_model/test_voltage_link.py @@ -1,9 +1,12 @@ import unittest +from typing_extensions import override + from .VoltagePorts import VoltageLink class VoltageLinkTestCase(unittest.TestCase): + @override def setUp(self) -> None: self.pb = VoltageLink()._elaborated_def_to_proto() diff --git a/edg/jlcparts/JlcPartsBase.py b/edg/jlcparts/JlcPartsBase.py index 20a64e51c..e0c62d464 100644 --- a/edg/jlcparts/JlcPartsBase.py +++ b/edg/jlcparts/JlcPartsBase.py @@ -5,6 +5,8 @@ import gzip import os +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcPart import JlcPart @@ -102,6 +104,7 @@ def config_root_dir(root_dir: str) -> None: _cached_table: Optional[PartsTable] = None # set on a per-class basis @classmethod + @override def _make_table(cls) -> PartsTable: """Return the table, cached if possible""" if cls._cached_table is None: @@ -164,9 +167,11 @@ def _parse_table(cls) -> PartsTable: return PartsTable(rows) @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return [not row[cls.BASIC_PART_COL], cls._row_area(row), super()._row_sort_by(row), row[cls.COST_COL]] + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.lcsc_part, row[self.LCSC_COL]) diff --git a/edg/jlcparts/JlcPartsBjt.py b/edg/jlcparts/JlcPartsBjt.py index 5fe5ba887..8120de599 100644 --- a/edg/jlcparts/JlcPartsBjt.py +++ b/edg/jlcparts/JlcPartsBjt.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcBjt import JlcBjt from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -12,6 +15,7 @@ class JlcPartsBjt(PartsTableSelectorFootprint, JlcPartsBase, TableBjt): } @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsBoardTop.py b/edg/jlcparts/JlcPartsBoardTop.py index cf7f0348e..791f2a94c 100644 --- a/edg/jlcparts/JlcPartsBoardTop.py +++ b/edg/jlcparts/JlcPartsBoardTop.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..parts import * from .JlcPartsResistorSmd import JlcPartsResistorSmd @@ -13,6 +15,7 @@ class JlcPartsRefinements(DesignTop): """List of refinements that use JlcParts - mix this into a BoardTop""" + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ diff --git a/edg/jlcparts/JlcPartsDiode.py b/edg/jlcparts/JlcPartsDiode.py index 0ef775578..d9713108f 100644 --- a/edg/jlcparts/JlcPartsDiode.py +++ b/edg/jlcparts/JlcPartsDiode.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcDiode import JlcDiode from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -13,6 +16,7 @@ class JlcPartsDiode(PartsTableSelectorFootprint, JlcPartsBase, TableDiode): ] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: @@ -50,6 +54,7 @@ class JlcPartsZenerDiode(TableZenerDiode, PartsTableSelectorFootprint, JlcPartsB _JLC_PARTS_FILE_NAMES = ["DiodesZener_Diodes"] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsElectrolyticCapacitor.py b/edg/jlcparts/JlcPartsElectrolyticCapacitor.py index e6a805420..83e849475 100644 --- a/edg/jlcparts/JlcPartsElectrolyticCapacitor.py +++ b/edg/jlcparts/JlcPartsElectrolyticCapacitor.py @@ -1,5 +1,8 @@ from typing import Any, Optional, Dict import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -9,6 +12,7 @@ class JlcPartsElectrolyticCapacitor(PartsTableSelectorFootprint, JlcPartsBase, T _PACKAGE_PARSER = re.compile(r"^SMD,D([\d.]+)xL([\d.]+)mm$") @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: diff --git a/edg/jlcparts/JlcPartsFerriteBead.py b/edg/jlcparts/JlcPartsFerriteBead.py index 38f094de5..d671caea0 100644 --- a/edg/jlcparts/JlcPartsFerriteBead.py +++ b/edg/jlcparts/JlcPartsFerriteBead.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcFerriteBead import JlcFerriteBead from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -8,6 +11,7 @@ class JlcPartsFerriteBead(PartsTableSelectorFootprint, JlcPartsBase, TableFerrit _JLC_PARTS_FILE_NAMES = ["FiltersakaEMI_OptimizationFerrite_Beads"] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsFet.py b/edg/jlcparts/JlcPartsFet.py index b5eb67f7e..6971c6caf 100644 --- a/edg/jlcparts/JlcPartsFet.py +++ b/edg/jlcparts/JlcPartsFet.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcFet import JlcFet from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -15,6 +18,7 @@ class JlcPartsBaseFet(JlcPartsBase, BaseTableFet): } @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsInductor.py b/edg/jlcparts/JlcPartsInductor.py index d970a7609..e91151743 100644 --- a/edg/jlcparts/JlcPartsInductor.py +++ b/edg/jlcparts/JlcPartsInductor.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcInductor import JlcInductor from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -13,6 +16,7 @@ class JlcPartsInductor(PartsTableSelectorFootprint, JlcPartsBase, TableInductor) ] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsLed.py b/edg/jlcparts/JlcPartsLed.py index 5d2f264bc..c889b9acc 100644 --- a/edg/jlcparts/JlcPartsLed.py +++ b/edg/jlcparts/JlcPartsLed.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcLed import JlcLed from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -28,6 +31,7 @@ class JlcPartsLed(PartsTableSelectorFootprint, JlcPartsBase, TableLed): } @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsMlcc.py b/edg/jlcparts/JlcPartsMlcc.py index 4022bd96d..50618f42c 100644 --- a/edg/jlcparts/JlcPartsMlcc.py +++ b/edg/jlcparts/JlcPartsMlcc.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcCapacitor import JlcCapacitor, JlcDummyCapacitor from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -13,6 +16,7 @@ def __init__(self, *args: Any, capacitance_minimum_size: BoolLike = True, **kwar self.generator_param(self.capacitance_minimum_size) @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: @@ -37,6 +41,7 @@ def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: st except (KeyError, TypeError, PartParserUtil.ParseError): return None + @override def _table_postprocess(self, table: PartsTable) -> PartsTable: # TODO deduplicate w/ JlcCapacitor def filter_minimum_size(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: @@ -59,9 +64,11 @@ def filter_minimum_size(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, A return table @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return [row[cls.PARALLEL_COUNT], super(JlcPartsMlcc, cls)._row_sort_by(row)] + @override def _row_generate(self, row: PartsTableRow) -> None: # see comment in TableCapacitor._row_generate for why this needs to be here if row[self.PARALLEL_COUNT] == 1: @@ -71,6 +78,7 @@ def _row_generate(self, row: PartsTableRow) -> None: self.assign(self.actual_basic_part, True) # dummy value self._make_parallel_footprints(row) + @override def _make_parallel_footprints(self, row: PartsTableRow) -> None: cap_model = JlcDummyCapacitor(set_lcsc_part=row[self.LCSC_COL], set_basic_part=row[self.BASIC_PART_COL], diff --git a/edg/jlcparts/JlcPartsPptcFuse.py b/edg/jlcparts/JlcPartsPptcFuse.py index 405c20ed4..aa27d3e87 100644 --- a/edg/jlcparts/JlcPartsPptcFuse.py +++ b/edg/jlcparts/JlcPartsPptcFuse.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcPptcFuse import JlcPptcFuse from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -8,6 +11,7 @@ class JlcPartsPptcFuse(PartsTableSelectorFootprint, JlcPartsBase, TableFuse, Ppt _JLC_PARTS_FILE_NAMES = ["Circuit_ProtectionResettable_Fuses"] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/jlcparts/JlcPartsResistorSmd.py b/edg/jlcparts/JlcPartsResistorSmd.py index 1f22e6061..d9968e147 100644 --- a/edg/jlcparts/JlcPartsResistorSmd.py +++ b/edg/jlcparts/JlcPartsResistorSmd.py @@ -1,4 +1,7 @@ from typing import Any, Optional, Dict + +from typing_extensions import override + from ..abstract_parts import * from ..parts.JlcResistor import JlcResistor from .JlcPartsBase import JlcPartsBase, JlcPartsAttributes @@ -8,6 +11,7 @@ class JlcPartsResistorSmd(PartsTableSelectorFootprint, JlcPartsBase, TableResist _JLC_PARTS_FILE_NAMES = ["ResistorsChip_Resistor___Surface_Mount"] @classmethod + @override def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: str, package: str, attributes: JlcPartsAttributes) \ -> Optional[Dict[PartsTableColumn, Any]]: try: diff --git a/edg/parts/AdcSpi_Mcp3201.py b/edg/parts/AdcSpi_Mcp3201.py index 3c35373b1..615fe3a80 100644 --- a/edg/parts/AdcSpi_Mcp3201.py +++ b/edg/parts/AdcSpi_Mcp3201.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -29,6 +31,7 @@ def __init__(self) -> None: self.spi = self.Port(SpiPeripheral(dio_model, frequency_limit=(10, 1600) * kHertz)) self.cs = self.Port(dio_model) + @override def contents(self) -> None: # Note, B-grade chip has lower INL (+/-1 LSB) compared to C-grade (+/-2 LSB) self.footprint( @@ -68,6 +71,7 @@ def __init__(self) -> None: self.spi = self.Export(self.ic.spi, [Output]) self.cs = self.Export(self.ic.cs) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/AdcSpi_Mcp3561.py b/edg/parts/AdcSpi_Mcp3561.py index 7b8c50e1e..35d90e4b0 100644 --- a/edg/parts/AdcSpi_Mcp3561.py +++ b/edg/parts/AdcSpi_Mcp3561.py @@ -1,5 +1,7 @@ from typing import Optional +from typing_extensions import override + from ..abstract_parts import * @@ -43,6 +45,7 @@ def __init__(self, has_ext_ref: BoolLike) -> None: self.has_ext_ref = self.ArgParameter(has_ext_ref) self.generator_param(self.ch.requested(), self.vrefp.is_connected(), self.has_ext_ref) + @override def generate(self) -> None: ch_requested = self.get(self.ch.requested()) CHANNEL_USE_MAPPINGS = [ @@ -114,6 +117,7 @@ def __init__(self) -> None: self.spi = self.Export(self.ic.spi, [Output]) self.cs = self.Export(self.ic.cs) + @override def contents(self) -> None: super().contents() @@ -135,6 +139,7 @@ def contents(self) -> None: # technically optional, but accuracy potentially degraded if omitted self.vref_cap = imp.Block(DecouplingCapacitor(10*uFarad(tol=0.2))).connected(pwr=self.ic.vrefp) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/AnalogSwitch_7400.py b/edg/parts/AnalogSwitch_7400.py index 938351849..76e9d066b 100644 --- a/edg/parts/AnalogSwitch_7400.py +++ b/edg/parts/AnalogSwitch_7400.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -29,6 +31,7 @@ def __init__(self) -> None: self.b1 = self.Port(Passive(), optional=True) self.b0 = self.Port(Passive(), optional=True) + @override def contents(self) -> None: super().contents() @@ -52,6 +55,7 @@ def contents(self) -> None: class Sn74lvc1g3157(AnalogSwitch): """2:1 analog switch, 6ohm Ron(typ), in SOT-363. """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/AnalogSwitch_Dg468.py b/edg/parts/AnalogSwitch_Dg468.py index 9beab7765..53e3f55d2 100644 --- a/edg/parts/AnalogSwitch_Dg468.py +++ b/edg/parts/AnalogSwitch_Dg468.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -28,6 +30,7 @@ def __init__(self) -> None: self.com = self.Port(Passive()) self.no = self.Port(Passive(), optional=True) + @override def contents(self) -> None: super().contents() @@ -55,6 +58,7 @@ def __init__(self) -> None: super().__init__() self.generator_param(self.control_gnd.is_connected()) + @override def contents(self) -> None: super().contents() @@ -74,6 +78,7 @@ def contents(self) -> None: capacitance=0.1*uFarad(tol=0.2), )).connected(self.gnd, self.pwr) + @override def generate(self) -> None: super().generate() if self.get(self.control_gnd.is_connected()): diff --git a/edg/parts/AnalogSwitch_Nlas4157.py b/edg/parts/AnalogSwitch_Nlas4157.py index 4be0aa4bd..c4f7e042c 100644 --- a/edg/parts/AnalogSwitch_Nlas4157.py +++ b/edg/parts/AnalogSwitch_Nlas4157.py @@ -1,4 +1,5 @@ from deprecated import deprecated +from typing_extensions import override from ..abstract_parts import * from .JlcPart import JlcPart @@ -31,6 +32,7 @@ def __init__(self) -> None: self.b1 = self.Port(Passive(), optional=True) self.b0 = self.Port(Passive(), optional=True) + @override def contents(self) -> None: super().contents() @@ -58,6 +60,7 @@ class Nlas4157(AnalogSwitch): - TS5A3159: 5v tolerant, 1 ohm - TS5A3160: 5v tolerant, 1 ohm """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Batteries.py b/edg/parts/Batteries.py index b22f425a7..ec7bdc620 100644 --- a/edg/parts/Batteries.py +++ b/edg/parts/Batteries.py @@ -1,5 +1,7 @@ from typing import Optional, Union, Any +from typing_extensions import override + from ..abstract_parts import * @@ -13,6 +15,7 @@ def __init__(self, voltage: RangeLike = (2.0, 3.0)*Volt, *args: Any, )) self.gnd.init_from(Ground()) + @override def contents(self) -> None: super().contents() @@ -38,6 +41,7 @@ def __init__(self, voltage: RangeLike = (2.5, 4.2)*Volt, *args: Any, )) self.gnd.init_from(Ground()) + @override def contents(self) -> None: super().contents() @@ -64,6 +68,7 @@ def __init__(self, voltage: RangeLike = (1.0, 1.6)*Volt, *args: Any, current_limits=(0, 1)*Amp, )) + @override def contents(self) -> None: super().contents() @@ -87,6 +92,7 @@ def __init__(self, count: IntLike = 1, *, cell_actual_voltage: RangeLike = (1.0, self.cell_actual_voltage = self.ArgParameter(cell_actual_voltage) self.generator_param(self.count) + @override def generate(self) -> None: super().generate() prev_cell: Optional[AaBattery] = None diff --git a/edg/parts/BatteryCharger_Mcp73831.py b/edg/parts/BatteryCharger_Mcp73831.py index c32c294a5..b14013326 100644 --- a/edg/parts/BatteryCharger_Mcp73831.py +++ b/edg/parts/BatteryCharger_Mcp73831.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -24,6 +26,7 @@ def __init__(self, actual_charging_current: RangeLike) -> None: )) self.prog = self.Port(Passive()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -56,6 +59,7 @@ def __init__(self, charging_current: RangeLike) -> None: self.charging_current = self.ArgParameter(charging_current) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BatteryProtector_S8261A.py b/edg/parts/BatteryProtector_S8261A.py index 2771a2dd7..13b7c3a02 100644 --- a/edg/parts/BatteryProtector_S8261A.py +++ b/edg/parts/BatteryProtector_S8261A.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -18,6 +20,7 @@ def __init__(self) -> None: self.co = self.Port(Passive()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -62,6 +65,7 @@ def __init__(self) -> None: drain_voltage=self.pwr_in.link().voltage )) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Bldc_Drv8313.py b/edg/parts/Bldc_Drv8313.py index ab028c314..37522ed05 100644 --- a/edg/parts/Bldc_Drv8313.py +++ b/edg/parts/Bldc_Drv8313.py @@ -1,6 +1,8 @@ import functools from typing import Optional +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -36,6 +38,7 @@ def __init__(self) -> None: self.cpl = self.Port(Passive()) # connect Vm rated, 0.01uF ceramic capacitor self.cph = self.Port(Passive()) + @override def contents(self) -> None: out_model = DigitalSource.from_supply( self.gnd, self.vm, @@ -119,6 +122,7 @@ def __init__(self, *, risense_res: RangeLike = 100*mOhm(tol=0.05)) -> None: self.risense_res = self.ArgParameter(risense_res) self.generator_param(self.pgnd_sense.requested()) + @override def contents(self) -> None: super().contents() self.vm_cap_bulk = self.Block(DecouplingCapacitor((10*0.8, 100)*uFarad)).connected(self.gnd, self.ic.vm) @@ -140,6 +144,7 @@ def contents(self) -> None: self.nsleep_default = self.Block(DigitalSourceConnected()) \ .out_with_default(self.ic.nsleep, self.nsleep, self.ic.v3p3.as_digital_source()) + @override def generate(self) -> None: super().generate() pgnd_requested = self.get(self.pgnd_sense.requested()) diff --git a/edg/parts/BoostConverter_AnalogDevices.py b/edg/parts/BoostConverter_AnalogDevices.py index 2ccda2dc7..1e4013d43 100644 --- a/edg/parts/BoostConverter_AnalogDevices.py +++ b/edg/parts/BoostConverter_AnalogDevices.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -22,6 +24,7 @@ def __init__(self, output_voltage: RangeLike): input_thresholds=(0.35, 1)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -45,6 +48,7 @@ class Ltc3429(VoltageRegulatorEnableWrapper, DiscreteBoostConverter): """Low-input-voltage boost converter (starts as low as 0.85V). Pin-compatible with the less-expensive UM3429S""" NMOS_CURRENT_LIMIT = 0.6 + @override def contents(self) -> None: super().contents() @@ -76,5 +80,6 @@ def contents(self) -> None: self.connect(self.power_path.pwr_out, self.pwr_out) self.connect(self.power_path.switch, self.ic.sw) + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.nshdn diff --git a/edg/parts/BoostConverter_DiodesInc.py b/edg/parts/BoostConverter_DiodesInc.py index 1f663917d..fa1aa594f 100644 --- a/edg/parts/BoostConverter_DiodesInc.py +++ b/edg/parts/BoostConverter_DiodesInc.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -19,6 +21,7 @@ def __init__(self) -> None: input_thresholds=(0.4, 1.5)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -39,9 +42,11 @@ def contents(self) -> None: class Ap3012(VoltageRegulatorEnableWrapper, DiscreteBoostConverter): """Adjustable boost converter in SOT-23-5 with integrated switch""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.nshdn + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BoostConverter_TexasInstruments.py b/edg/parts/BoostConverter_TexasInstruments.py index 77f8afb6b..85d797089 100644 --- a/edg/parts/BoostConverter_TexasInstruments.py +++ b/edg/parts/BoostConverter_TexasInstruments.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self) -> None: input_threshold_abs=(0.4, 1.3)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -41,9 +44,11 @@ def contents(self) -> None: class Tps61040(VoltageRegulatorEnableWrapper, DiscreteBoostConverter): """PFM (DCM, discontinuous mode) boost converter in SOT-23-5""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() @@ -174,6 +179,7 @@ def __init__(self) -> None: input_threshold_abs=(0.5, 1.5)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -194,9 +200,11 @@ def contents(self) -> None: class Lm2733(VoltageRegulatorEnableWrapper, DiscreteBoostConverter): """Adjustable boost converter in SOT-23-5 with integrated switch""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.nshdn + @override def contents(self) -> None: import math super().contents() diff --git a/edg/parts/BoostConverter_Torex.py b/edg/parts/BoostConverter_Torex.py index 8b006010d..b997b03dd 100644 --- a/edg/parts/BoostConverter_Torex.py +++ b/edg/parts/BoostConverter_Torex.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -38,6 +40,7 @@ def __init__(self, output_voltage: RangeLike, frequency: RangeLike = Range.all() self.actual_current_limit = self.Parameter(RangeExpr()) # set by part number self.actual_frequency = self.Parameter(RangeExpr()) # set by part number + @override def generate(self) -> None: super().generate() @@ -73,6 +76,7 @@ class Xc9142(Resettable, DiscreteBoostConverter, GeneratorBlock): """Low-input-voltage boost converter (starts as low as 0.9V) with fixed output. XC9142 has PWM/PFM functionality, compared to PWM only for XC9141. Semi pin compatible with XC9140, LTC3525, MAX1724.""" + @override def contents(self) -> None: super().contents() self.generator_param(self.reset.is_connected()) @@ -94,6 +98,7 @@ def contents(self) -> None: self.connect(self.power_path.pwr_out, self.pwr_out) self.connect(self.power_path.switch, self.ic.sw) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): diff --git a/edg/parts/BootstrapVoltageAdder.py b/edg/parts/BootstrapVoltageAdder.py index 4001ccfa1..392d7e549 100644 --- a/edg/parts/BootstrapVoltageAdder.py +++ b/edg/parts/BootstrapVoltageAdder.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -19,6 +21,7 @@ def __init__(self, frequency: RangeLike = 250*kHertz(tol=0), ripple_limit: Float self.frequency = self.ArgParameter(frequency) self.ripple_limit = self.ArgParameter(ripple_limit) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BuckBoostConverter_Custom.py b/edg/parts/BuckBoostConverter_Custom.py index c3351e396..735777441 100644 --- a/edg/parts/BuckBoostConverter_Custom.py +++ b/edg/parts/BuckBoostConverter_Custom.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * @@ -50,6 +52,7 @@ def __init__(self, *args: Any, self.ripple_ratio = self.ArgParameter(ripple_ratio) self.rds_on = self.ArgParameter(rds_on) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BuckConverter_Ap3418.py b/edg/parts/BuckConverter_Ap3418.py index 4a43ef7f6..10bf6ca96 100644 --- a/edg/parts/BuckConverter_Ap3418.py +++ b/edg/parts/BuckConverter_Ap3418.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -18,6 +20,7 @@ def __init__(self) -> None: input_threshold_abs=(0.4, 1.5)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -38,9 +41,11 @@ def contents(self) -> None: class Ap3418(VoltageRegulatorEnableWrapper, DiscreteBuckConverter): """Adjustable synchronous buck converter in SOT-23-5 with integrated switch""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BuckConverter_Custom.py b/edg/parts/BuckConverter_Custom.py index 9788669d5..2803d85ec 100644 --- a/edg/parts/BuckConverter_Custom.py +++ b/edg/parts/BuckConverter_Custom.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * @@ -22,6 +24,7 @@ def __init__(self, *args: Any, self.voltage_drop = self.ArgParameter(voltage_drop) self.rds_on = self.ArgParameter(rds_on) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BuckConverter_Mps.py b/edg/parts/BuckConverter_Mps.py index 6e4d92410..902280340 100644 --- a/edg/parts/BuckConverter_Mps.py +++ b/edg/parts/BuckConverter_Mps.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -58,6 +60,7 @@ def __init__(self, charging_current: RangeLike): self.cc = self.Port(UsbCcPort(), optional=True) self.usb = self.Port(UsbDevicePort(), optional=True) # BC protocol only + @override def contents(self) -> None: super().contents() self.require(self.vin.current_draw.within((0, 3.2)*Amp), "Iin max limit") @@ -128,6 +131,7 @@ def __init__(self, *args: Any, frequency: RangeLike = (900, 1280)*kHertz, self.frequency = self.ArgParameter(frequency) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/BuckConverter_TexasInstruments.py b/edg/parts/BuckConverter_TexasInstruments.py index cfd86bda8..a7b8eda6b 100644 --- a/edg/parts/BuckConverter_TexasInstruments.py +++ b/edg/parts/BuckConverter_TexasInstruments.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -18,6 +20,7 @@ def __init__(self) -> None: input_thresholds=(0.8, 1.6)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -39,9 +42,11 @@ def contents(self) -> None: class Tps561201(VoltageRegulatorEnableWrapper, DiscreteBuckConverter): """Adjustable synchronous buck converter in SOT-23-6 with integrated switch""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() @@ -100,6 +105,7 @@ def __init__(self) -> None: input_thresholds=(1.16, 1.35)*Volt )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -124,6 +130,7 @@ class Tps54202h(Resettable, DiscreteBuckConverter, GeneratorBlock): Note: TPS54202 has frequency spread-spectrum operation and internal pull-up on EN TPS54202H has no internal EN pull-up but a Zener diode clamp to limit voltage. """ + @override def contents(self) -> None: super().contents() self.generator_param(self.reset.is_connected()) @@ -163,6 +170,7 @@ def contents(self) -> None: self.pwr_out) self.connect(self.power_path.switch, self.ic.sw) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): diff --git a/edg/parts/Camera_Ov2640_Fpc24.py b/edg/parts/Camera_Ov2640_Fpc24.py index c507bd17f..9b12bf7b7 100644 --- a/edg/parts/Camera_Ov2640_Fpc24.py +++ b/edg/parts/Camera_Ov2640_Fpc24.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom @@ -88,6 +90,7 @@ def __init__(self) -> None: super().__init__() self.generator_param(self.pwdn.is_connected(), self.reset.is_connected()) + @override def contents(self) -> None: super().contents() self.dovdd_cap = self.Block(DecouplingCapacitor(capacitance=0.1*uFarad(tol=0.2)))\ @@ -112,6 +115,7 @@ def contents(self) -> None: self.connect(self.dvp8.y6, self.device.y.request('8')) self.connect(self.dvp8.y7, self.device.y.request('9')) + @override def generate(self) -> None: super().generate() if self.get(self.pwdn.is_connected()): diff --git a/edg/parts/CanBlocks.py b/edg/parts/CanBlocks.py index 5c8dc57b7..b4d7d5f63 100644 --- a/edg/parts/CanBlocks.py +++ b/edg/parts/CanBlocks.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -8,6 +10,7 @@ def __init__(self) -> None: self.gnd.init_from(Ground()) self.can.init_from(CanDiffPort()) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/CanTransceiver_Iso1050.py b/edg/parts/CanTransceiver_Iso1050.py index 209d40565..1ea5debcb 100644 --- a/edg/parts/CanTransceiver_Iso1050.py +++ b/edg/parts/CanTransceiver_Iso1050.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -28,6 +30,7 @@ def __init__(self) -> None: current_draw=(-4, 4) * mAmp, current_limits=(-70, 70) * mAmp ))) + @override def contents(self) -> None: super().contents() self.footprint( @@ -49,6 +52,7 @@ def contents(self) -> None: class Iso1050dub(IsolatedCanTransceiver): + @override def contents(self) -> None: super().contents() self.ic = self.Block(Iso1050dub_Device()) diff --git a/edg/parts/CanTransceiver_Sn65hvd230.py b/edg/parts/CanTransceiver_Sn65hvd230.py index 74453fdc2..bb5745f83 100644 --- a/edg/parts/CanTransceiver_Sn65hvd230.py +++ b/edg/parts/CanTransceiver_Sn65hvd230.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -24,6 +26,7 @@ def __init__(self) -> None: current_draw=(-30, 30) * uAmp, current_limits=(-250, 250) * mAmp ))) + @override def contents(self) -> None: super().contents() self.footprint( @@ -46,6 +49,7 @@ def contents(self) -> None: class Sn65hvd230(CanTransceiver): + @override def contents(self) -> None: super().contents() self.ic = self.Block(Sn65hvd230_Device()) diff --git a/edg/parts/CeramicResonator_Cstne.py b/edg/parts/CeramicResonator_Cstne.py index 906cc1d47..0974086ee 100644 --- a/edg/parts/CeramicResonator_Cstne.py +++ b/edg/parts/CeramicResonator_Cstne.py @@ -1,13 +1,17 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart class Cstne(CeramicResonator, GeneratorBlock, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() self.gnd.init_from(Ground()) self.generator_param(self.frequency) + @override def generate(self) -> None: super().generate() parts = [ # tolerance is total stackup: initial temperature, aging diff --git a/edg/parts/Comparator_Lmv331.py b/edg/parts/Comparator_Lmv331.py index 4cb215824..e589f190e 100644 --- a/edg/parts/Comparator_Lmv331.py +++ b/edg/parts/Comparator_Lmv331.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self) -> None: out_model = DigitalSource.low_from_supply(self.gnd) self.out = self.Port(out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -40,6 +43,7 @@ def contents(self) -> None: class Lmv331(Comparator): """General purpose comparator""" + @override def contents(self) -> None: super().contents() self.ic = self.Block(Lmv331_Device()) diff --git a/edg/parts/Connector_Banana.py b/edg/parts/Connector_Banana.py index bb95317b6..58341228e 100644 --- a/edg/parts/Connector_Banana.py +++ b/edg/parts/Connector_Banana.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -7,6 +9,7 @@ class Ct3151(BananaSafetyJack, FootprintBlock): TODO: automatically support color code generation? """ + @override def contents(self) -> None: super().contents() self.footprint( @@ -26,6 +29,7 @@ class Fcr7350(BananaSafetyJack, FootprintBlock): TODO: automatically support color code generation? """ + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Connector_Rf.py b/edg/parts/Connector_Rf.py index 4af93c49b..e43b7656b 100644 --- a/edg/parts/Connector_Rf.py +++ b/edg/parts/Connector_Rf.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart class Bwipx_1_001e(RfConnectorTestPoint, UflConnector, JlcPart, FootprintBlock): """BAT WIRELESS IPEX connector""" + @override def contents(self) -> None: super().contents() self.footprint( @@ -22,6 +25,7 @@ def contents(self) -> None: class Amphenol901143(SmaFConnector, FootprintBlock): """PTH right-angle SMA-F connector""" + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Connectors.py b/edg/parts/Connectors.py index 54797c944..f9ca26ab2 100644 --- a/edg/parts/Connectors.py +++ b/edg/parts/Connectors.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Header import JstShSmHorizontal @@ -18,6 +20,7 @@ def __init__(self, class Pj_102ah(PowerBarrelJack, FootprintBlock): """Barrel jack for 2.1mm ID and 5.5mm OD""" + @override def contents(self) -> None: super().contents() self.require(self.pwr.voltage_out.within((0, 24)*Volt)) # datasheet ratings for connector @@ -36,6 +39,7 @@ def contents(self) -> None: class Pj_036ah(PowerBarrelJack, FootprintBlock): """SMT Barrel jack for 2.1mm ID and 5.5mm OD""" + @override def contents(self) -> None: super().contents() self.require(self.pwr.voltage_out.within((0, 24)*Volt)) # datasheet ratings for connector diff --git a/edg/parts/CurrentSense_Ad8418.py b/edg/parts/CurrentSense_Ad8418.py index 02d027fce..80cbeabe5 100644 --- a/edg/parts/CurrentSense_Ad8418.py +++ b/edg/parts/CurrentSense_Ad8418.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -33,6 +35,7 @@ def __init__(self, in_diff_range: RangeLike): impedance=2*Ohm(tol=0) # range not specified )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -55,6 +58,7 @@ def contents(self) -> None: class Ad8418a(CurrentSensor, KiCadImportableBlock, Block): + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:DifferentialAmplifier' return { @@ -75,6 +79,7 @@ def __init__(self, in_diff_range: RangeLike): self.ref = self.Export(self.amp.vref1) # TODO optional for grounded unidirectional self.out = self.Export(self.amp.out) + @override def contents(self) -> None: super().contents() self.connect(self.ref, self.amp.vref2) diff --git a/edg/parts/DacI2c_Mcp4728.py b/edg/parts/DacI2c_Mcp4728.py index 2086068a8..f61efe9fb 100644 --- a/edg/parts/DacI2c_Mcp4728.py +++ b/edg/parts/DacI2c_Mcp4728.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -31,6 +33,7 @@ def __init__(self) -> None: self.generator_param(self.ldac.is_connected()) + @override def generate(self) -> None: super().generate() @@ -84,6 +87,7 @@ def __init__(self, output_caps: BoolLike = True) -> None: self.generator_param(self.output_caps, self.out0.is_connected(), self.out1.is_connected(), self.out2.is_connected(), self.out3.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/DacI2c_Mcp47f.py b/edg/parts/DacI2c_Mcp47f.py index 0aa8429c4..dde950528 100644 --- a/edg/parts/DacI2c_Mcp47f.py +++ b/edg/parts/DacI2c_Mcp47f.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -45,6 +47,7 @@ def __init__(self, addr_lsb: IntLike) -> None: self.addr_lsb = self.ArgParameter(addr_lsb) self.generator_param(self.addr_lsb) + @override def generate(self) -> None: super().generate() @@ -99,6 +102,7 @@ def __init__(self, addr_lsb: IntLike = 0) -> None: self.lat0 = self.Export(self.ic.lat0) self.lat1 = self.Export(self.ic.lat1) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/DacSpi_Mcp4901.py b/edg/parts/DacSpi_Mcp4901.py index 2ba2c9af0..150b65c5b 100644 --- a/edg/parts/DacSpi_Mcp4901.py +++ b/edg/parts/DacSpi_Mcp4901.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -29,6 +31,7 @@ def __init__(self) -> None: self.spi = self.Port(SpiPeripheral(dio_model, frequency_limit=(0, 20) * MHertz)) self.cs = self.Port(dio_model) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', @@ -65,6 +68,7 @@ def __init__(self) -> None: self.cs = self.Export(self.ic.cs) self.ldac = self.Export(self.ic.ldac) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/DebugHeaders.py b/edg/parts/DebugHeaders.py index c2733e280..887b7f76e 100644 --- a/edg/parts/DebugHeaders.py +++ b/edg/parts/DebugHeaders.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Header import PinHeader127DualShrouded from .PassiveConnector_TagConnect import TagConnect @@ -5,6 +7,7 @@ class SwdCortexTargetHeader(SwdCortexTargetConnector, SwdCortexTargetConnectorReset, SwdCortexTargetConnectorSwo, SwdCortexTargetConnectorTdi): + @override def contents(self) -> None: super().contents() self.conn = self.Block(PinHeader127DualShrouded(10)) @@ -23,6 +26,7 @@ def contents(self) -> None: class SwdCortexTargetTagConnect(SwdCortexTargetConnector, SwdCortexTargetConnectorReset, SwdCortexTargetConnectorSwo): """OFFICIAL tag connect SWD header using the TC2030 series cables. https://www.tag-connect.com/wp-content/uploads/bsk-pdf-manager/TC2030-CTX_1.pdf""" + @override def contents(self) -> None: super().contents() self.conn = self.Block(TagConnect(6)) @@ -38,6 +42,7 @@ def contents(self) -> None: class SwdCortexTargetTc2050(SwdCortexTargetConnector, SwdCortexTargetConnectorReset, SwdCortexTargetConnectorSwo, SwdCortexTargetConnectorTdi): """UNOFFICIAL tag connect SWD header, maintaining physical pin compatibility with the 2x05 1.27mm header.""" + @override def contents(self) -> None: super().contents() self.conn = self.Block(TagConnect(10)) diff --git a/edg/parts/DirectionSwitch_Alps.py b/edg/parts/DirectionSwitch_Alps.py index 12f4d1da0..440caa559 100644 --- a/edg/parts/DirectionSwitch_Alps.py +++ b/edg/parts/DirectionSwitch_Alps.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -5,6 +7,7 @@ class Skrh(DirectionSwitchCenter, DirectionSwitch, JlcPart, FootprintBlock): """Generic SKRH directional switch with pushbutton. Default part is SKRHABE010, but footprint should be compatible with the entire SKRH series.""" + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Distance_Vl53l0x.py b/edg/parts/Distance_Vl53l0x.py index f48df0ad2..4a43b1914 100644 --- a/edg/parts/Distance_Vl53l0x.py +++ b/edg/parts/Distance_Vl53l0x.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -28,6 +30,7 @@ def __init__(self) -> None: input_threshold_abs=(0.6, 1.12), )), [Output]) + @override def contents(self) -> None: super().contents() self.footprint( @@ -67,6 +70,7 @@ def __init__(self) -> None: doc="Interrupt output for new data available") self.generator_param(self.reset.is_connected(), self.int.is_connected()) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): @@ -89,6 +93,7 @@ class Vl53l0xConnector(Vl53l0x, WrapperFootprintBlock): This has an onboard 2.8v regulator, but thankfully the IO tolerance is not referenced to Vdd TODO: not completely correct that this should extend the application circuit""" + @override def generate(self) -> None: super().generate() self.footprint( @@ -119,6 +124,7 @@ def __init__(self, count: IntLike, *, first_reset_fixed: BoolLike = False): self.first_reset_fixed = self.ArgParameter(first_reset_fixed) self.generator_param(self.count, self.first_reset_fixed) + @override def generate(self) -> None: super().generate() self.elt = ElementDict[Vl53l0x]() diff --git a/edg/parts/EInkBoostPowerPath.py b/edg/parts/EInkBoostPowerPath.py index 164c385f4..24ec74a0e 100644 --- a/edg/parts/EInkBoostPowerPath.py +++ b/edg/parts/EInkBoostPowerPath.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -25,6 +27,7 @@ def __init__(self, voltage_out: RangeLike, current: RangeLike, inductance: Range self.resistance = self.ArgParameter(resistance) self.diode_voltage_drop = self.ArgParameter(diode_voltage_drop) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/EInk_E2154fs091.py b/edg/parts/EInk_E2154fs091.py index 98c8e559d..08befc1ee 100644 --- a/edg/parts/EInk_E2154fs091.py +++ b/edg/parts/EInk_E2154fs091.py @@ -1,4 +1,7 @@ from typing import * + +from typing_extensions import override + from ..abstract_parts import * @@ -39,6 +42,7 @@ def __init__(self) -> None: self.vgl = self.Port(Passive()) self.vcom = self.Port(Passive()) + @override def contents(self) -> None: super().contents() @@ -95,6 +99,7 @@ def __init__(self) -> None: self.cs = self.Export(self.ic.cs) self.spi = self.Export(self.ic.spi) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/EInk_Er_Epd027_2.py b/edg/parts/EInk_Er_Epd027_2.py index dfe19222c..d6972036f 100644 --- a/edg/parts/EInk_Er_Epd027_2.py +++ b/edg/parts/EInk_Er_Epd027_2.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom from .EInkBoostPowerPath import EInkBoostPowerPath class Er_Epd027_2_Outline(InternalSubcircuit, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Epd027_2_Outline', {}, @@ -95,6 +98,7 @@ def __init__(self) -> None: self.generator_param(self.dc.is_connected()) + @override def contents(self) -> None: super().contents() @@ -126,6 +130,7 @@ def contents(self) -> None: self.connect(self.boost.pos_out, self.device.vgh) self.connect(self.boost.neg_out, self.device.vgl) + @override def generate(self) -> None: super().generate() if self.get(self.dc.is_connected()): # 4-line serial, BS low diff --git a/edg/parts/EInk_WaveshareDriver.py b/edg/parts/EInk_WaveshareDriver.py index 14593743b..3fb2527fb 100644 --- a/edg/parts/EInk_WaveshareDriver.py +++ b/edg/parts/EInk_WaveshareDriver.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom from .EInkBoostPowerPath import EInkBoostPowerPath @@ -91,6 +93,7 @@ def __init__(self) -> None: self.generator_param(self.dc.is_connected()) + @override def contents(self) -> None: super().contents() @@ -125,6 +128,7 @@ def contents(self) -> None: self.connect(self.boost.pos_out, self.device.prevgh) self.connect(self.boost.neg_out, self.device.prevgl) + @override def generate(self) -> None: super().generate() if self.get(self.dc.is_connected()): # 4-line serial, BS low diff --git a/edg/parts/EnvironmentalSensor_Bme680.py b/edg/parts/EnvironmentalSensor_Bme680.py index 422960cb4..f079b69b6 100644 --- a/edg/parts/EnvironmentalSensor_Bme680.py +++ b/edg/parts/EnvironmentalSensor_Bme680.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self) -> None: ) self.i2c = self.Port(I2cTarget(dio_model, [0x76])) + @override def contents(self) -> None: self.footprint( 'U', 'Package_LGA:Bosch_LGA-8_3x3mm_P0.8mm_ClockwisePinNumbering', @@ -52,6 +55,7 @@ def __init__(self) -> None: self.pwr_io = self.Export(self.ic.vddio, default=self.pwr, doc="IO supply voltage") self.i2c = self.Export(self.ic.i2c, [InOut]) + @override def contents(self) -> None: super().contents() # capacitors from shuttle board example self.vdd_cap = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/EnvironmentalSensor_Sensirion.py b/edg/parts/EnvironmentalSensor_Sensirion.py index d04e6e3fd..89f1b442b 100644 --- a/edg/parts/EnvironmentalSensor_Sensirion.py +++ b/edg/parts/EnvironmentalSensor_Sensirion.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -17,6 +19,7 @@ def __init__(self) -> None: ) self.i2c = self.Port(I2cTarget(dio_model, [0x70])) + @override def contents(self) -> None: self.footprint( 'U', 'Sensor_Humidity:Sensirion_DFN-4-1EP_2x2mm_P1mm_EP0.7x1.6mm', @@ -43,6 +46,7 @@ def __init__(self) -> None: self.pwr = self.Export(self.ic.vdd, [Power]) self.i2c = self.Export(self.ic.i2c, [InOut]) + @override def contents(self) -> None: super().contents() # capacitors from datasheet self.vdd_cap = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/EnvironmentalSensor_Ti.py b/edg/parts/EnvironmentalSensor_Ti.py index 831ee93d2..6b375182c 100644 --- a/edg/parts/EnvironmentalSensor_Ti.py +++ b/edg/parts/EnvironmentalSensor_Ti.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -17,6 +19,7 @@ def __init__(self) -> None: ) self.i2c = self.Port(I2cTarget(dio_model, [0x40])) + @override def contents(self) -> None: super().contents() self.footprint( @@ -45,6 +48,7 @@ def __init__(self) -> None: self.gnd = self.Export(self.ic.gnd, [Common]) self.i2c = self.Export(self.ic.i2c, [InOut]) + @override def contents(self) -> None: super().contents() # X7R capacitor recommended @@ -70,6 +74,7 @@ def __init__(self, addr_lsb: IntLike) -> None: self.addr_lsb = self.ArgParameter(addr_lsb) self.generator_param(self.addr_lsb) + @override def generate(self) -> None: super().generate() addr_lsb = self.get(self.addr_lsb) @@ -105,6 +110,7 @@ def __init__(self, addr_lsb: IntLike = 0): self.i2c = self.Export(self.ic.i2c, [InOut]) self.alert = self.Export(self.ic.alert, optional=True, doc="Overtemperature SMBus alert") + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(0.01*uFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/FanConnector.py b/edg/parts/FanConnector.py index 70fdf91b7..cef800704 100644 --- a/edg/parts/FanConnector.py +++ b/edg/parts/FanConnector.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -29,6 +31,7 @@ def __init__(self) -> None: class CpuFan3Pin(CpuFanConnector, FootprintBlock): """3-pin fan controller""" + @override def contents(self) -> None: super().contents() self.footprint( @@ -44,6 +47,7 @@ def contents(self) -> None: class CpuFan4Pin(CpuFanConnector, CpuFanPwmControl, FootprintBlock): """3-pin fan controller""" + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Fpga_Ice40up.py b/edg/parts/Fpga_Ice40up.py index 21ce08e19..6ae06b177 100644 --- a/edg/parts/Fpga_Ice40up.py +++ b/edg/parts/Fpga_Ice40up.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart from .PassiveConnector_Header import PinHeader127DualShrouded @@ -15,6 +17,7 @@ def __init__(self) -> None: self.cs = self.Port(DigitalSource.empty()) self.reset = self.Port(DigitalSource.empty()) + @override def contents(self) -> None: super().contents() self.conn = self.Block(PinHeader127DualShrouded(10)) @@ -89,6 +92,7 @@ def __init__(self, **kwargs: Any) -> None: self.spi_config = self.Port(SpiController(self._dpio1_model)) self.spi_config_cs = self.Port(self._dpio1_model) + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: # names consistent with pinout spreadsheet return VariantPinRemapper({ 'VCCPLL': self.vcc_pll, @@ -108,6 +112,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: # names consistent with p 'IOB_35b_SPI_SS': self.spi_config_cs, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: pio0_model = self.make_dio_model(self.gnd, self.vccio_0) dpio0_model = pio0_model # differential capability currently not modeled @@ -170,6 +175,7 @@ def _io_pinmap(self) -> PinMapUtil: PeripheralAnyResource('SPI2', spi_model), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() @@ -257,6 +263,7 @@ def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self.cdone = self.Port(DigitalSource.empty(), optional=True) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Fusb302b.py b/edg/parts/Fusb302b.py index d337d4ce0..6a0feea35 100644 --- a/edg/parts/Fusb302b.py +++ b/edg/parts/Fusb302b.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -23,6 +25,7 @@ def __init__(self) -> None: self.i2c = self.Port(I2cTarget(i2c_model, [0x22])) self.int_n = self.Port(DigitalSource.low_from_supply(self.gnd), optional=True) + @override def contents(self) -> None: self.footprint( 'U', 'Package_DFN_QFN:WQFN-14-1EP_2.5x2.5mm_P0.5mm_EP1.45x1.45mm', @@ -63,6 +66,7 @@ def __init__(self) -> None: self.i2c = self.Export(self.ic.i2c) self.int = self.Export(self.ic.int_n) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Fuseholder_Nano2.py b/edg/parts/Fuseholder_Nano2.py index b1c762c8d..159cd6367 100644 --- a/edg/parts/Fuseholder_Nano2.py +++ b/edg/parts/Fuseholder_Nano2.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..electronics_model import Volt, FootprintBlock from ..abstract_parts import Fuse from .JlcPart import JlcPart @@ -6,6 +8,7 @@ class Nano2Fuseholder(Fuse, JlcPart, FootprintBlock): """Littelfuse Nano2 / 154 series fuseholder. Generic versions exist as 1808 fuses. TODO: generate fuse part numbers from a table, currently this only generates the holder""" + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/GateDriver_Ir2301.py b/edg/parts/GateDriver_Ir2301.py index 1c85e0745..8d3d990cf 100644 --- a/edg/parts/GateDriver_Ir2301.py +++ b/edg/parts/GateDriver_Ir2301.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -41,6 +43,7 @@ def __init__(self) -> None: )) self.assign(self.vb.current_draw, (50, 190)*uAmp + self.ho.link().current_drawn) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', @@ -64,6 +67,7 @@ def contents(self) -> None: class Ir2301(HalfBridgeDriver, HalfBridgeDriverIndependent): """IR2301 half-bridge driver supporting 600V offset, 5-20v input, external boot diode, no shoot through protect, no deadtime.""" + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/GateDriver_Ncp3420.py b/edg/parts/GateDriver_Ncp3420.py index dbb7ca827..432f7f9d9 100644 --- a/edg/parts/GateDriver_Ncp3420.py +++ b/edg/parts/GateDriver_Ncp3420.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -43,6 +45,7 @@ def __init__(self) -> None: self.assign(self.vcc.current_draw, (0.7, 5.0)*mAmp + self.drvl.link().current_drawn + self.drvh.link().current_drawn) # only system supply given + @override def contents(self) -> None: super().contents() self.footprint( @@ -70,6 +73,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.has_boot_diode, self.high_pwr.is_connected()) + @override def contents(self) -> None: super().contents() @@ -86,6 +90,7 @@ def contents(self) -> None: # serves as both boot cap and decoupling cap self.high_cap = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.high_gnd, self.ic.bst) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/GateDriver_Ucc27282.py b/edg/parts/GateDriver_Ucc27282.py index 93d38a8c5..ba4c01a6d 100644 --- a/edg/parts/GateDriver_Ucc27282.py +++ b/edg/parts/GateDriver_Ucc27282.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -41,6 +43,7 @@ def __init__(self) -> None: self.assign(self.vdd.current_draw, (0.3, 4.5)*mAmp + (0.2, 4)*mAmp + self.lo.link().current_drawn + self.ho.link().current_drawn) + @override def contents(self) -> None: super().contents() self.footprint( @@ -65,6 +68,7 @@ def contents(self) -> None: class Ucc27282(HalfBridgeDriver, HalfBridgeDriverIndependent): """UCC27282 half-bridge driver supporting 100V offset, 5.5-16v input, internal boot diode, shoot through protect, no deadtime.""" + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Imu_Lsm6ds3trc.py b/edg/parts/Imu_Lsm6ds3trc.py index 7f5971b3a..6966f9a6f 100644 --- a/edg/parts/Imu_Lsm6ds3trc.py +++ b/edg/parts/Imu_Lsm6ds3trc.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -27,6 +29,7 @@ def __init__(self) -> None: self.int1 = self.Port(dout_model, optional=True) self.int2 = self.Port(dout_model, optional=True) + @override def contents(self) -> None: self.footprint( 'U', 'Package_LGA:Bosch_LGA-14_3x2.5mm_P0.5mm', @@ -67,6 +70,7 @@ def __init__(self) -> None: self.int1 = self.Export(self.ic.int1, optional=True, doc="Programmable interrupt") self.int2 = self.Export(self.ic.int2, optional=True, doc="Programmable interrupt") + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/Ina219.py b/edg/parts/Ina219.py index 0d3e850fc..8ed7739c2 100644 --- a/edg/parts/Ina219.py +++ b/edg/parts/Ina219.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -29,6 +31,7 @@ def __init__(self, addr_lsb: IntLike): self.in_pos = self.Port(AnalogSink(voltage_limits=(-0.3, 26) * Volt)) self.in_neg = self.Port(AnalogSink(voltage_limits=(-0.3, 26) * Volt)) + @override def generate(self) -> None: super().generate() @@ -89,6 +92,7 @@ def __init__(self, shunt_resistor: RangeLike = 2.0 * mOhm(tol=0.05), *, addr_lsb self.sense_pos = self.Export(self.Rs.pwr_in) self.sense_neg = self.Export(self.Rs.pwr_out) + @override def contents(self) -> None: super().contents() self.connect(self.Rs.sense_in, self.ic.in_pos) diff --git a/edg/parts/Inamp_Ina826.py b/edg/parts/Inamp_Ina826.py index 92040be1e..7e25a26cc 100644 --- a/edg/parts/Inamp_Ina826.py +++ b/edg/parts/Inamp_Ina826.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -35,6 +37,7 @@ def __init__(self) -> None: self.rg2 = self.Port(Passive()) self.rg3 = self.Port(Passive()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -60,6 +63,7 @@ class Ina826(KiCadImportableBlock, GeneratorBlock): """Cost-effective instrumentation amplifier in SOIC-8, with gain 1-1000 set by single resistor. TODO: DiffAmp / InAmp abstract class, which supports KiCadImportableBlock """ + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: mapping: Dict[str, Dict[str, BasePort]] = { 'Simulation_SPICE:OPAMP': { # reference pin not supported @@ -89,6 +93,7 @@ def __init__(self, ratio: RangeLike = 10*Ratio(tol=0.05)): self.actual_ratio = self.Parameter(RangeExpr()) self.generator_param(self.ratio) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/IoExpander_Pca9554.py b/edg/parts/IoExpander_Pca9554.py index 60a5dd039..101daaf0a 100644 --- a/edg/parts/IoExpander_Pca9554.py +++ b/edg/parts/IoExpander_Pca9554.py @@ -1,6 +1,8 @@ from itertools import chain from typing import Dict, List, Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -27,6 +29,7 @@ def __init__(self, addr_lsb: IntLike, **kwargs: Any) -> None: self.addr_lsb = self.ArgParameter(addr_lsb) self.generator_param(self.addr_lsb, self.pin_assigns, self.io.requested()) + @override def generate(self) -> None: dout_model = DigitalBidir.from_supply( # same between TI and NXP versions self.gnd, self.vdd, @@ -87,6 +90,7 @@ def __init__(self, addr_lsb: IntLike = 0) -> None: self.i2c = self.Export(self.ic.i2c) self.io = self.Export(self.ic.io) + @override def contents(self) -> None: super().contents() self.assign(self.actual_pin_assigns, self.ic.actual_pin_assigns) diff --git a/edg/parts/IoExpander_Pcf8574.py b/edg/parts/IoExpander_Pcf8574.py index 8aaf2f167..f07ca4ba4 100644 --- a/edg/parts/IoExpander_Pcf8574.py +++ b/edg/parts/IoExpander_Pcf8574.py @@ -1,6 +1,8 @@ from itertools import chain from typing import Dict, Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -27,6 +29,7 @@ def __init__(self, addr_lsb: IntLike, **kwargs: Any) -> None: self.addr_lsb = self.ArgParameter(addr_lsb) self.generator_param(self.addr_lsb, self.pin_assigns, self.io.requested()) + @override def generate(self) -> None: super().generate() dout_model = DigitalBidir.from_supply( # same between TI and NXP versions @@ -87,6 +90,7 @@ def __init__(self, addr_lsb: IntLike = 0) -> None: self.i2c = self.Export(self.ic.i2c) self.io = self.Export(self.ic.io) + @override def contents(self) -> None: super().contents() self.assign(self.actual_pin_assigns, self.ic.actual_pin_assigns) diff --git a/edg/parts/Isolator_Cbmud1200.py b/edg/parts/Isolator_Cbmud1200.py index eadeb119e..468891e58 100644 --- a/edg/parts/Isolator_Cbmud1200.py +++ b/edg/parts/Isolator_Cbmud1200.py @@ -1,5 +1,7 @@ from typing import List +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -34,6 +36,7 @@ def __init__(self) -> None: self.voa = self.Port(out_model) self.vob = self.Port(out_model) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', @@ -58,6 +61,7 @@ class Cbmud1200l(DigitalIsolator, GeneratorBlock): def __init__(self) -> None: super().__init__() + @override def generate(self) -> None: super().generate() assert not self.get(self.in_b.requested()) and not self.get(self.out_a.requested()), f"device has no b->a channels" diff --git a/edg/parts/Jacdac.py b/edg/parts/Jacdac.py index 500ee59bc..600a1aa8d 100644 --- a/edg/parts/Jacdac.py +++ b/edg/parts/Jacdac.py @@ -1,5 +1,7 @@ from typing import Optional +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -11,6 +13,7 @@ def __init__(self) -> None: self.nodes = self.Port(Vector(JacdacDataPort.empty())) self.passives = self.Port(Vector(JacdacPassivePort.empty())) + @override def contents(self) -> None: super().contents() self.jd_data = self.connect(self.nodes.map_extract(lambda node: node.jd_data), @@ -80,12 +83,14 @@ def __init__(self, is_power_provider: BoolLike = False) -> None: self.generator_param(self.jd_pwr_src.is_connected()) + @override def contents(self) -> None: super().contents() self.require(self.jd_pwr_src.is_connected() | self.jd_pwr_sink.is_connected()) self.require(self.jd_pwr_src.is_connected().implies(~self.jd_pwr_sink.is_connected())) + @override def generate(self) -> None: super().generate() @@ -106,6 +111,7 @@ def generate(self) -> None: class Rclamp0521p(TvsDiode, FootprintBlock, JlcPart): """RCLAMP0521P-N TVS diode in 0402 package, recommended in the Jacdac DDK.""" + @override def contents(self) -> None: super().contents() self.require(self.working_voltage.within(self.actual_working_voltage)) @@ -148,6 +154,7 @@ def __init__(self, is_power_provider: BoolLike = False) -> None: self.generator_param(self.jd_pwr_src.is_connected(), self.jd_pwr_sink.is_connected()) + @override def generate(self) -> None: super().contents() @@ -183,6 +190,7 @@ def __init__(self) -> None: self.signal = self.Port(DigitalBidir.empty(), [Input]) self.jd_data = self.Port(JacdacDataPort.empty(), [Output]) + @override def contents(self) -> None: super().contents() self.ferrite = self.Block(FerriteBead(hf_impedance=(1, float('inf'))*kOhm)) @@ -214,6 +222,7 @@ def __init__(self) -> None: super().__init__() self.jd_data = self.Port(JacdacPassivePort()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -229,6 +238,7 @@ def __init__(self) -> None: super().__init__() self.gnd = self.Port(Ground()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -244,6 +254,7 @@ def __init__(self) -> None: super().__init__() self.gnd = self.Port(Ground()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -259,6 +270,7 @@ def __init__(self) -> None: super().__init__() self.jd_pwr = self.Port(VoltageSink()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -275,6 +287,7 @@ class JacdacDeviceTop(DesignTop): Recommend connecting to the nets, instead of connecting directly to the created Blocks and their Ports.""" + @override def contents(self) -> None: super().contents() self.edge = self.Block(JacdacEdgeConnector()) diff --git a/edg/parts/JlcAntenna.py b/edg/parts/JlcAntenna.py index 736646db5..d55f0fbcc 100644 --- a/edg/parts/JlcAntenna.py +++ b/edg/parts/JlcAntenna.py @@ -1,5 +1,7 @@ from typing import Optional, Dict, Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcTableSelector @@ -28,6 +30,7 @@ class JlcAntenna(JlcTableSelector, TableAntenna, FootprintBlock): } @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Antennas': @@ -47,6 +50,7 @@ def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: return cls._jlc_table().map_new_columns(parse_row) + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.gnd.init_from(Ground()) # unused for current parts diff --git a/edg/parts/JlcBjt.py b/edg/parts/JlcBjt.py index aa4ec5022..9e636482c 100644 --- a/edg/parts/JlcBjt.py +++ b/edg/parts/JlcBjt.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -32,6 +35,7 @@ class JlcBjt(PartsTableSelectorFootprint, JlcTableSelector, TableBjt): ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Bipolar Transistors - BJT': diff --git a/edg/parts/JlcBlackbox.py b/edg/parts/JlcBlackbox.py index 3ea875a0d..e6c991f11 100644 --- a/edg/parts/JlcBlackbox.py +++ b/edg/parts/JlcBlackbox.py @@ -1,5 +1,7 @@ from typing import Tuple, Callable, Mapping, List +from typing_extensions import override + from ..electronics_model import * from .JlcPart import JlcPart @@ -9,6 +11,7 @@ class KiCadJlcBlackbox(KiCadBlackboxBase, JlcPart, FootprintBlock, GeneratorBloc This can't extend KiCadBlackbox because KiCadBlackbox.block_from_symbol is non-compositional """ @classmethod + @override def block_from_symbol(cls, symbol: KiCadSymbol, lib: KiCadLibSymbol) -> \ Tuple['KiCadJlcBlackbox', Callable[['KiCadJlcBlackbox'], Mapping[str, BasePort]]]: pin_numbers = [pin.number for pin in lib.pins] @@ -38,6 +41,7 @@ def __init__(self, kicad_pins: ArrayStringLike, kicad_refdes_prefix: StringLike, self.kicad_pins = self.ArgParameter(kicad_pins) self.generator_param(self.kicad_pins) + @override def generate(self) -> None: super().generate() mapping = {pin_name: self.ports.append_elt(Passive(), pin_name) diff --git a/edg/parts/JlcCapacitor.py b/edg/parts/JlcCapacitor.py index c700a06b7..2069ecd89 100644 --- a/edg/parts/JlcCapacitor.py +++ b/edg/parts/JlcCapacitor.py @@ -1,6 +1,8 @@ from typing import Optional, Any, Dict import re +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart, JlcTableSelector @@ -38,6 +40,7 @@ def __init__(self, *args: Any, capacitance_minimum_size: BoolLike = True, **kwar self.generator_param(self.capacitance_minimum_size) @classmethod + @override def _make_table(cls) -> PartsTable: CAPACITOR_MATCHES = { 'nominal_capacitance': re.compile(r"(^|\s)([^±]\S+F)($|\s)"), @@ -79,6 +82,7 @@ def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: return cls._jlc_table().map_new_columns(parse_row) + @override def _table_postprocess(self, table: PartsTable) -> PartsTable: def filter_minimum_size(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: # enforce minimum packages, note the cutoffs are exclusive @@ -100,9 +104,11 @@ def filter_minimum_size(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, A return table @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return [row[cls.PARALLEL_COUNT], super(JlcCapacitor, cls)._row_sort_by(row)] + @override def _row_generate(self, row: PartsTableRow) -> None: # see comment in TableCapacitor._row_generate for why this needs to be here if row[self.PARALLEL_COUNT] == 1: @@ -112,6 +118,7 @@ def _row_generate(self, row: PartsTableRow) -> None: self.assign(self.actual_basic_part, True) # dummy value self._make_parallel_footprints(row) + @override def _make_parallel_footprints(self, row: PartsTableRow) -> None: cap_model = JlcDummyCapacitor(set_lcsc_part=row[self.LCSC_PART_HEADER], set_basic_part=row[self.BASIC_PART_HEADER] == self.BASIC_PART_VALUE, diff --git a/edg/parts/JlcCrystal.py b/edg/parts/JlcCrystal.py index ad1ba4a5a..ae2c51446 100644 --- a/edg/parts/JlcCrystal.py +++ b/edg/parts/JlcCrystal.py @@ -1,5 +1,8 @@ import re from typing import Optional, Dict, Any, List + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcTableSelector, DescriptionParser @@ -24,6 +27,7 @@ class JlcCrystal(PartsTableSelectorFootprint, JlcTableSelector, TableCrystal): } @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Crystals': diff --git a/edg/parts/JlcDiode.py b/edg/parts/JlcDiode.py index 24df07d7e..106b1d035 100644 --- a/edg/parts/JlcDiode.py +++ b/edg/parts/JlcDiode.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -56,6 +59,7 @@ class JlcDiode(PartsTableSelectorFootprint, JlcTableSelector, JlcBaseDiode, Tabl ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] not in [ @@ -97,6 +101,7 @@ class JlcZenerDiode(PartsTableSelectorFootprint, JlcTableSelector, JlcBaseDiode, ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Zener Diodes': diff --git a/edg/parts/JlcElectrolyticCapacitor.py b/edg/parts/JlcElectrolyticCapacitor.py index d8e6abbf5..9b14b743a 100644 --- a/edg/parts/JlcElectrolyticCapacitor.py +++ b/edg/parts/JlcElectrolyticCapacitor.py @@ -1,6 +1,8 @@ from typing import Optional, Any, Dict, List import re +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -25,6 +27,7 @@ def __init__(self, *args: Any, capacitance_minimum_size: BoolLike = True, **kwar self.generator_param(self.capacitance_minimum_size) @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Aluminum Electrolytic Capacitors - SMD': diff --git a/edg/parts/JlcFerriteBead.py b/edg/parts/JlcFerriteBead.py index 2f6402fe5..888782d19 100644 --- a/edg/parts/JlcFerriteBead.py +++ b/edg/parts/JlcFerriteBead.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -33,6 +36,7 @@ class JlcFerriteBead(PartsTableSelectorFootprint, JlcTableSelector, TableFerrite ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if not row['Second Category'] == 'Ferrite Beads': diff --git a/edg/parts/JlcFet.py b/edg/parts/JlcFet.py index dd2c7b8f9..d5c802832 100644 --- a/edg/parts/JlcFet.py +++ b/edg/parts/JlcFet.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -16,6 +19,7 @@ def __init__(self, *args: Any, fallback_gate_charge: RangeLike = Range.from_tole self.fallback_gate_charge = self.ArgParameter(fallback_gate_charge) self.generator_param(self.fallback_gate_charge) + @override def _table_postprocess(self, table: PartsTable) -> PartsTable: fallback_gate_charge = self.get(self.fallback_gate_charge) def process_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: @@ -166,6 +170,7 @@ class JlcBaseFet(JlcTableSelector): } @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'MOSFETs': diff --git a/edg/parts/JlcInductor.py b/edg/parts/JlcInductor.py index e1a711465..9dd3ba2f6 100644 --- a/edg/parts/JlcInductor.py +++ b/edg/parts/JlcInductor.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -86,6 +89,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.require(self.frequency.within(self.manual_frequency_rating)) @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] not in ('Inductors (SMD)', 'Power Inductors'): diff --git a/edg/parts/JlcLed.py b/edg/parts/JlcLed.py index f5d284b3b..8ead12006 100644 --- a/edg/parts/JlcLed.py +++ b/edg/parts/JlcLed.py @@ -1,5 +1,7 @@ from typing import Optional, Dict, Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcTableSelector @@ -35,6 +37,7 @@ class JlcLed(PartsTableSelectorFootprint, JlcTableSelector, TableLed): } @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Light Emitting Diodes (LED)': diff --git a/edg/parts/JlcOscillator.py b/edg/parts/JlcOscillator.py index 8cdb5d6da..c1a131d42 100644 --- a/edg/parts/JlcOscillator.py +++ b/edg/parts/JlcOscillator.py @@ -1,5 +1,8 @@ import re from typing import Optional, Dict, Any, List + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart, JlcTableSelector, DescriptionParser @@ -72,6 +75,7 @@ class JlcOscillator(JlcTableSelector, TableOscillator): ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] not in ('Pre-programmed Oscillators', 'Oscillators'): @@ -97,6 +101,7 @@ def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: lambda row: [row[cls.BASIC_PART_HEADER], cls._row_area(row), row[cls.COST]] ) + @override def _row_generate(self, row: PartsTableRow) -> None: for series, device_cls in self.SERIES_DEVICE_MAP.items(): if row[self.PART_NUMBER_COL].startswith(series): diff --git a/edg/parts/JlcPart.py b/edg/parts/JlcPart.py index e92fc3d9c..e54d64918 100644 --- a/edg/parts/JlcPart.py +++ b/edg/parts/JlcPart.py @@ -1,6 +1,8 @@ from typing import Optional, Dict, Any, Tuple, Callable, List import re +from typing_extensions import override + from ..abstract_parts import * @@ -89,9 +91,11 @@ def parse_full_description(description: str, parser_options: List[DescriptionPar @non_library class JlcTableSelector(PartsTableAreaSelector, PartsTableFootprintFilter, JlcPart, JlcTableBase): @classmethod + @override def _row_sort_by(cls, row: PartsTableRow) -> Any: return [row[cls.BASIC_PART_HEADER], cls._row_area(row), super()._row_sort_by(row), row[cls.COST]] + @override def _row_generate(self, row: PartsTableRow) -> None: super()._row_generate(row) self.assign(self.lcsc_part, row[self.LCSC_PART_HEADER]) diff --git a/edg/parts/JlcPptcFuse.py b/edg/parts/JlcPptcFuse.py index bc4d3a8a5..5ad2c5de6 100644 --- a/edg/parts/JlcPptcFuse.py +++ b/edg/parts/JlcPptcFuse.py @@ -1,5 +1,8 @@ from typing import * import re + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -32,6 +35,7 @@ class JlcPptcFuse(PartsTableSelectorFootprint, JlcTableSelector, TableFuse, Pptc ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if not row['Second Category'] == 'Resettable Fuses': diff --git a/edg/parts/JlcResistor.py b/edg/parts/JlcResistor.py index f6d4bb832..2bbecf410 100644 --- a/edg/parts/JlcResistor.py +++ b/edg/parts/JlcResistor.py @@ -1,5 +1,8 @@ import re from typing import Optional, Dict, Any + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcTableSelector @@ -31,6 +34,7 @@ class JlcResistor(PartsTableSelectorFootprint, JlcTableSelector, TableResistor): } @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['First Category'] != 'Resistors': diff --git a/edg/parts/JlcResistorArray.py b/edg/parts/JlcResistorArray.py index 86bacfc86..44b407c61 100644 --- a/edg/parts/JlcResistorArray.py +++ b/edg/parts/JlcResistorArray.py @@ -1,5 +1,8 @@ import re from typing import Optional, Dict, Any, List + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import DescriptionParser, JlcTableSelector @@ -23,6 +26,7 @@ class JlcResistorArray(PartsTableSelectorFootprint, JlcTableSelector, TableResis ] @classmethod + @override def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if row['Second Category'] != 'Resistor Networks & Arrays': diff --git a/edg/parts/JlcSwitches.py b/edg/parts/JlcSwitches.py index 50f3d5420..1977693cf 100644 --- a/edg/parts/JlcSwitches.py +++ b/edg/parts/JlcSwitches.py @@ -1,8 +1,11 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart class JlcSwitch(TactileSwitch, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() @@ -19,6 +22,7 @@ def contents(self) -> None: class Skrtlae010(TactileSwitch, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Joystick_Xbox.py b/edg/parts/Joystick_Xbox.py index 149913259..4ffe04098 100644 --- a/edg/parts/Joystick_Xbox.py +++ b/edg/parts/Joystick_Xbox.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -15,6 +17,7 @@ def __init__(self) -> None: self.ax1 = self.Port(AnalogSource.from_supply(self.gnd, self.pwr)) self.ax2 = self.Port(AnalogSource.from_supply(self.gnd, self.pwr)) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Jumpers.py b/edg/parts/Jumpers.py index fc346c73e..46e378cdd 100644 --- a/edg/parts/Jumpers.py +++ b/edg/parts/Jumpers.py @@ -1,7 +1,10 @@ +from typing_extensions import override + from ..abstract_parts import * class SolderJumperTriangular(Jumper, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Labels.py b/edg/parts/Labels.py index bfb93c35d..f27ddb87a 100644 --- a/edg/parts/Labels.py +++ b/edg/parts/Labels.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from deprecated import deprecated @deprecated("non-circuit footprints should be added in layout as non-schematic items") class LeadFreeIndicator(Label, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -15,6 +18,7 @@ def contents(self) -> None: @deprecated("non-circuit footprints should be added in layout as non-schematic items") class IdDots4(Label, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -26,6 +30,7 @@ def contents(self) -> None: @deprecated("non-circuit footprints should be added in layout as non-schematic items") class DuckLogo(Label, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -37,6 +42,7 @@ def contents(self) -> None: @deprecated("non-circuit footprints should be added in layout as non-schematic items") class LemurLogo(Label, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Lcd_Ch280qv10_Ct.py b/edg/parts/Lcd_Ch280qv10_Ct.py index f8ec11018..2da5b04b5 100644 --- a/edg/parts/Lcd_Ch280qv10_Ct.py +++ b/edg/parts/Lcd_Ch280qv10_Ct.py @@ -1,8 +1,11 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom class Ch280qv10_Ct_Outline(InternalSubcircuit, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Ch280qv10_Ct_Outline', {}, @@ -107,6 +110,7 @@ def __init__(self) -> None: self.ctp_i2c = self.Export(self.device.ctp_i2c, optional=True) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.device.vci) diff --git a/edg/parts/Lcd_Er_Tft1_28_3.py b/edg/parts/Lcd_Er_Tft1_28_3.py index 63f530b96..3734b8e16 100644 --- a/edg/parts/Lcd_Er_Tft1_28_3.py +++ b/edg/parts/Lcd_Er_Tft1_28_3.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from .PassiveConnector_Fpc import Fpc050Bottom from ..abstract_parts import * @@ -5,6 +7,7 @@ class Er_Tft_128_3_Outline(InternalSubcircuit, FootprintBlock): """Footprint for TFT panel outline""" + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Tft1_28_3_Outline', {}, @@ -83,6 +86,7 @@ def __init__(self) -> None: self.ctp_rst = self.Export(self.ic.ctp_rst, optional=True, doc='Touch panel interface') self.ctp_int = self.Export(self.ic.ctp_int, optional=True, doc='Touch panel interface') + @override def contents(self) -> None: super().contents() self.connect(self.reset, self.ic.rst) diff --git a/edg/parts/Lcd_Qt096t_if09.py b/edg/parts/Lcd_Qt096t_if09.py index b87bb4855..16a2105f6 100644 --- a/edg/parts/Lcd_Qt096t_if09.py +++ b/edg/parts/Lcd_Qt096t_if09.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom @@ -49,6 +51,7 @@ def __init__(self) -> None: self.spi = self.Export(self.device.spi) self.led = self.Port(DigitalSink.empty()) + @override def contents(self) -> None: super().contents() self.connect(self.reset, self.device.reset) diff --git a/edg/parts/LedDriver_Al8861.py b/edg/parts/LedDriver_Al8861.py index f2b074576..7b5d6f155 100644 --- a/edg/parts/LedDriver_Al8861.py +++ b/edg/parts/LedDriver_Al8861.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self, peak_output_current: FloatLike): self.peak_output_current = self.ArgParameter(peak_output_current) + @override def contents(self) -> None: super().contents() self.require(self.peak_output_current < 2*Amp) @@ -60,6 +63,7 @@ def __init__(self, diode_voltage_drop: RangeLike = Range.all()): self.actual_ripple = self.Parameter(RangeExpr()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/LedDriver_Tps92200.py b/edg/parts/LedDriver_Tps92200.py index ee46a31bf..bbd8ca922 100644 --- a/edg/parts/LedDriver_Tps92200.py +++ b/edg/parts/LedDriver_Tps92200.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -25,6 +27,7 @@ def __init__(self, peak_output_current: FloatLike): self.sw = self.Port(VoltageSource()) self.boot = self.Port(Passive()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -62,6 +65,7 @@ def __init__(self, led_voltage: RangeLike = (1, 4)*Volt, *, self.input_ripple_limit = self.ArgParameter(input_ripple_limit) self.output_ripple_limit = self.ArgParameter(output_ripple_limit) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/LedMatrix.py b/edg/parts/LedMatrix.py index d4dc106db..bc9641b9b 100644 --- a/edg/parts/LedMatrix.py +++ b/edg/parts/LedMatrix.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from typing import Dict, Optional, Tuple @@ -9,9 +11,11 @@ class CharlieplexedLedMatrix(Light, GeneratorBlock, SvgPcbTemplateBlock): Anodes (columns) are directly connected to the IO line, while the cathodes (rows) are connected through a resistor. A generalization of https://en.wikipedia.org/wiki/Charlieplexing#/media/File:3-pin_Charlieplexing_matrix_with_common_resistors.svg """ + @override def _svgpcb_fn_name_adds(self) -> Optional[str]: return f"{self._svgpcb_get(self.ncols)}_{self._svgpcb_get(self.nrows)}" + @override def _svgpcb_template(self) -> str: led_block = self._svgpcb_footprint_block_path_of(['led[0_0]']) res_block = self._svgpcb_footprint_block_path_of(['res[0]']) @@ -160,6 +164,7 @@ def _svgpcb_template(self) -> str: }} """ + @override def _svgpcb_bbox(self) -> Tuple[float, float, float, float]: return (-1.0, -1.0, self._svgpcb_get(self.ncols) * .2 * 25.4 + 1.0, (self._svgpcb_get(self.nrows) + 1) * .2 * 25.4 + 1.0) @@ -178,6 +183,7 @@ def __init__(self, nrows: IntLike, ncols: IntLike, self.ncols = self.ArgParameter(ncols) self.generator_param(self.nrows, self.ncols) + @override def generate(self) -> None: super().generate() nrows = self.get(self.nrows) diff --git a/edg/parts/Leds.py b/edg/parts/Leds.py index f29b2af49..4f04f329d 100644 --- a/edg/parts/Leds.py +++ b/edg/parts/Leds.py @@ -1,8 +1,11 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart class SmtLed(Led, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -16,6 +19,7 @@ def contents(self) -> None: class ThtLed(Led, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -29,6 +33,7 @@ def contents(self) -> None: class Smt0606RgbLed(RgbLedCommonAnode, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -46,6 +51,7 @@ def contents(self) -> None: class Smt0404RgbLed(RgbLedCommonAnode, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -63,6 +69,7 @@ def contents(self) -> None: class ThtRgbLed(RgbLedCommonAnode, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/LightSensor_As7341.py b/edg/parts/LightSensor_As7341.py index 2ee4fedaa..98082d309 100644 --- a/edg/parts/LightSensor_As7341.py +++ b/edg/parts/LightSensor_As7341.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -19,6 +21,7 @@ def __init__(self) -> None: ) self.i2c = self.Port(I2cTarget(dio_model, [0x39])) + @override def contents(self) -> None: self.footprint( 'U', 'Package_LGA:AMS_OLGA-8_2x3.1mm_P0.8mm', @@ -49,6 +52,7 @@ def __init__(self) -> None: self.gnd = self.Export(self.ic.gnd, [Common]) self.i2c = self.Export(self.ic.i2c) + @override def contents(self) -> None: super().contents() # capacitance value assumed, same value as on Adafruit's breakout diff --git a/edg/parts/LightSensor_Bh1750.py b/edg/parts/LightSensor_Bh1750.py index 6a74c1c14..8b2964186 100644 --- a/edg/parts/LightSensor_Bh1750.py +++ b/edg/parts/LightSensor_Bh1750.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -18,6 +20,7 @@ def __init__(self) -> None: ) self.i2c = self.Port(I2cTarget(dio_model, [0x23])) + @override def contents(self) -> None: self.footprint( 'U', 'Package_TO_SOT_SMD:HVSOF6', @@ -45,6 +48,7 @@ def __init__(self) -> None: self.gnd = self.Export(self.ic.gnd, [Common]) self.i2c = self.Export(self.ic.i2c) + @override def contents(self) -> None: super().contents() # capacitors from shuttle board example self.vcc_cap = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.ic.vcc) diff --git a/edg/parts/LinearRegulators.py b/edg/parts/LinearRegulators.py index 49dc8e8d8..0d159f8b3 100644 --- a/edg/parts/LinearRegulators.py +++ b/edg/parts/LinearRegulators.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -16,6 +18,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() parts = [ # output voltage @@ -46,6 +49,7 @@ def generate(self) -> None: class Ld1117(LinearRegulator): + @override def contents(self) -> None: with self.implicit_connect( ImplicitConnect(self.gnd, [Common]), @@ -70,6 +74,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() TOLERANCE = 0.03 # worst-case -40 < Tj < 125C, slightly better at 25C @@ -106,6 +111,7 @@ class Ldl1117(LinearRegulator): """A series of fixed-output, general-purpose, low-dropout linear regulators in SOT-223 and supporting up to 18V input and 1.2A draw. """ + @override def contents(self) -> None: with self.implicit_connect( ImplicitConnect(self.gnd, [Common]), @@ -137,6 +143,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() @@ -176,9 +183,11 @@ def generate(self) -> None: class Ap2204k(VoltageRegulatorEnableWrapper, LinearRegulator): """AP2204K block providing the LinearRegulator interface and optional enable (tied high if not connected). """ + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() self.ic = self.Block(Ap2204k_Device(self.output_voltage)) @@ -218,6 +227,7 @@ def __init__(self, output_voltage: RangeLike): class Ap7215(LinearRegulator): """AP7215 fixed 3.3v LDO in SOT-89 providing the LinearRegulator interface. """ + @override def contents(self) -> None: super().contents() self.ic = self.Block(Ap7215_Device(self.output_voltage)) @@ -240,6 +250,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() parts = [ # output range, part number, (dropout typ @10mA, max @100mA), max current, lcsc, basic part @@ -287,6 +298,7 @@ def generate(self) -> None: class Xc6206p(LinearRegulator): """XC6206P LDOs in SOT-23 which seem popular in some open-source designs and some are JLC basic parts.""" + @override def contents(self) -> None: with self.implicit_connect( ImplicitConnect(self.gnd, [Common]), @@ -318,6 +330,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() TOLERANCE = 0.02 # worst-case -40 < Tj < 125C, slightly better at 25C @@ -352,9 +365,11 @@ def generate(self) -> None: class Xc6209(VoltageRegulatorEnableWrapper, LinearRegulator): """XC6209F (F: 300mA version, no pull-down resistor; 2: +/-2% accuracy) Low-ESR ceramic cap compatible""" + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.ce + @override def contents(self) -> None: super().contents() @@ -387,6 +402,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() TOLERANCE = 0.02 # worst-case -40 < Tj < 125C, slightly better at 25C @@ -422,9 +438,11 @@ def generate(self) -> None: class Ap2210(VoltageRegulatorEnableWrapper, LinearRegulator): """AP2210 RF ULDO in SOT-23-5 with high PSRR and high(er) voltage tolerant. """ + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() @@ -458,6 +476,7 @@ def __init__(self, output_voltage: RangeLike): input_thresholds=(0.4, 1.2)*Volt )) + @override def generate(self) -> None: super().generate() parts = [ # output voltage, Table in 6.5 tolerance varies by output voltage @@ -525,9 +544,11 @@ class Lp5907(VoltageRegulatorEnableWrapper, LinearRegulator): - AP139 - TCR2EF """ + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() @@ -559,6 +580,7 @@ def __init__(self, output_voltage: RangeLike): input_thresholds=(0.3, 1)*Volt )) + @override def generate(self) -> None: super().generate() tolerance = 0.015 # over 125C range, Vout >= 1v @@ -606,9 +628,11 @@ class Tlv757p(VoltageRegulatorEnableWrapper, LinearRegulator): By default, this models worst-case dropout at 1A, consult datasheet for lower dropouts for lower currents While it can electrically handle 1A, beware of thermal limits. Shuts down at 155C, Rja for SOT-23-5 of 100C/W """ + @override def _generator_inner_reset_pin(self) -> Port[DigitalLink]: return self.ic.en + @override def contents(self) -> None: super().contents() @@ -630,6 +654,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() @@ -672,6 +697,7 @@ def generate(self) -> None: class L78l(LinearRegulator): """L78Lxx high(er) input voltage linear regulator in SOT-89. """ + @override def contents(self) -> None: super().contents() self.ic = self.Block(L78l_Device(self.output_voltage)) diff --git a/edg/parts/Logic_74Ahct.py b/edg/parts/Logic_74Ahct.py index 1ee82eb5f..c065c486d 100644 --- a/edg/parts/Logic_74Ahct.py +++ b/edg/parts/Logic_74Ahct.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self) -> None: current_limits=(-8, 8)*mAmp, ), [Output]) + @override def contents(self) -> None: super().contents() self.footprint( @@ -48,6 +51,7 @@ def __init__(self) -> None: self.input = self.Export(self.ic.a, [Input]) self.output = self.Export(self.ic.y, [Output]) + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.gnd, self.pwr) diff --git a/edg/parts/Logic_74Lvc.py b/edg/parts/Logic_74Lvc.py index b9358f5f3..8c8095948 100644 --- a/edg/parts/Logic_74Lvc.py +++ b/edg/parts/Logic_74Lvc.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -31,6 +33,7 @@ def __init__(self) -> None: self.nq = self.Port(dout_model, optional=True) self.require(self.q.is_connected() | self.nq.is_connected()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -67,6 +70,7 @@ def __init__(self) -> None: self.q = self.Export(self.ic.q, optional=True) self.nq = self.Export(self.ic.nq, optional=True) + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.gnd, self.pwr) @@ -103,6 +107,7 @@ def __init__(self) -> None: self.require((self.out2.is_connected() == self.in2a.is_connected()) & (self.out2.is_connected() == self.in2b.is_connected())) + @override def contents(self) -> None: super().contents() self.footprint( @@ -138,6 +143,7 @@ def __init__(self) -> None: self.out1 = self.Export(self.ic.out1, optional=True) self.out2 = self.Export(self.ic.out2, optional=True) + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.gnd, self.pwr) diff --git a/edg/parts/Lsm6dsv16x.py b/edg/parts/Lsm6dsv16x.py index 52ac3e495..6b6bf3248 100644 --- a/edg/parts/Lsm6dsv16x.py +++ b/edg/parts/Lsm6dsv16x.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from .JlcPart import JlcPart from ..abstract_parts import * @@ -30,6 +32,7 @@ def __init__(self) -> None: self.qvar1 = self.Port(Passive(), optional=True) self.qvar2 = self.Port(Passive(), optional=True) + @override def contents(self) -> None: self.footprint( 'U', 'Package_LGA:Bosch_LGA-14_3x2.5mm_P0.5mm', @@ -77,6 +80,7 @@ def __init__(self) -> None: self.qvar1 = self.Export(self.ic.qvar1, optional=True, doc="qvar input pin 1") self.qvar2 = self.Export(self.ic.qvar2, optional=True, doc="qvar input pin 2") + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(100 * nFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/Mag_Qmc5883l.py b/edg/parts/Mag_Qmc5883l.py index 9d5ce533e..2e7d9ab80 100644 --- a/edg/parts/Mag_Qmc5883l.py +++ b/edg/parts/Mag_Qmc5883l.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -26,6 +28,7 @@ def __init__(self) -> None: self.setc = self.Port(Passive()) self.c1 = self.Port(Passive()) + @override def contents(self) -> None: self.footprint( 'U', 'Package_LGA:LGA-16_3x3mm_P0.5mm', @@ -67,6 +70,7 @@ def __init__(self) -> None: self.i2c = self.Export(self.ic.i2c) self.drdy = self.Export(self.ic.drdy, optional=True) + @override def contents(self) -> None: super().contents() self.vdd_cap = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.gnd, self.ic.vdd) diff --git a/edg/parts/MagneticSensor_A1304.py b/edg/parts/MagneticSensor_A1304.py index ae986a187..c0667792e 100644 --- a/edg/parts/MagneticSensor_A1304.py +++ b/edg/parts/MagneticSensor_A1304.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -16,6 +18,7 @@ def __init__(self) -> None: signal_out_abs=(0.38, 2.87) # output saturation limits @ Vcc=3.3v )) + @override def contents(self) -> None: self.footprint( 'U', 'Package_TO_SOT_SMD:SOT-23', @@ -41,6 +44,7 @@ def __init__(self) -> None: self.pwr = self.Export(self.ic.vcc, [Power]) self.out = self.Export(self.ic.vout, [Output]) + @override def contents(self) -> None: super().contents() self.cbyp = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.pwr) diff --git a/edg/parts/MagneticSwitch_Ah1806.py b/edg/parts/MagneticSwitch_Ah1806.py index d38366e0d..deec12ed6 100644 --- a/edg/parts/MagneticSwitch_Ah1806.py +++ b/edg/parts/MagneticSwitch_Ah1806.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -15,6 +17,7 @@ def __init__(self) -> None: self.gnd, current_limits=(-1, 0)*mAmp )) + @override def contents(self) -> None: self.footprint( 'U', 'Package_TO_SOT_SMD:SOT-23', @@ -43,6 +46,7 @@ def __init__(self) -> None: self.pwr = self.Export(self.ic.vdd, [Power]) self.out = self.Export(self.ic.output, [Output]) + @override def contents(self) -> None: super().contents() self.cin = self.Block(DecouplingCapacitor(100*nFarad(tol=0.2))).connected(self.gnd, self.pwr) diff --git a/edg/parts/Mechanicals.py b/edg/parts/Mechanicals.py index 9f5e2d7e7..c579358c7 100644 --- a/edg/parts/Mechanicals.py +++ b/edg/parts/Mechanicals.py @@ -1,8 +1,11 @@ from deprecated import deprecated +from typing_extensions import override + from ..abstract_parts import * @deprecated("non-circuit footprints should be added in layout as non-schematic items") class Outline_Pn1332(Mechanical, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint( @@ -22,6 +25,7 @@ def __init__(self) -> None: super().__init__() self.pad = self.Port(Passive(), optional=True) + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Microcontroller_Esp.py b/edg/parts/Microcontroller_Esp.py index eb0f9d4c8..f9a004948 100644 --- a/edg/parts/Microcontroller_Esp.py +++ b/edg/parts/Microcontroller_Esp.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Header import PinHeader254 from .PassiveConnector_TagConnect import TagConnect @@ -32,6 +34,7 @@ def __init__(self, *args: Any, require_auto_reset: BoolLike = True, **kwargs: An self.require_auto_reset = self.ArgParameter(require_auto_reset) + @override def contents(self) -> None: super().contents() self.require(self.require_auto_reset.implies(self.en.is_connected() & self.boot.is_connected()), @@ -42,6 +45,7 @@ def contents(self) -> None: class EspProgrammingPinHeader254(EspProgrammingHeader): """Programming header for ESP series micros using 2.54mm headers, matching the pinning in the reference schematics.""" + @override def contents(self) -> None: super().contents() @@ -62,6 +66,7 @@ class EspProgrammingTc2030(EspProgrammingAutoReset, EspProgrammingHeader): Per boot docs, EN is connected to RTS and boot is connected to DTR (CTS on the original pinning, since it doesn't have a DTR pin). """ + @override def contents(self) -> None: super().contents() @@ -88,6 +93,7 @@ def __init__(self, programming: StringLike = "uart-button"): self.program_en_node = self.connect() self.program_boot_node = self.connect() + @override def generate(self) -> None: super().generate() programming = self.get(self.programming) @@ -125,6 +131,7 @@ def __init__(self) -> None: self.en = self.Port(DigitalSource.empty()) self.boot = self.Port(DigitalSource.empty()) + @override def contents(self) -> None: super().contents() signal_voltage = self.dtr.link().voltage.hull(self.rts.link().voltage) diff --git a/edg/parts/Microcontroller_Esp32.py b/edg/parts/Microcontroller_Esp32.py index 384b1d4b2..0a9593450 100644 --- a/edg/parts/Microcontroller_Esp32.py +++ b/edg/parts/Microcontroller_Esp32.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart from .Microcontroller_Esp import HasEspProgramming @@ -37,6 +39,7 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: pullup_capable=True, pulldown_capable=True, ) + @override def _io_pinmap(self) -> PinMapUtil: pwr = self._vddio() dio_model = self._dio_model(pwr) @@ -160,9 +163,11 @@ def __init__(self, **kwargs: Any) -> None: # similarly, the programming UART is fixed and allocated separately self.uart0 = self.Port(UartPort(dio_model), optional=True) + @override def _vddio(self) -> Port[VoltageLink]: return self.pwr + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ 'Vdd': self.pwr, @@ -223,6 +228,7 @@ class Esp32_Wroom_32_Device(Esp32_Base, InternalSubcircuit, FootprintBlock, JlcP 'GPIO23': '37', } + @override def generate(self) -> None: super().generate() @@ -246,6 +252,7 @@ def __init__(self) -> None: self.ic: Esp32_Wroom_32_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -262,6 +269,7 @@ def contents(self) -> None: self.vcc_cap0 = imp.Block(DecouplingCapacitor(22 * uFarad(tol=0.2))) # C1 self.vcc_cap1 = imp.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))) # C2 + @override def generate(self) -> None: super().generate() @@ -325,12 +333,14 @@ class Freenove_Esp32_Wrover(IoControllerUsbOut, IoControllerPowerOut, Esp32_Ios, # 'GPIO23': '39', # camera CSI_HREF } + @override def _vddio(self) -> Port[VoltageLink]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr else: return self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") @@ -367,6 +377,7 @@ def __init__(self, **kwargs: Any) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Esp32c3.py b/edg/parts/Microcontroller_Esp32c3.py index 1001b44c9..fb486f1a4 100644 --- a/edg/parts/Microcontroller_Esp32c3.py +++ b/edg/parts/Microcontroller_Esp32c3.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart from .Microcontroller_Esp import HasEspProgramming @@ -37,6 +39,7 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: pullup_capable=True, pulldown_capable=True, ) + @override def _io_pinmap(self) -> PinMapUtil: pwr = self._vddio() dio_model = self._dio_model(pwr) @@ -95,9 +98,11 @@ class Esp32c3_Base(Esp32c3_Ios, BaseIoControllerPinmapGenerator): """ SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] # pin name in base -> pin name(s) + @override def _vddio(self) -> Port[VoltageLink]: return self.pwr + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return { 'Vdd': self.pwr, @@ -145,6 +150,7 @@ class Esp32c3_Wroom02_Device(Esp32c3_Base, InternalSubcircuit, FootprintBlock, J 'GPIO0': '18', } + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper(super()._system_pinmap()).remap({ 'Vdd': '1', @@ -157,6 +163,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'TXD': '12', # TXD, GPIO21 }) + @override def generate(self) -> None: super().generate() @@ -181,6 +188,7 @@ def __init__(self) -> None: self.io2_ext_connected: bool = False self.io8_ext_connected: bool = False + @override def contents(self) -> None: super().contents() @@ -196,6 +204,7 @@ def contents(self) -> None: self.vcc_cap0 = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) # C1 self.vcc_cap1 = imp.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))) # C2 + @override def generate(self) -> None: super().generate() @@ -216,6 +225,7 @@ def generate(self) -> None: self.io2_ext_connected = True # set to ensure this runs after external connections ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: """Add support for _GPIO2/8/9_STRAP and remap them to io2/8/9.""" @@ -253,6 +263,7 @@ class Esp32c3_Device(Esp32c3_Base, InternalSubcircuit, FootprintBlock, JlcPart): 'GPIO19': '26', } + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper(super()._system_pinmap()).remap({ 'Vdd': ['31', '32'], # VDDA @@ -287,6 +298,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.xtal = self.Port(CrystalDriver(frequency_limits=40*MHertz(tol=10e-6), voltage_out=self.pwr.link().voltage)) + @override def generate(self) -> None: super().generate() @@ -328,6 +340,7 @@ def __init__(self) -> None: self.io2_ext_connected: bool = False self.io8_ext_connected: bool = False + @override def contents(self) -> None: super().contents() with self.implicit_connect( @@ -369,6 +382,7 @@ def contents(self) -> None: inductance=2*nHenry(tol=0.2), )).connected(self.pwr, self.ic.vdd3p3) + @override def generate(self) -> None: super().generate() @@ -389,6 +403,7 @@ def generate(self) -> None: self.io2_ext_connected = True # set to ensure this runs after external connections ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: """Add support for _GPIO2/8/9_STRAP and remap them to io2/8/9.""" @@ -408,6 +423,7 @@ def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportTy return None return super()._make_export_vector(self_io, inner_vector, name, assign) + @override def _crystal_required(self) -> bool: return True # crystal oscillator always required @@ -444,12 +460,14 @@ class Xiao_Esp32c3(IoControllerUsbOut, IoControllerPowerOut, Esp32c3_Ios, IoCont 'VDD_SPI': '11', } + @override def _vddio(self) -> Port[VoltageLink]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr else: return self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") @@ -465,6 +483,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'VUSB': self.vusb_out, }).remap(self.SYSTEM_PIN_REMAP) + @override def contents(self) -> None: super().contents() @@ -482,6 +501,7 @@ def contents(self) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Esp32s3.py b/edg/parts/Microcontroller_Esp32s3.py index 5b7613807..93a8e58c9 100644 --- a/edg/parts/Microcontroller_Esp32s3.py +++ b/edg/parts/Microcontroller_Esp32s3.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart from .Microcontroller_Esp import HasEspProgramming @@ -38,6 +40,7 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: pullup_capable=True, pulldown_capable=True, ) + @override def _io_pinmap(self) -> PinMapUtil: pwr = self._vddio() dio_model = self._dio_model(pwr) @@ -154,9 +157,11 @@ class Esp32s3_Base(Esp32s3_Ios, GeneratorBlock): """ SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] # pin name in base -> pin name(s) + @override def _vddio(self) -> Port[VoltageLink]: return self.pwr + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ 'VDD': self.pwr, # including VDD3V3, VDD3P3_RTC, VDD_SPI, VDD3P3_CPU @@ -228,6 +233,7 @@ class Esp32s3_Wroom_1_Device(Esp32s3_Base, InternalSubcircuit, FootprintBlock, J 'GPIO1': '39', } + @override def generate(self) -> None: super().generate() @@ -250,6 +256,7 @@ def __init__(self) -> None: self.ic: Esp32s3_Wroom_1_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -266,6 +273,7 @@ def contents(self) -> None: self.vcc_cap1 = imp.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))) # C2 + @override def generate(self) -> None: super().generate() @@ -276,6 +284,7 @@ def generate(self) -> None: gnd=self.gnd, pwr=self.pwr, io=self.ic.chip_pu) ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: """Allow overloading strapping pins""" @@ -337,12 +346,14 @@ class Freenove_Esp32s3_Wroom(IoControllerUsbOut, IoControllerPowerOut, Esp32s3_I 'GPIO1': '38', } + @override def _vddio(self) -> Port[VoltageLink]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr else: return self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") @@ -358,6 +369,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'VUSB': self.vusb_out, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: # allow the camera I2C pins to be used externally pwr = self._vddio() return super()._io_pinmap().add([ @@ -366,6 +378,7 @@ def _io_pinmap(self) -> PinMapUtil: # allow the camera I2C pins to be used exte }) ]) + @override def contents(self) -> None: super().contents() @@ -383,6 +396,7 @@ def contents(self) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Lpc1549.py b/edg/parts/Microcontroller_Lpc1549.py index 38ac7fe70..63b11666b 100644 --- a/edg/parts/Microcontroller_Lpc1549.py +++ b/edg/parts/Microcontroller_Lpc1549.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -38,6 +40,7 @@ def __init__(self, **kwargs: Any) -> None: self.reset = self.Port(DigitalSink.empty(), optional=True) # internally pulled up, TODO disable-able and assignable as GPIO self._io_ports.insert(0, self.swd) + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ 'VddA': self.pwr, @@ -56,6 +59,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'RESET': self.reset }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: # Port models dio_5v_model = DigitalBidir.from_supply( @@ -173,6 +177,7 @@ def _io_pinmap(self) -> PinMapUtil: }), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() @@ -327,6 +332,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground.empty(), [Common]) self.swd = self.Port(SwdPullPort(DigitalSource.empty()), [InOut]) + @override def contents(self) -> None: super().contents() self.swdio = self.Block(PullupResistor((10, 100) * kOhm(tol=0.05))).connected(self.pwr, self.swd.swdio) @@ -345,6 +351,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Lpc1549Base_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -376,12 +383,14 @@ def contents(self) -> None: self.vref_cap[1] = imp.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))) self.vref_cap[2] = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.reset) + @override def _crystal_required(self) -> bool: # crystal needed for CAN or USB b/c tighter freq tolerance return len(self.get(self.can.requested())) > 0 or len(self.get(self.usb.requested())) > 0 \ or super()._crystal_required() diff --git a/edg/parts/Microcontroller_Rp2040.py b/edg/parts/Microcontroller_Rp2040.py index ca3ed57eb..9e1e9d9ef 100644 --- a/edg/parts/Microcontroller_Rp2040.py +++ b/edg/parts/Microcontroller_Rp2040.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -35,6 +37,7 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: pullup_capable=True, pulldown_capable=True ) + @override def _io_pinmap(self) -> PinMapUtil: pwr = self._vddio() dio_usb_model = dio_ft_model = dio_std_model = self._dio_model(pwr) @@ -177,6 +180,7 @@ class Rp2040_Device(Rp2040_Ios, BaseIoControllerPinmapGenerator, InternalSubcirc 'SWCLK': '24', } + @override def _vddio(self) -> Port[VoltageLink]: return self.iovdd @@ -221,6 +225,7 @@ def __init__(self, **kwargs: Any) -> None: self.run = self.Port(DigitalSink.empty(), optional=True) # internally pulled up self._io_ports.insert(0, self.swd) + @override def contents(self) -> None: super().contents() @@ -233,6 +238,7 @@ def contents(self) -> None: self.run.init_from(DigitalSink.from_bidir(dio_ft_model)) # Pin/peripheral resource definitions (table 3) + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return { '51': self.qspi_sd3, @@ -268,6 +274,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: '57': self.gnd, # pad } + @override def generate(self) -> None: super().generate() @@ -293,6 +300,7 @@ def __init__(self) -> None: self.usb_rp = self.Port(UsbHostPort.empty(), [Input]) self.usb = self.Port(UsbDevicePort.empty(), [Output]) + @override def contents(self) -> None: super().contents() @@ -317,6 +325,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Rp2040_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -353,6 +362,7 @@ def contents(self) -> None: self.vreg_out_cap = self.Block(DecouplingCapacitor(1 * uFarad(tol=0.2))).connected(self.gnd, self.ic.dvdd) + @override def generate(self) -> None: super().generate() @@ -360,6 +370,7 @@ def generate(self) -> None: self.connect(self.reset, self.ic.run) ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: if isinstance(self_io, UsbDevicePort): # assumed at most one USB port generates @@ -368,6 +379,7 @@ def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportTy return assign return super()._make_export_vector(self_io, inner_vector, name, assign) + @override def _crystal_required(self) -> bool: # crystal needed for USB b/c tighter freq tolerance return len(self.get(self.usb.requested())) > 0 or super()._crystal_required() @@ -405,12 +417,14 @@ class Xiao_Rp2040(IoControllerUsbOut, IoControllerPowerOut, IoControllerVin, Rp2 'GPIO3': '11', } + @override def _vddio(self) -> Port[VoltageLink]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr else: return self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power return VariantPinRemapper({ @@ -424,6 +438,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'VUSB': self.vusb_out, }).remap(self.SYSTEM_PIN_REMAP) + @override def contents(self) -> None: super().contents() @@ -453,6 +468,7 @@ def contents(self) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Stm32f103.py b/edg/parts/Microcontroller_Stm32f103.py index 359228dbd..f8bef26a5 100644 --- a/edg/parts/Microcontroller_Stm32f103.py +++ b/edg/parts/Microcontroller_Stm32f103.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -43,6 +45,7 @@ def __init__(self, **kwargs: Any) -> None: self.swd = self.Port(SwdTargetPort.empty()) self._io_ports.insert(0, self.swd) + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ # Pin/peripheral resource definitions (table 3) 'Vbat': self.pwr, @@ -56,6 +59,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'NRST': self.nrst, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: # Port models dio_ft_model = DigitalBidir.from_supply( @@ -175,6 +179,7 @@ def _io_pinmap(self) -> PinMapUtil: }), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() @@ -273,6 +278,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Stm32f103Base_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -295,13 +301,16 @@ def contents(self) -> None: self.vdda_cap_0 = imp.Block(DecouplingCapacitor(10 * nFarad(tol=0.2))) self.vdda_cap_1 = imp.Block(DecouplingCapacitor(1 * uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.nrst) + ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: if isinstance(self_io, UsbDevicePort): # assumed at most one USB port generates @@ -312,6 +321,7 @@ def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportTy return assign return super()._make_export_vector(self_io, inner_vector, name, assign) + @override def _crystal_required(self) -> bool: # crystal needed for CAN or USB b/c tighter freq tolerance return len(self.get(self.can.requested())) > 0 or len(self.get(self.usb.requested())) > 0 \ or super()._crystal_required() diff --git a/edg/parts/Microcontroller_Stm32f303.py b/edg/parts/Microcontroller_Stm32f303.py index b7d7d0670..e4979e6d1 100644 --- a/edg/parts/Microcontroller_Stm32f303.py +++ b/edg/parts/Microcontroller_Stm32f303.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * @@ -22,6 +24,7 @@ def _vdd_model(self) -> VoltageSink: current_draw=(0.00055, 80)*mAmp + self.io_current_draw.upper() # table 25 Idd standby to max ) + @override def _io_pinmap(self) -> PinMapUtil: """Returns the mappable for a STM32F303 device with the input power and ground references. This allows a shared definition between discrete chips and microcontroller boards""" @@ -169,6 +172,7 @@ class Stm32f303_Device(Stm32f303_Ios, IoController, InternalSubcircuit, Generato TODO IMPLEMENT ME""" SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ # 'Vbat': self.vdd, @@ -217,12 +221,14 @@ class Nucleo_F303k8(IoControllerUsbOut, IoControllerPowerOut, IoController, Stm3 'PB3': '30', # CN4.15, D13 } + @override def _vddio_vdda(self) -> Tuple[Port[VoltageLink], Port[VoltageLink]]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr, self.pwr else: return self.pwr_out, self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") @@ -255,6 +261,7 @@ def __init__(self) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Stm32g031.py b/edg/parts/Microcontroller_Stm32g031.py index fff3a0c2c..731501f36 100644 --- a/edg/parts/Microcontroller_Stm32g031.py +++ b/edg/parts/Microcontroller_Stm32g031.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -30,6 +32,7 @@ def __init__(self, **kwargs: Any) -> None: self.nrst = self.Port(DigitalSink.empty(), optional=True) # internally pulled up + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ # Pin/peripheral resource definitions (section 4) 'Vdd': self.pwr, @@ -37,6 +40,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'PF2-NRST': self.nrst, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: # Port models input_range = self.gnd.link().voltage.hull(self.pwr.link().voltage) @@ -141,6 +145,7 @@ def _io_pinmap(self) -> PinMapUtil: }), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() @@ -206,6 +211,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Stm32g031Base_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -221,6 +227,7 @@ def contents(self) -> None: self.pwr_cap0 = imp.Block(DecouplingCapacitor(4.7 * uFarad(tol=0.2))) self.pwr_cap1 = imp.Block(DecouplingCapacitor(0.1 * uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microcontroller_Stm32g431.py b/edg/parts/Microcontroller_Stm32g431.py index 3bf0e95b7..cfcaf8438 100644 --- a/edg/parts/Microcontroller_Stm32g431.py +++ b/edg/parts/Microcontroller_Stm32g431.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from .JlcPart import JlcPart from ..abstract_parts import * @@ -31,6 +33,7 @@ def __init__(self, **kwargs: Any) -> None: self._io_ports.insert(0, self.swd) self.nrst = self.Port(DigitalSink.empty(), optional=True) # internally pulled up + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ 'Vdd': self.pwr, @@ -41,6 +44,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'PG10-NRST': self.nrst, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: input_range = self.gnd.link().voltage.hull(self.pwr.link().voltage) io_voltage_limit = (input_range + (-0.3, 3.6) * Volt).intersect( @@ -185,6 +189,7 @@ def _io_pinmap(self) -> PinMapUtil: }), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() self.footprint( @@ -245,6 +250,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Stm32g431Base_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() with self.implicit_connect( @@ -263,6 +269,7 @@ def contents(self) -> None: self.pwr_cap3 = imp.Block(DecouplingCapacitor(100 * nFarad(tol=0.2))) self.pwr_cap4 = imp.Block(DecouplingCapacitor(1 * uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): diff --git a/edg/parts/Microcontroller_Stm32l432.py b/edg/parts/Microcontroller_Stm32l432.py index 19b16d402..164e8b7e2 100644 --- a/edg/parts/Microcontroller_Stm32l432.py +++ b/edg/parts/Microcontroller_Stm32l432.py @@ -1,5 +1,7 @@ from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -31,6 +33,7 @@ def __init__(self, **kwargs: Any) -> None: self.nrst = self.Port(DigitalSink.empty(), optional=True) # internally pulled up + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ # Pin/peripheral resource definitions (section 4) 'Vdd': self.pwr, @@ -39,6 +42,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'NRST': self.nrst, }).remap(self.SYSTEM_PIN_REMAP) + @override def _io_pinmap(self) -> PinMapUtil: # Port models input_range = self.gnd.link().voltage.hull(self.pwr.link().voltage) @@ -157,6 +161,7 @@ def _io_pinmap(self) -> PinMapUtil: }), ]).remap_pins(self.RESOURCE_PIN_REMAP) + @override def generate(self) -> None: super().generate() @@ -224,6 +229,7 @@ def __init__(self, **kwargs: Any) -> None: self.ic: Stm32l432Base_Device self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() @@ -243,12 +249,14 @@ def contents(self) -> None: self.vdda_cap0 = imp.Block(DecouplingCapacitor(10*nFarad(tol=0.2))) self.vdda_cap1 = imp.Block(DecouplingCapacitor(1*uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.nrst) # otherwise NRST has internal pull-up + @override def _crystal_required(self) -> bool: # crystal needed for CAN b/c tighter freq tolerance # note: no crystal needed for USB, has clock recovery system (CRS) trimming for USB only return len(self.get(self.can.requested())) > 0 or super()._crystal_required() diff --git a/edg/parts/Microcontroller_nRF52840.py b/edg/parts/Microcontroller_nRF52840.py index 96b8c95e9..94a5e0e78 100644 --- a/edg/parts/Microcontroller_nRF52840.py +++ b/edg/parts/Microcontroller_nRF52840.py @@ -1,6 +1,8 @@ from abc import abstractmethod from typing import * +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -36,6 +38,7 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: pullup_capable=True, pulldown_capable=True, ) + @override def _io_pinmap(self) -> PinMapUtil: """Returns the mappable for given the input power and ground references. This separates the system pins definition from the IO pins definition.""" @@ -172,9 +175,11 @@ def _io_pinmap(self) -> PinMapUtil: class Nrf52840_Base(Nrf52840_Ios, GeneratorBlock): SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] # pin name in base -> pin name(s) + @override def _vddio(self) -> Port[VoltageLink]: return self.pwr + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: return VariantPinRemapper({ 'Vdd': self.pwr, @@ -252,6 +257,7 @@ class Holyiot_18010_Device(Nrf52840_Base, InternalSubcircuit): 'P0.10': '36', } + @override def generate(self) -> None: super().generate() @@ -273,6 +279,7 @@ def __init__(self, **kwargs: Any) -> None: self.pwr_usb = self.Export(self.ic.pwr_usb, optional=True) self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.ic.pwr) @@ -281,6 +288,7 @@ def contents(self) -> None: self.connect(self.swd_node, self.ic.swd) self.connect(self.reset_node, self.ic.nreset) + @override def generate(self) -> None: super().generate() if self.get(self.reset.is_connected()): @@ -350,6 +358,7 @@ class Mdbt50q_1mv2_Device(Nrf52840_Base, InternalSubcircuit, JlcPart): 'P1.01': '61', } + @override def generate(self) -> None: super().generate() @@ -386,6 +395,7 @@ def __init__(self, **kwargs: Any) -> None: self.pwr_usb = self.Export(self.ic.pwr_usb, optional=True) self.generator_param(self.reset.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.ic.pwr) @@ -400,6 +410,7 @@ def contents(self) -> None: ) as imp: self.vcc_cap = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) + @override def generate(self) -> None: super().generate() @@ -407,6 +418,7 @@ def generate(self) -> None: self.connect(self.reset, self.ic.nreset) ExportType = TypeVar('ExportType', bound=Port) + @override def _make_export_vector(self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str]) -> Optional[str]: if isinstance(self_io, UsbDevicePort): # assumed at most one USB port generates @@ -461,12 +473,14 @@ class Feather_Nrf52840(IoControllerUsbOut, IoControllerPowerOut, Nrf52840_Ios, I # note onboard VBAT sense divider at P0.29 } + @override def _vddio(self) -> Port[VoltageLink]: if self.get(self.pwr.is_connected()): # board sinks power return self.pwr else: return self.pwr_out + @override def _system_pinmap(self) -> Dict[str, CircuitPort]: if self.get(self.pwr.is_connected()): # board sinks power self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") @@ -482,6 +496,7 @@ def _system_pinmap(self) -> Dict[str, CircuitPort]: 'Vbus': self.vusb_out, }).remap(self.SYSTEM_PIN_REMAP) + @override def contents(self) -> None: super().contents() @@ -501,6 +516,7 @@ def contents(self) -> None: self.generator_param(self.pwr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Microphone_Sd18ob261.py b/edg/parts/Microphone_Sd18ob261.py index 03976b9fc..a092bf270 100644 --- a/edg/parts/Microphone_Sd18ob261.py +++ b/edg/parts/Microphone_Sd18ob261.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -27,6 +29,7 @@ def __init__(self) -> None: current_limits=(-20, 20)*mAmp # short circuit current for data pin )) + @override def contents(self) -> None: self.footprint( 'U', 'Sensor_Audio:Knowles_LGA-5_3.5x2.65mm', @@ -61,6 +64,7 @@ def __init__(self) -> None: self.generator_param(self.lr.is_connected()) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/MotorDriver_Drv8833.py b/edg/parts/MotorDriver_Drv8833.py index 1c05e47c5..422b58b91 100644 --- a/edg/parts/MotorDriver_Drv8833.py +++ b/edg/parts/MotorDriver_Drv8833.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -34,6 +36,7 @@ def __init__(self) -> None: self.bout1 = self.Port(dout_model, optional=True) self.bout2 = self.Port(dout_model, optional=True) + @override def contents(self) -> None: self.assign(self.vm.current_draw, (1.6, 3000) * uAmp + # from sleep to max operating (0, # calculate possible motor current, assuming A1/2 and B1/2 are coupled (and not independent) @@ -99,6 +102,7 @@ def __init__(self) -> None: self.bout1 = self.Export(self.ic.bout1, optional=True) self.bout2 = self.Export(self.ic.bout2, optional=True) + @override def contents(self) -> None: super().contents() @@ -109,6 +113,7 @@ def contents(self) -> None: self.connect(self.vcp_cap.pos, self.ic.vcp) self.connect(self.vcp_cap.neg.adapt_to(VoltageSink()), self.ic.vm) + @override def generate(self) -> None: super().generate() if self.get(self.sleep.is_connected()): diff --git a/edg/parts/MotorDriver_Drv8870.py b/edg/parts/MotorDriver_Drv8870.py index a2a305907..ad5b11830 100644 --- a/edg/parts/MotorDriver_Drv8870.py +++ b/edg/parts/MotorDriver_Drv8870.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -32,6 +34,7 @@ def __init__(self) -> None: current_draw=RangeExpr() )) + @override def contents(self) -> None: self.assign(self.isen.current_draw, (0, self.out1.link().current_drawn.abs().upper().max( @@ -75,6 +78,7 @@ def __init__(self, current_trip: RangeLike = (2, 3)*Amp) -> None: self.current_trip = self.ArgParameter(current_trip) + @override def contents(self) -> None: super().contents() self.vm_cap0 = self.Block(DecouplingCapacitor(0.1*uFarad(tol=0.2))).connected(self.gnd, self.ic.vm) diff --git a/edg/parts/MotorDriver_L293dd.py b/edg/parts/MotorDriver_L293dd.py index 0e04ddb7e..b5edddc0e 100644 --- a/edg/parts/MotorDriver_L293dd.py +++ b/edg/parts/MotorDriver_L293dd.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -42,6 +44,7 @@ def __init__(self) -> None: self.require(self.out3.is_connected().implies(self.in3.is_connected() & self.en2.is_connected())) self.require(self.out4.is_connected().implies(self.in4.is_connected() & self.en2.is_connected())) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:SOIC-20W_7.5x12.8mm_P1.27mm', @@ -92,6 +95,7 @@ def __init__(self) -> None: self.out3 = self.Export(self.ic.out3, optional=True) self.out4 = self.Export(self.ic.out4, optional=True) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Neopixel.py b/edg/parts/Neopixel.py index 9b852c215..de5e7c0dd 100644 --- a/edg/parts/Neopixel.py +++ b/edg/parts/Neopixel.py @@ -1,5 +1,7 @@ from typing import Optional, Tuple +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -37,6 +39,7 @@ def __init__(self) -> None: current_limits=0*mAmp(tol=0), )) + @override def contents(self) -> None: self.footprint( 'D', 'LED_SMD:LED_WS2812B_PLCC4_5.0x5.0mm_P3.2mm', @@ -75,6 +78,7 @@ def __init__(self) -> None: current_limits=0*mAmp(tol=0), ), optional=True) + @override def contents(self) -> None: self.footprint( 'D', 'edg:LED_SK6812MINI-E', @@ -121,6 +125,7 @@ def __init__(self) -> None: current_limits=0*mAmp(tol=0), ), optional=True) + @override def contents(self) -> None: self.footprint( 'D', 'LED_SMD:LED_SK6812_EC15_1.5x1.5mm', @@ -168,6 +173,7 @@ def __init__(self) -> None: current_limits=0*mAmp(tol=0), ), optional=True) + @override def contents(self) -> None: self.footprint( 'D', 'LED_SMD:LED_WS2812B-2020_PLCC4_2.0x2.0mm', @@ -214,6 +220,7 @@ def __init__(self) -> None: current_limits=0*mAmp(tol=0), ), optional=True) + @override def contents(self) -> None: self.footprint( 'D', 'edg:LED_SK6812-SIDE-A', @@ -254,6 +261,7 @@ def __init__(self, count: IntLike): self.count = self.ArgParameter(count) self.generator_param(self.count) + @override def generate(self) -> None: super().generate() self.led = ElementDict[Neopixel]() @@ -270,9 +278,11 @@ def generate(self) -> None: class NeopixelArrayCircular(NeopixelArray, SvgPcbTemplateBlock): """An array of Neopixels, with a circular layout template""" + @override def _svgpcb_fn_name_adds(self) -> Optional[str]: return f"{self._svgpcb_get(self.count)}" + @override def _svgpcb_template(self) -> str: led_block = self._svgpcb_footprint_block_path_of(['led[0]']) led_reftype, led_refnum = self._svgpcb_refdes_of(['led[0]']) @@ -397,5 +407,6 @@ def _svgpcb_template(self) -> str: }} """ + @override def _svgpcb_bbox(self) -> Tuple[float, float, float, float]: return -25.4 - 1.0, -25.4 - 1.0, 25.4 + 1.0, 25.4 + 1.0 diff --git a/edg/parts/Oled_Er_Oled_022.py b/edg/parts/Oled_Er_Oled_022.py index 71723ee33..d99bf4d88 100644 --- a/edg/parts/Oled_Er_Oled_022.py +++ b/edg/parts/Oled_Er_Oled_022.py @@ -1,8 +1,11 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom class Er_Oled022_1_Outline(InternalSubcircuit, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Oled022_1_Outline', {}, @@ -74,6 +77,7 @@ def __init__(self) -> None: self.i2c = self.Port(I2cTarget.empty(), optional=True) self.generator_param(self.spi.is_connected(), self.i2c.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.reset, self.device.res) @@ -96,6 +100,7 @@ def contents(self) -> None: self.vcc_cap2 = self.Block(DecouplingCapacitor(capacitance=10*uFarad(tol=0.2)))\ .connected(self.gnd, self.device.vcc) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Oled_Er_Oled_028.py b/edg/parts/Oled_Er_Oled_028.py index 0eb2605b8..0e73c880c 100644 --- a/edg/parts/Oled_Er_Oled_028.py +++ b/edg/parts/Oled_Er_Oled_028.py @@ -1,8 +1,11 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom class Er_Oled028_1_Outline(InternalSubcircuit, FootprintBlock): + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Oled028_1_Outline', {}, @@ -88,6 +91,7 @@ def __init__(self) -> None: self.generator_param(self.dc.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.device.vci) @@ -123,6 +127,7 @@ def contents(self) -> None: self.connect(self.vsl_d1.cathode, self.vsl_d2.anode) self.connect(self.vsl_d2.cathode.adapt_to(Ground()), self.gnd) + @override def generate(self) -> None: super().generate() if self.get(self.dc.is_connected()): # 4-line serial diff --git a/edg/parts/Oled_Er_Oled_091_3.py b/edg/parts/Oled_Er_Oled_091_3.py index cba39e969..6705cf55e 100644 --- a/edg/parts/Oled_Er_Oled_091_3.py +++ b/edg/parts/Oled_Er_Oled_091_3.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom class Er_Oled_091_3_Outline(InternalSubcircuit, FootprintBlock): """Footprint for OLED panel outline""" + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Oled0.91_3_Outline', {}, @@ -77,6 +80,7 @@ def __init__(self) -> None: self.cs = self.Export(self.device.cs) self.dc = self.Export(self.device.dc) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.device.vbat) diff --git a/edg/parts/Oled_Er_Oled_096_1_1.py b/edg/parts/Oled_Er_Oled_096_1_1.py index 93e99b2a9..0da14e85f 100644 --- a/edg/parts/Oled_Er_Oled_096_1_1.py +++ b/edg/parts/Oled_Er_Oled_096_1_1.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc050Bottom class Er_Oled_096_1_1_Outline(InternalSubcircuit, FootprintBlock): """Footprint for OLED panel outline""" + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Oled0.96_1.1_Outline', {}, @@ -87,6 +90,7 @@ def __init__(self) -> None: self.i2c = self.Port(I2cTarget.empty(), optional=True) self.generator_param(self.spi.is_connected(), self.dc.is_connected(), self.i2c.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.pwr, self.device.vbat) @@ -113,6 +117,7 @@ def contents(self) -> None: self.vcc_cap = self.Block(DecouplingCapacitor(capacitance=(2.2*0.8, 10)*uFarad))\ .connected(self.gnd, self.device.vcc) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Oled_Er_Oled_096_1c.py b/edg/parts/Oled_Er_Oled_096_1c.py index 3fc81f9df..0ae925757 100644 --- a/edg/parts/Oled_Er_Oled_096_1c.py +++ b/edg/parts/Oled_Er_Oled_096_1c.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .PassiveConnector_Fpc import Fpc030Bottom class Er_Oled_096_1c_Outline(InternalSubcircuit, FootprintBlock): """Footprint for OLED panel outline""" + @override def contents(self) -> None: super().contents() self.footprint('U', 'edg:Lcd_Er_Oled0.96_1c_Outline', {}, @@ -88,6 +91,7 @@ def __init__(self) -> None: self.i2c = self.Port(I2cSlave.empty(), optional=True) self.generator_param(self.spi.is_connected(), self.dc.is_connected(), self.i2c.is_connected()) + @override def contents(self) -> None: super().contents() self.connect(self.reset, self.device.res) @@ -116,6 +120,7 @@ def contents(self) -> None: self.connect(self.vsl_d1.cathode, self.vsl_d2.anode) self.connect(self.vsl_d2.cathode.adapt_to(Ground()), self.gnd) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/Oled_Nhd_312_25664uc.py b/edg/parts/Oled_Nhd_312_25664uc.py index 6c9d53003..393e9da2e 100644 --- a/edg/parts/Oled_Nhd_312_25664uc.py +++ b/edg/parts/Oled_Nhd_312_25664uc.py @@ -1,4 +1,7 @@ from typing import * + +from typing_extensions import override + from ..abstract_parts import * @@ -27,6 +30,7 @@ def __init__(self) -> None: self.nres = self.Port(DigitalSink.from_bidir(io_model)) self.ncs = self.Port(DigitalSink.from_bidir(io_model)) + @override def contents(self) -> None: super().contents() @@ -73,6 +77,7 @@ def __init__(self) -> None: self.cs = self.Export(self.device.ncs) self.spi = self.Port(SpiPeripheral(DigitalBidir.empty())) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Opamp_Lmv321.py b/edg/parts/Opamp_Lmv321.py index 6145f849b..774dd5696 100644 --- a/edg/parts/Opamp_Lmv321.py +++ b/edg/parts/Opamp_Lmv321.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -23,6 +25,7 @@ def __init__(self) -> None: current_limits=(-40, 40)*mAmp, # output short circuit current )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -44,6 +47,7 @@ def contents(self) -> None: class Lmv321(Opamp): """RRO op-amp in SOT-23-5. """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Opamp_Mcp6001.py b/edg/parts/Opamp_Mcp6001.py index 2c6d73e84..7df44c745 100644 --- a/edg/parts/Opamp_Mcp6001.py +++ b/edg/parts/Opamp_Mcp6001.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -25,6 +27,7 @@ def __init__(self) -> None: impedance=300*Ohm(tol=0) # no tolerance bounds given on datasheet )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -46,6 +49,7 @@ def contents(self) -> None: class Mcp6001(Opamp): """MCP6001 RRO op-amp in SOT-23-5 """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Opamp_Opax171.py b/edg/parts/Opamp_Opax171.py index 2f960302d..472d220cd 100644 --- a/edg/parts/Opamp_Opax171.py +++ b/edg/parts/Opamp_Opax171.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -46,6 +48,7 @@ def __init__(self) -> None: self.innb = self.Port(analog_in_model) self.outb = self.Port(analog_out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -70,6 +73,7 @@ def contents(self) -> None: class Opa2171(MultipackOpampGenerator): """Dual precision general purpose RRO opamp. """ + @override def _make_multipack_opamp(self) -> MultipackOpampGenerator.OpampPorts: self.ic = self.Block(Opa2171_Device()) # Datasheet section 9: recommend 0.1uF bypass capacitors close to power supply pins diff --git a/edg/parts/Opamp_Opax189.py b/edg/parts/Opamp_Opax189.py index 532272144..83a582599 100644 --- a/edg/parts/Opamp_Opax189.py +++ b/edg/parts/Opamp_Opax189.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -41,6 +43,7 @@ def __init__(self) -> None: self.vinn = self.Port(analog_in_model) self.vout = self.Port(self._analog_out_model()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -65,6 +68,7 @@ def contents(self) -> None: class Opa189(Opamp): """High voltage (4.5-36V), low-noise opamp in SOIC-8. """ + @override def contents(self) -> None: super().contents() @@ -95,6 +99,7 @@ def __init__(self) -> None: self.innb = self.Port(analog_in_model) self.outb = self.Port(analog_out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -119,6 +124,7 @@ def contents(self) -> None: class Opa2189(MultipackOpampGenerator): """Dual precision RRO opamps. """ + @override def _make_multipack_opamp(self) -> MultipackOpampGenerator.OpampPorts: self.ic = self.Block(Opa2189_Device()) # Datasheet section 10: recommend 0.1uF bypass capacitors close to power supply pins diff --git a/edg/parts/Opamp_Opax197.py b/edg/parts/Opamp_Opax197.py index ae2182af4..e96098170 100644 --- a/edg/parts/Opamp_Opax197.py +++ b/edg/parts/Opamp_Opax197.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -41,6 +43,7 @@ def __init__(self) -> None: self.vinn = self.Port(analog_in_model) self.vout = self.Port(self._analog_out_model()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -66,6 +69,7 @@ class Opa197(Opamp): """High voltage opamp (4.5-36V) in SOIC-8. (part also available in SOT-23-5) """ + @override def contents(self) -> None: super().contents() @@ -97,6 +101,7 @@ def __init__(self) -> None: self.innb = self.Port(analog_in_model) self.outb = self.Port(analog_out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -121,6 +126,7 @@ def contents(self) -> None: class Opa2197(MultipackOpampGenerator): """Dual precision RRO opamps. """ + @override def _make_multipack_opamp(self) -> MultipackOpampGenerator.OpampPorts: self.ic = self.Block(Opa2197_Device()) # Datasheet section 9: recommend 0.1uF bypass capacitors close to power supply pins diff --git a/edg/parts/Opamp_Opax333.py b/edg/parts/Opamp_Opax333.py index 0e05f3d58..f847d0a5a 100644 --- a/edg/parts/Opamp_Opax333.py +++ b/edg/parts/Opamp_Opax333.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -29,6 +31,7 @@ def __init__(self) -> None: self.innb = self.Port(analog_in_model) self.outb = self.Port(analog_out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -53,6 +56,7 @@ def contents(self) -> None: class Opa2333(MultipackOpampGenerator): """Dual precision RRIO (including negative input) opamps. """ + @override def _make_multipack_opamp(self) -> MultipackOpampGenerator.OpampPorts: self.ic = self.Block(Opa2333_Device()) # Datasheet section 9: recommend 0.1uF bypass capacitors close to power supply pins diff --git a/edg/parts/Opamp_Tlv9061.py b/edg/parts/Opamp_Tlv9061.py index 73c66c8e2..3077416ab 100644 --- a/edg/parts/Opamp_Tlv9061.py +++ b/edg/parts/Opamp_Tlv9061.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -24,6 +26,7 @@ def __init__(self) -> None: impedance=100*Ohm(tol=0) # no tolerance bounds given on datasheet; open-loop impedance )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -46,6 +49,7 @@ def contents(self) -> None: class Tlv9061(Opamp): """RRIO op-amp in SOT-23-6. """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Opamp_Tlv915x.py b/edg/parts/Opamp_Tlv915x.py index c0b9fe1be..e1449eb82 100644 --- a/edg/parts/Opamp_Tlv915x.py +++ b/edg/parts/Opamp_Tlv915x.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -29,6 +31,7 @@ def __init__(self) -> None: self.innb = self.Port(analog_in_model) self.outb = self.Port(analog_out_model) + @override def contents(self) -> None: super().contents() self.footprint( @@ -53,6 +56,7 @@ def contents(self) -> None: class Tlv9152(MultipackOpampGenerator): """Dual RRIO opamps. """ + @override def _make_multipack_opamp(self) -> MultipackOpampGenerator.OpampPorts: self.ic = self.Block(Tlv9152_Device()) # Datasheet section 9: recommend 0.1uF bypass capacitors close to power supply pins diff --git a/edg/parts/PassiveConnector_Fpc.py b/edg/parts/PassiveConnector_Fpc.py index 02f41a3bc..5528534e9 100644 --- a/edg/parts/PassiveConnector_Fpc.py +++ b/edg/parts/PassiveConnector_Fpc.py @@ -1,4 +1,7 @@ from typing import Tuple + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -23,10 +26,12 @@ class Fpc050Bottom(Fpc050): class Fpc050BottomFlip(Fpc050Bottom, GeneratorBlock): """Flipped FPC connector - bottom entry connector is top entry on the opposite board side. Reverses the pin ordering to reflect the mirroring.""" + @override def contents(self) -> None: super().contents() self.generator_param(self.length, self.pins.requested()) + @override def generate(self) -> None: super().generate() self.conn = self.Block(Fpc050Top(self.length)) @@ -46,6 +51,7 @@ class HiroseFh12sh(Fpc050Bottom, FootprintPassiveConnector): _kicad_pins = {6, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 25, 26, 28, 30, 32, 33, 34, 35, 36, 40, 45, 50, 53} allowed_pins = _fh12_pins.intersection(_kicad_pins) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_FFC-FPC:Hirose_FH12-{length}S-0.5SH_1x{length:02d}-1MP_P0.50mm_Horizontal', "Hirose", f"FH12-{length}S-0.5SH") @@ -86,6 +92,7 @@ class Afc01(Fpc050Bottom, FootprintPassiveConnector, JlcPart): 60: 'C2918970' # FCC } + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: # TODO this isn't the intended hook and uses side effects, but it works for now self.assign(self.lcsc_part, self.PART_NUMBERS[length]) @@ -128,6 +135,7 @@ class Afc07Top(Fpc050Top, FootprintPassiveConnector, JlcPart): 54: 'C262258', # also C2691600 for -ECC 60: 'C262652' # ECA } + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: # TODO this isn't the intended hook and uses side effects, but it works for now self.assign(self.lcsc_part, self.PART_NUMBERS[length]) @@ -139,6 +147,8 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class Te1734839(Fpc050Top, FootprintPassiveConnector): """TE x-1734839 FFC/FPC connector, 0.50mm pitch horizontal top contacts.""" allowed_positions = range(5, 50) + + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_FFC-FPC:TE_{length // 10}-1734839-{length % 10}_1x{length:02d}-1MP_P0.5mm_Horizontal', "TE Connectivity", f"{length // 10}-1734839-{length % 10}") @@ -178,6 +188,7 @@ class HiroseFh35cshw(Fpc030TopBottom, FootprintPassiveConnector, JlcPart): PART_NUMBERS = { # partial list of the ones currently used 31: 'C424662', } + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: # TODO this isn't the intended hook and uses side effects, but it works for now self.assign(self.lcsc_part, self.PART_NUMBERS[length]) diff --git a/edg/parts/PassiveConnector_Header.py b/edg/parts/PassiveConnector_Header.py index c4db3c172..14492baa0 100644 --- a/edg/parts/PassiveConnector_Header.py +++ b/edg/parts/PassiveConnector_Header.py @@ -1,4 +1,7 @@ from typing import Tuple + +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -11,6 +14,7 @@ class PinHeader254(PassiveConnector): class PinHeader254Vertical(PinHeader254, FootprintPassiveConnector): """Generic 2.54mm pin header in vertical through-hole.""" allowed_pins = range(1, 40+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_PinHeader_2.54mm:PinHeader_1x{length:02d}_P2.54mm_Vertical', "Generic", f"PinHeader2.54 1x{length}") @@ -19,6 +23,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class PinHeader254Horizontal(PinHeader254, FootprintPassiveConnector): """Generic 2.54mm pin header in horizontal (right-angle) through-hole.""" allowed_pins = range(1, 40+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_PinHeader_2.54mm:PinHeader_1x{length:02d}_P2.54mm_Horizontal', "Generic", f"PinHeader2.54 1x{length} Horizontal") @@ -27,6 +32,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class PinSocket254(FootprintPassiveConnector): """Generic 2.54mm pin socket in vertical through-hole.""" allowed_pins = range(1, 40+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_PinSocket_2.54mm:PinSocket_1x{length:02d}_P2.54mm_Vertical', "Generic", f"PinSocket2.54 1x{length}") @@ -35,6 +41,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class PinHeader254DualShroudedInline(FootprintPassiveConnector): """Generic 2.54mm dual-row pin header in edge-inline.""" allowed_pins = {6} + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'edg:PinHeader_2x{length//2:02d}_P2.54mm_EdgeInline', "Generic", f"PinHeader2.54 Shrouded 2x{length//2}") @@ -43,6 +50,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class PinHeader127DualShrouded(FootprintPassiveConnector, JlcPart): """Generic dual-row 1.27mm pin header in vertical through-hole pinned in zigzag.""" allowed_pins = [10] # TODO support more + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: assert length == 10, "TODO support more lengths" self.assign(self.lcsc_part, 'C2962219') @@ -60,6 +68,7 @@ class JstXh(FootprintPassiveConnector): class JstXhAVertical(JstXh): """JST B*B-XH-A series connector: 2.50mm shrouded and polarized, in vertical through-hole.""" allowed_pins = list(range(2, 16+1)) + [20] + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_JST:JST_XH_B{length}B-XH-A_1x{length:02d}_P2.50mm_Vertical', "JST", f"B{length}B-XH-A") @@ -68,6 +77,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class JstXhAHorizontal(JstXh): """JST S*B-XH-A series connector: 2.50mm shrouded and polarized, in horizontal through-hole.""" allowed_pins = list(range(2, 16+1)) + [20] + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_JST:JST_XH_S{length}B-XH-A_1x{length:02d}_P2.50mm_Vertical', "JST", f"S{length}B-XH-A") @@ -81,6 +91,7 @@ class JstPh(FootprintPassiveConnector): class JstPhKVertical(JstPh): """JST B*B-PH-K series connector: 2.00mm shrouded and polarized, in vertical through-hole.""" allowed_pins = range(2, 16+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_JST:JST_PH_B{length}B-PH-K_1x{length:02d}_P2.00mm_Vertical', "JST", f"B{length}B-PH-K") @@ -106,6 +117,7 @@ class JstPhKHorizontal(JstPh, JlcPart): 15: 'C157936', 16: 'C157934', } + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: self.assign(self.lcsc_part, self.PART_NUMBERS[length]) self.assign(self.actual_basic_part, False) @@ -116,6 +128,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class JstPhSmVertical(JstPh): """JST B*B-PH-SM4 series connector: 2.00mm shrouded and polarized, in vertical surface-mount.""" allowed_pins = range(2, 16+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_JST:JST_PH_B{length}B-PH-SM4-TB_1x{length:02d}-1MP_P2.00mm_Vertical', "JST", f"B{length}B-PH-SM4-TB") @@ -133,6 +146,7 @@ class JstPhSmVerticalJlc(JlcPart, JstPhSmVertical): 8: 'C519165', 14: 'C278813', } + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: # TODO this isn't the intended hook and uses side effects, but it works for now self.assign(self.lcsc_part, self.PART_NUMBERS[length]) @@ -160,6 +174,7 @@ class JstShSmHorizontal(FootprintPassiveConnector, JlcPart): 20: 'C160415', } allowed_pins = PART_NUMBERS.keys() + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: # TODO this isn't the intended hook and uses side effects, but it works for now self.assign(self.lcsc_part, self.PART_NUMBERS[length]) @@ -177,6 +192,7 @@ class Picoblade(FootprintPassiveConnector): class Picoblade53398(Picoblade): """Picoblade connector in surface-mount vertical.""" allowed_pins = list(range(2, 16+1)) + [20] + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_Molex:Molex_PicoBlade_53398-{length:02d}71_1x{length:02d}-1MP_P1.25mm_Vertical', "Molex", f"53398{length:02d}71") @@ -185,6 +201,7 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class Picoblade53261(Picoblade): """Picoblade connector in surface-mount horizontal.""" allowed_pins = list(range(2, 16+1)) + [20] + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_Molex:Molex_PicoBlade_53261-{length:02d}71_1x{length:02d}-1MP_P1.25mm_Vertical', "Molex", f"53261{length:02d}71") @@ -194,6 +211,7 @@ class MolexSl(FootprintPassiveConnector): """Molex SL series connector: 2.54mm shrouded and polarized, in vertical through-hole. Breadboard wire compatible - especially for debugging in a pinch.""" allowed_pins = range(2, 25+1) + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector_Molex:Molex_SL_171971-00{length:02d}_1x{length:02d}_P2.54mm_Vertical', "Molex", f"171971-00{length:02d}_1x{length:02d}") diff --git a/edg/parts/PassiveConnector_TagConnect.py b/edg/parts/PassiveConnector_TagConnect.py index 64f3552b9..5c70aca47 100644 --- a/edg/parts/PassiveConnector_TagConnect.py +++ b/edg/parts/PassiveConnector_TagConnect.py @@ -1,4 +1,7 @@ from typing import Tuple + +from typing_extensions import override + from ..abstract_parts import * @@ -10,6 +13,7 @@ class TagConnect(FootprintPassiveConnector): class TagConnectLegged(TagConnect): """Tag-connect pogo pin pad for the legged version. Compatible with non-legged versions.""" allowed_pins = {6, 10, 14} # KiCad only has footprints for 2x03, 2x05, 2x07 + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector:Tag-Connect_TC20{length // 2}0-IDC-FP_2x{length // 2:02d}_P1.27mm_Vertical', '', '') # no physical part @@ -17,5 +21,6 @@ def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: class TagConnectNonLegged(TagConnect): """Tag-connect pogo pin pad for the non-legged version. NOT compatible with legged versions.""" allowed_pins = {6, 10} # KiCad only has footprints for 2x03 and 2x05 + @override def part_footprint_mfr_name(self, length: int) -> Tuple[str, str, str]: return (f'Connector:Tag-Connect_TC20{length // 2}0-IDC-NL_2x{length // 2:02d}_P1.27mm_Vertical', '', '') # no physical part diff --git a/edg/parts/PowerConditioning.py b/edg/parts/PowerConditioning.py index fdbdb7ddb..d77e3ef62 100644 --- a/edg/parts/PowerConditioning.py +++ b/edg/parts/PowerConditioning.py @@ -1,5 +1,7 @@ from typing import Optional, cast +from typing_extensions import override + from ..abstract_parts import * from ..electronics_model.PassivePort import PassiveAdapterVoltageSink, PassiveAdapterVoltageSource @@ -10,6 +12,7 @@ def __init__(self) -> None: self.pos = self.Port(VoltageSink()) self.neg = self.Port(Ground()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -203,6 +206,7 @@ def __init__(self, diode_voltage_drop: RangeLike, fet_rds_on: RangeLike) -> None self.diode_voltage_drop = self.ArgParameter(diode_voltage_drop) self.fet_rds_on = self.ArgParameter(fet_rds_on) + @override def contents(self) -> None: super().contents() @@ -269,6 +273,7 @@ def __init__(self, gate_resistor: RangeLike = 10 * kOhm(tol=0.05), rds_on: Range self.gate_resistor = self.ArgParameter(gate_resistor) self.rds_on = self.ArgParameter(rds_on) + @override def contents(self) -> None: super().contents() output_current_draw = self.pwr_out.link().current_drawn @@ -315,6 +320,7 @@ def __init__(self, r1_val: RangeLike = 100 * kOhm(tol=0.01), r2_val: RangeLike = self.r2_val = self.ArgParameter(r2_val) self.rds_on = self.ArgParameter(rds_on) + @override def contents(self) -> None: super().contents() self.r1 = self.Block(Resistor(resistance=self.r1_val)) @@ -383,6 +389,7 @@ def __init__(self, pull_resistance: RangeLike = 10 * kOhm(tol=0.05), amp_resista self.amp_resistance = self.ArgParameter(amp_resistance) self.diode_drop = self.ArgParameter(diode_drop) + @override def contents(self) -> None: super().contents() control_voltage = self.btn_in.link().voltage.hull(self.gnd.link().voltage) @@ -455,6 +462,7 @@ def __init__(self, pull_resistance: RangeLike = 10 * kOhm(tol=0.05), amp_resista self.btn_out = self.Export(self.pwr_gate.btn_out) self.control = self.Export(self.pwr_gate.control) + @override def contents(self) -> None: super().contents() with self.implicit_connect( diff --git a/edg/parts/PriceGetter.py b/edg/parts/PriceGetter.py index ec4105f72..816283f1f 100644 --- a/edg/parts/PriceGetter.py +++ b/edg/parts/PriceGetter.py @@ -2,6 +2,8 @@ import os from typing import List, Tuple, Dict, Optional +from typing_extensions import override + from .. import edgir from ..abstract_parts import * @@ -11,6 +13,7 @@ def __init__(self, design: CompiledDesign): self.design = design self.part_list: Dict[str, int] = {} + @override def visit_block(self, context: TransformUtil.TransformContext, block: edgir.BlockTypes) -> None: lcsc_part_number = self.design.get_value(context.path.to_tuple() + ('lcsc_part',)) part = self.design.get_value(context.path.to_tuple() + ('fp_part',)) @@ -87,6 +90,7 @@ def generate_price(self, lcsc_part_number: str, quantity: int) -> Optional[float temp_price = price return quantity * temp_price + @override def run(self, design: CompiledDesign, args: Dict[str, str]={}) -> List[Tuple[edgir.LocalPath, str]]: assert not args price_list = PartQuantityTransform(design).run() diff --git a/edg/parts/ResetGenerator_Apx803s.py b/edg/parts/ResetGenerator_Apx803s.py index 25d561db1..d1f452322 100644 --- a/edg/parts/ResetGenerator_Apx803s.py +++ b/edg/parts/ResetGenerator_Apx803s.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -15,6 +17,7 @@ def __init__(self, reset_threshold: RangeLike) -> None: self.generator_param(self.reset_threshold) self.actual_reset_threshold = self.Parameter(RangeExpr()) + @override def generate(self) -> None: super().generate() parts = [ # output range, part number, lcsc diff --git a/edg/parts/ResistiveSensor.py b/edg/parts/ResistiveSensor.py index 90127eb42..3cd194790 100644 --- a/edg/parts/ResistiveSensor.py +++ b/edg/parts/ResistiveSensor.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -20,6 +22,7 @@ def __init__(self, resistance_range: RangeLike, fixed_resistance: RangeLike) -> self.actual_impedance = self.Parameter(RangeExpr()) self.actual_series_impedance = self.Parameter(RangeExpr()) + @override def contents(self) -> None: self.top = self.Block(Resistor(self.fixed_resistance, voltage=self.input.link().voltage)) self.bot = self.Block(PassiveConnector(2)) diff --git a/edg/parts/RfModules.py b/edg/parts/RfModules.py index c73141b9b..0866a735a 100644 --- a/edg/parts/RfModules.py +++ b/edg/parts/RfModules.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -27,6 +29,7 @@ def __init__(self) -> None: self.rssi = self.Port(DigitalSource.from_bidir(digital_model), optional=True) self.associate = self.Port(DigitalSource.from_bidir(digital_model), optional=True) + @override def contents(self) -> None: super().contents() self.footprint( @@ -70,6 +73,7 @@ def __init__(self) -> None: self.rssi = self.Export(self.ic.rssi, optional=True) self.associate = self.Export(self.ic.associate, optional=True) + @override def contents(self) -> None: super().contents() @@ -102,6 +106,7 @@ def __init__(self) -> None: self.cts = self.Port(DigitalSink.from_bidir(digital_model), optional=True) self.rts = self.Port(DigitalSource.from_bidir(digital_model), optional=True) + @override def contents(self) -> None: super().contents() self.footprint( diff --git a/edg/parts/Rf_Pn7160.py b/edg/parts/Rf_Pn7160.py index 52465b417..8f6451bdb 100644 --- a/edg/parts/Rf_Pn7160.py +++ b/edg/parts/Rf_Pn7160.py @@ -1,6 +1,8 @@ from typing import Tuple from math import pi +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -42,6 +44,7 @@ def __init__(self, ant_footprint: StringLike, freq: FloatLike, inductance: Float self.z_real = self.Parameter(FloatExpr()) self.z_imag = self.Parameter(FloatExpr()) + @override def generate(self) -> None: super().generate() @@ -76,6 +79,7 @@ def __init__(self, target_q: FloatLike, ant_r: FloatLike, ant_x: FloatLike): self.z_real = self.Parameter(FloatExpr()) self.z_imag = self.Parameter(FloatExpr()) + @override def generate(self) -> None: super().generate() @@ -119,6 +123,7 @@ def __init__(self, freq_cutoff: FloatLike, inductance: FloatLike, input_res: Flo self.out2 = self.Port(Passive()) self.gnd = self.Port(Ground.empty(), [Common]) + @override def generate(self) -> None: super().generate() @@ -168,6 +173,7 @@ def __init__(self, freq: FloatLike, src_r: FloatLike, src_x: FloatLike, snk_r: F self.out2 = self.Port(Passive()) self.gnd = self.Port(Ground.empty(), [Common]) + @override def generate(self) -> None: super().generate() @@ -198,6 +204,7 @@ def __init__(self, resistance: RangeLike, capacitance: RangeLike, voltage: Range self.out1 = self.Port(Passive()) self.out2 = self.Port(Passive()) + @override def contents(self) -> None: super().contents() rrx_model = Resistor(resistance=self.resistance) @@ -266,6 +273,7 @@ def __init__(self) -> None: input_threshold_abs=(0.4, 1.1)*Volt )) + @override def contents(self) -> None: self.footprint( 'U', 'Package_DFN_QFN:HVQFN-40-1EP_6x6mm_P0.5mm_EP4.1x4.1mm', @@ -327,6 +335,7 @@ def __init__(self) -> None: self.i2c = self.Export(self.ic.i2c) self.irq = self.Export(self.ic.irq) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Rf_Sx1262.py b/edg/parts/Rf_Sx1262.py index 87cba6c8f..0959289a7 100644 --- a/edg/parts/Rf_Sx1262.py +++ b/edg/parts/Rf_Sx1262.py @@ -1,6 +1,8 @@ from typing import Tuple from math import pi +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -25,6 +27,7 @@ def __init__(self) -> None: # note that most other comparable RF switches do not have single-pin control # a future revision so the application circuit will replace this part with a dual-pin control circuit + @override def contents(self) -> None: super().contents() @@ -60,6 +63,7 @@ def __init__(self) -> None: self.ctrl = self.Port(DigitalSink.empty()) self.vdd = self.Port(VoltageSink.empty(), [Power]) + @override def contents(self) -> None: super().contents() @@ -119,6 +123,7 @@ def __init__(self, frequency: FloatLike, src_resistance: FloatLike, src_reactanc self.generator_param(self.frequency, self.src_resistance, self.src_reactance, self.load_resistance, self.tolerance) + @override def generate(self) -> None: super().generate() @@ -183,6 +188,7 @@ def __init__(self) -> None: input_threshold_factor=(0.2, 0.7) )) + @override def contents(self) -> None: self.footprint( 'U', 'Package_DFN_QFN:QFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm', @@ -239,6 +245,7 @@ def __init__(self) -> None: # note, DIO2 is used for RF switch, DIO3 is used for TCXO control; these functions cannot be remapped elsewhere self.busy = self.Export(self.ic.busy) # "the BUSY line is mandatory" + @override def contents(self) -> None: super().contents() self.connect(self.ic.vbat_io, self.pwr) diff --git a/edg/parts/RotaryEncoder_Alps.py b/edg/parts/RotaryEncoder_Alps.py index 7d39efa56..bd7212899 100644 --- a/edg/parts/RotaryEncoder_Alps.py +++ b/edg/parts/RotaryEncoder_Alps.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -6,6 +8,7 @@ class Ec11eWithSwitch(RotaryEncoderSwitch, RotaryEncoder, JlcPart, FootprintBloc """Generic EC11E PTH rotary with pushbutton switch. Default part is EC11E18244A5, with 1.5mm pushbutton travel, 36 detents (finest), but footprint should be compatible with other parts in the EC11E w/ switch series""" + @override def contents(self) -> None: super().contents() @@ -29,6 +32,7 @@ class Ec11j15WithSwitch(RotaryEncoderSwitch, RotaryEncoder, JlcPart, FootprintBl """Generic EC11J15 SMD rotary with pushbutton switch. Default part is EC11J1525402, with 1.5mm pushbutton travel, 30 detents (finest), but footprint should be compatible with other parts in the EC11J15 w/ switch series""" + @override def contents(self) -> None: super().contents() @@ -52,6 +56,7 @@ def contents(self) -> None: class Ec05e(RotaryEncoder, JlcPart, FootprintBlock): """Generic EC05E PTH rotary encoder with hollow shaft. Default part is EC05E1220401, horizontal-mount part.""" + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/RotaryEncoder_Bourns.py b/edg/parts/RotaryEncoder_Bourns.py index b2d47e3e1..22df2b9b8 100644 --- a/edg/parts/RotaryEncoder_Bourns.py +++ b/edg/parts/RotaryEncoder_Bourns.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -5,6 +7,7 @@ class Pec11s(RotaryEncoderSwitch, RotaryEncoder, FootprintBlock): """Bourns PEC11S SMD rotary with pushbutton switch. Default part is PEC11S-929K-S0015, but entire series is footprint-compatible. While the copper pattern is compatible with the EC11J15, there is a different mounting boss.""" + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/Rtc_Pcf2129.py b/edg/parts/Rtc_Pcf2129.py index 75d641196..554c5e19a 100644 --- a/edg/parts/Rtc_Pcf2129.py +++ b/edg/parts/Rtc_Pcf2129.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -36,6 +38,7 @@ def __init__(self) -> None: voltage_out=self.pwr_bat.link().voltage )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -74,6 +77,7 @@ def __init__(self) -> None: self.clkout = self.Export(self.ic.clkout, optional=True) self.int = self.Export(self.ic.int, optional=True) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/SdCards.py b/edg/parts/SdCards.py index 27c294958..48da72e21 100644 --- a/edg/parts/SdCards.py +++ b/edg/parts/SdCards.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -35,6 +37,7 @@ def __init__(self) -> None: self.cd = self.Port(sw_model, optional=True) self.wp = self.Port(sw_model, optional=True) + @override def contents(self) -> None: super().contents() # TODO do we need capacitors? @@ -66,6 +69,7 @@ class MicroSdSocket(SdCard): class Dm3btDsfPejs(MicroSdSocket, Connector, FootprintBlock): + @override def contents(self) -> None: super().contents() # TODO add pull up resistors and capacitors and w/e? @@ -89,6 +93,7 @@ def contents(self) -> None: class Molex1040310811(MicroSdSocket, Connector, JlcPart, FootprintBlock): + @override def contents(self) -> None: super().contents() # TODO add pull up resistors and capacitors and w/e? diff --git a/edg/parts/SolidStateRelay_G3VM_61GR2.py b/edg/parts/SolidStateRelay_G3VM_61GR2.py index c5d368cc3..d7c836266 100644 --- a/edg/parts/SolidStateRelay_G3VM_61GR2.py +++ b/edg/parts/SolidStateRelay_G3VM_61GR2.py @@ -1,7 +1,10 @@ +from typing_extensions import override + from ..abstract_parts import * class G3VM_61GR2(SolidStateRelay, FootprintBlock): + @override def contents(self) -> None: super().contents() self.assign(self.led_forward_voltage, (1.18, 1.48)*Volt) diff --git a/edg/parts/SolidStateRelay_Toshiba.py b/edg/parts/SolidStateRelay_Toshiba.py index c3c2cb3d0..9dab1ffc8 100644 --- a/edg/parts/SolidStateRelay_Toshiba.py +++ b/edg/parts/SolidStateRelay_Toshiba.py @@ -1,7 +1,10 @@ +from typing_extensions import override + from ..abstract_parts import * class Tlp3545a(SolidStateRelay, FootprintBlock): + @override def contents(self) -> None: super().contents() self.assign(self.led_forward_voltage, (1.50, 1.80)*Volt) @@ -27,6 +30,7 @@ def contents(self) -> None: class Tlp170am(SolidStateRelay, FootprintBlock): + @override def contents(self) -> None: super().contents() self.assign(self.led_forward_voltage, (1.1, 1.4)*Volt) # 1.27 nominal diff --git a/edg/parts/SpeakerDriver_Analog.py b/edg/parts/SpeakerDriver_Analog.py index 7ce1f910c..82a2d4f47 100644 --- a/edg/parts/SpeakerDriver_Analog.py +++ b/edg/parts/SpeakerDriver_Analog.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -21,6 +23,7 @@ def __init__(self) -> None: self.byp = self.Port(Passive()) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', @@ -51,6 +54,7 @@ def __init__(self) -> None: self.sig = self.Port(AnalogSink.empty(), [Input]) self.spk = self.Port(SpeakerDriverPort(AnalogSource.empty()), [Output]) + @override def contents(self) -> None: super().contents() # TODO size component based on higher level input? @@ -107,6 +111,7 @@ def __init__(self) -> None: self.vo1 = self.Port(speaker_port) self.vo2 = self.Port(speaker_port) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:MSOP-8-1EP_3x3mm_P0.65mm_EP1.68x1.88mm_ThermalVias', @@ -144,6 +149,7 @@ def __init__(self, gain: RangeLike = Range.from_tolerance(20, 0.2)): self.gain = self.ArgParameter(gain) + @override def contents(self) -> None: import math super().contents() @@ -206,6 +212,7 @@ def __init__(self) -> None: self.vop = self.Port(speaker_port) self.von = self.Port(speaker_port) + @override def contents(self) -> None: self.footprint( 'U', 'Package_SO:MSOP-8_3x3mm_P0.65mm', @@ -238,6 +245,7 @@ def __init__(self) -> None: self.sig = self.Port(AnalogSink.empty(), [Input]) self.spk = self.Port(SpeakerDriverPort(AnalogSource.empty()), [Output]) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/SpeakerDriver_Max98357a.py b/edg/parts/SpeakerDriver_Max98357a.py index f0f060034..c49aec81a 100644 --- a/edg/parts/SpeakerDriver_Max98357a.py +++ b/edg/parts/SpeakerDriver_Max98357a.py @@ -1,5 +1,7 @@ from typing import Dict +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -24,6 +26,7 @@ def __init__(self) -> None: self.generator_param(self.part, self.footprint_spec) + @override def generate(self) -> None: super().generate() if not self.get(self.footprint_spec) or \ @@ -85,6 +88,7 @@ def __init__(self) -> None: self.i2s = self.Export(self.ic.i2s, [Input]) self.out = self.Export(self.ic.out, [Output]) + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/SpiMemory_93Lc.py b/edg/parts/SpiMemory_93Lc.py index 116f0da4b..539c06503 100644 --- a/edg/parts/SpiMemory_93Lc.py +++ b/edg/parts/SpiMemory_93Lc.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -40,6 +42,7 @@ def __init__(self, size: RangeLike): self.size = self.ArgParameter(size) self.generator_param(self.size) + @override def generate(self) -> None: super().generate() suitable_parts = [part for part in self.PARTS if part[0] in self.get(self.size)] @@ -68,6 +71,7 @@ class E93Lc_B(SpiMemory): """93LCxxB series of SPI EEPROMs. The E prefix is because Python identifiers can't start with numbers Note, A variant is 8-bit word, B variant is 16-bit word """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/SpiMemory_W25q.py b/edg/parts/SpiMemory_W25q.py index 07a841e4e..41e5fd6e6 100644 --- a/edg/parts/SpiMemory_W25q.py +++ b/edg/parts/SpiMemory_W25q.py @@ -1,5 +1,7 @@ from typing import Any +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -42,6 +44,7 @@ def __init__(self, size: RangeLike): self.size = self.ArgParameter(size) self.generator_param(self.size) + @override def generate(self) -> None: super().generate() suitable_parts = [part for part in self.PARTS if part[0] in self.get(self.size)] @@ -75,6 +78,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.generator_param(self.io2.is_connected(), self.io3.is_connected()) + @override def contents(self) -> None: super().contents() @@ -89,6 +93,7 @@ def contents(self) -> None: capacitance=0.1*uFarad(tol=0.2) )).connected(self.gnd, self.pwr) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/StepperDriver_A4988.py b/edg/parts/StepperDriver_A4988.py index a5947db0e..f6648390f 100644 --- a/edg/parts/StepperDriver_A4988.py +++ b/edg/parts/StepperDriver_A4988.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -67,6 +69,7 @@ def __init__(self) -> None: self.assign(self.vbb2.current_draw, self.out2a.link().current_drawn.hull(self.out2b.link().current_drawn).abs().hull((0, 0)) + kVbbDraw) + @override def contents(self) -> None: self.footprint( 'U', 'Package_DFN_QFN:TQFN-28-1EP_5x5mm_P0.5mm_EP3.25x3.25mm_ThermalVias', @@ -136,6 +139,7 @@ def __init__(self, step_resolution: IntLike = 16, self.out2a = self.Export(self.ic.out2a) self.out2b = self.Export(self.ic.out2b) + @override def contents(self) -> None: super().contents() @@ -168,6 +172,7 @@ def contents(self) -> None: self.connect(isense.a, sensen) self.connect(isense.b.adapt_to(Ground()), self.gnd) + @override def generate(self) -> None: super().generate() @@ -229,6 +234,7 @@ def __init__(self, step_resolution: IntLike = 16): self.out2a = self.Export(self.model.out2a) self.out2b = self.Export(self.model.out2b) + @override def generate(self) -> None: super().generate() diff --git a/edg/parts/SwitchMatrix.py b/edg/parts/SwitchMatrix.py index 8f70896d3..46ad77761 100644 --- a/edg/parts/SwitchMatrix.py +++ b/edg/parts/SwitchMatrix.py @@ -1,5 +1,7 @@ from typing import cast, Optional, Tuple +from typing_extensions import override + from ..abstract_parts import * @@ -14,9 +16,11 @@ class SwitchMatrix(HumanInterface, GeneratorBlock, SvgPcbTemplateBlock): This generates per-switch diodes which allows multiple keys to be pressed simultaneously. Diode anodes are attached to the rows, while cathodes go through each switch to the cols. """ + @override def _svgpcb_fn_name_adds(self) -> Optional[str]: return f"{self._svgpcb_get(self.ncols)}_{self._svgpcb_get(self.nrows)}" + @override def _svgpcb_template(self) -> str: switch_block = self._svgpcb_footprint_block_path_of(['sw[0,0]']) diode_block = self._svgpcb_footprint_block_path_of(['d[0,0]']) @@ -103,6 +107,7 @@ def _svgpcb_template(self) -> str: }} """ + @override def _svgpcb_bbox(self) -> Tuple[float, float, float, float]: return (-1.0, -1.0, self._svgpcb_get(self.ncols) * 0.5 * 25.4 + 1.0, (self._svgpcb_get(self.nrows) + 1) * .5 * 25.4 + 1.0) @@ -118,6 +123,7 @@ def __init__(self, nrows: IntLike, ncols: IntLike, voltage_drop: RangeLike = (0, self.ncols = self.ArgParameter(ncols) self.generator_param(self.nrows, self.ncols) + @override def generate(self) -> None: super().generate() row_ports = {} diff --git a/edg/parts/SwitchedCap_TexasInstruments.py b/edg/parts/SwitchedCap_TexasInstruments.py index aba203f43..56790b3fb 100644 --- a/edg/parts/SwitchedCap_TexasInstruments.py +++ b/edg/parts/SwitchedCap_TexasInstruments.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -27,6 +29,7 @@ def __init__(self) -> None: # input_threshold_abs=(0.8, 2)*Volt # ), optional=True) + @override def contents(self) -> None: super().contents() self.footprint( @@ -58,6 +61,7 @@ def __init__(self, output_resistance_limit: FloatLike = 25 * Ohm, self.output_resistance_limit = self.ArgParameter(output_resistance_limit) self.output_ripple_limit = self.ArgParameter(output_ripple_limit) + @override def contents(self) -> None: super().contents() self.require(self.output_resistance_limit >= 2 * self.ic.SWITCH_RESISTANCE.upper, diff --git a/edg/parts/Switches.py b/edg/parts/Switches.py index 2471a9281..918ccc844 100644 --- a/edg/parts/Switches.py +++ b/edg/parts/Switches.py @@ -1,7 +1,10 @@ +from typing_extensions import override + from ..abstract_parts import * class SmtSwitch(TactileSwitch, FootprintBlock): + @override def contents(self) -> None: super().contents() @@ -19,6 +22,7 @@ def contents(self) -> None: class SmtSwitchRa(TactileSwitch, FootprintBlock): + @override def contents(self) -> None: super().contents() @@ -40,6 +44,7 @@ class KailhSocket(MechanicalKeyswitch, FootprintBlock): Name: Switch_Keyboard_Hotswap_Kailh Location: ${KICAD6_3RD_PARTY}/footprints/com_github_perigoso_keyswitch-kicad-library/Switch_Keyboard_Hotswap_Kailh.pretty """ + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/TestPoint_Keystone.py b/edg/parts/TestPoint_Keystone.py index 8622fcb8a..9dca08f45 100644 --- a/edg/parts/TestPoint_Keystone.py +++ b/edg/parts/TestPoint_Keystone.py @@ -1,9 +1,12 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart class Keystone5015(TestPoint, FootprintBlock, JlcPart): """Keystone 5015 / 5017 (difference in p/n is only from packaging) SMD test point""" + @override def contents(self) -> None: super().contents() self.assign(self.lcsc_part, 'C238130') @@ -21,6 +24,7 @@ def contents(self) -> None: class CompactKeystone5015(TestPoint, FootprintBlock, JlcPart): """Keystone 5015 / 5017 but with an experimental compact footprint""" + @override def contents(self) -> None: super().contents() self.assign(self.lcsc_part, 'C2906768') @@ -38,6 +42,7 @@ def contents(self) -> None: class Keystone5000(TestPoint, FootprintBlock, JlcPart): """Keystone 5000-5004 series PTH test mini points""" + @override def contents(self) -> None: super().contents() self.assign(self.lcsc_part, 'C238122') diff --git a/edg/parts/TestPoint_Rc.py b/edg/parts/TestPoint_Rc.py index faa27a2df..6d0338088 100644 --- a/edg/parts/TestPoint_Rc.py +++ b/edg/parts/TestPoint_Rc.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * @@ -14,6 +16,7 @@ def __init__(self, size: StringLike = '0805'): self.size = self.ArgParameter(size) self.generator_param(self.size) + @override def generate(self) -> None: super().generate() if self.get(self.size) not in self._PART_TABLE: diff --git a/edg/parts/ThermalSensor_FlirLepton.py b/edg/parts/ThermalSensor_FlirLepton.py index d98f27fa4..6641fbb16 100644 --- a/edg/parts/ThermalSensor_FlirLepton.py +++ b/edg/parts/ThermalSensor_FlirLepton.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -34,6 +36,7 @@ def __init__(self) -> None: self.pwr_dwn_l = self.Port(DigitalSink.from_bidir(dio_model)) self.vsync = self.Port(DigitalSource.from_bidir(dio_model), optional=True) + @override def contents(self) -> None: super().contents() @@ -105,6 +108,7 @@ def __init__(self) -> None: self.cci = self.Export(self.ic.cci, doc="I2C-like Command and Control Interface") self.vsync = self.Export(self.ic.vsync, optional=True, doc="Optional frame-sync output") + @override def contents(self) -> None: super().contents() diff --git a/edg/parts/UsbInterface_Ft232h.py b/edg/parts/UsbInterface_Ft232h.py index 1530e04b9..3083afdd0 100644 --- a/edg/parts/UsbInterface_Ft232h.py +++ b/edg/parts/UsbInterface_Ft232h.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .SpiMemory_93Lc import E93Lc_B from .JlcPart import JlcPart @@ -59,6 +61,7 @@ def __init__(self) -> None: self.adbus = self.Port(Vector(DigitalBidir.empty())) self.acbus = self.Port(Vector(DigitalBidir.empty())) + @override def contents(self) -> None: super().contents() @@ -139,6 +142,7 @@ def __init__(self) -> None: self.eedata = self.Port(DigitalBidir.empty()) self.spi = self.Port(SpiController.empty()) + @override def contents(self) -> None: super().contents() self.connect(self.eeclk, self.spi.sck) @@ -175,6 +179,7 @@ def __init__(self) -> None: self.generator_param(self.uart.is_connected(), self.mpsse.is_connected(), self.mpsse_cs.is_connected(), self.adbus.requested()) + @override def contents(self) -> None: # connections from Figure 6.1, bus powered configuration self.vbus_fb = self.Block(SeriesPowerFerriteBead(hf_impedance=(600*Ohm(tol=0.25)))) \ @@ -223,6 +228,7 @@ def contents(self) -> None: self.connect(self.eeprom_spi.eedata, self.ic.eedata) self.connect(self.eeprom_spi.spi, self.eeprom.spi) + @override def generate(self) -> None: # make connections and pin mutual exclusion constraints if self.get(self.uart.is_connected()): diff --git a/edg/parts/UsbPorts.py b/edg/parts/UsbPorts.py index c7aec1669..b3a6f35f2 100644 --- a/edg/parts/UsbPorts.py +++ b/edg/parts/UsbPorts.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -13,6 +15,7 @@ def __init__(self) -> None: self.usb.init_from(UsbDevicePort()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -47,6 +50,7 @@ def __init__(self, voltage_out: RangeLike = UsbConnector.USB2_VOLTAGE_RANGE, # self.cc = self.Port(UsbCcPort(pullup_capable=cc_pullup_capable), optional=True) + @override def contents(self) -> None: super().contents() @@ -96,6 +100,7 @@ def __init__(self, voltage_out: RangeLike = UsbConnector.USB2_VOLTAGE_RANGE, # self.generator_param(self.pwr.is_connected(), self.cc.is_connected()) + @override def generate(self) -> None: super().generate() if self.get(self.cc.is_connected()): # if CC externally connected, connect directly to USB port @@ -118,6 +123,7 @@ class UsbAPlugPads(UsbDeviceConnector, FootprintBlock): def __init__(self) -> None: super().__init__() + @override def contents(self) -> None: super().contents() self.pwr.init_from(VoltageSource( @@ -143,6 +149,7 @@ class UsbMicroBReceptacle(UsbDeviceConnector, FootprintBlock): def __init__(self) -> None: super().__init__() + @override def contents(self) -> None: super().contents() self.pwr.init_from(VoltageSource( @@ -178,6 +185,7 @@ def __init__(self) -> None: self.cc = self.Port(UsbCcPort.empty(), [Input]) self.gnd = self.Port(Ground.empty(), [Common]) + @override def contents(self) -> None: super().contents() pdr_model = PulldownResistor(resistance=5.1*kOhm(tol=0.01)) @@ -186,6 +194,7 @@ def contents(self) -> None: class Tpd2e009(UsbEsdDiode, FootprintBlock, JlcPart): + @override def contents(self) -> None: # Note, also compatible: https://www.diodes.com/assets/Datasheets/DT1452-02SO.pdf # PESD5V0X1BT,215 (different architecture, but USB listed as application) @@ -206,6 +215,7 @@ def contents(self) -> None: class Pesd5v0x1bt(UsbEsdDiode, FootprintBlock, JlcPart): """Ultra low capacitance ESD protection diode (0.9pF typ), suitable for USB and GbE""" + @override def contents(self) -> None: super().contents() self.gnd.init_from(Ground()) @@ -226,6 +236,7 @@ def contents(self) -> None: class Pgb102st23(UsbEsdDiode, FootprintBlock, JlcPart): """ESD suppressor, suitable for high speed protocols including USB2.0, 0.12pF typ""" + @override def contents(self) -> None: super().contents() self.gnd.init_from(Ground()) diff --git a/edg/parts/UsbUart_Cp2102.py b/edg/parts/UsbUart_Cp2102.py index 7f2499452..4232997fa 100644 --- a/edg/parts/UsbUart_Cp2102.py +++ b/edg/parts/UsbUart_Cp2102.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -96,6 +98,7 @@ def __init__(self) -> None: self.rts = self.Export(self.ic.rts, optional=True) self.cts = self.Export(self.ic.cts, optional=True) + @override def contents(self) -> None: super().contents() self.connect(self.ic.regin, self.ic.vbus) diff --git a/edg/parts/VoltageReferences.py b/edg/parts/VoltageReferences.py index 2c311fa3c..325a0602d 100644 --- a/edg/parts/VoltageReferences.py +++ b/edg/parts/VoltageReferences.py @@ -1,3 +1,5 @@ +from typing_extensions import override + from ..abstract_parts import * from .JlcPart import JlcPart @@ -14,6 +16,7 @@ def __init__(self, output_voltage: RangeLike): self.output_voltage = self.ArgParameter(output_voltage) self.generator_param(self.output_voltage) + @override def generate(self) -> None: super().generate() parts = [ # output voltage, table 7.5 @@ -45,6 +48,7 @@ def generate(self) -> None: class Ref30xx(VoltageReference): + @override def contents(self) -> None: with self.implicit_connect( ImplicitConnect(self.gnd, [Common]), diff --git a/examples/test_basickeyboard.py b/examples/test_basickeyboard.py index 61078437e..554e393a0 100644 --- a/examples/test_basickeyboard.py +++ b/examples/test_basickeyboard.py @@ -10,10 +10,13 @@ import unittest +from typing_extensions import override + from edg import * class BasicKeyboard(SimpleBoardTop): + @override def contents(self) -> None: super().contents() @@ -23,6 +26,7 @@ def contents(self) -> None: self.connect(self.sw.cols, self.mcu.gpio.request_vector()) self.connect(self.sw.rows, self.mcu.gpio.request_vector()) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ diff --git a/examples/test_battery_protector.py b/examples/test_battery_protector.py index c48923b7c..3e7889f38 100644 --- a/examples/test_battery_protector.py +++ b/examples/test_battery_protector.py @@ -1,9 +1,12 @@ import unittest +from typing_extensions import override + from edg import * class BatteryProtectorCircuit(BoardTop): + @override def contents(self) -> None: super().contents() self.battery_protector = self.Block(S8261A()) diff --git a/examples/test_bldc_controller.py b/examples/test_bldc_controller.py index eda73bf43..7393c4ec3 100644 --- a/examples/test_bldc_controller.py +++ b/examples/test_bldc_controller.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -76,6 +78,7 @@ def __init__(self) -> None: class BldcController(JlcBoardTop): """Test BLDC (brushless DC motor) driver circuit with position feedback and USB PD """ + @override def contents(self) -> None: super().contents() @@ -172,6 +175,7 @@ def contents(self) -> None: self.Block(AnalogTestPoint()), self.mcu.adc.request(f'curr_{i}')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_ble_joystick.py b/examples/test_ble_joystick.py index 7a36a4760..1f19e47d3 100644 --- a/examples/test_ble_joystick.py +++ b/examples/test_ble_joystick.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class BleJoystick(JlcBoardTop): """BLE joystick with XYAB buttons """ + @override def contents(self) -> None: super().contents() @@ -107,6 +110,7 @@ def contents(self) -> None: self.mp2722.i2c ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_blinky.py b/examples/test_blinky.py index be22671de..0b2ffa323 100644 --- a/examples/test_blinky.py +++ b/examples/test_blinky.py @@ -1,10 +1,13 @@ import unittest +from typing_extensions import override + from edg import * class TestLed(SimpleBoardTop): """The actually simplest circuit, a LED connected to a dummy source.""" + @override def contents(self) -> None: self.gnd = self.Block(DummyGround()) self.src = self.Block(DummyDigitalSource()) @@ -16,6 +19,7 @@ def contents(self) -> None: class TestBlinkyBasic(SimpleBoardTop): """The simplest cirucit, a microcontroller dev board with a LED.""" + @override def contents(self) -> None: self.mcu = self.Block(Nucleo_F303k8()) self.led = self.Block(IndicatorLed()) @@ -30,6 +34,7 @@ class TestBlinkyEmpty(SimpleBoardTop): class TestBlinkyBasicBattery(SimpleBoardTop): """The simplest cirucit, a microcontroller dev board with a LED, powered from a battery""" + @override def contents(self) -> None: self.bat = self.Block(AaBatteryStack(4)) self.mcu = self.Block(Xiao_Rp2040()) @@ -42,6 +47,7 @@ def contents(self) -> None: class TestBlinkyIncomplete(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -53,6 +59,7 @@ def contents(self) -> None: class TestBlinkyRegulated(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -66,6 +73,7 @@ def contents(self) -> None: class TestBlinkyComplete(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -77,6 +85,7 @@ def contents(self) -> None: self.connect(self.reg.pwr_out, self.mcu.pwr) self.connect(self.mcu.gpio.request('led'), self.led.signal) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -85,6 +94,7 @@ def refinements(self) -> Refinements: class TestBlinkyExpanded(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -104,6 +114,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request(f'led{i}'), self.led[i].signal) self.connect(self.usb.gnd, self.led[i].gnd) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -112,6 +123,7 @@ def refinements(self) -> Refinements: class TestBlinkyImplicit(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -133,6 +145,7 @@ def contents(self) -> None: self.led[i] = imp.Block(IndicatorLed()) self.connect(self.mcu.gpio.request(f'led{i}'), self.led[i].signal) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -141,6 +154,7 @@ def refinements(self) -> Refinements: class TestBlinkyChain(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -160,6 +174,7 @@ def contents(self) -> None: for i in range(4): (self.led[i], ), _ = self.chain(self.mcu.gpio.request(f'led{i}'), imp.Block(IndicatorLed())) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -168,6 +183,7 @@ def refinements(self) -> Refinements: class TestBlinkyMicro(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -187,6 +203,7 @@ def contents(self) -> None: for i in range(4): (self.led[i], ), _ = self.chain(self.mcu.gpio.request(f'led{i}'), imp.Block(IndicatorLed())) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -216,6 +233,7 @@ def __init__(self) -> None: output_threshold_offset=(0.2, -0.3) )) + @override def contents(self) -> None: super().contents() self.footprint( @@ -245,6 +263,7 @@ def __init__(self) -> None: self.connect(self.ic.gnd, self.cap.gnd, self.gnd) self.connect(self.ic.vout, self.out) + @override def contents(self) -> None: super().contents() @@ -261,11 +280,13 @@ def __init__(self) -> None: self.connect(self.cap.pwr, self.pwr) self.connect(self.cap.gnd, self.gnd) + @override def contents(self) -> None: super().contents() class TestBlinkyWithLibrary(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -288,6 +309,7 @@ def contents(self) -> None: self.mag = imp.Block(Lf21215tmr()) self.connect(self.mcu.gpio.request('mag'), self.mag.out) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -305,6 +327,7 @@ def refinements(self) -> Refinements: class TestBlinkyWithLibraryExport(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -327,6 +350,7 @@ def contents(self) -> None: self.mag = imp.Block(Lf21215tmr_Export()) self.connect(self.mcu.gpio.request('mag'), self.mag.out) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -351,6 +375,7 @@ def __init__(self, count: IntLike) -> None: self.count = self.ArgParameter(count) self.generator_param(self.count) + @override def generate(self) -> None: super().generate() self.led = ElementDict[IndicatorLed]() @@ -362,6 +387,7 @@ def generate(self) -> None: class TestBlinkyArray(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -381,6 +407,7 @@ def contents(self) -> None: # optionally, you may have also instantiated your magnetic sensor + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -398,6 +425,7 @@ def refinements(self) -> Refinements: class TestBlinkyPacked(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -417,6 +445,7 @@ def contents(self) -> None: # optionally, you may have also instantiated your magnetic sensor + @override def multipack(self) -> None: self.res_pack = self.PackedBlock(ResistorArray()) self.pack(self.res_pack.elements.request('0'), ['led', 'led[0]', 'res']) @@ -424,6 +453,7 @@ def multipack(self) -> None: self.pack(self.res_pack.elements.request('2'), ['led', 'led[2]', 'res']) self.pack(self.res_pack.elements.request('3'), ['led', 'led[3]', 'res']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -455,6 +485,7 @@ def __init__(self) -> None: self.sp = self.Port(Passive.empty()) self.sn = self.Port(Passive.empty()) + @override def contents(self) -> None: super().contents() self.Q1 = self.Block(Bjt.Npn((0, 5)*Volt, 0*Amp(tol=0))) @@ -463,6 +494,7 @@ def contents(self) -> None: class TestBlinkyWithSchematicImport(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -485,6 +517,7 @@ def contents(self) -> None: self.connect(self.conn.pins.request('3'), self.sense.sp) self.connect(self.conn.pins.request('4'), self.sense.sn) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -508,6 +541,7 @@ def __init__(self) -> None: self.sp = self.Port(Passive.empty()) self.sn = self.Port(Passive.empty()) + @override def contents(self) -> None: super().contents() self.Q1 = self.Block(Bjt.Npn((0, 5)*Volt, 0*Amp(tol=0))) @@ -523,6 +557,7 @@ def contents(self) -> None: class TestBlinkyWithModeledSchematicImport(SimpleBoardTop): + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -545,6 +580,7 @@ def contents(self) -> None: self.connect(self.conn.pins.request('3'), self.sense.sp) self.connect(self.conn.pins.request('4'), self.sense.sn) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_can_adapter.py b/examples/test_can_adapter.py index e1d7c525a..35b69970c 100644 --- a/examples/test_can_adapter.py +++ b/examples/test_can_adapter.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -12,6 +14,7 @@ def __init__(self) -> None: self.can = self.Port(CanDiffPort()) + @override def contents(self) -> None: super().contents() self.footprint( @@ -26,6 +29,7 @@ def contents(self) -> None: class CanAdapter(JlcBoardTop): + @override def contents(self) -> None: super().contents() @@ -66,6 +70,7 @@ def contents(self) -> None: self.mcu.adc.request('vobd_sense') ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_datalogger.py b/examples/test_datalogger.py index 2c42d1854..e34e938e7 100644 --- a/examples/test_datalogger.py +++ b/examples/test_datalogger.py @@ -1,10 +1,13 @@ import unittest +from typing_extensions import override + from edg import * from .test_high_switch import CalSolPowerConnector, CalSolCanBlock, CanFuse class Datalogger(BoardTop): + @override def contents(self) -> None: super().contents() @@ -112,6 +115,7 @@ def contents(self) -> None: (self.v5sense, ), _ = self.chain(self.v5, imp.Block(div_model), self.mcu.adc.request('v5sense')) (self.vscsense, ), _ = self.chain(self.buffer.sc_out, imp.Block(div_model), self.mcu.adc.request('vscsense')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_deskcontroller.py b/examples/test_deskcontroller.py index 08c91967c..0e3b9d8ba 100644 --- a/examples/test_deskcontroller.py +++ b/examples/test_deskcontroller.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -32,6 +34,7 @@ class DeskController(JlcBoardTop): """Standing desk controller for desks with a Jiecang controller https://community.home-assistant.io/t/desky-standing-desk-esphome-works-with-desky-uplift-jiecang-assmann-others/383790 """ + @override def contents(self) -> None: super().contents() @@ -104,6 +107,7 @@ def contents(self) -> None: self.Block(DigitalTestPoint('npx')), imp.Block(NeopixelArray(6))) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_esp_programmer.py b/examples/test_esp_programmer.py index 9b5a7bee1..f128902b4 100644 --- a/examples/test_esp_programmer.py +++ b/examples/test_esp_programmer.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -25,6 +27,7 @@ def __init__(self, *, pwr_current_draw: RangeLike = (0, 0)*mAmp): class EspProgrammer(JlcBoardTop): """USB UART converter board set up for ESP programming including auto-program circuit.""" + @override def contents(self) -> None: super().contents() self.usb_uart = self.Block(UsbCReceptacle()) @@ -63,6 +66,7 @@ def contents(self) -> None: (self.led, ), _ = self.chain(self.usbconv.suspend, imp.Block(IndicatorSinkLed(Led.White))) (self.led_en, ), _ = self.chain(self.usbconv.rts, imp.Block(IndicatorSinkLed(Led.Red))) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_fcml.py b/examples/test_fcml.py index 551d138e0..ef18e17ae 100644 --- a/examples/test_fcml.py +++ b/examples/test_fcml.py @@ -1,6 +1,8 @@ import unittest from typing import Optional, Dict +from typing_extensions import override + from edg import * from edg.abstract_parts.PartsTable import ExperimentalUserFnPartsTable @@ -18,6 +20,7 @@ def __init__(self, current: RangeLike): class SeriesPowerDiode(DiscreteApplication, KiCadImportableBlock): """Series diode that propagates voltage""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'Device:D' return {'A': self.pwr_in, 'K': self.pwr_out} @@ -84,6 +87,7 @@ def __init__(self, is_first: BoolLike = False, *, self.is_first = self.ArgParameter(is_first) self.generator_param(self.is_first, self.high_boot_out.is_connected()) + @override def generate(self) -> None: super().generate() # control path is still defined in HDL @@ -210,6 +214,7 @@ def __init__(self, input_voltage: RangeLike, output_voltage: RangeLike, frequenc self.actual_dutycycle = self.Parameter(RangeExpr()) self.actual_inductor_current_ripple = self.Parameter(RangeExpr()) + @override def generate(self) -> None: super().generate() inductor_scale = self.get(self.inductor_scale) @@ -291,6 +296,7 @@ def __init__(self, levels: IntLike, ratios: RangeLike, frequency: RangeLike, *, self.ratios = self.ArgParameter(ratios) self.generator_param(self.levels, self.ratios) + @override def generate(self) -> None: super().generate() levels = self.get(self.levels) @@ -345,6 +351,7 @@ def generate(self) -> None: class Fcml(JlcBoardTop): """FPGA + FCML (flying cpacitor multilevel converter) test circuit, plus a bunch of other hardware blocks to test like RP2040""" + @override def contents(self) -> None: super().contents() @@ -444,6 +451,7 @@ def contents(self) -> None: (self.conv_out_sense, ), _ = self.chain(self.conv.pwr_out, imp.Block(div_model), self.mcu.adc.request('conv_out_sense')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_high_switch.py b/examples/test_high_switch.py index cdd14cd22..82f4e89fd 100644 --- a/examples/test_high_switch.py +++ b/examples/test_high_switch.py @@ -9,6 +9,8 @@ import unittest +from typing_extensions import override + from edg import * @@ -22,6 +24,7 @@ def __init__(self) -> None: self.controller = self.Port(CanTransceiverPort.empty(), [Input]) self.can = self.Port(CanDiffPort.empty(), optional=True) + @override def contents(self) -> None: super().contents() @@ -55,6 +58,7 @@ class CanFuse(PptcFuse, FootprintBlock): def __init__(self, trip_current: RangeLike = (100, 200)*mAmp): super().__init__(trip_current) + @override def contents(self) -> None: super().contents() @@ -82,6 +86,7 @@ def __init__(self) -> None: )) self.gnd = self.Port(Ground()) + @override def contents(self) -> None: super().contents() @@ -107,6 +112,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground()) self.differential = self.Port(CanDiffPort(), [Output]) + @override def contents(self) -> None: super().contents() @@ -134,6 +140,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground()) self.differential = self.Port(CanDiffPort(), [Output]) + @override def contents(self) -> None: super().contents() @@ -161,6 +168,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground()) self.differential = self.Port(CanDiffPort(), [Output]) + @override def contents(self) -> None: super().contents() @@ -187,6 +195,7 @@ def __init__(self, current_draw: RangeLike = RangeExpr()) -> None: for i in range(2): self.out[i] = self.Port(VoltageSink(current_draw=current_draw)) + @override def contents(self) -> None: super().contents() @@ -216,6 +225,7 @@ def __init__(self, current_draw: RangeLike = RangeExpr()) -> None: for i in range(2): self.control[i] = self.Port(DigitalSink.empty()) + @override def contents(self) -> None: super().contents() @@ -233,6 +243,7 @@ def contents(self) -> None: class HighSwitch(BoardTop): + @override def contents(self) -> None: super().contents() @@ -287,6 +298,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request(f'light_{i}0'), light.control[0]) self.connect(self.mcu.gpio.request(f'light_{i}1'), light.control[1]) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_blinds.py b/examples/test_iot_blinds.py index b3c49c38b..0fb2f5413 100644 --- a/examples/test_iot_blinds.py +++ b/examples/test_iot_blinds.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -49,6 +51,7 @@ class IotRollerBlinds(JlcBoardTop): 6 motor 1 Motor takes ~12v (stall ~500mA, no-load ~300mA, min start 4v @ 150mA) """ + @override def contents(self) -> None: super().contents() @@ -124,6 +127,7 @@ def contents(self) -> None: 'app': 'conn, drv', }) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -178,6 +182,7 @@ class IotCurtainCrawler(JlcBoardTop): Hall sensor is SOT-23 type, marked "6201" """ + @override def contents(self) -> None: super().contents() @@ -259,6 +264,7 @@ def contents(self) -> None: 'app': 'motor, drv, enca, encb', }) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_display.py b/examples/test_iot_display.py index 0df59c07a..df04d6ef5 100644 --- a/examples/test_iot_display.py +++ b/examples/test_iot_display.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -19,6 +21,7 @@ def __init__(self, frequency: RangeLike = RangeExpr.ZERO, max_rds: FloatLike = 1 self.frequency = self.ArgParameter(frequency) self.max_rds = self.ArgParameter(max_rds) + @override def contents(self) -> None: super().contents() @@ -44,6 +47,7 @@ def contents(self) -> None: class IotDisplay(JlcBoardTop): """Battery-powered IoT e-paper display with deep sleep. """ + @override def contents(self) -> None: super().contents() @@ -138,6 +142,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request('fl_cs'), self.flash.cs) # no test point, clip the SOIC + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_fan.py b/examples/test_iot_fan.py index 9969c0245..d1660954a 100644 --- a/examples/test_iot_fan.py +++ b/examples/test_iot_fan.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class IotFan(JlcBoardTop): """IoT fan controller with a 12v barrel jack input and a CPU fan connector. """ + @override def contents(self) -> None: super().contents() @@ -94,6 +97,7 @@ def contents(self) -> None: fan.with_mixin(CpuFanPwmControl()).control ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_iron.py b/examples/test_iot_iron.py index 2e46e227a..a8361ed9a 100644 --- a/examples/test_iot_iron.py +++ b/examples/test_iot_iron.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -36,6 +38,7 @@ class IotIron(JlcBoardTop): Inspired by https://github.com/AxxAxx/AxxSolder/tree/main, see repo README for links on connector pinning. """ + @override def contents(self) -> None: super().contents() @@ -185,11 +188,13 @@ def contents(self) -> None: self.connect(self.tamp.output, self.mcu.adc.request('thermocouple')) self.tp_t = self.Block(AnalogTestPoint()).connected(self.iron.thermocouple) + @override def multipack(self) -> None: self.packed_opamp = self.PackedBlock(Opa2333()) self.pack(self.packed_opamp.elements.request('0'), ['ifilt', 'amp']) self.pack(self.packed_opamp.elements.request('1'), ['tamp', 'amp']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_knob.py b/examples/test_iot_knob.py index ecf9e31f7..d8d3e04ba 100644 --- a/examples/test_iot_knob.py +++ b/examples/test_iot_knob.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class IotKnob(JlcBoardTop): """IoT knob with lights, buttons, and a screen. """ + @override def contents(self) -> None: super().contents() @@ -107,6 +110,7 @@ def contents(self) -> None: self.mcu.adc.request('v5v_sense') ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_led_driver.py b/examples/test_iot_led_driver.py index 05ecb926c..07e23f30e 100644 --- a/examples/test_iot_led_driver.py +++ b/examples/test_iot_led_driver.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -19,6 +21,7 @@ def __init__(self) -> None: class IotLedDriver(JlcBoardTop): """Multichannel IoT high-power external LED driver with a 12v barrel jack input. """ + @override def contents(self) -> None: super().contents() @@ -94,6 +97,7 @@ def contents(self) -> None: ledk_sink = self.led_sink[i*2+1] = imp.Block(DummyPassive()) self.connect(led_drv.ledk, ledk_sink.io) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_iot_thermal_camera.py b/examples/test_iot_thermal_camera.py index 0d558351b..bd7303a13 100644 --- a/examples/test_iot_thermal_camera.py +++ b/examples/test_iot_thermal_camera.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class IotThermalCamera(JlcBoardTop): """Dual-mode IR and RGB camera board with ESP32 """ + @override def contents(self) -> None: super().contents() @@ -98,6 +101,7 @@ def contents(self) -> None: self.connect(self.flir.vsync, self.mcu.gpio.request('flir_vsync')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_jd_keyswitch.py b/examples/test_jd_keyswitch.py index 1e362a19a..13793b5ea 100644 --- a/examples/test_jd_keyswitch.py +++ b/examples/test_jd_keyswitch.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class JacdacKeyswitch(JacdacDeviceTop, JlcBoardTop): """A Jacdac socketed mechanical keyswitch with RGB, for the gamer-maker in all of us. """ + @override def contents(self) -> None: super().contents() @@ -43,6 +46,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request('jd_status'), self.jd_status) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_keyboard.py b/examples/test_keyboard.py index c9265aefd..1a508a476 100644 --- a/examples/test_keyboard.py +++ b/examples/test_keyboard.py @@ -10,10 +10,13 @@ import unittest +from typing_extensions import override + from edg import * class Keyboard(SimpleBoardTop): + @override def contents(self) -> None: super().contents() @@ -33,6 +36,7 @@ def contents(self) -> None: self.connect(self.sw.cols, self.mcu.gpio.request_vector()) self.connect(self.sw.rows, self.mcu.gpio.request_vector()) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( class_refinements=[ diff --git a/examples/test_ledmatrix.py b/examples/test_ledmatrix.py index 7237c9547..d67e05be5 100644 --- a/examples/test_ledmatrix.py +++ b/examples/test_ledmatrix.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class LedMatrix(JlcBoardTop): """A USB-connected WiFi-enabled LED matrix that demonstrates a charlieplexing LED matrix generator. """ + @override def contents(self) -> None: super().contents() @@ -42,6 +45,7 @@ def contents(self) -> None: self.matrix = imp.Block(CharlieplexedLedMatrix(6, 5, current_draw=(3.5, 5)*mAmp, color=Led.Yellow)) self.connect(self.mcu.gpio.request_vector('led'), self.matrix.ios) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_lora.py b/examples/test_lora.py index 86942e742..c8c494cb5 100644 --- a/examples/test_lora.py +++ b/examples/test_lora.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -50,6 +52,7 @@ class EspLora(JlcBoardTop): #define SDCARD_CS SPI_CS """ + @override def contents(self) -> None: super().contents() @@ -122,11 +125,13 @@ def contents(self) -> None: self.connect(self.nfc.reset, self.mcu.gpio.request('nfc_rst')) self.connect(self.nfc.irq, self.mcu.gpio.request('nfc_irq')) + @override def multipack(self) -> None: self.tx_cpack = self.PackedBlock(CombinedCapacitor()) self.pack(self.tx_cpack.elements.request('0'), ['lora', 'tx_l', 'c']) self.pack(self.tx_cpack.elements.request('1'), ['lora', 'tx_pi', 'c1']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_multimeter.py b/examples/test_multimeter.py index 6cc702505..ff7cc2943 100644 --- a/examples/test_multimeter.py +++ b/examples/test_multimeter.py @@ -1,12 +1,15 @@ import unittest from typing import Dict +from typing_extensions import override + from edg import * class ResistorMux(Interface, KiCadImportableBlock, GeneratorBlock): """Generates an array of resistors with one side muxed and the other end an array. Passive-typed. Specify an infinite resistance for an open circuit.""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:ResistorMux' return { @@ -29,6 +32,7 @@ def __init__(self, resistances: ArrayRangeLike): self.resistances = self.ArgParameter(resistances) self.generator_param(self.resistances) + @override def generate(self) -> None: super().generate() self.res = ElementDict[Resistor]() @@ -62,6 +66,7 @@ def __init__(self) -> None: self.select = self.Port(Vector(DigitalSink.empty())) + @override def contents(self) -> None: super().contents() @@ -104,6 +109,7 @@ def __init__(self, voltage_rating: RangeLike = RangeExpr()): self.voltage_rating = self.ArgParameter(voltage_rating) + @override def contents(self) -> None: super().contents() max_in_voltage = self.control.link().voltage.upper() @@ -163,6 +169,7 @@ class Multimeter(JlcBoardTop): CIRCUITS WHILE USB IS PLUGGED IN. BE AWARE OF GROUND PATHS. """ + @override def contents(self) -> None: super().contents() VOLTAGE_RATING = (0, 250) * Volt @@ -318,6 +325,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request_vector('driver_select'), self.driver.select) self.connect(self.mcu.gpio.request('driver_enable'), self.driver.enable) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_pcbbot.py b/examples/test_pcbbot.py index ca17cf28a..14df1e820 100644 --- a/examples/test_pcbbot.py +++ b/examples/test_pcbbot.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * from .test_robotdriver import PwmConnector @@ -30,6 +32,7 @@ class PcbBot(JlcBoardTop): - Charging ic is not reverse protected - MCU does not get turned off with the gate when powered by the USB and battery, though the vbatt line turns off. (by design) """ + @override def contents(self) -> None: super().contents() @@ -159,6 +162,7 @@ def contents(self) -> None: self.switch = imp.Block(DigitalSwitch()) self.connect(self.switch.out, self.mcu.gpio.request('pwr')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_protected_charger.py b/examples/test_protected_charger.py index 502590ca2..80ccd7f52 100644 --- a/examples/test_protected_charger.py +++ b/examples/test_protected_charger.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -11,6 +13,7 @@ class ProtectedCharger(JlcBoardTop): - A Port for load """ + @override def contents(self) -> None: super().contents() @@ -48,6 +51,7 @@ def contents(self) -> None: self.pwr_pins.pins.request('2').adapt_to(VoltageSink(current_draw=(0, 2.0) * Amp))) self.connect(self.pwr_pins.pins.request('3').adapt_to(Ground()), self.gnd) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_robotcrawler.py b/examples/test_robotcrawler.py index 58ceab71b..c61f7edf6 100644 --- a/examples/test_robotcrawler.py +++ b/examples/test_robotcrawler.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -49,6 +51,7 @@ class RobotCrawler(RobotCrawlerSpec, JlcBoardTop): """Implementation of the crawler robot, that implements what is needed to connect the interface blocks as well as optional additional blocks. """ + @override def contents(self) -> None: super().contents() @@ -161,6 +164,7 @@ def contents(self) -> None: imp.Block(NeopixelArray(10))) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_robotdriver.py b/examples/test_robotdriver.py index 76c00d785..f0c31fce2 100644 --- a/examples/test_robotdriver.py +++ b/examples/test_robotdriver.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -48,6 +50,7 @@ class RobotDriver(JlcBoardTop): """Robot driver that uses a ESP32 (non-C) chip and includes a few more blocks to use the extra available IOs """ + @override def contents(self) -> None: super().contents() @@ -170,6 +173,7 @@ def contents(self) -> None: self.connect(self.gnd, self.servo.gnd) self.connect(self.mcu.gpio.request('pwm'), self.servo.pwm) + @override def multipack(self) -> None: self.led_res = self.PackedBlock(ResistorArray()) self.pack(self.led_res.elements.request('0'), ['leds', 'led[0]', 'res']) @@ -177,6 +181,7 @@ def multipack(self) -> None: self.pack(self.led_res.elements.request('2'), ['leds', 'led[2]', 'res']) self.pack(self.led_res.elements.request('3'), ['leds', 'led[3]', 'res']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_robotowl.py b/examples/test_robotowl.py index 6711f30b3..4fe597cbd 100644 --- a/examples/test_robotowl.py +++ b/examples/test_robotowl.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * from .test_robotdriver import PwmConnector, LedConnector @@ -13,6 +15,7 @@ def __init__(self) -> None: self.pwr = self.Port(VoltageSink.empty(), [Power]) self.out = self.Port(AnalogSource.empty(), [Output]) + @override def contents(self) -> None: super().contents() self.import_kicad( @@ -39,6 +42,7 @@ class RobotOwl(JlcBoardTop): 1 NPX 1 analog """ + @override def contents(self) -> None: super().contents() @@ -111,6 +115,7 @@ def contents(self) -> None: imp.Block(LedConnector()) ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_seven_segment.py b/examples/test_seven_segment.py index 91d8d6549..8bb67cc87 100644 --- a/examples/test_seven_segment.py +++ b/examples/test_seven_segment.py @@ -1,11 +1,14 @@ import unittest +from typing_extensions import override + from edg import * class SevenSegment(JlcBoardTop): """RGB 7-segment clock using Neopixels. """ + @override def contents(self) -> None: super().contents() @@ -88,6 +91,7 @@ def contents(self) -> None: self.connect(self.v5v_sense.input, self.pwr) self.connect(self.v5v_sense.output, self.mcu.adc.request('v5v_sense')) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_simon.py b/examples/test_simon.py index b342d3116..3dd56f025 100644 --- a/examples/test_simon.py +++ b/examples/test_simon.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -15,6 +17,7 @@ def __init__(self) -> None: self.sw2 = self.Port(Ground(), [Common]) self.sw1 = self.Port(DigitalSource.low_from_supply(self.sw2)) + @override def contents(self) -> None: super().contents() @@ -31,6 +34,7 @@ def contents(self) -> None: class Simon(BoardTop): + @override def contents(self) -> None: super().contents() @@ -90,6 +94,7 @@ def contents(self) -> None: self.Block(ForcedDigitalSinkCurrentDraw((0, 0))), self.btn[i].led_a) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_values=[ diff --git a/examples/test_swd_debugger.py b/examples/test_swd_debugger.py index c11e2150e..9c5218f8c 100644 --- a/examples/test_swd_debugger.py +++ b/examples/test_swd_debugger.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -14,6 +16,7 @@ def __init__(self) -> None: self.swo = self.Port(DigitalBidir.empty(), optional=True) self.tdi = self.Port(DigitalBidir.empty(), optional=True) + @override def contents(self) -> None: super().contents() self.conn = self.Block(PinHeader127DualShrouded(10)) @@ -39,6 +42,7 @@ def __init__(self) -> None: self.reset = self.Port(DigitalSink.empty(), optional=True) self.swo = self.Port(DigitalBidir.empty(), optional=True) + @override def contents(self) -> None: super().contents() @@ -64,6 +68,7 @@ def __init__(self) -> None: self.swd = self.Port(SwdHostPort.empty(), [Output]) self.swo_in = self.Port(DigitalSink.empty()) + @override def contents(self) -> None: super().contents() @@ -89,6 +94,7 @@ def contents(self) -> None: class SwdDebugger(JlcBoardTop): + @override def contents(self) -> None: super().contents() @@ -153,6 +159,7 @@ def contents(self) -> None: self.mcu.adc.request('target_vsense') ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ @@ -196,6 +203,7 @@ def __init__(self) -> None: self.swdio = self.Port(DigitalSink.empty()) self.swd = self.Port(SwdHostPort.empty(), [Output]) + @override def contents(self) -> None: super().contents() @@ -204,6 +212,7 @@ def contents(self) -> None: class PicoProbe(JlcBoardTop): + @override def contents(self) -> None: super().contents() @@ -262,6 +271,7 @@ def contents(self) -> None: self.mcu.adc.request('target_vsense') ) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_tofarray.py b/examples/test_tofarray.py index 79bc7b241..441606222 100644 --- a/examples/test_tofarray.py +++ b/examples/test_tofarray.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -30,6 +32,7 @@ def __init__(self) -> None: # design configuration variables self.tof_count = self.Parameter(IntExpr(5)) + @override def contents(self) -> None: super().contents() @@ -103,6 +106,7 @@ def contents(self) -> None: self.spk_drv.pwr ) + @override def multipack(self) -> None: self.res1 = self.PackedBlock(ResistorArray()) self.pack(self.res1.elements.request('0'), ['leds', 'led[0]', 'res']) @@ -121,6 +125,7 @@ def multipack(self) -> None: self.pack(self.rgb.green, ['leds', 'led[6]']) self.pack(self.rgb.blue, ['leds', 'led[7]']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_usb_fpga_programmer.py b/examples/test_usb_fpga_programmer.py index 3f3763aa9..ec456c09f 100644 --- a/examples/test_usb_fpga_programmer.py +++ b/examples/test_usb_fpga_programmer.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -13,6 +15,7 @@ def __init__(self) -> None: self.cs = self.Port(DigitalSink.empty()) self.reset = self.Port(DigitalSink.empty()) + @override def contents(self) -> None: super().contents() self.conn = self.Block(PinHeader127DualShrouded(10)) @@ -29,6 +32,7 @@ def contents(self) -> None: class UsbFpgaProgrammer(JlcBoardTop): """USB UART converter board""" + @override def contents(self) -> None: super().contents() self.usb = self.Block(UsbCReceptacle()) @@ -56,6 +60,7 @@ def contents(self) -> None: self.connect(self.ft232.adbus.request('4'), self.out.cs) self.connect(self.ft232.adbus.request('7'), self.out.reset) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_usb_key.py b/examples/test_usb_key.py index d4eed6707..2563cb228 100644 --- a/examples/test_usb_key.py +++ b/examples/test_usb_key.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -9,6 +11,7 @@ def __init__(self) -> None: super().__init__() self.io = self.Port(DigitalBidir.empty(), [Input]) + @override def contents(self) -> None: super().contents() self.res = self.Block(Resistor(resistance=10*kOhm(tol=0.05))) # recommended by ST @@ -24,6 +27,7 @@ def __init__(self) -> None: self.gnd = self.Port(Ground.empty(), [Common]) self.io = self.Port(DigitalBidir.empty(), [Input]) + @override def contents(self) -> None: super().contents() self.cap = self.Block(Capacitor(10*nFarad(tol=0.2), voltage=self.io.link().voltage)) @@ -35,6 +39,7 @@ class UsbKey(JlcBoardTop): """USB dongle with the PCB as the USB-A contact surface and a microcontroller on the opposite side. Similar circuitry and same pinning as the Solokeys Somu: https://github.com/solokeys/solo-hw/tree/master/solo """ + @override def contents(self) -> None: super().contents() @@ -69,6 +74,7 @@ def contents(self) -> None: self.connect(self.mcu.gpio.request('b1_gnd'), self.mcu.gpio.request('c15_gnd'), self.usb.gnd.as_digital_source()) + @override def multipack(self) -> None: self.packed_mcu_vdda_cap = self.PackedBlock(CombinedCapacitor()) self.pack(self.packed_mcu_vdda_cap.elements.request('0'), ['mcu', 'vdda_cap0', 'cap']) @@ -80,6 +86,7 @@ def multipack(self) -> None: self.pack(self.packed_mcu_vdd1_cap.elements.request('1'), ['mcu', 'vdd_cap_bulk', 'cap']) self.pack(self.packed_mcu_vdd1_cap.elements.request('2'), ['mcu', 'vdd_cap[1]', 'cap']) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index 265589b74..d066ecc92 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -1,6 +1,8 @@ import unittest from typing import Mapping, Dict +from typing_extensions import override + from edg.abstract_parts.ESeriesUtil import ESeriesRatioUtil from edg.abstract_parts.ResistiveDivider import DividerValues from edg.electronics_model.VoltagePorts import VoltageSinkAdapterAnalogSource # needed by imported schematic @@ -44,6 +46,7 @@ def __init__(self, resistance: RangeLike): self.sense_in = self.Port(AnalogSource.empty()) self.sense_out = self.Port(AnalogSource.empty()) + @override def contents(self) -> None: super().contents() self.import_kicad(self.file_path("UsbSourceMeasure", f"{self.__class__.__name__}.kicad_sch"), @@ -68,6 +71,7 @@ class RangingCurrentSenseResistor(Interface, KiCadImportableBlock, GeneratorBloc The control line is one bit for each range (range connectivity is independent). Multiple ranges can be connected simultaneously, this allows make-before-break connectivity.""" + @override def symbol_pinning(self, symbol_name: str) -> Dict[str, BasePort]: assert symbol_name == 'edg_importable:CurrentSenseResistorMux' return { @@ -95,6 +99,7 @@ def __init__(self, resistances: ArrayRangeLike, currents: ArrayRangeLike): self.out_range = self.Parameter(RangeExpr()) + @override def generate(self) -> None: super().generate() self.ranges = ElementDict[SourceMeasureRangingCell]() @@ -132,6 +137,7 @@ def generate(self) -> None: class EmitterFollower(InternalSubcircuit, KiCadSchematicBlock, KiCadImportableBlock, Block): """Emitter follower circuit. """ + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'edg_importable:Follower' # this requires an schematic-modified symbol return { @@ -157,6 +163,7 @@ def __init__(self, current: RangeLike, rds_on: RangeLike, gate_clamp_voltage: Ra self.rds_on = self.ArgParameter(rds_on) self.gate_clamp_voltage = self.ArgParameter(gate_clamp_voltage) + @override def contents(self) -> None: super().contents() @@ -227,6 +234,7 @@ class GatedSummingAmplifier(InternalSubcircuit, KiCadSchematicBlock, KiCadImport TODO: diode parameter should be an enum. Current values: '' (no diode), 'sink', 'source' (sinks or sources current) """ + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name in ('Simulation_SPICE:OPAMP', 'edg_importable:Opamp') return {'M': self.actual, 'T': self.target, 'F': self.target_fine, '3': self.output, 'S': self.sense_out, @@ -255,6 +263,7 @@ def __init__(self, input_resistance: RangeLike = 0*Ohm(tol=0), *, self.generator_param(self.input_resistance, self.res, self.dir, self.series, self.tolerance, self.target_fine.is_connected(), self.sense_out.is_connected(), self.fine_scale) + @override def generate(self) -> None: super().generate() @@ -334,6 +343,7 @@ class JfetCurrentClamp(InternalSubcircuit, KiCadSchematicBlock, KiCadImportableB """JET-based current clamp, clamps to roughly 10mA while maintaining a relatively low non-clamping impedance of ~100ohm. Max ~35V limited by JFET Vgs,max. """ + @override def symbol_pinning(self, symbol_name: str) -> Mapping[str, BasePort]: assert symbol_name == 'edg_importable:Unk2' return {'1': self.input, '2': self.output} @@ -347,6 +357,7 @@ def __init__(self, model_voltage_clamp: RangeLike, model_signal_clamp: RangeLike self.input = self.Port(AnalogSink.empty(), [Power]) self.output = self.Port(AnalogSource.empty(), [Common]) + @override def contents(self) -> None: super().contents() @@ -380,6 +391,7 @@ def __init__(self) -> None: self.rst = self.Export(self.ic.in2a) # any in2 self.out = self.Export(self.ic.out1) + @override def contents(self) -> None: super().contents() self.connect(self.ic.out1, self.ic.in2b) @@ -421,6 +433,7 @@ def __init__(self, current: RangeLike, rds_on: RangeLike): self.current = self.ArgParameter(current) self.rds_on = self.ArgParameter(rds_on) + @override def contents(self) -> None: super().contents() @@ -437,6 +450,7 @@ def contents(self) -> None: # list many parts that are no longer basic. # class UsbSourceMeasure(JlcPartsRefinements, JlcBoardTop): class UsbSourceMeasure(JlcBoardTop): + @override def contents(self) -> None: super().contents() @@ -769,6 +783,7 @@ def contents(self) -> None: 'misc': 'fan_drv, fan, jlc_th', }) + @override def multipack(self) -> None: self.vimeas_amps = self.PackedBlock(Opa2189()) # low noise opamp self.pack(self.vimeas_amps.elements.request('0'), ['control', 'amp', 'amp']) @@ -786,6 +801,7 @@ def multipack(self) -> None: self.pack(self.cintref_amps.elements.request('0'), ['control', 'int', 'amp']) self.pack(self.cintref_amps.elements.request('1'), ['control', 'dmeas', 'amp']) # this path matters much less + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/examples/test_usb_uart.py b/examples/test_usb_uart.py index b26f674f7..bf9dae16b 100644 --- a/examples/test_usb_uart.py +++ b/examples/test_usb_uart.py @@ -1,5 +1,7 @@ import unittest +from typing_extensions import override + from edg import * @@ -22,6 +24,7 @@ def __init__(self, *, pwr_current_draw: RangeLike = (0, 0)*mAmp): class UsbUart(JlcBoardTop): """USB UART converter board""" + @override def contents(self) -> None: super().contents() self.usb_uart = self.Block(UsbCReceptacle()) @@ -55,6 +58,7 @@ def contents(self) -> None: self.out = imp.Block(UartConnector()) self.connect(self.usbconv.uart, self.out.uart) + @override def refinements(self) -> Refinements: return super().refinements() + Refinements( instance_refinements=[ diff --git a/pyproject.toml b/pyproject.toml index 214cee0d0..a2cd92e1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,10 +31,14 @@ packages = ["edg.edgir", "edg.edgrpc", "edg.core", "edg.hdl_server", "edg.electr edg = ["core/resources/edg-compiler-precompiled.jar", "electronics_model/resources/kicad_footprints.json", "abstract_parts/resources/*.kicad_sch", "parts/resources/Pruned_JLCPCB SMT Parts Library(20220419).csv", "parts/resources/*.kicad_sch"] [tool.mypy] -# enable_error_code = ["explicit-override"] +enable_error_code = ["explicit-override"] strict = true implicit_reexport = true +[[tool.mypy.overrides]] +module = ["edg.edgir.*", "edg.edgrpc.*"] # generated code +ignore_errors = true + [project.urls] Homepage = "https://github.com/BerkeleyHCI/PolymorphicBlocks"