DIRECTORY AbSets, BasicTime, BiRels, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenFromExtPrivate, LichenIntBasics, RefText, Rope, SetBasics; LichenFromExtImpl2: CEDAR MONITOR LOCKS dr USING dr: DesignReading IMPORTS AbSets, BasicTime, BiRels, IO, LichenDataOps, LichenDataStructure, LichenFromExtPrivate, LichenIntBasics, RefText, Rope, SetBasics EXPORTS LichenFromExtPrivate = BEGIN OPEN LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, LichenFromExtPrivate, Sets:AbSets; GetOSn: PROC [dr: DesignReading, ct: CellType, s: Source] RETURNS [name: SteppyName] ~ { raw: ROPE ~ GetName[s]; name _ ParseSteppyName[raw]; IF name.steps.rest#NIL THEN ERROR; name _ MapFirst[dr, ct, name]; RETURN}; GetName: PROC [s: Source] RETURNS [name: ROPE] = { from: IO.STREAM = s.stream; [] _ from.SkipWhitespace[]; SELECT from.PeekChar[] FROM '" => name _ from.GetRopeLiteral[]; ENDCASE => name _ from.GetTokenRope[TokenBreak].token; }; EndLine: PROC [from: IO.STREAM, buffer: REFTEXT] = { IF NOT from.EndOf[] THEN [] _ from.GetLine[buffer]; }; ReadTech: PROC [s: Source, reader: Reader, cr: CellReading] = { ct: CellType = cr.ct; from: IO.STREAM = s.stream; techname: ROPE _ GetName[s]; EndLine[from, cr.dr.buffer]; RETURN}; ReadTimestamp: PROC [s: Source, reader: Reader, cr: CellReading] = { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; unixTime: INT ~ from.GetInt[]; time: BasicTime.GMT ~ BasicTime.Update[unixOrigin, unixTime]; EndLine[from, cr.dr.buffer]; RETURN}; unixOrigin: BasicTime.GMT _ BasicTime.Pack[[ year: 1970, month: January, day: 1, hour: 0, minute: 0, second: 0, zone: 0--GMT, I hope--, dst: no]]; ReadVersion: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; version: ROPE ~ GetName[s]; deriver: ROPE ~ "UCB's Magic .extractor"; EndLine[from, cr.dr.buffer]; RETURN}; ReadScale: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; rscale: INT ~ from.GetInt[]; cscale: INT ~ from.GetInt[]; lscale: INT ~ from.GetInt[]; IF cr.scalingDefined THEN Warn[s, "More than one scale statment"]; cr.scalingDefined _ TRUE; cr.rScale _ rscale * cr.rScale; cr.cScale _ cscale * cr.cScale; cr.lUnits _ lscale * cr.lUnits; EndLine[from, cr.dr.buffer]; RETURN}; ReadResistClasses: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; n: INT _ 0; IF cr.resistClasses # undefinedINT THEN Warn[s, "More than one resistclasses statment"]; DO token: ROPE = from.GetTokenRope[TokenBreak].token; IF token.Equal["\n"] THEN EXIT; n _ n + 1; ENDLOOP; cr.resistClasses _ n; RETURN}; keepCruft: BOOL _ FALSE; ReadNode: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; fullName: SteppyName ~ GetOSn[cr.dr, ct, s]; R: INT ~ from.GetInt[]; C: INT ~ from.GetInt[]; x: INT ~ from.GetInt[]; y: INT ~ from.GetInt[]; ok: BOOL ~ SkipNTokens[from, cr.resistClasses*2, cr.dr.buffer]; attrs: LORA ~ ReadAttrs[s]; nv: Wire _ FetchWire[ct, fullName]; <> IF nv = NIL THEN nv _ CreateWire[ct, OneSteppy[fullName], FALSE, TRUE, TRUE]; CTIncludesPoint[ct, [x, y]]; EndLine[from, cr.dr.buffer]; RETURN}; ReadAttrs: PROC [s: Source, zeroNIL: BOOL _ FALSE] RETURNS [allTogetherNow: LORA _ NIL] = { from: IO.STREAM = s.stream; toke: ROPE _ NIL; IF zeroNIL THEN { [] _ from.SkipWhitespace[]; IF from.PeekChar[] = '0 THEN { IF from.GetChar[] # '0 THEN ERROR; RETURN}; }; {DO attr: ROPE _ NIL; toke _ from.GetTokenRope[AttrBreak !IO.EndOfStream => EXIT].token; IF toke.Equal[","] THEN {Warn[s, "Extra comma"]; LOOP}; IF NOT toke.Equal["\""] THEN GOTO Return; from.Backup['"]; attr _ from.GetRopeLiteral[ !IO.Error, IO.EndOfStream => {Warn[s, "not a rope literal"]; CONTINUE}]; IF attr # NIL THEN allTogetherNow _ CONS[attr, allTogetherNow]; toke _ from.GetTokenRope[AttrBreak !IO.EndOfStream => EXIT].token; IF NOT toke.Equal[","] THEN GOTO Return; ENDLOOP; EXITS Return => { FOR i: INT DECREASING IN [0 .. toke.Length[]) DO s.stream.Backup[toke.Fetch[i]]; ENDLOOP; }; }}; AttrBreak: PROC [char: CHAR] RETURNS [cc: IO.CharClass] = {cc _ SELECT char FROM ',, '\n, '" => break, ENDCASE => sepr}; ReadEquiv: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; name1: SteppyName ~ GetOSn[cr.dr, ct, s]; name2: SteppyName ~ GetOSn[cr.dr, ct, s]; v1: Wire ~ FetchWire[ct, name1]; v2: Wire ~ FetchWire[ct, name2]; IF name1.steps.rest#NIL OR name2.steps.rest#NIL THEN ERROR; SELECT TRUE FROM v1=v2 => IF v1=NIL THEN ERROR; v1=NIL => KnowVertexName[ct, v2, name1, FALSE]; v2=NIL => KnowVertexName[ct, v1, name2, FALSE]; ENDCASE => ERROR; EndLine[from, cr.dr.buffer]; RETURN}; ReadFet: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; type: ROPE ~ GetName[s]; xl: INT ~ from.GetInt[]; yl: INT ~ from.GetInt[]; xh: INT ~ from.GetInt[]; yh: INT ~ from.GetInt[]; area: INT ~ from.GetInt[]; perim: INT ~ from.GetInt[]; sub: ROPE ~ GetName[s]; GATE: FetTerminal ~ GetFetTerminal[s]; T1: FetTerminal ~ GetFetTerminal[s]; T2: FetTerminal ~ GetFetTerminal[s]; sct: CellType; tv: CellInstance; offset: Int2; DoTerm: PROC [portName: ROPE, ft: FetTerminal] ~ { path: Path ~ ParsePath[s, cr.dr, ct, ft.name, TRUE]; w: Wire ~ PathGet[cr.dr, ct, path, TRUE]; p: Port ~ FetchPort[sct, OSn[portName]]; Connect[cr.dr.d, w, p, tv]; RETURN}; [sct, offset] _ GetFetType[cr.dr, type, [[xl, xh], [yl, yh]], area, perim, T1.length+T2.length]; tv _ Instantiate[sct, ct, FALSE, [], offset, OneOSn[IO.PutFR["Q%g#", IO.int[cr.fetCount _ cr.fetCount + 1]]]]; DoTerm["gate", GATE]; DoTerm["ch1", T1]; DoTerm["ch2", T2]; EndLine[from, cr.dr.buffer]; RETURN}; GetFetTerminal: PROC [s: Source] RETURNS [ft: FetTerminal] ~ { from: IO.STREAM ~ s.stream; ft.name _ GetName[s]; ft.length _ from.GetInt[]; {attrs: LORA _ ReadAttrs[s, TRUE]; RETURN}}; GetFetType: PROC [dr: DesignReading, className: ROPE, innerGate: Range2, area, perim, sumChannelLengths: INT] RETURNS [ct: CellType, offset: Int2] ~ { d: Design ~ dr.d; shape: Int2 ~ RangeShape[innerGate]; ft: FetType ~ NEW [FetTypeRep _ [className, area, perim, sumChannelLengths]]; rft: FetType; rft _ NARROW[dr.fetTypes.ApplyA[ft].MDA]; offset _ Range2Min[innerGate]; IF rft = NIL THEN { cellTypeName: ROPE ~ IO.PutFLR["%g[%g,%g,%g,%g,%g]", LIST[IO.rope[ft.className], IO.int[ft.area], IO.int[ft.perim], IO.int[ft.twiceLength], IO.int[shape[X]], IO.int[shape[Y]] ]]; rft _ ft; ft.ct _ CreateCellType[d, leaf, OneRope[cellTypeName]]; ft.ct.bbox _ SizeRange[shape]; ft.ct.asTrans _ NEW [TransistorPrivate _ [ type: className, area: area, perimeter: perim]]; [] _ CreatePort[ft.ct, OneOSn[R["gate"]], FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE]; [] _ CreatePort[ft.ct, OneOSn[R["ch1"]], FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE]; [] _ CreatePort[ft.ct, OneOSn[R["ch2"]], FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE]; dr.fetTypes.AddNewAA[ft, rft]; }; ct _ rft.ct; RETURN}; ReadUse: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; typeName: ROPE ~ GetName[s]; useId: ROPE ~ GetName[s]; dxdx: INT ~ from.GetInt[]; dxdy: INT ~ from.GetInt[]; dx: INT ~ from.GetInt[]; dydx: INT ~ from.GetInt[]; dydy: INT ~ from.GetInt[]; dy: INT ~ from.GetInt[]; xfm: Transform ~ XfmFrom4[dxdx, dxdy, dydx, dydy]; pu: Use ~ ParseUseDef[useId]; u: Use ~ TransformUse[xfm, pu]; type: CellType ~ EnsureType[cr, u.childName, typeName, u.as, xfm, ct]; ci: CellInstance ~ Instantiate[type, ct, TRUE, IF u.as.kind=array THEN [] ELSE xfm, [dx, dy], OneOSn[u.childName]]; EndLine[from, cr.dr.buffer]}; TransformUse: PROC [xfm: Transform, u: Use] RETURNS [Use] ~ { WITH u.as SELECT FROM scalar => RETURN [u]; array => { aas: ArraySpec.array ~ [variant: array[ range: xfm.TranspRange2[range], sep: xfm.TransformVector[sep] ]]; RETURN [[childName: u.childName, as: aas]]}; ENDCASE => ERROR}; ParseUseDef: PROC [useId: ROPE] RETURNS [u: Use] ~ { in: IO.STREAM ~ IO.RIS[useId]; u.childName _ in.GetTokenRope[UseNameBreak].token; IF in.EndOf[] THEN { in.Close[]; RETURN [[u.childName, [scalar[]]]] } ELSE { as: ArraySpec.array _ [array[range: ALL[[0, 0]], sep: [0, 0]]]; Get: PROC [d: Dim2] ~ { IF in.GetChar[] # '[ THEN ERROR; as.range[d].min _ in.GetInt[]; IF in.GetChar[] # ': THEN ERROR; as.range[d].maxPlusOne _ in.GetInt[]+1; IF in.GetChar[] # ': THEN ERROR; as.sep[d] _ in.GetInt[]; IF in.GetChar[] # '] THEN ERROR; }; Get[X]; Get[Y]; IF NOT in.EndOf[] THEN ERROR; in.Close[]; RETURN [[u.childName, as]]; }; }; UseNameBreak: PROC [char: CHAR] RETURNS [cc: IO.CharClass] --IO.BreakProc-- = { cc _ SELECT char FROM '[, '], ': => break, ENDCASE => other; }; EnsureType: PROC [cr: CellReading, childName, typeName: ROPE, as: ArraySpec, xfm: Transform, parent: CellType] RETURNS [ct: CellType] ~ { dr: DesignReading ~ cr.dr; d: Design ~ dr.d; clip: BOOL ~ cr.dr.clipINT.HasAA[childName, parent]; cellTypeName: ROPE ~ WITH as SELECT FROM x: ArraySpec.scalar => typeName, x: ArraySpec.array => IO.PutFR["%g%g(%g.%g)", [rope[typeName]], [rope[FmtAS[as]]], [rope[NARROW[d.ctName.ApplyA[parent].MA]]], [rope[childName]] ], ENDCASE => ERROR; IF clip AND as.kind=array THEN RETURN EnsureType[cr, childName, cellTypeName, [scalar[]], xfm, parent]; WITH as SELECT FROM x: ArraySpec.scalar => { ct _ NARROW[d.ctName.ApplyA[typeName, rightToLeft].MDA]; IF ct#NIL THEN NULL ELSE IF clip THEN { ct _ CreateCellType[d, leaf, OneRope[typeName]]; ct.bbox _ ALL[[0, 1]]} ELSE ct _ ReadCellType[d, typeName, dr]; }; x: ArraySpec.array => { eltType: CellType ~ EnsureType[cr, NIL, typeName, [scalar[]], [], NIL]; size: Int2 ~ RangeShape[x.range]; ct _ CreateArray[d, eltType, size, [1, 1], BiRels.CreateSingleton[[I2V[[0, 0]], XfmV[xfm]], [int2s, xfmSpace]], OffsetsFromList[LIST[[o0: ALL[0], o1: x.sep]]], OneRope[cellTypeName]]; cr.dr.arraySpecs.AddNewAA[ct, NEW [ArraySpec.array _ x]]; IF NOT cr.newArrays.AddA[ct] THEN ERROR; }; ENDCASE => ERROR; }; NameElt: PROC [i: INT] RETURNS [eltName: NameStep] ~ {eltName _ NewInt[i]}; FmtAS: PROC [as: ArraySpec] RETURNS [r: ROPE] = { r _ WITH as SELECT FROM scalar => "scalar", array => IO.PutFLR["[%g:%g:%g][%g:%g:%g]", LIST[ IO.int[range[X].min], IO.int[range[X].maxPlusOne-1], IO.int[sep[X]], IO.int[range[Y].min], IO.int[range[Y].maxPlusOne-1], IO.int[sep[Y]]]], ENDCASE => ERROR; }; FmtShape: PROC [shape: Int2] RETURNS [r: ROPE] = { r _ IO.PutFR["[X: %g, Y: %g]", IO.int[shape[X]], IO.int[shape[Y]]]; RETURN}; ReadMerge: PROC [s: Source, reader: Reader, cr: CellReading] ~ { ct: CellType ~ cr.ct; from: IO.STREAM ~ s.stream; IF cr.firstMerge THEN {cr.firstMerge _ FALSE; TryArrayFile[cr]}; {name1: ROPE ~ GetName[s]; name2: ROPE ~ GetName[s]; path1: Path ~ ParsePath[s, cr.dr, ct, name1, TRUE]; path2: Path ~ ParsePath[s, cr.dr, ct, name2, TRUE]; IF ComparePaths[path1, cr.dr.mostRecentPathToMerge]#equal THEN { DoMerges[s, cr]; AddMerge[cr.dr, path1]; }; AddMerge[cr.dr, path2]; cr.dr.mostRecentPathToMerge _ path2; EndLine[from, cr.dr.buffer]; RETURN}}; AddMerge: PROC [dr: DesignReading, path: Path] ~ { arrayPrefix: Path ~ [IF path.cells#NIL AND path.cells.rest#NIL THEN WITH path.cells.first SELECT FROM x: ROPE => WITH path.cells.rest.first SELECT FROM r: REF Range2 => LIST[x, r], ENDCASE => NIL, ENDCASE => NIL ELSE NIL]; apv: Sets.Value ~ arrayPrefix.PathV; rs: REF Set--of Path-- _ NARROW[dr.toMerge.Apply[apv].MDA]; IF rs=NIL THEN dr.toMerge.AddNewPair[[apv, AV[rs _ Sets.CreateHashSet[paths].Refify]]]; IF NOT rs^.AddElt[PathV[path]] THEN ERROR; RETURN}; ArrayMerge: PUBLIC PROC [cr: CellReading, arrayInstance: CellInstance, instanceName: ROPE, path1, path2: Path, may: BOOL] RETURNS [merged: BOOL] = { dr: DesignReading ~ cr.dr; d: Design ~ dr.d; act: CellType = d.CiT[arrayInstance]; a: Array = act.asArray; et: CellType = act.EltType[]; rr1: REF Range2 = NARROW[path1.cells.first]; rr2: REF Range2 = NARROW[path2.cells.first]; r1: Range2 = rr1^; r2: Range2 = rr2^; size: Int2 = RangeShape[r2]; mai1: Int2 = Range2Min[r1]; mai2: Int2 = Range2Min[r2]; D: Int2 = LIB.Sub[mai2, mai1]; p1: Port = PortGet[dr, et, path1.PTail, may, FALSE]; p2: Port = PortGet[dr, et, path2.PTail, may, FALSE]; IF RangeShape[r1] # size THEN ERROR; IF p1=NIL OR p2=NIL THEN {IF may THEN ERROR ELSE RETURN [FALSE]}; IF may THEN { IF ABS[D[X]]>1 OR ABS[D[Y]]>1 THEN ERROR; MakeArrayNewConnection[d, a, r1, D, p1, p2]; RETURN [TRUE]} ELSE { IF size # [1, 1] THEN ERROR; merged _ ArrayEltPortsConnected[act, mai1, mai2, p1, p2]; RETURN}; }; MergeFinal: PUBLIC PROC [dr: DesignReading, ct: CellType, path1, path2: Path] = { w1, w2, nw: Wire; w1 _ PathGet[dr, ct, path1, TRUE]; w2 _ PathGet[dr, ct, path2, TRUE]; IF w1#w2 THEN nw _ MergeNets[dr.d, w1, w2, FALSE].merged; RETURN}; ParsePath: PUBLIC PROC [s: Source, dr: DesignReading, from: CellType, asRope: ROPE, map: BOOL] RETURNS [Path] = { in: IO.STREAM = IO.RIS[asRope]; GetRange: PROC RETURNS [x: Range] = { x.maxPlusOne _ (x.min _ in.GetInt[]) + 1; SELECT in.PeekChar[] FROM ': => { IF in.GetChar[] # ': THEN ERROR; x.maxPlusOne _ in.GetInt[] + 1; }; ',, '] => NULL; ENDCASE => ERROR; }; ClipTail: TYPE ~ RECORD [glob: BOOL, steps: NameStepList]; ReadClippedName: PROC [first: BOOL] RETURNS [ClipTail] ~ { toke: ROPE ~ in.GetTokenRope[PathNameBreak].token; SELECT TRUE FROM toke.Equal["/"] => RETURN ReadClippedName[first]; toke.Equal["["] => { r2: Range2 _ [X: [0, 1], Y: GetRange[]]; sep: ROPE _ in.GetTokenRope[PathNameBreak].token; twoD: BOOL _ sep.Equal[","]; IF twoD THEN { r2[X] _ GetRange[]; sep _ in.GetTokenRope[PathNameBreak].token}; IF NOT sep.Equal["]"] THEN ERROR; {ans: ClipTail _ ReadClippedName[FALSE]; IF LIB.RangeShape[r2] # [1, 1] THEN { IF NOT first THEN ERROR; IF ans.glob THEN first _ first ELSE cells _ cells.Append[NEW [Range2 _ r2]]; RETURN [ans]}; IF ans.glob THEN RETURN [ans]; ans.steps _ CONS[NewInt[r2[Y].min], ans.steps]; IF twoD THEN ans.steps _ CONS[NewInt[r2[X].min], ans.steps] ELSE first _ first; RETURN [ans]}}; toke.Equal["]"] => ERROR; toke.Equal[":"] => ERROR; toke.Equal[","] => ERROR; ENDCASE => {tail: ClipTail ~ IF in.EndOf[] THEN [FALSE, NIL] ELSE ReadClippedName[FALSE]; IF tail.glob THEN RETURN [tail]; RETURN [[toke.InlineFetch[toke.Length[]-1] = '!, CONS[toke, tail.steps]]]}; }; cells: TList _ []; DO toke: ROPE ~ in.GetTokenRope[PathNameBreak].token; ras: REF ArraySpec.array = NARROW[dr.arraySpecs.ApplyA[from].MDA]; next: CellType _ NIL; SELECT TRUE FROM toke.Equal["/"] => LOOP; toke.Equal["["] => { xd: BOOL = ras.range[X].min # ras.range[X].maxPlusOne-1; yd: BOOL = ras.range[Y].min # ras.range[Y].maxPlusOne-1; a: Array ~ from.asArray; r2: Range2 _ ras.range; twoD: BOOL _ FALSE; IF NOT (xd OR yd) THEN ERROR; IF yd THEN r2[Y] _ GetRange[] ELSE r2[X] _ GetRange[]; {sep: ROPE ~ in.GetTokenRope[PathNameBreak].token; SELECT TRUE FROM sep.Equal["]"] => NULL; sep.Equal[","] => { twoD _ TRUE; r2[X] _ GetRange[]; {eb: ROPE ~ in.GetTokenRope[PathNameBreak].token; IF NOT eb.Equal["]"] THEN ERROR}}; ENDCASE => ERROR; IF twoD # (xd AND yd) THEN ERROR; IF a.basePeriod # ALL[1] THEN ERROR; IF twoD THEN r2 _ VXfm[a.fXfm.Apply[I2V[ALL[0]]].Val].TranspRange2[r2]; cells _ cells.Append[NEW [Range2 _ r2]]; next _ from.EltType[]}}; toke.Equal["]"] => ERROR; toke.Equal[":"] => ERROR; toke.Equal[","] => ERROR; in.EndOf[] => { wireName: SteppyName ~ IF map THEN MapName[dr, from, toke] ELSE OSn[toke]; IF from.FetchWire[wireName]=NIL THEN ERROR; in.Close[]; RETURN [[cells.head, wireName]]}; ENDCASE => { cellName: ROPE ~ toke; clip: BOOL ~ dr.clipINT.HasAA[cellName, from]; cells _ cells.Append[cellName]; IF clip THEN { tail: ClipTail ~ ReadClippedName[TRUE]; RETURN [[cells.head, LSn[tail.steps]]]} ELSE next _ dr.d.CiT[from.FetchSubcell[OSn[cellName]]]}; IF next=NIL THEN ERROR; from _ next; ENDLOOP; }; PathNameBreak: PROC [char: CHAR] RETURNS [cc: IO.CharClass] --IO.BreakProc-- = { cc _ SELECT char FROM '[, '], ':, '/, ', => break, ENDCASE => other; }; PathGet: PUBLIC PROC [dr: DesignReading, from: CellType, path: Path, mayAdd: BOOL] RETURNS [w: Wire] = { d: Design ~ dr.d; IF path.cells#NIL THEN { name: ROPE ~ NARROW[path.cells.first]; clip: BOOL ~ dr.clipINT.HasAA[name, from]; ci: CellInstance ~ from.FetchSubcell[OSn[name]]; childPort: Port ~ PortGet[dr, d.CiT[ci], path.PTail, mayAdd, clip]; IF childPort # NIL THEN { w _ ConndWire[ci, childPort]; IF w=NIL THEN ERROR; RETURN}; RETURN} ELSE { w _ from.FetchWire[path.wireName]; RETURN}; }; PortGet: PROC [dr: DesignReading, from: CellType, path: Path, mayAdd, clip: BOOL] RETURNS [port: Port] = { d: Design ~ dr.d; IF clip THEN { IF path.cells#NIL THEN ERROR; port _ from.FetchPort[path.wireName]; IF port=NIL AND mayAdd THEN {port _ CreatePort[from, path.wireName.OneSteppy, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, nilBiRel]; port _ port}; } ELSE IF path.cells=NIL THEN { w: Wire ~ from.FetchWire[path.wireName]; port _ PortForWire[from, w, mayAdd]} ELSE WITH path.cells.first SELECT FROM x: REF Range2 => { ras: REF ArraySpec.array = NARROW[dr.arraySpecs.ApplyA[from].MDA]; a: Array = from.asArray; eltPort: Port = PortGet[dr, from.EltType[], path.PTail, mayAdd, clip]; IF eltPort=NIL THEN port _ NIL ELSE { index: Int2 = LIB.Sub[Range2Min[x^], Range2Min[ras.range]]; IF NOT Range2IsSingleton[x^] THEN ERROR; port _ GetArrayPortForPort[from, index, eltPort, mayAdd, TRUE, TRUE]; }; }; x: ROPE => { ci: CellInstance ~ from.FetchSubcell[OSn[x]]; subclip: BOOL ~ dr.clipINT.HasAA[x, from]; childPort: Port ~ PortGet[dr, d.CiT[ci], path.PTail, mayAdd, subclip]; IF childPort = NIL THEN port _ NIL ELSE { w: Wire ~ ConndWire[ci, childPort]; IF w=NIL THEN ERROR; port _ PortForWire[from, w, mayAdd]; }; }; ENDCASE => ERROR; port _ port}; ReadCap: PROC [s: Source, reader: Reader, cr: CellReading] = { ct: CellType = cr.ct; from: IO.STREAM = s.stream; EndLine[from, cr.dr.buffer]; }; SkipNTokens: PROC [from: IO.STREAM, n: INT, buffer: REFTEXT] RETURNS [ok: BOOL] = { WHILE n > 0 DO token: REFTEXT = from.GetToken[TokenBreak, buffer].token; IF RefText.Equal[token, "\n"] THEN RETURN [FALSE]; n _ n - 1; ENDLOOP; ok _ TRUE; }; Warn: PROC [s: Source, msg: ROPE, v1, v2, v3, v4, v5: IO.Value _ [null[]]] = { IF s.name # NIL THEN msg _ IO.PutFR["At %g[%g]: %g", [rope[s.name]], [integer[s.stream.GetIndex[]]], [rope[msg]]]; SIGNAL Warning[IO.PutFR[msg, v1, v2, v3, v4, v5]]; RETURN}; Start: PROC = { Register["tech", ReadTech]; Register["timestamp", ReadTimestamp]; Register["version", ReadVersion]; Register["scale", ReadScale]; Register["resistclasses", ReadResistClasses]; Register["node", ReadNode]; Register["equiv", ReadEquiv]; Register["fet", ReadFet]; Register["use", ReadUse]; Register["merge", ReadMerge]; Register["cap", ReadCap]; RETURN}; Start[]; END. θLichenFromExtImpl2.Mesa Last tweaked by Mike Spreitzer on April 12, 1989 3:44:49 pm PDT IF aas.sep[X]<0 AND aas.range[X].RangeLength>1 OR aas.sep[Y]<0 AND aas.range[Y].RangeLength>1 THEN ERROR; Register["adjust", ReadAdjust]; Κ– "cedar" style˜code™Kšœ?™?—K˜KšΟk œ&œf˜—K˜šΡbnxœœ˜!Kšœœ˜ Kšœœe˜ŠKšœ˜Kšœ˜—K˜Kš œœœœ<Οnœ˜kK˜šŸœœ.œ˜XKšœœ˜Kšœ˜Kšœœœœ˜"Kšœ˜Kšœ˜—K˜šŸœœ œœ˜2Kšœœœ ˜K˜šœ˜K˜#Kšœ/˜6—K˜—K˜š Ÿœœœœ œ˜4Kšœœœ˜3K˜—K˜šŸœœ1˜?K˜Kšœœœ ˜Kšœ œ˜K˜Kšœ˜—K˜šŸ œœ1˜DK˜Kšœœœ ˜Kšœ œ˜Kšœœ*˜=K˜Kšœ˜šœœ˜,Kšœ ˜ K˜K˜K˜K˜ K˜ KšœΟcœ˜K˜ ——K˜šŸ œœ1˜BK˜Kšœœœ ˜Kšœ œ˜Kšœ œ˜)K˜Kšœ˜—K˜šŸ œœ1˜@K˜Kšœœœ ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ)˜BKšœœ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜—K˜šŸœœ1˜HK˜Kšœœœ ˜Kšœœ˜ Kšœ!œ1˜Xš˜Kšœœ'˜2Kšœœœ˜K˜ Kšœ˜—Kšœ˜Kšœ˜—K˜Kšœ œœ˜K˜šŸœœ1˜?K˜Kšœœœ ˜Kšœ,˜,KšŸœœ˜KšŸœœ˜Kšœœ˜Kšœœ˜Kšœœ7˜?Kšœœ˜Kšœ#˜#Kš œœœœ˜*Kš œœœ*œœœ˜MKšœ˜K˜Kšœ˜—K˜šŸ œœœœœœœ˜[Kšœœœ ˜Kšœœœ˜šœ œ˜K˜šœœ˜Kšœœœ˜"Kšœ˜—K˜—šœ˜Kšœœœ˜Kšœ$œœ˜BKšœœœ˜7Kšœœœœ˜)K˜Kšœœœ0œ˜dKšœœœœ˜?Kšœ$œœ˜BKšœœœœ˜(Kšœ˜—š˜šœ ˜ š œœ œœ˜0Kšœ˜Kšœ˜—Kšœ˜——K˜—K˜š Ÿ œœœœœ ˜9Kšœœœœ ˜>—K˜šŸ œœ1˜@K˜Kšœœœ ˜Kšœ)˜)Kšœ)˜)Kšœ ˜ Kšœ ˜ Kš œœœœœœ˜;šœœ˜Kš œ œœœœ˜Kšœœ"œ˜/Kšœœ"œ˜/Kšœœ˜—K˜Kšœ˜—K˜šŸœœ1˜>K˜Kšœœœ ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ"˜&Kšœ"˜$Kšœ"˜$K˜Kšœ˜K˜ šŸœœ œ˜2Kšœ.œ˜4Kšœ#œ˜)Kšœ(˜(Kšœ˜Kšœ˜—KšœKœœ ˜`Kšœœœœ'˜nKšœœ˜Kšœœ˜Kšœœ˜K˜Kšœ˜—K˜šŸœœ œ˜>Kšœœœ ˜Kšœ˜K˜Kšœœœ˜"Kšœ˜ —K˜š Ÿ œœ œ5œœ!˜–Kšœ˜Kšœ$˜$Kšœœ<˜MK˜ Kšœœœ˜)Kšœ˜šœœœ˜Kšœœœœœœœœœœ˜²K˜ Kšœ7˜7Kšœ˜šœœ˜*K˜K˜ K˜—Kšœ*œœœœœœœ˜UKšœ)œœœœœœœ˜TKšœ)œœœœœœœ˜TK˜K˜—K˜ Kšœ˜—K˜šŸœœ1˜>K˜Kšœœœ ˜Kšœ œ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜K˜2Kšœ˜K˜KšœF˜FKš œ)œœœœ%˜sK˜—K˜šŸ œœœ ˜=šœœ˜Kšœ œ˜šœ ˜ šœ'˜'Kšœ˜Kšœ˜K˜—Kš œœœœœœ™iKšœ&˜,—Kšœœ˜——K˜šŸ œœ œœ ˜4Kš œœœœœ˜K˜2šœ œ˜K˜ Kšœ˜"Kšœ˜—šœ˜Kšœ$œ˜?šŸœœ˜Kšœœœ˜ K˜Kšœœœ˜ K˜'Kšœœœ˜ Kšœ˜Kšœœœ˜ K˜—Kšœ˜Kšœ˜Kšœœ œœ˜K˜ Kšœ˜K˜—K˜—K˜š Ÿ œœœœœ  œ˜Ošœœ˜Kšœ˜Kšœ ˜—K˜—K˜šŸ œœ(œ3œ˜‰Kšœ˜K˜Kšœœ*˜4šœœœœ˜(Kšœ ˜ KšœœAœœ˜“Kšœœ˜—KšœœœœB˜gšœœ˜šœ˜Kšœœ(œ˜8Kšœœœ˜šœœœ˜Kšœ0˜0Kšœ œ ˜—Kšœ$˜(K˜—šœ˜Kšœ#œœ˜GKšœ!˜!KšœCœ:œœ*˜·Kšœœ˜9Kšœœœœ˜(K˜—Kšœœ˜—K˜—K˜šŸœœœœ˜4Kšœ˜—K˜šŸœœœœ˜1šœœœ˜K˜šœ œ œ˜0Kšœ˜Kšœ˜Kšœ ˜Kšœ˜Kšœ˜Kšœ˜—Kšœœ˜—K˜—K˜šŸœœœœ˜2Kšœœœœ˜CKšœ˜—K˜šŸ œœ1˜@K˜Kšœœœ ˜Kšœœœ˜@Kšœœ˜Kšœœ˜Kšœ-œ˜3Kšœ-œ˜3šœ8œ˜@Kšœ˜K˜K˜—K˜Kšœ$˜$K˜Kšœ˜ —K˜šŸœœ$˜2šœœ œœ˜>šœœœ˜&šœœœœ˜1Kšœœ œ˜Kšœœ˜—Kšœ˜—Kšœœ˜ —Kšœ$˜$Kš œœ  œœœ˜;Kšœœœœ*˜WKšœœœœ˜*Kšœ˜—K˜šŸ œœœ>œœœ œ˜”K˜K˜K˜%K˜Kšœ˜Kšœœ œ˜,Kšœœ œ˜,Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšΠgnœ œ˜Kšœ-œ˜4Kšœ-œ˜4Kšœœœ˜$Kšœœœœœœœœœœœ˜Ašœœ˜ KšœœΟgœœœ’œœœ˜)Kšœ!’œ ˜,Kšœœ˜—šœ˜Kšœœœ˜Kšœ9˜9Kšœ˜—Kšœ˜—K˜šŸ œœœ:˜QK˜Kšœœ˜"Kšœœ˜"Kšœœœ ˜9Kšœ˜—K˜š Ÿ œœœ8œœœ ˜qKš œœœœœ ˜šŸœœœ˜%K˜)šœ˜˜Kšœœœ˜ K˜K˜—Kšœ œ˜Kšœœ˜—K˜—Kšœ œœœ˜:šŸœœ œœ˜:Kšœœ(˜2šœœ˜Kšœœ˜1šœ˜KšœŸœ˜(Kšœœ(˜1Kšœœ˜šœœ˜Kšœ˜Kšœ,˜,—Kšœœœœ˜!Kšœ!œ˜(šœœœ˜%Kšœœœœ˜Kšœ œœœ˜LKšœ˜—Kšœ œœ˜Kšœ œ˜/Kšœœ œœ˜OKšœ ˜—Kšœœ˜Kšœœ˜Kšœœ˜šœœ œœœœœ˜YKšœ œœ˜ Kšœ+œ˜K——K˜—K˜š˜Kšœœ(˜2Kšœœœœ˜BKšœœ˜šœœ˜Kšœœ˜šœ˜Kšœœ0˜8Kšœœ0˜8K˜K˜Kšœœœ˜Kš œœœœœ˜Kšœœœ˜6Kšœœ(˜2šœœ˜Kšœœ˜šœ˜Kšœœ˜ Kšœ˜Kšœœ(˜1Kšœœœœ˜"—Kšœœ˜—Kšœ œœœ˜!Kšœœœœ˜$Kš œœ ’œ œœ˜GKšœœ˜(Kšœ˜—Kšœœ˜Kšœœ˜Kšœœ˜˜Kšœœœœ ˜JKšœœœœ˜+K˜ Kšœ˜!—šœ˜ Kšœ œ˜Kšœœ$˜.Kšœ˜šœœ˜Kšœ!œ˜'Kšœ!˜'—Kšœ4˜8——Kšœœœœ˜Kšœ œ˜—Kšœ˜—K˜š Ÿ œœœœœ  œ˜Pšœœ˜Kšœ˜Kšœ ˜—K˜—K˜š Ÿœœœ9œœ˜hK˜šœ œœ˜Kšœœœ˜&Kšœœ ˜*Kšœ0˜0KšœC˜Cšœ œœ˜Kšœ˜Kšœœœœ˜Kšœ˜—Kšœ˜—šœ˜Kšœ"˜"Kšœ˜—Kšœ˜—K˜šŸœœ?œœ˜jK˜šœœ˜Kšœ œœœ˜Kšœ%˜%Kšœœœœ3œœœœœœœ˜‘K˜—šœœ œœ˜Kšœ(˜(Kšœ$˜$—šœœœ˜&šœœ ˜Kšœœœœ˜BK˜KšœF˜Fš œ œœœœ˜%Kšœœ*˜;Kšœœœœ˜(Kšœ9œœ˜EK˜—K˜—šœœ˜ Kšœ-˜-Kšœ œ˜*KšœF˜Fš œ œœœœ˜)Kšœ#˜#Kšœœœœ˜Kšœ$˜$K˜—K˜—Kšœœ˜—Kšœ ˜ —K˜šŸœœ1˜>K˜Kšœœœ ˜K˜K˜—K˜šŸ œœœœœ œœœ˜Sšœ˜Kšœœ+˜9Kšœœœœ˜2K˜ Kšœ˜—Kšœœ˜ K˜—K˜šŸœœœœ˜NKšœ œœœU˜rKšœ œ!˜2Kšœ˜—K˜šŸœœ˜K˜Kšœ%˜%Kšœ!˜!K˜Kšœ-˜-K˜K˜Kšœ˜K˜K˜K™Kšœ˜Kšœ˜—K˜K˜K˜Kšœ˜—…—I@c9