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: BOOL ← TRUE;
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:
BOOL ←
TRUE]
--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:
BOOL ←
TRUE]
--FieldProc-- =
BEGIN
fileName: ROPE ← from.GetTokenRope[IO.IDProc].token;
sub: IO.STREAM ← FS.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 REAL ← ALL[0],
gates: ARRAY TransistorType OF REAL ← ALL[0],
given: BOOLEAN ← FALSE];
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:
BOOL ←
TRUE]
--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:
BOOL ←
TRUE]
--FieldProc-- =
BEGIN
pd.area ← pd.length*pd.width;
END;
FinishEstimatingTransistor:
PROC [first:
CHAR, from:
IO.
STREAM, f: Format, pd: ParseData, c: Client]
RETURNS [continue:
BOOL ←
TRUE]
--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:
BOOL ←
TRUE]
--FieldProc-- =
{[] ← from.GetLineRope[]};
CoeffyComment:
PROC [first:
CHAR, from:
IO.
STREAM, f: Format, pd: ParseData, c: Client]
RETURNS [continue:
BOOL ←
TRUE]
--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: BOOLEAN ← TRUE;
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:
BOOL ←
TRUE]
--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:
BOOL ←
TRUE]
--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.