CDFrameShell.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, November 4, 1985 1:55:50 pm PST
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 ROPENEW[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"]
ELSERETURN[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: BOOLFALSE] = {
data:  REF PinRec ← NARROW[userdata];
shell.pins[data.side][index] ← data;
index ← index+1};
tables: ARRAY Side OF RedBlackTree.Table;
cnt: ARRAY Side OF INTALL[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 INTALL[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.STREAMIO.ROS[];
sideRope: ROPESELECT 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.STREAMFS.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: REFNIL, unord: BOOLFALSE]
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.