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. PSimReadImpl.Mesa Last Edited by: Spreitzer, May 28, 1984 10:43:24 pm PDT Κ (– "cedar" style˜Icode™K™7K˜KšΟk œœœ˜ K˜šΠbx œœ˜Kšœœœ˜Kšœ ˜—K˜Kšœœ ˜K˜š Οn œœœœœ#˜KKš˜Kšœœ˜(Kšœœœ ˜9Kšœœœ ˜9K˜?Kšœ˜—K˜šŸ œœœœ2˜SKš˜Kšœœœ˜šœ˜ Kšœœ˜ Kšœœœ ˜Kšœ(œ˜/Kšœœœ˜K˜š œ-œ œœ˜PK˜KKšœ˜—Kšœ˜—Kšœ˜—K˜š œ œœœœœ˜@Kšœœ˜—K˜Kšœœ˜K˜šŸ œœœœ˜5Kšœ œ˜*—K˜š Ÿ œœœœœ˜>Kš˜šœ#œœ˜7Kšœ%œœœ˜KKšœ˜—Kšœ œ˜ Kšœ˜—K˜šŸœœœ œœœ'œ œœΟc œ˜Kš˜šœ˜Kšœ;˜?šœ˜ K˜Kšœ œ˜Kšœ˜——Kšœ˜—K˜šŸœœœ œœœ'œ œœ  œ˜’Kš˜Kšœ œœ˜4Kšœœœœ˜)K˜K˜4K˜ Kšœ˜—K˜Kšœ œ:˜JKšœœ%˜2Kšœœ%˜2Kšœ œ0˜AKšœ œ/˜?Kšœ œ0˜@Kšœ œ5˜GKšœ œ4˜EKšœ œ5˜FKšœ œ%˜5Kšœ œ7˜FK˜Kšœœ:˜FKšœœ<˜JKšœœ;˜HKšœœ*˜8Kšœœ)˜6šœœ"œ˜BKš œœœGœœ˜ŽKšœ œ˜—šœœ!œ˜@Kš œœœFœœ˜ŒKšœ œ ˜—šœœ ˜Kšœ)œ˜L—Kšœ œ%˜8Kšœ œ%˜8Kšœœ(˜>K˜Kšœœœ ˜šœ œœ˜Kš œ œœœœ˜*Kš œœœœœ˜-Kšœœœ˜—K˜šŸ œœ˜0Kšœ œ˜!—K˜šŸœœ œœœ'œ œœ  œ˜ŽKš˜Kšœœ ˜ K˜Kšœ œœœ˜Kšœœ œœ˜Kšœ˜Kšœ"˜"šœ œ˜šœ1˜1Kšœ˜Kšœ ˜ —Kšœ˜—Kšœ˜Kšœ˜—K˜šŸœœ œœœ'œ œœ  œ˜Kš˜Kšœ˜Kšœ˜—K˜šŸœœ œœœ'œ œœ  œ˜”Kš˜Kšœœ ˜ K˜Kšœœœœ˜%Kš œœœ)œœ˜_Kšœœ œœ˜KšœB˜BKšœ"˜"Kšœ˜Kšœ˜—K˜šŸ œœœ œœœ'œ œœ  œ˜‹Kšœ˜—K˜šŸ œœ œœœ'œ œœ  œ˜‡Kš˜Kšœœ ˜ Kšœœ(˜1Kšœœœ˜šœœ&œ˜7Kšœœ˜"—š˜Kšœœœ˜Kšœ+˜+Kšœœœ˜Kšœœœ$˜LKšœœœ#˜KKšœœœ$˜MKšœœœ%˜NKšœœœ$˜MKšœœœ%˜OKšœœœ"˜HKšœœœ"˜HKšœœœ"˜HKšœœœ"˜HKšœœ˜ Kšœœœ˜Kšœ˜—Kšœ˜—K˜šŸœœ œœœ'œ œœ  œ˜’Kš˜K˜Kšœœœœ˜%Kš œœœ)œœ˜_Kšœ˜Kšœ˜Kšœ˜Kšœ˜—K˜šŸ œœ œœœ'œ œœ  œ˜…Kš˜Kšœœ$˜/Kšœœ$˜/Kšœ(˜(K˜Kšœ œœœ˜Kšœœ˜*Kšœœœ˜/šœ˜Kš œœœUœœœ˜¨Kšœ˜K˜—Kšœ˜Kšœ˜Kšœ˜—K˜š Ÿœœœœœœ˜.Kš œœ œœœ˜K—K˜š Ÿœœœœœ  œ˜DKš˜šœœ˜Kšœœœœœœœœœœ˜4Kšœ ˜—Kšœ˜—K˜š Ÿ œœœœœ  œ˜HKš˜šœœ˜Kšœœ ˜Kšœœœœœœœœ ˜%Kšœ ˜—Kšœ˜—K˜šŸœœ˜ Kš˜Kšœœ˜1Kš œœœœœ˜FKš œœœœœ˜FKš œœœœœ˜FKšœ0œV˜ŠKšœ`œs˜ΧKšœœ˜-Kšœœ˜1K˜K˜ Kšœ0œZ˜ŽKšœ`œs˜ΧKšœœ˜-Kšœœ˜1Kšœ˜Kšœ ˜ Kšœœ˜+Kšœ`œ`˜ΔKšœœ˜*Kšœœ˜1Kšœ ˜ Kšœ˜—K˜K˜K˜Kšœ˜—…—&Θ3@