DIRECTORY Basics USING [CompareINT, Comparison], CD, CDBasics, CDCells USING [IsCell], CDCommandOps USING [TheInstance], CDDirectory, CDFrame, CDIO, CDMenus USING [CreateEntry], CDOps USING [Info, SelectedInstance], CDPinObjects USING [GetLayer, GetName], CDSequencer USING [Command, ImplementCommand], CDSimpleOps USING [Select], Commander, CommandTool, FS, IO, NodeProps USING [PutProp], PutGet USING [FromFile, ToFile], PWPins, RedBlackTree, Rope USING [Cat, Equal, ROPE], TerminalIO USING [RequestRope, WriteRope], TextNode USING [Ref]; CDFrameShell: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDIO, CDMenus, CDOps, CDPinObjects, CDSequencer, CDSimpleOps, Commander, CommandTool, IO, FS, NodeProps, PWPins, PutGet, RedBlackTree, Rope, TerminalIO EXPORTS CDFrame = BEGIN OPEN CDFrame; Key: TYPE = REF INT; ROPE: TYPE = Rope.ROPE; WriteFrameShellFile: PROC [comm: CDSequencer.Command] = { inst: CD.Instance _ CDCommandOps.TheInstance[comm: comm, text: "Shell to File "]; IF inst#NIL THEN { TerminalIO.WriteRope[CDOps.Info[inst.ob]]; IF ~CDCells.IsCell[inst.ob] THEN TerminalIO.WriteRope[" is not a cell\n"] ELSE { shell: REF ShellRec; shellFile: REF ROPE _ NEW[ROPE _ comm.design.name.Cat[".shell"]]; IF comm.data#NIL THEN shellFile _ NARROW[comm.data] ELSE { TerminalIO.WriteRope["\n"]; shellFile _ NEW[ROPE _ TerminalIO.RequestRope["File name for shell: "]]}; shell _ ShellFromObject[inst.ob]; ShellToFile[shell] } } }; WriteFrameShellFileCT: Commander.CommandProc = { shell: REF ShellRec; file: ROPE _ CommandTool.NextArgument[cmd]; IF file=NIL THEN RETURN; shell _ ShellFromDesign[file]; ShellToFile[shell]}; ShellFromDesign: PUBLIC PROC[design: REF] RETURNS [shell: REF ShellRec] = { IF design#NIL AND ISTYPE[design, Rope.ROPE] THEN design _ CDIO.ReadDesign[NARROW[design]]; shell _ ShellFromObject[ObjectFromDesign[NARROW[design]]]}; ObjectFromDesign: PROC[design: CD.Design] RETURNS [cell: CD.Object] = { multiple: BOOL; inst: CD.Instance; CDSimpleOps.Select[design, [0,0]]; [inst, multiple] _ CDOps.SelectedInstance[design]; IF multiple THEN ERROR; IF inst=NIL THEN TerminalIO.WriteRope["\nShell from design . . . no cell at [0, 0]\n"]; IF inst#NIL THEN { TerminalIO.WriteRope["\nShell from cell: "]; TerminalIO.WriteRope[CDOps.Info[inst.ob]]; IF ~CDCells.IsCell[inst.ob] THEN TerminalIO.WriteRope[" is not a cell\n"] ELSE RETURN[inst.ob] } }; ShellFromObject: PUBLIC PROC[cell: CD.Object] RETURNS [shell: REF ShellRec] = { AddPinEntry: PWPins.InstanceEnumerator = { data: REF PinRec _ NEW[PinRec _ [ name: CDPinObjects.GetName[inst], side: PWPins.GetSide[cell, inst].side, size: inst.ob.size, pos: inst.location, layer: CDPinObjects.GetLayer[inst] ] ]; olddata: RedBlackTree.Node _ RedBlackTree.LookupNode[tables[data.side], GetKey[data]]; IF olddata#NIL THEN { TerminalIO.WriteRope["\n Duplicate Pins:"]; TerminalIO.WriteRope[ PinRope[NARROW[olddata.data]]]; TerminalIO.WriteRope[ PinRope[data]]; RETURN}; RedBlackTree.Insert[tables[data.side], data, GetKey[data]]; cnt[data.side] _ cnt[data.side]+1}; SeqTable: PROC [userdata: RedBlackTree.UserData] RETURNS [stop: BOOL _ FALSE] = { data: REF PinRec _ NARROW[userdata]; shell.pins[data.side][index] _ data; index _ index+1}; tables: ARRAY Side OF RedBlackTree.Table; cnt: ARRAY Side OF INT _ ALL[0]; index: INT; FOR currentSide: Side IN Side DO tables[currentSide] _ RedBlackTree.Create[getKey: GetKey, compare: Compare] ENDLOOP; [] _ PWPins.EnumerateEdgePins[cell, AddPinEntry]; shell _ NEW[ShellRec _ [ ]]; shell.name _ CDDirectory.Name[cell]; shell.size _ CDBasics.SizeOfRect[CD.InterestRect[cell]]; FOR currentSide: Side IN Side DO shell.pins[currentSide] _ NEW[PinSeq[cnt[currentSide]]]; index _ 0; RedBlackTree.EnumerateIncreasing[tables[currentSide], SeqTable] ENDLOOP }; ShellFromFile: PUBLIC PROC [shellName: ROPE] RETURNS [shell: REF ShellRec] = { tbp: IO.BreakProc = {RETURN[SELECT char FROM IN [IO.NUL .. IO.SP], ',, ':, '; => sepr, '[, '], '(, '), '{, '}, '", '+, '-, '*, '/, '@, '_ => break, ENDCASE => other]}; shellFile: ROPE _ shellName.Cat[".shell"]; in: IO.STREAM; cnt: ARRAY Side OF INT _ ALL[0]; pins: ARRAY Side OF LIST OF REF PinRec _ ALL[NIL]; shell _ NEW[ShellRec _ [name: shellName]]; in _ FS.StreamOpen[shellFile ! FS.Error => {in_NIL; CONTINUE}]; IF in=NIL THEN RETURN[shell]; shell.name _ IO.GetTokenRope[in].token; [ ] _ IO.GetTime[in]; shell.size.x _ IO.GetInt[in]; shell.size.y _ IO.GetInt[in]; DO name: ROPE _ IO.GetTokenRope[in, tbp ! IO.EndOfStream => EXIT].token; sideR: ROPE _ IO.GetTokenRope[in].token; posX: INT _ IO.GetInt[in]; posY: INT _ IO.GetInt[in]; sizeX: INT _ IO.GetInt[in]; sizeY: INT _ IO.GetInt[in]; layer: CD.Layer _ IO.GetInt[in]; side: Side _ SELECT TRUE FROM Rope.Equal[sideR, "LEFT"] => left, Rope.Equal[sideR, "RIGHT"] => right, Rope.Equal[sideR, "TOP"] => top, Rope.Equal[sideR, "BOTTOM"] => bottom, ENDCASE => ERROR; data: REF PinRec _ NEW[PinRec _ [ name: name, side: side, pos: [posX, posY], size: [sizeX, sizeY], layer: LOOPHOLE[layer] ] ]; cnt[side] _ cnt[side] + 1; pins[side] _ CONS[data, pins[side] ] ENDLOOP; in.Close[]; FOR side: Side IN Side DO shell.pins[side] _ NEW[PinSeq[cnt[side]]]; FOR pin: INT DECREASING IN [0..shell.pins[side].seqSize) DO shell.pins[side][pin] _ pins[side].first; pins[side] _ pins[side].rest ENDLOOP ENDLOOP }; PinRope: PROC[pin: REF PinRec] RETURNS[rope: ROPE] = { out: IO.STREAM _ IO.ROS[]; sideRope: ROPE _ SELECT pin.side FROM left => "LEFT ", right => "RIGHT ", top => "TOP ", bottom => "BOTTOM", ENDCASE => ERROR; out.PutF["\n%g %6g", IO.rope[pin.name], IO.rope[sideRope]]; out.PutF["%6g%6g%6g%6g%6g", IO.int[pin.pos.x], IO.int[pin.pos.y], IO.int[pin.size.x], IO.int[pin.size.y], IO.int[pin.layer]]; RETURN[ IO.RopeFromROS[out] ]}; ShellToFile: PUBLIC PROC[shell: REF ShellRec] = { shellFile: ROPE _ shell.name.Cat[".shell"]; tabStop45LookF: ROPE = "45 sp tabStops look.f"; node: TextNode.Ref; out: IO.STREAM _ FS.StreamOpen[shellFile, $create]; TerminalIO.WriteRope["\nWriting pin file: "]; TerminalIO.WriteRope[shellFile]; TerminalIO.WriteRope[" . . . "]; out.PutF["%g %18g%6g%6g\n", IO.rope[shell.name], IO.time[], IO.int[shell.size.x], IO.int[shell.size.y]]; FOR side: Side IN Side DO FOR i: INT IN [0..shell.pins[side].seqSize) DO out.PutRope[ PinRope[shell.pins[side][i]]] ENDLOOP ENDLOOP; out.PutRope["\n"]; out.Close[]; node _ PutGet.FromFile[shellFile]; NodeProps.PutProp[node.child, $Postfix, tabStop45LookF]; [ ] _ PutGet.ToFile[shellFile, node]; TerminalIO.WriteRope[" done\n"]}; GetSidePos: PUBLIC PROC [pin: REF PinRec] RETURNS [INT] = {RETURN[SELECT pin.side FROM left, right => pin.pos.y, ENDCASE => pin.pos.x]}; SetSidePos: PUBLIC PROC [pin: REF PinRec, pos: INT] = {SELECT pin.side FROM left, right => pin.pos.y_pos ENDCASE => pin.pos.x_pos}; NewFrame: PUBLIC PROC [size: INT, xory: XorY, name: Rope.ROPE, data: REF_NIL, unord: BOOL_FALSE] RETURNS [new: REF FrameSeq] = { new _ NEW[FrameSeq[size]]; new.xory _ xory; new.data _ data; new.unordered _ unord; new.shell _ NEW[ShellRec _ [name: name]] }; REFToINT: PROC [ref: REF] RETURNS [INT] = {pin: REF PinRec _ NARROW[ref]; RETURN[GetSidePos[pin]*CD.layerNum + pin.layer]}; GetKey: PROC [userdata: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] = {RETURN[userdata]}; Compare: PROC [k: RedBlackTree.Key, data: RedBlackTree.UserData] RETURNS [Basics.Comparison] = {RETURN[Basics.CompareINT[REFToINT[k], REFToINT[data]]]}; Commander.Register[proc: WriteFrameShellFileCT, key: "CDFrameShell"]; CDSequencer.ImplementCommand[a: $FrameShell, p: WriteFrameShellFile]; CDMenus.CreateEntry[$CellMenu, "Write frame shell file", $FrameShell]; TerminalIO.WriteRope["FrameShell program loaded\n"]; END. CDFrameShell.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by Curry, November 4, 1985 1:55:50 pm PST Κ ±˜šΠblœ™Jšœ<™)