diff --git a/.trinity/seals/analog_AnalogMosPsp103.json b/.trinity/seals/analog_AnalogMosPsp103.json index 6f2237d0a8..c5a6a554b5 100644 --- a/.trinity/seals/analog_AnalogMosPsp103.json +++ b/.trinity/seals/analog_AnalogMosPsp103.json @@ -7,11 +7,11 @@ }, { "spec": "specs/analog/mos_psp103_data.t27", - "spec_hash": "sha256:c3d11a64e1fb2eddb7724acb75bcf7c242551a683a7d265a7cdd0d208c8d4d7b" + "spec_hash": "sha256:d233143ed2fa30d3bd0ff9546a2df008d568e4a4d9c7e0ef69ffedee2e92a5d6" }, { "spec": "specs/analog/mos_table.t27", - "spec_hash": "sha256:16d28f10fa8663926dddb4bcced981cdc4cd8f38a6b748e4b7688f2e56bbab6c" + "spec_hash": "sha256:54e248069ae620d18d260231e238b6bc42dc3c65792bd1673b162c2dc97b2edb" }, { "spec": "specs/analog/sar_comparator.t27", @@ -19,23 +19,23 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:69fd7266d0521ec8d562ada8c030435202a0d2224d474dc5c5a9fc491000df19", - "gen_hash_rust": "sha256:745bf1988b0cb964b0196d6ea22d468bf839236585dd64e82d92ea70630e9e7b", - "gen_hash_verilog": "sha256:83361d5ce963f001d2afb09ca4d82d7dbf14caa8beecb7c6f5e3f67ac7cb8bc5", - "gen_hash_zig": "sha256:1b08ed9b9f43e9567fbfd414e308b40c86570febae56f72d7161f3d3b15d8704", + "gen_hash_c": "sha256:3e5e50bdd2f832394e41c7fc942ee2b98b9553db46d1988c37721c08b6847fbb", + "gen_hash_rust": "sha256:a88d4dacaeaf61bda5deb575152a70c098241e617a292cb4d74df64e4214a3df", + "gen_hash_verilog": "sha256:7c29cf75695e6734bfd23fed2f64db8fe522506e0cb1b4bf3a94dd1f266bfaf3", + "gen_hash_zig": "sha256:5e470893c4dc6c81ad93b2af02b9d8a981eb3678a82ea86c2c1ba7ecaf81b4d5", "module": "AnalogMosPsp103", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-19T18:09:16Z", + "sealed_at": "2026-10-19T19:25:21Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:d178addc19558d26f503d3f5493e9815fa534209fb14169244b0b439c431b2a9", + "spec_hash": "sha256:3edf0828e56e30977b96c2e943d203aac805fd197800d37a57fb4fc61c7152d8", "spec_path": "specs/analog/mos_psp103.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 25, - "total": 25, + "passed": 35, + "total": 35, "vacuous": 0 }, "toolchain": { diff --git a/.trinity/seals/analog_AnalogMosPsp103Data.json b/.trinity/seals/analog_AnalogMosPsp103Data.json index c2e691e690..b5f926452d 100644 --- a/.trinity/seals/analog_AnalogMosPsp103Data.json +++ b/.trinity/seals/analog_AnalogMosPsp103Data.json @@ -7,23 +7,23 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:9e8e5b97faba8e2120066681472986c2b70b5207fb9f26c57a38f527f531c576", - "gen_hash_rust": "sha256:715acf0a48c1f1ba88df704ffc3a48ab3190d65a4282270bb2976a57c1450954", - "gen_hash_verilog": "sha256:f6f05bdafbac3e28a73cc54412ed776429b0ef7ce1c08219fa7dfabc2c98ebdd", - "gen_hash_zig": "sha256:9a77f32c1a9ee683b89349a0d2e87d166a1a3a8154663dfdb79053c0d11895eb", + "gen_hash_c": "sha256:a02b76251db8d7a64d65c32aad434a1847ac703ad6a71f16e4c1b970e0ea74b5", + "gen_hash_rust": "sha256:395c8a715aade1101e29f187926bfa9a985f6134ba5777dcf467ead14fc9732b", + "gen_hash_verilog": "sha256:dc49c09d8a3a13829b2cb9fba5450faa1f9d50da2611d75e06f2562e0d2cab13", + "gen_hash_zig": "sha256:8b372dfd2e05f42a44f713738843f75750e9a4c21d2f55c35dcac0db763bea8d", "module": "AnalogMosPsp103Data", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-19T18:09:24Z", + "sealed_at": "2026-10-19T19:25:27Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:c3d11a64e1fb2eddb7724acb75bcf7c242551a683a7d265a7cdd0d208c8d4d7b", + "spec_hash": "sha256:d233143ed2fa30d3bd0ff9546a2df008d568e4a4d9c7e0ef69ffedee2e92a5d6", "spec_path": "specs/analog/mos_psp103_data.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 9, - "total": 9, + "passed": 10, + "total": 10, "vacuous": 0 }, "toolchain": { diff --git a/.trinity/seals/analog_AnalogMosTable.json b/.trinity/seals/analog_AnalogMosTable.json index 51a7f8f984..f56f4dc197 100644 --- a/.trinity/seals/analog_AnalogMosTable.json +++ b/.trinity/seals/analog_AnalogMosTable.json @@ -1,5 +1,5 @@ { - "built_by": "t27c-bootstrap@0.5.2+c948f4df7", + "built_by": "t27c-bootstrap@0.5.2+42a4860c4", "closure": [ { "spec": "specs/analog/linear.t27", @@ -7,23 +7,23 @@ } ], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:e0ca09255f83209260afff210947c8af851f5412f9aa7a40f7f5b148a29ac739", - "gen_hash_rust": "sha256:dd4d433feaf2d937fc3acb769f6a9a8febc6d7cc58363dbc061ad9922eba3eb6", - "gen_hash_verilog": "sha256:b7e968dea3013590b323ce7c40e3be8df1d047bf6bde5b58768de36438102e7d", - "gen_hash_zig": "sha256:652d1bfbd355d08e8eca4a3f13a4957322006510c310d796111db8aac65ef1d0", + "gen_hash_c": "sha256:0d463e6735ad1e4b396815cc2cd3fbeaf247b51957a064a17401c55c662e7c09", + "gen_hash_rust": "sha256:88836ddfbb71fe8ead14846b2366b665f9bc75c79744eacaa5c393835356a3cc", + "gen_hash_verilog": "sha256:81cec1ae23c7262af635c0fca6a89e7b20a57473d4b3a1d011fbcb6a4f5e2e07", + "gen_hash_zig": "sha256:b6d45978701159e277778cb20711620e7f45af9ea9385df6a06d353b323e79ab", "module": "AnalogMosTable", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-19T13:35:45Z", + "sealed_at": "2026-10-19T19:25:12Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:16d28f10fa8663926dddb4bcced981cdc4cd8f38a6b748e4b7688f2e56bbab6c", + "spec_hash": "sha256:54e248069ae620d18d260231e238b6bc42dc3c65792bd1673b162c2dc97b2edb", "spec_path": "specs/analog/mos_table.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 17, - "total": 17, + "passed": 20, + "total": 20, "vacuous": 0 }, "toolchain": { diff --git a/specs/analog/decks/psp103_idpa_tt.cir b/specs/analog/decks/psp103_idpa_tt.cir new file mode 100644 index 0000000000..a3e29de82d --- /dev/null +++ b/specs/analog/decks/psp103_idpa_tt.cir @@ -0,0 +1,138 @@ +IHP SG13G2 PSP103 log-domain current tables, corner mos_tt +* specs/analog/decks/psp103_idpa_tt.cir -- the log-domain current tables for specs/analog/mos_psp103_data.t27 (M3c-2, #10881, epic #10486), 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_tt; 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_tt.cir (the same +* netlist lines). +* Solver options: reltol 1e-6, vntol 1e-9, abstol 1e-14, as psp103_tab_tt.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= IHP_OSDI= ngspice -b psp103_idpa_tt.cir > psp103_idpa_tt.out (ngspice-47) +* 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.23, 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 " TAB " 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. +* 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_tt +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 +.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.23 + abs(vgk - 0.23)) / 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.23 + abs(vgk - 0.23)) / 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.23 + abs(vgn - 0.23)) / 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.23 + abs(vgp - 0.23)) / 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 +.endc +.end diff --git a/specs/analog/mos_psp103.t27 b/specs/analog/mos_psp103.t27 index ea3174323e..2203c1df04 100644 --- a/specs/analog/mos_psp103.t27 +++ b/specs/analog/mos_psp103.t27 @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 ; specs/analog/mos_psp103.t27 -- the CMOS inverter on the IHP SG13G2 PSP103 tables, per corner, judged by ngspice -; M3b of the analog emulation epic (#10486, issue #10516); M3c (#10777, sub-issue #10880) adds the terminal charge, THE CHARGE below, for tt and ss, and M3c-3 (#10882) for ff, fs and sf. M3a (specs/analog/mos_table.t27) solved a CMOS inverter whose MOS currents +; M3b of the analog emulation epic (#10486, issue #10516); M3c (#10777, sub-issue #10880) adds the terminal charge, THE CHARGE below, for tt and ss, and M3c-3 (#10882) for ff, fs and sf; M3c-2 (#10881) the log-domain current of tt, THE WEAK INVERSION below. M3a (specs/analog/mos_table.t27) solved a CMOS inverter whose MOS currents ; were read from a table made of the square law. This file runs the same solver, unchanged but for taking the NMOS table and the ; PMOS table as two arguments, on tables made from the foundry's model: Id(Vgs, Vds) of sg13_lv_nmos (W 1.0 um) and sg13_lv_pmos ; (W 3.0 um), L 0.45 um, PSP 103.6 through ngspice-47 and the OSDI interface, IHP-Open-PDK commit 21133f219b1a6da10d803e345761e77415ceff40, @@ -108,10 +108,20 @@ ; without both 3.6 million (214 mV, 14 %): the 1 % sees each. The charge of another corner in the tt run (6 .. 12 mV, 0.4 .. 0.8 %) is below the 1 %, as ; for the inverter, and above the check's 0.1 %. An inverter's own output node is not used for this: its edge kicks it 32 mV below 0 V and 38 mV above Vdd ; at 100 fF, where the tables end (a table has no Vds < 0 and no Vds > Vdd), so the node of the deck stays between 0.59 and 1.08 V. -; THE WEAK INVERSION IS NOT MET (part 3 of #10777, follow-up #10881). 1 % with a floor of 1e-9 A at the midpoints and R2 points stays at the measured -; 0.55 .. 0.73, and a test says why no read of these tables can do it: a table word is 298 pA, so rounding alone is up to 149 pA, 15 % of the floor -; where 1 % allows 10 pA; and the NMOS current grows 6.5 .. 7 times per 62.5 mV cell, where a chord is more than 41 % above the exponential at the -; middle. The reader that meets it is a log-domain table in finer units with an integer exp, a different reader: #10881. +; THE WEAK INVERSION IS NOT MET BY THESE TABLES (part 3 of #10777) -- AND IS MET BY THE LOG-DOMAIN TABLES (M3c-2, #10881). 1 % with a floor of 1e-9 A at the midpoints and R2 points of +; the linear tables stays at the measured 0.55 .. 0.73, and a test says why no read of THESE tables can do it: a table word is 298 pA, so rounding alone is up to 149 pA, 15 % of the +; floor where 1 % allows 10 pA; and the NMOS current grows 6.5 .. 7 times per 62.5 mV cell, where a chord is more than 41 % above the exponential at the middle. +; The reader that meets it is the log-domain one of mos_table.t27 (THE LOG-DOMAIN READER there, designed on paper with the error against the grid), on the tt tables TT_LG_N and TT_LG_P +; (97 x 49 nodes of log2(Id / F) with the Vds factor F apart, mos_psp103_data.t27). Against ngspice, relative error with a floor of 1e-9 A, NMOS / PMOS: +; at the 576 midpoints of the 62.5 mV cells (nodes of the log grid: the rounding of the words) 0.080 % / 0.094 % (the linear tables 0.5 .. 0.65) +; at the 1000 R2 points 0.398 % / 0.527 % (0.57 / 0.70 .. 0.75) +; at 1000 centres of the log grid's own cells, the worst place for a chord of it 0.467 % / 0.705 % (the linear tables 0.66 / 0.72) +; so the bar is met at every set with 1.42 times to spare at the worst place (the PMOS cell centres, moderate inversion); the absolute error is 52 nA and 38 nA at the R2 points, 12 times +; less than the linear tables'. The integer arithmetic costs 0.102 % at most (against the f64 twin of the read on the same words, floor 1 nA), the slope is the smooth model's to 0.56 % / +; 0.82 %, and the log tables at the 625 nodes of the linear grid are the linear tables' words to 11 / 7 words. The tt inverter on them (current from the log tables, the M3c drain charge) +; follows ngspice backward Euler within 0.0018 % and 0.025 % of the two 50 % delays at 500 fF / 100 ps and within 0.0014 % and 0.0033 % at 10 pF / 2 ns with the charge scaled by 1 / 20 +; (without the charge the 10 pF run is 0.16 % and 0.19 % off, as with the linear tables: the charge decides it, not the reader), its waveform within 3002 and 415 units (0.18 mV and +; 25 uV; the linear tables 6691 and, with the same charge, 7341), and its DC transfer within 2829 units (0.17 mV) where the linear tables are 91938 (5.5 mV) off. ; - ; THE NEGATIVE CONTROLS, tests that pass by seeing the failure. `check_tt` holds a pair of tables to the tt bounds (Id at the 1000 ; R2 points of each device, the DC transfer and the 10 pF transient against ngspice tt). The tt pair passes. The ss pair used where @@ -138,10 +148,16 @@ ; follows that corner's ngspice backward Euler within 0.025 % of either delay and 0.45 mV, and the charge of any other corner is refused (25 pairs of ; corner and charge, five pass). The gate node of a circuit in which an NMOS gate is loaded by a PMOS drain and 25 fF follows ngspice's backward Euler ; on the same 5 ps grid within 0.051 % of the supply (the issue asked for 1 %), and without the gate charge, or without the drain charge, it does not. -; WHAT IT DOES NOT SAY. That this is PSP103: it is a TABLE MODEL of it, bilinear, at 27 C, for two device sizes, no body effect (bulk at +; M3c-2: the tt log-domain tables of both devices, read by the integer exp of mos_table.t27 with the slope off the same words, are within 1 % (a floor of 1e-9 A on ngspice's current) at the 576 +; midpoints, the 1000 R2 points and 1000 centres of the grid's own cells: 0.080 %, 0.398 % and 0.467 % (NMOS), 0.094 %, 0.527 % and 0.705 % (PMOS), where the linear reader is at 0.5 and more +; (100 times worse); the tt inverter on them is within 0.025 % of the two 50 % delays of ngspice's backward Euler at 500 fF / 100 ps and at 10 pF / 2 ns (the charge scaled by 1 / 20), with +; three Newton iterations and a last residual of at most 2 units, and a mutant table, a doubled Vds scale or a PMOS table in the NMOS slot is refused by 5 to 100 times the bar. +; WHAT IT DOES NOT SAY. That this is PSP103: it is a TABLE MODEL of it, bilinear (the log tables: bilinear in log2 of Id / F), at 27 C, for two device sizes, no body effect (bulk at ; the source), no Vds < 0, no Vgs < 0 (the table's range is 0 .. 1.5 V), nothing about another W, L, m, temperature, the high-voltage -; devices, mismatch or Monte Carlo. That the relative-error proposal of the issue (1 %, floor 1e-9 A) is met: it is not (see above); the -; bound is the measured one (#10881). Charge: the drain and gate charge of all five corners, for a 500 fF node and a +; devices, mismatch or Monte Carlo. That the relative-error proposal of the issue (1 %, floor 1e-9 A) is met by the LINEAR tables: it is not (see above) and the bound held for them is the +; measured one; it is met by the log tables of tt, only: the other four corners have no log table, and the log tables have no gm, no charge and no Vds < 0. Below the floor of 1 nA the bar is +; an absolute 10 pA (1 % of the floor), and a current below 1.164 pA is held at that. The log read is checked for tt at the two circuits above: the 10 pF +; run needs the charge (0.16 % and 0.19 % off without it, the linear tables 0.14 % and 0.17 %), which is the M3c charge scaled, not a new measurement of it. Charge: the drain and gate charge of all five corners, for a 500 fF node and a ; 100 ps step; the gate charge is read by one circuit here, the gate node, in tt only, in f64 and not on the board's integer path; the source and bulk charge is not tabulated (the source and bulk are ; on the rails); the 10 pF run has no charge in it (its device capacitance is 0.2 % of the load). The transient is checked for tt only, on two ; circuits of one dt / C and one input (two levels, an ideal step); the other corners are checked on Id and on the DC transfer. Nothing about a board (no bitstream, BRAM, LUT, DSP, @@ -152,9 +168,9 @@ module AnalogMosPsp103; use analog::linear::{fabs64}; -use analog::mos_table::{CELL, CELL_F, VDD_F, NCELL, NODES, VDD, K_NEWTON, RES_BOUND, RUN_STEPS, lim, id_of, gm_cell, gds_cell, mag_diff, monotone, monotone_along, fmax64, run_fix, run_fix_q, run_tabf, run_tabf_q, max_of, board_step, inv_step, inv_step_q, g_resid_q, NOQ, idf, gdsf}; +use analog::mos_table::{CELL, CELL_F, VDD_F, NCELL, NODES, VDD, K_NEWTON, RES_BOUND, RUN_STEPS, lim, id_of, gm_cell, gds_cell, mag_diff, monotone, monotone_along, fmax64, run_fix, run_fix_q, run_tabf, run_tabf_q, max_of, board_step, inv_step, inv_step_q, g_resid_q, NOQ, idf, gdsf, LG_NG, LG_ND, LG_GBITS, LG_DBITS, LG_TAG, LG_LEN, lg_fine, id_log, gds_log, idf_log, cur_of, cur_gds, lg_lam, lg_rv, exp_f64}; use analog::sar_comparator::{sc_gmf}; -use analog::mos_psp103_data::{R2_A1, R2_A2, R2_TT_COUNT, CORNER_TT, CORNER_FF, CORNER_SS, CORNER_FS, CORNER_SF, TT_N, TT_P, SS_N, SS_P, TT_INV, TT_MID_N, TT_MID_P, TT_R2_N, TT_R2_P, INV10_BE, INV10_FINE, INV10_FINE_TPLH_FS, INV10_FINE_TPHL_FS, INV500_BE_TPLH_FS, INV500_BE_TPHL_FS, INV500_FINE_TPLH_FS, INV500_FINE_TPHL_FS, INV500_BE, TT_QD_N, TT_QG_N, TT_QD_P, TT_QG_P, SS_QD_N, SS_QG_N, SS_QD_P, SS_QG_P, OP_CDD_AF, OP_CDG_AF, OP_CGG_AF, OP_CGSOL_AF, OP_CGDOL_AF, OP_CJD_AF, OP_FF_AF, OP_FS_AF, OP_SF_AF, GATE_BE, table_n, table_p, fold_q, qd_n, qg_n, qd_p, qg_p, inv500_be, inv500_tplh_fs, inv500_tphl_fs, inv_dc, r2_n, r2_p, r2_count}; +use analog::mos_psp103_data::{R2_A1, R2_A2, R2_TT_COUNT, CORNER_TT, CORNER_FF, CORNER_SS, CORNER_FS, CORNER_SF, TT_N, TT_P, SS_N, SS_P, TT_INV, TT_MID_N, TT_MID_P, TT_R2_N, TT_R2_P, INV10_BE, INV10_FINE, INV10_FINE_TPLH_FS, INV10_FINE_TPHL_FS, INV500_BE_TPLH_FS, INV500_BE_TPHL_FS, INV500_FINE_TPLH_FS, INV500_FINE_TPHL_FS, INV500_BE, TT_QD_N, TT_QG_N, TT_QD_P, TT_QG_P, SS_QD_N, SS_QG_N, SS_QD_P, SS_QG_P, OP_CDD_AF, OP_CDG_AF, OP_CGG_AF, OP_CGSOL_AF, OP_CGDOL_AF, OP_CJD_AF, OP_FF_AF, OP_FS_AF, OP_SF_AF, GATE_BE, table_n, table_p, fold_q, qd_n, qg_n, qd_p, qg_p, inv500_be, inv500_tplh_fs, inv500_tphl_fs, inv_dc, r2_n, r2_p, r2_count, TT_LG_N, TT_LG_P, TT_CEN_N, TT_CEN_P}; pub const KIND : str = "analog-cell-check"; pub const ID : str = "analog/mos_psp103"; @@ -220,6 +236,12 @@ pub const EXP_S_SS_Q : u64 = 0x987F22AC4132345B; pub const EXP_S_FF_Q : u64 = 0x836220E2C48AB136; pub const EXP_S_FS_Q : u64 = 0xA45CC48E565AD2EB; pub const EXP_S_SF_Q : u64 = 0x67F02DF65E28F63E; +/// M3c-2: the tt run with the LOG-DOMAIN current tables and the tt drain-charge tables, at 500 fF / 100 ps (the gate at Vdd before step 0), and at 10 pF / 2 ns with the charge +/// tables scaled by 1 / 20. +pub const EXP_S_TT_LQ : u64 = 0x1745008BA3F87284; +pub const EXP_S_TT_LQ10 : u64 = 0x27D759234A27E404; +/// The issue's bar for the current: at most 1 % relative error with a floor of 1e-9 A on the reference. +pub const B_LOG_ISSUE : f64 = 0.01; ; --- the gate node (M3c-3, deck psp103_gate_node.cir) ------------------------------------------------- /// The node's own capacitance, 25 fF; dt = 5 ps on it is dt / C = 200 V/A, the unit of the current tables. @@ -244,6 +266,9 @@ pub fn amps_of(units: f64) -> f64 { return units / (DTC * UPV); } +/// One IUNIT of the log tables in A: a table word over 2^8, 1 / (DTC * 2^32) = 1.164 pA. +pub const IUNIT_A : f64 = 0.0000000000011641532182693481; + /// The R2 coordinate k * a, fractional part, in units of 2^-24 V over 0 .. 1.5 V. pub fn r2_units(k: u32, a: f64) -> u32 { const x : f64 = (k as f64) * a; @@ -251,16 +276,26 @@ pub fn r2_units(k: u32, a: f64) -> u32 { return lim(((f * 1.5 * UPV) + 0.5) as u32); } +/// The centre of cell floor(ncell * frac(k a)) of an axis of cells of 2^bits units: the held-out points of the log grid (kind 2 below), where a chord of that grid is worst. +pub fn cell_centre(k: u32, a: f64, ncell: u32, bits: u32) -> u32 { + const x : f64 = (k as f64) * a; + const f : f64 = x - ((x as u32) as f64); + const c : u32 = (f * (ncell as f64)) as u32; + return (c << bits) + (1 << (bits - 1)); +} + /// Vgs (Vsg) of held-out point idx: kind 0 is the cell midpoints (idx = i * 24 + j, the middle of cell i along Vgs), kind 1 -/// the R2 points (idx 0 is point k = 1). +/// the R2 points (idx 0 is point k = 1), kind 2 the centres of cells of the log grid picked by the R2 sequence (M3c-2). pub fn pt_vg(kind: u32, idx: u32) -> u32 { if (kind == 0) { return (idx / NCELL) * CELL + (CELL >> 1); } + if (kind == 2) { return cell_centre(idx + 1, R2_A1, LG_NG, LG_GBITS); } return r2_units(idx + 1, R2_A1); } /// Vds (Vsd) of held-out point idx. pub fn pt_vd(kind: u32, idx: u32) -> u32 { if (kind == 0) { return (idx % NCELL) * CELL + (CELL >> 1); } + if (kind == 2) { return cell_centre(idx + 1, R2_A2, LG_ND, LG_DBITS); } return r2_units(idx + 1, R2_A2); } @@ -293,16 +328,42 @@ pub fn hold_stats(t: []const u32, ref_pa: []const u32, kind: u32, n: u32) -> Hol return Hold { abs_a: abs_a, rel9: rel9, b6: b6, b5: b5, b4: b4, n6: n6, n5: n5, n4: n4 }; } +pub struct HoldL { rel9: f64, abs_a: f64, arith: f64, n9: u32 } + +/// A log table t (mos_table.t27, `lg_fine`) against the ngspice currents ref_pa (pA) at the first n held-out points of a kind (0 the 576 midpoints, 1 the R2 points, 2 the centres of the +/// log grid's cells): the largest relative error with a floor of 1e-9 A on the reference (the issue's measure, #10881), the largest absolute error in A, the largest gap of the +/// integer read to its f64 twin `idf_log` (the arithmetic of the read, relative, floor 1 nA), and how many of the points have a reference above the floor. +pub fn hold_log(t: []const u32, ref_pa: []const u32, kind: u32, n: u32) -> HoldL { + var rel9 : f64 = 0.0; + var abs_a : f64 = 0.0; + var arith : f64 = 0.0; + var n9 : u32 = 0; + var i : u32 = 0; + while (i < n) { + const vg : u32 = pt_vg(kind, i); + const vd : u32 = pt_vd(kind, i); + const got : f64 = ((lg_fine(t, vg, vd)) as f64) * IUNIT_A; + const twin : f64 = idf_log(t, vg as f64, vd as f64) * IUNIT_A; + const want : f64 = ((ref_pa[i as usize]) as f64) * 0.000000000001; + abs_a = fmax64(abs_a, fabs64(got - want)); + rel9 = fmax64(rel9, fabs64(got - want) / fmax64(want, 0.000000001)); + arith = fmax64(arith, fabs64(got - twin) / fmax64(twin, 0.000000001)); + if (want >= 0.000000001) { n9 = n9 + 1; } + i = i + 1; + } + return HoldL { rel9: rel9, abs_a: abs_a, arith: arith, n9: n9 }; +} + ; --- the inverter --------------------------------------------------------------------------------- /// The DC output of the inverter for gate a: the largest y at which the NMOS current at (a, y) does not exceed the PMOS current -/// at (Vdd - a, Vdd - y). Bisection on the integer table reads: the NMOS current rises with y and the PMOS current falls. +/// at (Vdd - a, Vdd - y). Bisection on the integer table reads: the NMOS current rises with y and the PMOS current falls. A log table (M3c-2) is read by `cur_of` like any other. pub fn dc_out(tn: []const u32, tp: []const u32, a: u32) -> u32 { var lo : u32 = 0; var hi : u32 = VDD; while (hi - lo > 1) { const mid : u32 = lo + ((hi - lo) >> 1); - if (id_of(tn, a, mid) > id_of(tp, VDD - a, VDD - mid)) { hi = mid; } else { lo = mid; } + if (cur_of(tn, a, mid) > cur_of(tp, VDD - a, VDD - mid)) { hi = mid; } else { lo = mid; } } return lo; } @@ -476,6 +537,35 @@ pub fn q500_ok(r: Q500) -> bool { return true; } +/// A charge table for another node capacitance: the charge tables are Q / 500 fF, so for a node of C = 500 fF * den / num every entry scales by num / den +/// (10 pF: 1 / 20), rounded half up. Nondecreasing tables stay nondecreasing. A test-side tool: a board loads the scaled table. +pub fn scale_q(src: []const u32, num: u32, den: u32, dst: []u32) { + var i : u32 = 0; + while (i < 625) { + dst[i as usize] = (src[i as usize] * num + den / 2) / den; + i = i + 1; + } +} + +pub struct InvL { up_rel: f64, dn_rel: f64, wave: f64, res: u32, fold: u64, rest: u32 } + +/// The inverter run of M3c-2: tables tn, tp (linear or log, `cur_of` reads either) and drain-charge tables qn, qp, the board's arithmetic (K_NEWTON iterations, the gate at Vdd +/// before step 0, from the DC rest value), against the 401-sample backward Euler waveform be of ngspice and its two 50 % delays in steps (ref_up after step 0, ref_dn after +/// step 200): the relative gap of each delay, the largest |dY| of the 401 samples in units, the largest last Newton residual, the fold of the 400 samples and the rest value. +pub fn inv_run_l(tn: []const u32, tp: []const u32, qn: []const u32, qp: []const u32, be: []const u32, ref_up: f64, ref_dn: f64) -> InvL { + var out : [400]u32 = [0] ** 400; + var res : [400]u32 = [0] ** 400; + var tmp : [400]f64 = [0.0] ** 400; + var fix : [401]f64 = [0.0] ** 401; + var bef : [401]f64 = [0.0] ** 401; + const rest : u32 = dc_out(tn, tp, VDD); + const s : u64 = run_fix_q(tn, tp, qn, qp, K_NEWTON, rest, VDD, false, &out, &res); + lift_u32(&out, 400, &tmp); + shift_run(rest as f64, &tmp, &fix); + lift_u32(be, 401, &bef); + return InvL { up_rel: rel_gap(delay_up(&fix), ref_up), dn_rel: rel_gap(delay_dn(&fix), ref_dn), wave: max_diff(&fix, &bef, 401), res: max_of(&res), fold: s, rest: rest }; +} + /// How many of the 576 cells of a table have the interpolant's movement across the cell equal to the cell's slope, within the 2 units /// of the two reads and the slope's rounding: ax 1 across a cell of Vds against `gds_cell`, ax 0 across a cell of Vgs against /// `gm_cell`. For a table nondecreasing along that axis. The slope is read off the same nodes as the value (FR-002). @@ -1328,7 +1418,7 @@ test the_issue_s_weak_inversion_one_percent_is_out_of_reach_of_a_chord_over_thes assert_eq(checked, 3); // (c) WHAT WOULD DO IT. Tabulating the current in units of 0.3 pA would put 1 % of the floor at 33 words, but the largest word, 402 uA, // is then 1.3e9, and the reader's u64 interpolation needs every word under 2^23: the read would need 128-bit sums or a table in the log - // domain (an integer exp). That is a different reader, not a finer grid: the next issue. + // domain (an integer exp). That is a different reader, not a finer grid: M3c-2 (#10881) built it, and the tests of the log-domain reader below hold it to the bar. var wide : f64 = 0.000402305 / 0.0000000000003; var bound : f64 = 8388608.0; assert wide > 100.0 * bound; @@ -1751,3 +1841,400 @@ test the_gate_nodes_slope_is_read_off_the_gate_charge_table_the_charge_comes_fro assert cw > 1870.0; assert cw < 1890.0; } + +test the_log_domain_reader_meets_one_percent_with_a_floor_of_1_nA_at_the_midpoints_the_r2_points_and_the_cell_centres { + // M3c-2 (#10881, part 3 of #10777). THE ISSUE'S SCENARIO: the tt log-domain tables of both devices, read by the integer exp of mos_table.t27 (`lg_fine`), against ngspice at the 576 + // cell midpoints and the 1000 R2 points, the same references as the linear tables above (0.55 .. 0.73), and at 1000 centres of the log grid's own cells (kind 2), the worst place for + // a chord of THAT grid: the relative error with a floor of 1e-9 A on the reference. + const mn : HoldL = hold_log(&TT_LG_N, &TT_MID_N, 0, 576); + const rn : HoldL = hold_log(&TT_LG_N, &TT_R2_N, 1, 1000); + const cn : HoldL = hold_log(&TT_LG_N, &TT_CEN_N, 2, 1000); + const mp : HoldL = hold_log(&TT_LG_P, &TT_MID_P, 0, 576); + const rp : HoldL = hold_log(&TT_LG_P, &TT_R2_P, 1, 1000); + const cp : HoldL = hold_log(&TT_LG_P, &TT_CEN_P, 2, 1000); + // THE BAR: at most 1 %, at every one of the 6 sets. + assert mn.rel9 < B_LOG_ISSUE; + assert rn.rel9 < B_LOG_ISSUE; + assert cn.rel9 < B_LOG_ISSUE; + assert mp.rel9 < B_LOG_ISSUE; + assert rp.rel9 < B_LOG_ISSUE; + assert cp.rel9 < B_LOG_ISSUE; + // What is measured, both sides. NMOS: 0.080 % at the midpoints (nodes of this grid: the rounding only), 0.398 % at the R2 points, 0.467 % at the cell centres. PMOS: 0.094 %, + // 0.527 % and 0.705 %: the worst place is the PMOS, at a cell centre in moderate inversion, 1.42 times under the bar. + assert mn.rel9 < 0.00081; + assert mn.rel9 > 0.00079; + assert rn.rel9 < 0.003978; + assert rn.rel9 > 0.003976; + assert cn.rel9 < 0.004676; + assert cn.rel9 > 0.004672; + assert mp.rel9 < 0.000937; + assert mp.rel9 > 0.000935; + assert rp.rel9 < 0.005267; + assert rp.rel9 > 0.005263; + assert cp.rel9 < 0.007049; + assert cp.rel9 > 0.007045; + // The absolute error, A: 52 nA at the worst R2 point (it was 651 nA), 48 nA at a centre; PMOS 38 nA and 33 nA (439 nA before). + assert rn.abs_a < 0.0000000521; + assert rn.abs_a > 0.0000000520; + assert cn.abs_a < 0.0000000481; + assert cn.abs_a > 0.0000000480; + assert rp.abs_a < 0.0000000384; + assert rp.abs_a > 0.0000000383; + assert cp.abs_a < 0.0000000328; + assert cp.abs_a > 0.0000000327; + assert mn.abs_a < 0.0000000026; + assert mp.abs_a < 0.0000000021; + // The points above the floor are most of them (a floor of 1 nA leaves 96 % and 90 % of the points to the relative bound; the rest are held to 10 pA). + assert_eq(mn.n9, 551); + assert_eq(rn.n9, 962); + assert_eq(cn.n9, 962); + assert_eq(mp.n9, 527); + assert_eq(rp.n9, 899); + assert_eq(cp.n9, 905); +} + +test the_integer_read_is_the_f64_read_of_the_same_words_to_the_rounding_of_a_unit { + // THE THREE ERRORS, the arithmetic apart: the integer read (`lg_fine`: the integer exp, F by series and table, the blends rounded) against its f64 twin `idf_log` on the same + // words (exact 2^x and 1 - e^-x, no rounding), relative with a floor of 1 nA: at most 0.102 %, which is one or two units of 1.164 pA at the 859 units of the floor. The table's + // own error (the log chord, the model) is the test above. + const mn : HoldL = hold_log(&TT_LG_N, &TT_MID_N, 0, 576); + const rn : HoldL = hold_log(&TT_LG_N, &TT_R2_N, 1, 1000); + const cn : HoldL = hold_log(&TT_LG_N, &TT_CEN_N, 2, 1000); + const mp : HoldL = hold_log(&TT_LG_P, &TT_MID_P, 0, 576); + const rp : HoldL = hold_log(&TT_LG_P, &TT_R2_P, 1, 1000); + const cp : HoldL = hold_log(&TT_LG_P, &TT_CEN_P, 2, 1000); + assert mn.arith < 0.00102; + assert rn.arith < 0.00102; + assert cn.arith < 0.00102; + assert mp.arith < 0.00102; + assert rp.arith < 0.00102; + assert cp.arith < 0.00102; + assert cp.arith > 0.001013; + assert mn.arith > 0.00094; + assert mp.arith > 0.00066; + // The arithmetic is a seventh of the table's error where the table's error is largest (the PMOS cell centres). + assert cp.arith * 6.0 < cp.rel9; +} + +test the_m3b_linear_reader_on_the_same_points_stays_at_half_or_more_the_negative_control { + // The linear reader of M3b/M3c on the linear tables, at the same 576 midpoints and 1000 R2 points, and at the 1000 centres of the log grid: 0.5 and more everywhere, 100 or more + // times the log reader's error. The new reader is what meets the bar. + const ln_m : Hold = hold_stats(&TT_N, &TT_MID_N, 0, 576); + const ln_r : Hold = hold_stats(&TT_N, &TT_R2_N, 1, 1000); + const ln_c : Hold = hold_stats(&TT_N, &TT_CEN_N, 2, 1000); + const lp_m : Hold = hold_stats(&TT_P, &TT_MID_P, 0, 576); + const lp_r : Hold = hold_stats(&TT_P, &TT_R2_P, 1, 1000); + const lp_c : Hold = hold_stats(&TT_P, &TT_CEN_P, 2, 1000); + assert ln_m.rel9 > 0.5; + assert ln_r.rel9 > 0.5; + assert ln_c.rel9 > 0.5; + assert lp_m.rel9 > 0.5; + assert lp_r.rel9 > 0.5; + assert lp_c.rel9 > 0.5; + assert ln_c.rel9 > 0.65; + assert ln_c.rel9 < 0.66; + assert lp_c.rel9 > 0.72; + assert lp_c.rel9 < 0.73; + const mn : HoldL = hold_log(&TT_LG_N, &TT_MID_N, 0, 576); + const rn : HoldL = hold_log(&TT_LG_N, &TT_R2_N, 1, 1000); + const cn : HoldL = hold_log(&TT_LG_N, &TT_CEN_N, 2, 1000); + const mp : HoldL = hold_log(&TT_LG_P, &TT_MID_P, 0, 576); + const rp : HoldL = hold_log(&TT_LG_P, &TT_R2_P, 1, 1000); + const cp : HoldL = hold_log(&TT_LG_P, &TT_CEN_P, 2, 1000); + assert ln_m.rel9 > 100.0 * mn.rel9; + assert ln_r.rel9 > 100.0 * rn.rel9; + assert ln_c.rel9 > 100.0 * cn.rel9; + assert lp_m.rel9 > 100.0 * mp.rel9; + assert lp_r.rel9 > 100.0 * rp.rel9; + assert lp_c.rel9 > 100.0 * cp.rel9; + // And the absolute error: the linear tables are 12 times worse in A at the R2 points. + assert ln_r.abs_a > 12.0 * rn.abs_a; + assert lp_r.abs_a > 11.0 * rp.abs_a; +} + +test the_log_tables_at_the_nodes_of_the_linear_grid_are_the_linear_tables_words_one_model { + // The two tables are from one model: the log table read at the 625 nodes of the 25 x 25 grid (all of them nodes of the 97 x 49 one) is the linear table's word to 11 words (NMOS) + // and 7 (PMOS) -- the rounding of a word in the linear table (0.5), in the log table (a part in 1e5), at the weak-inversion nodes where a word is a few percent -- and to + // 0.0057 % (NMOS) and 0.0083 % (PMOS) where the word is over 200. + var worst_n : u32 = 0; + var worst_p : u32 = 0; + var rel_n : f64 = 0.0; + var rel_p : f64 = 0.0; + var ix : u32 = 0; + while (ix < 25) { + var iy : u32 = 0; + while (iy < 25) { + const an : u32 = id_log(&TT_LG_N, ix * CELL, iy * CELL); + const ap : u32 = id_log(&TT_LG_P, ix * CELL, iy * CELL); + const bn : u32 = TT_N[(ix * 25 + iy) as usize]; + const bp : u32 = TT_P[(ix * 25 + iy) as usize]; + if (mag_diff(an, bn) > worst_n) { worst_n = mag_diff(an, bn); } + if (mag_diff(ap, bp) > worst_p) { worst_p = mag_diff(ap, bp); } + if (iy > 0 and bn > 200) { rel_n = fmax64(rel_n, (mag_diff(an, bn) as f64) / (bn as f64)); } + if (iy > 0 and bp > 200) { rel_p = fmax64(rel_p, (mag_diff(ap, bp) as f64) / (bp as f64)); } + iy = iy + 1; + } + ix = ix + 1; + } + assert_eq(worst_n, 11); + assert_eq(worst_p, 7); + assert rel_n < 0.0000574; + assert rel_n > 0.0000572; + assert rel_p < 0.0000831; + assert rel_p > 0.0000830; + // The corner and the largest entry: Id(1.5 V, 1.5 V) of the NMOS is 402.3 uA, the word 1349910 against the linear table's 1349912. + assert_eq(id_log(&TT_LG_N, VDD, VDD), 1349910); + assert_eq(TT_N[624], 1349912); + // Vds = 0 is a node with no current: the Vds factor F is 0 there, whatever the log word (the limit of Id / F), for every Vgs. + var vg : u32 = 0; + while (vg <= VDD) { + assert_eq(lg_fine(&TT_LG_N, vg, 0), 0); + assert_eq(lg_fine(&TT_LG_P, vg, 0), 0); + vg = vg + 1234567; + } + // And the log tables hold the unit of the linear ones: one IUNIT is a word over 2^8. + const one : f64 = IUNIT_A * 256.0 - amps_of(1.0); + assert one * one < 0.000000000000000000000000000001; +} + +test the_slope_of_the_log_read_is_read_off_the_same_words_and_follows_the_table { + // FR-002 for the new reader. gds_log, the slope the Newton step uses, against the movement of the f64 twin of the read (`idf_log`, no rounding) across +-2^12 units of Vds, in + // words per 2^20 units, over a lattice of 26 x 21 points that stays 2^13 inside the Vds cells: within 0.56 % (NMOS) and 0.82 % (PMOS) where the slope is at least 1000 + // words per cell (1788 and 1254 points), within 2.9 and 9.2 words below. (The integer read itself is a staircase of 1 / 65536 octave in the log word, so its own movement over a + // few units says nothing; the slope is the smooth model's, from the cell's four nodes and the two rv words.) + var rel_n : f64 = 0.0; + var rel_p : f64 = 0.0; + var abs_n : f64 = 0.0; + var abs_p : f64 = 0.0; + var cnt_n : u32 = 0; + var cnt_p : u32 = 0; + var vg : u32 = 3000000; + while (vg < VDD) { + var vd : u32 = 600000; + while (vd < VDD - 700000) { + const inside : u32 = vd % 524288; + if (inside > 8192 and inside < 524288 - 8192) { + const fdn : f64 = (idf_log(&TT_LG_N, vg as f64, ((vd + 4096) as f64)) - idf_log(&TT_LG_N, vg as f64, ((vd - 4096) as f64))) / 2.0; + const fdp : f64 = (idf_log(&TT_LG_P, vg as f64, ((vd + 4096) as f64)) - idf_log(&TT_LG_P, vg as f64, ((vd - 4096) as f64))) / 2.0; + const gn : f64 = (gds_log(&TT_LG_N, vg, vd)) as f64; + const gp : f64 = (gds_log(&TT_LG_P, vg, vd)) as f64; + if (fdn >= 1000.0) { rel_n = fmax64(rel_n, fabs64(gn - fdn) / fdn); cnt_n = cnt_n + 1; } else { abs_n = fmax64(abs_n, fabs64(gn - fdn)); } + if (fdp >= 1000.0) { rel_p = fmax64(rel_p, fabs64(gp - fdp) / fdp); cnt_p = cnt_p + 1; } else { abs_p = fmax64(abs_p, fabs64(gp - fdp)); } + } + vd = vd + 311111; + } + vg = vg + 700001; + } + assert_eq(cnt_n, 1788); + assert_eq(cnt_p, 1254); + assert rel_n < 0.0057; + assert rel_n > 0.0055; + assert rel_p < 0.0083; + assert rel_p > 0.0081; + assert abs_n < 2.9; + assert abs_p < 9.3; + // The slope follows the table: one node of the NMOS table moved up by 20000 words (23 %), and the slope inside the four cells that share it moves with it, to the same + // tolerance against the twin of the moved table; the slope of the unmoved table there is not that of the moved one. + var tm : [4851]u32 = [0] ** 4851; + var i : usize = 0; + while (i < 4851) { + tm[i] = TT_LG_N[i]; + i = i + 1; + } + tm[1 + 40 * 49 + 10] = tm[1 + 40 * 49 + 10] + 20000; + const pvg : u32 = 40 * 262144 + 131072; + const pvd : u32 = 9 * 524288 + 262144; + const f_old : f64 = (idf_log(&TT_LG_N, pvg as f64, ((pvd + 4096) as f64)) - idf_log(&TT_LG_N, pvg as f64, ((pvd - 4096) as f64))) / 2.0; + const f_new : f64 = (idf_log(&tm, pvg as f64, ((pvd + 4096) as f64)) - idf_log(&tm, pvg as f64, ((pvd - 4096) as f64))) / 2.0; + const g_old : f64 = (gds_log(&TT_LG_N, pvg, pvd)) as f64; + const g_new : f64 = (gds_log(&tm, pvg, pvd)) as f64; + assert fabs64(g_old - f_old) < 0.0057 * f_old + 3.0; + assert fabs64(g_new - f_new) < 0.0057 * f_new + 3.0; + assert fabs64(g_new - g_old) > 0.05 * f_old; + assert g_new > g_old; +} + +test the_inverter_dc_transfer_on_the_log_tables_is_32_times_closer_to_ngspice_than_on_the_linear_ones { + // The DC transfer of the inverter (49 points, the bisection of `dc_out` reading the tables through `cur_of`) against ngspice: the largest |dVout| is 2829 units (0.17 mV) + // where the linear tables have 91938 (5.5 mV), and the trip point is 5.9e-5 of a sweep step (1.8 uV) from ngspice's, where it was 11 uV. + const d : Dc = dc_check(&TT_LG_N, &TT_LG_P, &TT_INV); + const l : Dc = dc_check(&TT_N, &TT_P, &TT_INV); + assert d.worst < 2830.0; + assert d.worst > 2828.0; + assert l.worst > 91900.0; + assert d.worst * 32.0 < l.worst; + const vm : f64 = fabs64(d.vm_model - d.vm_ref); + assert vm < 0.000060; + assert vm > 0.000057; + assert vm * 6.0 < fabs64(l.vm_model - l.vm_ref); + assert_eq(dc_out(&TT_LG_N, &TT_LG_P, VDD), 2); +} + +test the_tt_inverter_at_500_fF_on_the_log_tables_is_within_0_05_percent_of_ngspice_backward_euler { + // The scenario of the issue: the tt inverter at 500 fF and dt = 100 ps, 400 steps, the current read by the log tables (the charge by the M3c drain-charge tables), the board's + // arithmetic (K = 3, the last residual at most 2 units), against ngspice backward Euler on the same grid. + const up_be5 : f64 = steps_of_fs(INV500_BE_TPLH_FS, EDGE1_500F_FS, DT_500F_FS); + const dn_be5 : f64 = steps_of_fs(INV500_BE_TPHL_FS, EDGE2_500F_FS, DT_500F_FS); + const r : InvL = inv_run_l(&TT_LG_N, &TT_LG_P, &TT_QD_N, &TT_QD_P, &INV500_BE, up_be5, dn_be5); + const old : InvL = inv_run_l(&TT_N, &TT_P, &TT_QD_N, &TT_QD_P, &INV500_BE, up_be5, dn_be5); + // The run: from the DC rest value of the log tables (2 units; ngspice's 11), the fold pinned, the last residual at the bound. + assert_eq(r.rest, 2); + assert_eq(r.fold, EXP_S_TT_LQ); + assert r.res <= RES_BOUND; + assert_eq(r.res, 2); + // THE BAR: both 50 % delays within 0.05 % (the issue asked for 0.05 % at 500 fF and 10 pF; the linear tables with the charge are 0.020 % and 0.0042 %). + assert r.up_rel < B_Q_DELAY_REL; + assert r.dn_rel < B_Q_DELAY_REL; + assert r.up_rel < B_ISSUE_DELAY_REL; + // What is measured, both sides: tpLH 0.0018 %, tpHL 0.0249 %. + assert r.up_rel < 0.0000186; + assert r.up_rel > 0.0000184; + assert r.dn_rel < 0.000250; + assert r.dn_rel > 0.000248; + // The waveform of 401 samples: the largest |dY| is 3002 units (0.18 mV, 0.012 % of Vdd), the linear tables' 6691. + assert r.wave < 3003.0; + assert r.wave > 3001.0; + assert old.wave > 6690.0; + assert r.wave * 2.0 < old.wave; + assert old.up_rel > 0.00019; + assert old.up_rel < 0.00021; + assert_eq(old.fold, EXP_S_TT_Q); +} + +test the_tt_inverter_at_10_pF_on_the_log_tables_is_within_0_05_percent_of_ngspice_backward_euler_with_the_charge_scaled { + // The 10 pF / 2 ns circuit has the same dt / C, so the same current tables; its charge is the 500 fF charge over 20 (the tables are Q / 500 fF), rounded to a word. With it the + // delays are within 0.0014 % and 0.0033 % of ngspice's backward Euler on the same 2 ns grid, and the waveform within 415 units (25 uV). + var be : [401]f64 = [0.0] ** 401; + lift_u32(&INV10_BE, 401, &be); + const up_be : f64 = delay_up(&be); + const dn_be : f64 = delay_dn(&be); + var qn : [625]u32 = [0] ** 625; + var qp : [625]u32 = [0] ** 625; + scale_q(&TT_QD_N, 1, 20, &qn); + scale_q(&TT_QD_P, 1, 20, &qp); + assert(monotone_along(&qn, 1)); + assert(monotone_along(&qp, 1)); + const r : InvL = inv_run_l(&TT_LG_N, &TT_LG_P, &qn, &qp, &INV10_BE, up_be, dn_be); + assert_eq(r.rest, 2); + assert_eq(r.fold, EXP_S_TT_LQ10); + assert r.res <= RES_BOUND; + assert_eq(r.res, 1); + assert r.up_rel < B_Q_DELAY_REL; + assert r.dn_rel < B_Q_DELAY_REL; + assert r.up_rel < 0.0000139; + assert r.up_rel > 0.0000138; + assert r.dn_rel < 0.0000331; + assert r.dn_rel > 0.0000329; + assert r.wave < 416.0; + assert r.wave > 414.0; + // THE CHARGE IS WHAT THE 10 pF RUN NEEDS, NOT THE READER: without it the log tables are 0.163 % and 0.189 % off (the linear tables 0.142 % and 0.172 %, above), outside 0.05 %, + // and the waveform 22306 units; with the linear tables and the same scaled charge the delays are 0.019 % and 0.013 % off and the waveform 7341, 17.7 times the log tables'. + const nq : InvL = inv_run_l(&TT_LG_N, &TT_LG_P, &NOQ, &NOQ, &INV10_BE, up_be, dn_be); + assert nq.up_rel > 3.0 * B_Q_DELAY_REL; + assert nq.dn_rel > 3.0 * B_Q_DELAY_REL; + assert nq.up_rel > 0.001625; + assert nq.up_rel < 0.001627; + assert nq.dn_rel > 0.001886; + assert nq.dn_rel < 0.001889; + assert nq.wave > 22305.0; + assert nq.wave < 22307.0; + const lin : InvL = inv_run_l(&TT_N, &TT_P, &qn, &qp, &INV10_BE, up_be, dn_be); + assert lin.up_rel < B_Q_DELAY_REL; + assert lin.dn_rel < B_Q_DELAY_REL; + assert lin.wave > 7340.0; + assert lin.wave < 7342.0; + assert lin.wave > 17.0 * r.wave; +} + +test one_and_two_newton_iterations_break_the_residual_bound_on_the_log_tables { + // The log tables' slope is what the Newton step uses, so the fixed K = 3 stays what it was on the linear tables: K = 1 leaves 6620 units, K = 2 leaves 12, K = 3 is at the bound. + var out : [400]u32 = [0] ** 400; + var res1 : [400]u32 = [0] ** 400; + var res2 : [400]u32 = [0] ** 400; + var res3 : [400]u32 = [0] ** 400; + const s1 : u64 = run_fix_q(&TT_LG_N, &TT_LG_P, &TT_QD_N, &TT_QD_P, 1, 2, VDD, false, &out, &res1); + const s2 : u64 = run_fix_q(&TT_LG_N, &TT_LG_P, &TT_QD_N, &TT_QD_P, 2, 2, VDD, false, &out, &res2); + const s3 : u64 = run_fix_q(&TT_LG_N, &TT_LG_P, &TT_QD_N, &TT_QD_P, K_NEWTON, 2, VDD, false, &out, &res3); + assert_eq(max_of(&res1), 6620); + assert_eq(max_of(&res2), 12); + assert max_of(&res3) <= RES_BOUND; + assert max_of(&res1) > RES_BOUND; + assert max_of(&res2) > RES_BOUND; + assert s1 != s3; + assert s2 != s3; + assert_eq(s3, EXP_S_TT_LQ); +} + +test a_mutant_log_table_or_a_wrong_device_fails_the_one_percent_bar { + // NEGATIVE CONTROLS of the reader: each passes by seeing the failure. The NMOS table with (1) every rv word doubled, (2) one octave added to every log word, (3) every rv word at + // the weak-inversion value (the Vds factor wrong in strong inversion), (4) every rv word at the strong-inversion value, (5) one node moved by 23 %, and (6) the PMOS table in + // the NMOS slot, each against the 1000 NMOS R2 points (and the cell centres for the single node), where the real table has 0.40 %. + var t : [4851]u32 = [0] ** 4851; + var i : usize = 0; + while (i < 4851) { + t[i] = TT_LG_N[i]; + i = i + 1; + } + var k : usize = 0; + while (k < 97) { + t[4754 + k] = 2 * TT_LG_N[4754 + k]; + k = k + 1; + } + const m1 : HoldL = hold_log(&t, &TT_R2_N, 1, 1000); + assert m1.rel9 > 0.99; + assert m1.rel9 < 1.0; + k = 0; + while (k < 97) { + t[4754 + k] = TT_LG_N[4754 + k]; + k = k + 1; + } + k = 1; + while (k <= 4753) { + t[k] = TT_LG_N[k] + 65536; + k = k + 1; + } + const m2 : HoldL = hold_log(&t, &TT_R2_N, 1, 1000); + assert m2.rel9 > 1.0; + assert m2.rel9 < 1.01; + k = 1; + while (k <= 4753) { + t[k] = TT_LG_N[k]; + k = k + 1; + } + k = 0; + while (k < 97) { + t[4754 + k] = 136533; + k = k + 1; + } + const m3 : HoldL = hold_log(&t, &TT_R2_N, 1, 1000); + assert m3.rel9 > 20.0; + k = 0; + while (k < 97) { + t[4754 + k] = 4959; + k = k + 1; + } + const m4 : HoldL = hold_log(&t, &TT_R2_N, 1, 1000); + assert m4.rel9 > 0.96; + assert m4.rel9 < 0.97; + k = 0; + while (k < 97) { + t[4754 + k] = TT_LG_N[4754 + k]; + k = k + 1; + } + t[1 + 40 * 49 + 10] = TT_LG_N[1 + 40 * 49 + 10] + 20000; + const m5 : HoldL = hold_log(&t, &TT_CEN_N, 2, 1000); + assert m5.rel9 > 0.054; + assert m5.rel9 < 0.055; + const m6 : HoldL = hold_log(&TT_LG_P, &TT_R2_N, 1, 1000); + assert m6.rel9 > 0.95; + assert m6.rel9 < 0.96; + // The real table, where the mutants are: 0.40 %. Every mutant is over 5 times the bar. + const good : HoldL = hold_log(&TT_LG_N, &TT_R2_N, 1, 1000); + assert good.rel9 < B_LOG_ISSUE; + assert m1.rel9 > 5.0 * B_LOG_ISSUE; + assert m2.rel9 > 5.0 * B_LOG_ISSUE; + assert m3.rel9 > 5.0 * B_LOG_ISSUE; + assert m4.rel9 > 5.0 * B_LOG_ISSUE; + assert m5.rel9 > 5.0 * B_LOG_ISSUE; + assert m6.rel9 > 5.0 * B_LOG_ISSUE; +} diff --git a/specs/analog/mos_psp103_data.t27 b/specs/analog/mos_psp103_data.t27 index 1f8129dd28..84c1c64cca 100644 --- a/specs/analog/mos_psp103_data.t27 +++ b/specs/analog/mos_psp103_data.t27 @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 ; specs/analog/mos_psp103_data.t27 -- the IHP SG13G2 PSP103 current tables, per corner, from ngspice: data and nothing else -; M3b of the analog emulation epic (#10486, issue #10516); M3c (#10777, sub-issue #10880) adds the charge tables, THE CHARGE TABLES below, for tt and ss; M3c-3 (#10882) adds them for ff, fs and sf. M3a (specs/analog/mos_table.t27) reads a 25 x 25 table by exact-integer +; M3b of the analog emulation epic (#10486, issue #10516); M3c (#10777, sub-issue #10880) adds the charge tables, THE CHARGE TABLES below, for tt and ss; M3c-3 (#10882) adds them for ff, fs and sf; M3c-2 (#10881) adds the log-domain current tables of tt, THE LOG-DOMAIN CURRENT TABLES below. M3a (specs/analog/mos_table.t27) reads a 25 x 25 table by exact-integer ; bilinear interpolation; this file holds the tables it reads when the device is the foundry's, Id(Vgs, Vds) of sg13_lv_nmos ; (W 1.0 um, L 0.45 um) and sg13_lv_pmos (W 3.0 um, L 0.45 um) for the five corners mos_tt, mos_ff, mos_ss, mos_fs and mos_sf, and the ; numbers the tests judge them by (held-out currents, the inverter's DC transfer, the inverter's transient). The functions are in @@ -21,6 +21,7 @@ ; capacitor and an NMOS gate on one node, the node's waveform of ngspice backward Euler on a 5 ps grid (GATE_BE) ; psp103_inv_be_500f_ss.cir, _ff, _fs, _sf (M3c-3) psp103_inv_be_500f.cir (tt) for the other four corners: the 500 fF waveform of ; ngspice backward Euler in that corner, the reference the charge tables of the corner are judged by +; psp103_idpa_tt.cir (M3c-2, #10881) the log-domain current tables of the tt corner, TT_LG_N and TT_LG_P, and 1000 held-out currents at cell centres of their grid ; Each is run as `IHP_PDK= IHP_OSDI= ngspice -b `; no deck holds a path. ngspice rounds each current ; to a table unit itself (nint in the deck) and prints it between "BEGIN name" and "END name"; the rows were wrapped onto lines ; below in print order, none changed or reordered. The pins (order-sensitive folds, as M3a pins its run) fail on any changed number. @@ -61,6 +62,22 @@ ; 5 ps on 25 fF is dt / C = 200 V/A again, so the current tables are the same words and the charge tables (Q / 500 fF) are scaled by 500 fF / 25 fF = 20. ; The node stays between 0.59 and 1.08 V, inside the tables' range. ; - +; THE LOG-DOMAIN CURRENT TABLES (M3c-2, issue #10881; tt only). TT_LG_N and TT_LG_P are a different table of the same two devices (sg13_lv_nmos W 1.0 um, sg13_lv_pmos +; W 3.0 um, L 0.45 um, IHP-Open-PDK 21133f219b1a6da10d803e345761e77415ceff40, mos_tt, 27 C), made to be read in the log domain by the integer exp of mos_table.t27: the linear +; tables above cannot give 1 % in weak inversion (a word is 298 pA and a chord over a 62.5 mV cell is 41 % above an exponential at the middle; the tests of mos_psp103.t27). +; A node is not Id but Id / F, as log2 in 1/65536 of an octave (16 fraction bits, an integer part under 2^5, so a word is under 2^21 and the reader's u64 interpolation +; holds), measured in IUNIT = 2^-8 of a linear-table word = 1 / (200 * 2^32) A = 1.164 pA. F is the Vds factor of weak inversion, F = 1 - exp(-Vds / s(Vgs)), handled apart by the +; reader; s is the scale of a gate voltage, s(Vgs) = sqrt(0.030^2 + (0.65 * max(Vgs - 0.23, 0))^2) volts, 30 mV (a little over kT/q) in weak inversion where F is exactly the +; diffusion factor, growing to 0.6 V and more in strong inversion where the channel is a resistor and F is nearly linear: it is the one number per gate node that makes +; Id / F nearly flat along Vds in both regimes (without it the first Vds cells are 5 % chords). The reader multiplies Vds by rv = nint(4096 / s), 97 words, the last 97 of each +; table; a table is [tag word 4294967295, 4753 words, 97 words] in one slice, so the one name `tn` of the Newton step carries it. The grid is 97 x 49 nodes, Vgs = ix * 15.625 mV +; (96 cells of 2^18 voltage units) and Vds = iy * 31.25 mV (48 cells of 2^19), 1.5 V on each axis, index ix * 49 + iy, the grid of the 25 x 25 tables refined 4 x along Vgs and +; 2 x along Vds (the curvature of ln Id along Vgs near threshold is what sets 15.6 mV: 31.2 mV gives 1.5 %, 15.6 mV 0.5 %). The column Vds = 0 holds the limit of Id / F there, +; s_eff * gds0, with gds0 the output conductance ngspice reports at Vds = 0 (the one number printed from the model, not from a current); every other node is nint of the formula +; from ngspice's Id at that node. Id below 1 IUNIT (1.164 pA) is held at 1 IUNIT; the PMOS is read at Vsg and Vsd. The 576 midpoints of the 62.5 mV cells, the held-out set of the +; linear tables, are NODES of this grid (a read there tests the rounding and nothing else), and the 1000 R2 points are off the nodes but not at the worst place of this grid, so +; TT_CEN_N and TT_CEN_P add 1000 currents in pA at CENTRES of its cells (R2 picks the cell), where a chord of THIS grid is worst. The pins fail on any changed number. +; - ; WHAT A PASS SAYS. The numbers in this file are the numbers the decks printed, in order (the pins), the five corners are in the order ; the foundry names them (ff above tt above ss in drive current for both devices; fs a fast NMOS with a slow PMOS, sf the reverse), and ; the units are the ones the header states. @@ -118,6 +135,19 @@ pub const OP_CGSOL_AF : u32 = 641; pub const OP_CGDOL_AF : u32 = 615; pub const OP_CJD_AF : u32 = 328; /// The same six numbers for the other three corners (M3c-3), in the order cdd, cdg, cgg, cgsol, cgdol, cjd, aF (decks psp103_q_ff.cir, _fs, _sf, block op_n). +; --- the format of the log-domain tables (M3c-2, #10881): the grid, the units, the scale of the Vds factor --------- +pub const LOG_GRID_G_UV : u32 = 15625; +pub const LOG_GRID_D_UV : u32 = 31250; +pub const LOG_NODES_G : u32 = 97; +pub const LOG_NODES_D : u32 = 49; +pub const LOG_FRAC_BITS : u32 = 16; +pub const LOG_FINE_BITS : u32 = 8; +pub const LOG_S_VT_UV : u32 = 30000; +pub const LOG_S_V0_UV : u32 = 230000; +pub const LOG_S_A_MILLI : u32 = 650; +pub const LOG_RV_NUM : u32 = 4096; +pub const LOG_CEN_COUNT : u32 = 1000; + pub const OP_FF_AF : [6]u32 = [111, 1458, 3621, 659, 631, 302]; pub const OP_FS_AF : [6]u32 = [95, 1427, 3551, 650, 623, 315]; pub const OP_SF_AF : [6]u32 = [69, 1376, 3425, 632, 607, 341]; @@ -146,6 +176,9 @@ pub const PIN_FF_Q : u64 = 0x1E6372A20D5D314A; pub const PIN_FS_Q : u64 = 0x45003C5379C10CC0; pub const PIN_SF_Q : u64 = 0x2029F1EF4D983675; +pub const PIN_TT_LG : u64 = 0x414B9D5DB65A4C34; +pub const PIN_TT_CEN : u64 = 0xBE8EC42434AE9194; + ; --- the numbers -------------------------------------------------------------------------------- ; --- corner mos_tt --------------------------------------------------------------------------- /// NMOS table, corner mos_tt: Id(Vgs = ix * 62.5 mV, Vds = iy * 62.5 mV) at index ix * 25 + iy, units of dt/C = 200 V/A times 2^-24 V (deck psp103_tab_tt.cir, block grid_n). @@ -2303,6 +2336,858 @@ pub const GATE_BE : [401]u32 = [ 12596472, 12596260, 12596052, 12595847, 12595645, 12595446, 12595250, 12595058, 12594868 ]; +; --- corner mos_tt, the log-domain current tables (M3c-2, #10881) --------------------------------- +/// NMOS log-domain current table, corner mos_tt, IHP-Open-PDK 21133f21, L 0.45 um, 27 C: the tag word (4294967295), then the 4753 words ix * 49 + iy of log2(Id / F) in 1/65536 octave over 2^-8 of a linear-table word (Vgs = ix * 15.625 mV, Vds = iy * 31.25 mV), then the 97 words rv = nint(4096 / s(Vgs)) at Vgs = ix * 15.625 mV (deck psp103_idpa_tt.cir, blocks lam_n and r_n). +pub const TT_LG_N : [4851]u32 = [ + 4294967295, 408635, 406768, 406804, 408484, 411585, 415497, 419717, 423951, 428098, 432100, 435948, 439617, 443128, + 446483, 449689, 452754, 455686, 458494, 461185, 463767, 466247, 468631, 470925, 473136, 475268, 477326, 479314, + 481237, 483099, 484904, 486653, 488352, 490002, 491607, 493168, 494690, 496172, 497619, 499031, 500412, 501763, + 503085, 504386, 505658, 506910, 508143, 509362, 510569, 511776, 453445, 451568, 451617, 453320, 456449, 460393, + 464644, 468912, 473092, 477124, 480995, 484697, 488235, 491614, 494841, 497927, 500878, 503703, 506410, 509006, + 511500, 513896, 516201, 518421, 520561, 522626, 524621, 526549, 528414, 530221, 531972, 533670, 535319, 536921, + 538479, 539994, 541470, 542909, 544311, 545680, 547017, 548324, 549603, 550856, 552084, 553290, 554478, 555646, + 556799, 498324, 496446, 496512, 498241, 501402, 505381, 509667, 513973, 518187, 522252, 526155, 529887, 533452, + 536856, 540108, 543216, 546188, 549033, 551758, 554372, 556880, 559291, 561609, 563842, 565993, 568068, 570072, + 572008, 573881, 575694, 577450, 579153, 580805, 582410, 583969, 585485, 586961, 588398, 589798, 591163, 592496, + 593796, 595068, 596311, 597527, 598719, 599889, 601037, 602167, 543268, 541395, 541481, 543239, 546434, 550451, + 554772, 559118, 563367, 567469, 571403, 575165, 578759, 582191, 585468, 588599, 591593, 594459, 597203, 599835, + 602360, 604787, 607120, 609366, 611530, 613617, 615631, 617578, 619460, 621281, 623046, 624756, 626414, 628024, + 629589, 631109, 632588, 634027, 635430, 636796, 638128, 639429, 640698, 641939, 643151, 644338, 645500, 646639, + 647757, 588272, 586410, 586518, 588306, 591536, 595591, 599949, 604334, 608621, 612757, 616724, 620518, 624141, + 627600, 630903, 634059, 637075, 639962, 642726, 645376, 647919, 650362, 652710, 654971, 657149, 659248, 661275, + 663233, 665125, 666956, 668730, 670448, 672115, 673732, 675303, 676830, 678314, 679759, 681165, 682535, 683871, + 685174, 686445, 687687, 688900, 690086, 691247, 692383, 693497, 633327, 631484, 631616, 633434, 636700, 640793, + 645190, 649613, 653937, 658108, 662108, 665933, 669585, 673072, 676400, 679580, 682619, 685527, 688311, 690980, + 693541, 696000, 698364, 700639, 702831, 704944, 706983, 708952, 710856, 712697, 714480, 716208, 717883, 719509, + 721088, 722621, 724113, 725563, 726975, 728351, 729692, 730999, 732274, 733519, 734735, 735924, 737086, 738223, + 739336, 678422, 676607, 676765, 678615, 681917, 686047, 690483, 694944, 699303, 703509, 707542, 711397, 715078, + 718592, 721946, 725149, 728211, 731139, 733943, 736630, 739208, 741684, 744064, 746354, 748559, 750685, 752737, + 754718, 756632, 758485, 760278, 762015, 763699, 765334, 766920, 768462, 769960, 771418, 772836, 774218, 775564, + 776877, 778157, 779407, 780627, 781819, 782985, 784125, 785240, 723541, 721766, 721956, 723837, 727173, 731341, + 735813, 740311, 744706, 748945, 753010, 756895, 760604, 764144, 767522, 770748, 773832, 776780, 779603, 782309, + 784904, 787395, 789790, 792094, 794313, 796452, 798516, 800508, 802434, 804297, 806100, 807846, 809540, 811183, + 812777, 814327, 815832, 817297, 818723, 820111, 821463, 822781, 824067, 825322, 826547, 827744, 828913, 830057, + 831176, 768656, 766944, 767169, 769083, 772453, 776655, 781163, 785696, 790124, 794395, 798490, 802403, 806139, + 809703, 813105, 816353, 819457, 822425, 825266, 827988, 830599, 833106, 835516, 837833, 840065, 842216, 844291, + 846295, 848231, 850104, 851916, 853672, 855374, 857025, 858628, 860185, 861698, 863170, 864602, 865996, 867354, + 868679, 869970, 871230, 872460, 873662, 874836, 875984, 877107, 813727, 812111, 812381, 814327, 817728, 821963, + 826504, 831068, 835527, 839828, 843950, 847889, 851649, 855236, 858659, 861927, 865049, 868035, 870893, 873631, + 876256, 878777, 881200, 883530, 885773, 887936, 890021, 892035, 893981, 895863, 897684, 899449, 901159, 902817, + 904427, 905991, 907511, 908989, 910427, 911828, 913192, 914522, 915818, 917083, 918318, 919524, 920703, 921855, + 922982, 858688, 857222, 857552, 859530, 862960, 867223, 871791, 876383, 880868, 885193, 889339, 893300, 897080, + 900687, 904128, 907413, 910551, 913552, 916424, 919175, 921814, 924346, 926780, 929121, 931374, 933546, 935641, + 937664, 939618, 941508, 943337, 945108, 946825, 948491, 950107, 951677, 953203, 954686, 956130, 957536, 958905, + 960239, 961540, 962810, 964049, 965259, 966442, 967598, 968729, 903438, 902207, 902618, 904632, 908084, 912367, + 916957, 921568, 926072, 930416, 934578, 938555, 942351, 945972, 949426, 952724, 955874, 958886, 961768, 964529, + 967176, 969718, 972160, 974509, 976770, 978949, 981051, 983080, 985040, 986936, 988770, 990547, 992269, 993940, + 995561, 997136, 998666, 1000154, 1001601, 1003011, 1004384, 1005722, 1007027, 1008300, 1009542, 1010756, 1011941, 1013100, + 1014234, 947822, 946956, 947486, 949536, 953003, 957296, 961895, 966515, 971027, 975378, 979548, 983532, 987334, + 990961, 994421, 997724, 1000880, 1003896, 1006783, 1009548, 1012200, 1014746, 1017191, 1019544, 1021809, 1023991, 1026096, + 1028128, 1030091, 1031990, 1033827, 1035607, 1037331, 1039004, 1040628, 1042205, 1043737, 1045227, 1046677, 1048088, 1049463, + 1050803, 1052109, 1053384, 1054628, 1055843, 1057030, 1058191, 1059326, 991611, 991305, 992010, 994102, 997571, 1001858, + 1006448, 1011060, 1015564, 1019907, 1024069, 1028046, 1031842, 1035462, 1038917, 1042215, 1045365, 1048378, 1051260, 1054022, + 1056670, 1059212, 1061655, 1064005, 1066267, 1068447, 1070549, 1072579, 1074541, 1076438, 1078273, 1080051, 1081774, 1083445, + 1085068, 1086643, 1088174, 1089663, 1091112, 1092522, 1093896, 1095235, 1096540, 1097814, 1099058, 1100272, 1101458, 1102618, + 1103752, 1034477, 1035011, 1035980, 1038122, 1041576, 1045834, 1050391, 1054969, 1059441, 1063753, 1067886, 1071835, 1075605, + 1079202, 1082635, 1085912, 1089043, 1092037, 1094903, 1097649, 1100282, 1102811, 1105240, 1107578, 1109828, 1111997, 1114090, + 1116110, 1118062, 1119950, 1121777, 1123547, 1125263, 1126927, 1128542, 1130111, 1131636, 1133119, 1134562, 1135967, 1137335, + 1138669, 1139970, 1141239, 1142477, 1143687, 1144869, 1146025, 1147155, 1076410, 1077979, 1079227, 1081373, 1084759, 1088939, + 1093422, 1097930, 1102335, 1106584, 1110658, 1114552, 1118270, 1121819, 1125206, 1128441, 1131533, 1134490, 1137321, 1140035, + 1142638, 1145138, 1147541, 1149852, 1152079, 1154225, 1156296, 1158296, 1160229, 1162098, 1163908, 1165661, 1167361, 1169010, + 1170610, 1172165, 1173677, 1175147, 1176577, 1177970, 1179328, 1180650, 1181941, 1183199, 1184428, 1185629, 1186802, 1187948, + 1189070, 1123762, 1123798, 1123555, 1124600, 1127289, 1131051, 1135275, 1139606, 1143875, 1148010, 1151983, 1155784, 1159416, + 1162885, 1166198, 1169363, 1172389, 1175286, 1178060, 1180720, 1183272, 1185724, 1188082, 1190351, 1192538, 1194646, 1196681, + 1198646, 1200546, 1202385, 1204165, 1205890, 1207563, 1209186, 1210762, 1212293, 1213782, 1215230, 1216640, 1218012, 1219350, + 1220654, 1221926, 1223168, 1224380, 1225564, 1226722, 1227853, 1228960, 1174964, 1171880, 1168853, 1167799, 1169094, 1171993, + 1175683, 1179667, 1183690, 1187635, 1191448, 1195109, 1198615, 1201966, 1205170, 1208234, 1211166, 1213973, 1216664, 1219245, + 1221723, 1224106, 1226397, 1228604, 1230732, 1232784, 1234765, 1236680, 1238532, 1240324, 1242061, 1243744, 1245376, 1246961, + 1248500, 1249996, 1251451, 1252867, 1254245, 1255588, 1256896, 1258172, 1259417, 1260633, 1261820, 1262980, 1264113, 1265222, + 1266307, 1225252, 1219517, 1213777, 1210361, 1209886, 1211566, 1214441, 1217870, 1221501, 1225150, 1228726, 1232189, 1235519, + 1238713, 1241772, 1244702, 1247508, 1250198, 1252779, 1255256, 1257637, 1259926, 1262130, 1264254, 1266303, 1268280, 1270191, + 1272038, 1273825, 1275556, 1277233, 1278860, 1280438, 1281971, 1283461, 1284909, 1286318, 1287689, 1289025, 1290327, 1291596, + 1292834, 1294042, 1295222, 1296375, 1297501, 1298603, 1299680, 1300735, 1272069, 1264807, 1257085, 1251557, 1249255, 1249536, + 1251389, 1254078, 1257163, 1260398, 1263648, 1266842, 1269944, 1272936, 1275815, 1278579, 1281233, 1283780, 1286227, 1288578, + 1290840, 1293017, 1295115, 1297138, 1299090, 1300976, 1302799, 1304563, 1306271, 1307926, 1309531, 1311088, 1312600, 1314069, + 1315497, 1316886, 1318238, 1319555, 1320838, 1322089, 1323309, 1324499, 1325661, 1326797, 1327906, 1328991, 1330052, 1331091, + 1332107, 1314569, 1306779, 1297928, 1290765, 1286797, 1285663, 1286401, 1288230, 1290652, 1293369, 1296207, 1299064, 1301883, + 1304632, 1307295, 1309866, 1312343, 1314727, 1317022, 1319231, 1321358, 1323409, 1325387, 1327296, 1329139, 1330922, 1332647, + 1334316, 1335934, 1337502, 1339024, 1340502, 1341937, 1343333, 1344690, 1346011, 1347298, 1348551, 1349773, 1350965, 1352128, + 1353264, 1354373, 1355456, 1356516, 1357552, 1358566, 1359559, 1360531, 1352760, 1345109, 1335864, 1327600, 1322233, 1319778, + 1319400, 1320324, 1322018, 1324150, 1326512, 1328976, 1331466, 1333934, 1336352, 1338706, 1340987, 1343193, 1345324, 1347379, + 1349364, 1351279, 1353129, 1354917, 1356645, 1358318, 1359937, 1361506, 1363028, 1364504, 1365937, 1367329, 1368683, 1369999, + 1371281, 1372528, 1373744, 1374929, 1376085, 1377213, 1378314, 1379389, 1380440, 1381468, 1382473, 1383456, 1384418, 1385361, + 1386284, 1386990, 1379849, 1370749, 1361887, 1355431, 1351810, 1350381, 1350411, 1351362, 1352877, 1354727, 1356764, 1358893, + 1361052, 1363204, 1365322, 1367394, 1369411, 1371369, 1373265, 1375101, 1376878, 1378597, 1380261, 1381873, 1383433, 1384946, + 1386413, 1387836, 1389219, 1390562, 1391867, 1393137, 1394372, 1395576, 1396748, 1397891, 1399006, 1400094, 1401156, 1402193, + 1403207, 1404198, 1405167, 1406115, 1407043, 1407952, 1408842, 1409715, 1417723, 1411254, 1402644, 1393612, 1386385, 1381780, + 1379398, 1378584, 1378810, 1379709, 1381037, 1382631, 1384382, 1386216, 1388086, 1389958, 1391811, 1393632, 1395412, 1397146, + 1398832, 1400470, 1402059, 1403600, 1405096, 1406546, 1407954, 1409321, 1410648, 1411938, 1413192, 1414412, 1415600, 1416756, + 1417883, 1418981, 1420053, 1421098, 1422118, 1423115, 1424089, 1425041, 1425972, 1426883, 1427775, 1428648, 1429504, 1430342, + 1431164, 1445416, 1439659, 1431727, 1422859, 1415160, 1409765, 1406547, 1404958, 1404499, 1404804, 1405619, 1406770, 1408139, + 1409643, 1411224, 1412843, 1414472, 1416094, 1417694, 1419265, 1420802, 1422302, 1423762, 1425184, 1426566, 1427910, 1429216, + 1430487, 1431722, 1432923, 1434093, 1435231, 1436340, 1437420, 1438474, 1439501, 1440503, 1441482, 1442438, 1443372, 1444285, + 1445178, 1446051, 1446907, 1447744, 1448564, 1449368, 1450156, 1450928, 1470488, 1465417, 1458236, 1449769, 1441867, 1435876, + 1431945, 1429662, 1428571, 1428315, 1428637, 1429358, 1430352, 1431526, 1432819, 1434184, 1435588, 1437009, 1438429, 1439838, + 1441226, 1442590, 1443925, 1445230, 1446503, 1447744, 1448954, 1450132, 1451279, 1452397, 1453486, 1454547, 1455582, 1456591, + 1457575, 1458536, 1459474, 1460389, 1461284, 1462159, 1463015, 1463852, 1464671, 1465473, 1466259, 1467029, 1467784, 1468524, + 1469250, 1493303, 1488862, 1482435, 1474516, 1466640, 1460239, 1455719, 1452825, 1451159, 1450383, 1450241, 1450551, 1451181, + 1452035, 1453044, 1454158, 1455339, 1456560, 1457802, 1459049, 1460291, 1461521, 1462734, 1463925, 1465092, 1466235, 1467351, + 1468442, 1469506, 1470545, 1471558, 1472547, 1473513, 1474455, 1475374, 1476273, 1477150, 1478008, 1478846, 1479666, 1480468, + 1481253, 1482022, 1482775, 1483513, 1484236, 1484945, 1485640, 1486323, 1514165, 1510288, 1504578, 1497282, 1489612, 1482977, + 1477992, 1474570, 1472389, 1471136, 1470562, 1470484, 1470767, 1471313, 1472047, 1472916, 1473878, 1474903, 1475968, 1477056, + 1478155, 1479253, 1480345, 1481426, 1482491, 1483538, 1484565, 1485572, 1486557, 1487521, 1488464, 1489385, 1490285, 1491165, + 1492025, 1492865, 1493687, 1494491, 1495277, 1496046, 1496799, 1497536, 1498258, 1498965, 1499658, 1500338, 1501005, 1501659, + 1502301, 1533334, 1529957, 1524904, 1518256, 1510924, 1504210, 1498881, 1495015, 1492378, 1490690, 1489717, 1489276, 1489233, + 1489484, 1489954, 1490586, 1491335, 1492168, 1493061, 1493993, 1494950, 1495920, 1496894, 1497866, 1498831, 1499786, 1500728, + 1501654, 1502564, 1503457, 1504332, 1505189, 1506028, 1506849, 1507653, 1508440, 1509210, 1509963, 1510701, 1511423, 1512131, + 1512824, 1513503, 1514168, 1514821, 1515461, 1516089, 1516705, 1517311, 1551022, 1548085, 1543625, 1537614, 1530707, 1524049, + 1518490, 1514261, 1511226, 1509149, 1507810, 1507032, 1506682, 1506654, 1506873, 1507276, 1507820, 1508468, 1509192, 1509972, + 1510790, 1511634, 1512493, 1513359, 1514227, 1515092, 1515950, 1516799, 1517636, 1518461, 1519271, 1520068, 1520849, 1521615, + 1522367, 1523103, 1523825, 1524532, 1525225, 1525904, 1526569, 1527221, 1527861, 1528488, 1529103, 1529707, 1530299, 1530881, + 1531452, 1567417, 1564864, 1560934, 1555527, 1549094, 1542601, 1536919, 1532408, 1529032, 1526606, 1524934, 1523845, 1523207, + 1522918, 1522897, 1523083, 1523429, 1523897, 1524458, 1525090, 1525772, 1526493, 1527239, 1528002, 1528775, 1529552, 1530329, + 1531102, 1531869, 1532627, 1533376, 1534114, 1534841, 1535555, 1536257, 1536946, 1537622, 1538285, 1538936, 1539575, 1540201, + 1540816, 1541419, 1542011, 1542591, 1543161, 1543721, 1544271, 1544811, 1582663, 1580450, 1576989, 1572141, 1566202, 1559958, + 1554250, 1549534, 1545873, 1543142, 1541167, 1539792, 1538888, 1538352, 1538105, 1538085, 1538242, 1538537, 1538941, 1539428, + 1539980, 1540579, 1541215, 1541877, 1542557, 1543248, 1543945, 1544645, 1545343, 1546038, 1546727, 1547409, 1548082, 1548747, + 1549401, 1550045, 1550678, 1551301, 1551912, 1552513, 1553103, 1553682, 1554251, 1554810, 1555359, 1555898, 1556428, 1556948, + 1557459, 1596897, 1594982, 1591936, 1587600, 1582153, 1576216, 1570566, 1565718, 1561828, 1558830, 1556584, 1554947, 1553796, + 1553030, 1552570, 1552353, 1552330, 1552460, 1552712, 1553060, 1553483, 1553966, 1554494, 1555057, 1555645, 1556252, 1556872, + 1557499, 1558131, 1558763, 1559394, 1560021, 1560643, 1561259, 1561868, 1562469, 1563061, 1563644, 1564218, 1564783, 1565339, + 1565885, 1566423, 1566951, 1567470, 1567980, 1568481, 1568975, 1569460, 1610219, 1608568, 1605888, 1602017, 1597045, 1591454, + 1585931, 1581021, 1576955, 1573731, 1571244, 1569369, 1567990, 1567010, 1566350, 1565948, 1565753, 1565725, 1565831, 1566044, + 1566344, 1566713, 1567137, 1567603, 1568102, 1568627, 1569170, 1569727, 1570292, 1570864, 1571437, 1572012, 1572584, 1573153, + 1573717, 1574276, 1574829, 1575374, 1575913, 1576444, 1576967, 1577482, 1577989, 1578488, 1578979, 1579462, 1579937, 1580405, + 1580866, 1622730, 1621312, 1618957, 1615504, 1610982, 1605754, 1600415, 1595505, 1591315, 1587904, 1585206, 1583116, 1581527, + 1580347, 1579500, 1578923, 1578565, 1578386, 1578352, 1578437, 1578617, 1578876, 1579197, 1579569, 1579981, 1580425, 1580894, + 1581381, 1581882, 1582394, 1582912, 1583433, 1583957, 1584480, 1585001, 1585519, 1586033, 1586543, 1587047, 1587545, 1588036, + 1588521, 1589000, 1589471, 1589936, 1590393, 1590844, 1591288, 1591725, 1634509, 1633298, 1631232, 1628153, 1624051, 1619193, + 1614078, 1609223, 1604959, 1601399, 1598518, 1596235, 1594455, 1593091, 1592068, 1591326, 1590815, 1590492, 1590324, 1590284, + 1590350, 1590501, 1590723, 1591004, 1591330, 1591695, 1592091, 1592510, 1592948, 1593400, 1593863, 1594333, 1594809, 1595287, + 1595766, 1596244, 1596721, 1597195, 1597665, 1598131, 1598593, 1599049, 1599499, 1599945, 1600384, 1600817, 1601244, 1601665, + 1602081, 1645626, 1644599, 1642789, 1640046, 1636332, 1631838, 1626976, 1622222, 1617930, 1614258, 1611224, 1608770, 1606816, + 1605282, 1604096, 1603199, 1602541, 1602082, 1601787, 1601628, 1601582, 1601631, 1601757, 1601948, 1602192, 1602479, 1602803, + 1603155, 1603531, 1603925, 1604334, 1604754, 1605182, 1605615, 1606053, 1606492, 1606932, 1607371, 1607809, 1608243, 1608675, + 1609103, 1609527, 1609947, 1610362, 1610772, 1611176, 1611576, 1611970, 1656141, 1655280, 1653697, 1651256, 1647898, 1643755, + 1639162, 1634548, 1630269, 1626523, 1623364, 1620761, 1618650, 1616958, 1615621, 1614579, 1613784, 1613194, 1612777, 1612504, + 1612352, 1612301, 1612334, 1612438, 1612601, 1612814, 1613067, 1613354, 1613668, 1614006, 1614361, 1614731, 1615112, 1615502, + 1615898, 1616299, 1616703, 1617108, 1617513, 1617917, 1618320, 1618721, 1619119, 1619513, 1619905, 1620292, 1620675, 1621053, + 1621428, 1666104, 1665391, 1664012, 1661841, 1658809, 1655001, 1650685, 1646239, 1642012, 1638225, 1634968, 1632238, 1629987, + 1628153, 1626675, 1625497, 1624573, 1623861, 1623328, 1622946, 1622691, 1622544, 1622488, 1622508, 1622592, 1622731, 1622915, + 1623138, 1623393, 1623674, 1623977, 1624298, 1624633, 1624980, 1625336, 1625698, 1626066, 1626437, 1626811, 1627185, 1627559, + 1627933, 1628305, 1628676, 1629044, 1629409, 1629770, 1630129, 1630484, 1675563, 1674984, 1673789, 1671860, 1669124, 1665632, + 1661595, 1657338, 1653193, 1649398, 1646071, 1643235, 1640861, 1638898, 1637290, 1635986, 1634939, 1634111, 1633468, 1632982, + 1632629, 1632390, 1632247, 1632185, 1632194, 1632261, 1632378, 1632538, 1632734, 1632960, 1633211, 1633484, 1633774, 1634078, + 1634394, 1634719, 1635051, 1635389, 1635731, 1636075, 1636422, 1636769, 1637116, 1637462, 1637807, 1638150, 1638492, 1638830, + 1639166, 1684568, 1684109, 1683078, 1681367, 1678900, 1675703, 1671939, 1667885, 1663849, 1660075, 1656703, 1653782, 1651301, + 1649221, 1647495, 1646073, 1644912, 1643974, 1643226, 1642641, 1642194, 1641866, 1641639, 1641499, 1641433, 1641430, 1641482, + 1641581, 1641719, 1641891, 1642091, 1642316, 1642561, 1642823, 1643099, 1643387, 1643684, 1643989, 1644299, 1644615, 1644933, + 1645254, 1645576, 1645899, 1646221, 1646543, 1646864, 1647183, 1647500, 1693141, 1692791, 1691909, 1690394, 1688173, 1685250, + 1681751, 1677909, 1674002, 1670274, 1666883, 1663898, 1661327, 1659144, 1657309, 1655778, 1654511, 1653469, 1652623, 1651943, + 1651406, 1650993, 1650685, 1650469, 1650331, 1650261, 1650250, 1650288, 1650370, 1650489, 1650639, 1650817, 1651018, 1651238, + 1651475, 1651726, 1651988, 1652260, 1652540, 1652826, 1653117, 1653412, 1653709, 1654008, 1654309, 1654609, 1654910, 1655210, + 1655509, 1701321, 1701071, 1700322, 1698985, 1696987, 1694318, 1691073, 1687445, 1683684, 1680025, 1676636, 1673607, 1670962, + 1668690, 1666757, 1665126, 1663759, 1662621, 1661680, 1660910, 1660288, 1659793, 1659408, 1659118, 1658911, 1658776, 1658702, + 1658682, 1658709, 1658776, 1658877, 1659009, 1659166, 1659345, 1659544, 1659758, 1659986, 1660226, 1660475, 1660732, 1660995, + 1661264, 1661537, 1661813, 1662091, 1662371, 1662651, 1662932, 1663213, 1709140, 1708980, 1708352, 1707177, 1705381, 1702947, + 1699942, 1696528, 1692923, 1689352, 1685987, 1682932, 1680229, 1677880, 1675860, 1674137, 1672678, 1671448, 1670419, 1669564, + 1668860, 1668286, 1667827, 1667467, 1667193, 1666993, 1666860, 1666783, 1666755, 1666771, 1666825, 1666911, 1667025, 1667164, + 1667324, 1667503, 1667697, 1667904, 1668123, 1668351, 1668587, 1668830, 1669078, 1669331, 1669587, 1669846, 1670107, 1670369, + 1670632, 1716625, 1716547, 1716030, 1715000, 1713388, 1711170, 1708393, 1705188, 1701747, 1698278, 1694955, 1691893, 1689148, + 1686733, 1684636, 1682831, 1681286, 1679971, 1678859, 1677922, 1677140, 1676492, 1675961, 1675532, 1675193, 1674932, 1674740, + 1674607, 1674528, 1674494, 1674500, 1674542, 1674614, 1674713, 1674835, 1674978, 1675138, 1675313, 1675502, 1675701, 1675911, + 1676128, 1676352, 1676582, 1676816, 1677054, 1677295, 1677538, 1677783, 1723791, 1723788, 1723372, 1722475, 1721031, 1719012, + 1716449, 1713448, 1710175, 1706820, 1703555, 1700501, 1697729, 1695263, 1693099, 1691219, 1689596, 1688202, 1687011, 1685998, + 1685142, 1684422, 1683823, 1683328, 1682927, 1682606, 1682357, 1682171, 1682040, 1681957, 1681918, 1681915, 1681946, 1682006, + 1682091, 1682199, 1682325, 1682469, 1682628, 1682799, 1682981, 1683173, 1683373, 1683580, 1683792, 1684010, 1684231, 1684456, + 1684683, 1730666, 1730733, 1730408, 1729631, 1728341, 1726505, 1724142, 1721337, 1718233, 1715001, 1711807, 1708778, 1705992, + 1703487, 1701267, 1699320, 1697626, 1696159, 1694895, 1693809, 1692882, 1692094, 1691429, 1690872, 1690410, 1690032, 1689728, + 1689489, 1689308, 1689178, 1689093, 1689048, 1689038, 1689059, 1689108, 1689181, 1689275, 1689387, 1689516, 1689659, 1689815, + 1689981, 1690157, 1690341, 1690532, 1690728, 1690930, 1691136, 1691346, 1737266, 1737395, 1737155, 1736488, 1735339, 1733671, + 1731495, 1728878, 1725941, 1722839, 1719728, 1716736, 1713950, 1711417, 1709151, 1707146, 1705388, 1703853, 1702520, 1701367, + 1700373, 1699521, 1698793, 1698175, 1697655, 1697221, 1696863, 1696574, 1696344, 1696168, 1696039, 1695952, 1695903, 1695886, + 1695899, 1695937, 1695998, 1696080, 1696180, 1696295, 1696424, 1696565, 1696717, 1696878, 1697048, 1697224, 1697406, 1697593, + 1697785, 1743612, 1743800, 1743636, 1743071, 1742049, 1740537, 1738535, 1736096, 1733324, 1730355, 1727336, 1724393, 1721619, + 1719069, 1716767, 1714713, 1712896, 1711300, 1709904, 1708687, 1707630, 1706715, 1705927, 1705251, 1704675, 1704187, 1703778, + 1703439, 1703163, 1702942, 1702770, 1702642, 1702553, 1702499, 1702476, 1702481, 1702510, 1702561, 1702632, 1702719, 1702822, + 1702938, 1703067, 1703205, 1703353, 1703508, 1703671, 1703840, 1704014, 1749722, 1749963, 1749870, 1749396, 1748492, 1747123, + 1745283, 1743014, 1740401, 1737567, 1734646, 1731763, 1729012, 1726456, 1724126, 1722031, 1720164, 1718511, 1717056, 1715779, + 1714663, 1713689, 1712844, 1712112, 1711482, 1710943, 1710484, 1710097, 1709775, 1709509, 1709295, 1709127, 1709000, 1708910, + 1708852, 1708823, 1708821, 1708842, 1708884, 1708944, 1709021, 1709112, 1709217, 1709333, 1709459, 1709594, 1709737, 1709888, + 1710044, 1755594, 1755885, 1755858, 1755469, 1754674, 1753436, 1751747, 1749638, 1747181, 1744482, 1741665, 1738850, 1736133, + 1733582, 1731234, 1729105, 1727194, 1725491, 1723982, 1722650, 1721477, 1720449, 1719549, 1718764, 1718083, 1717493, 1716987, + 1716554, 1716187, 1715879, 1715624, 1715417, 1715253, 1715126, 1715035, 1714973, 1714940, 1714931, 1714945, 1714978, 1715029, + 1715096, 1715177, 1715271, 1715376, 1715491, 1715614, 1715746, 1715885, 1761263, 1761599, 1761632, 1761321, 1760625, 1759509, + 1757960, 1756002, 1753694, 1751128, 1748419, 1745679, 1743004, 1740466, 1738109, 1735954, 1734006, 1732259, 1730700, 1729316, + 1728091, 1727010, 1726058, 1725223, 1724492, 1723855, 1723301, 1722823, 1722413, 1722064, 1721770, 1721524, 1721323, 1721162, + 1721037, 1720943, 1720879, 1720841, 1720827, 1720833, 1720859, 1720901, 1720959, 1721031, 1721114, 1721209, 1721314, 1721427, + 1721548, 1766737, 1767115, 1767202, 1766964, 1766359, 1765354, 1763936, 1762120, 1759954, 1757520, 1754919, 1752259, 1749635, + 1747118, 1744760, 1742587, 1740608, 1738821, 1737218, 1735787, 1734513, 1733382, 1732381, 1731497, 1730718, 1730035, 1729436, + 1728915, 1728463, 1728074, 1727740, 1727458, 1727221, 1727025, 1726867, 1726742, 1726648, 1726581, 1726539, 1726519, 1726519, + 1726537, 1726572, 1726622, 1726684, 1726759, 1726844, 1726939, 1727042, 1772016, 1772433, 1772571, 1772399, 1771879, 1770978, + 1769681, 1767998, 1765968, 1763663, 1761172, 1758597, 1756029, 1753542, 1751191, 1749006, 1747002, 1745182, 1743540, 1742065, + 1740745, 1739568, 1738520, 1737590, 1736766, 1736038, 1735397, 1734834, 1734341, 1733913, 1733542, 1733223, 1732951, 1732722, + 1732532, 1732376, 1732252, 1732157, 1732087, 1732041, 1732017, 1732011, 1732023, 1732051, 1732093, 1732147, 1732213, 1732290, + 1732376, 1777118, 1777570, 1777756, 1777646, 1777203, 1776398, 1775215, 1773656, 1771756, 1769575, 1767195, 1764707, 1762201, + 1759751, 1757413, 1755224, 1753202, 1751353, 1749676, 1748161, 1746800, 1745579, 1744487, 1743513, 1742646, 1741876, 1741193, + 1740590, 1740058, 1739591, 1739184, 1738830, 1738524, 1738262, 1738040, 1737854, 1737701, 1737578, 1737482, 1737410, 1737361, + 1737332, 1737321, 1737327, 1737348, 1737383, 1737430, 1737488, 1737557, 1782042, 1782529, 1782759, 1782705, 1782335, 1781620, + 1780541, 1779100, 1777324, 1775264, 1772992, 1770594, 1768154, 1765747, 1763430, 1761243, 1759209, 1757337, 1755629, 1754080, + 1752680, 1751419, 1750286, 1749271, 1748362, 1747551, 1746829, 1746187, 1745617, 1745114, 1744671, 1744283, 1743944, 1743650, + 1743397, 1743182, 1743000, 1742850, 1742727, 1742631, 1742557, 1742505, 1742472, 1742457, 1742457, 1742472, 1742500, 1742541, + 1742592, 1786817, 1787335, 1787606, 1787605, 1787301, 1786668, 1785687, 1784357, 1782697, 1780753, 1778588, 1776281, 1773911, + 1771551, 1769260, 1767081, 1765040, 1763151, 1761417, 1759836, 1758400, 1757102, 1755930, 1754875, 1753928, 1753078, 1752317, + 1751637, 1751031, 1750493, 1750015, 1749593, 1749222, 1748897, 1748614, 1748370, 1748160, 1747983, 1747835, 1747713, 1747615, + 1747540, 1747485, 1747448, 1747429, 1747424, 1747434, 1747456, 1747490, 1791434, 1791981, 1792289, 1792337, 1792096, 1791540, + 1790650, 1789423, 1787874, 1786041, 1783981, 1781765, 1779468, 1777160, 1774901, 1772736, 1770694, 1768791, 1767036, 1765427, + 1763960, 1762627, 1761419, 1760328, 1759343, 1758456, 1757659, 1756943, 1756302, 1755729, 1755218, 1754764, 1754361, 1754006, + 1753693, 1753421, 1753184, 1752980, 1752806, 1752660, 1752539, 1752441, 1752364, 1752307, 1752267, 1752243, 1752234, 1752239, + 1752255, 1795912, 1796485, 1796829, 1796922, 1796739, 1796254, 1795449, 1794319, 1792874, 1791148, 1789190, 1787065, 1784842, + 1782590, 1780367, 1778221, 1776182, 1774272, 1772499, 1770866, 1769371, 1768006, 1766765, 1765638, 1764618, 1763696, 1762863, + 1762113, 1761438, 1760832, 1760288, 1759803, 1759369, 1758984, 1758644, 1758343, 1758079, 1757850, 1757651, 1757481, 1757337, + 1757216, 1757118, 1757040, 1756980, 1756937, 1756910, 1756896, 1756896, 1800251, 1800849, 1801226, 1801362, 1801232, 1800813, + 1800088, 1799048, 1797703, 1796079, 1794220, 1792184, 1790037, 1787843, 1785661, 1783538, 1781508, 1779594, 1777808, 1776155, + 1774634, 1773241, 1771969, 1770810, 1769756, 1768801, 1767935, 1767151, 1766443, 1765805, 1765230, 1764714, 1764251, 1763837, + 1763468, 1763141, 1762851, 1762596, 1762373, 1762179, 1762012, 1761870, 1761750, 1761652, 1761572, 1761510, 1761464, 1761434, + 1761416, 1804462, 1805083, 1805490, 1805665, 1805585, 1805229, 1804577, 1803622, 1802371, 1800844, 1799081, 1797134, 1795062, + 1792929, 1790791, 1788696, 1786679, 1784766, 1782971, 1781302, 1779759, 1778339, 1777038, 1775849, 1774765, 1773777, 1772879, + 1772064, 1771324, 1770655, 1770050, 1769504, 1769012, 1768571, 1768174, 1767820, 1767505, 1767225, 1766978, 1766761, 1766571, + 1766407, 1766267, 1766148, 1766049, 1765968, 1765905, 1765856, 1765823, 1808544, 1809187, 1809622, 1809834, 1809801, 1809502, + 1808920, 1808045, 1806882, 1805448, 1803778, 1801917, 1799923, 1797852, 1795761, 1793697, 1791697, 1789789, 1787990, 1786307, + 1784746, 1783303, 1781976, 1780759, 1779645, 1778627, 1777699, 1776853, 1776084, 1775385, 1774751, 1774176, 1773656, 1773187, + 1772764, 1772385, 1772044, 1771740, 1771469, 1771229, 1771018, 1770833, 1770672, 1770533, 1770415, 1770316, 1770234, 1770169, + 1770119, 1812519, 1813181, 1813643, 1813889, 1813900, 1813654, 1813137, 1812337, 1811257, 1809911, 1808329, 1806553, 1804635, + 1802628, 1800586, 1798556, 1796578, 1794678, 1792877, 1791185, 1789607, 1788144, 1786794, 1785550, 1784409, 1783362, 1782405, + 1781530, 1780732, 1780004, 1779341, 1778739, 1778192, 1777696, 1777248, 1776843, 1776477, 1776149, 1775856, 1775593, 1775360, + 1775154, 1774973, 1774815, 1774677, 1774560, 1774461, 1774378, 1774311, 1816365, 1817046, 1817533, 1817811, 1817863, 1817668, + 1817211, 1816482, 1815481, 1814220, 1812724, 1811031, 1809187, 1807245, 1805255, 1803263, 1801309, 1799422, 1797623, 1795925, + 1794335, 1792855, 1791483, 1790216, 1789049, 1787976, 1786991, 1786089, 1785263, 1784508, 1783818, 1783189, 1782616, 1782095, + 1781621, 1781191, 1780802, 1780451, 1780135, 1779851, 1779597, 1779370, 1779169, 1778991, 1778836, 1778700, 1778584, 1778484, + 1778401, 1820115, 1820814, 1821324, 1821632, 1821721, 1821574, 1821173, 1820511, 1819584, 1818402, 1816988, 1815375, 1813606, + 1811728, 1809791, 1807840, 1805913, 1804041, 1802248, 1800547, 1798947, 1797451, 1796061, 1794772, 1793581, 1792484, 1791473, + 1790545, 1789692, 1788910, 1788194, 1787539, 1786941, 1786394, 1785896, 1785442, 1785030, 1784656, 1784318, 1784012, 1783737, + 1783490, 1783270, 1783073, 1782899, 1782746, 1782612, 1782496, 1782397, 1823759, 1824473, 1825005, 1825341, 1825466, 1825363, + 1825016, 1824416, 1823559, 1822454, 1821118, 1819583, 1817887, 1816074, 1814191, 1812281, 1810384, 1808532, 1806747, 1805046, + 1803439, 1801932, 1800524, 1799216, 1798004, 1796883, 1795848, 1794894, 1794017, 1793210, 1792468, 1791788, 1791165, 1790594, + 1790072, 1789596, 1789161, 1788765, 1788405, 1788078, 1787783, 1787516, 1787276, 1787061, 1786869, 1786698, 1786547, 1786415, + 1786299, 1827295, 1828025, 1828577, 1828939, 1829098, 1829036, 1828740, 1828198, 1827408, 1826376, 1825116, 1823656, 1822031, + 1820283, 1818455, 1816590, 1814726, 1812895, 1811121, 1809424, 1807813, 1806296, 1804875, 1803550, 1802317, 1801175, 1800117, + 1799140, 1798239, 1797408, 1796642, 1795938, 1795291, 1794697, 1794152, 1793653, 1793196, 1792778, 1792397, 1792051, 1791735, + 1791449, 1791190, 1790957, 1790747, 1790559, 1790391, 1790243, 1790112, 1830747, 1831491, 1832062, 1832449, 1832639, 1832616, + 1832367, 1831881, 1831154, 1830189, 1829002, 1827614, 1826059, 1824375, 1822602, 1820782, 1818953, 1817146, 1815387, 1813695, + 1812083, 1810558, 1809125, 1807785, 1806534, 1805372, 1804293, 1803293, 1802369, 1801515, 1800726, 1799999, 1799329, 1798712, + 1798145, 1797623, 1797145, 1796706, 1796305, 1795938, 1795603, 1795298, 1795020, 1794769, 1794541, 1794336, 1794152, 1793988, + 1793841, 1834104, 1834861, 1835450, 1835860, 1836080, 1836094, 1835889, 1835455, 1834787, 1833888, 1832769, 1831452, 1829965, + 1828344, 1826627, 1824853, 1823060, 1821280, 1819537, 1817854, 1816243, 1814714, 1813271, 1811917, 1810651, 1809470, 1808371, + 1807351, 1806405, 1805529, 1804718, 1803969, 1803276, 1802638, 1802049, 1801506, 1801007, 1800547, 1800126, 1799739, 1799385, + 1799061, 1798766, 1798496, 1798252, 1798030, 1797830, 1797650, 1797488, 1837378, 1838147, 1838753, 1839185, 1839431, 1839480, + 1839316, 1838932, 1838320, 1837483, 1836430, 1835181, 1833760, 1832200, 1830539, 1828813, 1827057, 1825305, 1823582, 1821909, + 1820302, 1818770, 1817320, 1815955, 1814674, 1813476, 1812359, 1811320, 1810353, 1809456, 1808624, 1807853, 1807139, 1806479, + 1805869, 1805306, 1804786, 1804307, 1803866, 1803460, 1803087, 1802745, 1802432, 1802145, 1801884, 1801645, 1801429, 1801233, + 1801056, 1840569, 1841349, 1841970, 1842422, 1842695, 1842775, 1842652, 1842313, 1841754, 1840976, 1839987, 1838802, 1837446, + 1835947, 1834341, 1832662, 1830946, 1829224, 1827522, 1825863, 1824261, 1822729, 1821274, 1819899, 1818605, 1817393, 1816259, + 1815201, 1814215, 1813298, 1812445, 1811654, 1810920, 1810239, 1809609, 1809026, 1808486, 1807987, 1807527, 1807102, 1806711, + 1806351, 1806020, 1805717, 1805439, 1805184, 1804952, 1804741, 1804549, 1843676, 1844467, 1845102, 1845573, 1845871, 1845982, + 1845895, 1845601, 1845092, 1844370, 1843441, 1842319, 1841025, 1839586, 1838035, 1836404, 1834728, 1833038, 1831359, 1829715, + 1828121, 1826591, 1825133, 1823750, 1822446, 1821220, 1820071, 1818995, 1817992, 1817056, 1816184, 1815373, 1814619, 1813919, + 1813269, 1812666, 1812108, 1811590, 1811111, 1810668, 1810259, 1809882, 1809534, 1809213, 1808919, 1808649, 1808401, 1808175, + 1807969, 1846712, 1847513, 1848162, 1848651, 1848971, 1849111, 1849059, 1848806, 1848345, 1847677, 1846805, 1845742, 1844508, + 1843128, 1841631, 1840049, 1838414, 1836756, 1835102, 1833475, 1831892, 1830365, 1828905, 1827517, 1826204, 1824965, 1823802, + 1822711, 1821690, 1820737, 1819847, 1819017, 1818244, 1817525, 1816856, 1816234, 1815657, 1815121, 1814623, 1814163, 1813736, + 1813341, 1812977, 1812640, 1812330, 1812044, 1811781, 1811540, 1811319, 1849665, 1850475, 1851137, 1851643, 1851985, 1852152, + 1852133, 1851920, 1851504, 1850886, 1850070, 1849065, 1847889, 1846566, 1845123, 1843589, 1841995, 1840372, 1838745, 1837136, + 1835565, 1834045, 1832585, 1831194, 1829873, 1828624, 1827448, 1826343, 1825306, 1824336, 1823429, 1822581, 1821790, 1821053, + 1820366, 1819726, 1819130, 1818577, 1818062, 1817584, 1817140, 1816729, 1816348, 1815995, 1815669, 1815368, 1815090, 1814834, + 1814599, 1852547, 1853366, 1854040, 1854562, 1854925, 1855117, 1855130, 1854953, 1854581, 1854011, 1853247, 1852298, 1851179, + 1849911, 1848520, 1847035, 1845483, 1843895, 1842296, 1840708, 1839151, 1837638, 1836181, 1834787, 1833460, 1832203, 1831016, + 1829898, 1828847, 1827861, 1826937, 1826073, 1825265, 1824510, 1823805, 1823147, 1822535, 1821963, 1821432, 1820937, 1820477, + 1820049, 1819652, 1819283, 1818942, 1818626, 1818334, 1818064, 1817814, 1855372, 1856199, 1856884, 1857421, 1857803, 1858019, + 1858061, 1857920, 1857588, 1857064, 1856350, 1855453, 1854389, 1853175, 1851836, 1850398, 1848888, 1847336, 1845765, 1844199, + 1842657, 1841154, 1839701, 1838307, 1836975, 1835711, 1834513, 1833383, 1832319, 1831318, 1830379, 1829498, 1828673, 1827902, + 1827180, 1826505, 1825875, 1825287, 1824739, 1824228, 1823751, 1823307, 1822895, 1822511, 1822154, 1821823, 1821516, 1821232, + 1820969, 1858113, 1858947, 1859642, 1860194, 1860594, 1860834, 1860904, 1860796, 1860503, 1860023, 1859357, 1858512, 1857501, + 1856340, 1855051, 1853660, 1852194, 1850677, 1849137, 1847595, 1846070, 1844578, 1843131, 1841738, 1840404, 1839134, 1837928, + 1836787, 1835711, 1834696, 1833743, 1832847, 1832007, 1831219, 1830481, 1829791, 1829144, 1828540, 1827976, 1827448, 1826956, + 1826497, 1826069, 1825670, 1825299, 1824954, 1824633, 1824335, 1824059, 1860811, 1861651, 1862357, 1862921, 1863338, 1863600, + 1863696, 1863619, 1863363, 1862924, 1862304, 1861508, 1860547, 1859436, 1858197, 1856853, 1855428, 1853949, 1852439, 1850921, + 1849414, 1847935, 1846495, 1845104, 1843769, 1842494, 1841281, 1840131, 1839043, 1838016, 1837049, 1836139, 1835283, 1834480, + 1833726, 1833020, 1832358, 1831738, 1831157, 1830614, 1830107, 1829632, 1829189, 1828776, 1828390, 1828030, 1827696, 1827384, + 1827094, 1863438, 1864285, 1864999, 1865576, 1866010, 1866291, 1866413, 1866366, 1866145, 1865746, 1865169, 1864420, 1863507, + 1862447, 1861256, 1859958, 1858575, 1857133, 1855654, 1854162, 1852675, 1851210, 1849779, 1848392, 1847057, 1845779, 1844560, + 1843401, 1842303, 1841265, 1840285, 1839361, 1838492, 1837674, 1836905, 1836184, 1835506, 1834871, 1834276, 1833718, 1833195, + 1832706, 1832248, 1831820, 1831420, 1831047, 1830698, 1830373, 1830071, 1866008, 1866861, 1867584, 1868173, 1868621, 1868922, + 1869068, 1869049, 1868861, 1868500, 1867965, 1867260, 1866395, 1865383, 1864239, 1862986, 1861645, 1860240, 1858794, 1857328, + 1855862, 1854411, 1852990, 1851610, 1850276, 1848996, 1847772, 1846607, 1845500, 1844451, 1843459, 1842523, 1841640, 1840808, + 1840025, 1839289, 1838597, 1837947, 1837336, 1836764, 1836226, 1835723, 1835251, 1834809, 1834395, 1834008, 1833646, 1833308, + 1832993, 1868507, 1869365, 1870096, 1870696, 1871160, 1871480, 1871648, 1871657, 1871500, 1871175, 1870680, 1870019, 1869200, + 1868234, 1867137, 1865929, 1864629, 1863262, 1861848, 1860410, 1858965, 1857532, 1856123, 1854749, 1853419, 1852138, 1850911, + 1849740, 1848625, 1847567, 1846565, 1845617, 1844721, 1843876, 1843080, 1842330, 1841624, 1840960, 1840335, 1839748, 1839197, + 1838680, 1838194, 1837739, 1837311, 1836911, 1836536, 1836185, 1835857, 1870963, 1871826, 1872565, 1873176, 1873653, 1873990, + 1874180, 1874214, 1874088, 1873797, 1873340, 1872721, 1871945, 1871024, 1869973, 1868807, 1867549, 1866219, 1864838, 1863427, + 1862006, 1860590, 1859194, 1857828, 1856502, 1855223, 1853993, 1852817, 1851695, 1850629, 1849616, 1848657, 1847750, 1846892, + 1846083, 1845320, 1844600, 1843922, 1843284, 1842683, 1842119, 1841587, 1841088, 1840619, 1840179, 1839766, 1839378, 1839014, + 1838674, 1873363, 1874231, 1874977, 1875597, 1876087, 1876441, 1876651, 1876710, 1876612, 1876354, 1875934, 1875355, 1874621, + 1873744, 1872736, 1871613, 1870395, 1869102, 1867755, 1866373, 1864975, 1863578, 1862195, 1860839, 1859519, 1858241, 1857011, + 1855831, 1854703, 1853629, 1852608, 1851638, 1850720, 1849851, 1849029, 1848253, 1847521, 1846830, 1846178, 1845564, 1844986, + 1844442, 1843929, 1843447, 1842994, 1842568, 1842168, 1841792, 1841440, 1875721, 1876593, 1877345, 1877975, 1878477, 1878846, + 1879075, 1879157, 1879087, 1878860, 1878475, 1877933, 1877241, 1876405, 1875439, 1874359, 1873180, 1871924, 1870610, 1869256, + 1867883, 1866505, 1865137, 1863792, 1862478, 1861203, 1859973, 1858790, 1857658, 1856577, 1855547, 1854569, 1853640, 1852759, + 1851926, 1851138, 1850393, 1849689, 1849024, 1848398, 1847806, 1847249, 1846724, 1846229, 1845763, 1845325, 1844912, 1844524, + 1844160, 1878022, 1878897, 1879656, 1880295, 1880808, 1881192, 1881440, 1881544, 1881500, 1881302, 1880951, 1880446, 1879792, + 1878998, 1878073, 1877033, 1875894, 1874675, 1873394, 1872070, 1870721, 1869363, 1868012, 1866678, 1865372, 1864101, 1862872, + 1861688, 1860552, 1859465, 1858428, 1857441, 1856502, 1855612, 1854767, 1853967, 1853210, 1852494, 1851818, 1851178, 1850575, + 1850005, 1849467, 1848960, 1848482, 1848031, 1847607, 1847207, 1846831, 1880281, 1881160, 1881925, 1882571, 1883096, 1883494, + 1883759, 1883884, 1883864, 1883695, 1883376, 1882906, 1882290, 1881534, 1880650, 1879650, 1878549, 1877366, 1876118, 1874823, + 1873500, 1872163, 1870828, 1869507, 1868210, 1866944, 1865717, 1864532, 1863393, 1862302, 1861258, 1860263, 1859316, 1858415, + 1857560, 1856749, 1855981, 1855253, 1854565, 1853913, 1853297, 1852715, 1852165, 1851646, 1851156, 1850694, 1850257, 1849846, + 1849458, 1882483, 1883365, 1884135, 1884790, 1885325, 1885736, 1886017, 1886163, 1886167, 1886026, 1885737, 1885301, 1884721, + 1884004, 1883158, 1882197, 1881135, 1879987, 1878773, 1877508, 1876210, 1874895, 1873578, 1872271, 1870983, 1869724, 1868500, + 1867316, 1866175, 1865080, 1864031, 1863029, 1862073, 1861164, 1860299, 1859478, 1858699, 1857960, 1857260, 1856597, 1855969, + 1855376, 1854814, 1854283, 1853781, 1853307, 1852860, 1852437, 1852038, 1884643, 1885528, 1886304, 1886965, 1887510, 1887934, + 1888231, 1888396, 1888423, 1888307, 1888048, 1887644, 1887100, 1886419, 1885612, 1884688, 1883663, 1882551, 1881369, 1880134, + 1878863, 1877571, 1876272, 1874979, 1873702, 1872450, 1871230, 1870048, 1868906, 1867808, 1866754, 1865746, 1864783, 1863865, + 1862991, 1862160, 1861371, 1860621, 1859910, 1859236, 1858597, 1857992, 1857419, 1856877, 1856364, 1855879, 1855420, 1854986, + 1854576, 1886762, 1887650, 1888429, 1889098, 1889652, 1890088, 1890400, 1890583, 1890631, 1890541, 1890310, 1889938, 1889426, + 1888781, 1888011, 1887124, 1886135, 1885059, 1883909, 1882704, 1881459, 1880190, 1878910, 1877632, 1876367, 1875123, 1873909, + 1872728, 1871587, 1870486, 1869428, 1868415, 1867445, 1866520, 1865637, 1864797, 1863998, 1863238, 1862517, 1861832, 1861182, + 1860566, 1859982, 1859429, 1858905, 1858408, 1857938, 1857494, 1857073, 1888839, 1889729, 1890513, 1891188, 1891751, 1892199, + 1892525, 1892725, 1892794, 1892728, 1892523, 1892181, 1891702, 1891091, 1890356, 1889506, 1888553, 1887510, 1886393, 1885218, + 1884000, 1882754, 1881493, 1880231, 1878978, 1877744, 1876535, 1875358, 1874217, 1873116, 1872055, 1871037, 1870061, 1869128, + 1868238, 1867389, 1866581, 1865811, 1865080, 1864385, 1863724, 1863098, 1862503, 1861939, 1861404, 1860897, 1860416, 1859961, + 1859530, 1890874, 1891767, 1892555, 1893235, 1893807, 1894265, 1894605, 1894822, 1894911, 1894867, 1894689, 1894375, 1893927, + 1893350, 1892649, 1891834, 1890916, 1889907, 1888822, 1887677, 1886485, 1885263, 1884022, 1882777, 1881537, 1880313, 1879111, + 1877938, 1876799, 1875697, 1874633, 1873611, 1872631, 1871691, 1870794, 1869937, 1869120, 1868341, 1867600, 1866895, 1866225, + 1865588, 1864982, 1864408, 1863863, 1863345, 1862854, 1862389, 1861948, 1892868, 1893762, 1894554, 1895240, 1895820, 1896289, + 1896642, 1896874, 1896982, 1896960, 1896807, 1896520, 1896103, 1895558, 1894890, 1894109, 1893225, 1892250, 1891197, 1890081, + 1888916, 1887717, 1886498, 1885270, 1884044, 1882830, 1881636, 1880468, 1879332, 1878230, 1877165, 1876139, 1875154, 1874209, + 1873305, 1872441, 1871615, 1870828, 1870078, 1869363, 1868683, 1868036, 1867421, 1866837, 1866281, 1865754, 1865253, 1864777, + 1864326, 1894820, 1895715, 1896511, 1897203, 1897790, 1898268, 1898634, 1898882, 1899007, 1899007, 1898877, 1898618, 1898229, + 1897715, 1897080, 1896332, 1895481, 1894539, 1893518, 1892431, 1891294, 1890119, 1888920, 1887710, 1886499, 1885297, 1884111, + 1882949, 1881816, 1880715, 1879649, 1878622, 1877632, 1876683, 1875772, 1874901, 1874068, 1873272, 1872514, 1871790, 1871101, + 1870445, 1869820, 1869226, 1868660, 1868123, 1867612, 1867127, 1866666, 1896747, 1897644, 1898443, 1899140, 1899733, 1900221, + 1900599, 1900861, 1901003, 1901023, 1900916, 1900682, 1900321, 1899836, 1899233, 1898517, 1897699, 1896788, 1895798, 1894740, + 1893630, 1892479, 1891302, 1890109, 1888913, 1887723, 1886547, 1885391, 1884262, 1883162, 1882097, 1881067, 1880075, 1879120, + 1878204, 1877326, 1876486, 1875683, 1874916, 1874184, 1873485, 1872820, 1872186, 1871582, 1871007, 1870460, 1869940, 1869445, + 1868974, 1898633, 1899531, 1900333, 1901034, 1901634, 1902131, 1902520, 1902795, 1902955, 1902993, 1902908, 1902698, 1902365, + 1901909, 1901336, 1900652, 1899865, 1898986, 1898025, 1896997, 1895913, 1894787, 1893631, 1892458, 1891277, 1890100, 1888933, + 1887785, 1886660, 1885563, 1884498, 1883468, 1882473, 1881514, 1880593, 1879709, 1878863, 1878052, 1877277, 1876537, 1875830, + 1875156, 1874513, 1873900, 1873316, 1872759, 1872229, 1871725, 1871245, 1900476, 1901375, 1902180, 1902885, 1903492, 1903997, + 1904397, 1904686, 1904861, 1904918, 1904854, 1904668, 1904361, 1903933, 1903389, 1902736, 1901980, 1901132, 1900202, 1899202, + 1898145, 1897043, 1895909, 1894755, 1893591, 1892426, 1891270, 1890130, 1889011, 1887918, 1886854, 1885823, 1884826, 1883865, + 1882939, 1882050, 1881197, 1880380, 1879598, 1878850, 1878135, 1877452, 1876800, 1876179, 1875586, 1875020, 1874482, 1873968, + 1873480, 1902276, 1903177, 1903984, 1904694, 1905307, 1905820, 1906230, 1906532, 1906723, 1906797, 1906754, 1906591, 1906309, + 1905908, 1905393, 1904770, 1904044, 1903226, 1902326, 1901355, 1900325, 1899248, 1898136, 1897001, 1895854, 1894704, 1893559, + 1892427, 1891314, 1890225, 1889164, 1888133, 1887135, 1886171, 1885242, 1884349, 1883490, 1882667, 1881878, 1881123, 1880400, + 1879709, 1879050, 1878420, 1877818, 1877244, 1876697, 1876175, 1875677, 136533, 136533, 136533, 136533, 136533, 136533, + 136533, 136533, 136533, 136533, 136533, 136533, 136533, 136533, 136533, 135924, 125277, 108081, 91368, 77552, + 66660, 58112, 51334, 45876, 41412, 37706, 34587, 31931, 29644, 27657, 25914, 24375, 23005, 21780, + 20677, 19679, 18772, 17944, 17186, 16489, 15845, 15250, 14698, 14184, 13704, 13256, 12836, 12442, + 12071, 11721, 11392, 11080, 10784, 10504, 10238, 9986, 9745, 9516, 9297, 9088, 8888, 8697, + 8513, 8338, 8169, 8007, 7852, 7702, 7558, 7419, 7285, 7156, 7031, 6911, 6795, 6682, + 6574, 6468, 6366, 6267, 6172, 6079, 5989, 5901, 5816, 5733, 5653, 5575, 5499, 5425, + 5353, 5283, 5215, 5148, 5083, 5020, 4959 +]; +/// PMOS log-domain current table, corner mos_tt, IHP-Open-PDK 21133f21, L 0.45 um, 27 C: the tag word (4294967295), then the 4753 words ix * 49 + iy of log2(Id / F) in 1/65536 octave over 2^-8 of a linear-table word (Vgs = ix * 15.625 mV, Vds = iy * 31.25 mV), then the 97 words rv = nint(4096 / s(Vgs)) at Vgs = ix * 15.625 mV (deck psp103_idpa_tt.cir, blocks lam_p and r_p). +pub const TT_LG_P : [4851]u32 = [ + 4294967295, 222972, 219948, 217294, 215847, 215532, 215864, 216457, 217178, 217847, 218531, 219220, 219913, 220611, + 221317, 222034, 222762, 223504, 224261, 225034, 225824, 226632, 227459, 228306, 229174, 230062, 230973, 231905, + 232861, 233842, 234848, 235884, 236954, 238065, 239231, 240468, 241871, 243369, 245064, 247030, 249360, 252170, + 255598, 259801, 264947, 271200, 278707, 287575, 297856, 309539, 267417, 264002, 261181, 259570, 259107, 259280, + 259709, 260264, 260759, 261266, 261772, 262277, 262783, 263291, 263803, 264322, 264848, 265382, 265927, 266482, + 267049, 267628, 268220, 268826, 269446, 270082, 270732, 271399, 272082, 272784, 273506, 274250, 275021, 275826, + 276676, 277586, 278633, 279761, 281056, 282578, 284405, 286635, 289386, 292792, 297002, 302170, 308437, 315924, + 324708, 311984, 308405, 305459, 303719, 303155, 303230, 303556, 303956, 304392, 304785, 305176, 305562, 305945, + 306326, 306708, 307091, 307478, 307869, 308265, 308666, 309075, 309490, 309914, 310346, 310786, 311237, 311697, + 312167, 312649, 313142, 313648, 314168, 314704, 315262, 315846, 316465, 317163, 317908, 318752, 319730, 320891, + 322297, 324029, 326181, 328864, 332206, 336340, 341399, 347505, 356661, 353021, 349997, 348166, 347527, 347541, + 347802, 348136, 348480, 348828, 349146, 349458, 349763, 350065, 350365, 350663, 350962, 351261, 351563, 351867, + 352174, 352485, 352800, 353119, 353444, 353775, 354111, 354453, 354802, 355158, 355522, 355894, 356277, 356671, + 357080, 357510, 357967, 358484, 359040, 359672, 360409, 361290, 362362, 363687, 365341, 367412, 370001, 373222, + 377190, 401437, 397784, 394714, 392824, 392131, 392103, 392325, 392618, 392920, 393211, 393499, 393764, 394022, + 394274, 394523, 394768, 395012, 395255, 395497, 395740, 395984, 396229, 396475, 396724, 396976, 397230, 397488, + 397749, 398013, 398282, 398555, 398832, 399116, 399406, 399705, 400015, 400339, 400697, 401076, 401497, 401976, + 402536, 403205, 404020, 405028, 406285, 407861, 409833, 412292, 446305, 442660, 439562, 437638, 436907, 436850, + 437048, 437316, 437591, 437856, 438108, 438354, 438582, 438804, 439021, 439234, 439444, 439652, 439858, 440062, + 440267, 440471, 440676, 440881, 441087, 441294, 441502, 441712, 441923, 442137, 442353, 442571, 442793, 443018, + 443248, 443483, 443727, 443981, 444260, 444555, 444882, 445253, 445685, 446198, 446821, 447587, 448539, 449728, + 451214, 491256, 487631, 484514, 482572, 481817, 481739, 481921, 482174, 482433, 482682, 482917, 483140, 483352, + 483561, 483758, 483951, 484140, 484326, 484510, 484692, 484872, 485052, 485230, 485408, 485586, 485763, 485941, + 486120, 486299, 486478, 486659, 486841, 487024, 487209, 487396, 487586, 487780, 487980, 488193, 488414, 488652, + 488914, 489209, 489548, 489948, 490428, 491014, 491737, 492633, 536284, 532684, 529555, 527602, 526835, 526742, + 526913, 527157, 527408, 527647, 527872, 528084, 528286, 528479, 528666, 528850, 529027, 529200, 529370, 529538, + 529704, 529868, 530030, 530192, 530352, 530512, 530672, 530831, 530990, 531149, 531308, 531467, 531627, 531787, + 531948, 532111, 532275, 532442, 532614, 532794, 532981, 533180, 533397, 533638, 533912, 534230, 534607, 535060, + 535613, 581381, 577808, 574675, 572716, 571942, 571841, 572004, 572243, 572488, 572722, 572941, 573147, 573343, + 573530, 573710, 573884, 574054, 574221, 574383, 574543, 574700, 574854, 575008, 575159, 575309, 575459, 575607, + 575754, 575901, 576047, 576193, 576339, 576484, 576630, 576775, 576921, 577068, 577216, 577365, 577518, 577677, + 577841, 578014, 578199, 578402, 578630, 578889, 579191, 579548, 626538, 622996, 619863, 617902, 617126, 617020, + 617179, 617414, 617657, 617887, 618103, 618306, 618498, 618682, 618858, 619028, 619194, 619355, 619513, 619667, + 619820, 619970, 620118, 620264, 620408, 620551, 620692, 620833, 620972, 621111, 621249, 621387, 621523, 621660, + 621796, 621932, 622068, 622205, 622342, 622480, 622621, 622765, 622913, 623068, 623232, 623409, 623603, 623820, + 624068, 671741, 668239, 665111, 663151, 662374, 662268, 662425, 662658, 662899, 663129, 663344, 663545, 663735, + 663917, 664091, 664260, 664423, 664582, 664737, 664889, 665038, 665185, 665330, 665472, 665613, 665753, 665891, + 666028, 666163, 666297, 666431, 666564, 666696, 666827, 666958, 667088, 667218, 667348, 667477, 667607, 667738, + 667871, 668006, 668143, 668286, 668435, 668593, 668764, 668951, 716971, 713521, 710405, 708449, 707674, 707569, + 707726, 707960, 708201, 708431, 708646, 708847, 709038, 709219, 709393, 709560, 709723, 709881, 710035, 710186, + 710334, 710480, 710623, 710764, 710903, 711041, 711177, 711311, 711444, 711577, 711708, 711838, 711968, 712096, + 712224, 712351, 712477, 712603, 712729, 712855, 712980, 713106, 713234, 713362, 713493, 713627, 713766, 713911, + 714065, 762198, 758823, 755729, 753781, 753010, 752908, 753068, 753303, 753547, 753778, 753994, 754197, 754388, + 754570, 754745, 754913, 755076, 755234, 755389, 755540, 755688, 755833, 755976, 756117, 756255, 756392, 756528, + 756662, 756794, 756925, 757056, 757185, 757313, 757440, 757566, 757692, 757817, 757941, 758065, 758188, 758311, + 758434, 758557, 758681, 758805, 758931, 759060, 759191, 759328, 807376, 804114, 801054, 799119, 798356, 798260, + 798425, 798665, 798912, 799146, 799366, 799571, 799765, 799949, 800125, 800295, 800460, 800620, 800775, 800928, + 801077, 801223, 801367, 801508, 801648, 801785, 801921, 802055, 802188, 802319, 802450, 802579, 802707, 802834, + 802960, 803085, 803210, 803334, 803457, 803579, 803701, 803823, 803944, 804066, 804187, 804310, 804433, 804558, + 804685, 852431, 849341, 846338, 844425, 843675, 843589, 843762, 844009, 844262, 844503, 844727, 844937, 845135, + 845323, 845503, 845677, 845844, 846007, 846165, 846320, 846471, 846620, 846765, 846909, 847050, 847189, 847327, + 847462, 847596, 847729, 847861, 847991, 848120, 848248, 848375, 848501, 848626, 848751, 848874, 848997, 849119, + 849241, 849363, 849484, 849604, 849725, 849846, 849968, 850091, 897671, 894669, 891641, 889698, 888935, 888849, + 889029, 889285, 889547, 889796, 890029, 890246, 890451, 890645, 890831, 891010, 891183, 891350, 891513, 891672, + 891827, 891979, 892129, 892276, 892420, 892562, 892702, 892841, 892978, 893113, 893247, 893379, 893511, 893641, + 893770, 893898, 894025, 894151, 894276, 894401, 894525, 894648, 894770, 894892, 895014, 895135, 895256, 895378, + 895499, 949790, 943992, 939037, 935945, 934573, 934195, 934247, 934454, 934703, 934954, 935195, 935422, 935637, + 935841, 936036, 936223, 936404, 936579, 936749, 936915, 937076, 937234, 937390, 937542, 937691, 937839, 937984, + 938127, 938268, 938408, 938545, 938682, 938817, 938951, 939083, 939215, 939345, 939474, 939603, 939730, 939857, + 939983, 940108, 940232, 940356, 940480, 940603, 940725, 940848, 1007486, 997033, 988693, 983423, 980780, 979716, + 979423, 979467, 979648, 979877, 980116, 980352, 980578, 980796, 981004, 981204, 981397, 981583, 981764, 981940, + 982112, 982279, 982443, 982603, 982761, 982916, 983069, 983219, 983367, 983513, 983657, 983800, 983941, 984080, + 984218, 984355, 984491, 984625, 984758, 984890, 985022, 985152, 985281, 985410, 985538, 985665, 985792, 985918, + 986043, 1066073, 1051304, 1039474, 1031709, 1027441, 1025388, 1024524, 1024257, 1024278, 1024432, 1024642, 1024874, 1025109, + 1025341, 1025566, 1025783, 1025993, 1026195, 1026392, 1026583, 1026768, 1026950, 1027126, 1027299, 1027469, 1027635, 1027798, + 1027959, 1028117, 1028273, 1028426, 1028578, 1028728, 1028876, 1029022, 1029166, 1029310, 1029451, 1029592, 1029731, 1029869, + 1030006, 1030142, 1030277, 1030411, 1030544, 1030676, 1030808, 1030938, 1122773, 1104926, 1090197, 1080106, 1074162, 1070979, + 1069388, 1068672, 1068428, 1068434, 1068570, 1068769, 1068998, 1069237, 1069477, 1069714, 1069944, 1070168, 1070386, 1070597, + 1070802, 1071002, 1071197, 1071387, 1071573, 1071755, 1071933, 1072108, 1072280, 1072449, 1072616, 1072780, 1072942, 1073101, + 1073259, 1073414, 1073568, 1073720, 1073871, 1074020, 1074167, 1074313, 1074458, 1074602, 1074744, 1074885, 1075026, 1075165, + 1075303, 1176236, 1156692, 1139863, 1127831, 1120351, 1116042, 1113662, 1112412, 1111819, 1111606, 1111611, 1111740, 1111936, + 1112167, 1112414, 1112666, 1112917, 1113164, 1113406, 1113641, 1113871, 1114094, 1114311, 1114523, 1114730, 1114933, 1115130, + 1115324, 1115514, 1115701, 1115884, 1116064, 1116241, 1116416, 1116588, 1116757, 1116925, 1117090, 1117253, 1117414, 1117574, + 1117732, 1117888, 1118042, 1118196, 1118347, 1118498, 1118647, 1118795, 1225788, 1205795, 1187687, 1174157, 1165359, 1160014, + 1156856, 1155042, 1154051, 1153565, 1153392, 1153408, 1153539, 1153738, 1153974, 1154231, 1154496, 1154763, 1155028, 1155289, + 1155544, 1155793, 1156036, 1156273, 1156504, 1156730, 1156950, 1157165, 1157376, 1157583, 1157786, 1157984, 1158180, 1158372, + 1158560, 1158746, 1158929, 1159110, 1159288, 1159463, 1159637, 1159808, 1159977, 1160145, 1160310, 1160474, 1160636, 1160796, + 1160955, 1271107, 1251669, 1233052, 1218468, 1208593, 1202334, 1198451, 1196079, 1194670, 1193880, 1193488, 1193355, 1193388, + 1193526, 1193729, 1193972, 1194238, 1194514, 1194795, 1195076, 1195354, 1195627, 1195894, 1196155, 1196411, 1196660, 1196904, + 1197141, 1197374, 1197601, 1197824, 1198042, 1198256, 1198466, 1198673, 1198875, 1199075, 1199271, 1199464, 1199654, 1199842, + 1200027, 1200210, 1200390, 1200568, 1200744, 1200917, 1201089, 1201259, 1312146, 1293966, 1275523, 1260312, 1249588, 1242542, + 1238000, 1235095, 1233267, 1232153, 1231517, 1231204, 1231106, 1231154, 1231298, 1231504, 1231750, 1232020, 1232303, 1232593, + 1232884, 1233173, 1233459, 1233740, 1234015, 1234285, 1234548, 1234806, 1235058, 1235304, 1235545, 1235781, 1236012, 1236239, + 1236461, 1236679, 1236893, 1237103, 1237310, 1237514, 1237714, 1237911, 1238106, 1238297, 1238486, 1238673, 1238857, 1239039, + 1239219, 1349080, 1332556, 1314846, 1299406, 1288051, 1280337, 1275200, 1271795, 1269556, 1268110, 1267211, 1266692, 1266437, + 1266367, 1266423, 1266568, 1266771, 1267014, 1267282, 1267564, 1267855, 1268149, 1268443, 1268735, 1269022, 1269305, 1269583, + 1269855, 1270121, 1270381, 1270636, 1270886, 1271130, 1271369, 1271604, 1271834, 1272059, 1272281, 1272498, 1272712, 1272922, + 1273129, 1273332, 1273533, 1273730, 1273925, 1274117, 1274306, 1274493, 1382239, 1367516, 1350943, 1335640, 1323861, 1315589, + 1309920, 1306047, 1303409, 1301630, 1300457, 1299714, 1299280, 1299066, 1299011, 1299069, 1299207, 1299401, 1299634, 1299892, + 1300167, 1300451, 1300741, 1301031, 1301321, 1301608, 1301891, 1302170, 1302443, 1302711, 1302974, 1303232, 1303484, 1303732, + 1303974, 1304212, 1304445, 1304673, 1304897, 1305118, 1305334, 1305547, 1305756, 1305962, 1306164, 1306364, 1306561, 1306754, + 1306945, 1412031, 1399075, 1383882, 1369038, 1357036, 1348312, 1342170, 1337862, 1334842, 1332734, 1331281, 1330303, 1329673, + 1329298, 1329111, 1329062, 1329114, 1329239, 1329418, 1329634, 1329877, 1330137, 1330408, 1330685, 1330966, 1331247, 1331527, + 1331804, 1332077, 1332346, 1332611, 1332871, 1333126, 1333376, 1333621, 1333862, 1334098, 1334329, 1334556, 1334779, 1334998, + 1335213, 1335425, 1335633, 1335837, 1336039, 1336237, 1336432, 1336624, 1438872, 1427549, 1413834, 1399709, 1387684, 1378615, + 1372059, 1367352, 1363969, 1361540, 1359808, 1358590, 1357754, 1357204, 1356870, 1356698, 1356647, 1356687, 1356796, 1356955, + 1357150, 1357372, 1357613, 1357866, 1358127, 1358392, 1358659, 1358926, 1359192, 1359455, 1359715, 1359972, 1360224, 1360472, + 1360716, 1360955, 1361190, 1361420, 1361647, 1361869, 1362087, 1362302, 1362513, 1362720, 1362924, 1363124, 1363321, 1363516, + 1363707, 1463154, 1453289, 1441040, 1427822, 1415965, 1406663, 1399753, 1394683, 1390960, 1388224, 1386218, 1384759, 1383713, + 1382981, 1382489, 1382182, 1382016, 1381959, 1381984, 1382073, 1382210, 1382382, 1382581, 1382799, 1383030, 1383271, 1383518, + 1383768, 1384019, 1384270, 1384520, 1384767, 1385012, 1385253, 1385491, 1385725, 1385956, 1386182, 1386404, 1386623, 1386838, + 1387049, 1387257, 1387461, 1387662, 1387859, 1388053, 1388245, 1388433, 1485219, 1476629, 1465764, 1453564, 1442051, 1432633, + 1425437, 1420042, 1416004, 1412976, 1410706, 1409010, 1407754, 1406838, 1406184, 1405735, 1405445, 1405281, 1405214, 1405223, + 1405290, 1405403, 1405551, 1405726, 1405920, 1406129, 1406348, 1406574, 1406805, 1407038, 1407273, 1407507, 1407739, 1407970, + 1408199, 1408424, 1408647, 1408866, 1409082, 1409295, 1409504, 1409710, 1409912, 1410112, 1410308, 1410500, 1410690, 1410877, + 1411061, 1505371, 1497884, 1488283, 1477146, 1466125, 1456711, 1449297, 1443620, 1439293, 1435992, 1433470, 1431545, 1430083, + 1428982, 1428163, 1427569, 1427151, 1426873, 1426707, 1426629, 1426620, 1426667, 1426757, 1426881, 1427031, 1427202, 1427387, + 1427584, 1427789, 1428000, 1428214, 1428431, 1428648, 1428865, 1429080, 1429295, 1429507, 1429717, 1429924, 1430129, 1430331, + 1430529, 1430725, 1430918, 1431108, 1431295, 1431479, 1431660, 1431838, 1523857, 1517320, 1508850, 1498764, 1488349, 1479059, + 1471504, 1465589, 1461004, 1457449, 1454689, 1452545, 1450883, 1449600, 1448619, 1447879, 1447330, 1446936, 1446666, 1446496, + 1446407, 1446382, 1446408, 1446476, 1446577, 1446704, 1446851, 1447014, 1447189, 1447373, 1447563, 1447759, 1447957, 1448157, + 1448357, 1448558, 1448757, 1448956, 1449153, 1449347, 1449540, 1449730, 1449918, 1450103, 1450286, 1450466, 1450643, 1450818, + 1450990, 1540895, 1535176, 1527705, 1518623, 1508889, 1499832, 1492215, 1486112, 1481298, 1477512, 1474529, 1472177, 1470323, + 1468864, 1467724, 1466838, 1466159, 1465647, 1465271, 1465007, 1464832, 1464732, 1464691, 1464699, 1464746, 1464825, 1464930, + 1465055, 1465196, 1465350, 1465513, 1465684, 1465861, 1466041, 1466224, 1466408, 1466593, 1466778, 1466963, 1467146, 1467328, + 1467509, 1467687, 1467864, 1468039, 1468211, 1468381, 1468549, 1468714, 1556654, 1551641, 1545048, 1536901, 1527886, 1519158, + 1511560, 1505322, 1500314, 1496319, 1493130, 1490583, 1488546, 1486919, 1485623, 1484595, 1483787, 1483158, 1482676, 1482315, + 1482055, 1481876, 1481765, 1481710, 1481700, 1481729, 1481788, 1481872, 1481976, 1482097, 1482231, 1482375, 1482527, 1482685, + 1482849, 1483015, 1483184, 1483354, 1483524, 1483695, 1483866, 1484035, 1484204, 1484371, 1484536, 1484700, 1484862, 1485023, + 1485181, 1571293, 1566890, 1561066, 1553773, 1545484, 1537161, 1529663, 1523343, 1518178, 1513997, 1510621, 1507890, 1505681, + 1503893, 1502447, 1501282, 1500347, 1499602, 1499015, 1498558, 1498210, 1497952, 1497769, 1497649, 1497581, 1497556, 1497567, + 1497607, 1497672, 1497758, 1497859, 1497975, 1498101, 1498235, 1498377, 1498523, 1498674, 1498827, 1498983, 1499140, 1499297, + 1499455, 1499612, 1499769, 1499925, 1500080, 1500234, 1500386, 1500537, 1584936, 1581063, 1575912, 1569391, 1561812, 1553950, + 1546623, 1540280, 1534994, 1530655, 1527108, 1524209, 1521838, 1519897, 1518308, 1517010, 1515952, 1515094, 1514403, 1513850, + 1513415, 1513077, 1512822, 1512635, 1512507, 1512427, 1512388, 1512383, 1512407, 1512455, 1512523, 1512607, 1512705, 1512814, + 1512932, 1513057, 1513188, 1513324, 1513463, 1513605, 1513749, 1513893, 1514039, 1514185, 1514330, 1514475, 1514620, 1514764, + 1514906, 1597692, 1594282, 1589719, 1583891, 1576990, 1569621, 1562531, 1556221, 1550855, 1546385, 1542687, 1539634, 1537111, + 1535026, 1533301, 1531875, 1530699, 1529730, 1528937, 1528291, 1527769, 1527352, 1527023, 1526770, 1526580, 1526444, 1526354, + 1526303, 1526284, 1526293, 1526326, 1526377, 1526446, 1526527, 1526621, 1526723, 1526834, 1526950, 1527072, 1527198, 1527326, + 1527457, 1527590, 1527724, 1527859, 1527994, 1528128, 1528263, 1528397, 1609654, 1606649, 1602603, 1597394, 1591129, 1584268, + 1577466, 1571245, 1565840, 1561266, 1557438, 1554245, 1551583, 1549362, 1547509, 1545961, 1544671, 1543596, 1542703, 1541965, + 1541358, 1540862, 1540461, 1540141, 1539890, 1539697, 1539555, 1539456, 1539394, 1539363, 1539358, 1539376, 1539414, 1539467, + 1539534, 1539613, 1539702, 1539798, 1539901, 1540010, 1540122, 1540239, 1540358, 1540479, 1540602, 1540726, 1540851, 1540976, + 1541101, 1620898, 1618249, 1614658, 1610002, 1604325, 1597972, 1591497, 1585415, 1580013, 1575367, 1571430, 1568113, 1565324, + 1562977, 1561002, 1559339, 1557939, 1556761, 1555773, 1554945, 1554255, 1553682, 1553209, 1552822, 1552510, 1552261, 1552066, + 1551919, 1551812, 1551740, 1551698, 1551681, 1551687, 1551711, 1551751, 1551805, 1551870, 1551946, 1552029, 1552120, 1552216, + 1552317, 1552422, 1552530, 1552641, 1552753, 1552867, 1552982, 1553098, 1631495, 1629162, 1625973, 1621808, 1616672, 1610814, + 1604694, 1598793, 1593436, 1588748, 1584724, 1581300, 1578395, 1575932, 1573843, 1572071, 1570567, 1569291, 1568210, 1567296, + 1566524, 1565875, 1565331, 1564879, 1564506, 1564200, 1563953, 1563758, 1563606, 1563492, 1563412, 1563360, 1563332, 1563326, + 1563339, 1563367, 1563408, 1563462, 1563525, 1563597, 1563676, 1563760, 1563850, 1563945, 1564042, 1564143, 1564245, 1564350, + 1564456, 1641513, 1639458, 1636624, 1632897, 1628255, 1622871, 1617120, 1611438, 1606163, 1601464, 1597377, 1593862, 1590854, + 1588285, 1586090, 1584214, 1582611, 1581242, 1580071, 1579073, 1578222, 1577499, 1576886, 1576369, 1575935, 1575574, 1575275, + 1575030, 1574834, 1574678, 1574559, 1574471, 1574410, 1574373, 1574357, 1574358, 1574375, 1574406, 1574448, 1574500, 1574561, + 1574629, 1574703, 1574783, 1574867, 1574955, 1575046, 1575139, 1575235, 1650991, 1649185, 1646667, 1643331, 1639137, 1634203, + 1628825, 1623389, 1618232, 1613555, 1609428, 1605840, 1602743, 1600077, 1597784, 1595813, 1594116, 1592657, 1591402, 1590322, + 1589395, 1588600, 1587920, 1587340, 1586846, 1586429, 1586078, 1585786, 1585544, 1585346, 1585188, 1585064, 1584969, 1584901, + 1584855, 1584830, 1584822, 1584829, 1584849, 1584881, 1584923, 1584974, 1585032, 1585096, 1585166, 1585241, 1585320, 1585402, + 1585487, 1659981, 1658397, 1656160, 1653173, 1649386, 1644873, 1639866, 1634697, 1629688, 1625061, 1620919, 1617277, 1614104, + 1611353, 1608971, 1606909, 1605125, 1603581, 1602244, 1601087, 1600086, 1599222, 1598476, 1597834, 1597282, 1596810, 1596408, + 1596068, 1595781, 1595542, 1595344, 1595183, 1595055, 1594955, 1594880, 1594827, 1594793, 1594776, 1594774, 1594785, 1594808, + 1594841, 1594882, 1594931, 1594986, 1595047, 1595113, 1595183, 1595257, 1668528, 1667142, 1665156, 1662482, 1659063, 1654941, + 1650295, 1645405, 1640570, 1636022, 1631888, 1628209, 1624975, 1622150, 1619687, 1617543, 1615676, 1614052, 1612637, 1611406, + 1610334, 1609402, 1608592, 1607890, 1607282, 1606756, 1606304, 1605916, 1605585, 1605304, 1605067, 1604870, 1604707, 1604575, + 1604470, 1604389, 1604329, 1604288, 1604263, 1604253, 1604256, 1604270, 1604294, 1604327, 1604367, 1604414, 1604467, 1604525, + 1604587, 1676667, 1675459, 1673698, 1671305, 1668218, 1664459, 1660160, 1655554, 1650913, 1646468, 1642366, 1638670, 1635390, + 1632500, 1629966, 1627746, 1625803, 1624103, 1622615, 1621312, 1620172, 1619175, 1618304, 1617542, 1616878, 1616301, 1615799, + 1615364, 1614989, 1614666, 1614391, 1614157, 1613960, 1613796, 1613661, 1613552, 1613465, 1613399, 1613352, 1613320, 1613302, + 1613297, 1613304, 1613320, 1613345, 1613377, 1613416, 1613461, 1613512, 1684424, 1683376, 1681817, 1679676, 1676891, 1673466, + 1669497, 1665177, 1660745, 1656425, 1652376, 1648683, 1645371, 1642430, 1639832, 1637544, 1635531, 1633760, 1632202, 1630832, + 1629627, 1628568, 1627637, 1626819, 1626101, 1625471, 1624921, 1624440, 1624022, 1623659, 1623345, 1623075, 1622844, 1622647, + 1622482, 1622345, 1622232, 1622141, 1622070, 1622016, 1621978, 1621954, 1621942, 1621941, 1621950, 1621968, 1621993, 1622025, + 1622063, 1691833, 1690930, 1689553, 1687638, 1685127, 1682008, 1678352, 1674313, 1670099, 1665922, 1661947, 1658275, 1654946, + 1651966, 1649315, 1646966, 1644888, 1643052, 1641429, 1639995, 1638728, 1637608, 1636620, 1635747, 1634976, 1634297, 1633699, + 1633174, 1632713, 1632309, 1631957, 1631651, 1631386, 1631158, 1630963, 1630797, 1630657, 1630541, 1630446, 1630371, 1630312, + 1630268, 1630237, 1630219, 1630212, 1630214, 1630225, 1630243, 1630269, 1698916, 1698144, 1696932, 1695222, 1692957, 1690121, + 1686758, 1682992, 1679002, 1674984, 1671101, 1667466, 1664137, 1661129, 1658434, 1656032, 1653896, 1652000, 1650316, 1648822, + 1647496, 1646319, 1645275, 1644349, 1643528, 1642800, 1642156, 1641587, 1641084, 1640641, 1640251, 1639910, 1639611, 1639351, + 1639126, 1638932, 1638765, 1638624, 1638506, 1638407, 1638327, 1638264, 1638215, 1638179, 1638155, 1638142, 1638138, 1638142, + 1638155, 1705702, 1705048, 1703985, 1702460, 1700420, 1697841, 1694753, 1691250, 1687486, 1683636, 1679862, 1676281, 1672965, + 1669942, 1667214, 1664767, 1662579, 1660627, 1658887, 1657336, 1655954, 1654723, 1653626, 1652649, 1651778, 1651004, 1650315, + 1649702, 1649158, 1648676, 1648250, 1647873, 1647541, 1647250, 1646995, 1646772, 1646579, 1646413, 1646271, 1646150, 1646048, + 1645965, 1645897, 1645843, 1645802, 1645773, 1645754, 1645745, 1645744, 1712212, 1711666, 1710737, 1709380, 1707543, 1705200, + 1702367, 1699117, 1695576, 1691903, 1688249, 1684738, 1681450, 1678424, 1675672, 1673188, 1670955, 1668953, 1667160, 1665557, + 1664122, 1662839, 1661691, 1660664, 1659747, 1658926, 1658194, 1657539, 1656956, 1656435, 1655973, 1655561, 1655197, 1654874, + 1654589, 1654338, 1654119, 1653927, 1653761, 1653618, 1653495, 1653391, 1653304, 1653232, 1653175, 1653129, 1653095, 1653071, + 1653057, 1718450, 1718003, 1717197, 1715992, 1714341, 1712214, 1709619, 1706608, 1703288, 1699795, 1696274, 1692846, 1689599, + 1686582, 1683817, 1681304, 1679033, 1676988, 1675148, 1673495, 1672011, 1670679, 1669483, 1668410, 1667446, 1666582, 1665807, + 1665112, 1664490, 1663932, 1663434, 1662989, 1662592, 1662238, 1661924, 1661646, 1661400, 1661184, 1660994, 1660828, 1660684, + 1660560, 1660453, 1660364, 1660289, 1660227, 1660178, 1660139, 1660111, 1724454, 1724095, 1723401, 1722334, 1720852, 1718924, + 1716547, 1713764, 1710657, 1707347, 1703965, 1700632, 1697439, 1694443, 1691674, 1689141, 1686839, 1684755, 1682872, 1681174, + 1679644, 1678265, 1677024, 1675906, 1674899, 1673992, 1673176, 1672442, 1671781, 1671188, 1670654, 1670176, 1669747, 1669363, + 1669020, 1668714, 1668442, 1668201, 1667987, 1667799, 1667633, 1667489, 1667363, 1667255, 1667163, 1667085, 1667020, 1666967, + 1666925, 1730235, 1729958, 1729365, 1728424, 1727095, 1725348, 1723175, 1720604, 1717704, 1714576, 1711340, 1708111, 1704982, + 1702018, 1699256, 1696711, 1694384, 1692267, 1690346, 1688607, 1687034, 1685612, 1684327, 1683166, 1682117, 1681170, 1680314, + 1679541, 1678844, 1678215, 1677647, 1677136, 1676676, 1676262, 1675891, 1675558, 1675259, 1674993, 1674756, 1674545, 1674358, + 1674193, 1674049, 1673922, 1673812, 1673718, 1673637, 1673569, 1673513, 1735797, 1735595, 1735095, 1734269, 1733080, 1731499, + 1729514, 1727143, 1724441, 1721493, 1718406, 1715290, 1712236, 1709314, 1706568, 1704020, 1701676, 1699532, 1697578, 1695802, + 1694189, 1692727, 1691401, 1690200, 1689111, 1688124, 1687230, 1686421, 1685688, 1685024, 1684424, 1683881, 1683390, 1682947, + 1682547, 1682187, 1681863, 1681572, 1681312, 1681079, 1680871, 1680686, 1680522, 1680377, 1680250, 1680138, 1680042, 1679959, + 1679888, 1741161, 1741026, 1740611, 1739890, 1738830, 1737402, 1735590, 1733407, 1730893, 1728121, 1725185, 1722187, 1719217, + 1716347, 1713627, 1711083, 1708729, 1706564, 1704582, 1702773, 1701125, 1699625, 1698261, 1697021, 1695895, 1694870, 1693940, + 1693095, 1692327, 1691630, 1690997, 1690423, 1689902, 1689430, 1689003, 1688617, 1688268, 1687952, 1687669, 1687413, 1687184, + 1686979, 1686796, 1686633, 1686488, 1686360, 1686248, 1686150, 1686065, 1746328, 1746256, 1745919, 1745295, 1744352, 1743064, + 1741413, 1739405, 1737070, 1734470, 1731686, 1728810, 1725932, 1723123, 1720436, 1717906, 1715548, 1713369, 1711364, 1709527, + 1707847, 1706313, 1704914, 1703638, 1702475, 1701416, 1700450, 1699571, 1698770, 1698040, 1697376, 1696772, 1696222, 1695722, + 1695268, 1694855, 1694481, 1694143, 1693836, 1693559, 1693309, 1693083, 1692881, 1692700, 1692538, 1692393, 1692265, 1692152, + 1692052, 1751330, 1751315, 1751049, 1750512, 1749677, 1748517, 1747015, 1745169, 1743004, 1740569, 1737935, 1735185, 1732403, + 1729662, 1727018, 1724508, 1722154, 1719966, 1717943, 1716082, 1714374, 1712808, 1711376, 1710067, 1708870, 1707776, 1706777, + 1705865, 1705032, 1704271, 1703576, 1702942, 1702364, 1701836, 1701355, 1700918, 1700519, 1700156, 1699827, 1699528, 1699257, + 1699012, 1698791, 1698591, 1698412, 1698251, 1698107, 1697978, 1697864, 1756158, 1756195, 1755995, 1755539, 1754803, 1753761, + 1752396, 1750703, 1748698, 1746422, 1743935, 1741312, 1738632, 1735966, 1733371, 1730889, 1728546, 1726355, 1724320, 1722439, + 1720706, 1719113, 1717651, 1716310, 1715081, 1713956, 1712925, 1711981, 1711117, 1710325, 1709601, 1708939, 1708333, 1707778, + 1707272, 1706809, 1706386, 1706000, 1705649, 1705329, 1705037, 1704772, 1704532, 1704314, 1704118, 1703940, 1703780, 1703637, + 1703508, 1760834, 1760919, 1760779, 1760397, 1759752, 1758819, 1757580, 1756028, 1754174, 1752050, 1749707, 1747211, 1744636, + 1742050, 1739512, 1737065, 1734739, 1732550, 1730508, 1728611, 1726858, 1725240, 1723751, 1722381, 1721122, 1719966, 1718905, + 1717931, 1717037, 1716216, 1715464, 1714773, 1714140, 1713560, 1713028, 1712540, 1712094, 1711686, 1711312, 1710971, 1710659, + 1710375, 1710116, 1709880, 1709666, 1709472, 1709296, 1709137, 1708994, 1765359, 1765489, 1765404, 1765091, 1764529, 1763696, + 1762574, 1761153, 1759441, 1757462, 1755258, 1752890, 1750422, 1747921, 1745444, 1743038, 1740736, 1738556, 1736511, 1734604, + 1732833, 1731194, 1729681, 1728284, 1726998, 1725814, 1724724, 1723721, 1722798, 1721950, 1721170, 1720452, 1719793, 1719187, + 1718630, 1718119, 1717649, 1717218, 1716823, 1716461, 1716129, 1715826, 1715548, 1715295, 1715064, 1714853, 1714662, 1714488, + 1714330, 1769745, 1769916, 1769882, 1769632, 1769146, 1768406, 1767392, 1766094, 1764515, 1762673, 1760604, 1758360, 1756001, + 1753588, 1751179, 1748820, 1746546, 1744381, 1742339, 1740425, 1738641, 1736984, 1735449, 1734029, 1732717, 1731506, 1730389, + 1729359, 1728409, 1727534, 1726727, 1725984, 1725299, 1724668, 1724087, 1723552, 1723060, 1722607, 1722191, 1721808, 1721457, + 1721134, 1720839, 1720567, 1720319, 1720092, 1719885, 1719696, 1719524, 1773994, 1774203, 1774215, 1774023, 1773609, 1772953, + 1772039, 1770855, 1769401, 1767690, 1765751, 1763630, 1761379, 1759058, 1756720, 1754413, 1752174, 1750029, 1747994, 1746079, + 1744286, 1742614, 1741060, 1739619, 1738283, 1737048, 1735905, 1734850, 1733874, 1732973, 1732141, 1731372, 1730663, 1730008, + 1729404, 1728847, 1728332, 1727858, 1727421, 1727018, 1726647, 1726306, 1725992, 1725703, 1725439, 1725195, 1724973, 1724769, + 1724582, 1778128, 1778371, 1778427, 1778287, 1777938, 1777361, 1776540, 1775461, 1774123, 1772535, 1770721, 1768719, 1766577, + 1764347, 1762084, 1759834, 1757634, 1755514, 1753491, 1751578, 1749779, 1748096, 1746527, 1745066, 1743710, 1742452, 1741285, + 1740205, 1739205, 1738279, 1737422, 1736630, 1735897, 1735218, 1734591, 1734011, 1733476, 1732980, 1732523, 1732100, 1731710, + 1731350, 1731018, 1730712, 1730431, 1730172, 1729933, 1729715, 1729514, 1782126, 1782401, 1782497, 1782407, 1782118, 1781614, + 1780879, 1779899, 1778671, 1777200, 1775505, 1773619, 1771583, 1769448, 1767263, 1765073, 1762918, 1760827, 1758821, 1756915, + 1755115, 1753424, 1751842, 1750366, 1748990, 1747712, 1746524, 1745421, 1744398, 1743449, 1742569, 1741753, 1740997, 1740297, + 1739647, 1739046, 1738489, 1737973, 1737496, 1737054, 1736646, 1736268, 1735918, 1735595, 1735297, 1735022, 1734769, 1734535, + 1734321, 1786022, 1786326, 1786459, 1786414, 1786182, 1785745, 1785089, 1784200, 1783074, 1781713, 1780132, 1778357, 1776427, + 1774386, 1772280, 1770154, 1768047, 1765990, 1764005, 1762110, 1760312, 1758617, 1757025, 1755534, 1754143, 1752845, 1751637, + 1750513, 1749468, 1748497, 1747595, 1746757, 1745979, 1745256, 1744586, 1743963, 1743386, 1742850, 1742353, 1741892, 1741465, + 1741069, 1740703, 1740363, 1740049, 1739758, 1739490, 1739241, 1739012, 1789806, 1790137, 1790304, 1790302, 1790120, 1789746, + 1789163, 1788360, 1787330, 1786072, 1784599, 1782932, 1781105, 1779157, 1777133, 1775073, 1773018, 1770999, 1769040, 1767159, + 1765367, 1763670, 1762072, 1760570, 1759164, 1757850, 1756624, 1755480, 1754415, 1753423, 1752500, 1751640, 1750841, 1750098, + 1749407, 1748764, 1748167, 1747612, 1747096, 1746616, 1746171, 1745758, 1745374, 1745018, 1744688, 1744382, 1744098, 1743835, + 1743592, 1793478, 1793834, 1794033, 1794070, 1793937, 1793620, 1793106, 1792383, 1791442, 1790282, 1788911, 1787349, 1785622, + 1783767, 1781824, 1779834, 1777834, 1775856, 1773927, 1772064, 1770282, 1768588, 1766985, 1765476, 1764058, 1762730, 1761487, + 1760325, 1759241, 1758230, 1757287, 1756407, 1755588, 1754825, 1754114, 1753452, 1752835, 1752261, 1751727, 1751229, 1750767, + 1750336, 1749936, 1749564, 1749218, 1748896, 1748598, 1748321, 1748065, 1797063, 1797442, 1797669, 1797743, 1797653, 1797390, + 1796940, 1796290, 1795433, 1794365, 1793091, 1791628, 1789999, 1788235, 1786374, 1784454, 1782511, 1780578, 1778682, 1776841, + 1775072, 1773383, 1771780, 1770264, 1768837, 1767496, 1766238, 1765061, 1763959, 1762929, 1761967, 1761069, 1760230, 1759447, + 1758717, 1758036, 1757401, 1756808, 1756256, 1755741, 1755261, 1754814, 1754397, 1754009, 1753647, 1753311, 1752998, 1752707, + 1752437, 1800549, 1800949, 1801203, 1801310, 1801262, 1801049, 1800658, 1800077, 1799297, 1798316, 1797135, 1795766, 1794231, + 1792557, 1790778, 1788929, 1787046, 1785161, 1783300, 1781485, 1779732, 1778052, 1776450, 1774932, 1773498, 1772146, 1770876, + 1769684, 1768566, 1767519, 1766539, 1765623, 1764766, 1763965, 1763216, 1762517, 1761864, 1761253, 1760683, 1760151, 1759655, + 1759191, 1758758, 1758354, 1757978, 1757627, 1757300, 1756995, 1756711, 1803948, 1804368, 1804648, 1804785, 1804776, 1804608, + 1804272, 1803755, 1803049, 1802148, 1801054, 1799777, 1798332, 1796746, 1795048, 1793271, 1791449, 1789614, 1787792, 1786005, + 1784272, 1782602, 1781006, 1779487, 1778048, 1776688, 1775407, 1774202, 1773069, 1772007, 1771011, 1770077, 1769203, 1768384, + 1767618, 1766901, 1766230, 1765603, 1765016, 1764467, 1763953, 1763474, 1763025, 1762606, 1762215, 1761849, 1761508, 1761189, + 1760892, 1807262, 1807700, 1808003, 1808169, 1808195, 1808070, 1807785, 1807328, 1806690, 1805865, 1804854, 1803663, 1802306, + 1800805, 1799186, 1797482, 1795722, 1793939, 1792159, 1790404, 1788692, 1787037, 1785449, 1783932, 1782490, 1781124, 1779834, + 1778617, 1777471, 1776395, 1775383, 1774433, 1773543, 1772707, 1771924, 1771190, 1770503, 1769858, 1769255, 1768690, 1768161, + 1767665, 1767202, 1766768, 1766361, 1765981, 1765626, 1765294, 1764984, 1810491, 1810946, 1811270, 1811463, 1811521, 1811437, + 1811199, 1810798, 1810224, 1809471, 1808537, 1807428, 1806155, 1804737, 1803197, 1801565, 1799869, 1798139, 1796403, 1794682, + 1792995, 1791358, 1789779, 1788267, 1786825, 1785455, 1784157, 1782931, 1781774, 1780684, 1779659, 1778694, 1777788, 1776937, + 1776138, 1775388, 1774684, 1774024, 1773404, 1772823, 1772279, 1771768, 1771289, 1770841, 1770420, 1770026, 1769657, 1769312, + 1768989, 1813648, 1814118, 1814462, 1814680, 1814768, 1814721, 1814527, 1814178, 1813664, 1812978, 1812118, 1811087, 1809894, + 1808556, 1807093, 1805532, 1803900, 1802225, 1800534, 1798849, 1797190, 1795572, 1794007, 1792501, 1791061, 1789689, 1788386, + 1787151, 1785984, 1784883, 1783844, 1782866, 1781945, 1781079, 1780265, 1779499, 1778780, 1778104, 1777469, 1776873, 1776313, + 1775788, 1775295, 1774832, 1774397, 1773989, 1773607, 1773248, 1772912, 1816720, 1817204, 1817566, 1817807, 1817925, 1817912, + 1817760, 1817459, 1817001, 1816378, 1815587, 1814631, 1813515, 1812254, 1810867, 1809376, 1807808, 1806190, 1804546, 1802900, + 1801271, 1799675, 1798125, 1796629, 1795193, 1793821, 1792515, 1791274, 1790099, 1788987, 1787937, 1786946, 1786012, 1785132, + 1784303, 1783523, 1782789, 1782098, 1781449, 1780838, 1780263, 1779724, 1779216, 1778739, 1778291, 1777870, 1777474, 1777103, + 1776754, 1819720, 1820218, 1820597, 1820859, 1821003, 1821023, 1820910, 1820654, 1820248, 1819685, 1818960, 1818074, 1817032, + 1815846, 1814531, 1813110, 1811606, 1810044, 1808449, 1806844, 1805247, 1803676, 1802143, 1800659, 1799229, 1797859, 1796551, + 1795306, 1794124, 1793003, 1791943, 1790941, 1789994, 1789101, 1788259, 1787465, 1786716, 1786012, 1785348, 1784723, 1784134, + 1783581, 1783059, 1782569, 1782107, 1781673, 1781265, 1780881, 1780520, 1822663, 1823173, 1823567, 1823850, 1824018, 1824067, + 1823990, 1823777, 1823420, 1822912, 1822248, 1821429, 1820457, 1819342, 1818099, 1816746, 1815305, 1813800, 1812254, 1810690, + 1809128, 1807583, 1806070, 1804599, 1803178, 1801812, 1800504, 1799256, 1798068, 1796940, 1795870, 1794857, 1793899, 1792994, + 1792139, 1791331, 1790570, 1789851, 1789174, 1788535, 1787933, 1787365, 1786831, 1786327, 1785852, 1785405, 1784984, 1784588, + 1784215, 1825521, 1826042, 1826451, 1826752, 1826944, 1827021, 1826978, 1826804, 1826494, 1826038, 1825433, 1824677, 1823772, + 1822727, 1821553, 1820266, 1818889, 1817441, 1815946, 1814425, 1812899, 1811383, 1809892, 1808437, 1807026, 1805666, 1804360, + 1803111, 1801920, 1800785, 1799708, 1798686, 1797718, 1796801, 1795934, 1795115, 1794340, 1793609, 1792918, 1792267, 1791651, + 1791071, 1790523, 1790007, 1789520, 1789060, 1788627, 1788219, 1787834, 1828336, 1828867, 1829290, 1829608, 1829820, 1829924, + 1829911, 1829775, 1829507, 1829100, 1828550, 1827854, 1827012, 1826033, 1824925, 1823704, 1822387, 1820996, 1819552, 1818076, + 1816586, 1815100, 1813633, 1812196, 1810797, 1809445, 1808142, 1806893, 1805699, 1804560, 1803476, 1802446, 1801468, 1800541, + 1799663, 1798832, 1798045, 1797301, 1796598, 1795934, 1795306, 1794712, 1794152, 1793623, 1793123, 1792652, 1792206, 1791786, + 1791390, 1831080, 1831620, 1832056, 1832390, 1832622, 1832750, 1832767, 1832665, 1832438, 1832077, 1831579, 1830939, 1830158, + 1829242, 1828198, 1827040, 1825785, 1824450, 1823058, 1821626, 1820175, 1818721, 1817279, 1815861, 1814477, 1813134, 1811837, + 1810590, 1809395, 1808253, 1807163, 1806126, 1805140, 1804203, 1803315, 1802473, 1801675, 1800920, 1800204, 1799528, 1798888, + 1798282, 1797710, 1797168, 1796657, 1796173, 1795716, 1795285, 1794877, 1833768, 1834317, 1834764, 1835112, 1835363, 1835514, + 1835558, 1835489, 1835299, 1834982, 1834532, 1833946, 1833223, 1832367, 1831385, 1830289, 1829093, 1827814, 1826473, 1825087, + 1823675, 1822254, 1820839, 1819443, 1818075, 1816743, 1815453, 1814210, 1813015, 1811870, 1810777, 1809734, 1808740, 1807795, + 1806898, 1806045, 1805237, 1804470, 1803744, 1803056, 1802404, 1801787, 1801202, 1800649, 1800126, 1799631, 1799163, 1798719, + 1798300, 1836384, 1836941, 1837399, 1837762, 1838030, 1838202, 1838272, 1838234, 1838080, 1837804, 1837400, 1836865, 1836197, + 1835399, 1834477, 1833440, 1832303, 1831080, 1829790, 1828450, 1827079, 1825693, 1824307, 1822933, 1821583, 1820264, 1818983, + 1817745, 1816552, 1815407, 1814311, 1813263, 1812264, 1811312, 1810406, 1809544, 1808726, 1807949, 1807212, 1806513, 1805850, + 1805222, 1804626, 1804062, 1803528, 1803022, 1802542, 1802088, 1801658, 1838959, 1839523, 1839991, 1840367, 1840651, 1840843, + 1840937, 1840927, 1840806, 1840569, 1840208, 1839721, 1839105, 1838362, 1837497, 1836519, 1835438, 1834269, 1833030, 1831737, + 1830406, 1829056, 1827699, 1826350, 1825019, 1823715, 1822444, 1821212, 1820023, 1818879, 1817781, 1816729, 1815725, 1814766, + 1813852, 1812983, 1812155, 1811369, 1810621, 1809912, 1809238, 1808599, 1807993, 1807418, 1806872, 1806355, 1805865, 1805400, + 1804960, 1841477, 1842049, 1842526, 1842913, 1843213, 1843423, 1843539, 1843556, 1843467, 1843265, 1842946, 1842504, 1841938, + 1841248, 1840438, 1839515, 1838489, 1837374, 1836185, 1834938, 1833650, 1832335, 1831010, 1829686, 1828376, 1827087, 1825829, + 1824605, 1823421, 1822278, 1821180, 1820126, 1819117, 1818153, 1817233, 1816355, 1815519, 1814724, 1813967, 1813248, 1812564, + 1811915, 1811298, 1810713, 1810157, 1809629, 1809128, 1808653, 1808203, 1843955, 1844532, 1845018, 1845416, 1845730, 1845957, + 1846094, 1846136, 1846076, 1845908, 1845627, 1845228, 1844709, 1844069, 1843311, 1842442, 1841470, 1840407, 1839268, 1838067, + 1836820, 1835542, 1834249, 1832952, 1831663, 1830392, 1829146, 1827932, 1826754, 1825614, 1824516, 1823461, 1822449, 1821480, + 1820554, 1819670, 1818826, 1818022, 1817257, 1816528, 1815835, 1815175, 1814549, 1813953, 1813387, 1812849, 1812338, 1811853, + 1811392, 1846376, 1846959, 1847453, 1847861, 1848188, 1848431, 1848588, 1848653, 1848621, 1848485, 1848240, 1847882, 1847407, + 1846815, 1846108, 1845290, 1844371, 1843359, 1842269, 1841114, 1839909, 1838669, 1837408, 1836139, 1834873, 1833621, 1832390, + 1831186, 1830015, 1828880, 1827784, 1826729, 1825715, 1824742, 1823811, 1822921, 1822070, 1821259, 1820485, 1819747, 1819045, + 1818376, 1817740, 1817135, 1816559, 1816011, 1815490, 1814995, 1814525, 1848758, 1849345, 1849846, 1850264, 1850602, 1850861, + 1851036, 1851123, 1851117, 1851011, 1850800, 1850480, 1850047, 1849500, 1848841, 1848074, 1847204, 1846242, 1845200, 1844090, + 1842927, 1841725, 1840498, 1839257, 1838016, 1836783, 1835568, 1834376, 1833214, 1832085, 1830992, 1829937, 1828922, 1827946, + 1827011, 1826115, 1825259, 1824440, 1823659, 1822913, 1822202, 1821524, 1820879, 1820264, 1819679, 1819122, 1818591, 1818087, + 1817607, 1851082, 1851674, 1852181, 1852608, 1852958, 1853231, 1853423, 1853531, 1853549, 1853472, 1853294, 1853010, 1852617, + 1852114, 1851501, 1850782, 1849961, 1849048, 1848053, 1846988, 1845867, 1844703, 1843510, 1842299, 1841083, 1839872, 1838673, + 1837495, 1836342, 1835220, 1834131, 1833079, 1832063, 1831086, 1830148, 1829248, 1828386, 1827561, 1826773, 1826020, 1825301, + 1824615, 1823961, 1823337, 1822743, 1822176, 1821637, 1821123, 1820634, 1853365, 1853962, 1854475, 1854911, 1855271, 1855557, + 1855766, 1855893, 1855934, 1855883, 1855735, 1855486, 1855131, 1854670, 1854101, 1853427, 1852654, 1851788, 1850840, 1849819, + 1848740, 1847614, 1846455, 1845275, 1844085, 1842895, 1841715, 1840551, 1839410, 1838295, 1837212, 1836162, 1835148, 1834170, + 1833229, 1832326, 1831459, 1830629, 1829834, 1829074, 1828348, 1827654, 1826991, 1826359, 1825757, 1825182, 1824633, 1824111, + 1823613, 1855609, 1856209, 1856728, 1857171, 1857541, 1857839, 1858063, 1858209, 1858271, 1858246, 1858127, 1857910, 1857591, + 1857169, 1856642, 1856013, 1855285, 1854465, 1853561, 1852585, 1851546, 1850459, 1849335, 1848185, 1847022, 1845856, 1844694, + 1843546, 1842417, 1841312, 1840235, 1839189, 1838176, 1837199, 1836256, 1835350, 1834479, 1833644, 1832843, 1832077, 1831344, + 1830643, 1829973, 1829333, 1828721, 1828138, 1827581, 1827050, 1826544, 1857812, 1858415, 1858939, 1859389, 1859769, 1860078, + 1860316, 1860479, 1860562, 1860560, 1860468, 1860282, 1859997, 1859612, 1859126, 1858539, 1857855, 1857079, 1856220, 1855286, + 1854289, 1853239, 1852150, 1851032, 1849896, 1848753, 1847612, 1846480, 1845364, 1844269, 1843200, 1842159, 1841149, 1840172, + 1839229, 1838321, 1837447, 1836608, 1835802, 1835030, 1834290, 1833582, 1832905, 1832257, 1831638, 1831047, 1830482, 1829943, + 1829428, 1859974, 1860581, 1861110, 1861566, 1861954, 1862274, 1862525, 1862704, 1862806, 1862826, 1862760, 1862603, 1862351, + 1862002, 1861553, 1861007, 1860365, 1859633, 1858816, 1857924, 1856967, 1855956, 1854901, 1853815, 1852708, 1851589, 1850469, + 1849354, 1848252, 1847169, 1846108, 1845073, 1844067, 1843092, 1842149, 1841240, 1840363, 1839520, 1838710, 1837933, 1837187, + 1836473, 1835789, 1835134, 1834508, 1833909, 1833336, 1832789, 1832266, 1862096, 1862705, 1863238, 1863701, 1864097, 1864427, + 1864691, 1864885, 1865005, 1865046, 1865004, 1864874, 1864653, 1864338, 1863926, 1863419, 1862817, 1862126, 1861352, 1860501, + 1859584, 1858610, 1857591, 1856536, 1855457, 1854364, 1853266, 1852169, 1851083, 1850011, 1848959, 1847931, 1846930, 1845958, + 1845016, 1844106, 1843228, 1842382, 1841568, 1840787, 1840036, 1839316, 1838625, 1837964, 1837331, 1836724, 1836144, 1835589, + 1835059, 1864177, 1864789, 1865326, 1865794, 1866197, 1866537, 1866813, 1867021, 1867158, 1867219, 1867200, 1867096, 1866905, + 1866621, 1866245, 1865775, 1865213, 1864562, 1863828, 1863017, 1862139, 1861203, 1860218, 1859196, 1858146, 1857079, 1856003, + 1854926, 1853855, 1852796, 1851755, 1850735, 1849740, 1848771, 1847831, 1846922, 1846042, 1845194, 1844378, 1843592, 1842836, + 1842111, 1841415, 1840747, 1840107, 1839494, 1838907, 1838345, 1837807, 1866235, 1866849, 1867390, 1867863, 1868273, 1868621, + 1868908, 1869129, 1869282, 1869361, 1869364, 1869285, 1869120, 1868867, 1868524, 1868090, 1867565, 1866953, 1866258, 1865487, + 1864647, 1863747, 1862797, 1861807, 1860786, 1859745, 1858691, 1857634, 1856580, 1855535, 1854505, 1853494, 1852505, 1851540, + 1850603, 1849694, 1848815, 1847965, 1847146, 1846357, 1845597, 1844867, 1844165, 1843492, 1842846, 1842226, 1841632, 1841063, + 1840518, 1868253, 1868869, 1869412, 1869890, 1870306, 1870663, 1870960, 1871193, 1871361, 1871458, 1871481, 1871425, 1871287, + 1871063, 1870752, 1870351, 1869863, 1869288, 1868631, 1867898, 1867095, 1866232, 1865316, 1864358, 1863367, 1862352, 1861322, + 1860285, 1859249, 1858219, 1857200, 1856199, 1855217, 1854258, 1853324, 1852417, 1851538, 1850688, 1849866, 1849074, 1848311, + 1847576, 1846870, 1846191, 1845539, 1844913, 1844313, 1843737, 1843185, 1870229, 1870847, 1871393, 1871875, 1872298, 1872662, + 1872968, 1873214, 1873396, 1873510, 1873552, 1873518, 1873405, 1873209, 1872928, 1872560, 1872106, 1871568, 1870948, 1870252, + 1869486, 1868658, 1867777, 1866851, 1865889, 1864901, 1863895, 1862880, 1861861, 1860847, 1859842, 1858850, 1857876, 1856924, + 1855994, 1855090, 1854212, 1853361, 1852539, 1851744, 1850978, 1850240, 1849529, 1848845, 1848188, 1847557, 1846950, 1846368, + 1845810, 1872164, 1872783, 1873333, 1873819, 1874247, 1874619, 1874934, 1875191, 1875386, 1875516, 1875577, 1875564, 1875475, + 1875306, 1875053, 1874717, 1874296, 1873793, 1873209, 1872549, 1871820, 1871027, 1870179, 1869285, 1868354, 1867393, 1866412, + 1865418, 1864419, 1863420, 1862429, 1861448, 1860484, 1859538, 1858613, 1857712, 1856836, 1855987, 1855163, 1854368, 1853599, + 1852857, 1852143, 1851455, 1850793, 1850156, 1849545, 1848957, 1848393, 136533, 136533, 136533, 136533, 136533, 136533, + 136533, 136533, 136533, 136533, 136533, 136533, 136533, 136533, 136533, 135924, 125277, 108081, 91368, 77552, + 66660, 58112, 51334, 45876, 41412, 37706, 34587, 31931, 29644, 27657, 25914, 24375, 23005, 21780, + 20677, 19679, 18772, 17944, 17186, 16489, 15845, 15250, 14698, 14184, 13704, 13256, 12836, 12442, + 12071, 11721, 11392, 11080, 10784, 10504, 10238, 9986, 9745, 9516, 9297, 9088, 8888, 8697, + 8513, 8338, 8169, 8007, 7852, 7702, 7558, 7419, 7285, 7156, 7031, 6911, 6795, 6682, + 6574, 6468, 6366, 6267, 6172, 6079, 5989, 5901, 5816, 5733, 5653, 5575, 5499, 5425, + 5353, 5283, 5215, 5148, 5083, 5020, 4959 +]; +/// NMOS drain current in pA at 1000 centres of the log grid's cells, point k = 1 .. 1000 at Vgs = (floor(96 frac(k a1)) + 1/2) * 15.625 mV, Vds = (floor(48 frac(k a2)) + 1/2) * 31.25 mV (deck psp103_idpa_tt.cir, block cen_n). +pub const TT_CEN_N : [1000]u32 = [ + 213747387, 51417686, 6380591, 273, 238125698, 80149784, 10004061, 1007, 115214019, 95941398, 9759186, 3358, 235254453, 111244850, + 15340614, 3453, 266639871, 100100325, 19118724, 15477, 292527431, 125196889, 16507118, 53888, 199744836, 144336232, 25980085, 167147, + 295769269, 64071405, 34779823, 124989, 330041553, 145379657, 44320923, 434233, 97494589, 171584610, 41480548, 1160577, 290395450, 191945563, + 55143580, 947594, 360436771, 143003997, 67587056, 2555913, 387765708, 202259318, 23888367, 5025157, 146, 229123785, 73137016, 8247945, + 583, 47606436, 89211819, 7850974, 1951, 211304931, 104728467, 11096933, 1496, 256268009, 81719492, 16425373, 8467, 282472727, + 117548763, 6499319, 30965, 157114050, 136452874, 22368369, 100965, 277263808, 7652660, 31028796, 66325, 318291291, 133519203, 40004181, + 259866, 11317217, 162445670, 35198707, 769443, 246300088, 183791620, 49807449, 1776157, 346306887, 99456609, 57754128, 1821395, 376130608, + 189031513, 69972689, 3854704, 123926625, 219295085, 65553935, 6683821, 327, 241677749, 82977828, 5954465, 1127, 181606128, 98019670, + 9035717, 3628, 243834248, 50928784, 14048474, 4528, 272212403, 108923129, 19766874, 17560, 89317275, 128580720, 19186875, 59401, + 252514150, 140539243, 27280133, 33573, 307200050, 113535468, 35880945, 153836, 335534475, 152982639, 21688089, 489358, 188019742, 175145925, + 44573192, 1251473, 320455376, 41867393, 52838276, 1202030, 363860426, 175429455, 64512210, 2863913, 58066277, 209165590, 55345182, 5361567, + 180, 232321302, 76405939, 2328465, 659, 137901439, 91416764, 7296538, 2124, 229448424, 18564189, 11768585, 2356, 262565990, + 99258344, 17062636, 10076, 10470093, 120690188, 15808085, 21330, 226414989, 132952013, 23727003, 8377, 293637705, 81549873, 32127819, + 85359, 324695740, 144025700, 40984563, 299106, 134881943, 166448870, 36079676, 838847, 295059195, 186554405, 47825963, 741299, 352284018, + 153025209, 59215742, 2089158, 382127599, 198515122, 41934249, 4163789, 233500999, 216587286, 69837740, 5817736, 376, 79727367, 84916423, + 5649497, 1239, 214825462, 99843790, 9695473, 1258, 251725525, 86220134, 14663928, 5565, 276568231, 107885556, 10806625, 12257, + 181616024, 125422909, 20368441, 39966, 277797975, 47783350, 28401392, 45552, 314504554, 132823512, 36869551, 180580, 54166477, 157654920, + 31476342, 540370, 260009559, 178111986, 42971165, 353102, 337980279, 118829103, 54319601, 1430560, 370888230, 188365321, 13849413, 3143189, + 180988987, 207187924, 63110504, 4624433, 213, 9469540, 78891968, 4210282, 719, 191341827, 93324349, 7927942, 298, 240220455, + 70250637, 12370662, 1862, 267292047, 100076242, 17646836, 7123, 122283914, 117943089, 17422255, 23377, 257674916, 135114133, 24875291, + 24628, 302874156, 117994633, 29996472, 103377, 322173695, 149432239, 24432290, 335326, 224430212, 169669914, 38266575, 903652, 321271970, + 70099480, 49365821, 925759, 359170551, 175306848, 60520098, 1768415, 101095460, 197611100, 56625542, 3557548, 307804594, 219945851, 72600993, + 2882172, 422, 156677313, 86923812, 6262354, 1343, 227493711, 37285138, 10282596, 1028, 257176911, 91901066, 15226046, 4022, + 50163207, 110964929, 14438142, 13576, 236556266, 127704284, 21550736, 11992, 283551384, 94608677, 26485696, 57383, 312520724, 140261149, + 8912514, 205245, 165707696, 161210230, 34030432, 587836, 300287748, 24788814, 44583002, 560471, 348145027, 153224581, 55423439, 1205944, + 11688380, 188627876, 46610759, 2658330, 271855206, 210866286, 66374934, 653785, 243, 107607633, 80964909, 4800076, 485, 214951525, + 89744228, 8398345, 534, 246778898, 83923128, 12917541, 2242, 271137272, 103574748, 11349988, 7963, 200444235, 120368650, 18612038, + 25289, 269888705, 67762999, 23179624, 30864, 301905123, 130406261, 30832971, 120027, 93574490, 153282129, 29566726, 368918, 278683369, + 172402060, 39971177, 218716, 334979272, 128589203, 50714708, 781817, 365352841, 178443228, 27423862, 1919343, 212986308, 201713898, 60662158, + 3781529, 349589961, 61406099, 70143245, 3540768, 288, 196436274, 83578307, 6801710, 263, 235934720, 71854138, 10812815, 1230, + 261432122, 96158713, 6967489, 4564, 150230622, 113495556, 13706829, 14803, 256481294, 20764195, 20079736, 16829, 290926047, 118711931, + 27321674, 68437, 10911828, 144752439, 24729556, 228067, 242549186, 157744718, 35797372, 52009, 320159840, 100954869, 45974558, 478788, + 355086099, 167345976, 56625906, 1355372, 140454338, 192446910, 54383802, 2854809, 321888376, 213960783, 64308427, 2562456, 380314631, 169652450, + 77821697, 5315559, 524, 225681760, 50794256, 8910082, 687, 251586616, 88607055, 13419685, 2593, 101332460, 106317523, 11217053, + 8742, 236849007, 122476750, 17333873, 8541, 279389776, 105844085, 24015574, 38091, 306614760, 136064055, 16067800, 85000, 192862161, + 149637115, 31534146, 259381, 305664733, 52622296, 41414076, 287032, 343462875, 154115646, 51919667, 901438, 56683406, 183758248, 47181207, + 2087351, 285835932, 205067235, 58587897, 1571782, 364773413, 140516214, 71942732, 4026458, 313, 213125785, 16252578, 7284106, 363, + 241539728, 81504794, 9663846, 1457, 29478832, 99192216, 8912295, 5066, 209323939, 115669199, 14650137, 2012, 268469805, 81814273, + 20916016, 21419, 296287983, 121484117, 2798482, 48968, 128833016, 142033601, 27420030, 156389, 284410711, 160197951, 37263403, 156658, + 331131654, 139907857, 47205376, 570553, 360386399, 174127170, 33050479, 1492783, 236882215, 196132267, 53360407, 3037586, 346218626, 90173115, + 66204536, 3001701, 389579751, 197984000, 79349555, 5774295, 186, 225277173, 72419714, 7925524, 831, 248272192, 92095208, 6805398, + 2917, 169554958, 108623117, 12175103, 9469, 254922582, 43967317, 18154339, 7036, 285692210, 113142079, 24773489, 27760, 72377811, + 133954268, 23360636, 93965, 255342724, 152247762, 33074300, 78542, 317655359, 114605340, 42675203, 353351, 342127979, 163973592, 17754215, + 1011297, 173656364, 187729341, 47829062, 2243132, 327662134, 26606308, 60606105, 2092714, 376705366, 177337086, 73522890, 3573807, 86, + 214812496, 58427248, 6442951, 455, 238762052, 85530325, 1266772, 1667, 129609635, 101661542, 9909090, 5532, 238616031, 117281157, + 15470288, 3630, 275730439, 102280173, 21669028, 15905, 300565732, 125820905, 19375256, 54835, 214494696, 144761550, 29066873, 169230, + 304682033, 75681442, 34972433, 202432, 331058111, 154227929, 44489228, 655004, 117305377, 178680557, 42170527, 1619945, 298225280, 199211296, + 55465874, 1367776, 362563619, 150633605, 67846276, 2609462, 396223503, 203654467, 40284111, 5083293, 244, 229806371, 78373531, 8309963, + 965, 65349880, 94777320, 7998628, 3216, 216876196, 105034395, 12995043, 1772, 264343732, 86374184, 18772001, 8744, 290482511, + 118244112, 10676203, 31581, 173859486, 136908980, 25235908, 102319, 280835249, 22840958, 31221581, 110016, 319504116, 141167159, 40174082, + 404941, 33552275, 169465384, 36508514, 1112679, 257697016, 190976003, 50154406, 235635, 348990851, 111120432, 62321414, 1867863, 384627048, + 191096901, 5257503, 3908200, 128, 220066785, 70748716, 6799476, 542, 242215320, 88388948, 6135906, 1146, 193447333, 98339303, + 10728779, 3672, 252027265, 59443259, 16199052, 4705, 280198188, 109807458, 22355737, 18354, 108454666, 129075834, 19444451, 60282, + 258187779, 147117888, 27477764, 56908, 308614915, 122556375, 36052789, 246056, 336331597, 159945894, 25656876, 732780, 217566527, 182243705, + 44957703, 1266042, 330312119, 57164543, 57223730, 1241385, 372428375, 178421197, 69301167, 2912314, 80957273, 210067917, 61059378, 5414917, + 300, 233470095, 76858744, 3817574, 672, 152387219, 91752684, 8795886, 2152, 237963273, 29776206, 13716814, 2467, 270526799, + 100622035, 19449818, 10332, 30951079, 121237484, 16157425, 35116, 234334544, 139412017, 23930619, 26083, 295502402, 92948854, 32298701, + 139654, 325598304, 150957140, 3623453, 462347, 152781213, 167029070, 39818237, 849947, 306172423, 8609914, 52016808, 772525, 360932768, + 158397764, 63823699, 2131290, 390538228, 199631542, 48811508, 4212698, 248446126, 224123432, 70355300, 7076184, 384, 96722697, 85618642, + 6946714, 1256, 223827232, 100127877, 11442575, 1324, 259686613, 88995640, 14761019, 5730, 277214582, 113941592, 12143207, 20250, + 193371951, 131759016, 20784909, 65367, 280471648, 60916942, 28574656, 75902, 315504418, 139915285, 37025152, 184829, 75485499, 158305006, + 35070839, 548513, 273150815, 178563659, 46961571, 465270, 346848396, 127905982, 58748117, 1466746, 379320220, 189736867, 21860496, 3187294, + 198614764, 214663036, 63767764, 5720751, 218, 28294917, 79261233, 5306760, 730, 201718553, 93619474, 9484586, 576, 248226652, + 75148885, 12465322, 3121, 267983018, 106007498, 2000196, 11795, 137927555, 124149992, 17636923, 38404, 261838069, 7483593, 25051391, + 41535, 304069584, 121086720, 33262724, 106247, 330357788, 150147594, 28462621, 341097, 239462769, 170154200, 42050789, 914055, 330578159, + 83157888, 53603094, 955570, 361423560, 177378085, 60724833, 2370572, 121813499, 205029071, 57548511, 4492490, 316743404, 227483436, 72999709, + 3827859, 430, 169356726, 87231947, 7622495, 1359, 230811981, 47442234, 10374573, 1729, 257951246, 97750202, 15315284, 6678, + 69003525, 117041941, 14674597, 22372, 242452031, 134066667, 21730271, 12988, 291889211, 105819128, 29547459, 59285, 320685474, 141127828, + 14675827, 209170, 183479312, 161735249, 37613477, 595438, 310454211, 40298540, 44828209, 583468, 349464296, 161728695, 55837656, 1672439, + 34693521, 195990242, 48874290, 3439106, 283414693, 218337053, 66815277, 1921739, 247, 122967289, 81280963, 4890530, 797, 217281118, + 6037221, 8487319, 903, 247669714, 89785215, 13004093, 3734, 10234950, 109512961, 11777405, 13147, 209723696, 120739297, 18791030, + 25597, 278432999, 76759712, 26034656, 32100, 310061665 +]; +/// PMOS drain current in pA at 1000 centres of the log grid's cells, point k = 1 .. 1000 at Vgs = (floor(96 frac(k a1)) + 1/2) * 15.625 mV, Vds = (floor(48 frac(k a2)) + 1/2) * 31.25 mV (deck psp103_idpa_tt.cir, block cen_p). +pub const TT_CEN_P : [1000]u32 = [ + 147018599, 32335025, 1335850, 24, 162478093, 47682766, 2441310, 62, 80505311, 56317166, 3522066, 162, 167067461, 65016308, + 5634502, 387, 188614817, 64636659, 6977591, 1039, 205631906, 79054540, 8034515, 2759, 141567458, 89999128, 12174479, 7329, + 215368583, 43775826, 16326126, 11264, 240522787, 96834984, 21011774, 30003, 69506630, 112483819, 23131953, 79017, 211649157, 124873280, + 29949502, 174239, 269670621, 98486214, 36500309, 435254, 289534622, 139220649, 15578099, 952547, 15, 156106267, 43625425, 1841353, + 39, 33443962, 52305534, 2734682, 101, 149094845, 60897034, 3696321, 199, 181056991, 53400730, 5770753, 640, 198440778, + 74191727, 3541266, 1699, 110760047, 85018978, 10388679, 4517, 200789307, 5293198, 14325114, 6904, 231770183, 89001932, 18696653, + 18486, 8133222, 106615343, 19824363, 49016, 177148809, 119291390, 26995432, 127479, 257945387, 68532549, 30536888, 286395, 280508897, + 130143365, 36997379, 659615, 88980444, 149452393, 39313360, 1352166, 24, 163660889, 48498703, 2030599, 63, 127053933, 56819871, + 2888842, 168, 172201903, 33903627, 4711099, 394, 191173198, 68952644, 7059400, 1047, 62991103, 80105292, 8782343, 2781, + 181307868, 86091465, 12428172, 4157, 223279814, 76011527, 16522196, 11391, 243176586, 100587436, 12948254, 30280, 133957863, 113627051, + 24134635, 79722, 236374681, 29074216, 27700207, 183681, 270964058, 120581382, 33852587, 444005, 41847390, 142650281, 33721836, 967205, + 15, 157213700, 44670394, 822428, 40, 95995902, 52853271, 2216108, 104, 161798106, 12552774, 3770011, 242, 184161899, + 63131137, 5846697, 646, 7446829, 75238938, 7196652, 1062, 161218829, 81285859, 10668628, 1160, 213033288, 55026399, 14518556, + 7000, 235159909, 94713527, 18867076, 18660, 95851102, 107996441, 19179508, 49443, 215463018, 120071039, 24938125, 115379, 261721004, + 105015188, 30840126, 292227, 283737084, 135523872, 26154982, 670203, 168232836, 145469005, 40888318, 986656, 25, 55596238, 48994853, + 1647028, 65, 150988245, 57240635, 2957046, 148, 176582497, 55351545, 4779426, 399, 192870296, 66610640, 5199912, 655, + 128112025, 76571205, 9043139, 1737, 200842966, 32527687, 12625987, 4296, 227426164, 87609538, 16691575, 11501, 38610017, 102368719, + 16690276, 30541, 187510388, 114488312, 22301781, 59806, 250377058, 81499743, 28008188, 187748, 275100930, 128527004, 9011000, 451328, + 129697034, 139162285, 37062334, 685515, 16, 6667500, 45336272, 1184586, 41, 133799191, 53298814, 2276326, 41, 168534394, + 45595525, 3832063, 153, 186092611, 61922510, 5914631, 405, 85947867, 71942395, 7592401, 1071, 185155850, 81824595, 10873781, + 2636, 218878961, 78169168, 12887100, 7072, 230912221, 96963493, 13368750, 18821, 160339164, 108969776, 19784340, 49855, 236870851, + 48308572, 25263969, 118644, 266110530, 119705167, 31100645, 192617, 72473306, 132804023, 33313056, 461741, 225683472, 146535646, 41688672, + 802601, 26, 108940322, 49472905, 1702739, 69, 159550318, 24648345, 3012725, 95, 179016666, 57063655, 4840036, 250, + 35427652, 67520324, 6216403, 661, 168777355, 77148949, 9260786, 1536, 203874082, 63147516, 11133987, 4347, 223611452, 91199253, + 5308388, 11601, 117472135, 103504924, 17461007, 30791, 219718370, 17220117, 22653113, 73986, 257428436, 104173483, 28228049, 121789, + 8445835, 126676379, 27988790, 303021, 197142392, 140386899, 38122403, 212162, 17, 74706350, 45837850, 1238357, 29, 150443721, + 50103954, 2316685, 58, 171802495, 52217071, 3886309, 155, 187467925, 63049347, 4887680, 409, 141633748, 72571376, 7816896, + 1082, 193734717, 45584944, 9521829, 2670, 215905933, 85033139, 13017936, 7137, 66350924, 98256590, 15140588, 18976, 202217744, + 109730849, 20174209, 28490, 247226523, 87482792, 25532813, 76139, 269446363, 120006150, 17232911, 194650, 152770066, 134260603, 34760053, + 467312, 260806056, 42784562, 39093666, 873062, 19, 137074997, 46426175, 1744196, 34, 164312512, 45265282, 3060497, 96, + 180628205, 58614869, 3215853, 253, 105440099, 68189682, 5396586, 667, 183523214, 14200708, 8049718, 1642, 207982303, 77721245, + 11261295, 4389, 7800765, 92866850, 12746362, 11696, 173895144, 99546390, 17883715, 7819, 235547727, 68785105, 22933104, 47232, + 261416154, 112729730, 28460672, 123283, 100356748, 128128121, 31249089, 306616, 237444086, 141324294, 35754983, 599949, 286491708, 117827215, + 42930900, 1274050, 36, 157023481, 32808057, 2357965, 60, 173764382, 54147677, 3934944, 157, 70973908, 63808169, 4325675, + 413, 168593384, 73088541, 6737487, 1000, 199664820, 69523206, 9645667, 2699, 217894674, 87434952, 8839608, 4452, 136850320, + 94350088, 15663620, 11834, 223876940, 36157841, 20469950, 29211, 252614431, 103982331, 25763795, 77065, 40679511, 122226374, 27365328, + 196892, 208003963, 135314630, 32523666, 373770, 273643470, 97248400, 39502336, 904039, 23, 148289559, 10818251, 1778097, 37, + 166829740, 49833149, 2415842, 97, 20795615, 59511192, 3370944, 256, 147840013, 68727449, 5540513, 276, 191564904, 54322603, + 8170240, 1663, 210433955, 77681709, 1650267, 2740, 91055599, 89361853, 13554734, 7282, 206757077, 100195538, 18188390, 17923, + 243241037, 94396507, 23168545, 47822, 263979570, 115968249, 19564516, 124636, 170165844, 129346675, 29494856, 309980, 258037944, 62467184, + 36197280, 625884, 292947910, 137596125, 43258903, 1301903, 23, 154605569, 44620205, 1820608, 61, 169276386, 55282673, 2538076, + 159, 118815127, 64391918, 4477540, 419, 181654954, 29665992, 6851370, 634, 202841259, 72397500, 9754293, 1687, 51272165, + 84298235, 11515340, 4488, 183684739, 95056058, 15998921, 10445, 232878112, 77536526, 20711722, 29592, 249290860, 109400413, 10968763, + 77889, 123774859, 123597819, 26444124, 198983, 242386494, 18593918, 33014206, 418604, 282711545, 122887438, 39843553, 649517, 12, + 147526706, 36721911, 1339231, 38, 162698722, 51265133, 567242, 99, 90527748, 60157982, 3544492, 259, 169513349, 69110474, + 5651410, 389, 195512781, 65795293, 8274182, 1040, 212116634, 79260548, 9563720, 2763, 152563375, 90112581, 13942072, 7339, + 222638947, 51541435, 16361112, 18218, 241047479, 102907456, 21041726, 48331, 83529961, 117684064, 23375807, 125896, 217994823, 130268278, + 30026233, 270311, 271306907, 103726197, 36555720, 436852, 296828444, 139979735, 25893920, 955111, 23, 156352073, 47091384, 1845314, + 62, 45796130, 56021060, 2757606, 161, 153201997, 60967974, 4586327, 227, 187414794, 56142240, 6932942, 641, 204857199, + 74438429, 5759615, 1701, 122847775, 85144298, 12011604, 4523, 203560555, 15756600, 14359882, 11183, 232461396, 94417494, 18726501, + 29857, 24042465, 111725736, 20324758, 78652, 185863905, 124592416, 27083167, 48279, 260105272, 76472283, 33395724, 287479, 287782707, + 131414093, 3497038, 661478, 14, 149751924, 42707781, 1358323, 38, 163830617, 52089088, 2062638, 63, 135812028, 56894795, + 3652993, 170, 178603147, 39321954, 5743173, 395, 197524293, 69312284, 8366345, 1050, 76496042, 80247200, 8844104, 2785, + 185719687, 90722223, 12464189, 6804, 224147509, 82235297, 16552028, 18425, 243526788, 105621660, 14980187, 48795, 155520671, 118831147, + 24241220, 79838, 244605936, 39574975, 30423039, 184476, 278247000, 122533260, 36860109, 445305, 58301044, 143036696, 37311805, 969498, + 24, 157587121, 44798375, 1349907, 40, 106310002, 52933351, 2861837, 105, 168392931, 20001363, 4673099, 243, 190449675, + 63777441, 7019621, 647, 21947019, 75405593, 7290410, 1715, 167217587, 85805626, 10706659, 3514, 214303958, 62735521, 14547717, + 11331, 235587327, 99688149, 2266673, 30144, 108557558, 108179317, 21466546, 49513, 224556146, 6013346, 27520978, 116154, 269025982, + 108651645, 33711865, 293076, 290962590, 136064470, 30387992, 671847, 179404943, 151200291, 41049661, 1372959, 25, 67443502, 49165563, + 2177880, 65, 157883957, 57304814, 3734966, 149, 182823554, 56848274, 4789998, 399, 193103816, 70779917, 5618275, 1057, + 136621781, 80977827, 9123598, 2807, 202822247, 41406985, 12655320, 6958, 227928562, 92640705, 16717786, 11518, 53761277, 102588288, + 18853469, 30583, 197862811, 114614061, 24743025, 71468, 257819550, 87648807, 30744592, 188309, 282291830, 129256576, 14052584, 452454, + 142452203, 144808746, 37296565, 982542, 16, 19882311, 45428564, 1608183, 41, 141567316, 53365958, 2936038, 77, 174763447, + 48449911, 3841573, 246, 186351041, 65982338, 1068424, 653, 96921960, 76233831, 7636410, 1729, 188356222, 5166455, 10903523, + 4273, 219543702, 79995431, 14708672, 7083, 237659204, 97220470, 15623917, 18847, 171748805, 109108335, 22082610, 49923, 244625272, + 57169549, 27861357, 119024, 267392962, 120954563, 31140847, 297698, 87218840, 138368679, 33675453, 681157, 233003687, 152273222, 41793470, + 1134415, 26, 118100620, 49543831, 2248290, 70, 161551623, 31281071, 3021152, 152, 179326550, 61037173, 4849539, 403, + 48621226, 71696482, 6271414, 1066, 173277990, 81566402, 9291319, 1593, 210579403, 70146523, 12815389, 4354, 230297426, 91550077, + 8674902, 11617, 130370255, 103660983, 19618312, 30832, 228082813, 27891990, 22703761, 74282, 258242941, 110315177, 28308901, 191296, + 24996696, 132162355, 29024575, 458791, 206163890, 146036681, 38247151, 616951, 17, 85460041, 45911215, 1245114, 43, 151978841, + 4082744, 2324026, 94, 172191432, 56149236, 3894760, 249, 7261267, 67107195, 4991669, 659, 148470355, 72664008, 7847305, + 1084, 200555884, 51415089, 11063444, 2676, 222536257 +]; + ; --- the accessors and the tests ------------------------------------------------------------------------ /// The fold of the first n entries of t after the state s. Order matters. @@ -2769,3 +3654,98 @@ test the_500_fF_waveform_is_the_numbers_ngspice_printed { t[200] = t[200] + 1; assert fold_arr(&t, 401, 0) != fold_arr(&INV500_BE, 401, 0); } + +test the_log_domain_tables_are_the_numbers_ngspice_printed { + // M3c-2 (#10881). The two tables, the tag word first, in the order N then P, and the 1000 + 1000 held-out currents: the pins see one changed number. + var s : u64 = fold_arr(&TT_LG_N, 4851, 0); + s = fold_arr(&TT_LG_P, 4851, s); + assert_eq(s, PIN_TT_LG); + var c : u64 = fold_arr(&TT_CEN_N, 1000, 0); + c = fold_arr(&TT_CEN_P, 1000, c); + assert_eq(c, PIN_TT_CEN); + // The layout: the tag word, 97 * 49 words of log2(Id / F), 97 words of rv. The format constants agree with it and with the 1.5 V supply. + var gn : u32 = LOG_NODES_G; + var dn : u32 = LOG_NODES_D; + var gstep : u32 = LOG_GRID_G_UV; + var dstep : u32 = LOG_GRID_D_UV; + assert_eq(gn * dn, 4753); + assert_eq(1 + gn * dn + gn, 4851); + assert_eq((gn - 1) * gstep, 1000 * VDD_MV); + assert_eq((dn - 1) * dstep, 1000 * VDD_MV); + var fbits : u32 = LOG_FRAC_BITS; + var ubits : u32 = LOG_FINE_BITS; + assert_eq(fbits, 16); + assert_eq(ubits, 8); + assert_eq(TT_LG_N[0], 4294967295); + assert_eq(TT_LG_P[0], 4294967295); + // Every log word is under 2^21 (the reader's u64 interpolation needs under 2^23): at most 1.91 M, 29.1 octaves over 1.164 pA, 0.65 mA of Id / F at Vds = 0; at + // least 0.41 M (NMOS: 87 pA of off current) and 0.22 M (PMOS: 11 pA). + var lo_n : u32 = TT_LG_N[1]; + var hi_n : u32 = TT_LG_N[1]; + var lo_p : u32 = TT_LG_P[1]; + var hi_p : u32 = TT_LG_P[1]; + var i : usize = 1; + while (i <= 4753) { + if (TT_LG_N[i] < lo_n) { lo_n = TT_LG_N[i]; } + if (TT_LG_N[i] > hi_n) { hi_n = TT_LG_N[i]; } + if (TT_LG_P[i] < lo_p) { lo_p = TT_LG_P[i]; } + if (TT_LG_P[i] > hi_p) { hi_p = TT_LG_P[i]; } + i = i + 1; + } + assert_eq(hi_n, 1906797); + assert_eq(hi_p, 1875577); + assert_eq(lo_n, 406768); + assert_eq(lo_p, 215532); + assert hi_n < 2097152; + assert hi_p < 2097152; + // The rv words (the last 97 of a table) follow their formula, rv = nint(4096 / s) with s^2 = 0.03^2 + (0.65 max(Vgs - 0.23, 0))^2: rv^2 s^2 = 4096^2 to the + // rounding of rv (half a word, so 1 / rv in the square), for both tables alike, and they never rise with Vgs. + var k : usize = 0; + var steps : u32 = 0; + while (k < 97) { + const vg : f64 = ((k as f64) * (gstep as f64)) * 0.000001; + var ov : f64 = vg - 0.23; + if (ov < 0.0) { ov = 0.0; } + const s2 : f64 = 0.0009 + 0.4225 * ov * ov; + const rv : f64 = (TT_LG_N[4754 + k]) as f64; + const dev : f64 = (rv * rv * s2) / 16777216.0 - 1.0; + assert dev * dev * rv * rv < 1.21; + assert_eq(TT_LG_N[4754 + k], TT_LG_P[4754 + k]); + if (k > 0) { + assert TT_LG_N[4754 + k] <= TT_LG_N[4754 + k - 1]; + steps = steps + 1; + } + k = k + 1; + } + assert_eq(steps, 96); + assert_eq(TT_LG_N[4754], 136533); + assert_eq(TT_LG_N[4850], 4959); + // The held-out currents at cell centres: all positive, the smallest 86 pA (NMOS) and 12 pA (PMOS), the largest 396 uA and 297 uA. + var cmin_n : u32 = TT_CEN_N[0]; + var cmax_n : u32 = TT_CEN_N[0]; + var cmin_p : u32 = TT_CEN_P[0]; + var cmax_p : u32 = TT_CEN_P[0]; + i = 0; + while (i < 1000) { + if (TT_CEN_N[i] < cmin_n) { cmin_n = TT_CEN_N[i]; } + if (TT_CEN_N[i] > cmax_n) { cmax_n = TT_CEN_N[i]; } + if (TT_CEN_P[i] < cmin_p) { cmin_p = TT_CEN_P[i]; } + if (TT_CEN_P[i] > cmax_p) { cmax_p = TT_CEN_P[i]; } + i = i + 1; + } + assert_eq(cmin_n, 86); + assert_eq(cmin_p, 12); + assert_eq(cmax_n, 396223503); + assert_eq(cmax_p, 296828444); + // The count constant, and a pin sees one changed number in a table of this size too. + var ncen : u32 = LOG_CEN_COUNT; + assert_eq(ncen, 1000); + var t : [4851]u32 = [0] ** 4851; + i = 0; + while (i < 4851) { + t[i] = TT_LG_N[i]; + i = i + 1; + } + t[2000] = t[2000] + 1; + assert fold_arr(&t, 4851, 0) != fold_arr(&TT_LG_N, 4851, 0); +} diff --git a/specs/analog/mos_table.t27 b/specs/analog/mos_table.t27 index 4667678abe..0793ffbf68 100644 --- a/specs/analog/mos_table.t27 +++ b/specs/analog/mos_table.t27 @@ -11,6 +11,32 @@ ; nondecreasing along Vds. The tests of the generalization are the last three: zero charge is the old path bit for bit; a plane of charge (no ; current) gives the closed form of the gate-edge kick and the load, for an NMOS-side and a PMOS-side charge; the mirror holds with the four tables ; swapped. mos_psp103.t27 runs it on the PSP103 tables. +; M3c-2 (#10881, part 3 of #10777) adds the weak-inversion-accurate current, THE LOG-DOMAIN READER below, as a generalization of the read and not a copy of it: `read_w` is the bilinear +; read of any uniform grid (id_of is its 24 x 24 cell case, bit for bit, a test), a log table is a slice with a tag word that `cur_of` and `cur_gds` tell from a linear one, and the +; Newton step, the charge path and M3a's pinned run are the same functions as before (`g_pos`, `g_neg` and `gq_deriv` read the current through `cur_of` / `cur_gds`). +; - +; THE LOG-DOMAIN READER, DESIGNED ON PAPER FIRST (M3c-2). The linear 25 x 25 table cannot give 1 % in weak inversion for two reasons that no finer read repairs: a word is 298 pA, so its +; rounding alone is 15 % of the 1 nA floor where 1 % allows 10 pA, and Id grows 6.5 .. 7 times per 62.5 mV cell, where a chord is 41 % above the exponential at the middle. So the table +; holds the LOG of the current and the reader takes an integer exp: +; the table lam = log2(Id / F) in 1/65536 of an octave (16 fraction bits: from 1 pA to 0.65 mA is under 2^21 words, the u64 blend needs under 2^23), in units of IUNIT = 2^-8 of a +; linear-table word = 1.164 pA. ln Id is nearly LINEAR in Vgs in weak inversion, so a chord of it is exact there. F = 1 - exp(-Vds / s(Vgs)) is the Vds factor of weak +; inversion, handled apart: Id is 0 at Vds = 0 (no log), and the first Vds cell is a 35 % chord error of Id on its own. The column Vds = 0 holds the limit of Id / F, +; s * gds0. s is a gate scale, 30 mV in weak inversion (the diffusion factor, exact) growing to 0.6 V in strong inversion (the channel is a resistor, F nearly linear): with +; one fixed s the first Vds cells are 5 % chords in strong inversion (Id / F = Vds / F grows 2.7 times over 2.4 s). +; the exp 2^(lam / 2^16) = a shift by the integer part and 2^f from a 129-entry table (2^-(i/128) in Q24, linear between its entries, 3.7e-6 off). F = 1 - 2^-(x log2 e) from the +; same table, and below x = 1/16 the series x - x^2 / 2 + x^3 / 6: a difference of two table values has an absolute error of 62 / 2^24, a whole F at x = 1e-3. +; the slope d(F E) / dVds = F' E + F E ln2 d(lam) / dVds with F' = rv e^-x: read off the same words (FR-002), the cell's two differences of lam along Vds blended along Vgs, their +; positive and negative parts apart (a log word may fall with Vds), the sum floored at 0. +; THE GRID. Error against grid and format, the worst relative error with a floor of 1e-9 A over every 7.8 mV lattice point that is not a node (a dense ngspice run of 193 x 193 points, a scratch +; study that is not in the repo) and at the repo's held-out points, NMOS / PMOS: +; the linear table, 62.5 mV x 62.5 mV, a chord on Id 0.55 .. 0.73 (the issue's measure at the midpoints and R2 points: the baseline) +; log(Id / F), F with a fixed 25.9 mV: 62.5 x 62.5 mV 44 %; 31.2 x 31.2 3.0 / 3.2 %; 15.6 x 15.6 mV 0.78 / 0.83 % (9409 words a device) +; log(Id / F), F with s(Vgs): 62.5 x 62.5 mV 6.1 / 5.3 %; 31.2 x 31.2 1.5 %; 15.6 x 62.5 1.5 / 1.8 %; 15.6 x 31.2 mV 0.51 / 0.71 % (4753 + 97 words) <- CHOSEN; 7.8 x 31.2 0.52 / 0.60 % +; Along Vgs the curvature of ln Id near threshold sets 15.6 mV (31.2 mV gives 1.5 % at every Vds); along Vds 31.2 mV (62.5 mV gives 1.5 .. 1.8 %, the knee between triode and +; saturation); 7.8 mV along Vgs gains 0.1 %, a finer Vds more than that only in the first cell. The tables and their format are in mos_psp103_data.t27, the deck psp103_idpa_tt.cir. +; THE THREE ERRORS of the read, apart (mos_psp103.t27): arithmetic (the integer read against its f64 twin on the same words) at most 0.102 % with a floor of 1 nA, which is one or two +; units of 1.164 pA at the floor's 859; table + model (against ngspice) 0.40 % / 0.53 % at the 1000 R2 points and 0.47 % / 0.71 % at 1000 centres of the grid's cells, 0.08 % / +; 0.09 % at the 576 midpoints (nodes of this grid: the rounding of the words only); discretization (the inverter's, ngspice backward Euler against converged) is not touched by the read. ; - ; THE CIRCUIT. The reference is mirekez/cpphdl, analog/examples/cmos_inverter: Vdd = 1.2 V, an NMOS from Y to ground and a ; PMOS from Y to Vdd, both gates on A, A = 0 V and then 1.2 V from 2 us, Y loaded by 10 pF, dt = 10 ns, stop at 4 us (400 @@ -88,9 +114,12 @@ ; the inverter's output node with a fixed three Newton iterations whose last residual is at most 1 unit (47.68 nV) at ; every one of 400 steps, ends the run at 0 V where cpphdl requires at most 1 mV, stays within 0.61 unit of the f64 ; model of the same iteration, within 0.428 mV of the analytic square law solved to convergence, and differs from its -; own dt / 2 run by at most 27.2 mV; the 400 samples fold to the S pinned below. +; own dt / 2 run by at most 27.2 mV; the 400 samples fold to the S pinned below. M3c-2: the same arithmetic reads any uniform grid and a table of log2(Id / F) with an integer exp +; (a table of 129 words and a shift), its slope off the same words, and is exact to a part in 1e5 of a closed-form current and slope (synthetic tables); the tests of mos_psp103.t27 hold it +; to ngspice at 1 %. ; WHAT IT DOES NOT SAY. Nothing about a transistor: the table is the square law, not PSP103 (M3b), and nothing here is a -; PDK corner. Nothing about a board: no bitstream, no clock, no LUT, DSP or BRAM, no division cost, no UART line. +; PDK corner; the log reader is exact on integer tables of known law and says nothing about any device by itself. No gm of a log table (it needs the slope of rv with Vgs: the +; Newton step here is scalar and uses gds only). Nothing about a board: no bitstream, no clock, no LUT, DSP or BRAM, no division cost, no UART line. ; Nothing about the continuous circuit: the 27 mV is the scheme at dt = 10 ns, and the table error adds to it. Nothing ; about a circuit with a second nonlinear node (the Newton here is scalar), a netlist (the reader is M2), a device ; with Vds < 0, or an input other than the two levels. Nothing about power or about speed against SPICE. cpphdl's @@ -239,14 +268,204 @@ pub fn gm_cell(t: []const u32, vg: u32, vd: u32) -> u32 { return blend1(d0, d1, frac_of(dv)); } +; --- the log-domain reader (M3c-2, #10881): the same table machinery on a grid of any cell size, and a current read in the log domain ---------- +; The tables read above are 25 x 25 words of 2^20 units. The generalization is the read of ANY uniform grid (`cell_w`, `blend_w`, `read_w`: cell sizes 2^bits, node counts as +; arguments, the weights 2^bits, the rounding half of the shift), of which `id_of` is the 24 x 24 cell case (a test: every read agrees), and on top of it a current whose table +; holds log2(Id / F) instead of Id, with the Vds factor F and the exp of a small table and a shift. THE FORMAT is in the header and in mos_psp103_data.t27; here is the +; arithmetic, all unsigned words: +; lam = the bilinear blend of the table's log words (16 fraction bits of an octave, under 2^21) -- the same `blend` with 2^18 and 2^19 weights +; rv = the linear blend along Vgs of the two rv words of the cell: x = Vds * rv / 2^36 (Q24: x24 = (vd * rv + 2^11) >> 12) +; F = 1 - exp(-x) in Q24: below x = 1/16 the series x - x^2/2 + x^3/6, above it 1 - 2^-(x log2 e) from the table EXP2NEG (2^-(i/128) in Q24, linear in between, a shift for the +; integer part) +; E = 2^(lam / 2^16) as an integer: 2^f from the same table (2 * 2^-(1 - f)), a shift for the integer part; Id = E * F in IUNIT = 2^-8 of a linear-table word +; The word an inverter step wants is the rounded Id / 2^8. The slope is read off the same words (FR-002): d(F E)/dVds = F' E + F E ln2 d(lam)/dVds, with F' = rv e^-x and d(lam) the +; blend along Vgs of the cell's two differences along Vds, its positive and negative parts apart (a log word may fall with Vds), in the units of `gds_cell` (words per 2^20 units). + +pub const LG_TAG : u32 = 4294967295; +/// The log tables' grid: 2^18 units (15.625 mV) along Vgs, 2^19 (31.25 mV) along Vds, 96 and 48 cells, 97 x 49 nodes. +pub const LG_GBITS : u32 = 18; +pub const LG_DBITS : u32 = 19; +pub const LG_NG : u32 = 96; +pub const LG_ND : u32 = 48; +/// Nodes along Vds, the log words in a table (97 * 49), the offset of the rv words (tag word, then the log words) and the table's length. +pub const LG_NODES_D : u32 = 49; +pub const LG_LAM_LEN : usize = 4753; +pub const LG_R_OFF : usize = 4754; +pub const LG_LEN : usize = 4851; +/// log2(e) and ln(2) in Q16. +pub const LOG2E_Q16 : u64 = 94548; +pub const LN2_Q16 : u64 = 45426; +/// 2^-(i/128) in Q24, i = 0 .. 128: 16777216 down to 8388608. +pub const EXP2NEG : [129]u32 = [ + 16777216, 16686609, 16596492, 16506861, 16417715, 16329050, 16240863, 16153153, 16065917, 15979152, + 15892855, 15807025, 15721658, 15636752, 15552304, 15468313, 15384775, 15301688, 15219050, 15136859, + 15055111, 14973805, 14892937, 14812507, 14732511, 14652947, 14573813, 14495106, 14416824, 14338964, + 14261526, 14184505, 14107901, 14031710, 13955931, 13880561, 13805598, 13731039, 13656884, 13583129, + 13509772, 13436812, 13364245, 13292070, 13220286, 13148888, 13077877, 13007249, 12937002, 12867135, + 12797645, 12728530, 12659789, 12591419, 12523418, 12455784, 12388516, 12321610, 12255067, 12188882, + 12123055, 12057584, 11992466, 11927700, 11863283, 11799215, 11735492, 11672114, 11609078, 11546382, + 11484025, 11422004, 11360319, 11298967, 11237946, 11177254, 11116891, 11056853, 10997140, 10937749, + 10878679, 10819928, 10761494, 10703375, 10645571, 10588079, 10530897, 10474024, 10417458, 10361198, + 10305242, 10249587, 10194234, 10139179, 10084422, 10029960, 9975792, 9921917, 9868333, 9815039, + 9762032, 9709311, 9656875, 9604722, 9552851, 9501261, 9449948, 9398913, 9348154, 9297668, + 9247455, 9197514, 9147842, 9098438, 9049301, 9000430, 8951823, 8903477, 8855394, 8807569, + 8760003, 8712694, 8665641, 8618841, 8572295, 8525999, 8479954, 8434157, 8388608 +]; + +/// The grid cell of a voltage on an axis of ncell cells of 2^bits units; the top node belongs to the last cell. `cell_of` is bits = 20, ncell = 24. +pub fn cell_w(v: u32, bits: u32, ncell: u32) -> u32 { + const c : u32 = v >> bits; + if (c >= ncell) { return ncell - 1; } + return c; +} + +/// The bilinear blend of four nodes with weights 2^bx along the first axis and 2^by along the second, rounded half up: `blend` is bx = by = 20. fx, fy in [0, 2^bx], [0, 2^by]. +pub fn blend_w(t00: u64, t10: u64, t01: u64, t11: u64, fx: u32, fy: u32, bx: u32, by: u32) -> u32 { + const wxu : u32 = 1 << bx; + const wyu : u32 = 1 << by; + const lo : u64 = t00 * ((wxu - fx) as u64) + t10 * (fx as u64); + const hi : u64 = t01 * ((wxu - fx) as u64) + t11 * (fx as u64); + return ((lo * ((wyu - fy) as u64) + hi * (fy as u64) + (((wxu as u64) * (wyu as u64)) >> 1)) >> (bx + by)) as u32; +} + +/// The linear blend of two cell differences d0 (at 0) and d1 (at 1) with the position f in [0, 2^bits], rounded half up: `blend1` is bits = 20. +pub fn blend1_w(d0: u64, d1: u64, f: u32, bits: u32) -> u64 { + const wu : u32 = 1 << bits; + const half : u32 = wu >> 1; + return (d0 * ((wu - f) as u64) + d1 * (f as u64) + (half as u64)) >> bits; +} + +/// The bilinear read of a table of (ncg + 1) x (ncd + 1) nodes stored from index off, index off + ix * (ncd + 1) + iy, cells of 2^gb units along the first axis and 2^db along the +/// second. `id_of` is off = 0, gb = db = 20, ncg = ncd = 24 on a 625-word table. +pub fn read_w(t: []const u32, off: usize, vg: u32, vd: u32, gb: u32, db: u32, ncg: u32, ncd: u32) -> u32 { + const gv : u32 = lim(vg); + const dv : u32 = lim(vd); + const cx : u32 = cell_w(gv, gb, ncg); + const cy : u32 = cell_w(dv, db, ncd); + const nd1 : usize = (ncd + 1) as usize; + const i00 : usize = off + ((cx as usize) * nd1) + (cy as usize); + return blend_w((t[i00]) as u64, (t[i00 + nd1]) as u64, (t[i00 + 1]) as u64, (t[i00 + nd1 + 1]) as u64, gv - (cx << gb), dv - (cy << db), gb, db); +} + +/// 2^-g for g in [0, 1] given in Q24, in Q24, from EXP2NEG, linear between its entries (rounded half up). The chord of 2^-x over 1/128 is at most 3.7e-6 off. +pub fn exp2neg(g: u64) -> u64 { + const i : u64 = g >> 17; + if (i >= 128) { return (EXP2NEG[128]) as u64; } + const j : u64 = g & 131071; + const a : u64 = (EXP2NEG[i as usize]) as u64; + const b : u64 = (EXP2NEG[(i + 1) as usize]) as u64; + return a - (((a - b) * j + 65536) >> 17); +} + +/// F = 1 - exp(-x) for x in Q24, in Q24: the series x - x^2 / 2 + x^3 / 6 below 1/16 (the term after it is under 2.6e-5 of F there, and a difference of two table values +/// would not hold F to a part in a thousand at x = 1e-3), 1 - 2^-(x log2 e) above, exactly 1 once the integer part of x log2 e reaches 25 (e^-x under 2^-25). +pub fn vds_factor(x24: u64) -> u64 { + if (x24 < 1048576) { return vds_series(x24); } + return 16777216 - exp_neg_tab(x24); +} + +/// e^-x for x in Q24, in Q24: 1 - F below 1/16, the table value itself above (not 1 - F, whose error of 62 units would be most of e^-x for x above 8): the slope of F, F' = rv e^-x. +pub fn exp_neg_q24(x24: u64) -> u64 { + if (x24 < 1048576) { return 16777216 - vds_series(x24); } + return exp_neg_tab(x24); +} + +/// The series of F: x - x^2 / 2 + x^3 / 6 in Q24 (x below 1/16). +pub fn vds_series(x24: u64) -> u64 { + const x2 : u64 = (x24 * x24 + 8388608) >> 24; + const x3 : u64 = (x2 * x24 + 8388608) >> 24; + return x24 - (x2 >> 1) + x3 / 6; +} + +/// e^-x from the table: 2^-(x log2 e), the fraction of the exponent from EXP2NEG, the integer part a shift; 0 once the integer part reaches 25. +pub fn exp_neg_tab(x24: u64) -> u64 { + const y24 : u64 = (x24 * LOG2E_Q16 + 32768) >> 16; + const k : u64 = y24 >> 24; + if (k >= 25) { return 0; } + return exp2neg(y24 & 16777215) >> k; +} + +/// 2^(lam / 2^16) as an integer: 2^f = 2 * 2^-(1 - f) from the table, shifted by the integer part of lam / 2^16, rounded half up. lam is under 2^21. +pub fn exp2_lam(lam: u32) -> u64 { + const k : u32 = lam >> 16; + const f : u32 = lam & 65535; + const m : u64 = 2 * exp2neg(((65536 - f) as u64) << 8); + return ((m << k) + 8388608) >> 24; +} + +/// rv at Vgs: the blend along Vgs of the two rv words of the cell, rounded half up. t is a log table (the tag word, the log words, the rv words). +pub fn lg_rv(t: []const u32, vg: u32) -> u64 { + const gv : u32 = lim(vg); + const cx : u32 = cell_w(gv, LG_GBITS, LG_NG); + const r0 : u64 = (t[LG_R_OFF + (cx as usize)]) as u64; + const r1 : u64 = (t[LG_R_OFF + (cx as usize) + 1]) as u64; + return blend1_w(r0, r1, gv - (cx << LG_GBITS), LG_GBITS); +} + +/// The log word of the table at (vg, vd): the blend of the four nodes, 16 fraction bits of an octave. +pub fn lg_lam(t: []const u32, vg: u32, vd: u32) -> u32 { + return read_w(t, 1, vg, vd, LG_GBITS, LG_DBITS, LG_NG, LG_ND); +} + +/// Id(vg, vd) of a log table in IUNIT = 2^-8 of a linear-table word (1.164 pA): F * 2^(lam / 2^16), both rounded. The largest, 402 uA, is 3.5e8 under 2^29. +pub fn lg_fine(t: []const u32, vg: u32, vd: u32) -> u64 { + const gv : u32 = lim(vg); + const dv : u32 = lim(vd); + const x24 : u64 = (((dv as u64) * lg_rv(t, gv)) + 2048) >> 12; + return (exp2_lam(lg_lam(t, gv, dv)) * vds_factor(x24) + 8388608) >> 24; +} + +/// Id(vg, vd) of a log table in table units (words of 298 pA), rounded half up: what the Newton step adds. +pub fn id_log(t: []const u32, vg: u32, vd: u32) -> u32 { + return ((lg_fine(t, vg, vd) + 128) >> 8) as u32; +} + +/// gds of a log table at (vg, vd): how much Id moves across 2^20 units of Vds, in words, the slope of the same read: F' E + F E ln2 d(lam)/dVds (see above), floored at 0. +pub fn gds_log(t: []const u32, vg: u32, vd: u32) -> u32 { + const gv : u32 = lim(vg); + const dv : u32 = lim(vd); + const cx : u32 = cell_w(gv, LG_GBITS, LG_NG); + const cy : u32 = cell_w(dv, LG_DBITS, LG_ND); + const r : u64 = lg_rv(t, gv); + const f : u64 = vds_factor((((dv as u64) * r) + 2048) >> 12); + const e : u64 = exp2_lam(lg_lam(t, gv, dv)); + const idf : u64 = (e * f + 8388608) >> 24; + const term1 : u64 = (((r * exp_neg_q24((((dv as u64) * r) + 2048) >> 12)) >> 24) * e) >> 24; + const nd1 : usize = (LG_NODES_D) as usize; + const i00 : usize = 1 + ((cx as usize) * nd1) + (cy as usize); + const a00 : u64 = (t[i00]) as u64; + const a01 : u64 = (t[i00 + 1]) as u64; + const a10 : u64 = (t[i00 + nd1]) as u64; + const a11 : u64 = (t[i00 + nd1 + 1]) as u64; + const fx : u32 = gv - (cx << LG_GBITS); + const up : u64 = blend1_w(dpos(a01, a00), dpos(a11, a10), fx, LG_GBITS); + const dn : u64 = blend1_w(dpos(a00, a01), dpos(a10, a11), fx, LG_GBITS); + const t2p : u64 = (((idf * up) >> 16) * LN2_Q16) >> 23; + const t2n : u64 = (((idf * dn) >> 16) * LN2_Q16) >> 23; + return dpos(term1 + t2p, t2n) as u32; +} + +/// The current of a device table at (vg, vd) in words: a log table (its first word is the tag) is read by `id_log`, any other table by `id_of`. Table words of the +/// linear tables are under 2^23, never the tag, so the old tables are read exactly as before. +pub fn cur_of(t: []const u32, vg: u32, vd: u32) -> u32 { + if (t[0] == LG_TAG) { return id_log(t, vg, vd); } + return id_of(t, vg, vd); +} + +/// gds of a device table at (vg, vd) in words per 2^20 units: `gds_log` for a log table, `gds_cell` for any other. +pub fn cur_gds(t: []const u32, vg: u32, vd: u32) -> u32 { + if (t[0] == LG_TAG) { return gds_log(t, vg, vd); } + return gds_cell(t, vg, vd); +} + /// The positive terms of g at y: y + In(A, y). pub fn g_pos(t: []const u32, y: u32, a: u32) -> u32 { - return y + id_of(t, a, y); + return y + cur_of(t, a, y); } /// The negative terms of g at y: y0 + Ip(Vdd - A, Vdd - y). The PMOS reads the same table, mirrored. pub fn g_neg(t: []const u32, y: u32, y0: u32, a: u32) -> u32 { - return y0 + id_of(t, VDD - a, VDD - y); + return y0 + cur_of(t, VDD - a, VDD - y); } /// |p - n|. @@ -276,7 +495,7 @@ pub fn gq_neg(tp: []const u32, qn: []const u32, qp: []const u32, y: u32, y0: u32 /// g'(y) in units of 2^20: one cell for the node's own C, plus the Vds slopes of the four tables, each read off its own table /// (the value and its derivative are one object, FR-002). pub fn gq_deriv(tn: []const u32, tp: []const u32, qn: []const u32, qp: []const u32, y: u32, a: u32) -> u64 { - return (CELL as u64) + (gds_cell(tn, a, y) as u64) + (gds_cell(tp, VDD - a, VDD - y) as u64) + (gds_cell(qn, a, y) as u64) + (gds_cell(qp, VDD - a, VDD - y) as u64); + return (CELL as u64) + (cur_gds(tn, a, y) as u64) + (cur_gds(tp, VDD - a, VDD - y) as u64) + (gds_cell(qn, a, y) as u64) + (gds_cell(qp, VDD - a, VDD - y) as u64); } /// |g(y)| of the charge-aware equation, in units. @@ -627,6 +846,52 @@ pub fn run_ana(f: f64, nsteps: u32, edge: u32, out: []f64) { } } +/// exp(x) in real arithmetic for the tests: x / 256 by the Taylor series to the 13th term, then squared eight times (relative error under 1e-13 for |x| < 40). +pub fn exp_f64(x: f64) -> f64 { + const y : f64 = x / 256.0; + var term : f64 = 1.0; + var sum : f64 = 1.0; + var i : u32 = 1; + while (i < 14) { + term = term * y / (i as f64); + sum = sum + term; + i = i + 1; + } + var k : u32 = 0; + while (k < 8) { + sum = sum * sum; + k = k + 1; + } + return sum; +} + +/// The cell of a real voltage on an axis of ncell cells of cell units (the f64 model's `cell_w`). +pub fn cellf_w(v: f64, cell: f64, ncell: u32) -> u32 { + var c : u32 = (v / cell) as u32; + if (c >= ncell) { c = ncell - 1; } + return c; +} + +/// `lg_fine` in real arithmetic on the same words: the bilinear blend of the log words and the linear blend of the rv words with no rounding, F = 1 - exp(-x) and 2^(lam / 2^16) +/// exact (`exp_f64`). Id in IUNIT, vg and vd in units. The integer read is checked against this: that is the arithmetic error, apart from the table's. +pub fn idf_log(t: []const u32, vg: f64, vd: f64) -> f64 { + const gc : f64 = 262144.0; + const dc : f64 = 524288.0; + const cx : u32 = cellf_w(vg, gc, LG_NG); + const cy : u32 = cellf_w(vd, dc, LG_ND); + const fx : f64 = (vg - (cx as f64) * gc) / gc; + const fy : f64 = (vd - (cy as f64) * dc) / dc; + const nd1 : usize = (LG_NODES_D) as usize; + const i00 : usize = 1 + (cx as usize) * nd1 + (cy as usize); + const lo : f64 = (t[i00] as f64) * (1.0 - fx) + (t[i00 + nd1] as f64) * fx; + const hi : f64 = (t[i00 + 1] as f64) * (1.0 - fx) + (t[i00 + nd1 + 1] as f64) * fx; + const lam : f64 = lo * (1.0 - fy) + hi * fy; + const r0 : f64 = (t[LG_R_OFF + (cx as usize)]) as f64; + const r1 : f64 = (t[LG_R_OFF + (cx as usize) + 1]) as f64; + const x : f64 = vd * (r0 * (1.0 - fx) + r1 * fx) / 68719476736.0; + return (1.0 - exp_f64(0.0 - x)) * exp_f64(lam * 0.6931471805599453 / 65536.0); +} + ; --- the tests ---------------------------------------------------------------------------------- test the_grid_and_the_units_are_exact { @@ -1127,3 +1392,211 @@ test the_mirrored_circuit_with_charge_gives_the_mirrored_step_with_the_four_tabl // A step that sees no previous gate (A0 = A) differs from one coming from Vdd: the gate edge is in the charge. assert inv_step_q(&tn, &tp, &qn, &qp, 9000000, 0, VDD, 3) != inv_step_q(&tn, &tp, &qn, &qp, 9000000, 0, 0, 3); } + +test the_log_reader_generalizes_the_m3a_read_it_is_the_same_arithmetic_on_another_grid { + // M3c-2 (#10881, FR-004). `read_w` is the read of any uniform grid; the 24 x 24 cells of 2^20 units are one case of it, and there it IS `id_of`: every point, bit for bit. + var t : [625]u32 = [0] ** 625; + build_table(&t, VTH_V); + var checked : u32 = 0; + var vg : u32 = 0; + while (vg <= VDD + 7) { + var vd : u32 = 3; + while (vd <= VDD + 7) { + assert_eq(read_w(&t, 0, vg, vd, 20, 20, 24, 24), id_of(&t, vg, vd)); + assert_eq(cur_of(&t, vg, vd), id_of(&t, vg, vd)); + assert_eq(cur_gds(&t, vg, vd), gds_cell(&t, vg, vd)); + checked = checked + 1; + vd = vd + 1523417; + } + vg = vg + 1100003; + } + assert checked > 300; + // The pieces: the cell, the blend of four nodes and the blend of two differences are the old ones when the weights are 2^20. + var v : u32 = 0; + while (v <= VDD + 9) { + assert_eq(cell_w(v, 20, 24), cell_of(v)); + v = v + 777777; + } + assert_eq(cell_w(VDD, 20, 24), 23); + assert_eq(cell_w(VDD, 18, 96), 95); + assert_eq(cell_w(VDD, 19, 48), 47); + var fx : u32 = 0; + while (fx <= CELL) { + var fy : u32 = 0; + while (fy <= CELL) { + assert_eq(blend_w(100, 20000, 300000, 4000000, fx, fy, 20, 20), blend(100, 20000, 300000, 4000000, fx, fy)); + assert_eq(blend_w(7, 0, 0, 0, fx, fy, 20, 20), blend(7, 0, 0, 0, fx, fy)); + fy = fy + 262144; + } + assert_eq(blend1_w(10, 3000000, fx, 20) as u32, blend1(10, 3000000, fx)); + fx = fx + 131071; + } + // On a grid of other cells the weights follow the cell: the corners at the corners, the mean at the centre. + assert_eq(blend_w(100, 200, 300, 400, 0, 0, 18, 19), 100); + assert_eq(blend_w(100, 200, 300, 400, 262144, 0, 18, 19), 200); + assert_eq(blend_w(100, 200, 300, 400, 0, 524288, 18, 19), 300); + assert_eq(blend_w(100, 200, 300, 400, 262144, 524288, 18, 19), 400); + assert_eq(blend_w(100, 200, 300, 400, 131072, 262144, 18, 19), 250); + assert_eq(blend_w(1, 0, 0, 0, 131072, 262144, 18, 19), 0); + assert_eq(blend_w(2, 0, 0, 0, 131072, 262144, 18, 19), 1); + assert_eq(blend1_w(10, 30, 131072, 18), 20); + // A table with no tag is read as before: the first word of a linear table is below 2^23, never the tag. + assert t[0] != LG_TAG; + assert t[624] < 8388608; +} + +test the_exp_is_a_table_and_a_shift_and_is_exact_to_the_rounding_of_the_table { + // EXP2NEG is 2^-(i/128) in Q24, each entry the nearest integer (a sum of the table's exact values in real arithmetic). + var i : u32 = 0; + var worst : f64 = 0.0; + while (i <= 128) { + const want : f64 = 16777216.0 * exp_f64(0.0 - (i as f64) * 0.6931471805599453 / 128.0); + worst = fmax64(worst, fabs64((EXP2NEG[i as usize] as f64) - want)); + i = i + 1; + } + assert worst < 0.5000001; + assert worst > 0.4; + assert_eq(EXP2NEG[0], 16777216); + assert_eq(EXP2NEG[128], 8388608); + // 2^f from the table and a shift: E = 2^(lam / 65536) to its rounding to an integer and the chord of the table (3.7e-6 relative). + var lam : u32 = 0; + var rel : f64 = 0.0; + var absw : f64 = 0.0; + var checked : u32 = 0; + while (lam < 1900000) { + const want : f64 = exp_f64((lam as f64) * 0.6931471805599453 / 65536.0); + const got : f64 = (exp2_lam(lam)) as f64; + absw = fmax64(absw, fabs64(got - want)); + if (want > 10000000.0) { rel = fmax64(rel, fabs64(got - want) / want); } + checked = checked + 1; + lam = lam + 7919; + } + assert checked > 200; + assert absw < 1800.0; + assert absw > 1700.0; + assert rel < 0.0000038; + assert rel > 0.0000030; + assert_eq(exp2_lam(0), 1); + assert_eq(exp2_lam(65536), 2); + assert_eq(exp2_lam(65536 * 10), 1024); + assert_eq(exp2_lam(65536 * 28), 268435456); + // F = 1 - exp(-x): the series below 1/16 to a few units of Q24, the table above it to the chord (3.7e-6 of 1 = 62 units), and exactly 1 once e^-x is under 2^-25. + var x24 : u32 = 1; + var worst_lo : f64 = 0.0; + var worst_hi : f64 = 0.0; + var rel_lo : f64 = 0.0; + while (x24 < 805306368) { + const x : f64 = (x24 as f64) / 16777216.0; + const want : f64 = 16777216.0 * (1.0 - exp_f64(0.0 - x)); + const got : f64 = (vds_factor(x24 as u64)) as f64; + if (x24 < 1048576) { + worst_lo = fmax64(worst_lo, fabs64(got - want)); + if (x24 > 16384) { rel_lo = fmax64(rel_lo, fabs64(got - want) / want); } + } else { + worst_hi = fmax64(worst_hi, fabs64(got - want)); + } + x24 = x24 + 1 + x24 / 61; + } + assert worst_lo < 11.0; + assert worst_lo > 10.0; + assert rel_lo < 0.000037; + assert rel_lo > 0.000035; + assert worst_hi < 64.5; + assert worst_hi > 63.5; + assert_eq(vds_factor(0), 0); + assert_eq(vds_factor(805306368) as u32, 16777216); + // F is nondecreasing in x across the switch from the series to the table (a step back would be a negative conductance). + var prev : u64 = 0; + var steps : u32 = 0; + x24 = 1040000; + while (x24 < 1060000) { + const f : u64 = vds_factor(x24 as u64); + assert f >= prev; + prev = f; + x24 = x24 + 97; + steps = steps + 1; + } + assert steps > 150; +} + +test a_synthetic_log_table_gives_the_closed_form_value_and_slope { + // Three log tables made of integers whose Id is a closed form: the log word is L0 + 8192 ix (the current grows 2^(8192 / 65536) = 9 % per node along Vgs) plus 0, + // +16384 iy or -16384 iy (a factor 2^(+-1/4) per node along Vds), rv = 50000 (s = 82 mV). So Id(vg, vd) = (1 - exp(-vd rv / 2^36)) 2^(lam / 65536) in IUNIT with + // lam = L0 + vg / 32 + c vd, c = 0, 1 / 32 or -1 / 32; and its slope is F' E + F E ln2 c / 65536 per unit of Vds. + var tab : [4851]u32 = [0] ** 4851; + var tabp : [4851]u32 = [0] ** 4851; + var tabn : [4851]u32 = [0] ** 4851; + var tabz : [4851]u32 = [0] ** 4851; + tab[0] = LG_TAG; + tabp[0] = LG_TAG; + tabn[0] = LG_TAG; + tabz[0] = LG_TAG; + var ix : u32 = 0; + while (ix < 97) { + var iy : u32 = 0; + while (iy < 49) { + const at : usize = (1 + ix * 49 + iy) as usize; + tab[at] = 700000 + 8192 * ix; + tabp[at] = 400000 + 8192 * ix + 16384 * iy; + tabn[at] = 1300000 + 8192 * ix - 16384 * iy; + tabz[at] = 1700000 + 8192 * ix - 32768 * iy; + iy = iy + 1; + } + tab[(4754 + ix) as usize] = 50000; + tabp[(4754 + ix) as usize] = 50000; + tabn[(4754 + ix) as usize] = 50000; + tabz[(4754 + ix) as usize] = 50000; + ix = ix + 1; + } + var v0 : f64 = 0.0; + var vp : f64 = 0.0; + var vn : f64 = 0.0; + var s0 : f64 = 0.0; + var sp : f64 = 0.0; + var sn : f64 = 0.0; + var checked : u32 = 0; + var vg : u32 = 100000; + while (vg < VDD) { + var vd : u32 = 70000; + while (vd < VDD) { + const x : f64 = (vd as f64) * 50000.0 / 68719476736.0; + const f : f64 = 1.0 - exp_f64(0.0 - x); + const fp : f64 = 50000.0 / 68719476736.0 * exp_f64(0.0 - x); + const lam0 : f64 = 700000.0 + (vg as f64) / 32.0; + const lamp : f64 = 400000.0 + (vg as f64) / 32.0 + (vd as f64) / 32.0; + const lamn : f64 = 1300000.0 + (vg as f64) / 32.0 - (vd as f64) / 32.0; + const e0 : f64 = exp_f64(lam0 * 0.6931471805599453 / 65536.0); + const ep : f64 = exp_f64(lamp * 0.6931471805599453 / 65536.0); + const en : f64 = exp_f64(lamn * 0.6931471805599453 / 65536.0); + // The value: the rounding to an integer (half) and a part in 1e5 of the value (the chord of the table's two exps). + v0 = fmax64(v0, fabs64(((lg_fine(&tab, vg, vd)) as f64) - f * e0) - 0.00007 * f * e0); + vp = fmax64(vp, fabs64(((lg_fine(&tabp, vg, vd)) as f64) - f * ep) - 0.00007 * f * ep); + vn = fmax64(vn, fabs64(((lg_fine(&tabn, vg, vd)) as f64) - f * en) - 0.00007 * f * en); + // The slope in words per 2^20 units: 2^20 / 2^8 = 4096 words per unit of IUNIT per unit of Vds. Two words and 0.4 % of it. + const sl0 : f64 = fp * e0 * 4096.0; + const slp : f64 = (fp * ep + f * ep * 0.6931471805599453 / 32.0 / 65536.0) * 4096.0; + var sln : f64 = (fp * en - f * en * 0.6931471805599453 / 32.0 / 65536.0) * 4096.0; + if (sln < 0.0) { sln = 0.0; } + s0 = fmax64(s0, fabs64(((gds_log(&tab, vg, vd)) as f64) - sl0) - 0.004 * sl0); + sp = fmax64(sp, fabs64(((gds_log(&tabp, vg, vd)) as f64) - slp) - 0.004 * slp); + sn = fmax64(sn, fabs64(((gds_log(&tabn, vg, vd)) as f64) - sln) - 0.004 * sln); + checked = checked + 1; + vd = vd + 1700003; + } + vg = vg + 1300007; + } + assert checked > 100; + assert v0 < 1.01; + assert vp < 1.01; + assert vn < 1.01; + assert s0 < 2.0; + assert sp < 2.0; + assert sn < 2.0; + // The Vds dependence of the log word is read: the current of the table that rises with Vds is not the current of the flat one, and where the log word falls so fast that the + // slope of F E would be negative (a fall of 2^(-1/2) per node, ln2 / 16 of E per 2^20 units against F' E = rv e^-x E / 2^36 at x = 2.2) the slope is floored at 0, not wrapped. + assert lg_fine(&tab, 12000000, 3000000) != lg_fine(&tabp, 12000000, 3000000); + assert gds_log(&tab, 12000000, 3000000) > 0; + assert gds_log(&tabp, 12000000, 3000000) > 0; + assert_eq(gds_log(&tabz, 12000000, 3000000), 0); + assert lg_fine(&tabz, 12000000, 3000000) > 0; +}