@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,97 @@
|
|
|
1
|
+
// A program that reaches its output port with nothing at all.
|
|
2
|
+
//
|
|
3
|
+
// **The question a builder actually asks, and the one nothing answered.** Wire a guitar signal
|
|
4
|
+
// into a chip the registry cannot model -- an omitted codec, a DSP declared as a pin shell, a
|
|
5
|
+
// package whose analog pins the packet never traced -- and the chip lowers to `open`. The
|
|
6
|
+
// compiled program is then byte-for-byte the circuit *without* it: the stages before it stamp
|
|
7
|
+
// exactly as they did, the document is `ok`, and the output jack sits on a node no live block
|
|
8
|
+
// produces. `ic-not-executed` names the chip; nothing named the consequence.
|
|
9
|
+
//
|
|
10
|
+
// **What this proves, and it is a proof rather than an inference.** `link.ts` already computes
|
|
11
|
+
// which blocks reach the output (`blocksReachingOutput`) and emits only those into `order`. A
|
|
12
|
+
// program whose `order` is empty executes no block under any runtime, at any control position,
|
|
13
|
+
// at any sample rate. It cannot produce audio. That is a statement about the emitted program,
|
|
14
|
+
// not a claim about a graph.
|
|
15
|
+
//
|
|
16
|
+
// **Why this is not path-finding, which was the obvious design and is the wrong one.**
|
|
17
|
+
// `scripts/report-signal-path.ts` walks input to output over device conduction, and its own
|
|
18
|
+
// header records the trap: a non-inverting op-amp stage has no passive route from its signal
|
|
19
|
+
// input to its output, so `vemuram-jan-ray`, `mxr-micro-amp` and `jhs-morning-glory` all read
|
|
20
|
+
// "no path" while rendering perfectly well. A warning built on that graph would fire on working
|
|
21
|
+
// pedals, and a warning that cries wolf on a working pedal is worse than no warning. The first
|
|
22
|
+
// attempt here made a smaller version of the same mistake -- comparing `ports.output`, a global
|
|
23
|
+
// node id, against the node ids inside stamps -- and flagged 42 of 118 packets including
|
|
24
|
+
// `mxr-micro-amp` and `mxr-carbon-copy`. Block node ids are block-local; the comparison was
|
|
25
|
+
// meaningless. Measured against the emitted `order` instead, the false-alarm count is zero.
|
|
26
|
+
//
|
|
27
|
+
// **What it does not prove.** Not that a program with a non-empty `order` is audible: a block
|
|
28
|
+
// can execute and still be attenuated to nothing, which is `report-signal-path.ts`'s question
|
|
29
|
+
// and stays there. And a live `macro` block whose write-back reaches no block claiming the
|
|
30
|
+
// output port is *not* caught, because `blocksReachingOutput` treats every macro as live by
|
|
31
|
+
// construction; `boss-ps-2` and `boss-tu-3` are in that position and are deliberately left
|
|
32
|
+
// alone rather than flagged on a rule this cannot back.
|
|
33
|
+
//
|
|
34
|
+
// **Warning, not refusal**, for the reason the repository settles this trade every time: four
|
|
35
|
+
// corpus packets are in this state today (`boss-bf-3`, `boss-hr-2`, `boss-oc-3`, `boss-st-2`,
|
|
36
|
+
// each a digital pedal whose audio path crosses a chip that is not modelled) and refusing them
|
|
37
|
+
// would trade a compiling packet for a stricter gate. `boss-bf-3` is the one to look at first:
|
|
38
|
+
// it compiles **148 blocks and executes none of them**.
|
|
39
|
+
import { deviceCountByNode } from "./device-laws.js";
|
|
40
|
+
/**
|
|
41
|
+
* How much of the document is wired, as a sentence, or empty when it is wired normally.
|
|
42
|
+
*
|
|
43
|
+
* **The number that explains the block count.** `boss-bf-3` compiles 148 blocks of one stamp each
|
|
44
|
+
* and runs none, and the block count alone reads like a compiler defect. It is not: its 166
|
|
45
|
+
* devices declare 458 terminals across 418 non-ground nodes and only **10** of those nodes are
|
|
46
|
+
* touched by more than one device. A node one device touches is not a net, so the document is a
|
|
47
|
+
* terminalized parts list rather than a circuit, which is exactly the graph coverage its own
|
|
48
|
+
* README claims (`terminalized-source-shell`).
|
|
49
|
+
*
|
|
50
|
+
* Reported as a measurement with no threshold and no verdict, because the corpus has a spread
|
|
51
|
+
* rather than two classes: the median packet shares 93.3% of its non-ground nodes, and the tail
|
|
52
|
+
* runs 2.1% (`boss-oc-3`), 2.4% (`boss-bf-3`), 4.8% (`boss-bf-2`), 11.5% (`boss-dd-5`). Naming a
|
|
53
|
+
* cutoff would invent a boundary the data does not have; the reader can see the ratio.
|
|
54
|
+
*/
|
|
55
|
+
function wiringSummary(netlist) {
|
|
56
|
+
const counts = deviceCountByNode(netlist);
|
|
57
|
+
let nets = 0;
|
|
58
|
+
let shared = 0;
|
|
59
|
+
for (const [node, devices] of counts) {
|
|
60
|
+
if (node === 0) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
nets += 1;
|
|
64
|
+
if (devices >= 2) {
|
|
65
|
+
shared += 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (nets === 0) {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
const terminals = netlist.devices.reduce((total, device) => total + device.nodes.length, 0);
|
|
72
|
+
return (` Its ${netlist.devices.length} devices declare ${terminals} terminals across ${nets} ` +
|
|
73
|
+
`non-ground nodes, and ${shared} of those nodes are touched by more than one device: a node ` +
|
|
74
|
+
"only one device touches is not a net, so a low share here means the document's " +
|
|
75
|
+
"connectivity was never captured rather than that a component is missing a model.");
|
|
76
|
+
}
|
|
77
|
+
export function findUnreachableOutput(program, netlist) {
|
|
78
|
+
if (program.order.length > 0) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
const macros = program.blocks.filter((block) => block.kind === "macro" || block.kind === "composed").length;
|
|
82
|
+
return [
|
|
83
|
+
{
|
|
84
|
+
code: "output-port-unreachable",
|
|
85
|
+
device: null,
|
|
86
|
+
detail: `no block reaches the output port, so this program's execution order is empty: ` +
|
|
87
|
+
`${program.blocks.length} block${program.blocks.length === 1 ? " was" : "s were"} compiled ` +
|
|
88
|
+
`(${macros} of them DSP blocks) and none of them runs. It can produce no audio at any ` +
|
|
89
|
+
"control position. The usual cause is a component on the signal path that carries no " +
|
|
90
|
+
"executable model, which an `ic-not-executed` or `electrically-isolated-ic` warning " +
|
|
91
|
+
"beside this one will name: the stages around it still compile, so the document looks " +
|
|
92
|
+
"whole while the path to the jack is severed." +
|
|
93
|
+
wiringSummary(netlist),
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=unreachable-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unreachable-output.js","sourceRoot":"","sources":["../src/unreachable-output.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,6EAA6E;AAC7E,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,8FAA8F;AAC9F,6BAA6B;AAC7B,EAAE;AACF,uFAAuF;AACvF,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,gGAAgG;AAChG,+FAA+F;AAC/F,gGAAgG;AAChG,yFAAyF;AACzF,4FAA4F;AAC5F,4FAA4F;AAC5F,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,2FAA2F;AAC3F,4FAA4F;AAC5F,2FAA2F;AAC3F,wDAAwD;AACxD,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,+FAA+F;AAC/F,+FAA+F;AAC/F,wDAAwD;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;;;;;;;;;;;GAcG;AACH,SAAS,aAAa,CAAC,OAAgB;IACtC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YAChB,SAAS;QACV,CAAC;QACD,IAAI,IAAI,CAAC,CAAC;QACV,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,CAAC;QACb,CAAC;IACF,CAAC;IACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CACvC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAC9C,CAAC,CACD,CAAC;IACF,OAAO,CACN,QAAQ,OAAO,CAAC,OAAO,CAAC,MAAM,oBAAoB,SAAS,qBAAqB,IAAI,GAAG;QACvF,yBAAyB,MAAM,8DAA8D;QAC7F,iFAAiF;QACjF,kFAAkF,CAClF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,OAAgB,EAChB,OAAgB;IAEhB,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CACnC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAC9D,CAAC,MAAM,CAAC;IACT,OAAO;QACN;YACC,IAAI,EAAE,yBAAyB;YAC/B,MAAM,EAAE,IAAI;YACZ,MAAM,EACL,gFAAgF;gBAChF,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,YAAY;gBAC5F,IAAI,MAAM,6EAA6E;gBACvF,sFAAsF;gBACtF,qFAAqF;gBACrF,uFAAuF;gBACvF,8CAA8C;gBAC9C,aAAa,CAAC,OAAO,CAAC;SACvB;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Device, LawedNetlist, NonExecutableSupportShellWarning, UnreadableTerminalRoleWarning } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* A component declared as one transistor that is really **several devices in one shell**.
|
|
4
|
+
*
|
|
5
|
+
* `boss-ce-1` declares `SRC_CE1_Q3_Q6_D01_D05_CLOCK_BRIDGE_SUPPORT` as `kind: bjt` with
|
|
6
|
+
* **nineteen** terminals, standing for four transistors and five diodes, and
|
|
7
|
+
* `SRC_CE1_Q15_Q16_Q17_POWER_REGULATOR` as `kind: bjt` with eight, standing for three. Stamping
|
|
8
|
+
* either as a single transistor invents a device: the packet's own `Description` says "Exact
|
|
9
|
+
* physical package C/B/E orientation … remain unresolved", so there is no base, collector or
|
|
10
|
+
* emitter to bind, and declaration order supplies one anyway.
|
|
11
|
+
*
|
|
12
|
+
* **Two conditions, and the conjunction is what makes this safe.**
|
|
13
|
+
*
|
|
14
|
+
* - *The law cannot consume the terminals.* A `bjt`/`fet` law binds exactly three nodes, so a
|
|
15
|
+
* component declaring more has terminals no stamp can reach.
|
|
16
|
+
* - *And its roles cannot be read.* This is the discriminator. Measured across the corpus, 20
|
|
17
|
+
* devices declare more terminals than their kind's law consumes, and almost all are
|
|
18
|
+
* legitimate: 14 are multi-junction diodes (bridges, dual tube rectifiers) that
|
|
19
|
+
* `diodeJunctions` places by role, and `moogerfooger-mf-102`'s four `MPQ3906` sections are a
|
|
20
|
+
* quad transistor array declaring `collector`/`base`/`emitter` plus two unused package pins,
|
|
21
|
+
* which read cleanly. Only `boss-ce-1`'s two shells fail both tests.
|
|
22
|
+
*
|
|
23
|
+
* **Why not read `PartNumber`.** These shells announce themselves there —
|
|
24
|
+
* `"Q3/Q4 2SA493; Q5/Q6 2SC536F; D01-D05 1S1555"` is plainly several parts — and splitting that
|
|
25
|
+
* string on its separators is exactly the prose parsing this repository forbids for a
|
|
26
|
+
* classification decision. Terminal count against a law's fixed arity, and whether a closed role
|
|
27
|
+
* vocabulary reads, are structural facts about the document instead.
|
|
28
|
+
*
|
|
29
|
+
* Deliberately not extended to `opamp`: an op-amp package legitimately declares more terminals
|
|
30
|
+
* than its law binds (supplies, a second section), so arity says nothing there. `boss-dm-3`'s
|
|
31
|
+
* 8-pin `IC1` is that case and is a registry-expansion question, not a shell.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isMultiDeviceTransistorShell(device: Device): boolean;
|
|
34
|
+
export declare function findUnreadableTerminalRoles(lawed: LawedNetlist): readonly UnreadableTerminalRoleWarning[];
|
|
35
|
+
/**
|
|
36
|
+
* The multi-device shells stage 3 resolved to `open`, so a packet is told the component was
|
|
37
|
+
* dropped rather than silently losing it.
|
|
38
|
+
*
|
|
39
|
+
* Paired with `isMultiDeviceTransistorShell`'s use in `resolveDevice`: that decides the law, this
|
|
40
|
+
* reports it. Conjoined with the law so a device the predicate matches but some other rule opened
|
|
41
|
+
* — an isolated IC, a charge pump — is not attributed to this one.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findMultiDeviceShells(lawed: LawedNetlist): readonly NonExecutableSupportShellWarning[];
|
|
44
|
+
/**
|
|
45
|
+
* An `opamp` whose own device-class law cannot bind its terminals, so a registry `sections` entry
|
|
46
|
+
* is the only thing that can place them.
|
|
47
|
+
*
|
|
48
|
+
* **The direction matters, and it is the OTA rule inverted.** `sectionDevices` records that for an
|
|
49
|
+
* OTA "the registry only wins when it can bind by role", because an OTA carries a correct
|
|
50
|
+
* role-bound device-class law and a positional guess from an entry written for other spellings is
|
|
51
|
+
* strictly worse. An op-amp is in the same position, so the same principle gives the mirror rule:
|
|
52
|
+
* **the device-class law wins wherever it can read the terminals, and the registry is consulted
|
|
53
|
+
* only where it cannot.** That keeps every ordinary op-amp exactly where it is.
|
|
54
|
+
*
|
|
55
|
+
* Measured over the corpus: 113 `opamp` devices declare three terminals, 195 declare five, four
|
|
56
|
+
* declare seven (`LM308`/`OP07CP` balance pins, `HA1457W` compensation pins) and **one** declares
|
|
57
|
+
* eight -- `boss-dm-3`'s `IC1`, a whole `NJM4558DD` dual package as a single component. Only that
|
|
58
|
+
* one fails to bind, because it names two non-inverting inputs and `uniqueRoleIndex` refuses an
|
|
59
|
+
* ambiguous read. Stamped as one op-amp it put both inputs on node 4 and drove node 10, which is
|
|
60
|
+
* *both* sections' non-inverting input.
|
|
61
|
+
*
|
|
62
|
+
* Widening `mayCarryRegistrySections` to every `opamp` was tried on 2026-09-02 and measured wrong:
|
|
63
|
+
* `boss-dm-3` itself became `unsupported` and 14 other packets' programs moved. This predicate is
|
|
64
|
+
* why the fix is scoped rather than a kind test.
|
|
65
|
+
*/
|
|
66
|
+
export declare function opampNeedsRegistrySections(device: Device): boolean;
|
|
67
|
+
//# sourceMappingURL=unreadable-terminal-role.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unreadable-terminal-role.d.ts","sourceRoot":"","sources":["../src/unreadable-terminal-role.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EACX,MAAM,EACN,YAAY,EACZ,gCAAgC,EAChC,6BAA6B,EAC7B,MAAM,SAAS,CAAC;AAwDjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAqBpE;AA8HD,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,YAAY,GACjB,SAAS,6BAA6B,EAAE,CAqI1C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,YAAY,GACjB,SAAS,gCAAgC,EAAE,CAuB7C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQlE"}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
// A device that **named** its terminals in a spelling no resolver recognises, and was therefore
|
|
2
|
+
// wired by declaration order.
|
|
3
|
+
//
|
|
4
|
+
// **The defect class this closes.** Four asymmetric-device resolvers in `lower.ts` -- transistor,
|
|
5
|
+
// op-amp, two-terminal diode, supply -- fall back to declaration order when they cannot read a
|
|
6
|
+
// terminal role. That fallback is correct for a document of bare lugs, which carries no
|
|
7
|
+
// orientation evidence at all. It is a *guess* for a document that named its terminals in a
|
|
8
|
+
// vocabulary the resolver does not speak, and the guess is silent: the packet compiles `ok`,
|
|
9
|
+
// renders, and sounds like something. `bjtTerminals`' own comment records why that matters --
|
|
10
|
+
// 449 of the corpus's 490 transistors do not declare their control terminal first, so positional
|
|
11
|
+
// order exchanges base and collector on nearly every transistor there is.
|
|
12
|
+
//
|
|
13
|
+
// **Why a warning and not a refusal.** The 2026-09-02 census (R1 in
|
|
14
|
+
// `thoughts/shared/plans/archive/2026-08-31-v2-complexity-reduction-plan.md`) measured the residue after
|
|
15
|
+
// the true synonyms were absorbed: five packets that compile today carry a device this would
|
|
16
|
+
// refuse, and all five render. `CompileWarning`'s own contract is the rule for exactly this
|
|
17
|
+
// situation -- "things that compiled but will not behave. A warning never blocks a program ... but
|
|
18
|
+
// it must not be silent either" -- and this repository's standing principle is not to trade a
|
|
19
|
+
// working product for a stricter gate. So the silent class becomes *named* here, which was the
|
|
20
|
+
// whole complaint, and promoting these rows to refusals is a later layer, once the named rows are
|
|
21
|
+
// corrected at the source.
|
|
22
|
+
//
|
|
23
|
+
// **What this does not claim.** A warning here says the resolver could not read the declared
|
|
24
|
+
// roles and fell back to position. It does **not** say the resulting wiring is wrong: declaration
|
|
25
|
+
// order may coincide with the right answer, and on a symmetric device it always does. The
|
|
26
|
+
// `orientationFreeRoles` escape hatch removes the cases where the fallback is the document's
|
|
27
|
+
// intended reading, so what remains is "a stated fact this pipeline could not use" -- which is
|
|
28
|
+
// the same bar `report-source-coverage.ts` applies on the property side.
|
|
29
|
+
import { orientationFreeRoles, supplyDriveRoles, } from "./terminal-roles.js";
|
|
30
|
+
import { foldToken } from "./registry.js";
|
|
31
|
+
import { otaPackageOrderAssumed } from "./device-laws.js";
|
|
32
|
+
import { optocouplerBinding } from "./lower.js";
|
|
33
|
+
/**
|
|
34
|
+
* The one terminal index whose role is in `accepted`, or null when none or several are.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors `lower.ts`'s `uniqueRoleIndex` deliberately, including its refusal of an ambiguous
|
|
37
|
+
* match: a device declaring two terminals that both read as one slot is more than one device in
|
|
38
|
+
* one component, and the resolver falls back for that reason too.
|
|
39
|
+
*/
|
|
40
|
+
function unique(roles, accepted) {
|
|
41
|
+
const found = roles.flatMap((role, index) => role !== null && accepted.has(role) ? [index] : []);
|
|
42
|
+
return found.length === 1 ? (found[0] ?? null) : null;
|
|
43
|
+
}
|
|
44
|
+
const allSlotsRead = (roles, slots) => slots.every((slot) => unique(roles, slot) !== null);
|
|
45
|
+
/**
|
|
46
|
+
* The declared roles a resolver was given and could not place: everything the document named,
|
|
47
|
+
* minus the tokens that deliberately state no orientation. Empty means there was nothing to
|
|
48
|
+
* misread — either the document named nothing, or what it named carries no electrode claim.
|
|
49
|
+
*/
|
|
50
|
+
function unplaceableRoles(roles, slots) {
|
|
51
|
+
const named = roles.filter((role) => role !== null);
|
|
52
|
+
if (named.length === 0 || allSlotsRead(roles, slots)) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
return named.filter((role) => !orientationFreeRoles.has(role));
|
|
56
|
+
}
|
|
57
|
+
/** A transistor whose declared roles do not give exactly one full electrode triple. */
|
|
58
|
+
function transistorDeclaredRolesMissing(device) {
|
|
59
|
+
// Fewer than three terminals is not a transistor this law can bind at all, and a device with
|
|
60
|
+
// none reaches no resolver.
|
|
61
|
+
if (device.nodes.length < 3) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const declared = device.identity.declaredTerminalRoles;
|
|
65
|
+
const has = (role) => declared.filter((value) => value === role).length === 1;
|
|
66
|
+
return !((has("base") && has("collector") && has("emitter")) ||
|
|
67
|
+
(has("gate") && has("drain") && has("source")));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A component declared as one transistor that is really **several devices in one shell**.
|
|
71
|
+
*
|
|
72
|
+
* `boss-ce-1` declares `SRC_CE1_Q3_Q6_D01_D05_CLOCK_BRIDGE_SUPPORT` as `kind: bjt` with
|
|
73
|
+
* **nineteen** terminals, standing for four transistors and five diodes, and
|
|
74
|
+
* `SRC_CE1_Q15_Q16_Q17_POWER_REGULATOR` as `kind: bjt` with eight, standing for three. Stamping
|
|
75
|
+
* either as a single transistor invents a device: the packet's own `Description` says "Exact
|
|
76
|
+
* physical package C/B/E orientation … remain unresolved", so there is no base, collector or
|
|
77
|
+
* emitter to bind, and declaration order supplies one anyway.
|
|
78
|
+
*
|
|
79
|
+
* **Two conditions, and the conjunction is what makes this safe.**
|
|
80
|
+
*
|
|
81
|
+
* - *The law cannot consume the terminals.* A `bjt`/`fet` law binds exactly three nodes, so a
|
|
82
|
+
* component declaring more has terminals no stamp can reach.
|
|
83
|
+
* - *And its roles cannot be read.* This is the discriminator. Measured across the corpus, 20
|
|
84
|
+
* devices declare more terminals than their kind's law consumes, and almost all are
|
|
85
|
+
* legitimate: 14 are multi-junction diodes (bridges, dual tube rectifiers) that
|
|
86
|
+
* `diodeJunctions` places by role, and `moogerfooger-mf-102`'s four `MPQ3906` sections are a
|
|
87
|
+
* quad transistor array declaring `collector`/`base`/`emitter` plus two unused package pins,
|
|
88
|
+
* which read cleanly. Only `boss-ce-1`'s two shells fail both tests.
|
|
89
|
+
*
|
|
90
|
+
* **Why not read `PartNumber`.** These shells announce themselves there —
|
|
91
|
+
* `"Q3/Q4 2SA493; Q5/Q6 2SC536F; D01-D05 1S1555"` is plainly several parts — and splitting that
|
|
92
|
+
* string on its separators is exactly the prose parsing this repository forbids for a
|
|
93
|
+
* classification decision. Terminal count against a law's fixed arity, and whether a closed role
|
|
94
|
+
* vocabulary reads, are structural facts about the document instead.
|
|
95
|
+
*
|
|
96
|
+
* Deliberately not extended to `opamp`: an op-amp package legitimately declares more terminals
|
|
97
|
+
* than its law binds (supplies, a second section), so arity says nothing there. `boss-dm-3`'s
|
|
98
|
+
* 8-pin `IC1` is that case and is a registry-expansion question, not a shell.
|
|
99
|
+
*/
|
|
100
|
+
export function isMultiDeviceTransistorShell(device) {
|
|
101
|
+
if (device.kind !== "bjt" &&
|
|
102
|
+
device.kind !== "jfet" &&
|
|
103
|
+
device.kind !== "mosfet") {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (device.nodes.length <= 3) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
// **The declared triple, not a table of spellings.** This predicate decides the *program* --
|
|
110
|
+
// a shell is opened rather than stamped -- so it was the last program-affecting reader of
|
|
111
|
+
// `transistorControlRoles` and its two siblings -- now deleted, since diagnostics were their
|
|
112
|
+
// only other reader and it needed neither. Every device this distinguishes already declares
|
|
113
|
+
// its electrodes, which is what makes the swap behaviour-neutral: `moogerfooger-mf-102`'s
|
|
114
|
+
// four `MPQ3906` sections declare `collector`/`base`/`emitter` beside two unused package
|
|
115
|
+
// pins, `fulltone-ocd`'s and `mxr-carbon-copy`'s MOSFETs declare `drain`/`gate`/`source`
|
|
116
|
+
// beside `bulk`, and `boss-ce-1`'s two shells declare nothing at all -- which is exactly the
|
|
117
|
+
// distinction being drawn.
|
|
118
|
+
return transistorDeclaredRolesMissing(device);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The slot sets each law's resolver reads, or null for a law this check does not cover.
|
|
122
|
+
*
|
|
123
|
+
* Only the four asymmetric resolvers that **fall back to declaration order** are listed. A
|
|
124
|
+
* resolver that already refuses on an unreadable role needs nothing here -- the triode, the
|
|
125
|
+
* pentode, the tube diode, the transformer and the multi-junction diode all name the offending
|
|
126
|
+
* token themselves. Deliberately absent for a different reason: a **pot**, whose unresolved
|
|
127
|
+
* orientation is a quiet-reference hint rather than a topology decision ("an unresolved pot,
|
|
128
|
+
* never a wrong one" -- `lowerRegion`'s own parameter docs); a **switch**, where the corpus
|
|
129
|
+
* routinely leaves the common terminal unnamed and `switchPoles` treats the first contact as
|
|
130
|
+
* common by design; and an **OTA**, whose binding permits a null bias pin outright and whose
|
|
131
|
+
* package fallback requires eight all-null roles, so a named OTA never reaches it.
|
|
132
|
+
*/
|
|
133
|
+
function slotsForLaw(law, device) {
|
|
134
|
+
// `bjt`, `fet` and `ideal-opamp` are handled by `declaredRolesMissing` instead: since
|
|
135
|
+
// 2026-09-03 their resolvers read the declared `role` rather than the terminal name, so
|
|
136
|
+
// checking the name vocabulary here would report a device as readable that the resolver then
|
|
137
|
+
// refuses or wires positionally -- the silent fallback this warning exists to catch. Keeping
|
|
138
|
+
// a warning on a different vocabulary from the resolver it guards is how that bug was
|
|
139
|
+
// introduced once already, in this same file, on the same day.
|
|
140
|
+
if (law === "bjt" || law === "fet" || law === "ideal-opamp") {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// A two-terminal diode is handled by `diodeDeclaredRolesMissing` for the same reason: its
|
|
144
|
+
// resolver reads the declared `anode`/`cathode`, so a name check here would call a device
|
|
145
|
+
// readable that the resolver then orients by declaration order.
|
|
146
|
+
if (law === "diode" && device.nodes.length === 2) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
// A rail declares one terminal and means "against ground", which is not a polarity
|
|
150
|
+
// question -- `supplyTerminals` returns early for it and reads no role at all.
|
|
151
|
+
if ((law === "voltage-source" || law === "ac-source") &&
|
|
152
|
+
device.nodes.length > 1) {
|
|
153
|
+
return [supplyDriveRoles];
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* `supplyTerminals` resolves from **either** end alone -- one named terminal beside an unlabelled
|
|
159
|
+
* lug is enough, and requiring both would discard the evidence in a supply declaring `positive`
|
|
160
|
+
* next to a bare pin. So its readable test is a disjunction where the other three are
|
|
161
|
+
* conjunctions, and treating it as a conjunction here would warn about supplies the resolver
|
|
162
|
+
* orients correctly.
|
|
163
|
+
*
|
|
164
|
+
* **The return half of the disjunction is gone**, along with `supplyReturnRoles`. Emptying that
|
|
165
|
+
* set left the corpus's `terminal-role-unreadable` count unchanged at 34, and removing its slot
|
|
166
|
+
* outright left it unchanged again -- so no corpus supply was being spared a warning by a
|
|
167
|
+
* `negative`/`neutral`/`return` *name*. Its declared counterpart is what `supplyTerminals` reads.
|
|
168
|
+
*/
|
|
169
|
+
function supplyReadable(roles) {
|
|
170
|
+
return roles.some((role) => role !== null && supplyDriveRoles.has(role));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The three-terminal roles a `bjt`/`fet` resolver needs, and whether the device declares them.
|
|
174
|
+
*
|
|
175
|
+
* Kept beside the name-based check rather than merged with it, because the two ask different
|
|
176
|
+
* questions now: this one asks what the *source declared*, which is what `lower.ts` reads.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* A switch with three or more contacts that declares no pole, so `switchPoles` takes the first
|
|
180
|
+
* contact as the common.
|
|
181
|
+
*
|
|
182
|
+
* **Two contacts are exempt, and the exemption is measured rather than assumed.** A closed contact
|
|
183
|
+
* pair is a symmetric conductance, so which terminal is called the pole cannot change the circuit
|
|
184
|
+
* -- verified by swapping the two terminals of `earthquaker-devices-plumes`'s `SW` and diffing the
|
|
185
|
+
* program: the only difference is the stamp's `a` and `b` fields exchanging, `{"a":25,"b":0}` for
|
|
186
|
+
* `{"a":0,"b":25}`. The digest moves and the circuit does not, which is the one case where the
|
|
187
|
+
* digest gate reports a difference that is not there.
|
|
188
|
+
*
|
|
189
|
+
* At three contacts it matters: the pole is the node every throw hangs off, and choosing the wrong
|
|
190
|
+
* one rewires the switch. 118 corpus switches name what each contact *connects to* -- `effect`,
|
|
191
|
+
* `bypass`, `rectifier_output` -- which says nothing about which is the pole, and 32 of those have
|
|
192
|
+
* three or more contacts.
|
|
193
|
+
*/
|
|
194
|
+
function switchPoleUnreadable(device) {
|
|
195
|
+
const declared = device.identity.declaredTerminalRoles;
|
|
196
|
+
if (declared.some((role) => role === "common")) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
// The name rung this used to mirror is gone from `switchPoles` along with
|
|
200
|
+
// `switchCommonRoles`, so the declared role above is the whole test. It stays worth
|
|
201
|
+
// recording that mirroring mattered: checking only the declaration once reported 62
|
|
202
|
+
// switches, and its first two examples had a terminal literally named `common`, which the
|
|
203
|
+
// compiler was still reading -- a warning naming a mechanism the compiler did not use is
|
|
204
|
+
// worse than none.
|
|
205
|
+
// Contacts only: a `coil` or `pin` terminal is not part of the mechanism's contact set, and a
|
|
206
|
+
// document declaring neither still has every terminal to choose a pole from.
|
|
207
|
+
const contacts = declared.some((role) => role !== null)
|
|
208
|
+
? declared.filter((role) => role === "throw").length
|
|
209
|
+
: device.nodes.length;
|
|
210
|
+
return contacts >= 3;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A two-terminal diode that declares no orientation, so `diodeTerminals` takes its direction from
|
|
214
|
+
* declaration order.
|
|
215
|
+
*
|
|
216
|
+
* **`end`/`end` is the case this exists for.** Core's `end` means two interchangeable ends, which
|
|
217
|
+
* is true of a resistor and false of a diode: a diode has a direction, so `end`/`end` says the
|
|
218
|
+
* source did not state it rather than that there is nothing to state. 13 corpus diodes are in
|
|
219
|
+
* that position, and reversing one of them moves the program — measured by mutation, in a review
|
|
220
|
+
* that found this while `orientationFreeRoles` was keeping the warning quiet about it.
|
|
221
|
+
*/
|
|
222
|
+
function diodeDeclaredRolesMissing(device) {
|
|
223
|
+
const declared = device.identity.declaredTerminalRoles;
|
|
224
|
+
return !(declared.includes("anode") && declared.includes("cathode"));
|
|
225
|
+
}
|
|
226
|
+
/** An op-amp whose declared roles do not give exactly one of each signal pin. */
|
|
227
|
+
function opampDeclaredRolesMissing(device) {
|
|
228
|
+
const declared = device.identity.declaredTerminalRoles;
|
|
229
|
+
return !["nonInverting", "inverting", "output"].every((role) => declared.filter((value) => value === role).length === 1);
|
|
230
|
+
}
|
|
231
|
+
export function findUnreadableTerminalRoles(lawed) {
|
|
232
|
+
const warnings = [];
|
|
233
|
+
// Read the law rather than `device.kind`, because a multi-section part has already become
|
|
234
|
+
// one device per section by this stage, with its roles rewritten to canonical ones -- so a
|
|
235
|
+
// dual op-amp the registry recognises is correctly wired and must not be reported here.
|
|
236
|
+
const lawByDevice = new Map(lawed.resolutions.flatMap((resolution) => resolution.outcome === "law"
|
|
237
|
+
? [[resolution.device, resolution.law.kind]]
|
|
238
|
+
: []));
|
|
239
|
+
for (const device of lawed.netlist.devices) {
|
|
240
|
+
const law = lawByDevice.get(device.id);
|
|
241
|
+
if (law === undefined) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (law === "selector") {
|
|
245
|
+
if (switchPoleUnreadable(device)) {
|
|
246
|
+
const named = device.identity.terminalRoles
|
|
247
|
+
.filter((role) => role !== null)
|
|
248
|
+
.map((role) => `"${role}"`);
|
|
249
|
+
warnings.push({
|
|
250
|
+
code: "terminal-role-unreadable",
|
|
251
|
+
device: device.id,
|
|
252
|
+
detail: `switch ${device.id} declares no \`common\` among its ${device.nodes.length} ` +
|
|
253
|
+
"terminals' roles, so the first contact was taken as the pole and every other " +
|
|
254
|
+
`contact hung off it${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
|
|
255
|
+
"With three or more contacts the pole decides the wiring; with two it cannot.",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (law === "ota") {
|
|
261
|
+
if (otaPackageOrderAssumed(device)) {
|
|
262
|
+
warnings.push({
|
|
263
|
+
code: "terminal-role-unreadable",
|
|
264
|
+
device: device.id,
|
|
265
|
+
detail: `OTA ${device.id} names none of its eight terminals and declares no ` +
|
|
266
|
+
"electrodes, so its inputs, output and bias were read as DIP-8 package " +
|
|
267
|
+
"order. That is a better assumption than declaration order, which puts the " +
|
|
268
|
+
"output on pin 3, but it is still the package's convention rather than " +
|
|
269
|
+
"anything this document states.",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (law === "optocoupler") {
|
|
275
|
+
const binding = optocouplerBinding(device);
|
|
276
|
+
if (binding !== "declared") {
|
|
277
|
+
warnings.push({
|
|
278
|
+
code: "terminal-role-unreadable",
|
|
279
|
+
device: device.id,
|
|
280
|
+
detail: binding === "named"
|
|
281
|
+
? `optocoupler ${device.id} declares no anode or cell ends, so its LED ` +
|
|
282
|
+
"direction was taken from its terminals' names instead. The wiring is " +
|
|
283
|
+
"right and the evidence is prose: declaring `anode` and two `end` " +
|
|
284
|
+
"roles states the same fact in a form nothing has to spell-match."
|
|
285
|
+
: `optocoupler ${device.id} declares no roles and names none its ` +
|
|
286
|
+
"resolver recognises, so its LED and cell were taken in declaration " +
|
|
287
|
+
"order. An LED has a direction and the source did not state one.",
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (law === "diode" && device.nodes.length === 2) {
|
|
293
|
+
if (diodeDeclaredRolesMissing(device)) {
|
|
294
|
+
const named = device.identity.terminalRoles
|
|
295
|
+
.filter((role) => role !== null)
|
|
296
|
+
.map((role) => `"${role}"`);
|
|
297
|
+
warnings.push({
|
|
298
|
+
code: "terminal-role-unreadable",
|
|
299
|
+
device: device.id,
|
|
300
|
+
detail: `diode ${device.id} declares no anode and cathode among its terminals' roles, ` +
|
|
301
|
+
`so its direction was taken in declaration order instead${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
|
|
302
|
+
"A diode has a direction and `end` does not state one, so declaration order " +
|
|
303
|
+
"may or may not be the way this one conducts.",
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (law === "bjt" || law === "fet") {
|
|
309
|
+
if (transistorDeclaredRolesMissing(device)) {
|
|
310
|
+
const named = device.identity.terminalRoles
|
|
311
|
+
.filter((role) => role !== null)
|
|
312
|
+
.map((role) => `"${role}"`);
|
|
313
|
+
warnings.push({
|
|
314
|
+
code: "terminal-role-unreadable",
|
|
315
|
+
device: device.id,
|
|
316
|
+
detail: `${device.kind} ${device.id} does not declare a base/collector/emitter or ` +
|
|
317
|
+
"gate/drain/source among its terminals' roles, so they were taken in " +
|
|
318
|
+
`declaration order instead${named.length > 0 ? ` (its terminals are named ${named.join(", ")})` : ""}. ` +
|
|
319
|
+
"Declaration order may or may not be the right wiring.",
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const slots = slotsForLaw(law, device);
|
|
325
|
+
if (slots === null) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const roles = device.identity.terminalRoles;
|
|
329
|
+
// A supply resolves from **either** end alone, so its readable test is a disjunction
|
|
330
|
+
// where the other three are conjunctions; `unplaceableRoles` asks the conjunction.
|
|
331
|
+
if ((law === "voltage-source" || law === "ac-source") &&
|
|
332
|
+
supplyReadable(roles)) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
// Empty covers all three silent cases at once: nothing declared (bare lugs, where
|
|
336
|
+
// declaration order is all the document supports), roles that read cleanly, and roles
|
|
337
|
+
// that are orientation-free and so state no electrode to have missed.
|
|
338
|
+
const unreadable = unplaceableRoles(roles, slots);
|
|
339
|
+
if (unreadable.length === 0) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
warnings.push({
|
|
343
|
+
code: "terminal-role-unreadable",
|
|
344
|
+
device: device.id,
|
|
345
|
+
detail: `${device.kind} ${device.id} declares terminal role${unreadable.length === 1 ? "" : "s"} ` +
|
|
346
|
+
`${unreadable.map((role) => `"${role}"`).join(", ")} that its ${law} lowering ` +
|
|
347
|
+
"cannot place, so its terminals were taken in declaration order instead. Declaration " +
|
|
348
|
+
"order may or may not be the right wiring; the device's declared roles were not used.",
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return warnings;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* The multi-device shells stage 3 resolved to `open`, so a packet is told the component was
|
|
355
|
+
* dropped rather than silently losing it.
|
|
356
|
+
*
|
|
357
|
+
* Paired with `isMultiDeviceTransistorShell`'s use in `resolveDevice`: that decides the law, this
|
|
358
|
+
* reports it. Conjoined with the law so a device the predicate matches but some other rule opened
|
|
359
|
+
* — an isolated IC, a charge pump — is not attributed to this one.
|
|
360
|
+
*/
|
|
361
|
+
export function findMultiDeviceShells(lawed) {
|
|
362
|
+
const opened = new Set(lawed.resolutions.flatMap((resolution) => resolution.outcome === "law" && resolution.law.kind === "open"
|
|
363
|
+
? [resolution.device]
|
|
364
|
+
: []));
|
|
365
|
+
return lawed.netlist.devices.flatMap((device) => opened.has(device.id) && isMultiDeviceTransistorShell(device)
|
|
366
|
+
? [
|
|
367
|
+
{
|
|
368
|
+
code: "non-executable-support-shell",
|
|
369
|
+
device: device.id,
|
|
370
|
+
detail: `${device.kind} ${device.id} declares ${device.nodes.length} terminals for a law that ` +
|
|
371
|
+
"binds three, and names none of them readably, so it stands for several devices " +
|
|
372
|
+
"rather than one. It is not executed: stamping it as a single transistor would " +
|
|
373
|
+
"invent a base, collector and emitter the source does not state.",
|
|
374
|
+
},
|
|
375
|
+
]
|
|
376
|
+
: []);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* An `opamp` whose own device-class law cannot bind its terminals, so a registry `sections` entry
|
|
380
|
+
* is the only thing that can place them.
|
|
381
|
+
*
|
|
382
|
+
* **The direction matters, and it is the OTA rule inverted.** `sectionDevices` records that for an
|
|
383
|
+
* OTA "the registry only wins when it can bind by role", because an OTA carries a correct
|
|
384
|
+
* role-bound device-class law and a positional guess from an entry written for other spellings is
|
|
385
|
+
* strictly worse. An op-amp is in the same position, so the same principle gives the mirror rule:
|
|
386
|
+
* **the device-class law wins wherever it can read the terminals, and the registry is consulted
|
|
387
|
+
* only where it cannot.** That keeps every ordinary op-amp exactly where it is.
|
|
388
|
+
*
|
|
389
|
+
* Measured over the corpus: 113 `opamp` devices declare three terminals, 195 declare five, four
|
|
390
|
+
* declare seven (`LM308`/`OP07CP` balance pins, `HA1457W` compensation pins) and **one** declares
|
|
391
|
+
* eight -- `boss-dm-3`'s `IC1`, a whole `NJM4558DD` dual package as a single component. Only that
|
|
392
|
+
* one fails to bind, because it names two non-inverting inputs and `uniqueRoleIndex` refuses an
|
|
393
|
+
* ambiguous read. Stamped as one op-amp it put both inputs on node 4 and drove node 10, which is
|
|
394
|
+
* *both* sections' non-inverting input.
|
|
395
|
+
*
|
|
396
|
+
* Widening `mayCarryRegistrySections` to every `opamp` was tried on 2026-09-02 and measured wrong:
|
|
397
|
+
* `boss-dm-3` itself became `unsupported` and 14 other packets' programs moved. This predicate is
|
|
398
|
+
* why the fix is scoped rather than a kind test.
|
|
399
|
+
*/
|
|
400
|
+
export function opampNeedsRegistrySections(device) {
|
|
401
|
+
if (device.kind !== "opamp") {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
// The same question `opampTerminals` asks, on the same field: a package declares two of each
|
|
405
|
+
// signal role and the resolver refuses it, so this predicate has to agree with that or the
|
|
406
|
+
// two disagree about which devices need sections.
|
|
407
|
+
return opampDeclaredRolesMissing(device);
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=unreadable-terminal-role.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unreadable-terminal-role.js","sourceRoot":"","sources":["../src/unreadable-terminal-role.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PartRegistry } from "./registry";
|
|
2
|
+
import type { CompileWarning, Netlist } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Parts whose terminals are mapped to law slots by declaration order alone.
|
|
5
|
+
*
|
|
6
|
+
* **Measured 2026-09-03: 30 devices across 21 packets, and one of them is wrong.**
|
|
7
|
+
* (55 corpus devices take the positional rung; the 30 are those whose entry pinout is null
|
|
8
|
+
* throughout, so nothing checks the order at all.)
|
|
9
|
+
* `moogerfooger-mf-102`'s `U13` is a 78L05 whose three terminals are `pin1`/`pin2`/`pin3`, and the
|
|
10
|
+
* order the entry assumed puts the regulator's reference on the pedal's own rail: node 3 carries
|
|
11
|
+
* 24 devices and solves to **-4.9989 V**, so 18 of the packet's 26 active devices sit dark with
|
|
12
|
+
* their base-emitter junctions reverse-biased by a whole supply.
|
|
13
|
+
*
|
|
14
|
+
* **There is no connectivity rule to fall back on, and that was tested rather than assumed.**
|
|
15
|
+
* "The reference is the grounded terminal and the output is the busier of the rest" agrees with
|
|
16
|
+
* four of the corpus's named regulators, disagrees with `boss-dd-3b`'s `TA78L05F`, and cannot
|
|
17
|
+
* apply to `boss-rv-3`, whose 78L05 has no terminal on ground at all. A rule that fixes one
|
|
18
|
+
* packet and breaks another is not a rule.
|
|
19
|
+
*
|
|
20
|
+
* Nor does the corpus agree on the order itself: three packets name a 78Lxx `in, gnd, out` and
|
|
21
|
+
* `electro-harmonix-q-tron` names it `in, out, ground`. So this is reported rather than repaired
|
|
22
|
+
* -- the order has to be asserted by the entry's `pinout` or by the document's own terminal
|
|
23
|
+
* roles, and until one of them does, an author who writes a package's pins in a different order
|
|
24
|
+
* gets a different circuit with no diagnostic.
|
|
25
|
+
*/
|
|
26
|
+
export declare function findUnverifiedPinoutBindings(netlist: Netlist, registry: PartRegistry): readonly CompileWarning[];
|
|
27
|
+
//# sourceMappingURL=unverified-pinout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unverified-pinout.d.ts","sourceRoot":"","sources":["../src/unverified-pinout.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAoE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,YAAY,GACpB,SAAS,cAAc,EAAE,CAgC3B"}
|