Hi Ananth,

I can reproduce the first point with your deck on current master (5156616b8): after the sweep @m1[w] reads 1e-12 and the second op gives i(vd) = -1.26010e-10 instead of -1.25000e-04. Without .option scale the deck is unchanged, as you reported.

Your reading of the path is right. In dctrcurv.c the save for a PARAM_CODE sweep variable goes through DEVask, which returns the instance value already multiplied by scale (TRCVvSave, around line 230). At the end of the sweep DCTsetInstParam() hands that saved value back to DEVparam (around line 616), and mos1par.c applies scale again on MOS1_W; same for L, AD, AS, PD, PS on every MOS level that scales geometry.

Attached is a patch against master. After DCTsetInstParam(start) it reads the value back with DEVask: the ratio asked/start is the effective scale factor of that parameter (1 for an unscaled parameter, scale for geometry), and TRCVvSave is divided by it so the final restore lands on the original value. It is generic, no per-device parameter list. The factor is left at 1 when start or the read-back value is 0, so a sweep starting exactly at 0 is not covered. It adds tests/regression/dcsweep-param-scale/ (w, l and @r1[resistance]), which fails on the unpatched binary and passes with the patch. make check: 62 PASS, 0 FAIL. With the patch your deck gives @m1[w] = 1e-06 and i(vd) = -1.25000e-04 after the sweep.

I left the second point (rebinning during the sweep) alone; happy to look at it separately if useful.

I used an AI coding assistant for part of the analysis and the patch; I reviewed and tested everything before posting.

Clement Saillant