circuit-json-to-spice 0.0.25 → 0.0.27
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 +1 -0
- package/dist/index.js +106 -40
- package/lib/circuitJsonToSpice.ts +107 -18
- package/package.json +3 -3
- package/tests/examples/assets/switch.json +999 -0
- package/tests/examples/switch.test.tsx +29 -0
- package/tests/unit/voltage-probe.test.ts +75 -22
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import { circuitJsonToSpice } from "lib/circuitJsonToSpice"
|
|
3
|
+
import switchCircuit from "./assets/switch.json"
|
|
4
|
+
|
|
5
|
+
test(
|
|
6
|
+
"Switch circuit",
|
|
7
|
+
async () => {
|
|
8
|
+
const circuitJson = switchCircuit as any
|
|
9
|
+
|
|
10
|
+
const spiceNetlist = circuitJsonToSpice(circuitJson)
|
|
11
|
+
const spiceString = spiceNetlist.toSpiceString()
|
|
12
|
+
|
|
13
|
+
expect(spiceString).toMatchInlineSnapshot(`
|
|
14
|
+
"* Circuit JSON to SPICE Netlist
|
|
15
|
+
.MODEL SW_SW1 SW(Ron=0.1 Roff=1e9 Vt=2.5 Vh=0.1)
|
|
16
|
+
.MODEL NPN NPN
|
|
17
|
+
RR_base N1 VP_BASE 10K
|
|
18
|
+
VCTRL_SW1 NCTRL_SW1 0 PULSE(0 5 0 1n 1n 0.0005 0.001)
|
|
19
|
+
SSW1 VP_BASE N2 NCTRL_SW1 0 SW_SW1
|
|
20
|
+
QQ1 VP_COLLECTOR N2 0 NPN
|
|
21
|
+
RR_collector N1 VP_COLLECTOR 300
|
|
22
|
+
Vsimulation_voltage_source_0 N1 0 DC 5
|
|
23
|
+
.PRINT TRAN V(VP_BASE) V(VP_COLLECTOR)
|
|
24
|
+
.tran 0.00005 0.004 UIC
|
|
25
|
+
.END"
|
|
26
|
+
`)
|
|
27
|
+
},
|
|
28
|
+
{ timeout: 10000 },
|
|
29
|
+
)
|
|
@@ -68,14 +68,15 @@ const baseCircuit: AnyCircuitElement[] = [
|
|
|
68
68
|
},
|
|
69
69
|
]
|
|
70
70
|
|
|
71
|
-
test("voltage probe with
|
|
71
|
+
test("voltage probe with signal_input_source_port_id creates .PRINT statement", () => {
|
|
72
72
|
const circuitJson: AnyCircuitElement[] = [
|
|
73
73
|
...baseCircuit,
|
|
74
74
|
{
|
|
75
75
|
type: "simulation_voltage_probe",
|
|
76
|
-
|
|
76
|
+
simulation_voltage_probe_id: "probe1",
|
|
77
|
+
signal_input_source_port_id: "R1_p2",
|
|
77
78
|
name: "VOUT",
|
|
78
|
-
}
|
|
79
|
+
},
|
|
79
80
|
]
|
|
80
81
|
|
|
81
82
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -86,14 +87,15 @@ test("voltage probe with source_port_id creates .PRINT statement", () => {
|
|
|
86
87
|
expect(spiceString).toContain(`RR2 VOUT N2 1K`)
|
|
87
88
|
})
|
|
88
89
|
|
|
89
|
-
test("voltage probe with
|
|
90
|
+
test("voltage probe with signal_input_source_net_id creates .PRINT statement", () => {
|
|
90
91
|
const circuitJson: AnyCircuitElement[] = [
|
|
91
92
|
...baseCircuit,
|
|
92
93
|
{
|
|
93
94
|
type: "simulation_voltage_probe",
|
|
94
|
-
|
|
95
|
+
simulation_voltage_probe_id: "probe1",
|
|
96
|
+
signal_input_source_net_id: "net1",
|
|
95
97
|
name: "VOUT",
|
|
96
|
-
}
|
|
98
|
+
},
|
|
97
99
|
]
|
|
98
100
|
|
|
99
101
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -109,9 +111,10 @@ test("voltage probe without transient analysis does not create .PRINT statement"
|
|
|
109
111
|
...baseCircuit.filter((e) => e.type !== "simulation_experiment"),
|
|
110
112
|
{
|
|
111
113
|
type: "simulation_voltage_probe",
|
|
112
|
-
|
|
114
|
+
simulation_voltage_probe_id: "probe1",
|
|
115
|
+
signal_input_source_port_id: "R1_p2",
|
|
113
116
|
name: "VOUT",
|
|
114
|
-
}
|
|
117
|
+
},
|
|
115
118
|
]
|
|
116
119
|
|
|
117
120
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -138,14 +141,16 @@ test("voltage probe on ground node is ignored, but other probes are not", () =>
|
|
|
138
141
|
},
|
|
139
142
|
{
|
|
140
143
|
type: "simulation_voltage_probe",
|
|
141
|
-
|
|
144
|
+
simulation_voltage_probe_id: "probe_gnd",
|
|
145
|
+
signal_input_source_port_id: "R2_p2",
|
|
142
146
|
name: "probe_gnd",
|
|
143
|
-
}
|
|
147
|
+
},
|
|
144
148
|
{
|
|
145
149
|
type: "simulation_voltage_probe",
|
|
146
|
-
|
|
150
|
+
simulation_voltage_probe_id: "probe_vout",
|
|
151
|
+
signal_input_source_port_id: "R1_p2",
|
|
147
152
|
name: "VOUT",
|
|
148
|
-
}
|
|
153
|
+
},
|
|
149
154
|
]
|
|
150
155
|
|
|
151
156
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -164,14 +169,16 @@ test("multiple voltage probes create single .PRINT statement", () => {
|
|
|
164
169
|
...baseCircuit,
|
|
165
170
|
{
|
|
166
171
|
type: "simulation_voltage_probe",
|
|
167
|
-
|
|
172
|
+
simulation_voltage_probe_id: "probe_n1",
|
|
173
|
+
signal_input_source_port_id: "R1_p1",
|
|
168
174
|
name: "N1",
|
|
169
|
-
}
|
|
175
|
+
},
|
|
170
176
|
{
|
|
171
177
|
type: "simulation_voltage_probe",
|
|
172
|
-
|
|
178
|
+
simulation_voltage_probe_id: "probe_vout",
|
|
179
|
+
signal_input_source_port_id: "R1_p2",
|
|
173
180
|
name: "VOUT",
|
|
174
|
-
}
|
|
181
|
+
},
|
|
175
182
|
]
|
|
176
183
|
|
|
177
184
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -339,19 +346,22 @@ test("probes with N-style names don't conflict with auto-generated names", () =>
|
|
|
339
346
|
// Probes
|
|
340
347
|
{
|
|
341
348
|
type: "simulation_voltage_probe",
|
|
342
|
-
|
|
349
|
+
simulation_voltage_probe_id: "probe_n1",
|
|
350
|
+
signal_input_source_port_id: "R1_p1",
|
|
343
351
|
name: "N1",
|
|
344
|
-
}
|
|
352
|
+
},
|
|
345
353
|
{
|
|
346
354
|
type: "simulation_voltage_probe",
|
|
347
|
-
|
|
355
|
+
simulation_voltage_probe_id: "probe_n2",
|
|
356
|
+
signal_input_source_port_id: "R2_p1",
|
|
348
357
|
name: "N2",
|
|
349
|
-
}
|
|
358
|
+
},
|
|
350
359
|
{
|
|
351
360
|
type: "simulation_voltage_probe",
|
|
352
|
-
|
|
361
|
+
simulation_voltage_probe_id: "probe_n4",
|
|
362
|
+
signal_input_source_port_id: "R4_p1",
|
|
353
363
|
name: "N4",
|
|
354
|
-
}
|
|
364
|
+
},
|
|
355
365
|
]
|
|
356
366
|
|
|
357
367
|
const netlist = circuitJsonToSpice(circuitJson)
|
|
@@ -373,3 +383,46 @@ test("probes with N-style names don't conflict with auto-generated names", () =>
|
|
|
373
383
|
expect(spiceString).not.toContain("V(n3)")
|
|
374
384
|
expect(spiceString).not.toContain("V(n5)")
|
|
375
385
|
})
|
|
386
|
+
|
|
387
|
+
test("differential voltage probe creates .PRINT statement", () => {
|
|
388
|
+
const circuitJson: AnyCircuitElement[] = [
|
|
389
|
+
...baseCircuit,
|
|
390
|
+
{
|
|
391
|
+
type: "simulation_voltage_probe",
|
|
392
|
+
simulation_voltage_probe_id: "probe_diff",
|
|
393
|
+
name: "VR1",
|
|
394
|
+
signal_input_source_port_id: "R1_p1",
|
|
395
|
+
reference_input_source_port_id: "R1_p2",
|
|
396
|
+
},
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
const netlist = circuitJsonToSpice(circuitJson)
|
|
400
|
+
const spiceString = netlist.toSpiceString()
|
|
401
|
+
|
|
402
|
+
expect(spiceString).toContain("RR1 N2 N1 1K")
|
|
403
|
+
expect(spiceString).toContain("RR2 N1 N3 1K")
|
|
404
|
+
expect(spiceString).toContain(".PRINT TRAN V(N2,N1)")
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
test("differential voltage probe without a name creates .PRINT statement", () => {
|
|
408
|
+
const circuitJson: AnyCircuitElement[] = [
|
|
409
|
+
...baseCircuit,
|
|
410
|
+
{
|
|
411
|
+
type: "simulation_voltage_probe",
|
|
412
|
+
simulation_voltage_probe_id: "probe_diff",
|
|
413
|
+
signal_input_source_port_id: "R1_p1",
|
|
414
|
+
reference_input_source_port_id: "R1_p2",
|
|
415
|
+
},
|
|
416
|
+
]
|
|
417
|
+
|
|
418
|
+
const netlist = circuitJsonToSpice(circuitJson)
|
|
419
|
+
const spiceString = netlist.toSpiceString()
|
|
420
|
+
|
|
421
|
+
// No single-ended probe to name nodes, so nodes are auto-named.
|
|
422
|
+
// R1_p1 is floating -> N2
|
|
423
|
+
// R1_p2 is on net1 -> N1
|
|
424
|
+
// Probe is on R1_p1 and R1_p2, so V(N2,N1)
|
|
425
|
+
expect(spiceString).toContain("RR1 N2 N1 1K")
|
|
426
|
+
expect(spiceString).toContain("RR2 N1 N3 1K")
|
|
427
|
+
expect(spiceString).toContain(".PRINT TRAN V(N2,N1)")
|
|
428
|
+
})
|