Skip to content

Commit dd97ffe

Browse files
authored
Unify .connected(...) with DummyBlocks and TestPoints (#511)
Adds connected(...) to DummyBlocks with a base class. Unifies the port name to `io`, adding a deprecation pathway for the older port names. Refactors the .connected(...) in TestPoints with a base class. Refactors use sites. Resolves #506, resolves #500
1 parent 3d4f75f commit dd97ffe

29 files changed

Lines changed: 246 additions & 256 deletions

‎edg/abstract_parts/TestPoint.py‎

Lines changed: 54 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from typing import Any
2-
from typing_extensions import override
1+
from typing import Any, TypeVar, Generic
2+
from typing_extensions import override, Self
33

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

1717

18+
TestPointLinkType = TypeVar("TestPointLinkType", bound=Link)
19+
20+
1821
@non_library
19-
class BaseTypedTestPoint(TypedTestPoint, Block):
22+
class BaseTypedTestPoint(TypedTestPoint, Block, Generic[TestPointLinkType]):
2023
"""Base class with utility infrastructure for typed test points"""
2124

2225
def __init__(self, tp_name: StringLike = "") -> None:
2326
super().__init__()
24-
self.io: Port
27+
self.io: Port[TestPointLinkType]
2528
self.tp_name = self.ArgParameter(tp_name)
26-
self.tp = self.Block(TestPoint(tp_name=StringExpr()))
29+
30+
def connected(self, io: Port[TestPointLinkType]) -> Self:
31+
builder.block().connect(io, self.io)
32+
return self
33+
34+
35+
@non_library
36+
class BaseSingleTestPoint(BaseTypedTestPoint[TestPointLinkType], Generic[TestPointLinkType]):
37+
"""Base class that provides naming infrastructure for single-wire test points"""
38+
39+
def __init__(self, *args: Any, **kwargs: Any) -> None:
40+
super().__init__(*args, **kwargs)
41+
self.tp = self.Block(TestPoint(StringExpr()))
2742

2843
@override
2944
def contents(self) -> None:
@@ -32,61 +47,46 @@ def contents(self) -> None:
3247

3348

3449
@non_library
35-
class BaseRfTestPoint(TypedTestPoint, Block):
50+
class BaseRfTestPoint(BaseTypedTestPoint[TestPointLinkType], Generic[TestPointLinkType]):
3651
"""Base class with utility infrastructure for typed RF test points."""
3752

38-
def __init__(self, tp_name: StringLike = "") -> None:
39-
super().__init__()
40-
self.tp_name = self.ArgParameter(tp_name)
53+
def __init__(self, *args: Any, **kwargs: Any) -> None:
54+
super().__init__(*args, **kwargs)
4155
self.conn = self.Block(RfConnector())
4256
self.gnd = self.Export(self.conn.gnd, [Common])
43-
self.io: Port
4457

4558
@override
4659
def contents(self) -> None:
4760
super().contents()
48-
conn_tp = self.conn.with_mixin(RfConnectorTestPoint(StringExpr()))
49-
self.assign(conn_tp.tp_name, (self.tp_name == "").then_else(self.io.link().name(), self.tp_name))
61+
self.conn.with_mixin(RfConnectorTestPoint((self.tp_name == "").then_else(self.io.link().name(), self.tp_name)))
5062

5163

52-
class GroundTestPoint(BaseTypedTestPoint, Block):
53-
"""Test point with a VoltageSink port."""
64+
class GroundTestPoint(BaseSingleTestPoint[GroundLink]):
65+
"""Test point with a Ground port."""
5466

55-
def __init__(self, *args: Any) -> None:
56-
super().__init__(*args)
67+
def __init__(self, *args: Any, **kwargs: Any) -> None:
68+
super().__init__(*args, **kwargs)
5769
self.io: Ground = self.Port(Ground(), [InOut])
5870
self.connect(self.io.net, self.tp.io)
5971

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

64-
65-
class VoltageTestPoint(BaseTypedTestPoint, Block):
73+
class VoltageTestPoint(BaseSingleTestPoint[VoltageLink]):
6674
"""Test point with a VoltageSink port."""
6775

68-
def __init__(self, *args: Any) -> None:
69-
super().__init__(*args)
76+
def __init__(self, *args: Any, **kwargs: Any) -> None:
77+
super().__init__(*args, **kwargs)
7078
self.io: VoltageSink = self.Port(VoltageSink(), [InOut])
7179
self.connect(self.io.net, self.tp.io)
7280

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

78-
class DigitalTestPoint(BaseTypedTestPoint, Block):
82+
class DigitalTestPoint(BaseSingleTestPoint[DigitalLink]):
7983
"""Test point with a DigitalSink port."""
8084

81-
def __init__(self, *args: Any) -> None:
82-
super().__init__(*args)
85+
def __init__(self, *args: Any, **kwargs: Any) -> None:
86+
super().__init__(*args, **kwargs)
8387
self.io: DigitalSink = self.Port(DigitalSink(), [InOut])
8488
self.connect(self.io.net, self.tp.io)
8589

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

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

112112

113-
class AnalogTestPoint(BaseTypedTestPoint, Block):
113+
class AnalogTestPoint(BaseSingleTestPoint[AnalogLink]):
114114
"""Test point with a AnalogSink port"""
115115

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

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

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

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

141-
class I2cTestPoint(TypedTestPoint, Block):
133+
class I2cTestPoint(BaseTypedTestPoint[I2cLink]):
142134
"""Two test points for I2C SDA and SCL"""
143135

144-
def __init__(self, tp_name: StringLike = "") -> None:
145-
super().__init__()
146-
self.io = self.Port(I2cTarget(DigitalBidir.empty()), [InOut])
147-
self.tp_name = self.ArgParameter(tp_name)
136+
def __init__(self, *args: Any, **kwargs: Any) -> None:
137+
super().__init__(*args, **kwargs)
138+
self.io: I2cTarget = self.Port(I2cTarget(DigitalBidir.empty()), [InOut])
148139

149140
@override
150141
def contents(self) -> None:
@@ -155,18 +146,13 @@ def contents(self) -> None:
155146
self.connect(self.tp_scl.io, self.io.scl)
156147
self.connect(self.tp_sda.io, self.io.sda)
157148

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

163-
class SpiTestPoint(TypedTestPoint, Block):
150+
class SpiTestPoint(BaseTypedTestPoint[SpiLink]):
164151
"""Test points for SPI"""
165152

166-
def __init__(self, tp_name: StringLike = "") -> None:
167-
super().__init__()
168-
self.io = self.Port(SpiPeripheral(DigitalBidir.empty()), [InOut])
169-
self.tp_name = self.ArgParameter(tp_name)
153+
def __init__(self, *args: Any, **kwargs: Any) -> None:
154+
super().__init__(*args, **kwargs)
155+
self.io: SpiPeripheral = self.Port(SpiPeripheral(DigitalBidir.empty()), [InOut])
170156

171157
@override
172158
def contents(self) -> None:
@@ -179,18 +165,13 @@ def contents(self) -> None:
179165
self.connect(self.tp_mosi.io, self.io.mosi)
180166
self.connect(self.tp_miso.io, self.io.miso)
181167

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

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

190-
def __init__(self, tp_name: StringLike = "") -> None:
191-
super().__init__()
192-
self.io = self.Port(CanPassivePort(DigitalBidir.empty()), [InOut])
193-
self.tp_name = self.ArgParameter(tp_name)
172+
def __init__(self, *args: Any, **kwargs: Any) -> None:
173+
super().__init__(*args, **kwargs)
174+
self.io: CanPassivePort = self.Port(CanPassivePort(DigitalBidir.empty()), [InOut])
194175

195176
@override
196177
def contents(self) -> None:
@@ -201,18 +182,13 @@ def contents(self) -> None:
201182
self.connect(self.tp_txd.io, self.io.txd)
202183
self.connect(self.tp_rxd.io, self.io.rxd)
203184

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

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

212-
def __init__(self, tp_name: StringLike = "") -> None:
213-
super().__init__()
214-
self.io = self.Port(CanDiffPort(DigitalBidir.empty()), [InOut])
215-
self.tp_name = self.ArgParameter(tp_name)
189+
def __init__(self, *args: Any, **kwargs: Any) -> None:
190+
super().__init__(*args, **kwargs)
191+
self.io: CanDiffPort = self.Port(CanDiffPort(DigitalBidir.empty()), [InOut])
216192

217193
@override
218194
def contents(self) -> None:
@@ -222,7 +198,3 @@ def contents(self) -> None:
222198
self.tp_canl = self.Block(DigitalTestPoint(name_prefix + ".canl"))
223199
self.connect(self.tp_canh.io, self.io.canh)
224200
self.connect(self.tp_canl.io, self.io.canl)
225-
226-
def connected(self, io: Port[CanLogicLink]) -> "CanDiffTestPoint":
227-
builder.block().connect(io, self.io)
228-
return self

‎edg/abstract_parts/test_ideal_circuit.py‎

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,20 @@ class IdealCircuitTestTop(Block):
1010
def __init__(self) -> None:
1111
super().__init__()
1212
self.gnd = self.Block(DummyGround())
13-
self.pwr = self.Block(DummyVoltageSource(5 * Volt(tol=0)))
1413
with self.implicit_connect(
15-
ImplicitConnect(self.gnd.gnd, [Common]),
14+
ImplicitConnect(self.gnd.io, [Common]),
1615
) as imp:
1716
self.reg = imp.Block(LinearRegulator(2 * Volt(tol=0)))
18-
self.connect(self.reg.pwr_in, self.pwr.pwr)
19-
self.reg_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0)))
20-
self.connect(self.reg_draw.pwr, self.reg.pwr_out)
17+
self.pwr = self.Block(DummyVoltageSource(5 * Volt(tol=0))).connected(self.reg.pwr_in)
18+
self.reg_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.reg.pwr_out)
2119

2220
self.boost = imp.Block(BoostConverter(4 * Volt(tol=0)))
2321
self.connect(self.boost.pwr_in, self.reg.pwr_out)
24-
self.boost_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0)))
25-
self.connect(self.boost_draw.pwr, self.boost.pwr_out) # draws 2A from reg
22+
self.boost_draw = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.boost.pwr_out)
2623

2724
self.mcu = imp.Block(IoController())
2825
self.connect(self.mcu.pwr, self.reg.pwr_out)
29-
self.mcu_io = self.Block(DummyDigitalSink())
30-
self.connect(self.mcu_io.io, self.mcu.gpio.request("test"))
26+
self.mcu_io = self.Block(DummyDigitalSink()).connected(self.mcu.gpio.request("test"))
3127

3228
self.require(self.pwr.current_drawn == 3 * Amp(tol=0))
3329
self.require(self.reg_draw.voltage == 2 * Volt(tol=0))

‎edg/circuits/LevelShifter.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,4 @@ def generate(self) -> None:
8686
if self.get(self.hv_res) != RangeExpr.INF:
8787
self.hv_pu = self.Block(PullupResistor(self.hv_res)).connected(self.hv_pwr, self.hv_io)
8888
else:
89-
self.dummy_hv = self.Block(DummyVoltageSink()) # must be connected
90-
self.connect(self.dummy_hv.pwr, self.hv_pwr)
89+
self.dummy_hv = self.Block(DummyVoltageSink()).connected(self.hv_pwr) # mark as connected

‎edg/circuits/test_diodemerge.py‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ class DiodeMergeTestTop(DesignTop):
1010
def __init__(self) -> None:
1111
super().__init__()
1212
self.dut = self.Block(DiodePowerMerge(voltage_drop=(0, 1) * Volt))
13-
(self.srca,), _ = self.chain(
14-
self.dut.pwr_ins.request(), self.Block(DummyVoltageSource(voltage_out=(12, 14) * Volt))
15-
)
16-
(self.srcb,), _ = self.chain(
17-
self.dut.pwr_ins.request(), self.Block(DummyVoltageSource(voltage_out=(4, 5) * Volt))
18-
)
19-
(self.sink,), _ = self.chain(self.dut.pwr_out, self.Block(DummyVoltageSink(current_draw=(0.5, 1.5) * Amp)))
13+
self.srca = self.Block(DummyVoltageSource(voltage_out=(12, 14) * Volt)).connected(self.dut.pwr_ins.request())
14+
self.srcb = self.Block(DummyVoltageSource(voltage_out=(4, 5) * Volt)).connected(self.dut.pwr_ins.request())
15+
self.sink = self.Block(DummyVoltageSink(current_draw=(0.5, 1.5) * Amp)).connected(self.dut.pwr_out)
2016

2117
@override
2218
def refinements(self) -> Refinements:

‎edg/circuits/test_opamp.py‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@
66
from .OpampCircuits import Amplifier
77

88

9-
class AnalogSourceDummy(Block):
10-
def __init__(self) -> None:
11-
super().__init__()
12-
self.port = self.Port(AnalogSource(), [InOut])
13-
14-
159
class TestOpamp(Opamp):
1610
@override
1711
def contents(self) -> None:
@@ -34,11 +28,11 @@ class AmplifierTestTop(Block):
3428
def __init__(self) -> None:
3529
super().__init__()
3630
self.dut = self.Block(Amplifier(amplification=Range.from_tolerance(2, 0.05)))
37-
(self.dummyin,), _ = self.chain(self.dut.input, self.Block(AnalogSourceDummy()))
38-
(self.dummyref,), _ = self.chain(self.dut.reference, self.Block(AnalogSourceDummy()))
39-
(self.dummyout,), _ = self.chain(self.dut.output, self.Block(DummyAnalogSink()))
40-
(self.dummypwr,), _ = self.chain(self.dut.pwr, self.Block(DummyVoltageSource()))
41-
(self.dummygnd,), _ = self.chain(self.dut.gnd, self.Block(DummyGround()))
31+
self.dummygnd = self.Block(DummyGround()).connected(self.dut.gnd)
32+
self.dummypwr = self.Block(DummyVoltageSource()).connected(self.dut.pwr)
33+
self.dummyin = self.Block(DummyAnalogSource()).connected(self.dut.input)
34+
self.dummyref = self.Block(DummyAnalogSource()).connected(self.dut.reference)
35+
self.dummyout = self.Block(DummyAnalogSink()).connected(self.dut.output)
4236

4337

4438
class OpampCircuitTest(unittest.TestCase):

‎edg/circuits/test_power_circuits.py‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ def __init__(self) -> None:
1212
super().__init__()
1313
self.dut = self.Block(RampLimiter())
1414

15-
(self.dummyin,), _ = self.chain(self.dut.pwr_in, self.Block(DummyVoltageSource(voltage_out=12 * Volt(tol=0))))
16-
(self.dummyout,), _ = self.chain(self.dut.pwr_out, self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))))
17-
(self.dummyctl,), _ = self.chain(
18-
self.dut.control, self.Block(DummyDigitalSource(voltage_out=3.3 * Volt(tol=0)))
19-
)
20-
(self.dummygnd,), _ = self.chain(self.dut.gnd, self.Block(DummyGround()))
15+
self.dummygnd = self.Block(DummyGround()).connected(self.dut.gnd)
16+
self.dummyin = self.Block(DummyVoltageSource(voltage_out=12 * Volt(tol=0))).connected(self.dut.pwr_in)
17+
self.dummyout = self.Block(DummyVoltageSink(current_draw=1 * Amp(tol=0))).connected(self.dut.pwr_out)
18+
self.dummyctl = self.Block(DummyDigitalSource(voltage_out=3.3 * Volt(tol=0))).connected(self.dut.control)
2119

2220
@override
2321
def refinements(self) -> Refinements:

‎edg/circuits/test_switching_converters.py‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ def __init__(self) -> None:
171171
output_voltage_ripple=25 * mVolt,
172172
)
173173
)
174-
(self.pwr_in,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_in)
175-
(self.switch,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.switch)
176-
(self.pwr_out,), _ = self.chain(self.Block(DummyVoltageSink()), self.dut.pwr_out)
177-
(self.gnd,), _ = self.chain(self.Block(DummyGround()), self.dut.gnd)
174+
self.gnd = self.Block(DummyGround()).connected(self.dut.gnd)
175+
self.pwr_in = self.Block(DummyVoltageSource()).connected(self.dut.pwr_in)
176+
self.switch = self.Block(DummyVoltageSource()).connected(self.dut.switch)
177+
self.pwr_out = self.Block(DummyVoltageSink()).connected(self.dut.pwr_out)
178178

179179
self.require(self.dut.actual_dutycycle.contains(Range(0.334, 0.832)))
180180
self.require(self.dut.actual_inductor_current_ripple.contains(Range(0.433, 0.478)))
@@ -206,10 +206,10 @@ def __init__(self) -> None:
206206
output_voltage_ripple=25 * mVolt,
207207
)
208208
)
209-
(self.pwr_in,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_in)
210-
(self.pwr_out,), _ = self.chain(self.Block(DummyVoltageSource()), self.dut.pwr_out)
211-
(self.switch,), _ = self.chain(self.Block(DummyVoltageSink()), self.dut.switch)
212-
(self.gnd,), _ = self.chain(self.Block(DummyGround()), self.dut.gnd)
209+
self.gnd = self.Block(DummyGround()).connected(self.dut.gnd)
210+
self.pwr_in = self.Block(DummyVoltageSource()).connected(self.dut.pwr_in)
211+
self.pwr_out = self.Block(DummyVoltageSource()).connected(self.dut.pwr_out)
212+
self.switch = self.Block(DummyVoltageSink()).connected(self.dut.switch)
213213

214214
self.require(self.dut.actual_dutycycle.contains(Range(0.4, 0.771)))
215215
self.require(self.dut.actual_inductor_current_ripple.contains(Range(0.495, 0.546)))

0 commit comments

Comments
 (0)