Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .trinity/seals/analog_AnalogVacaskCompare.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"built_by": "t27c-bootstrap@0.5.2+42a4860c4",
"closure": [
{
"spec": "specs/analog/linear.t27",
"spec_hash": "sha256:3ddef7be183aba583ed285334ee389b48a65b41335e98914514235db7c4e5d62"
},
{
"spec": "specs/analog/mos_psp103_50c_data.t27",
"spec_hash": "sha256:9e68629797a29516836ca3e0b5e4881b0e751d847c58fd52b63e8f69746dbbe1"
},
{
"spec": "specs/analog/sar_cdac.t27",
"spec_hash": "sha256:a7c45039214a8b2e92333a88befc95af33ff482ce08af3be97e2c5b8be3eacd3"
},
{
"spec": "specs/analog/sar_comparator.t27",
"spec_hash": "sha256:db347ab1845e5323822b3ab77ba3d43b9923d105cc717e7224ad54c7328d23a7"
},
{
"spec": "specs/analog/sar_comparator_psp.t27",
"spec_hash": "sha256:03fa3e42e50de0a06436cc2e57636a6b59c1be04243a9b836920832e8dae0c40"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:f71c5a48c0b3aae59f3a17afe4de367bd8d540628235fb83434f2f4e9d3723e3",
"gen_hash_rust": "sha256:7d8d89854812415f71cb89a0dd31f6d3d81fffbd493c89ccff3466ac63246ed4",
"gen_hash_verilog": "sha256:02dfb81526d778825abe51290335ceae060dc7c6013d3e55df679acc86ed0db7",
"gen_hash_zig": "sha256:2ea822986e1cbb42629e90cc8022c66053b75cb62293cfd766bbea8aca2c03d8",
"module": "AnalogVacaskCompare",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T19:09:26Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:05213c3d5e45f33b213cae102a6c579d40efa267a2ff1c98ed8dc0e5944b64a4",
"spec_path": "specs/analog/vacask_compare.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 7,
"total": 7,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
49 changes: 49 additions & 0 deletions specs/analog/decks/vacask_cdac_half.sim
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
SAR ADC split capacitive DAC, one half, ideal capacitors, 16 codes: the VACASK twin of sar_cdac_half.cir
// specs/analog/decks/vacask_cdac_half.sim -- second-simulator data for specs/analog/vacask_compare.t27 (analog M4a, #10911, epic #10486). A netlist in VACASK's
// own syntax plus a control block; the numbers are read from its raw file (see "What is read").
// Topology of Diff_cap_DAC as in sar_cdac_half.cir (the ngspice deck of this repository, which this deck repeats): the LSB array, 31 units from node l to the
// plates p1..p5 (1, 2, 4, 8, 16 units), the bridge, 1 unit between l and m (m is Vout, the top plate), and the MSB array, 31 units from m to the plates p6..p10
// (1, 2, 4, 8, 16 units). Unit = 100 fF, ideal. VACASK's capacitor device has one value per instance: a plate of u units is ONE capacitor of u * 100 fF (the
// ngspice deck has u of 100 fF; parallel capacitors are one capacitor of the sum). No golden-deck text is used: the topology is the repository's own deck's.
// The tracking switch is not modelled: l and m start at the sampled 0.75 V (icmode "uic" and the ic list; every capacitor starts uncharged because every plate
// rests at VCM = 0.75 V: the ic list names the ten plate nodes too, at 0.75 V, because in uic mode a node that is not listed starts at 0 V, also a node a
// source drives, so a capacitor between l and an unlisted plate would start charged to 0.75 V and shift every result by 0.75 V; the ngspice deck's IC=0 on
// each capacitor says the same thing). The plates rest at 0.75 V for 10 ns; then, over 1 ps, plate j goes to VDD = 1.5 V when bit j-1 of the circuit variable code is 1 and to
// 0 V when it is 0 (the ngspice deck's 0.75 + 0.75 (2 bit - 1)): the code is `code`. The network is algebraic (capacitors only), so the settled voltage does not
// depend on the time grid. Sweep "cs" (analysis cdac): the 16 codes of the spec's NG_SPOT list. Integration: trapezoidal (VACASK's default), the step capped at 1 ns,
// stop at 30 ns.
// What is read (outside this file, from cdac.raw): v(m) and v(l) at 29 ns, interpolated linearly between the two nearest points. Run: vacask -sp -qp
// vacask_cdac_half.sim (cwd holds nothing else; only the OSDI file capacitor.osdi of VACASK's own device library is loaded).

load "capacitor.osdi"
model v vsource
model cap capacitor

cl1 (l p1) cap c=100f
cl2 (l p2) cap c=200f
cl3 (l p3) cap c=400f
cl4 (l p4) cap c=800f
cl5 (l p5) cap c=1600f
cbr (l m) cap c=100f
cm6 (m p6) cap c=100f
cm7 (m p7) cap c=200f
cm8 (m p8) cap c=400f
cm9 (m p9) cap c=800f
cm10 (m p10) cap c=1600f
vp1 (p1 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/1), 2)-1)]
vp2 (p2 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/2), 2)-1)]
vp3 (p3 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/4), 2)-1)]
vp4 (p4 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/8), 2)-1)]
vp5 (p5 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/16), 2)-1)]
vp6 (p6 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/32), 2)-1)]
vp7 (p7 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/64), 2)-1)]
vp8 (p8 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/128), 2)-1)]
vp9 (p9 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/256), 2)-1)]
vp10 (p10 0) v type="pwl" wave=[0, 0.75, 10n, 0.75, 10.001n, 0.75+0.75*(2*fmod(floor(code*1.0/512), 2)-1)]

control
var code=0
save v(m) v(l)
sweep cs variable="code" values=[0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 511, 513, 341, 682, 1023] continuation=0
analysis cdac tran step=1n stop=30n maxstep=1n icmode="uic" ic={"l", 0.75, "m", 0.75, "p1", 0.75, "p2", 0.75, "p3", 0.75, "p4", 0.75, "p5", 0.75, "p6", 0.75, "p7", 0.75, "p8", 0.75, "p9", 0.75, "p10", 0.75}
endc
71 changes: 71 additions & 0 deletions specs/analog/decks/vacask_cmp_real.sim
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
SAR ADC dynamic comparator on PSP103, real device charges, 50 C: the VACASK twin of sar_cmp_psp_real.cir
// specs/analog/decks/vacask_cmp_real.sim -- second-simulator data for specs/analog/vacask_compare.t27 (analog, #10911, epic #10486).
// A netlist in VACASK's own syntax plus a control block; the numbers are read from its raw files (see "What is read").
// Circuits, side by side in one netlist, as in sar_cmp_psp_real.cir (the ngspice deck this one repeats, element for element):
// xb the subcircuit dynamic_comparator with 4 fF on dp and dn (bdp, bdn): the latch alone;
// xtop the subcircuit dynamic_comparator_top: the same latch, 4 fF on each output, an inverter on each, 4 fF on each inverter output
// and the NAND of the two inverter outputs, "Valid". The converter's comparator with the loads it has there.
// The subcircuits are the golden SAR deck's (uberWAVE wp2-parser/golden/top.spice, GPL-2.0). They are fetched at run time and NEVER vendored:
// the file vacask_golden.inc is made from the very subcircuit text that SAR_GOLDEN_SUBCKTS names for the ngspice decks, by one awk program that
// changes only the syntax and stops with an error line on any line it does not know:
// .subckt NAME p1 p2 .. -> subckt NAME (p1 p2 ..) .ends -> ends
// XMk d g s b MASTER params.. -> XMk (d g s b) MASTER params.. (MASTER = sg13_lv_nmos or sg13_lv_pmos; w, l, ng, m unchanged)
// xk n1 n2 .. SUBCKT -> xk (n1 n2 ..) SUBCKT
// Ck n1 n2 VALUE m=1 -> Ck (n1 n2) cap c=VALUE
// * comment lines are dropped. Only dynamic_comparator, dynamic_comparator_top, inverter and nand are taken.
// PSP103 (IHP-Open-PDK 21133f219b1a6da10d803e345761e77415ceff40, cornerMOSlv mos_tt) through OSDI, 50 C, with ALL its charge: the gate, overlap
// and junction capacitance of every device. Nothing is scaled; an ideal 1.6 ps clock stands for the delay-cell clkc; the inputs are held.
// THE MODELS are the PDK's own, converted to VACASK's syntax by VACASK's converter (python3 -m vacask.sg13g2tovc from VACASK's source tree,
// PDK_ROOT a COPY of the checkout because the converter writes into it): sg13g2_vacask_common.lib and cornerMOSlv.lib in libs.tech/vacask/models of
// the copy, and the instance wrappers sg13_lv_nmos and sg13_lv_pmos of the PDK's own sg13g2_moslv_mod.lib, with its formulas for as, ad, ps, pd.
// THE OSDI FILE is psp103.osdi, the one the ngspice decks load: the ngspice image's /opt/osdi directory is first on module_path_prefix in a
// .vacaskrc.toml next to the deck, so both simulators run the SAME compiled model file. (The converter compiles its own copy, which differs in bytes.)
// Run: PDK_ROOT=<converted copy> PDK=ihp-sg13g2 vacask -sp vacask_cmp_real.sim (cwd holds vacask_golden.inc and the .vacaskrc.toml)
// INPUTS: VDD 1.5 V, common mode 0.75 V. The swept variable sd is the signed half input in units of 2^-24 V: VDP = 0.75 + sd h, VDN = 0.75 - sd h,
// so VDP - VDN = 2 sd units. Write sd and the 16777216 as REALS: an integer sd divides to 0.
// sweep hs (analysis run1) sd = +-16777, +-4194, +-1049, +-262, +-84, +-8, +-1: the ngspice deck's first list.
// sweep ds (analysis scan) VDP - VDN = d units for d = -2700, -2600, -2571, -2570, -2540, -2400 (sd = d / 2): its second list.
// sweep fs (analysis fine) d = -2598, -2594, -2590, -2586, -2582, -2578, -2574, -2572, around VACASK's own flip point of xtop.
// The clock is 0 until 200 ps, then rises over 1.6 ps (its 50 % point at 200.8 ps).
// THE START: icmode "uic" and the spec's rest (ap = an = net2 = net3 = n_clkc = 1.5 V, dp = dn = 0, net1 = 0.4009999632835388 V) and the
// inverters' and NAND's outputs at their logic values; nodes not named start at 0 and settle in the 200 ps before the clock (the ngspice deck's
// .ic with uic). Both simulators leave this start the same way: vdd, vdp, vdn and clkc are not in the list either and start at 0 V, the state is
// not a solution, and the outputs jump from 0 to about 1.2 V in the first 0.05 ps, then fall back through 0.75 V at about 150 ps, before the clock.
// Their pre-clock waveforms agree within 0.4 mV from 1 ps on and within 0.15 mV from 30 ps on (specs/analog/vacask_compare.t27).
// INTEGRATION: trapezoidal (VACASK's default, tran_method), the step capped at 0.5 ps, reltol 1e-8, vntol 1e-11, abstol 1e-13 as in the ngspice deck.
// WHAT IS READ (outside this file, from run1.raw, scan.raw and fine.raw): tck, the clock through 0.75 V; tfirst, the first of dp and dn of xb
// through 0.75 V rising at or after tck (the early rise of the start is not a decision; the ngspice deck's meas does not see it either); tres,
// |dp - dn| of xb through 0.75 V; tvalid, Valid through 0.75 V rising after tck; xb's dp and dn and xtop's dp and dn at 3 ns. Crossings are linear
// interpolations between consecutive output points, as ngspice's meas does; times are given after tck.

include "sg13g2_vacask_common.lib"
include "cornerMOSlv.lib" section=mos_tt
include "vacask_golden.inc"

load "capacitor.osdi"
model v vsource
model cap capacitor

vdd (vdd 0) v dc=1.5
vdp (vdp 0) v dc=0.75+sd/16777216.0
vdn (vdn 0) v dc=0.75-sd/16777216.0
vclk (clkc 0) v type="pwl" wave=[0, 0, 200p, 0, 201.6p, 1.5]
xb (vdp vdn clkc vdd 0 bdp bdn) dynamic_comparator
cbdp (bdp 0) cap c=4f
cbdn (bdn 0) cap c=4f
xtop (vocp vocn valid vdp vdn clkc vdd 0) dynamic_comparator_top

control
var sd=0
options temp=50 reltol=1e-8 vntol=1e-11 abstol=1e-13
save v(clkc) v(bdp) v(bdn) v(valid) v('xtop:dp') v('xtop:dn')
var ic0={"xb:ap", 1.5, "xb:an", 1.5, "xb:net1", 0.4009999632835388, "xb:net2", 1.5, "xb:net3", 1.5, "bdp", 0, "bdn", 0, "xb:n_clkc", 1.5,
"xtop:x1:ap", 1.5, "xtop:x1:an", 1.5, "xtop:x1:net1", 0.4009999632835388, "xtop:x1:net2", 1.5, "xtop:x1:net3", 1.5, "xtop:dp", 0, "xtop:dn", 0,
"xtop:x1:n_clkc", 1.5, "vocp", 1.5, "vocn", 1.5, "valid", 0}
sweep hs variable="sd" values=[16777, -16777, 4194, -4194, 1049, -1049, 262, -262, 84, -84, 8, -8, 1, -1] continuation=0
analysis run1 tran step=0.1p stop=3n maxstep=0.5p icmode="uic" ic=ic0
sweep ds variable="sd" values=[-1350, -1300, -1285.5, -1285, -1270, -1200] continuation=0
analysis scan tran step=0.1p stop=3n maxstep=0.5p icmode="uic" ic=ic0
sweep fs variable="sd" values=[-1299.0, -1297.0, -1295.0, -1293.0, -1291.0, -1289.0, -1287.0, -1286.0] continuation=0
analysis fine tran step=0.1p stop=3n maxstep=0.5p icmode="uic" ic=ic0
endc
Loading
Loading