@vessel-dsp/compiler 0.0.0-stage → 0.2.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.
Files changed (226) hide show
  1. package/README.md +314 -2
  2. package/dist/bake.d.ts +38 -0
  3. package/dist/bake.d.ts.map +1 -0
  4. package/dist/bake.js +101 -0
  5. package/dist/bake.js.map +1 -0
  6. package/dist/bbd-clock.d.ts +171 -0
  7. package/dist/bbd-clock.d.ts.map +1 -0
  8. package/dist/bbd-clock.js +1750 -0
  9. package/dist/bbd-clock.js.map +1 -0
  10. package/dist/block-row.d.ts +51 -0
  11. package/dist/block-row.d.ts.map +1 -0
  12. package/dist/block-row.js +17 -0
  13. package/dist/block-row.js.map +1 -0
  14. package/dist/bypass.d.ts +3 -0
  15. package/dist/bypass.d.ts.map +1 -0
  16. package/dist/bypass.js +228 -0
  17. package/dist/bypass.js.map +1 -0
  18. package/dist/compile.d.ts +24 -0
  19. package/dist/compile.d.ts.map +1 -0
  20. package/dist/compile.js +344 -0
  21. package/dist/compile.js.map +1 -0
  22. package/dist/converter-scale.d.ts +14 -0
  23. package/dist/converter-scale.d.ts.map +1 -0
  24. package/dist/converter-scale.js +133 -0
  25. package/dist/converter-scale.js.map +1 -0
  26. package/dist/couple.d.ts +28 -0
  27. package/dist/couple.d.ts.map +1 -0
  28. package/dist/couple.js +567 -0
  29. package/dist/couple.js.map +1 -0
  30. package/dist/dangling-active-terminal.d.ts +47 -0
  31. package/dist/dangling-active-terminal.d.ts.map +1 -0
  32. package/dist/dangling-active-terminal.js +542 -0
  33. package/dist/dangling-active-terminal.js.map +1 -0
  34. package/dist/declared-program.d.ts +23 -0
  35. package/dist/declared-program.d.ts.map +1 -0
  36. package/dist/declared-program.js +387 -0
  37. package/dist/declared-program.js.map +1 -0
  38. package/dist/denomination.d.ts +48 -0
  39. package/dist/denomination.d.ts.map +1 -0
  40. package/dist/denomination.js +27 -0
  41. package/dist/denomination.js.map +1 -0
  42. package/dist/device-laws.d.ts +237 -0
  43. package/dist/device-laws.d.ts.map +1 -0
  44. package/dist/device-laws.js +3497 -0
  45. package/dist/device-laws.js.map +1 -0
  46. package/dist/diagnostics.d.ts +13 -0
  47. package/dist/diagnostics.d.ts.map +1 -0
  48. package/dist/diagnostics.js +19 -0
  49. package/dist/diagnostics.js.map +1 -0
  50. package/dist/emit.d.ts +8 -0
  51. package/dist/emit.d.ts.map +1 -0
  52. package/dist/emit.js +43 -0
  53. package/dist/emit.js.map +1 -0
  54. package/dist/errors.d.ts +22 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +39 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/firmware-class.d.ts +69 -0
  59. package/dist/firmware-class.d.ts.map +1 -0
  60. package/dist/firmware-class.js +20 -0
  61. package/dist/firmware-class.js.map +1 -0
  62. package/dist/fixtures/circuits.d.ts +1721 -0
  63. package/dist/fixtures/circuits.d.ts.map +1 -0
  64. package/dist/fixtures/circuits.js +13404 -0
  65. package/dist/fixtures/circuits.js.map +1 -0
  66. package/dist/fixtures/expected.d.ts +257 -0
  67. package/dist/fixtures/expected.d.ts.map +1 -0
  68. package/dist/fixtures/expected.js +311 -0
  69. package/dist/fixtures/expected.js.map +1 -0
  70. package/dist/fixtures/index.d.ts +4 -0
  71. package/dist/fixtures/index.d.ts.map +1 -0
  72. package/dist/fixtures/index.js +8 -0
  73. package/dist/fixtures/index.js.map +1 -0
  74. package/dist/fixtures/registry.d.ts +52 -0
  75. package/dist/fixtures/registry.d.ts.map +1 -0
  76. package/dist/fixtures/registry.js +341 -0
  77. package/dist/fixtures/registry.js.map +1 -0
  78. package/dist/generic-tube-fit.d.ts +12 -0
  79. package/dist/generic-tube-fit.d.ts.map +1 -0
  80. package/dist/generic-tube-fit.js +45 -0
  81. package/dist/generic-tube-fit.js.map +1 -0
  82. package/dist/grounded-clock-supply.d.ts +13 -0
  83. package/dist/grounded-clock-supply.d.ts.map +1 -0
  84. package/dist/grounded-clock-supply.js +45 -0
  85. package/dist/grounded-clock-supply.js.map +1 -0
  86. package/dist/identify.d.ts +50 -0
  87. package/dist/identify.d.ts.map +1 -0
  88. package/dist/identify.js +319 -0
  89. package/dist/identify.js.map +1 -0
  90. package/dist/index.d.ts +10 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +19 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/inert-controls.d.ts +15 -0
  95. package/dist/inert-controls.d.ts.map +1 -0
  96. package/dist/inert-controls.js +266 -0
  97. package/dist/inert-controls.js.map +1 -0
  98. package/dist/latch-seed.d.ts +53 -0
  99. package/dist/latch-seed.d.ts.map +1 -0
  100. package/dist/latch-seed.js +257 -0
  101. package/dist/latch-seed.js.map +1 -0
  102. package/dist/link.d.ts +7 -0
  103. package/dist/link.d.ts.map +1 -0
  104. package/dist/link.js +270 -0
  105. package/dist/link.js.map +1 -0
  106. package/dist/lower.d.ts +79 -0
  107. package/dist/lower.d.ts.map +1 -0
  108. package/dist/lower.js +1855 -0
  109. package/dist/lower.js.map +1 -0
  110. package/dist/netlist.d.ts +79 -0
  111. package/dist/netlist.d.ts.map +1 -0
  112. package/dist/netlist.js +4746 -0
  113. package/dist/netlist.js.map +1 -0
  114. package/dist/non-executable-clock-drivers.d.ts +8 -0
  115. package/dist/non-executable-clock-drivers.d.ts.map +1 -0
  116. package/dist/non-executable-clock-drivers.js +33 -0
  117. package/dist/non-executable-clock-drivers.js.map +1 -0
  118. package/dist/open-category.d.ts +98 -0
  119. package/dist/open-category.d.ts.map +1 -0
  120. package/dist/open-category.js +111 -0
  121. package/dist/open-category.js.map +1 -0
  122. package/dist/over-driven-node.d.ts +33 -0
  123. package/dist/over-driven-node.d.ts.map +1 -0
  124. package/dist/over-driven-node.js +188 -0
  125. package/dist/over-driven-node.js.map +1 -0
  126. package/dist/part-catalog.d.ts +7 -0
  127. package/dist/part-catalog.d.ts.map +1 -0
  128. package/dist/part-catalog.js +6639 -0
  129. package/dist/part-catalog.js.map +1 -0
  130. package/dist/part-number.d.ts +32 -0
  131. package/dist/part-number.d.ts.map +1 -0
  132. package/dist/part-number.js +80 -0
  133. package/dist/part-number.js.map +1 -0
  134. package/dist/partition.d.ts +7 -0
  135. package/dist/partition.d.ts.map +1 -0
  136. package/dist/partition.js +242 -0
  137. package/dist/partition.js.map +1 -0
  138. package/dist/port-full-scale.d.ts +70 -0
  139. package/dist/port-full-scale.d.ts.map +1 -0
  140. package/dist/port-full-scale.js +235 -0
  141. package/dist/port-full-scale.js.map +1 -0
  142. package/dist/pot-orientation.d.ts +114 -0
  143. package/dist/pot-orientation.d.ts.map +1 -0
  144. package/dist/pot-orientation.js +551 -0
  145. package/dist/pot-orientation.js.map +1 -0
  146. package/dist/power-domain-control.d.ts +40 -0
  147. package/dist/power-domain-control.d.ts.map +1 -0
  148. package/dist/power-domain-control.js +142 -0
  149. package/dist/power-domain-control.js.map +1 -0
  150. package/dist/proxy-declaration.d.ts +121 -0
  151. package/dist/proxy-declaration.d.ts.map +1 -0
  152. package/dist/proxy-declaration.js +50 -0
  153. package/dist/proxy-declaration.js.map +1 -0
  154. package/dist/registry.d.ts +323 -0
  155. package/dist/registry.d.ts.map +1 -0
  156. package/dist/registry.js +192 -0
  157. package/dist/registry.js.map +1 -0
  158. package/dist/sparse-schedule.d.ts +65 -0
  159. package/dist/sparse-schedule.d.ts.map +1 -0
  160. package/dist/sparse-schedule.js +421 -0
  161. package/dist/sparse-schedule.js.map +1 -0
  162. package/dist/speaker-load.d.ts +38 -0
  163. package/dist/speaker-load.d.ts.map +1 -0
  164. package/dist/speaker-load.js +97 -0
  165. package/dist/speaker-load.js.map +1 -0
  166. package/dist/stage-coverage.d.ts +21 -0
  167. package/dist/stage-coverage.d.ts.map +1 -0
  168. package/dist/stage-coverage.js +124 -0
  169. package/dist/stage-coverage.js.map +1 -0
  170. package/dist/stamp-partition.d.ts +314 -0
  171. package/dist/stamp-partition.d.ts.map +1 -0
  172. package/dist/stamp-partition.js +472 -0
  173. package/dist/stamp-partition.js.map +1 -0
  174. package/dist/supply-reference.d.ts +19 -0
  175. package/dist/supply-reference.d.ts.map +1 -0
  176. package/dist/supply-reference.js +66 -0
  177. package/dist/supply-reference.js.map +1 -0
  178. package/dist/supply-short.d.ts +32 -0
  179. package/dist/supply-short.d.ts.map +1 -0
  180. package/dist/supply-short.js +118 -0
  181. package/dist/supply-short.js.map +1 -0
  182. package/dist/supply-stamps.d.ts +51 -0
  183. package/dist/supply-stamps.d.ts.map +1 -0
  184. package/dist/supply-stamps.js +363 -0
  185. package/dist/supply-stamps.js.map +1 -0
  186. package/dist/terminal-role.d.ts +109 -0
  187. package/dist/terminal-role.d.ts.map +1 -0
  188. package/dist/terminal-role.js +46 -0
  189. package/dist/terminal-role.js.map +1 -0
  190. package/dist/terminal-roles.d.ts +59 -0
  191. package/dist/terminal-roles.d.ts.map +1 -0
  192. package/dist/terminal-roles.js +92 -0
  193. package/dist/terminal-roles.js.map +1 -0
  194. package/dist/transformer.d.ts +181 -0
  195. package/dist/transformer.d.ts.map +1 -0
  196. package/dist/transformer.js +476 -0
  197. package/dist/transformer.js.map +1 -0
  198. package/dist/types.d.ts +3157 -0
  199. package/dist/types.d.ts.map +1 -0
  200. package/dist/types.js +11 -0
  201. package/dist/types.js.map +1 -0
  202. package/dist/unbounded-operating-point.d.ts +35 -0
  203. package/dist/unbounded-operating-point.d.ts.map +1 -0
  204. package/dist/unbounded-operating-point.js +181 -0
  205. package/dist/unbounded-operating-point.js.map +1 -0
  206. package/dist/unexecuted-region.d.ts +3 -0
  207. package/dist/unexecuted-region.d.ts.map +1 -0
  208. package/dist/unexecuted-region.js +122 -0
  209. package/dist/unexecuted-region.js.map +1 -0
  210. package/dist/unimplemented-control-role.d.ts +3 -0
  211. package/dist/unimplemented-control-role.d.ts.map +1 -0
  212. package/dist/unimplemented-control-role.js +61 -0
  213. package/dist/unimplemented-control-role.js.map +1 -0
  214. package/dist/unreachable-output.d.ts +3 -0
  215. package/dist/unreachable-output.d.ts.map +1 -0
  216. package/dist/unreachable-output.js +97 -0
  217. package/dist/unreachable-output.js.map +1 -0
  218. package/dist/unreadable-terminal-role.d.ts +67 -0
  219. package/dist/unreadable-terminal-role.d.ts.map +1 -0
  220. package/dist/unreadable-terminal-role.js +409 -0
  221. package/dist/unreadable-terminal-role.js.map +1 -0
  222. package/dist/unverified-pinout.d.ts +27 -0
  223. package/dist/unverified-pinout.d.ts.map +1 -0
  224. package/dist/unverified-pinout.js +121 -0
  225. package/dist/unverified-pinout.js.map +1 -0
  226. package/package.json +75 -5
@@ -0,0 +1,344 @@
1
+ // The pipeline: `.vdsp` source text -> a program, or an explanation of the refusal.
2
+ //
3
+ // Seven stages, composed. The registry is a parameter rather than an import, so the
4
+ // compiler holds no knowledge of any specific part -- and compiling with an empty
5
+ // registry is a legitimate configuration that measures what works with no part
6
+ // knowledge at all.
7
+ import { attachDeviceLaws, composeMacroBlocks, findElectricallyIsolatedIcs, findIcsNotExecuted, findUnimplementedDeviceLaws, JFET_DEFAULT_THRESHOLD_VOLTS, JFET_DEFAULT_TRANSCONDUCTANCE, SILICON_FORWARD_BETA, SILICON_SATURATION_CURRENT, } from "./device-laws.js";
8
+ import { findMultiDeviceShells, findUnreadableTerminalRoles, } from "./unreadable-terminal-role.js";
9
+ import { findUnexecutedRegions } from "./unexecuted-region.js";
10
+ import { deriveBypass } from "./bypass.js";
11
+ import { applyConverterScale } from "./converter-scale.js";
12
+ import { couple } from "./couple.js";
13
+ import { emit } from "./emit.js";
14
+ import { StageRefusal } from "./errors.js";
15
+ import { findInertControls } from "./inert-controls.js";
16
+ import { link } from "./link.js";
17
+ import { lower } from "./lower.js";
18
+ import { readNetlist } from "./netlist.js";
19
+ import { partition } from "./partition.js";
20
+ import { emptyRegistry } from "./registry.js";
21
+ import { findDanglingActiveTerminals, synthesizeOpampImplicitBias, } from "./dangling-active-terminal.js";
22
+ import { findOverDrivenNodes } from "./over-driven-node.js";
23
+ import { findSupplyShorts } from "./supply-short.js";
24
+ import { findUnreachableOutput } from "./unreachable-output.js";
25
+ import { findPowerDomainControls } from "./power-domain-control.js";
26
+ import { findUnimplementedControlRoles } from "./unimplemented-control-role.js";
27
+ import { findUnverifiedPinoutBindings } from "./unverified-pinout.js";
28
+ import { findGenericTubeFits } from "./generic-tube-fit.js";
29
+ import { findGroundedClockSupplies } from "./grounded-clock-supply.js";
30
+ import { findNonExecutableClockDrivers } from "./non-executable-clock-drivers.js";
31
+ import { GROUND } from "./types.js";
32
+ import { findUnboundedOpamps } from "./unbounded-operating-point.js";
33
+ /**
34
+ * Compile, or explain the refusal. This never throws for a document it cannot use.
35
+ *
36
+ * A stage raises a `StageRefusal` when the *source* does not support a program, and
37
+ * that becomes a result rather than an exception: one malformed packet must not take
38
+ * down a batch, and "could not read the document" is an answer a caller can act on.
39
+ *
40
+ * Anything else propagates. A compiler bug reported as an unsupported pedal would be
41
+ * a wrong answer about someone's circuit, so the catch is deliberately narrow.
42
+ */
43
+ export function compile(source, options = { registry: emptyRegistry }) {
44
+ try {
45
+ return run(source, options);
46
+ }
47
+ catch (error) {
48
+ if (!(error instanceof StageRefusal)) {
49
+ throw error;
50
+ }
51
+ return {
52
+ status: "unsupported",
53
+ reasons: [
54
+ { stage: error.stage, device: error.device, reason: error.message },
55
+ ],
56
+ };
57
+ }
58
+ }
59
+ function run(source, options) {
60
+ const netlist = readNetlist(source, {
61
+ inputJack: options.inputJack,
62
+ outputJack: options.outputJack,
63
+ });
64
+ const lawed = attachDeviceLaws(netlist, options.registry ?? emptyRegistry);
65
+ // Decision 1: an unmodellable device makes the whole pedal/amp unsupported, and
66
+ // the refusal names every component and reason rather than the first one.
67
+ const unsupported = lawed.resolutions.filter((resolution) => resolution.outcome === "unsupported");
68
+ if (unsupported.length > 0) {
69
+ return {
70
+ status: "unsupported",
71
+ reasons: unsupported.map((resolution) => ({
72
+ stage: "device-laws",
73
+ device: resolution.device,
74
+ reason: resolution.outcome === "unsupported" ? resolution.reason : "",
75
+ })),
76
+ };
77
+ }
78
+ const partitioning = partition(lawed);
79
+ const lowered = lower(partitioning, lawed);
80
+ // Stage 5.5: a macro's `coupled`/`parameter` ports reference other blocks, so wiring them
81
+ // happens once every region has one, not while `lower` is still producing them one at a time.
82
+ // `couple` also corrects the dependency graph's audio-out edge (clause 3, the region
83
+ // schedule) -- `link` must sort against that corrected graph, not stage 4's original one, or
84
+ // a coupled seam's downstream side would be free to run before the macro that feeds it.
85
+ const coupled = couple(lowered, partitioning, lawed);
86
+ const bypass = deriveBypass(netlist);
87
+ // Stage 5.75 (board-p3 row 4): the three decomposed models execute as
88
+ // catalog-parameterized compositions. Unconditional since board-p3 row 7 deleted the
89
+ // dispatched kernels: there is no second route to emit, and both runtimes refuse a
90
+ // `macro` block by name rather than execute one.
91
+ const composed = composeMacroBlocks(coupled.blocks);
92
+ const linked = link(composed, { ...partitioning, dependencies: coupled.dependencies }, netlist.controls, netlist.ports, netlist.portImpedanceOhms, netlist.portDeclaredFullScaleVolts, bypass);
93
+ // Stage 6.5: an op-amp the topology leaves genuinely undefined (no DC path back to its
94
+ // inverting input, or none from its non-inverting input to any reference) gets an implicit
95
+ // bias so its operating point is bounded rather than left to whatever `gmin` alone settles
96
+ // into -- see `dangling-active-terminal.ts`'s "implicit op-amp DC-bias synthesis" section.
97
+ // Every later Program-consuming stage below reads the bridged program, because that is the
98
+ // one the runtime will actually execute.
99
+ // Stage 6.75: a composed program between two converters takes their full-scale ratio as its
100
+ // level, or says why it cannot. Read from the catalog by exact part id and found by
101
+ // connectivity, so nothing about it is declared in the document.
102
+ const scaled = applyConverterScale(synthesizeOpampImplicitBias(linked), netlist, options.registry ?? emptyRegistry);
103
+ const program = scaled.program;
104
+ // A program with no blocks has nothing to execute, so calling it `ok` reports a
105
+ // compiled pedal that can only ever render silence. `boss-ps-2` reaches here: its
106
+ // jacks and ground are wired and its 223 electrically active parts declare no
107
+ // terminals, so every one is correctly dropped and nothing is left to solve.
108
+ if (program.blocks.length === 0) {
109
+ return {
110
+ status: "unsupported",
111
+ reasons: [
112
+ {
113
+ stage: "link",
114
+ device: null,
115
+ reason: "no component contributes to the signal path, so the program has nothing to execute",
116
+ },
117
+ ],
118
+ };
119
+ }
120
+ // Strict Admission: Floating wipers or completely disconnected devices are genuine structural
121
+ // defects in the source capture that must be refused. Controls in unscheduled blocks (e.g.
122
+ // unselected channels or scope exclusions documented in packet boundary) remain warnings.
123
+ const inertControls = findInertControls(netlist, program);
124
+ const structuralDefects = inertControls.filter((w) => w.isStructuralDefect);
125
+ if (structuralDefects.length > 0) {
126
+ return {
127
+ status: "unsupported",
128
+ reasons: structuralDefects.map((w) => ({
129
+ stage: "link",
130
+ device: (w.devices && w.devices.length > 0) ? w.devices[0] : null,
131
+ reason: w.detail,
132
+ })),
133
+ };
134
+ }
135
+ // Warnings are computed only for a program that exists and whose controls are connected.
136
+ return {
137
+ status: "ok",
138
+ program,
139
+ warnings: [
140
+ ...(netlist.warnings ?? []),
141
+ ...inertControls.filter((w) => !w.isStructuralDefect),
142
+ ...findUnboundedOpamps(netlist),
143
+ ...findSupplyShorts(netlist),
144
+ ...findOverDrivenNodes(program),
145
+ ...findDanglingActiveTerminals(program),
146
+ ...findGroundedClockSupplies(program),
147
+ ...findNonExecutableClockDrivers(netlist, options.registry ?? emptyRegistry),
148
+ ...findGenericTubeFits(netlist, options.registry ?? emptyRegistry),
149
+ ...findUnverifiedPinoutBindings(netlist, options.registry ?? emptyRegistry),
150
+ ...findPowerDomainControls(netlist, program.controls ?? [], [netlist.ports.input, netlist.ports.output].filter((node) => typeof node === "number")),
151
+ ...findUnimplementedControlRoles(program.controls ?? []),
152
+ ...findElectricallyIsolatedIcs(netlist),
153
+ ...findIcsNotExecuted(lawed, netlist, options.registry ?? emptyRegistry),
154
+ ...findUnreadableTerminalRoles(lawed),
155
+ ...findMultiDeviceShells(lawed),
156
+ ...findUnimplementedDeviceLaws(lawed),
157
+ ...findUnreachableOutput(program, netlist),
158
+ ...findUnexecutedRegions(program),
159
+ ...findDeclaredDelays(program),
160
+ ...findUnmodelledModulation(program),
161
+ ...findRailsWithoutVoltage(netlist),
162
+ ...findFetLawDefaults(netlist),
163
+ ...findBjtLawDefaults(netlist),
164
+ ...findOpampLawDefaults(lawed),
165
+ ...scaled.warnings,
166
+ ],
167
+ };
168
+ }
169
+ /**
170
+ * Delay macros whose modulation input the part declares and the document wires, but which
171
+ * admission refused -- so the delay is a constant and whatever sweeps it in the real pedal does
172
+ * not reach it.
173
+ *
174
+ * This is the difference between a flanger and a fixed comb filter, and the two compiled to
175
+ * indistinguishable programs. The refusal itself is correct -- gate 1b measured that an
176
+ * LFO-swept clock is a signal rather than a control-rate parameter -- but a correct refusal that
177
+ * nobody is told about renders a pedal doing none of what it is named for.
178
+ */
179
+ function findUnmodelledModulation(program) {
180
+ return program.blocks.flatMap((block) => (block.kind === "macro" || block.kind === "composed") &&
181
+ typeof block.modulationRefusal === "string"
182
+ ? [
183
+ {
184
+ code: "modulation-not-modelled",
185
+ device: null,
186
+ detail: `${block.id} declares a modulation input this document wires, but ` +
187
+ `${block.modulationRefusal}. ` +
188
+ // The consequence is not the same in both cases, and saying the wrong
189
+ // one discredits the warning: a delay that derives from its own clock
190
+ // network still works, it just cannot be swept.
191
+ (block.clockControl != null || block.delayProvenance === "derived"
192
+ ? "Its delay still follows its own clock network, but nothing in the " +
193
+ "circuit can sweep it."
194
+ : "Its delay is therefore a constant, and whatever sweeps it in the " +
195
+ "real pedal does not reach it."),
196
+ },
197
+ ]
198
+ : []);
199
+ }
200
+ /**
201
+ * Delay macros whose delay time was typed into the source instead of derived from the clock
202
+ * network they are wired to.
203
+ *
204
+ * A derived delay is a consequence of the packet's own R and C: change either and it moves, and
205
+ * a wrong value shows up as a wrong delay. A declared `DelayMs` renders exactly what it says and
206
+ * is therefore unfalsifiable by any render -- which is precisely why it must not pass silently.
207
+ * The two were indistinguishable in the program until now, so a reader could not tell a
208
+ * simulated delay from a reported one.
209
+ */
210
+ function findDeclaredDelays(program) {
211
+ return program.blocks.flatMap((block) => (block.kind === "macro" || block.kind === "composed") &&
212
+ block.delayProvenance === "declared"
213
+ ? [
214
+ {
215
+ code: "declared-delay-not-derived",
216
+ device: null,
217
+ detail: `${block.id} runs ${block.modelId} at ` +
218
+ `${((block.parameters.delaySeconds ?? 0) * 1000).toFixed(1)} ms taken from the ` +
219
+ `source's declared DelayMs, not derived from a clock network: ` +
220
+ `${block.delayDeclaredReason ?? "no reason recorded"}. That number renders ` +
221
+ `whatever it says, so it is not evidence about this circuit's delay time.`,
222
+ },
223
+ ]
224
+ : []);
225
+ }
226
+ /** Voltage-less rails that something is connected to. See `RailWithoutVoltageWarning`. */
227
+ function findRailsWithoutVoltage(netlist) {
228
+ const loaded = new Map();
229
+ for (const device of netlist.devices) {
230
+ for (const node of new Set(device.nodes))
231
+ loaded.set(node, (loaded.get(node) ?? 0) + 1);
232
+ }
233
+ return netlist.devices.flatMap((device) => {
234
+ if (device.kind !== "rail")
235
+ return [];
236
+ const volts = device.parameters.volts;
237
+ if (volts !== undefined && Number.isFinite(volts))
238
+ return [];
239
+ const attached = [...new Set(device.nodes)].filter((node) => node !== GROUND && (loaded.get(node) ?? 0) > 1);
240
+ if (attached.length === 0)
241
+ return [];
242
+ return [
243
+ {
244
+ code: "rail-without-voltage",
245
+ device: device.id,
246
+ detail: `${device.id} declares no voltage, so it asserts nothing and lowers open; ` +
247
+ `${attached.length === 1 ? `node ${attached[0]} has` : `nodes ${attached.join(", ")} have`} ` +
248
+ "other devices attached, and they see only gmin to ground. A supply the sheet draws " +
249
+ "there solves at 0 V.",
250
+ },
251
+ ];
252
+ });
253
+ }
254
+ /** JFETs stamped with the fet law's own defaults. See `FetLawDefaultWarning`. */
255
+ function findFetLawDefaults(netlist) {
256
+ const defaulted = netlist.devices.filter((device) => device.kind === "jfet" &&
257
+ (device.parameters.thresholdVolts === undefined ||
258
+ device.parameters.transconductance === undefined));
259
+ if (defaulted.length === 0)
260
+ return [];
261
+ const listed = defaulted.map((device) => {
262
+ const missing = [
263
+ device.parameters.thresholdVolts === undefined ? "Vt0" : null,
264
+ device.parameters.transconductance === undefined ? "Beta" : null,
265
+ ].filter((name) => name !== null);
266
+ const part = device.identity.partNumber;
267
+ return `${device.id}${part === null ? "" : ` (${part})`} without ${missing.join("/")}`;
268
+ });
269
+ return [
270
+ {
271
+ code: "fet-law-default-parameters",
272
+ device: null,
273
+ devices: defaulted.map((device) => device.id),
274
+ detail: `${defaulted.length} JFET(s) run on the fet law's own defaults ` +
275
+ `(Vt0 ${JFET_DEFAULT_THRESHOLD_VOLTS} V, Beta ${JFET_DEFAULT_TRANSCONDUCTANCE * 1e3} mS), ` +
276
+ `which are not any part's values: ${listed.join("; ")}. Harmless for a switch that is ` +
277
+ "fully on or off; decisive for one biased near its knee.",
278
+ },
279
+ ];
280
+ }
281
+ /** BJTs stamped with the bjt law's own defaults. See `BjtLawDefaultWarning`. */
282
+ function findBjtLawDefaults(netlist) {
283
+ const defaulted = netlist.devices.filter((device) => device.kind === "bjt" &&
284
+ (device.parameters.saturationCurrent === undefined ||
285
+ device.parameters.beta === undefined));
286
+ if (defaulted.length === 0)
287
+ return [];
288
+ const listed = defaulted.map((device) => {
289
+ const missing = [
290
+ device.parameters.saturationCurrent === undefined ? "IS" : null,
291
+ device.parameters.beta === undefined ? "BF" : null,
292
+ ].filter((name) => name !== null);
293
+ const part = device.identity.partNumber;
294
+ return `${device.id}${part === null ? "" : ` (${part})`} without ${missing.join("/")}`;
295
+ });
296
+ return [
297
+ {
298
+ code: "bjt-law-default-parameters",
299
+ device: null,
300
+ devices: defaulted.map((device) => device.id),
301
+ detail: `${defaulted.length} BJT(s) run on the bjt law's own defaults ` +
302
+ `(IS ${SILICON_SATURATION_CURRENT} A, BF ${SILICON_FORWARD_BETA}), ` +
303
+ `which are not any part's values: ${listed.join("; ")}. Harmless for a saturated ` +
304
+ "switch; decisive for a biased stage.",
305
+ },
306
+ ];
307
+ }
308
+ /** Op-amps that state no output-swing drop. See `OpampLawDefaultWarning`. */
309
+ function findOpampLawDefaults(lawed) {
310
+ const byId = new Map(lawed.netlist.devices.map((device) => [device.id, device]));
311
+ const stated = new Map();
312
+ for (const resolution of lawed.resolutions) {
313
+ if (resolution.outcome !== "law" || resolution.law.kind !== "ideal-opamp")
314
+ continue;
315
+ // A section of a package is lowered as `<device>#<index>`; the warning names the device.
316
+ const id = resolution.device.replace(/#\d+$/, "");
317
+ stated.set(id, (stated.get(id) ?? true) && resolution.law.outputSwingDropVolts !== undefined);
318
+ }
319
+ const defaulted = [...stated].flatMap(([id, has]) => (has ? [] : [id]));
320
+ if (defaulted.length === 0)
321
+ return [];
322
+ const listed = defaulted.map((id) => {
323
+ const part = byId.get(id)?.identity.partNumber ?? null;
324
+ return `${id}${part === null ? "" : ` (${part})`}`;
325
+ });
326
+ return [
327
+ {
328
+ code: "opamp-law-default-parameters",
329
+ device: null,
330
+ devices: defaulted,
331
+ detail: `${defaulted.length} op-amp(s) swing the full supply because the part states no ` +
332
+ `output-swing drop: ${listed.join("; ")}. Harmless for a stage that never nears ` +
333
+ "the rails; decisive for a comparator, an LFO or a clipper.",
334
+ },
335
+ ];
336
+ }
337
+ export function compileToArtifact(source, options) {
338
+ const result = compile(source, options);
339
+ return {
340
+ result,
341
+ artifact: result.status === "ok" ? emit(result.program) : null,
342
+ };
343
+ }
344
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type PartRegistry } from "./registry";
2
+ import type { ConverterScaleNotModelledWarning, Netlist, Program } from "./types";
3
+ /**
4
+ * Scale every composed block that sits between two cited converters, and name every one that
5
+ * touches a converter but cannot be scaled.
6
+ *
7
+ * A block no converter touches is left alone and raises nothing: a bucket-brigade composition
8
+ * is analog end to end and has no full scale to be wrong about.
9
+ */
10
+ export declare function applyConverterScale(program: Program, netlist: Netlist, registry: PartRegistry): {
11
+ readonly program: Program;
12
+ readonly warnings: readonly ConverterScaleNotModelledWarning[];
13
+ };
14
+ //# sourceMappingURL=converter-scale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter-scale.d.ts","sourceRoot":"","sources":["../src/converter-scale.ts"],"names":[],"mappings":"AAkBA,OAAO,EAGN,KAAK,YAAY,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACX,gCAAgC,EAEhC,OAAO,EAEP,OAAO,EACP,MAAM,SAAS,CAAC;AA4BjB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,YAAY,GACpB;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,gCAAgC,EAAE,CAAA;CAAE,CAoG/F"}
@@ -0,0 +1,133 @@
1
+ // Converter full scale: the gain a program between an ADC and a DAC actually has.
2
+ //
3
+ // A composed program runs in volts: its input is the solved voltage at its input node and its
4
+ // output drives its output node in volts. That is exact only when the chip's converters have
5
+ // equal full scales. In the pedal the ADC maps its full scale to digital 1.0 and the DAC maps
6
+ // digital 1.0 back to its own, so the program's volts-to-volts gain is `dac / adc` times
7
+ // whatever the firmware does. The firmware is the program; the ratio is a fact about two parts.
8
+ //
9
+ // **Connectivity, not names.** A converter is the one on the block's input or output node, found
10
+ // by the node the circuit shares with it, and it is a converter because its exact part id has a
11
+ // `converter` entry in the catalog. Nothing is declared in the document.
12
+ //
13
+ // **Unity and a warning, never a guess, when a side is unknown.** The ratio is applied only when
14
+ // both sides are wired and both full scales are cited. Otherwise the program stays unity in volts,
15
+ // which is a level assumption the reader must be told about: `boss-dd-5` sits ~7.5 dB below
16
+ // its own deck for exactly this reason.
17
+ import { canonicalPartId } from "./part-number.js";
18
+ import { foldPartId, } from "./registry.js";
19
+ /** The catalog's converter declaration for a device's exact part id, or null. */
20
+ function converterOf(device, registry) {
21
+ const partNumber = device.identity.partNumber;
22
+ if (partNumber === null)
23
+ return null;
24
+ const canonical = foldPartId(canonicalPartId(partNumber));
25
+ for (const entry of registry.entries) {
26
+ if (entry.converter !== undefined &&
27
+ entry.partIds.some((id) => foldPartId(canonicalPartId(id)) === canonical)) {
28
+ return entry.converter;
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ function describe(converter) {
34
+ const fullScale = converter.declaration.fullScaleVoltsPeakToPeak;
35
+ return (`${converter.device.id} ${converter.device.identity.partNumber} ` +
36
+ (fullScale === null ? "(full scale not cited)" : `(${fullScale} Vp-p full scale)`));
37
+ }
38
+ /**
39
+ * Scale every composed block that sits between two cited converters, and name every one that
40
+ * touches a converter but cannot be scaled.
41
+ *
42
+ * A block no converter touches is left alone and raises nothing: a bucket-brigade composition
43
+ * is analog end to end and has no full scale to be wrong about.
44
+ */
45
+ export function applyConverterScale(program, netlist, registry) {
46
+ const converters = netlist.devices.flatMap((device) => {
47
+ const declaration = converterOf(device, registry);
48
+ return declaration === null ? [] : [{ device, declaration }];
49
+ });
50
+ if (converters.length === 0)
51
+ return { program, warnings: [] };
52
+ // Ports and stamps address MNA rows, not source nodes, so both are translated through the
53
+ // owning block's `nodeIds` before they can be compared with a converter's terminals.
54
+ const sourceNode = new Map();
55
+ const outputNodeOf = new Map();
56
+ for (const block of program.blocks) {
57
+ if (block.kind !== "mna")
58
+ continue;
59
+ sourceNode.set(block.id, block.nodeIds);
60
+ for (const stamp of block.stamps) {
61
+ const node = block.nodeIds[stamp.kind === "macro-audio-source" ? stamp.node : -1];
62
+ if (stamp.kind === "macro-audio-source" && node !== undefined) {
63
+ outputNodeOf.set(stamp.macroId, node);
64
+ }
65
+ }
66
+ }
67
+ const on = (node, direction) => node === undefined
68
+ ? []
69
+ : converters.filter((converter) => converter.declaration.direction === direction &&
70
+ converter.device.nodes.includes(node));
71
+ const warnings = [];
72
+ const blocks = program.blocks.map((block) => {
73
+ if (block.kind !== "composed")
74
+ return block;
75
+ const adcs = on(block.audioIn === null
76
+ ? undefined
77
+ : sourceNode.get(block.audioIn.block)?.[block.audioIn.node], "adc");
78
+ const dacs = on(outputNodeOf.get(block.id), "dac");
79
+ // A reprogrammable chip's program sits behind converters by construction, so in a document
80
+ // that has them its volts-in, volts-out assumption is named even where neither is wired to it.
81
+ if (adcs.length === 0 && dacs.length === 0 && block.modelSource !== "declared")
82
+ return block;
83
+ const adc = adcs.length === 1 ? adcs[0] : undefined;
84
+ const dac = dacs.length === 1 ? dacs[0] : undefined;
85
+ const adcScale = adc?.declaration.fullScaleVoltsPeakToPeak ?? null;
86
+ const dacScale = dac?.declaration.fullScaleVoltsPeakToPeak ?? null;
87
+ if (adcScale !== null && dacScale !== null) {
88
+ const gain = dacScale / adcScale;
89
+ return {
90
+ ...block,
91
+ positions: block.positions.map((position) => ({
92
+ ...position,
93
+ ops: [
94
+ ...position.ops,
95
+ {
96
+ op: "mix",
97
+ terms: [{ source: { kind: "temp", index: position.out }, gain }],
98
+ out: position.ops.length,
99
+ },
100
+ ],
101
+ out: position.ops.length,
102
+ })),
103
+ };
104
+ }
105
+ const side = (found, direction, node) => {
106
+ if (found.length === 1)
107
+ return `its ${node} is ${describe(found[0])}`;
108
+ if (found.length > 1) {
109
+ return `its ${node} touches ${found.length} ${direction.toUpperCase()}s (${found.map((c) => c.device.id).join(", ")}), so which one converts is not decidable`;
110
+ }
111
+ const elsewhere = converters.filter((c) => c.declaration.direction === direction);
112
+ return (`its ${node} reaches no ${direction.toUpperCase()}` +
113
+ (elsewhere.length > 0
114
+ ? `; ${elsewhere.map(describe).join(" and ")} ${elsewhere.length === 1 ? "is" : "are"} in the document, not wired to it`
115
+ : ""));
116
+ };
117
+ warnings.push({
118
+ code: "converter-scale-not-modelled",
119
+ device: null,
120
+ detail: `${block.id} runs in volts, unity from input to output, but ` +
121
+ `${side(adcs, "adc", "input")}, and ${side(dacs, "dac", "output")}. ` +
122
+ "The pedal's gain there is the DAC's full scale over the ADC's, so the level of " +
123
+ "everything this program outputs is unmodelled by that ratio." +
124
+ [...adcs, ...dacs, ...converters]
125
+ .filter((c, i, all) => all.indexOf(c) === i && c.declaration.fullScaleVoltsPeakToPeak === null)
126
+ .map((c) => ` ${c.device.identity.partNumber}: ${c.declaration.basis}`)
127
+ .join(""),
128
+ });
129
+ return block;
130
+ });
131
+ return { program: { ...program, blocks }, warnings };
132
+ }
133
+ //# sourceMappingURL=converter-scale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter-scale.js","sourceRoot":"","sources":["../src/converter-scale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Block, LawedNetlist, Partitioning, Stamp } from "./types";
2
+ export type Coupled = {
3
+ readonly blocks: readonly Block[];
4
+ /**
5
+ * `partitioning.dependencies`, corrected for every macro's audio-out edge -- see this
6
+ * file's header. This is what `link.ts` must sort against instead of the stage-4 graph,
7
+ * so a coupled seam's two sides land in the right order within a sample rather than the
8
+ * downstream side reading last sample's write-back by accident.
9
+ */
10
+ readonly dependencies: Partitioning["dependencies"];
11
+ };
12
+ export declare function couple(blocks: readonly Block[], partitioning: Partitioning, lawed: LawedNetlist): Coupled;
13
+ /**
14
+ * A new stamp, added to a block whose `linear`/`controlFree` are re-derived rather than
15
+ * assumed unchanged -- the same rule `lowerRegion` itself follows, so a stamp this stage adds
16
+ * cannot silently leave a block claiming a solver cost or a control independence its own
17
+ * stamps contradict.
18
+ *
19
+ * Exported for `dangling-active-terminal.ts`'s implicit op-amp bias synthesis, which adds a
20
+ * stamp to an already-linked block for the same reason this stage does: a block's derived
21
+ * fields must never describe a stamps array it does not have.
22
+ */
23
+ export declare function withStamp(block: Extract<Block, {
24
+ readonly kind: "mna";
25
+ }>, stamp: Stamp): Extract<Block, {
26
+ readonly kind: "mna";
27
+ }>;
28
+ //# sourceMappingURL=couple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"couple.d.ts","sourceRoot":"","sources":["../src/couple.ts"],"names":[],"mappings":"AAoHA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAU,YAAY,EAAU,KAAK,EAAE,MAAM,SAAS,CAAC;AAGxF,MAAM,MAAM,OAAO,GAAG;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;CACpD,CAAC;AA6BF,wBAAgB,MAAM,CACrB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,YAAY,GACjB,OAAO,CAgaT;AAcD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACxB,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,EAC/C,KAAK,EAAE,KAAK,GACV,OAAO,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAgC1C"}