Question:
How to pass the modified device model parameters (such as W, L, Tox) to the sub-circuit during Monte Carlo iterations loop?
Tool version:
[boris@E7440 inverter]$ ngspice -v
ngspice compiled from ngspice revision 23
Written originally by Berkeley University
Currently maintained by the NGSpice Project
Copyright (C) 1985-1996, The Regents of the University of California
Copyright (C) 1999-2008, The NGSpice Project
[boris@E7440 inverter]$ uname -a
Linux E7440.DELL 4.4.13-200.fc22.x86_64 #1 SMP Wed Jun 8 15:59:40 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[boris@E7440 inverter]$
Test-case:
Here is a small standalone test-case that demonstrates the problem; performing Monte Carlo analysis on a simple inverter gate by varying the width and length of the transistor channel.
SPICE3 file
.GLOBAL VDD VBP
V0DD VDD 0 1.1
V0BP VBP 0 1.1
.GLOBAL VSS VBN
V0SS VSS 0 0.0
V0BN VBN 0 0.0
X1 VDD VSS VBP VBN X A INV1
V1 A 0 DC 0 PWL( 2501.80p 1.10 2503.02p 1.10 2504.24p 1.10 2505.46p 1.10 2506.68p 1.10 2507.90p 1.09 2509.12p 1.09 2510.34p 1.09 2511.56p 1.09 2512.78p 1.08 2514.00p 1.07 2515.22p 1.06 2516.44p 1.05 2517.66p 1.03 2518.88p 1.01 2520.10p 0.98 2521.32p 0.94 2522.54p 0.88 2523.76p 0.79 2524.98p 0.67 2526.20p 0.55 2527.42p 0.43 2528.64p 0.31 2529.86p 0.22 2531.08p 0.16 2532.30p 0.12 2533.52p 0.09 2534.74p 0.07 2535.96p 0.05 2537.18p 0.04 2538.40p 0.03 2539.62p 0.02 2540.84p 0.01 2542.06p 0.01 2543.28p 0.01 2544.50p 0.01 2545.72p 0.00 2546.94p 0.00 2548.16p 0.00 2549.38p 0.00 2550.60p 0.00 )
C1 X 0 12.3f
.OPTIONS NOACCT
.control
save A X
let mc_runs = 25
let run = 0
set curplot = new
set plot_out = $curplot
define unif(nom, var) (nom + (nom*var) * sunif(0))
define aunif(nom, avar) (nom + avar * sunif(0))
define gauss(nom, var, sig) (nom + (nom*var)/sig * sgauss(0))
define agauss(nom, avar, sig) (nom + avar/sig * sgauss(0))
dowhile run <= mc_runs
alter @M1[W] = gauss(0.72u, 0.1, 3)
alter @M1[L] = gauss(0.18u, 0.1, 3)
alter @M2[W] = gauss(0.36u, 0.1, 3)
alter @M2[L] = gauss(0.18u, 0.1, 3)
tran 3p 3n 2n
set run ="$&run"
print run
linearize A X
set plot_tmp = $curplot
setplot $plot_out
if run=0
let time={$plot_tmp}.time
let vin={$plot_tmp}.A
end
let vout{$run}={$plot_tmp}.X
setplot $plot_tmp
let run = run + 1
end
plot {$plot_out}.allv
.endc
.END
.MODEL NFET NMOS(LEVEL=14 VERSION=4.6.5)
.MODEL PFET PMOS(LEVEL=14 VERSION=4.6.5)
.SUBCKT INV1 VDD VSS VBP VBN X A
M1 X A VDD VBP pfet W=0.72u L=0.18u AD=3.6p PD=2.34p AS=3.6p PS=2.34p
M2 X A VSS VBN nfet W=0.36u L=0.18u AD=1.8p PD=1.62p AS=1.8p PS=1.62p
.ENDS
The SPICE output is following:
[boris@E7440 inverter]$ ngspice simulate_mc2.sp
******
** ngspice-23 : Circuit level simulation program
** The U. C. Berkeley CAD Group
** Copyright 1985-1994, Regents of the University of California.
** Please get your ngspice manual from http://ngspice.sourceforge.net/docs.html
** Please file your bug-reports at http://ngspice.sourceforge.net/bugrep.html
** Creation Date: Tue Jul 8 03:06:23 UTC 2014
******
Circuit: simulation file
Error: no such device or model name m1
Error: no such device or model name m1
Error: no such device or model name m2
Error: no such device or model name m2
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 0.000000e+00
Error: no such device or model name m1
Error: no such device or model name m1
Error: no such device or model name m2
Error: no such device or model name m2
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 1.000000e+00
Error: no such device or model name m1
Error: no such device or model name m1
Error: no such device or model name m2
Error: no such device or model name m2
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 2.000000e+00
Error: no such device or model name m1
Error: no such device or model name m1
Error: no such device or model name m2
Error: no such device or model name m2
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00nce value : 2.55551e-09
No. of Data Rows : 501
run = 3.000000e+00
Obviously something goes wrong with passing the parameters to the sub-circuit. I have also tried the following syntax variations:
alter X1.@M1[W] = gauss(0.72u, 0.1, 3)
alter X1:@M1[W] = gauss(0.72u, 0.1, 3)
alter X1/@M1[W] = gauss(0.72u, 0.1, 3)
alter @X1.M1[W] = gauss(0.72u, 0.1, 3)
alter @X1:M1[W] = gauss(0.72u, 0.1, 3)
alter @X1/M1[W] = gauss(0.72u, 0.1, 3)
alter @X1.@M1[W] = gauss(0.72u, 0.1, 3)
alter @X1:@M1[W] = gauss(0.72u, 0.1, 3)
alter @X1/@M1[W] = gauss(0.72u, 0.1, 3)
alter @X1[M1[W]] = gauss(0.72u, 0.1, 3)
alter @X1(M1[W]) = gauss(0.72u, 0.1, 3)
alter @X1{M1[W]} = gauss(0.72u, 0.1, 3)
Nothing works...
By the way, when I move the sub-circuit content within the main netlist, simulation works fine...
Example:
SPICE3 file
.GLOBAL VDD VBP
V0DD VDD 0 1.1
V0BP VBP 0 1.1
.GLOBAL VSS VBN
V0SS VSS 0 0.0
V0BN VBN 0 0.0
M1 X A VDD VBP pfet W=0.72u L=0.18u AD=3.6p PD=2.34p AS=3.6p PS=2.34p
M2 X A VSS VBN nfet W=0.36u L=0.18u AD=1.8p PD=1.62p AS=1.8p PS=1.62p
V1 A 0 DC 0 PWL( 2501.80p 1.10 2503.02p 1.10 2504.24p 1.10 2505.46p 1.10 2506.68p 1.10 2507.90p 1.09 2509.12p 1.09 2510.34p 1.09 2511.56p 1.09 2512.78p 1.08 2514.00p 1.07 2515.22p 1.06 2516.44p 1.05 2517.66p 1.03 2518.88p 1.01 2520.10p 0.98 2521.32p 0.94 2522.54p 0.88 2523.76p 0.79 2524.98p 0.67 2526.20p 0.55 2527.42p 0.43 2528.64p 0.31 2529.86p 0.22 2531.08p 0.16 2532.30p 0.12 2533.52p 0.09 2534.74p 0.07 2535.96p 0.05 2537.18p 0.04 2538.40p 0.03 2539.62p 0.02 2540.84p 0.01 2542.06p 0.01 2543.28p 0.01 2544.50p 0.01 2545.72p 0.00 2546.94p 0.00 2548.16p 0.00 2549.38p 0.00 2550.60p 0.00 )
C1 X 0 12.3f
.OPTIONS NOACCT
.control
save A X
let mc_runs = 5
let run = 0
set curplot = new
set plot_out = $curplot
define unif(nom, var) (nom + (nom*var) * sunif(0))
define aunif(nom, avar) (nom + avar * sunif(0))
define gauss(nom, var, sig) (nom + (nom*var)/sig * sgauss(0))
define agauss(nom, avar, sig) (nom + avar/sig * sgauss(0))
dowhile run <= mc_runs
alter @M1[W] = gauss(0.72u, 0.1, 3)
alter @M1[L] = gauss(0.18u, 0.1, 3)
alter @M2[W] = gauss(0.36u, 0.1, 3)
alter @M2[L] = gauss(0.18u, 0.1, 3)
tran 3p 3n 2n
set run ="$&run"
print run
linearize A X
set plot_tmp = $curplot
setplot $plot_out
if run=0
let time={$plot_tmp}.time
let vin={$plot_tmp}.A
end
let vout{$run}={$plot_tmp}.X
setplot $plot_tmp
let run = run + 1
end
plot {$plot_out}.allv
.endc
.END
.MODEL NFET NMOS(LEVEL=14 VERSION=4.6.5)
.MODEL PFET PMOS(LEVEL=14 VERSION=4.6.5)
Result:
[boris@E7440 inverter]$ ngspice simulate_mc1.sp
******
** ngspice-23 : Circuit level simulation program
** The U. C. Berkeley CAD Group
** Copyright 1985-1994, Regents of the University of California.
** Please get your ngspice manual from http://ngspice.sourceforge.net/docs.html
** Please file your bug-reports at http://ngspice.sourceforge.net/bugrep.html
** Creation Date: Tue Jul 8 03:06:23 UTC 2014
******
Circuit: simulation file
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 0.000000e+00
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 1.000000e+00
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00
No. of Data Rows : 501
run = 2.000000e+00
Doing analysis at TEMP = 27.000000 and TNOM = 27.000000
OpenMP: 2 threads are requested in BSIM4
%100.00nce value : 2.52249e-09
No. of Data Rows : 501
run = 3.000000e+00
However, this is not a practical solution. I would like to simulate other cells too, but copy pasting the contents of different sub-circuits into the main netlist is cumbersome and error prone.
May I recommend the ngspice discussion forums for posting such question? A much faster answer would have been available, not just by chance as has happened here.
After running your input file interactively, give the command 'listing expand', and you will see what the circuit structure looks like after subcircuit expansion.
m1 has becom m.x1.m1, m2 has become m.x1.m2. The alter command acts on the expanded circuit. Therefore, by replacing m1 by m.x1.m1 and m2 by m.x1.m2 in the alter statements you will get a suitable result.
Holger