From fe3e1a0bbbd04759b037db5a8d683a63533904ac Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 09:16:05 +0700 Subject: [PATCH] analog: mos_psp103.t27 -- IHP SG13G2 PSP103 tables for five corners from ngspice, run by M3a's solver, inverter against ngspice (Closes #10516) M3b of the analog emulation epic (#10486). Id(Vgs, Vds) of sg13_lv_nmos (W 1.0 um) and sg13_lv_pmos (W 3.0 um), L 0.45 um, from ngspice-47 with PSP 103.6 over OSDI, IHP-Open-PDK commit 21133f21, 27 C, for mos_tt, mos_ff, mos_ss, mos_fs and mos_sf: 25 x 25 nodes of 62.5 mV over 0 .. 1.5 V, which is M3a's reader exactly. The decks (specs/analog/decks/psp103_*.cir) print the numbers, rounded to table units by ngspice itself; mos_psp103_data.t27 holds them with order-sensitive pins; mos_psp103.t27 judges them. mos_table.t27 changes only so that the solver takes the NMOS table and the PMOS table as two arguments (g_resid, newton_iter, inv_step, board_step, run_fix, newton_iter_f, run_tabf); every M3a test passes the same table twice and its pinned run is unchanged bit for bit. A new test checks the mirror with two different tables. sar_comparator.t27 is untouched; its seal is renewed because the closure hash of mos_table.t27 moved. Measured against ngspice tt: Id at 576 midpoints and 1000 R2 points per device within 6.5e-7 A (NMOS) and 4.4e-7 A (PMOS), relative error 0.56 % / 0.41 % where Id >= 100 uA; the proposed 1 % with a floor of 1e-9 A is NOT met (0.55 .. 0.73, weak inversion). DC transfer of the inverter within 5.5 mV and 11 uV of trip point (every corner within 6.6 mV and 0.26 mV). Transient at 10 pF, 400 steps: arithmetic 4.8 units, table + model 1.28 mV and 0.14 / 0.17 % of the delay, discretization 14.4 mV and 0.5 / 0.7 %. The gap to ngspice at 500 fF is 3.1 / 3.6 % and scales with 1 / C: it is the device capacitance, which these current-only tables lack. Negative controls: ss tables used as tt, any other corner used as tt, and the tables in the wrong slots all fail the tt check. test-report: 14 + 4 + 11 pass, 0 vacuous. Left for the charge tables and the weak-inversion read: see #10777. Co-Authored-By: Claude Sonnet 5.5 --- .trinity/seals/analog_AnalogMosPsp103.json | 41 + .../seals/analog_AnalogMosPsp103Data.json | 33 + .trinity/seals/analog_AnalogMosTable.json | 20 +- .../seals/analog_AnalogSarComparator.json | 6 +- specs/analog/decks/psp103_inv_be.cir | 45 + specs/analog/decks/psp103_inv_be_500f.cir | 30 + specs/analog/decks/psp103_inv_fine.cir | 40 + specs/analog/decks/psp103_inv_fine_500f.cir | 25 + specs/analog/decks/psp103_tab_ff.cir | 86 ++ specs/analog/decks/psp103_tab_fs.cir | 86 ++ specs/analog/decks/psp103_tab_sf.cir | 86 ++ specs/analog/decks/psp103_tab_ss.cir | 86 ++ specs/analog/decks/psp103_tab_tt.cir | 96 ++ specs/analog/mos_psp103.t27 | 802 +++++++++++ specs/analog/mos_psp103_data.t27 | 1239 +++++++++++++++++ specs/analog/mos_table.t27 | 120 +- 16 files changed, 2778 insertions(+), 63 deletions(-) create mode 100644 .trinity/seals/analog_AnalogMosPsp103.json create mode 100644 .trinity/seals/analog_AnalogMosPsp103Data.json create mode 100644 specs/analog/decks/psp103_inv_be.cir create mode 100644 specs/analog/decks/psp103_inv_be_500f.cir create mode 100644 specs/analog/decks/psp103_inv_fine.cir create mode 100644 specs/analog/decks/psp103_inv_fine_500f.cir create mode 100644 specs/analog/decks/psp103_tab_ff.cir create mode 100644 specs/analog/decks/psp103_tab_fs.cir create mode 100644 specs/analog/decks/psp103_tab_sf.cir create mode 100644 specs/analog/decks/psp103_tab_ss.cir create mode 100644 specs/analog/decks/psp103_tab_tt.cir create mode 100644 specs/analog/mos_psp103.t27 create mode 100644 specs/analog/mos_psp103_data.t27 diff --git a/.trinity/seals/analog_AnalogMosPsp103.json b/.trinity/seals/analog_AnalogMosPsp103.json new file mode 100644 index 0000000000..147dcf14ba --- /dev/null +++ b/.trinity/seals/analog_AnalogMosPsp103.json @@ -0,0 +1,41 @@ +{ + "built_by": "t27c-bootstrap@0.5.2+ea35d9b72", + "closure": [ + { + "spec": "specs/analog/linear.t27", + "spec_hash": "sha256:3ddef7be183aba583ed285334ee389b48a65b41335e98914514235db7c4e5d62" + }, + { + "spec": "specs/analog/mos_psp103_data.t27", + "spec_hash": "sha256:d5f3244ff1936f2b96e95b06e022d6b42b489ac49e025ec99486d6d36e6c6580" + }, + { + "spec": "specs/analog/mos_table.t27", + "spec_hash": "sha256:9c0d1537ed5d8d60c4bdcb67d1e4c73ef80270e8cab224cb089c5b568fe11182" + } + ], + "config": "gen=c,rust,verilog,zig;tests=zig", + "gen_hash_c": "sha256:d7a49c643703a544723718186df74850018c4bf067fdb06ca9c860d775e069e8", + "gen_hash_rust": "sha256:32ee0d51345b936e45ff10956b90fdcafb6106bca46c2700de2bf43bf4407119", + "gen_hash_verilog": "sha256:0e3d19e85e67353129e8213c6135a5d1b518de4d7502c2d92512695b92de832e", + "gen_hash_zig": "sha256:445a5f05e794204ad3e4c198735c6fb1f4ab816e26fd36d3c408bba83168164f", + "module": "AnalogMosPsp103", + "ring": 12, + "seal_schema": 2, + "sealed_at": "2026-10-19T02:10:22Z", + "sealed_by": "t27c-bootstrap@0.5.2", + "spec_hash": "sha256:c5bd55a847953654fbef792dcfc61da7f6434b8023341df9ab4a53e5d082bbe0", + "spec_path": "specs/analog/mos_psp103.t27", + "tests": { + "failed": 0, + "failing": [], + "forced": false, + "passed": 11, + "total": 11, + "vacuous": 0 + }, + "toolchain": { + "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10", + "zig": "0.16.0" + } +} \ No newline at end of file diff --git a/.trinity/seals/analog_AnalogMosPsp103Data.json b/.trinity/seals/analog_AnalogMosPsp103Data.json new file mode 100644 index 0000000000..06125dea5e --- /dev/null +++ b/.trinity/seals/analog_AnalogMosPsp103Data.json @@ -0,0 +1,33 @@ +{ + "built_by": "t27c-bootstrap@0.5.2+ea35d9b72", + "closure": [ + { + "spec": "specs/analog/linear.t27", + "spec_hash": "sha256:3ddef7be183aba583ed285334ee389b48a65b41335e98914514235db7c4e5d62" + } + ], + "config": "gen=c,rust,verilog,zig;tests=zig", + "gen_hash_c": "sha256:d0135ebcf91901c442dc8a0c3e3a431f50a57cbc563d430a34e45e68392c9dfe", + "gen_hash_rust": "sha256:9dad368c2549f028ae0828213c7231a0e8ff613988ff42ce7d3aac6fcf9c4e52", + "gen_hash_verilog": "sha256:52f448d5fe93db1de3faa5fa13cb881486ec67a2ed17d1db475cd4d8d222ac82", + "gen_hash_zig": "sha256:1bdd4c520cb0864ffa3c4d2f7ce80418e7a0752e37610b81b4a000c528c413f9", + "module": "AnalogMosPsp103Data", + "ring": 12, + "seal_schema": 2, + "sealed_at": "2026-10-19T02:10:08Z", + "sealed_by": "t27c-bootstrap@0.5.2", + "spec_hash": "sha256:d5f3244ff1936f2b96e95b06e022d6b42b489ac49e025ec99486d6d36e6c6580", + "spec_path": "specs/analog/mos_psp103_data.t27", + "tests": { + "failed": 0, + "failing": [], + "forced": false, + "passed": 4, + "total": 4, + "vacuous": 0 + }, + "toolchain": { + "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10", + "zig": "0.16.0" + } +} \ No newline at end of file diff --git a/.trinity/seals/analog_AnalogMosTable.json b/.trinity/seals/analog_AnalogMosTable.json index 1456fca1db..5b1d2673a8 100644 --- a/.trinity/seals/analog_AnalogMosTable.json +++ b/.trinity/seals/analog_AnalogMosTable.json @@ -1,5 +1,5 @@ { - "built_by": "t27c-bootstrap@0.5.2+9b556b7c3", + "built_by": "t27c-bootstrap@0.5.2+ea35d9b72", "closure": [ { "spec": "specs/analog/linear.t27", @@ -7,27 +7,27 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:a4c0ec9ec8298af635a1cb7363b0b9644b99f7f0a1b80bd709fb8b14184a82fb", - "gen_hash_rust": "sha256:d0cbeb4b09d5da7c886eaeefaa2c395a2b699b643a1b25bb7372c62d857f0d87", - "gen_hash_verilog": "sha256:97d7e477baee00d846fc850c5888d0fbbf7cf9c072124ee4f55e4b76eeffc851", - "gen_hash_zig": "sha256:d9752320d155e8ace406d0008627ea48410160f8b25eea9eb424b9e10eb4d540", + "gen_hash_c": "sha256:3de4432818944eab74fae03952b4b4cffd104b00b9cda80dd73bb6ed6e819f0c", + "gen_hash_rust": "sha256:775c36a7f0370d1bc3dd0752f72f435e3fbc6e4972ad9b5c77efc35fb2784750", + "gen_hash_verilog": "sha256:0f3b42817e930cb80890ec45f5ecb5ecdf2a73bb764d029149ab8519dfd43dfc", + "gen_hash_zig": "sha256:05393568aa75f13169560fb6fd1118d46141ae46931458fc181ac12ba42ca196", "module": "AnalogMosTable", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T16:22:23Z", + "sealed_at": "2026-10-19T02:09:56Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:168cd93374cec92ece02ddab1be51f49308d9efd3288ac0427f912d4a7521782", + "spec_hash": "sha256:9c0d1537ed5d8d60c4bdcb67d1e4c73ef80270e8cab224cb089c5b568fe11182", "spec_path": "specs/analog/mos_table.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 13, - "total": 13, + "passed": 14, + "total": 14, "vacuous": 0 }, "toolchain": { - "test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d", + "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10", "zig": "0.16.0" } } \ No newline at end of file diff --git a/.trinity/seals/analog_AnalogSarComparator.json b/.trinity/seals/analog_AnalogSarComparator.json index 62ec02f8a1..31503ea410 100644 --- a/.trinity/seals/analog_AnalogSarComparator.json +++ b/.trinity/seals/analog_AnalogSarComparator.json @@ -1,5 +1,5 @@ { - "built_by": "t27c-bootstrap@0.5.2+9b556b7c3", + "built_by": "t27c-bootstrap@0.5.2+ea35d9b72", "closure": [ { "spec": "specs/analog/linear.t27", @@ -7,7 +7,7 @@ }, { "spec": "specs/analog/mos_table.t27", - "spec_hash": "sha256:168cd93374cec92ece02ddab1be51f49308d9efd3288ac0427f912d4a7521782" + "spec_hash": "sha256:9c0d1537ed5d8d60c4bdcb67d1e4c73ef80270e8cab224cb089c5b568fe11182" } ], "config": "gen=c,rust,verilog,zig;tests=zig", @@ -18,7 +18,7 @@ "module": "AnalogSarComparator", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-18T18:44:35Z", + "sealed_at": "2026-10-19T02:10:33Z", "sealed_by": "t27c-bootstrap@0.5.2", "spec_hash": "sha256:2df42ed0afe41add0b43762dfa05c8aa38ecbc022bea8f7bbd72f55917bcb806", "spec_path": "specs/analog/sar_comparator.t27", diff --git a/specs/analog/decks/psp103_inv_be.cir b/specs/analog/decks/psp103_inv_be.cir new file mode 100644 index 0000000000..486971427a --- /dev/null +++ b/specs/analog/decks/psp103_inv_be.cir @@ -0,0 +1,45 @@ +IHP SG13G2 inverter, 10 pF, backward Euler on a fixed 2 ns grid, corner mos_tt +* specs/analog/decks/psp103_inv_be.cir -- reference data for specs/analog/mos_psp103.t27 (M3b, #10516, epic #10486). A netlist plus a +* .control block that prints the numbers. +* Circuit: the inverter of the uberWAVE golden SAR deck (PMOS w=3.0u l=0.45u, NMOS w=1.0u l=0.45u, both sg13_lv, ng=1, m=1; Vdd 1.5 V), +* a lumped load of 10 pF on the output, no other element. Model, corner and temperature as in psp103_tab_tt.cir (IHP-Open-PDK commit +* 21133f219b1a6da10d803e345761e77415ceff40, mos_tt, 27 C). dt = 2 ns, so dt / C = 200 V/A, the scale of the tables in +* mos_psp103_data.t27. The device capacitances of PSP103 (gate-drain overlap and channel, drain junctions), which the table model does not +* have, are a few fF to some ten fF: about 0.2 % of 10 pF. psp103_inv_be_500f.cir is the same run at 500 fF, where they are 20 times +* larger in proportion. +* Paths are NOT in this file: ngspice reads IHP_PDK (the IHP-Open-PDK checkout) and IHP_OSDI (the directory with the compiled +* psp103.osdi and psp103_nqs.osdi) from the environment. +* Run: IHP_PDK= IHP_OSDI= ngspice -b psp103_inv_be.cir > psp103_inv_be.out (ngspice-47) +* The input is a B source of nint(time / dt), a staircase that declares no breakpoint: Vdd (the output rests near 0 V) up to the +* grid point 2 ns, 0 V from 3 ns (nint = 2) up to 403 ns, Vdd again from 403 ns (nint = 202). ngspice opens the run with steps of +* tstep / 100 that double up to tmax; tstep = 0.78125 dt makes the first step 15.625 ps and the end of that ramp exactly dt = 2 ns, so every +* internal point from then on is a multiple of 2 ns. Step k (k = 0..399) of the spec ends at (k + 2) dt and sees the input of nint = +* k + 2: 0 V for k < 200, Vdd from k = 200. Integration: gear with maxord 1 is backward Euler; trtol = 1e7 stops the truncation test +* from shrinking a step; reltol, vntol and abstol are tight enough for 1e-6 V and loose enough for Newton to converge at the input steps. +* tstop is two steps past the last row used: ngspice splits a last step that would pass tstop, and that would move the last row. +* What it prints: between "BEGIN tran_be" and "END tran_be", 401 rows " TAB