|
1 | | -from typing import Mapping |
| 1 | +from typing import Mapping, Tuple, List, NamedTuple |
2 | 2 |
|
3 | 3 | from electronics_model import * |
4 | 4 | from .Categories import Analog |
@@ -29,3 +29,56 @@ def __init__(self) -> None: |
29 | 29 |
|
30 | 30 | class OpampElement(Opamp): |
31 | 31 | """Packed opamp element""" |
| 32 | + |
| 33 | + |
| 34 | +@abstract_block |
| 35 | +class MultipackOpamp(Analog, MultipackBlock): |
| 36 | + """Base class for packed opamps - devices that have multiple opamps in a single package, |
| 37 | + with shared power and ground connections. Typically used with the multipack feature to |
| 38 | + fit individual opamps across the design hierarchy into one of these.""" |
| 39 | + def __init__(self): |
| 40 | + super().__init__() |
| 41 | + self.elements = self.PackedPart(PackedBlockArray(OpampElement())) |
| 42 | + self.pwr = self.PackedExport(self.elements.ports_array(lambda x: x.pwr)) |
| 43 | + self.gnd = self.PackedExport(self.elements.ports_array(lambda x: x.gnd)) |
| 44 | + self.inp = self.PackedExport(self.elements.ports_array(lambda x: x.inp)) |
| 45 | + self.inn = self.PackedExport(self.elements.ports_array(lambda x: x.inn)) |
| 46 | + self.out = self.PackedExport(self.elements.ports_array(lambda x: x.out)) |
| 47 | + |
| 48 | + |
| 49 | +@non_library |
| 50 | +class MultipackOpampGenerator(MultipackOpamp, GeneratorBlock): |
| 51 | + """Skeleton base class that provides scaffolding for common packed opamp definitions""" |
| 52 | + class OpampPorts(NamedTuple): |
| 53 | + gnd: VoltageSink |
| 54 | + pwr: VoltageSink |
| 55 | + amps: List[Tuple[AnalogSink, AnalogSink, AnalogSource]] # amp-, amp+, out |
| 56 | + |
| 57 | + def __init__(self): |
| 58 | + super().__init__() |
| 59 | + self.generator_param(self.pwr.requested(), self.gnd.requested(), |
| 60 | + self.inn.requested(), self.inp.requested(), self.out.requested()) |
| 61 | + |
| 62 | + def _make_multipack_opamp(self) -> OpampPorts: |
| 63 | + """Generates the opamp as a block in self, including any application circuit components like decoupling capacitors. |
| 64 | + Returns (gnd, pwr, [(in-, in+, out)]).""" |
| 65 | + raise NotImplementedError # implement me |
| 66 | + |
| 67 | + def generate(self): |
| 68 | + super().generate() |
| 69 | + amp_ports = self._make_multipack_opamp() |
| 70 | + |
| 71 | + self.gnd_merge = self.Block(PackedVoltageSource()) |
| 72 | + self.pwr_merge = self.Block(PackedVoltageSource()) |
| 73 | + self.connect(self.gnd_merge.pwr_out, amp_ports.gnd) |
| 74 | + self.connect(self.pwr_merge.pwr_out, amp_ports.pwr) |
| 75 | + |
| 76 | + requested = self.get(self.pwr.requested()) |
| 77 | + assert self.get(self.gnd.requested()) == self.get(self.inp.requested()) == \ |
| 78 | + self.get(self.inn.requested()) == self.get(self.out.requested()) == requested |
| 79 | + for i, (amp_neg, amp_pos, amp_out) in zip(requested, amp_ports.amps): |
| 80 | + self.connect(self.pwr.append_elt(VoltageSink.empty(), i), self.pwr_merge.pwr_ins.request(i)) |
| 81 | + self.connect(self.gnd.append_elt(VoltageSink.empty(), i), self.gnd_merge.pwr_ins.request(i)) |
| 82 | + self.connect(self.inn.append_elt(AnalogSink.empty(), i), amp_neg) |
| 83 | + self.connect(self.inp.append_elt(AnalogSink.empty(), i), amp_pos) |
| 84 | + self.connect(self.out.append_elt(AnalogSource.empty(), i), amp_out) |
0 commit comments