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
18 changes: 9 additions & 9 deletions .trinity/seals/analog_AnalogMosPsp103.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
{
"spec": "specs/analog/mos_psp103_data.t27",
"spec_hash": "sha256:d233143ed2fa30d3bd0ff9546a2df008d568e4a4d9c7e0ef69ffedee2e92a5d6"
"spec_hash": "sha256:c4d59c5d87b03810373bfabb9024f4e1051184f3abab9a613e02ab0ae54848d9"
},
{
"spec": "specs/analog/mos_table.t27",
Expand All @@ -19,23 +19,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:3e5e50bdd2f832394e41c7fc942ee2b98b9553db46d1988c37721c08b6847fbb",
"gen_hash_rust": "sha256:a88d4dacaeaf61bda5deb575152a70c098241e617a292cb4d74df64e4214a3df",
"gen_hash_verilog": "sha256:7c29cf75695e6734bfd23fed2f64db8fe522506e0cb1b4bf3a94dd1f266bfaf3",
"gen_hash_zig": "sha256:5e470893c4dc6c81ad93b2af02b9d8a981eb3678a82ea86c2c1ba7ecaf81b4d5",
"gen_hash_c": "sha256:4446826415b9ebd392d8914d179402c3a3f9e47d763d2dcae36adae658718a51",
"gen_hash_rust": "sha256:fe23e4b6d1eba2e93cee13f82a7cd28affadd606ec8c1c3c7af01a40e39ffe18",
"gen_hash_verilog": "sha256:df799ffacdb77c27ef750561e79c146db3f7c2727ebfac2719205581a23ef8af",
"gen_hash_zig": "sha256:ee71152bbc3668896c1d5e42bed445515a696a74cdbb6e6e9159d5c0146b6ffc",
"module": "AnalogMosPsp103",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T19:25:21Z",
"sealed_at": "2026-10-20T03:08:06Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:3edf0828e56e30977b96c2e943d203aac805fd197800d37a57fb4fc61c7152d8",
"spec_hash": "sha256:e04b69e5c43188a3d46a4c0949cfc727f239721de73fb46e92c8a845bbbbc98e",
"spec_path": "specs/analog/mos_psp103.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 35,
"total": 35,
"passed": 40,
"total": 40,
"vacuous": 0
},
"toolchain": {
Expand Down
16 changes: 8 additions & 8 deletions .trinity/seals/analog_AnalogMosPsp103Data.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:a02b76251db8d7a64d65c32aad434a1847ac703ad6a71f16e4c1b970e0ea74b5",
"gen_hash_rust": "sha256:395c8a715aade1101e29f187926bfa9a985f6134ba5777dcf467ead14fc9732b",
"gen_hash_verilog": "sha256:dc49c09d8a3a13829b2cb9fba5450faa1f9d50da2611d75e06f2562e0d2cab13",
"gen_hash_zig": "sha256:8b372dfd2e05f42a44f713738843f75750e9a4c21d2f55c35dcac0db763bea8d",
"gen_hash_c": "sha256:b54bb70dcdaad8eac3180a3a51ee5d30d340b951edd734d4e817c161c1081f94",
"gen_hash_rust": "sha256:22cfdd782fe043555e0aa880bf922c2de502545f50aa5c92fb3e27fb0231fd2a",
"gen_hash_verilog": "sha256:f0e9948d7d18bf642dceae55962767fd570aea0a3c5dd0590d315566afc3509a",
"gen_hash_zig": "sha256:c9e11b43a265e022f096562ce39f6963dea17aa55489c83ccf2fc953ba1c186e",
"module": "AnalogMosPsp103Data",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T19:25:27Z",
"sealed_at": "2026-10-20T03:08:15Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:d233143ed2fa30d3bd0ff9546a2df008d568e4a4d9c7e0ef69ffedee2e92a5d6",
"spec_hash": "sha256:c4d59c5d87b03810373bfabb9024f4e1051184f3abab9a613e02ab0ae54848d9",
"spec_path": "specs/analog/mos_psp103_data.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 10,
"total": 10,
"passed": 11,
"total": 11,
"vacuous": 0
},
"toolchain": {
Expand Down
172 changes: 172 additions & 0 deletions specs/analog/decks/psp103_idpa_ff.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
IHP SG13G2 PSP103 log-domain current tables, corner mos_ff
* specs/analog/decks/psp103_idpa_ff.cir -- the log-domain current tables for specs/analog/mos_psp103_data.t27 (M3c-4, #11211, epic #10486; the format of M3c-2, #10881), the weak-inversion-accurate
* read of mos_table.t27. A netlist plus a .control block that prints the numbers.
* Model: IHP-Open-PDK commit 21133f219b1a6da10d803e345761e77415ceff40, ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib (PSP 103.6, revision 200310), section
* mos_ff; the model code is libs.tech/verilog-a/psp103/psp103.va of the same commit, compiled with OpenVAF-Reloaded v24.0.2mob to psp103.osdi (and psp103_nqs.osdi).
* Temperature 27 C (TNOM 27 C). Devices: sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1 and sg13_lv_pmos w=3.0u l=0.45u ng=1 m=1, exactly the devices of psp103_tab_ff.cir (the same
* netlist lines).
* Solver options: reltol 1e-6, vntol 1e-9, abstol 1e-14, as psp103_tab_ff.cir.
* Paths are NOT in this file. ngspice reads two environment variables: IHP_PDK, the IHP-Open-PDK checkout, and IHP_OSDI, the directory that holds the compiled
* psp103.osdi and psp103_nqs.osdi.
* Run: IHP_PDK=<checkout> IHP_OSDI=<osdi dir> ngspice -b psp103_idpa_ff.cir > psp103_idpa_ff.out (ngspice-47)
* THE CORNER (M3c-4, #11211). This deck is psp103_idpa_tt.cir with the .lib section mos_ff, the three numbers of the gate scale s(Vgs) below (each corner has its own: they were fitted
* to the corner's own 193 x 193 grid of ngspice currents, 7.8125 mV apart, so that the read is best between the nodes; the tests of mos_psp103.t27 judge the choice, this deck does not), and
* four more blocks at the end, r2_n, r2_p, mid_n and mid_p, the held-out currents of this corner that the tt corner's linear-table deck printed and the other corners' did not.
* THE TABLE. A node is the drain current Id, divided by the factor of weak inversion F = 1 - exp(-Vds / s(Vgs)), as log2 in 1/65536 of an octave, relative to
* IUNIT = 1 / (200 * 2^32) A = 1.164 pA (one table word of the linear tables, 298 pA, over 256). With the gate scale
* s(Vgs) = sqrt(0.030^2 + (0.65 * max(Vgs - 0.195, 0))^2) volts, rv = nint(4096 / s) (the word the reader multiplies Vds by), s_eff = 4096 / rv,
* the word of node (ix, iy), Vgs = ix * 15.625 mV (ix = 0 .. 96), Vds = iy * 31.25 mV (iy = 0 .. 48), is
* iy >= 1: nint(65536 * log2(max(Id / F(Vds; s_eff), IUNIT) / IUNIT))
* iy = 0: nint(65536 * log2(max(s_eff * gds0, IUNIT) / IUNIT)) gds0 = the output conductance ngspice reports at Vds = 0, the limit of Id / F there.
* Index ix * 49 + iy, ix outer, 4753 rows. The PMOS is read at Vsg = 1.5 V - Vgp and Vsd = 1.5 V - Vdp, source and bulk on the 1.5 V rail, the same words.
* What it prints. Between "BEGIN name" and "END name" every row "<index> TAB <value>" is one number, in sweep order (the first sweep source runs fastest).
* The values are pasted into the spec in that order, none changed.
* lam_n, lam_p the 4753 words of the NMOS and of the PMOS (as above); r_n, r_p rv at Vgs = ix * 15.625 mV, 97 rows each.
* cen_n, cen_p Id in pA (nint(Id * 1e12)) at 1000 held-out points that are CENTRES of cells of this grid, the places a chord of it is worst: point k = 1..1000 is
* Vgs (Vsg) = (floor(96 frac(k a1)) + 1/2) * 15.625 mV and Vds (Vsd) = (floor(48 frac(k a2)) + 1/2) * 31.25 mV, a1 = 0.7548776662466927, a2 = 0.5698402909980532.
* r2_n, r2_p (corners other than tt, M3c-4) Id in pA (nint(Id * 1e12)) at the 1000 R2 points Vgs (Vsg) = 1.5 frac(k a1), Vds (Vsd) = 1.5 frac(k a2), k = 1..1000, the held-out set
* of the linear tables of the tt corner (the first 200 are the points of psp103_tab_ff.cir): points that are neither nodes nor cell centres of this grid.
* mid_n, mid_p (corners other than tt, M3c-4) Id in pA at the 576 cell midpoints Vgs, Vds = (i + 1/2) * 62.5 mV of the linear grid, i = 0..23 (outer index the gate): nodes of this grid.
* nmos table device: drain VDN, gate VGN, source and bulk at 0 V
.lib $IHP_PDK/ihp-sg13g2/libs.tech/ngspice/models/cornerMOSlv.lib mos_ff
VDN dn 0 0
VGN gn 0 0
XMN dn gn 0 0 sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1
* pmos table device: source and bulk at the 1.5 V rail, drain VDP and gate VGP, both swept downward from 1.5 V
VSP sp 0 1.5
VDP dp 0 1.5
VGP gp 0 1.5
XMP dp gp sp sp sg13_lv_pmos w=3.0u l=0.45u ng=1 m=1
* held-out points: B sources compute the cell centre from the sweep variable k; the zero-volt sources VRDN, VRDP measure the drain current
VK k 0 1
BRGN rgn 0 V = (floor(96*(v(k)*0.7548776662466927-floor(v(k)*0.7548776662466927)))+0.5)*0.015625
BRDN rdn0 0 V = (floor(48*(v(k)*0.5698402909980532-floor(v(k)*0.5698402909980532)))+0.5)*0.03125
VRDN rdn0 rdn 0
XRN rdn rgn 0 0 sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1
BRGP rgp 0 V = 1.5-(floor(96*(v(k)*0.7548776662466927-floor(v(k)*0.7548776662466927)))+0.5)*0.015625
BRDP rdp0 0 V = 1.5-(floor(48*(v(k)*0.5698402909980532-floor(v(k)*0.5698402909980532)))+0.5)*0.03125
VRDP rdp rdp0 0
VRSP rsp 0 1.5
XRP rdp rgp rsp rsp sg13_lv_pmos w=3.0u l=0.45u ng=1 m=1
* R2 points: the held-out set of the linear tables, 1000 points per device; the same construction, in volts, with Vgs (Vsg) = 1.5 frac(k a1), Vds (Vsd) = 1.5 frac(k a2)
BQGN qgn 0 V = 1.5*(v(k)*0.7548776662466927-floor(v(k)*0.7548776662466927))
BQDN qdn0 0 V = 1.5*(v(k)*0.5698402909980532-floor(v(k)*0.5698402909980532))
VQDN qdn0 qdn 0
XQN qdn qgn 0 0 sg13_lv_nmos w=1.0u l=0.45u ng=1 m=1
BQGP qgp 0 V = 1.5-1.5*(v(k)*0.7548776662466927-floor(v(k)*0.7548776662466927))
BQDP qdp0 0 V = 1.5-1.5*(v(k)*0.5698402909980532-floor(v(k)*0.5698402909980532))
VQDP qdp qdp0 0
VQSP qsp 0 1.5
XQP qdp qgp qsp qsp sg13_lv_pmos w=3.0u l=0.45u ng=1 m=1
.temp 27
.options reltol=1e-6 vntol=1e-9 abstol=1e-14
.control
pre_osdi $IHP_OSDI/psp103.osdi
pre_osdi $IHP_OSDI/psp103_nqs.osdi
set numdgt=10
set noprintscale
save all @n.xmn.nsg13_lv_nmos[gds] @n.xmp.nsg13_lv_pmos[gds]
* the output conductance at Vds = 0 at the 97 gate nodes, and the gate scale and its word there (the same for both devices); plots dc1 (nmos) and dc2 (pmos)
alter VDN = 0
dc VGN 0 1.5 0.015625
let gzn = @n.xmn.nsg13_lv_nmos[gds]
let kk = vector(97)
let vgk = kk * 0.015625
let ovk = (vgk - 0.195 + abs(vgk - 0.195)) / 2
let sk = sqrt(0.03 * 0.03 + 0.65 * 0.65 * ovk * ovk)
let rk = nint(4096 / sk)
let sek = 4096 / rk
let an = gzn * sek
let zn = (an + 1.1641532182693481e-12 + abs(an - 1.1641532182693481e-12)) / 2
let l0n = nint(65536 / ln(2) * ln(zn / 1.1641532182693481e-12))
alter VDP = 1.5
dc VGP 1.5 0 -0.015625
let gzp = @n.xmp.nsg13_lv_pmos[gds]
let kk = vector(97)
let vgk = kk * 0.015625
let ovk = (vgk - 0.195 + abs(vgk - 0.195)) / 2
let sk = sqrt(0.03 * 0.03 + 0.65 * 0.65 * ovk * ovk)
let rk = nint(4096 / sk)
let sek = 4096 / rk
let ap = gzp * sek
let zp = (ap + 1.1641532182693481e-12 + abs(ap - 1.1641532182693481e-12)) / 2
let l0p = nint(65536 / ln(2) * ln(zp / 1.1641532182693481e-12))
echo BEGIN r_n
print rk
echo END r_n
echo BEGIN r_p
print rk
echo END r_p
* the NMOS grid
alter VDN = 0
dc VDN 0 1.5 0.03125 VGN 0 1.5 0.015625
let vgn = v(gn)
let vdn = v(dn)
let ovn = (vgn - 0.195 + abs(vgn - 0.195)) / 2
let sn = sqrt(0.03 * 0.03 + 0.65 * 0.65 * ovn * ovn)
let rn = nint(4096 / sn)
let fn = 1 - exp(0 - vdn * rn / 4096)
let idn = 0 - i(VDN)
let qn = (idn + abs(idn)) / 2
let jn = qn / (fn + 1e-30)
let mn = (jn + 1.1641532182693481e-12 + abs(jn - 1.1641532182693481e-12)) / 2
let lamn = nint(65536 / ln(2) * ln(mn / 1.1641532182693481e-12))
let k = 0
while k < 97
let lamn[k*49] = dc1.l0n[k]
let k = k + 1
end
echo BEGIN lam_n
print lamn
echo END lam_n
* the PMOS grid
alter VDP = 1.5
dc VDP 1.5 0 -0.03125 VGP 1.5 0 -0.015625
let vgp = 1.5 - v(gp)
let vdp = 1.5 - v(dp)
let ovp = (vgp - 0.195 + abs(vgp - 0.195)) / 2
let sp = sqrt(0.03 * 0.03 + 0.65 * 0.65 * ovp * ovp)
let rp = nint(4096 / sp)
let fp = 1 - exp(0 - vdp * rp / 4096)
let idp = i(VDP)
let qp = (idp + abs(idp)) / 2
let jp = qp / (fp + 1e-30)
let mp = (jp + 1.1641532182693481e-12 + abs(jp - 1.1641532182693481e-12)) / 2
let lamp = nint(65536 / ln(2) * ln(mp / 1.1641532182693481e-12))
let k = 0
while k < 97
let lamp[k*49] = dc2.l0p[k]
let k = k + 1
end
echo BEGIN lam_p
print lamp
echo END lam_p
echo BEGIN cen_n
dc VK 1 1000 1
let u = nint(i(VRDN) * 1e12)
print u
echo END cen_n
echo BEGIN cen_p
let u = nint(i(VRDP) * 1e12)
print u
echo END cen_p
echo BEGIN r2_n
let u = nint(i(VQDN) * 1e12)
print u
echo END r2_n
echo BEGIN r2_p
let u = nint(i(VQDP) * 1e12)
print u
echo END r2_p
echo BEGIN mid_n
dc VDN 0.03125 1.46875 0.0625 VGN 0.03125 1.46875 0.0625
let u = nint(-i(VDN) * 1e12)
print u
echo END mid_n
echo BEGIN mid_p
dc VDP 1.46875 0.03125 -0.0625 VGP 1.46875 0.03125 -0.0625
let u = nint(i(VDP) * 1e12)
print u
echo END mid_p
.endc
.end
Loading
Loading