SimReadImpl.Mesa
Last Edited by: Spreitzer, May 28, 1984 10:43:24 pm PDT
DIRECTORY FS, IO, Rope, SimRead;
SimReadImpl: CEDAR PROGRAM
IMPORTS FS, IO, Rope
EXPORTS SimRead =
BEGIN OPEN SimRead;
FromStream: PUBLIC PROC [from: IO.STREAM, client: Client, format: Format] =
BEGIN
pd: ParseData ← NEW [ParseDataRep ← []];
IF format.Init # NIL THEN format.Init[pd: pd, f: format];
IF client.Init # NIL THEN client.Init[pd: pd, c: client];
StreamWork[from: from, pd: pd, client: client, format: format];
END;
StreamWork: PROC [from: IO.STREAM, pd: ParseData, client: Client, format: Format] =
BEGIN
more: BOOLTRUE;
WHILE more DO
char: CHAR;
fields: LIST OF FieldProc;
[] ← from.SkipWhitespace[flushComments: FALSE];
IF from.EndOf[] THEN EXIT;
char ← from.GetChar[];
FOR fields ← format.whatToDo[char], fields.rest WHILE (fields # NIL) AND more DO
more ← fields.first[first: char, from: from, f: format, pd: pd, c: client];
ENDLOOP;
ENDLOOP;
END;
FormatDefs: TYPE = LIST OF FormatDef; FormatDef: TYPE = RECORD [
name: ROPE, format: Format];
formats: FormatDefs ← NIL;
SetFormat: PUBLIC PROC [name: ROPE, format: Format] =
{formats ← CONS[[name, format], formats]};
GetFormat: PUBLIC PROC [name: ROPE] RETURNS [format: Format] =
BEGIN
FOR fs: FormatDefs ← formats, fs.rest WHILE fs # NIL DO
IF fs.first.name.Equal[s2: name, case: TRUE] THEN RETURN [fs.first.format];
ENDLOOP;
format ← NIL;
END;
UseClientsOther: PUBLIC PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
IF c.GotOther # NIL
THEN continue ← c.GotOther[char: first, from: from, cd: c.data]
ELSE BEGIN
[] ← from.GetLineRope[];
continue ← TRUE;
END;
END;
FollowIndirection: PUBLIC PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
fileName: ROPE ← from.GetTokenRope[IO.IDProc].token;
sub: IO.STREAMFS.StreamOpen[fileName];
[] ← from.GetLineRope[];
StreamWork[from: sub, pd: pd, client: c, format: f];
sub.Close[];
END;
NodeName: PUBLIC FieldProc = {pd.name ← from.GetTokenRope[IDBreak].token};
NodeX: PUBLIC FieldProc = {pd.x ← from.GetReal[]};
NodeY: PUBLIC FieldProc = {pd.y ← from.GetReal[]};
MetalArea: PUBLIC FieldProc = {pd.areas[Metal] ← from.GetReal[]};
PolyArea: PUBLIC FieldProc = {pd.areas[Poly] ← from.GetReal[]};
DiffArea: PUBLIC FieldProc = {pd.areas[NDiff] ← from.GetReal[]};
MetalPerim: PUBLIC FieldProc = {pd.perimiters[Metal] ← from.GetReal[]};
PolyPerim: PUBLIC FieldProc = {pd.perimiters[Poly] ← from.GetReal[]};
DiffPerim: PUBLIC FieldProc = {pd.perimiters[NDiff] ← from.GetReal[]};
EatTrash: PUBLIC FieldProc = {[] ← from.GetRefAny[]};
ReadCap: PUBLIC FieldProc = {pd.capacitanceEstimate ← from.GetReal[]};
Gate: PUBLIC FieldProc = {pd.gate ← from.GetTokenRope[IDBreak].token};
Source: PUBLIC FieldProc = {pd.source ← from.GetTokenRope[IDBreak].token};
Drain: PUBLIC FieldProc = {pd.drain ← from.GetTokenRope[IDBreak].token};
Length: PUBLIC FieldProc = {pd.length ← from.GetReal[]};
Width: PUBLIC FieldProc = {pd.width ← from.GetReal[]};
AbsLength: FieldProc = {IF (pd.length ← from.GetReal[]) < 0 THEN {
IF c.warningLog # NIL THEN c.warningLog.PutF["SimRead found negative length (%g) at char %g.\n", IO.real[pd.length], IO.int[from.GetIndex[]]];
pd.length ← ABS[pd.length]}};
AbsWidth: FieldProc = {IF (pd.width ← from.GetReal[]) < 0 THEN {
IF c.warningLog # NIL THEN c.warningLog.PutF["SimRead found negative width (%g) at char %g.\n", IO.real[pd.width], IO.int[from.GetIndex[]]];
pd.width ← ABS[pd.width]}};
Shape: PUBLIC FieldProc =
{[] ← from.SkipWhitespace[flushComments: FALSE]; pd.shape ← from.GetChar[]};
TransistorX: PUBLIC FieldProc = {pd.x ← from.GetReal[]};
TransistorY: PUBLIC FieldProc = {pd.y ← from.GetReal[]};
TransistorArea: PUBLIC FieldProc = {pd.area ← from.GetReal[]};
Coefs: TYPE = REF CoefsRep;
CoefsRep: TYPE = RECORD [
area, perim: ARRAY Layer OF REALALL[0],
gates: ARRAY TransistorType OF REALALL[0],
given: BOOLEANFALSE];
AllocateCoefs: PROC [pd: ParseData, f: Format] =
{pd.other ← NEW [CoefsRep ← []]};
FinishEstimatingNode: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
coefs: Coefs ← NARROW[pd.other];
[] ← from.GetLineRope[];
IF c.GotNode = NIL THEN RETURN;
IF NOT coefs.given THEN ERROR;
pd.capacitanceEstimate ← 0;
pd.capEstimateClass ← incremental;
FOR l: Layer IN Layer DO
pd.capacitanceEstimate ← pd.capacitanceEstimate +
pd.areas[l]*coefs.area[l] +
pd.perimiters[l]*coefs.perim[l];
ENDLOOP;
c.GotNode[pd, c.data];
END;
ComputeTransistorArea: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
pd.area ← pd.length*pd.width;
END;
FinishEstimatingTransistor: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
coefs: Coefs ← NARROW[pd.other];
[] ← from.GetLineRope[];
IF c.GotTransistor = NIL THEN RETURN;
pd.transistorType ← SELECT first FROM 'e => nE, 'd => nD, 'c => pE, 'b => pD, ENDCASE => ERROR;
IF NOT coefs.given THEN ERROR;
pd.capacitanceEstimate ← pd.area * coefs.gates[pd.transistorType];
pd.capEstimateClass ← incremental;
c.GotTransistor[pd, c.data];
END;
EatComment: PUBLIC PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
{[] ← from.GetLineRope[]};
CoeffyComment: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
coefs: Coefs ← NARROW[pd.other];
cmd: ROPE ← from.GetTokenRope[IDLineBreak].token;
IF cmd.Equal["\n"] THEN RETURN;
IF NOT cmd.Equal["capacitanceCoefficients", FALSE] THEN
{[] ← from.GetLineRope[]; RETURN};
DO
ok: BOOLEANTRUE;
cmd ← from.GetTokenRope[IDLineBreak].token;
IF cmd.Equal["\n"] THEN RETURN;
IF cmd.Equal["diffArea", FALSE] THEN coefs.area[NDiff] ← from.GetReal[] ELSE
IF cmd.Equal["polyArea", FALSE] THEN coefs.area[Poly] ← from.GetReal[] ELSE
IF cmd.Equal["metalArea", FALSE] THEN coefs.area[Metal] ← from.GetReal[] ELSE
IF cmd.Equal["diffPerim", FALSE] THEN coefs.perim[NDiff] ← from.GetReal[] ELSE
IF cmd.Equal["polyPerim", FALSE] THEN coefs.perim[Poly] ← from.GetReal[] ELSE
IF cmd.Equal["metalPerim", FALSE] THEN coefs.perim[Metal] ← from.GetReal[] ELSE
IF cmd.Equal["NEGate", FALSE] THEN coefs.gates[nE] ← from.GetReal[] ELSE
IF cmd.Equal["NDGate", FALSE] THEN coefs.gates[nD] ← from.GetReal[] ELSE
IF cmd.Equal["PEGate", FALSE] THEN coefs.gates[pE] ← from.GetReal[] ELSE
IF cmd.Equal["PDGate", FALSE] THEN coefs.gates[pD] ← from.GetReal[] ELSE
ok ← FALSE;
IF ok THEN coefs.given ← TRUE;
ENDLOOP;
END;
FinishBerkeleyTransistor: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
[] ← from.GetLineRope[];
IF c.GotTransistor = NIL THEN RETURN;
pd.transistorType ← SELECT first FROM 'e => nE, 'd => nD, 'c => pE, 'b => pD, ENDCASE => ERROR;
pd.capacitanceEstimate ← 0;
pd.capEstimateClass ← ignore;
c.GotTransistor[pd, c.data];
END;
BerkeleyCap: PROC [first: CHAR, from: IO.STREAM, f: Format, pd: ParseData, c: Client] RETURNS [continue: BOOLTRUE] --FieldProc-- =
BEGIN
name1: ROPE ← from.GetTokenRope[IDBreak].token;
name2: ROPE ← from.GetTokenRope[IDBreak].token;
pd.capacitanceEstimate ← from.GetReal[];
[] ← from.GetLineRope[];
IF c.GotNode = NIL THEN RETURN;
IF name2.Equal["GND"] THEN pd.name ← name1
ELSE IF name1.Equal["GND"] THEN pd.name ← name2
ELSE {
IF c.warningLog # NIL THEN c.warningLog.PutF["SimRead non-grounded capacitor between %g and %g at char %g.\n", IO.rope[name1], IO.rope[name2], IO.int[from.GetIndex[]]];
RETURN;
};
pd.capEstimateClass ← absolute;
c.GotNode[pd, c.data];
END;
GetInt: PROC [s: IO.STREAM] RETURNS [i: INT] =
{i ← s.GetInt[!IO.Error => IF ec = Overflow THEN {i ← ceiling; CONTINUE}]};
IDBreak: PROC [char: CHAR] RETURNS [IO.CharClass] --IO.BreakProc-- =
BEGIN
RETURN [SELECT char FROM
IO.SP, IO.CR, IO.ESC, IO.LF, IO.TAB, ',, '; => sepr,
ENDCASE => other];
END;
IDLineBreak: PROC [char: CHAR] RETURNS [IO.CharClass] --IO.BreakProc-- =
BEGIN
RETURN [SELECT char FROM
IO.CR => break,
IO.SP, IO.ESC, IO.LF, IO.TAB => sepr,
ENDCASE => other];
END;
Start: PROC =
BEGIN
useClientsOther: Handler = LIST[UseClientsOther];
chipmonk: Format ← NEW [FormatRep ← [ALL[useClientsOther], NIL, NIL]];
stanford: Format ← NEW [FormatRep ← [ALL[useClientsOther], NIL, NIL]];
berkeley: Format ← NEW [FormatRep ← [ALL[useClientsOther], NIL, NIL]];
chipmonk.whatToDo['N] ← chipmonk.whatToDo['n] ← LIST [NodeName, MetalArea, PolyArea, DiffArea, DiffPerim, EatTrash, FinishEstimatingNode];
chipmonk.whatToDo['e] ← chipmonk.whatToDo['d] ← chipmonk.whatToDo['c] ← chipmonk.whatToDo['b] ← LIST [Gate, Source, Drain, Length, Width, TransistorX, TransistorY, ComputeTransistorArea, FinishEstimatingTransistor];
chipmonk.whatToDo['|] ← LIST [CoeffyComment];
chipmonk.whatToDo['@] ← LIST [FollowIndirection];
chipmonk.Init ← AllocateCoefs;
SetFormat["Chipmonk", chipmonk];
stanford.whatToDo['N] ← stanford.whatToDo['n] ← LIST [NodeName, NodeX, NodeY, MetalArea, PolyArea, DiffArea, DiffPerim, FinishEstimatingNode];
stanford.whatToDo['e] ← stanford.whatToDo['d] ← stanford.whatToDo['c] ← stanford.whatToDo['b] ← LIST [Gate, Source, Drain, Length, Width, Shape, TransistorX, TransistorY, TransistorArea, FinishEstimatingTransistor];
stanford.whatToDo['|] ← LIST [CoeffyComment];
stanford.whatToDo['@] ← LIST [FollowIndirection];
stanford.Init ← AllocateCoefs;
SetFormat["Stanford", stanford];
berkeley.whatToDo['C] ← LIST [BerkeleyCap];
berkeley.whatToDo['e] ← berkeley.whatToDo['d] ← berkeley.whatToDo['c] ← berkeley.whatToDo['b] ← LIST [Gate, Source, Drain, AbsLength, AbsWidth, TransistorX, TransistorY, FinishBerkeleyTransistor];
berkeley.whatToDo['|] ← LIST [EatComment];
berkeley.whatToDo['@] ← LIST [FollowIndirection];
SetFormat["Berkeley", berkeley];
END;
Start[];
END.