Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 54 additions & 82 deletions edg/abstract_parts/TestPoint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Any
from typing_extensions import override
from typing import Any, TypeVar, Generic
from typing_extensions import override, Self

from ..electronics_interfaces import *
from .Connectors import RfConnector, RfConnectorTestPoint
Expand All @@ -15,15 +15,30 @@ def __init__(self, tp_name: StringLike = "") -> None:
self.tp_name = self.ArgParameter(tp_name)


TestPointLinkType = TypeVar("TestPointLinkType", bound=Link)


@non_library
class BaseTypedTestPoint(TypedTestPoint, Block):
class BaseTypedTestPoint(TypedTestPoint, Block, Generic[TestPointLinkType]):
"""Base class with utility infrastructure for typed test points"""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.io: Port
self.io: Port[TestPointLinkType]
self.tp_name = self.ArgParameter(tp_name)
self.tp = self.Block(TestPoint(tp_name=StringExpr()))

def connected(self, io: Port[TestPointLinkType]) -> Self:
builder.block().connect(io, self.io)
return self

Comment on lines +18 to +33

@non_library
class BaseSingleTestPoint(BaseTypedTestPoint[TestPointLinkType], Generic[TestPointLinkType]):
"""Base class that provides naming infrastructure for single-wire test points"""

def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.tp = self.Block(TestPoint(StringExpr()))

@override
def contents(self) -> None:
Expand All @@ -32,61 +47,46 @@ def contents(self) -> None:


@non_library
class BaseRfTestPoint(TypedTestPoint, Block):
class BaseRfTestPoint(BaseTypedTestPoint[TestPointLinkType], Generic[TestPointLinkType]):
"""Base class with utility infrastructure for typed RF test points."""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.tp_name = self.ArgParameter(tp_name)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.conn = self.Block(RfConnector())
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()))
self.assign(conn_tp.tp_name, (self.tp_name == "").then_else(self.io.link().name(), self.tp_name))
self.conn.with_mixin(RfConnectorTestPoint((self.tp_name == "").then_else(self.io.link().name(), self.tp_name)))


class GroundTestPoint(BaseTypedTestPoint, Block):
"""Test point with a VoltageSink port."""
class GroundTestPoint(BaseSingleTestPoint[GroundLink]):
"""Test point with a Ground port."""

def __init__(self, *args: Any) -> None:
super().__init__(*args)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: Ground = self.Port(Ground(), [InOut])
self.connect(self.io.net, self.tp.io)

def connected(self, io: Port[GroundLink]) -> "GroundTestPoint":
builder.block().connect(io, self.io)
return self


class VoltageTestPoint(BaseTypedTestPoint, Block):
class VoltageTestPoint(BaseSingleTestPoint[VoltageLink]):
"""Test point with a VoltageSink port."""

def __init__(self, *args: Any) -> None:
super().__init__(*args)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: VoltageSink = self.Port(VoltageSink(), [InOut])
self.connect(self.io.net, self.tp.io)

def connected(self, io: Port[VoltageLink]) -> "VoltageTestPoint":
builder.block().connect(io, self.io)
return self


class DigitalTestPoint(BaseTypedTestPoint, Block):
class DigitalTestPoint(BaseSingleTestPoint[DigitalLink]):
"""Test point with a DigitalSink port."""

def __init__(self, *args: Any) -> None:
super().__init__(*args)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: DigitalSink = self.Port(DigitalSink(), [InOut])
self.connect(self.io.net, self.tp.io)

def connected(self, io: Port[DigitalLink]) -> "DigitalTestPoint":
builder.block().connect(io, self.io)
return self


class DigitalArrayTestPoint(TypedTestPoint, GeneratorBlock):
"""Creates an array of Digital test points, sized from the port array's connections."""
Expand All @@ -110,20 +110,16 @@ def generate(self) -> None:
self.connect(self.io.append_elt(DigitalSink.empty(), requested), tp.io)


class AnalogTestPoint(BaseTypedTestPoint, Block):
class AnalogTestPoint(BaseSingleTestPoint[AnalogLink]):
"""Test point with a AnalogSink port"""

def __init__(self, *args: Any) -> None:
super().__init__(*args)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: AnalogSink = self.Port(AnalogSink(), [InOut])
self.connect(self.io.net, self.tp.io)

def connected(self, io: Port[AnalogLink]) -> "AnalogTestPoint":
builder.block().connect(io, self.io)
return self


class AnalogCoaxTestPoint(BaseRfTestPoint, Block):
class AnalogCoaxTestPoint(BaseRfTestPoint[AnalogLink]):
"""Test point with a AnalogSink port and using a coax connector with shielding connected to gnd.
No impedance matching, this is intended for lower frequency signals where the wavelength would be
much longer than the test lead length"""
Expand All @@ -133,18 +129,13 @@ def __init__(self, *args: Any) -> None:
self.io: AnalogSink = self.Port(AnalogSink(), [InOut])
self.connect(self.io.net, self.conn.sig)

def connected(self, io: Port[AnalogLink]) -> "AnalogCoaxTestPoint":
builder.block().connect(io, self.io)
return self


class I2cTestPoint(TypedTestPoint, Block):
class I2cTestPoint(BaseTypedTestPoint[I2cLink]):
"""Two test points for I2C SDA and SCL"""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.io = self.Port(I2cTarget(DigitalBidir.empty()), [InOut])
self.tp_name = self.ArgParameter(tp_name)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: I2cTarget = self.Port(I2cTarget(DigitalBidir.empty()), [InOut])

@override
def contents(self) -> None:
Expand All @@ -155,18 +146,13 @@ def contents(self) -> None:
self.connect(self.tp_scl.io, self.io.scl)
self.connect(self.tp_sda.io, self.io.sda)

def connected(self, io: Port[I2cLink]) -> "I2cTestPoint":
builder.block().connect(io, self.io)
return self


class SpiTestPoint(TypedTestPoint, Block):
class SpiTestPoint(BaseTypedTestPoint[SpiLink]):
"""Test points for SPI"""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.io = self.Port(SpiPeripheral(DigitalBidir.empty()), [InOut])
self.tp_name = self.ArgParameter(tp_name)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: SpiPeripheral = self.Port(SpiPeripheral(DigitalBidir.empty()), [InOut])

@override
def contents(self) -> None:
Expand All @@ -179,18 +165,13 @@ def contents(self) -> None:
self.connect(self.tp_mosi.io, self.io.mosi)
self.connect(self.tp_miso.io, self.io.miso)

def connected(self, io: Port[SpiLink]) -> "SpiTestPoint":
builder.block().connect(io, self.io)
return self


class CanControllerTestPoint(TypedTestPoint, Block):
class CanControllerTestPoint(BaseTypedTestPoint[CanLogicLink]):
"""Two test points for CAN controller-side TXD and RXD"""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.io = self.Port(CanPassivePort(DigitalBidir.empty()), [InOut])
self.tp_name = self.ArgParameter(tp_name)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: CanPassivePort = self.Port(CanPassivePort(DigitalBidir.empty()), [InOut])

@override
def contents(self) -> None:
Expand All @@ -201,18 +182,13 @@ def contents(self) -> None:
self.connect(self.tp_txd.io, self.io.txd)
self.connect(self.tp_rxd.io, self.io.rxd)

def connected(self, io: Port[CanLogicLink]) -> "CanControllerTestPoint":
builder.block().connect(io, self.io)
return self


class CanDiffTestPoint(TypedTestPoint, Block):
class CanDiffTestPoint(BaseTypedTestPoint[CanDiffLink]):
"""Two test points for CAN differential-side canh and canl"""

def __init__(self, tp_name: StringLike = "") -> None:
super().__init__()
self.io = self.Port(CanDiffPort(DigitalBidir.empty()), [InOut])
self.tp_name = self.ArgParameter(tp_name)
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.io: CanDiffPort = self.Port(CanDiffPort(DigitalBidir.empty()), [InOut])

@override
def contents(self) -> None:
Expand All @@ -222,7 +198,3 @@ def contents(self) -> None:
self.tp_canl = self.Block(DigitalTestPoint(name_prefix + ".canl"))
self.connect(self.tp_canh.io, self.io.canh)
self.connect(self.tp_canl.io, self.io.canl)

def connected(self, io: Port[CanLogicLink]) -> "CanDiffTestPoint":
builder.block().connect(io, self.io)
return self
14 changes: 5 additions & 9 deletions edg/abstract_parts/test_ideal_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,20 @@ class IdealCircuitTestTop(Block):
def __init__(self) -> None:
super().__init__()
self.gnd = self.Block(DummyGround())
self.pwr = self.Block(DummyVoltageSource(5 * Volt(tol=0)))
with self.implicit_connect(
ImplicitConnect(self.gnd.gnd, [Common]),
ImplicitConnect(self.gnd.io, [Common]),
) as imp:
self.reg = imp.Block(LinearRegulator(2 * Volt(tol=0)))
self.connect(self.reg.pwr_in, self.pwr.pwr)
self.reg_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0)))
self.connect(self.reg_draw.pwr, self.reg.pwr_out)
self.pwr = self.Block(DummyVoltageSource(5 * Volt(tol=0))).connected(self.reg.pwr_in)
self.reg_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.reg.pwr_out)

self.boost = imp.Block(BoostConverter(4 * Volt(tol=0)))
self.connect(self.boost.pwr_in, self.reg.pwr_out)
self.boost_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0)))
self.connect(self.boost_draw.pwr, self.boost.pwr_out) # draws 2A from reg
self.boost_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.boost.pwr_out)

self.mcu = imp.Block(IoController())
self.connect(self.mcu.pwr, self.reg.pwr_out)
self.mcu_io = self.Block(DummyDigitalSink())
self.connect(self.mcu_io.io, self.mcu.gpio.request("test"))
self.mcu_io = self.Block(DummyDigitalSink()).connected(self.mcu.gpio.request("test"))

self.require(self.pwr.current_drawn == 3 * Amp(tol=0))
self.require(self.reg_draw.voltage == 2 * Volt(tol=0))
Expand Down
3 changes: 1 addition & 2 deletions edg/circuits/LevelShifter.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,4 @@ def generate(self) -> None:
if self.get(self.hv_res) != RangeExpr.INF:
self.hv_pu = self.Block(PullupResistor(self.hv_res)).connected(self.hv_pwr, self.hv_io)
else:
self.dummy_hv = self.Block(DummyVoltageSink()) # must be connected
self.connect(self.dummy_hv.pwr, self.hv_pwr)
self.dummy_hv = self.Block(DummyVoltageSink()).connected(self.hv_pwr) # mark as connected
10 changes: 3 additions & 7 deletions edg/circuits/test_diodemerge.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ class DiodeMergeTestTop(DesignTop):
def __init__(self) -> None:
super().__init__()
self.dut = self.Block(DiodePowerMerge(voltage_drop=(0, 1) * Volt))
(self.srca,), _ = self.chain(
self.dut.pwr_ins.request(), self.Block(DummyVoltageSource(voltage_out=(12, 14) * Volt))
)
(self.srcb,), _ = self.chain(
self.dut.pwr_ins.request(), self.Block(DummyVoltageSource(voltage_out=(4, 5) * Volt))
)
(self.sink,), _ = self.chain(self.dut.pwr_out, self.Block(DummyVoltageSink(current_draw=(0.5, 1.5) * Amp)))
self.srca = self.Block(DummyVoltageSource(voltage_out=(12, 14) * Volt)).connected(self.dut.pwr_ins.request())
self.srcb = self.Block(DummyVoltageSource(voltage_out=(4, 5) * Volt)).connected(self.dut.pwr_ins.request())
self.sink = self.Block(DummyVoltageSink(current_draw=(0.5, 1.5) * Amp)).connected(self.dut.pwr_out)

@override
def refinements(self) -> Refinements:
Expand Down
16 changes: 5 additions & 11 deletions edg/circuits/test_opamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@
from .OpampCircuits import Amplifier


class AnalogSourceDummy(Block):
def __init__(self) -> None:
super().__init__()
self.port = self.Port(AnalogSource(), [InOut])


class TestOpamp(Opamp):
@override
def contents(self) -> None:
Expand All @@ -34,11 +28,11 @@ class AmplifierTestTop(Block):
def __init__(self) -> None:
super().__init__()
self.dut = self.Block(Amplifier(amplification=Range.from_tolerance(2, 0.05)))
(self.dummyin,), _ = self.chain(self.dut.input, self.Block(AnalogSourceDummy()))
(self.dummyref,), _ = self.chain(self.dut.reference, self.Block(AnalogSourceDummy()))
(self.dummyout,), _ = self.chain(self.dut.output, self.Block(DummyAnalogSink()))
(self.dummypwr,), _ = self.chain(self.dut.pwr, self.Block(DummyVoltageSource()))
(self.dummygnd,), _ = self.chain(self.dut.gnd, self.Block(DummyGround()))
self.dummygnd = self.Block(DummyGround()).connected(self.dut.gnd)
self.dummypwr = self.Block(DummyVoltageSource()).connected(self.dut.pwr)
self.dummyin = self.Block(DummyAnalogSource()).connected(self.dut.input)
self.dummyref = self.Block(DummyAnalogSource()).connected(self.dut.reference)
self.dummyout = self.Block(DummyAnalogSink()).connected(self.dut.output)


class OpampCircuitTest(unittest.TestCase):
Expand Down
10 changes: 4 additions & 6 deletions edg/circuits/test_power_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ def __init__(self) -> None:
super().__init__()
self.dut = self.Block(RampLimiter())

(self.dummyin,), _ = self.chain(self.dut.pwr_in, self.Block(DummyVoltageSource(voltage_out=12 * Volt(tol=0))))
(self.dummyout,), _ = self.chain(self.dut.pwr_out, self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))))
(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()))
self.dummygnd = self.Block(DummyGround()).connected(self.dut.gnd)
self.dummyin = self.Block(DummyVoltageSource(voltage_out=12 * Volt(tol=0))).connected(self.dut.pwr_in)
self.dummyout = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.dut.pwr_out)
self.dummyctl = self.Block(DummyDigitalSource(voltage_out=3.3 * Volt(tol=0))).connected(self.dut.control)

@override
def refinements(self) -> Refinements:
Expand Down
16 changes: 8 additions & 8 deletions edg/circuits/test_switching_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ def __init__(self) -> None:
output_voltage_ripple=25 * mVolt,
)
)
(self.pwr_in,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_in)
(self.switch,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.switch)
(self.pwr_out,), _ = self.chain(self.Block(DummyVoltageSink()), self.dut.pwr_out)
(self.gnd,), _ = self.chain(self.Block(DummyGround()), self.dut.gnd)
self.gnd = self.Block(DummyGround()).connected(self.dut.gnd)
self.pwr_in = self.Block(DummyVoltageSource()).connected(self.dut.pwr_in)
self.switch = self.Block(DummyVoltageSource()).connected(self.dut.switch)
self.pwr_out = self.Block(DummyVoltageSink()).connected(self.dut.pwr_out)

self.require(self.dut.actual_dutycycle.contains(Range(0.334, 0.832)))
self.require(self.dut.actual_inductor_current_ripple.contains(Range(0.433, 0.478)))
Expand Down Expand Up @@ -206,10 +206,10 @@ def __init__(self) -> None:
output_voltage_ripple=25 * mVolt,
)
)
(self.pwr_in,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_in)
(self.pwr_out,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_out)
(self.switch,), _ = self.chain(self.Block(DummyVoltageSink()), self.dut.switch)
(self.gnd,), _ = self.chain(self.Block(DummyGround()), self.dut.gnd)
self.gnd = self.Block(DummyGround()).connected(self.dut.gnd)
self.pwr_in = self.Block(DummyVoltageSource()).connected(self.dut.pwr_in)
self.pwr_out = self.Block(DummyVoltageSource()).connected(self.dut.pwr_out)
self.switch = self.Block(DummyVoltageSink()).connected(self.dut.switch)

self.require(self.dut.actual_dutycycle.contains(Range(0.4, 0.771)))
self.require(self.dut.actual_inductor_current_ripple.contains(Range(0.495, 0.546)))
Expand Down
Loading
Loading