@vessel-dsp/compiler 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -2
- package/dist/bake.d.ts +38 -0
- package/dist/bake.d.ts.map +1 -0
- package/dist/bake.js +101 -0
- package/dist/bake.js.map +1 -0
- package/dist/bbd-clock.d.ts +171 -0
- package/dist/bbd-clock.d.ts.map +1 -0
- package/dist/bbd-clock.js +1750 -0
- package/dist/bbd-clock.js.map +1 -0
- package/dist/block-row.d.ts +51 -0
- package/dist/block-row.d.ts.map +1 -0
- package/dist/block-row.js +17 -0
- package/dist/block-row.js.map +1 -0
- package/dist/bypass.d.ts +3 -0
- package/dist/bypass.d.ts.map +1 -0
- package/dist/bypass.js +228 -0
- package/dist/bypass.js.map +1 -0
- package/dist/compile.d.ts +24 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +348 -0
- package/dist/compile.js.map +1 -0
- package/dist/converter-scale.d.ts +14 -0
- package/dist/converter-scale.d.ts.map +1 -0
- package/dist/converter-scale.js +133 -0
- package/dist/converter-scale.js.map +1 -0
- package/dist/couple.d.ts +28 -0
- package/dist/couple.d.ts.map +1 -0
- package/dist/couple.js +567 -0
- package/dist/couple.js.map +1 -0
- package/dist/dangling-active-terminal.d.ts +47 -0
- package/dist/dangling-active-terminal.d.ts.map +1 -0
- package/dist/dangling-active-terminal.js +542 -0
- package/dist/dangling-active-terminal.js.map +1 -0
- package/dist/declared-program.d.ts +23 -0
- package/dist/declared-program.d.ts.map +1 -0
- package/dist/declared-program.js +387 -0
- package/dist/declared-program.js.map +1 -0
- package/dist/denomination.d.ts +48 -0
- package/dist/denomination.d.ts.map +1 -0
- package/dist/denomination.js +27 -0
- package/dist/denomination.js.map +1 -0
- package/dist/device-laws.d.ts +237 -0
- package/dist/device-laws.d.ts.map +1 -0
- package/dist/device-laws.js +3513 -0
- package/dist/device-laws.js.map +1 -0
- package/dist/diagnostics.d.ts +13 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +19 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emit.d.ts +8 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +43 -0
- package/dist/emit.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/firmware-class.d.ts +69 -0
- package/dist/firmware-class.d.ts.map +1 -0
- package/dist/firmware-class.js +20 -0
- package/dist/firmware-class.js.map +1 -0
- package/dist/fixtures/circuits.d.ts +1742 -0
- package/dist/fixtures/circuits.d.ts.map +1 -0
- package/dist/fixtures/circuits.js +13896 -0
- package/dist/fixtures/circuits.js.map +1 -0
- package/dist/fixtures/expected.d.ts +261 -0
- package/dist/fixtures/expected.d.ts.map +1 -0
- package/dist/fixtures/expected.js +315 -0
- package/dist/fixtures/expected.js.map +1 -0
- package/dist/fixtures/index.d.ts +4 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +8 -0
- package/dist/fixtures/index.js.map +1 -0
- package/dist/fixtures/registry.d.ts +52 -0
- package/dist/fixtures/registry.d.ts.map +1 -0
- package/dist/fixtures/registry.js +341 -0
- package/dist/fixtures/registry.js.map +1 -0
- package/dist/generic-tube-fit.d.ts +12 -0
- package/dist/generic-tube-fit.d.ts.map +1 -0
- package/dist/generic-tube-fit.js +45 -0
- package/dist/generic-tube-fit.js.map +1 -0
- package/dist/grounded-clock-supply.d.ts +13 -0
- package/dist/grounded-clock-supply.d.ts.map +1 -0
- package/dist/grounded-clock-supply.js +45 -0
- package/dist/grounded-clock-supply.js.map +1 -0
- package/dist/identify.d.ts +50 -0
- package/dist/identify.d.ts.map +1 -0
- package/dist/identify.js +319 -0
- package/dist/identify.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/inert-controls.d.ts +15 -0
- package/dist/inert-controls.d.ts.map +1 -0
- package/dist/inert-controls.js +266 -0
- package/dist/inert-controls.js.map +1 -0
- package/dist/latch-seed.d.ts +53 -0
- package/dist/latch-seed.d.ts.map +1 -0
- package/dist/latch-seed.js +257 -0
- package/dist/latch-seed.js.map +1 -0
- package/dist/link.d.ts +7 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +270 -0
- package/dist/link.js.map +1 -0
- package/dist/lower.d.ts +79 -0
- package/dist/lower.d.ts.map +1 -0
- package/dist/lower.js +1855 -0
- package/dist/lower.js.map +1 -0
- package/dist/netlist.d.ts +79 -0
- package/dist/netlist.d.ts.map +1 -0
- package/dist/netlist.js +4746 -0
- package/dist/netlist.js.map +1 -0
- package/dist/non-executable-clock-drivers.d.ts +8 -0
- package/dist/non-executable-clock-drivers.d.ts.map +1 -0
- package/dist/non-executable-clock-drivers.js +33 -0
- package/dist/non-executable-clock-drivers.js.map +1 -0
- package/dist/open-category.d.ts +98 -0
- package/dist/open-category.d.ts.map +1 -0
- package/dist/open-category.js +111 -0
- package/dist/open-category.js.map +1 -0
- package/dist/over-driven-node.d.ts +33 -0
- package/dist/over-driven-node.d.ts.map +1 -0
- package/dist/over-driven-node.js +188 -0
- package/dist/over-driven-node.js.map +1 -0
- package/dist/part-catalog.d.ts +15 -0
- package/dist/part-catalog.d.ts.map +1 -0
- package/dist/part-catalog.js +6712 -0
- package/dist/part-catalog.js.map +1 -0
- package/dist/part-number.d.ts +32 -0
- package/dist/part-number.d.ts.map +1 -0
- package/dist/part-number.js +80 -0
- package/dist/part-number.js.map +1 -0
- package/dist/partition.d.ts +7 -0
- package/dist/partition.d.ts.map +1 -0
- package/dist/partition.js +242 -0
- package/dist/partition.js.map +1 -0
- package/dist/port-full-scale.d.ts +70 -0
- package/dist/port-full-scale.d.ts.map +1 -0
- package/dist/port-full-scale.js +235 -0
- package/dist/port-full-scale.js.map +1 -0
- package/dist/pot-orientation.d.ts +114 -0
- package/dist/pot-orientation.d.ts.map +1 -0
- package/dist/pot-orientation.js +551 -0
- package/dist/pot-orientation.js.map +1 -0
- package/dist/power-domain-control.d.ts +40 -0
- package/dist/power-domain-control.d.ts.map +1 -0
- package/dist/power-domain-control.js +142 -0
- package/dist/power-domain-control.js.map +1 -0
- package/dist/proxy-declaration.d.ts +121 -0
- package/dist/proxy-declaration.d.ts.map +1 -0
- package/dist/proxy-declaration.js +50 -0
- package/dist/proxy-declaration.js.map +1 -0
- package/dist/registry.d.ts +323 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +192 -0
- package/dist/registry.js.map +1 -0
- package/dist/sparse-schedule.d.ts +65 -0
- package/dist/sparse-schedule.d.ts.map +1 -0
- package/dist/sparse-schedule.js +421 -0
- package/dist/sparse-schedule.js.map +1 -0
- package/dist/speaker-load.d.ts +38 -0
- package/dist/speaker-load.d.ts.map +1 -0
- package/dist/speaker-load.js +97 -0
- package/dist/speaker-load.js.map +1 -0
- package/dist/stage-coverage.d.ts +21 -0
- package/dist/stage-coverage.d.ts.map +1 -0
- package/dist/stage-coverage.js +124 -0
- package/dist/stage-coverage.js.map +1 -0
- package/dist/stamp-partition.d.ts +314 -0
- package/dist/stamp-partition.d.ts.map +1 -0
- package/dist/stamp-partition.js +472 -0
- package/dist/stamp-partition.js.map +1 -0
- package/dist/supply-reference.d.ts +19 -0
- package/dist/supply-reference.d.ts.map +1 -0
- package/dist/supply-reference.js +66 -0
- package/dist/supply-reference.js.map +1 -0
- package/dist/supply-short.d.ts +32 -0
- package/dist/supply-short.d.ts.map +1 -0
- package/dist/supply-short.js +118 -0
- package/dist/supply-short.js.map +1 -0
- package/dist/supply-stamps.d.ts +51 -0
- package/dist/supply-stamps.d.ts.map +1 -0
- package/dist/supply-stamps.js +363 -0
- package/dist/supply-stamps.js.map +1 -0
- package/dist/terminal-role.d.ts +109 -0
- package/dist/terminal-role.d.ts.map +1 -0
- package/dist/terminal-role.js +46 -0
- package/dist/terminal-role.js.map +1 -0
- package/dist/terminal-roles.d.ts +59 -0
- package/dist/terminal-roles.d.ts.map +1 -0
- package/dist/terminal-roles.js +92 -0
- package/dist/terminal-roles.js.map +1 -0
- package/dist/transformer.d.ts +181 -0
- package/dist/transformer.d.ts.map +1 -0
- package/dist/transformer.js +476 -0
- package/dist/transformer.js.map +1 -0
- package/dist/types.d.ts +3157 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/unbounded-operating-point.d.ts +35 -0
- package/dist/unbounded-operating-point.d.ts.map +1 -0
- package/dist/unbounded-operating-point.js +181 -0
- package/dist/unbounded-operating-point.js.map +1 -0
- package/dist/unexecuted-region.d.ts +3 -0
- package/dist/unexecuted-region.d.ts.map +1 -0
- package/dist/unexecuted-region.js +122 -0
- package/dist/unexecuted-region.js.map +1 -0
- package/dist/unimplemented-control-role.d.ts +3 -0
- package/dist/unimplemented-control-role.d.ts.map +1 -0
- package/dist/unimplemented-control-role.js +61 -0
- package/dist/unimplemented-control-role.js.map +1 -0
- package/dist/unreachable-output.d.ts +3 -0
- package/dist/unreachable-output.d.ts.map +1 -0
- package/dist/unreachable-output.js +97 -0
- package/dist/unreachable-output.js.map +1 -0
- package/dist/unreadable-terminal-role.d.ts +67 -0
- package/dist/unreadable-terminal-role.d.ts.map +1 -0
- package/dist/unreadable-terminal-role.js +409 -0
- package/dist/unreadable-terminal-role.js.map +1 -0
- package/dist/unverified-pinout.d.ts +27 -0
- package/dist/unverified-pinout.d.ts.map +1 -0
- package/dist/unverified-pinout.js +121 -0
- package/dist/unverified-pinout.js.map +1 -0
- package/package.json +75 -5
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// Controls the document wires so that they provably cannot affect the circuit.
|
|
2
|
+
//
|
|
3
|
+
// Three reasons, and the third arrived with the execution schedule: a floating pot wiper, a
|
|
4
|
+
// device joined to nothing, and a control whose every element sits in a region the program
|
|
5
|
+
// does not execute. All three are structural -- connectivity, or the program's own `order`.
|
|
6
|
+
//
|
|
7
|
+
// This is a *warning* stage, not a refusal. A pedal with a dead knob still renders, and
|
|
8
|
+
// refusing it would cost 11 compiling corpus packets to fix a defect the user can hear
|
|
9
|
+
// around. What was not acceptable is shipping one silently: `ibanez-ts808` rendered
|
|
10
|
+
// bit-identical output at `Drive=0.1` and `Drive=0.9` and nothing in the compile result
|
|
11
|
+
// said why.
|
|
12
|
+
//
|
|
13
|
+
// The evidence is connectivity and nothing else. No component name, no `Description`,
|
|
14
|
+
// no role prose -- the same discipline the rest of the pipeline holds to.
|
|
15
|
+
import { potTerminals, stampControl } from "./lower.js";
|
|
16
|
+
/**
|
|
17
|
+
* A pot whose wiper node touches nothing else is electrically a fixed resistor.
|
|
18
|
+
*
|
|
19
|
+
* The two halves of the track are in series with a floating junction between them, so
|
|
20
|
+
* whatever the wiper takes from one half it gives back to the other and their sum is
|
|
21
|
+
* the whole track no matter where the knob sits. The pot still stamps, still solves,
|
|
22
|
+
* and still moves its two conductances -- it just cannot change any node voltage, which
|
|
23
|
+
* is why listening finds it and the matrix does not.
|
|
24
|
+
*
|
|
25
|
+
* A wiper tied back to one of its own ends is a rheostat and genuinely varies, so it
|
|
26
|
+
* has degree 2 and is correctly not reported here.
|
|
27
|
+
*/
|
|
28
|
+
export function findInertControls(netlist, program) {
|
|
29
|
+
const degree = new Map();
|
|
30
|
+
for (const device of netlist.devices) {
|
|
31
|
+
for (const node of device.nodes) {
|
|
32
|
+
degree.set(node, (degree.get(node) ?? 0) + 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const byControl = new Map();
|
|
36
|
+
for (const device of netlist.devices) {
|
|
37
|
+
if (device.control === null) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const bound = byControl.get(device.control);
|
|
41
|
+
if (bound === undefined) {
|
|
42
|
+
byControl.set(device.control, [device]);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
bound.push(device);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const unscheduled = controlsOnlyInUnscheduledBlocks(program);
|
|
49
|
+
const scheduledControls = controlsInScheduledBlocks(program);
|
|
50
|
+
// Controls a program reads through a port rather than a stamp. Their devices are genuinely
|
|
51
|
+
// dead to the circuit and that is not a defect: a mode pot read by a high-impedance input
|
|
52
|
+
// has a wiper driving nothing, and it still chooses which program runs. Reporting it would
|
|
53
|
+
// be a wrong answer about someone's circuit, which is the bar this whole file sets.
|
|
54
|
+
const portedControls = controlsReadThroughPorts(program);
|
|
55
|
+
const warnings = [];
|
|
56
|
+
for (const control of netlist.controls) {
|
|
57
|
+
const bound = byControl.get(control.id) ?? [];
|
|
58
|
+
if (bound.length === 0) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (portedControls.has(control.id)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// Every device the control drives must be dead for the claim to hold. One live gang, or a
|
|
65
|
+
// switch sharing the control, and the knob does something -- reporting it then would be a
|
|
66
|
+
// wrong answer about someone's circuit, which is worse than the silence this replaces. The
|
|
67
|
+
// narrower per-device fact is still visible in `devices`.
|
|
68
|
+
//
|
|
69
|
+
// **Two ways to be dead, and the second was missing.** A pot with a floating wiper is the
|
|
70
|
+
// original case. The other is a device with *every* terminal unwired, which the pot rule
|
|
71
|
+
// cannot express: `boss-od-3`'s `EFFECT_FOOTSWITCH` drives a switch whose three nodes are all
|
|
72
|
+
// degree 1, so the footswitch is bound to a real device that is connected to nothing, and the
|
|
73
|
+
// control read as fine. That packet's whole signal path is gated by JFETs whose gates the
|
|
74
|
+
// footswitch network should drive, so this is the control warning the pedal most needed.
|
|
75
|
+
const allPots = bound.every((device) => device.kind === "potentiometer" || device.kind === "rheostat");
|
|
76
|
+
const allDead = bound.every((device) => (device.kind === "potentiometer" && wiperIsFloating(device, degree)) ||
|
|
77
|
+
isFullyDisconnected(device, degree));
|
|
78
|
+
// **Three ways to be dead, and the device-level ones are reported first.** A floating
|
|
79
|
+
// wiper or a device joined to nothing is a fact about the circuit and is what a source
|
|
80
|
+
// reader can act on; sitting in an unexecuted region is a fact about the schedule, and
|
|
81
|
+
// only applies to audio potentiometers/rheostats (power contacts, bypass latches, and
|
|
82
|
+
// indicators naturally reside in DC/power regions outside the scheduled audio blocks).
|
|
83
|
+
if (!allDead && (!allPots || !unscheduled.has(control.id))) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const disconnected = bound.filter((device) => isFullyDisconnected(device, degree));
|
|
87
|
+
const isDisconnected = disconnected.length === bound.length;
|
|
88
|
+
const reasonKind = !allDead
|
|
89
|
+
? "unscheduled-region"
|
|
90
|
+
: isDisconnected
|
|
91
|
+
? "disconnected"
|
|
92
|
+
: "floating-wiper";
|
|
93
|
+
// A structural defect is one that breaks an executed block (a scheduled part of the audio path).
|
|
94
|
+
// Controls for unselected channels or unexecuted regions are warned about but do not refuse compilation.
|
|
95
|
+
const isStructuralDefect = allDead && (program.order.length === 0 || scheduledControls.has(control.id));
|
|
96
|
+
warnings.push({
|
|
97
|
+
code: "control-cannot-affect-circuit",
|
|
98
|
+
control: control.id,
|
|
99
|
+
reasonKind,
|
|
100
|
+
isStructuralDefect,
|
|
101
|
+
devices: bound.map((device) => device.id),
|
|
102
|
+
detail: !allDead
|
|
103
|
+
? `control "${control.id}" cannot affect the circuit: ` +
|
|
104
|
+
`${bound.length === 1 ? "the element it varies sits" : "every element it varies sits"} ` +
|
|
105
|
+
"in a region the program does not execute, because nothing in that region " +
|
|
106
|
+
"can reach the output jack"
|
|
107
|
+
: isDisconnected
|
|
108
|
+
? `control "${control.id}" cannot affect the circuit: ` +
|
|
109
|
+
`${bound.length === 1 ? "the device it drives has" : "every device it drives has"} ` +
|
|
110
|
+
"every terminal connected to nothing else, so the device is present in the " +
|
|
111
|
+
"document and joined to no circuit at all"
|
|
112
|
+
: `control "${control.id}" cannot affect the circuit: ` +
|
|
113
|
+
`${bound.length === 1 ? "its potentiometer has" : "every potentiometer it drives has"} ` +
|
|
114
|
+
"a wiper node connected to nothing else, so the two track halves stay in " +
|
|
115
|
+
"series and their sum is fixed at every knob position",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return warnings;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Controls whose every stamp sits in a block the program does not execute.
|
|
122
|
+
*
|
|
123
|
+
* The third way a knob can be provably dead, and the one only the emitted program can see:
|
|
124
|
+
* the device is wired, its stamps are real, and the region they are in owns neither jack and
|
|
125
|
+
* feeds nothing that does — so `link` leaves it out of `order` and the runtime never solves
|
|
126
|
+
* it. Measured on the corpus: 11 controls across 5 packets, `boss-od-1`'s battery contact and
|
|
127
|
+
* `boss-sd-1`'s effect switch being the two that no earlier rule catches.
|
|
128
|
+
*
|
|
129
|
+
* **A control with no stamp at all is deliberately not this warning.** 74 declared controls
|
|
130
|
+
* are in that position and almost all of them are jacks, LED indicators and DC-adaptor
|
|
131
|
+
* entries that were never knobs — a separate question about what belongs in
|
|
132
|
+
* `program.controls`, and warning about them would bury these 11 in 74 rows of noise.
|
|
133
|
+
*
|
|
134
|
+
* Reads `program.order` rather than re-deriving reachability, because the program's own
|
|
135
|
+
* statement of what executes is the fact being reported.
|
|
136
|
+
*/
|
|
137
|
+
/**
|
|
138
|
+
* Controls a block reads through a port: a clock control, or a router choosing a program.
|
|
139
|
+
*
|
|
140
|
+
* Neither changes the conductance matrix, so every structural test in this file calls them
|
|
141
|
+
* dead. They are not: the control reaches the program by another road.
|
|
142
|
+
*/
|
|
143
|
+
function controlsReadThroughPorts(program) {
|
|
144
|
+
const ported = new Set();
|
|
145
|
+
for (const block of program.blocks) {
|
|
146
|
+
if (block.kind !== "macro" && block.kind !== "composed")
|
|
147
|
+
continue;
|
|
148
|
+
const clock = block.clockControl?.controlId;
|
|
149
|
+
if (clock !== undefined)
|
|
150
|
+
ported.add(clock);
|
|
151
|
+
if (block.kind === "composed" && block.router !== null && block.router !== undefined) {
|
|
152
|
+
ported.add(block.router.controlId);
|
|
153
|
+
}
|
|
154
|
+
// A scanned or tapped line's control moves the program's delay without varying any device.
|
|
155
|
+
if (block.kind === "composed") {
|
|
156
|
+
for (const position of block.positions) {
|
|
157
|
+
for (const line of Object.values(position.lines)) {
|
|
158
|
+
if (line.sweep !== undefined)
|
|
159
|
+
ported.add(line.sweep.controlId);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// And a swept gain's knob moves a mix term the same way.
|
|
164
|
+
if (block.kind === "composed") {
|
|
165
|
+
for (const position of block.positions) {
|
|
166
|
+
for (const op of position.ops) {
|
|
167
|
+
if (op.op !== "mix")
|
|
168
|
+
continue;
|
|
169
|
+
for (const term of op.terms) {
|
|
170
|
+
if (term.sweep !== undefined)
|
|
171
|
+
ported.add(term.sweep.controlId);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return ported;
|
|
178
|
+
}
|
|
179
|
+
function controlsOnlyInUnscheduledBlocks(program) {
|
|
180
|
+
const scheduled = new Set(program.order);
|
|
181
|
+
const stampedAnywhere = new Set();
|
|
182
|
+
const stampedInScheduled = new Set();
|
|
183
|
+
for (const block of program.blocks) {
|
|
184
|
+
if (block.kind === "macro" || block.kind === "composed") {
|
|
185
|
+
const controlId = block.clockControl?.controlId;
|
|
186
|
+
if (controlId !== undefined) {
|
|
187
|
+
stampedAnywhere.add(controlId);
|
|
188
|
+
if (scheduled.has(block.id)) {
|
|
189
|
+
stampedInScheduled.add(controlId);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (block.kind !== "mna") {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
for (const stamp of block.stamps) {
|
|
198
|
+
const control = stampControl(stamp);
|
|
199
|
+
if (control === null) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
stampedAnywhere.add(control);
|
|
203
|
+
if (scheduled.has(block.id)) {
|
|
204
|
+
stampedInScheduled.add(control);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const control of stampedInScheduled) {
|
|
209
|
+
stampedAnywhere.delete(control);
|
|
210
|
+
}
|
|
211
|
+
return stampedAnywhere;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Controls whose stamps sit in at least one block the program executes in `order`.
|
|
215
|
+
*/
|
|
216
|
+
function controlsInScheduledBlocks(program) {
|
|
217
|
+
const scheduled = new Set(program.order);
|
|
218
|
+
const inScheduled = new Set();
|
|
219
|
+
for (const block of program.blocks) {
|
|
220
|
+
if (!scheduled.has(block.id)) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (block.kind === "macro" || block.kind === "composed") {
|
|
224
|
+
const controlId = block.clockControl?.controlId;
|
|
225
|
+
if (controlId !== undefined) {
|
|
226
|
+
inScheduled.add(controlId);
|
|
227
|
+
}
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (block.kind !== "mna") {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
for (const stamp of block.stamps) {
|
|
234
|
+
const control = stampControl(stamp);
|
|
235
|
+
if (control !== null) {
|
|
236
|
+
inScheduled.add(control);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return inScheduled;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A device joined to no circuit: every terminal it declares is touched by nothing else.
|
|
244
|
+
*
|
|
245
|
+
* Ground is deliberately *not* excused here, unlike in the dangling-terminal rule. A device with one
|
|
246
|
+
* terminal on ground and the rest unwired still cannot do anything, and a control driving it still
|
|
247
|
+
* cannot be heard -- which is the claim this file makes.
|
|
248
|
+
*/
|
|
249
|
+
function isFullyDisconnected(device, degree) {
|
|
250
|
+
return (device.nodes.length > 0 &&
|
|
251
|
+
device.nodes.every((node) => (degree.get(node) ?? 0) <= 1));
|
|
252
|
+
}
|
|
253
|
+
function wiperIsFloating(device, degree) {
|
|
254
|
+
if (device.nodes.length !== 3) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
// The same terminal-order reading the lowering stage uses, imported rather than
|
|
258
|
+
// repeated: a second copy of "which lug is the wiper" would drift from the one that
|
|
259
|
+
// decides what actually gets stamped, and then the warning would describe a
|
|
260
|
+
// different circuit from the program. Only the wiper is read here, which is decided
|
|
261
|
+
// before `potTerminals` ever consults connectivity, so two empty maps are exact -- not a
|
|
262
|
+
// stand-in -- for what this caller needs.
|
|
263
|
+
const [, wiper] = potTerminals(device, new Map(), new Map());
|
|
264
|
+
return (degree.get(wiper) ?? 0) === 1;
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=inert-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inert-controls.js","sourceRoot":"","sources":["../src/inert-controls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Netlist, NodeId, OperatingPointSeed } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* A cross-coupled pair, by connectivity alone.
|
|
4
|
+
*
|
|
5
|
+
* **Seed a base, never a collector.** This is the whole reason the rule is written in terms
|
|
6
|
+
* of bases. A seed enters the solve only through the nonlinear devices' linearisation
|
|
7
|
+
* points, and perturbing a *collector* creates no differential base drive: measured at every
|
|
8
|
+
* magnitude from `1e-9` to `5 V`, a collector seed returns the symmetric solution in an
|
|
9
|
+
* identical 16 iterations, so it does exactly nothing. A caller cannot be trusted to know
|
|
10
|
+
* that, which is why this function emits the seeds rather than exposing the pair.
|
|
11
|
+
*
|
|
12
|
+
* Four structural requirements, and each one is load-bearing:
|
|
13
|
+
*
|
|
14
|
+
* 1. **A direct resistor each way**, collector to the opposite base. All three corpus pairs
|
|
15
|
+
* are wired this way, two of them with a speed-up capacitor in parallel. Requiring a
|
|
16
|
+
* direct element rather than a path is most of what keeps this from over-matching.
|
|
17
|
+
* 2. **A shared emitter node.** The corpus pairs share ground, ground, and a common node
|
|
18
|
+
* that is not ground. Two transistors that merely have resistors between them do not.
|
|
19
|
+
* 3. **Rails are not routes.** Neither collector nor base may be a rail. Without this the
|
|
20
|
+
* supply links every collector to every base and the rule dissolves: measured, a census
|
|
21
|
+
* lacking it reported one packet as having **12** cross-coupled pairs among four
|
|
22
|
+
* transistors. The same exclusion `findUnboundedOpamps` and `switchesClosedForPortPath`
|
|
23
|
+
* make. An emitter *on* a rail is expected and fine — two of the three pairs sit on
|
|
24
|
+
* ground.
|
|
25
|
+
* 4. **Exclusivity.** A transistor in more than one candidate pair makes every pair it is in
|
|
26
|
+
* ambiguous, and an ambiguous latch is not seeded. Guessing which pair is the real one
|
|
27
|
+
* from a tie-break would put the pedal in a state chosen by node numbering.
|
|
28
|
+
*
|
|
29
|
+
* **Which side, with a floor.** `engagedBase` derives the side that engages the effect from
|
|
30
|
+
* connectivity, and when it cannot, this falls back to the lower base node id — deterministic,
|
|
31
|
+
* meaningless, and still a *physical* state rather than the midpoint. The fallback is the
|
|
32
|
+
* floor, not the intent: a latch nobody can read out is better left latched somewhere than
|
|
33
|
+
* left halfway.
|
|
34
|
+
*
|
|
35
|
+
* What this still does not give is **toggling**. The seed decides where the circuit powers up;
|
|
36
|
+
* it is not an input the control plane can move, so a footswitch cannot change it. That needs
|
|
37
|
+
* the latched-state operator with a state entry — see the runtime plan's S4 initial-state item.
|
|
38
|
+
*/
|
|
39
|
+
export type BistableLatch = {
|
|
40
|
+
readonly controlId: string | null;
|
|
41
|
+
readonly engagedBase: NodeId;
|
|
42
|
+
readonly bypassedBase: NodeId;
|
|
43
|
+
readonly emitter: NodeId;
|
|
44
|
+
readonly engagedCollector: NodeId;
|
|
45
|
+
readonly bypassedCollector: NodeId;
|
|
46
|
+
readonly engagedTransistorId: string;
|
|
47
|
+
readonly bypassedTransistorId: string;
|
|
48
|
+
};
|
|
49
|
+
export declare function findBistableLatches(netlist: Pick<Netlist, "devices"> & {
|
|
50
|
+
readonly controls?: readonly import("./types").Control[];
|
|
51
|
+
}): readonly BistableLatch[];
|
|
52
|
+
export declare function findLatchSeeds(netlist: Netlist): readonly OperatingPointSeed[];
|
|
53
|
+
//# sourceMappingURL=latch-seed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latch-seed.d.ts","sourceRoot":"","sources":["../src/latch-seed.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAY3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,OAAO,SAAS,EAAE,OAAO,EAAE,CAAA;CAAE,GAC9F,SAAS,aAAa,EAAE,CA6G1B;AAED,wBAAgB,cAAc,CAC7B,OAAO,EAAE,OAAO,GACd,SAAS,kBAAkB,EAAE,CAY/B"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// Operating-point seeds for cross-coupled bistables.
|
|
2
|
+
//
|
|
3
|
+
// A symmetric cross-coupled BJT pair has **three** DC solutions: two latched and the
|
|
4
|
+
// unstable midpoint between them. Newton started from `fill(0)` begins exactly on the
|
|
5
|
+
// symmetry axis and returns the midpoint, which is a valid solution of the system and a
|
|
6
|
+
// state no physical pedal holds. Nothing is failing to converge, so no iteration cap and
|
|
7
|
+
// no tolerance touches it — the initial guess *chooses the answer*, and the only fix is to
|
|
8
|
+
// make that guess data rather than a convention.
|
|
9
|
+
//
|
|
10
|
+
// Measured on the corpus: three compiled packets sit on the axis, at `1.74723 / 1.74723`,
|
|
11
|
+
// `1.78645 / 1.78645` and `3.13363 / 3.13363`, their two halves agreeing to between `2e-11`
|
|
12
|
+
// and `4e-6`. One of them is the corpus's only ngspice `disagrees`, one is near-silent, and
|
|
13
|
+
// the third **agrees with ngspice at `corr=1.0000`** — because the deck carries the same
|
|
14
|
+
// stamps and ngspice converges to the same midpoint. Parity cannot see this class.
|
|
15
|
+
//
|
|
16
|
+
// See `docs/troubleshootings/boss-hm-2-linear-where-ngspice-distorts.md` for what the
|
|
17
|
+
// midpoint does downstream: both collectors half-high bias every switching JFET
|
|
18
|
+
// identically, so the bypass and effect paths conduct at once and which dominates is
|
|
19
|
+
// settled by rounding.
|
|
20
|
+
/**
|
|
21
|
+
* Enough forward bias to put one base into conduction and let the pair fall to that side.
|
|
22
|
+
*
|
|
23
|
+
* Measured rather than chosen: seeding a single base at this value converges to a latched
|
|
24
|
+
* state in 16 iterations, the same count as the symmetric solve, and the mirrored seed
|
|
25
|
+
* reaches the mirrored state. Its exact value is not delicate — it has to be a base-emitter
|
|
26
|
+
* voltage that conducts, and anything that does selects the same basin.
|
|
27
|
+
*/
|
|
28
|
+
const LATCH_SEED_VOLTS = 0.65;
|
|
29
|
+
export function findBistableLatches(netlist) {
|
|
30
|
+
const rails = new Set([0]);
|
|
31
|
+
for (const device of netlist.devices) {
|
|
32
|
+
if (device.kind === "voltage-source" || device.kind === "rail") {
|
|
33
|
+
for (const node of device.nodes) {
|
|
34
|
+
rails.add(node);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const transistors = netlist.devices.flatMap((device) => {
|
|
39
|
+
if (device.kind !== "bjt") {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const collector = terminal(device, "collector");
|
|
43
|
+
const base = terminal(device, "base");
|
|
44
|
+
const emitter = terminal(device, "emitter");
|
|
45
|
+
if (collector === null || base === null || emitter === null) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
// Requirement 3, on the two nodes that carry the state. The emitter is exempt.
|
|
49
|
+
if (rails.has(collector) || rails.has(base)) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
return [{ id: String(device.id), collector, base, emitter }];
|
|
53
|
+
});
|
|
54
|
+
const coupledBetween = (a, b) => a === b ||
|
|
55
|
+
netlist.devices.some((device) => device.kind === "resistor" &&
|
|
56
|
+
device.nodes.length === 2 &&
|
|
57
|
+
device.nodes.includes(a) &&
|
|
58
|
+
device.nodes.includes(b));
|
|
59
|
+
const pairs = [];
|
|
60
|
+
for (let i = 0; i < transistors.length; i += 1) {
|
|
61
|
+
for (let j = i + 1; j < transistors.length; j += 1) {
|
|
62
|
+
const a = transistors[i];
|
|
63
|
+
const b = transistors[j];
|
|
64
|
+
if (a === undefined || b === undefined) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (a.emitter !== b.emitter) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!coupledBetween(a.collector, b.base) ||
|
|
71
|
+
!coupledBetween(b.collector, a.base)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
pairs.push({ a, b });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Requirement 4. A transistor in two candidate pairs makes all of them ambiguous.
|
|
78
|
+
const appearances = new Map();
|
|
79
|
+
for (const pair of pairs) {
|
|
80
|
+
for (const member of [pair.a, pair.b]) {
|
|
81
|
+
appearances.set(member.id, (appearances.get(member.id) ?? 0) + 1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const latches = [];
|
|
85
|
+
for (const pair of pairs) {
|
|
86
|
+
if ([pair.a, pair.b].some((m) => (appearances.get(m.id) ?? 0) > 1)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Prefer the side that engages the effect. Falling back to the lower base id keeps a
|
|
90
|
+
// latch this cannot read out of the unphysical midpoint, which is the seed's floor.
|
|
91
|
+
const engagedBaseNode = engagedBase(netlist, rails, pair.a, pair.b) ??
|
|
92
|
+
Math.min(pair.a.base, pair.b.base);
|
|
93
|
+
const engaged = engagedBaseNode === pair.a.base ? pair.a : pair.b;
|
|
94
|
+
const bypassed = engagedBaseNode === pair.a.base ? pair.b : pair.a;
|
|
95
|
+
const bypassControls = (netlist.controls ?? []).filter((c) => c.role === "bypass");
|
|
96
|
+
let controlId = bypassControls.length === 1 ? (bypassControls[0]?.id ?? null) : null;
|
|
97
|
+
if (controlId === null) {
|
|
98
|
+
for (const dev of netlist.devices) {
|
|
99
|
+
if (dev.kind === "switch" && dev.control !== null) {
|
|
100
|
+
controlId = dev.control;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
latches.push({
|
|
106
|
+
controlId,
|
|
107
|
+
engagedBase: engaged.base,
|
|
108
|
+
bypassedBase: bypassed.base,
|
|
109
|
+
emitter: pair.a.emitter,
|
|
110
|
+
engagedCollector: engaged.collector,
|
|
111
|
+
bypassedCollector: bypassed.collector,
|
|
112
|
+
engagedTransistorId: engaged.id,
|
|
113
|
+
bypassedTransistorId: bypassed.id,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return latches;
|
|
117
|
+
}
|
|
118
|
+
export function findLatchSeeds(netlist) {
|
|
119
|
+
const latches = findBistableLatches(netlist);
|
|
120
|
+
const seeds = [];
|
|
121
|
+
const seeded = new Set();
|
|
122
|
+
for (const latch of latches) {
|
|
123
|
+
if (seeded.has(latch.engagedBase)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
seeded.add(latch.engagedBase);
|
|
127
|
+
seeds.push({ node: latch.engagedBase, volts: LATCH_SEED_VOLTS });
|
|
128
|
+
}
|
|
129
|
+
return seeds;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Which member of the pair is high when the pedal is **engaged**, or `null` when that is not
|
|
133
|
+
* derivable from connectivity.
|
|
134
|
+
*
|
|
135
|
+
* Ported from the old spine's `discrete-bypass-latch.ts`, whose rule this repository already
|
|
136
|
+
* paid for: a latch's side is a control fact, and the two questions that decide it are which
|
|
137
|
+
* switches each collector gates, and which of those switch paths carries the audio the user
|
|
138
|
+
* adjusts. Every refusal below is one the old rule names, and returning `null` for all of
|
|
139
|
+
* them is deliberate — an undecidable side must fall back to *a* physical state rather than a
|
|
140
|
+
* confident guess, because being wrong here silently bypasses the pedal.
|
|
141
|
+
*
|
|
142
|
+
* Two edge sets, and the split matters:
|
|
143
|
+
*
|
|
144
|
+
* - **DC edges are resistors and diodes only.** Capacitors are excluded because a bistable's
|
|
145
|
+
* own cross-coupling capacitors, plus every supply bypass capacitor, would bridge the whole
|
|
146
|
+
* circuit and make both collectors appear to gate everything.
|
|
147
|
+
* - **Audio edges include capacitors**, since that is how a signal path is coupled, but
|
|
148
|
+
* exclude the switch channels themselves so a side cannot reach the controls *through* its
|
|
149
|
+
* counterpart.
|
|
150
|
+
*
|
|
151
|
+
* Both floods are blocked by rails, the same exclusion the rest of this file makes.
|
|
152
|
+
*/
|
|
153
|
+
function engagedBase(netlist, rails, a, b) {
|
|
154
|
+
const dcEdges = edgesOf(netlist, ["resistor", "diode"]);
|
|
155
|
+
const switches = netlist.devices.flatMap((switching) => {
|
|
156
|
+
if (switching.kind !== "jfet" && switching.kind !== "mosfet") {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const gate = terminal(switching, "gate");
|
|
160
|
+
const drain = terminal(switching, "drain");
|
|
161
|
+
return gate === null || drain === null
|
|
162
|
+
? []
|
|
163
|
+
: [{ id: String(switching.id), gate, drain }];
|
|
164
|
+
});
|
|
165
|
+
const gatedBy = (collector) => {
|
|
166
|
+
const reached = flood(collector, dcEdges, rails);
|
|
167
|
+
return switches
|
|
168
|
+
.filter((candidate) => reached.has(candidate.gate))
|
|
169
|
+
.map((candidate) => candidate.id)
|
|
170
|
+
.sort();
|
|
171
|
+
};
|
|
172
|
+
const gatedA = gatedBy(a.collector);
|
|
173
|
+
const gatedB = gatedBy(b.collector);
|
|
174
|
+
// Neither side drives a switch: not a switched bypass latch at all. A latch driving only
|
|
175
|
+
// an indicator lands here, correctly.
|
|
176
|
+
if (gatedA.length === 0 && gatedB.length === 0) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
// Both sides gate the same switches, so the sides are indistinguishable.
|
|
180
|
+
if (gatedA.length === gatedB.length &&
|
|
181
|
+
gatedA.every((id, index) => id === gatedB[index])) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const switchIds = new Set([...gatedA, ...gatedB]);
|
|
185
|
+
const audioEdges = edgesOf(netlist, [
|
|
186
|
+
"resistor",
|
|
187
|
+
"capacitor",
|
|
188
|
+
"inductor",
|
|
189
|
+
"potentiometer",
|
|
190
|
+
]).filter((edge) => !switchIds.has(edge.id));
|
|
191
|
+
// A control-bound device is one a knob varies, which is a typed field rather than a name.
|
|
192
|
+
const controlNodes = netlist.devices.flatMap((device) => device.control === null ? [] : device.nodes);
|
|
193
|
+
const reachesAControl = (gated) => gated.some((switchId) => {
|
|
194
|
+
const found = switches.find((candidate) => candidate.id === switchId);
|
|
195
|
+
if (found === undefined) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
const reached = flood(found.drain, audioEdges, rails);
|
|
199
|
+
return controlNodes.some((node) => reached.has(node));
|
|
200
|
+
});
|
|
201
|
+
const engagedA = reachesAControl(gatedA);
|
|
202
|
+
const engagedB = reachesAControl(gatedB);
|
|
203
|
+
if (engagedA === engagedB) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
return engagedA ? a.base : b.base;
|
|
207
|
+
}
|
|
208
|
+
/** Undirected two-terminal edges of the given kinds; a pot contributes one per terminal pair. */
|
|
209
|
+
function edgesOf(netlist, kinds) {
|
|
210
|
+
const wanted = new Set(kinds);
|
|
211
|
+
const edges = [];
|
|
212
|
+
for (const device of netlist.devices) {
|
|
213
|
+
if (!wanted.has(device.kind)) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
for (let i = 0; i < device.nodes.length; i += 1) {
|
|
217
|
+
for (let j = i + 1; j < device.nodes.length; j += 1) {
|
|
218
|
+
const a = device.nodes[i];
|
|
219
|
+
const b = device.nodes[j];
|
|
220
|
+
if (a !== undefined && b !== undefined && a !== b) {
|
|
221
|
+
edges.push({ a, b, id: String(device.id) });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return edges;
|
|
227
|
+
}
|
|
228
|
+
/** Reachable nodes, never entering a blocked node. */
|
|
229
|
+
function flood(start, edges, blocked) {
|
|
230
|
+
if (blocked.has(start)) {
|
|
231
|
+
return new Set();
|
|
232
|
+
}
|
|
233
|
+
const seen = new Set([start]);
|
|
234
|
+
const queue = [start];
|
|
235
|
+
while (queue.length > 0) {
|
|
236
|
+
const node = queue.pop();
|
|
237
|
+
for (const edge of edges) {
|
|
238
|
+
const other = edge.a === node ? edge.b : edge.b === node ? edge.a : null;
|
|
239
|
+
if (other === null || seen.has(other) || blocked.has(other)) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
seen.add(other);
|
|
243
|
+
queue.push(other);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return seen;
|
|
247
|
+
}
|
|
248
|
+
/** A terminal's node by role token, or `null` when the role is absent or repeated. */
|
|
249
|
+
function terminal(device, role) {
|
|
250
|
+
const found = device.identity.terminalRoles.flatMap((candidate, index) => candidate === role ? [index] : []);
|
|
251
|
+
if (found.length !== 1) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const node = device.nodes[found[0]];
|
|
255
|
+
return node === undefined ? null : node;
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=latch-seed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latch-seed.js","sourceRoot":"","sources":["../src/latch-seed.ts"],"names":[],"mappings":"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"}
|
package/dist/link.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { StageRefusal } from "./errors";
|
|
2
|
+
import type { Block, Control, Partitioning, Ports, Program, ProgramBypass } from "./types";
|
|
3
|
+
export declare class LinkError extends StageRefusal {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function link(blocks: readonly Block[], partitioning: Partitioning, controls: readonly Control[], ports: Ports, portImpedanceOhms?: Program["portImpedanceOhms"], portDeclaredFullScaleVolts?: Program["portImpedanceOhms"], bypass?: ProgramBypass): Program;
|
|
7
|
+
//# sourceMappingURL=link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAIxC,OAAO,KAAK,EACX,KAAK,EACL,OAAO,EAGP,YAAY,EACZ,KAAK,EACL,OAAO,EACP,aAAa,EACb,MAAM,SAAS,CAAC;AAEjB,qBAAa,SAAU,SAAQ,YAAY;gBAC9B,OAAO,EAAE,MAAM;CAG3B;AAED,wBAAgB,IAAI,CACnB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,EAAE,KAAK,EAGZ,iBAAiB,GAAE,OAAO,CAAC,mBAAmB,CAG7C,EAGD,0BAA0B,GAAE,OAAO,CAAC,mBAAmB,CAGtD,EACD,MAAM,GAAE,aAAoC,GAC1C,OAAO,CAkDT"}
|