<> <> <> <> <<>> <<>> DIRECTORY CD, CDEvents, CDIO, CDViewer, CommandTool, Convert, CoreGeometry, CoreOps, GList, IO, Rope, Sinix, Sisyph, SCUtils, TerminalIO, TilingClass; SCUtilsImpl: CEDAR PROGRAM IMPORTS CDEvents, CDViewer, CommandTool, CDIO, Convert, CoreGeometry, CoreOps, GList, IO, Rope, Sinix, Sisyph, TerminalIO, TilingClass EXPORTS SCUtils ~ BEGIN OPEN SCUtils; myDesign: PUBLIC CD.Design _ NIL; workingDirectory: ROPE _ CommandTool.CurrentWorkingDirectory[]; <> Log2: PUBLIC PROC [n: INT] RETURNS [log: INT _ 0] ~ { WHILE n > 1 DO n _ n/2; log _ log+1 ENDLOOP }; ComRecord: PUBLIC PROC [pattern: ROPE, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ { n: Names _ NIL; FOR i: INT DECREASING IN [0..Rope.Length[pattern]) DO SELECT Rope.Fetch[pattern, i] FROM '0 => n _ CONS["ComCell0.icon", n]; '1 => n _ CONS["ComCell1.icon", n]; 'X => n _ CONS["ComCellX.icon", n]; 'N => n _ CONS["ComCellN.icon", n]; 'E => n _ CONS["ComCellE.icon", n]; ENDCASE => ERROR; ENDLOOP; ct _ RecordX[n, cx, Rope.Cat[ctName, pattern]]; }; <> RecordX: PUBLIC PROC [obNames: Names, cx: Sisyph.Context, ctName: ROPE] RETURNS [ct: CellType] ~ { count: NAT _ GList.Length[obNames]; Index: TYPE = {ComCell0, ComCell1, ComCellX, ComCellN, ComCellE}; baseCTs: CellTypes _ NIL; public: Wire; -- public of cellType to be returned tileRow: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[count]]; tileArray: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[1]]; publicElements, arrayedWires, leftSideOnlyWires, rightSideOnlyWires, globalWires: Wires _ NIL; EachWire: CoreOps.EachWireProc = { sides: CoreGeometry.Sides = WireSide[wire, baseCTs.first]; vertical: BOOL = sides[top] OR sides[bottom]; IF vertical AND (sides[right] OR sides[left]) THEN WireSideProblem[wire, "touches adjacent sides", baseCTs.first]; IF vertical THEN { newPublic: Wire _ CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]]; arrayedWires _ CONS[wire, arrayedWires]; FOR i: INT IN [0..count) DO newPublic[i] _ CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL]; ENDLOOP; publicElements _ CONS[newPublic, publicElements]; } ELSE { IF sides=CoreGeometry.noSide THEN { IF IsGlobal[wire, cx] THEN { globalWires _ CONS [wire, globalWires]; publicElements _ CONS [wire, publicElements] } } ELSE { IF sides[left] THEN leftSideOnlyWires _ CONS[wire, leftSideOnlyWires]; IF sides[right] THEN rightSideOnlyWires _ CONS[wire, rightSideOnlyWires]; publicElements _ CONS [wire, publicElements] } } }; <> FOR l: Names _ obNames, l.rest WHILE l#NIL DO baseCTs _ CONS[Sisyph.ExtractSchematicByName[l.first, cx], baseCTs]; ENDLOOP; baseCTs _ NARROW[GList.Reverse[baseCTs]]; <> [] _ CoreOps.VisitWireSeq[baseCTs.first.public, EachWire]; public _ CoreOps.CreateWire[publicElements]; <> FOR i: INT IN [0..count) DO tileRow[i] _ NEW [TilingClass.TileRec _ [type: baseCTs.first]]; baseCTs _ baseCTs.rest; ENDLOOP; <> FOR wl: Wires _ leftSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[0].renaming _ CONS[[wireName, wireName], tileRow[0].renaming]; ENDLOOP; <> FOR wl: Wires _ rightSideOnlyWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; tileRow[count-1].renaming _ CONS[[wireName, wireName], tileRow[count-1].renaming]; ENDLOOP; <> FOR wl: Wires _ globalWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, wireName], tileRow[i].renaming]; ENDLOOP; ENDLOOP; <> FOR wl: Wires _ arrayedWires, wl.rest WHILE wl#NIL DO wireName: ROPE _ CoreOps.GetShortWireName[wl.first]; FOR i: NAT IN [0..count) DO tileRow[i].renaming _ CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileRow[i].renaming]; ENDLOOP; ENDLOOP; tileArray[0] _ tileRow; <> ct _ TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[ctName, ".RecordX"]]; }; LayoutDesign: PUBLIC PROC [] RETURNS [design: CD.Design] = { name: ROPE _ "CacheCells"; design _ CDViewer.FindDesign[name]; IF design=NIL THEN design _ CDIO.ReadDesign[name, NIL, workingDirectory]; IF design = NIL THEN ERROR; }; <> IsGlobal: PROC [w: Wire, cx: Sisyph.Context] RETURNS [BOOL _ FALSE] = { name: ROPE _ CoreOps.GetShortWireName[w]; FOR lr: LIST OF ROPE _ Sisyph.GetGlobalNames[cx], lr.rest WHILE lr#NIL DO IF Rope.Equal[name, lr.first] THEN RETURN [TRUE] ENDLOOP; }; WireSide: PROC [wire: Wire, baseCT: CellType] RETURNS [sides: CoreGeometry.Sides _ CoreGeometry.noSide] ~ { <> EachPin: CoreGeometry.EachPinProc = { sides[side] _ TRUE; }; [] _ CoreGeometry.EnumerateSides[Sisyph.mode.decoration, baseCT, wire, EachPin]; }; WireSideProblem: PROC [wire: Wire, msg: ROPE, baseCT: CellType] ~ { TerminalIO.PutF["\n*** Wire %g %g in cell %g\n", IO.rope[CoreOps.GetFullWireName[baseCT.public, wire]], IO.rope[msg], IO.rope[CoreOps.GetCellTypeName[baseCT]]]; SIGNAL Sinix.CallerBug[]; }; AfterInput: CDEvents.EventProc = { IF myDesign=NIL THEN myDesign _ design; }; CDEvents.RegisterEventProc[$AfterInput, AfterInput]; END.