BSimGeomImpl.mesa
Last Edited by: McCreight, April 24, 1985 7:11:16 pm PST
DIRECTORY
Commander,
CommandTool,
Convert,
BSimModel,
FS,
IO,
IOUtils,
LeastSq,
Real,
Rope;
BSimGeomImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, BSimModel, FS, IO, IOUtils, LeastSq, Real, Rope =
BEGIN
WPParams: TYPE = RECORD [
weight: REAL ← 1.0,
p: REF BSimModel.ProcessParams ← NIL
];
CombineDieFiles: PROC [ from: LIST OF Rope.ROPE, to: Rope.ROPE ] RETURNS [ comments: Rope.ROPENIL ] =
BEGIN
pp: REF BSimModel.ProcessParams = NEW[BSimModel.ProcessParams];
dieList: LIST OF REF WPParams ← NIL;
ps: LeastSq.PointSet ← NIL;
pt: LeastSq.Row ← NEW[LeastSq.RowRec[4]];
eqn: LeastSq.Row;
dieCount: INT ← 0;
wtSum: REAL ← 0.0;
mu, dL, dW: REAL;
sumSqErr, maxSqErr: REAL;
firstDie: REF WPParams ← NIL;
multipleL, multipleW: BOOLFALSE;
f: LIST OF Rope.ROPE ← from;
comments ← IO.PutFR["*BSIM Process File %g of %g\n*generated from the following die files:\n", IO.rope[to], IO.time[]];
WHILE f # NIL DO
r: Rope.ROPE ← f.first;
fullFName, attachedTo: Rope.ROPE;
created: BasicTime.GMT;
wt: REAL ← 1.0;
dieCount ← dieCount+1;
IF r.Equal["-w"] THEN {
wt ← Convert.RealFromLiteral[f.rest.first];
f ← f.rest.rest;
r ← f.first;
};
dieList ← CONS[NEW[WPParams ← [weight: wt, p: 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 (wt = %g, W/L = %g/%g)\n",
IO.rope[attachedTo],
IO.time[created],
IO.real[dieList.first.weight],
IO.int[Real.RoundLI[dieList.first.p.dutW]],
IO.int[Real.RoundLI[dieList.first.p.dutL]]
]];
IF firstDie = NIL THEN firstDie ← dieList.first ELSE {
multipleL ←multipleL OR dieList.first.p.dutL # firstDie.p.dutL;
multipleW ←multipleW OR dieList.first.p.dutW # firstDie.p.dutW;
IF dieList.first.p.toxMicrons # firstDie.p.toxMicrons
OR dieList.first.p.tempC # firstDie.p.tempC
OR dieList.first.p.vddVolts # firstDie.p.vddVolts THEN
comments ← comments.Cat["* WARNING -- incompatible die files!!\n"];
};
wtSum ← wtSum+wt;
f ← f.rest;
ENDLOOP;
pp^ ← dieList.first.p^;
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 WPParams ← dieList, dl.rest WHILE dl # NIL DO
CoxOverBeta0: REAL = (3.9*8.854E-10/dl.first.p.toxMicrons -- farads/sq cm--)
/dl.first.p.params[BSimModel.beta0][1];
pt[1] ← CoxOverBeta0*dl.first.p.dutW; -- first indep var
pt[2] ← CoxOverBeta0; -- second indep var
pt[3] ← dl.first.p.dutL; -- dep variable
LeastSq.AddPoint[ps, pt, dl.first.weight];
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 WPParams ← dieList, dl.rest WHILE dl # NIL DO
Cox: REAL = 3.9*8.854E-10/dl.first.p.toxMicrons; -- farads/sq cm
Leff: REAL = dl.first.p.dutL+dL;
Weff: REAL = dl.first.p.dutW+dW;
pred: REAL = mu*Cox*Weff/Leff;
act: REAL = dl.first.p.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]);
sumSqErr ← sumSqErr+dl.first.weight*err*err;
ENDLOOP;
comments ← IO.PutFR["%gBeta0 has RMS error of %g%%.\n",
IO.rope[comments],
IO.real[Real.SqRt[sumSqErr/wtSum]]];
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 WPParams ← dieList, dl.rest WHILE dl # NIL DO
Leff: REAL = dl.first.p.dutL+dL;
Weff: REAL = dl.first.p.dutW+dW;
pt[1] ← 1.0/Leff; -- first indep var
pt[2] ← 1.0/Weff; -- second indep var
pt[3] ← dl.first.p.params[parm][1]; -- dep variable
LeastSq.AddPoint[ps, pt, dl.first.weight];
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 WPParams ← dieList, dl.rest WHILE dl # NIL DO
Leff: REAL = dl.first.p.dutL+dL;
Weff: REAL = dl.first.p.dutW+dW;
Cox: REAL = 3.9*8.854E-10/dl.first.p.toxMicrons; -- farads/sq cm
pred: REAL = pp.params[parm][1]+(pp.params[parm][2]/Leff)+(pp.params[parm][3]/Weff);
act: REAL = dl.first.p.params[parm][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;
IF sqErr>maxSqErr THEN {
maxSqErr ← sqErr;
pp.params[parm][4] ← err;
pp.params[parm][5] ← dl.first.p.dutW;
pp.params[parm][6] ← dl.first.p.dutL;
};
sumSqErr ← sumSqErr+dl.first.weight*sqErr;
ENDLOOP;
comments ← IO.PutFR["%gParameter %g has RMS error of %g%%.\n",
IO.rope[comments], IO.int[parm], IO.real[Real.SqRt[sumSqErr/wtSum]]];
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 {
comments ← CombineDieFiles[to: argList.first, from: argList.rest.rest];
}
ELSE comments ← Rope.Cat["Improper argument format", cmd.procData.doc];
cmd.out.PutF["\n%g", IO.rope[comments]];
};
PutFRList: PROC [ format: Rope.ROPE, v: LIST OF REF ANY ] RETURNS [ result: LIST OF Rope.ROPE ] = {
ToValueList: PROC [ l: LIST OF REF ANY ] RETURNS [ vl: LIST OF IO.Value ] = {
IF l = NIL THEN vl ← NIL
ELSE WITH l.first SELECT FROM
ri: REF INT => vl ← CONS[IO.int[ri^], ToValueList[l.rest]];
rr: REF REAL => vl ← CONS[IO.real[rr^], ToValueList[l.rest]];
rv: REF IO.Value => vl ← CONS[rv^, ToValueList[l.rest]];
r: Rope.ROPE => vl ← CONS[IO.rope[r], ToValueList[l.rest]];
t: REF TEXT => vl ← CONS[IO.text[t], ToValueList[l.rest]];
ENDCASE => vl ← CONS[IO.refAny[l.first], ToValueList[l.rest]];
};
rev: LIST OF Rope.ROPENIL;
FOR vl: LIST OF REF ANY ← v, vl.rest WHILE vl # NIL DO
s: IO.STREAM = IO.ROS[];
pfp: IOUtils.PFProcs = IOUtils.CopyPFProcs[s];
tvl: LIST OF IO.Value ← NIL;
[] ← IOUtils.SetPFCodeProc[pfProcs: pfp, char: 'j, codeProc: JunkIt];
[] ← IOUtils.SetPFProcs[stream: s, pfProcs: pfp];
WITH vl.first SELECT FROM
l: LIST OF IO.Value => IO.PutFL[s, format, l];
l: LIST OF REF ANY => {tvl ← ToValueList[l]; IO.PutFL[s, format, tvl]};
ENDCASE => {tvl ← ToValueList[LIST[vl.first]]; IO.PutF[s, format, tvl.first]};
rev ← CONS[IO.RopeFromROS[s], rev];
ENDLOOP;
result ← NIL;
WHILE rev # NIL DO
result ← CONS[rev.first, result];
rev ← rev.rest;
ENDLOOP;
};
JunkIt: PROC [ stream: IO.STREAM, val: IO.Value, format: IOUtils.Format, char: CHAR ] -- IOUtils.PFCodeProc -- = {NULL};
DoCommandRopeList: PROC [ parent: Commander.Handle, l: LIST OF Rope.ROPE ] RETURNS [ out: Rope.ROPE, result: REF ANY ] = {
TRUSTED {[out, result] ← DoCommandList[parent, LOOPHOLE[l, LIST OF REF ANY]]};
};
DoCommandList: PROC [ parent: Commander.Handle, l: LIST OF REF ANY ] RETURNS [ out: Rope.ROPE, result: REF ANY ] = {
s: IO.STREAM = IO.ROS[];
IF parent = NIL THEN
parent ← NEW[Commander.CommandObject ← [out: s]];
FOR rl: LIST OF REF ANY ← l, rl.rest WHILE rl # NIL DO
[out, result] ← CommandTool.DoCommandRope[commandLine: NARROW[rl.first], parent: parent];
IO.Put[s, IO.rope[out]];
IF result = $Failure THEN EXIT;
ENDLOOP;
out ← IO.RopeFromROS[s];
};
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.