BSimGeomImpl.mesa
Last Edited by: McCreight, April 17, 1985 10:06:57 am PST
DIRECTORY
Commander,
CommandTool,
BSimModel,
FS,
IO,
LeastSq,
Real,
Rope;
BSimGeomImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, BSimModel, FS, IO, LeastSq, Real, Rope =
BEGIN
CombineDieFiles: PROC [ from: LIST OF REF ANY -- Rope --, to: Rope.ROPE ] RETURNS [ comments: Rope.ROPENIL ] =
BEGIN
pp: REF BSimModel.ProcessParams = NEW[BSimModel.ProcessParams];
dieList: LIST OF REF BSimModel.ProcessParams ← NIL;
ps: LeastSq.PointSet ← NIL;
pt: LeastSq.Row ← NEW[LeastSq.RowRec[4]];
eqn: LeastSq.Row;
dieCount: INT ← 0;
mu, dL, dW: REAL;
sumSqErr, maxSqErr: REAL;
firstDie: REF BSimModel.ProcessParams ← NIL;
multipleL, multipleW: BOOLFALSE;
comments ← IO.PutFR["*BSIM Process File %g of %g\n*generated from the following die files:\n", IO.rope[to], IO.time[]];
FOR f: LIST OF REF ANY ← from, f.rest WHILE f # NIL DO
WITH f.first SELECT FROM
r: Rope.ROPE => {
fullFName, attachedTo: Rope.ROPE;
created: BasicTime.GMT;
dieCount ← dieCount+1;
dieList ← CONS[BSimModel.ReadProcessFile[r], dieList];
[fullFName: fullFName, attachedTo: attachedTo, created: created] ←
FS.FileInfo[name: r];
IF attachedTo.Length = 0 THEN attachedTo ← fullFName;
comments ← comments.Cat[IO.PutFR["* %g of %g (W/L = %g/%g)\n",
IO.rope[attachedTo],
IO.time[created],
IO.int[Real.RoundLI[dieList.first.dutW]],
IO.int[Real.RoundLI[dieList.first.dutL]],
]];
IF firstDie = NIL THEN firstDie ← dieList.first ELSE {
multipleL ←multipleL OR dieList.first.dutL # firstDie.dutL;
multipleW ←multipleW OR dieList.first.dutW # firstDie.dutW;
IF dieList.first.toxMicrons # firstDie.toxMicrons
OR dieList.first.tempC # firstDie.tempC
OR dieList.first.vddVolts # firstDie.vddVolts THEN
comments ← comments.Cat["* WARNING -- incompatible die files!!\n"];
};
};
ENDCASE => NULL;
ENDLOOP;
pp^ ← dieList.first^;
comments ← Rope.Cat[comments, (IF multipleL THEN NIL ELSE "* WARNING -- dice have only one channel length\n"), (IF multipleW THEN NIL ELSE "* WARNING -- dice have only one channel width\n")];
pp.info ← Rope.Cat[comments, "*\n*The following information is from the last die file:\n", pp.info];
ps ← LeastSq.NewPointSet[4];
pt[0] ← 1.0;
The parameter in the file is beta0.
beta0 = mu*Cox*(W+dW)/(L+dL), where we know Cox, beta0, W, and L
(beta0/Cox)*(L+dL) = (dW*mu)+mu*W
L = (dW*mu)*(Cox/beta0)+mu*(W*(Cox/beta0))-dL
FOR dl: LIST OF REF BSimModel.ProcessParams ← dieList, dl.rest WHILE dl # NIL DO
CoxOverBeta0: REAL = (3.9*8.854E-10/dl.first.toxMicrons -- farads/sq cm--)
/dl.first.params[BSimModel.beta0][1];
pt[1] ← CoxOverBeta0*dl.first.dutW; -- first indep var
pt[2] ← CoxOverBeta0; -- second indep var
pt[3] ← dl.first.dutL; -- dep variable
LeastSq.AddPoint[ps, pt];
ENDLOOP;
eqn ← LeastSq.LeastSqFit[ps];
dL ← eqn[0];
mu ← -eqn[1];
dW ← -eqn[2]/mu;
pp.params[BSimModel.beta0][1] ← mu;
pp.params[BSimModel.beta0][2] ← dL;
pp.params[BSimModel.beta0][3] ← dW;
sumSqErr ← 0.0;
FOR dl: LIST OF REF BSimModel.ProcessParams ← dieList, dl.rest WHILE dl # NIL DO
Cox: REAL = 3.9*8.854E-10/dl.first.toxMicrons; -- farads/sq cm
Leff: REAL = dl.first.dutL+dL;
Weff: REAL = dl.first.dutW+dW;
pred: REAL = mu*Cox*Weff/Leff;
act: REAL = dl.first.params[BSimModel.beta0][1];
err: REAL = 100*(IF act=0 THEN (IF pred=0 THEN 0.0 ELSE 1.0) ELSE ABS[(pred-act)/act]);
sqErr: REAL = err*err;
sumSqErr ← sumSqErr+sqErr;
ENDLOOP;
comments ← IO.PutFR["%gBeta0 has RMS error of %g%%.\n",
IO.rope[comments],
IO.real[Real.SqRt[sumSqErr/dieCount]]];
FOR parm: NAT IN [0..BSimModel.nBasicBSimParams) DO
sumSqErr ← maxSqErr ← 0.0;
IF parm = BSimModel.beta0 THEN LOOP;
ps ← LeastSq.NewPointSet[4];
FOR dl: LIST OF REF BSimModel.ProcessParams ← dieList, dl.rest WHILE dl # NIL DO
Leff: REAL = dl.first.dutL+dL;
Weff: REAL = dl.first.dutW+dW;
act: REAL = dl.first.params[parm][1]*(SELECT parm FROM
BSimModel.x2beta0, BSimModel.beta0sat, BSimModel.x2beta0sat, BSimModel.x3beta0sat =>
Leff/Weff,
BSimModel.u1, BSimModel.x2u1, BSimModel.x3u1 => Leff,
ENDCASE => 1.0);
pt[1] ← 1.0/Leff; -- first indep var
pt[2] ← 1.0/Weff; -- second indep var
pt[3] ← act; -- dep variable
LeastSq.AddPoint[ps, pt];
ENDLOOP;
eqn ← LeastSq.LeastSqFit[ps];
pp.params[parm][1] ← -eqn[0];
pp.params[parm][2] ← -eqn[1];
pp.params[parm][3] ← -eqn[2];
FOR dl: LIST OF REF BSimModel.ProcessParams ← dieList, dl.rest WHILE dl # NIL DO
Leff: REAL = dl.first.dutL+dL;
Weff: REAL = dl.first.dutW+dW;
pred: REAL = pp.params[parm][1]+(pp.params[parm][2]/Leff)+(pp.params[parm][3]/Weff);
act: REAL = dl.first.params[parm][1]*(SELECT parm FROM
BSimModel.x2beta0, BSimModel.beta0sat, BSimModel.x2beta0sat, BSimModel.x3beta0sat =>
Leff/Weff,
BSimModel.u1, BSimModel.x2u1, BSimModel.x3u1 => Leff,
ENDCASE => 1.0);
err: REAL = 100*(IF act=0 THEN (IF pred=0 THEN 0.0 ELSE 1.0) ELSE ABS[(pred-act)/act]);
sqErr: REAL = err*err;
IF sqErr>maxSqErr THEN {
maxSqErr ← sqErr;
pp.params[parm][4] ← err;
pp.params[parm][5] ← dl.first.dutW;
pp.params[parm][6] ← dl.first.dutL;
};
sumSqErr ← sumSqErr+sqErr;
ENDLOOP;
comments ← IO.PutFR["%gParameter %g has RMS error of %g%%.\n",
IO.rope[comments], IO.int[parm], IO.real[Real.SqRt[sumSqErr/dieCount]]];
ENDLOOP;
BSimModel.WriteProcessFile[to, pp];
END;
MakeBSimProcessFile: PROC [cmd: Commander.Handle] RETURNS [result: REFNIL, msg: Rope.ROPENIL] -- Commander.CommandProc -- = {
argList: LIST OF Rope.ROPE;
nArgs: NAT;
comments: Rope.ROPE;
[list: argList, length: nArgs] ← CommandTool.ParseToList[cmd];
IF nArgs>4 AND Rope.Equal[argList.rest.first, "←"] THEN {
fromFiles: LIST OF REF ANY;
TRUSTED { fromFiles ← LOOPHOLE[argList.rest.rest, LIST OF REF ANY] };
comments ← CombineDieFiles[to: argList.first, from: fromFiles];
}
ELSE comments ← Rope.Cat["Improper argument format", cmd.procData.doc];
cmd.out.PutF["\n%g", IO.rope[comments]];
};
Commander.Register["MakeBSimProcessFile", MakeBSimProcessFile, "\n\nMakeBSimProcessFile takes a collection of BSim die files for dice of different lengths and widths and produces a process file from which BSim parameters can be calculated for any geometry. Format is:\n MakeBSIMProcessFile processFile ← dieFile dieFile ...\n"];
END.