CDPinListImpl.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, September 18, 1985 3:16:53 pm PDT
DIRECTORY
Basics USING [CompareINT, Comparison],
CD USING [Design, Instance, Object, Position],
CDCells USING [IsCell],
CDCommandOps USING [TheInstance],
CDIO,
CDMenus USING [CreateEntry],
CDOps USING [Info, SelectedInstance],
CDPinList USING [PinData, PinDataRec, PinList, PinLists, Side],
CDPinObjects USING [GetName],
CDSequencer USING [Command, ImplementCommand],
CDSimpleOps USING [Select],
Commander,
CommandTool,
FS USING [StreamOpen],
IO USING [BreakProc, Close, EndOfStream, GetInt, GetTokenRope, NUL, int, PutF, PutRope, rope, SP, STREAM],
NodeProps USING [PutProp],
PutGet USING [FromFile, ToFile],
PWPins USING [EnumerateEdgePins, GetSide, InstanceEnumerator],
RedBlackTree USING [Create, EnumerateIncreasing, Insert, Key, Table, UserData],
Rope USING [Cat, Equal, ROPE],
TerminalIO USING [RequestRope, WriteRope],
TextNode USING [Ref];
CDPinListImpl: CEDAR PROGRAM
IMPORTS Basics, CDCells, CDCommandOps, CDIO, CDMenus, CDOps, CDPinObjects, CDSequencer, CDSimpleOps, Commander, CommandTool, IO, FS, NodeProps, PWPins, PutGet, RedBlackTree, Rope, TerminalIO
EXPORTS CDPinList =
BEGIN OPEN CDPinList;
Key: TYPE = REF INT;
ROPE: TYPE = Rope.ROPE;
ListCellPinsProc: PROC [comm: CDSequencer.Command] = {
inst: CD.Instance ← CDCommandOps.TheInstance[comm: comm, text: "List cell pins "];
IF inst#NIL THEN {
TerminalIO.WriteRope[CDOps.Info[inst.ob]];
IF ~CDCells.IsCell[inst.ob]
THEN TerminalIO.WriteRope[" is not a cell\n"]
ELSE {
lists: PinLists ← ALL[NIL];
pinListFile: REF ROPENEW[ROPE ← comm.design.name.Cat[".pins"]];
IF comm.data#NIL
THEN pinListFile ← NARROW[comm.data]
ELSE {
TerminalIO.WriteRope["\n"];
pinListFile ← NEW[ROPE ← TerminalIO.RequestRope["File name for pin list: "]]};
lists ← ListPinsFromObject[inst.ob];
WritePinListsToFile[pinListFile^, lists] } } };
ListCellPinsCT: Commander.CommandProc = {
pinLists: PinLists;
file: ROPE ← CommandTool.NextArgument[cmd];
IF file=NIL THEN RETURN;
pinLists ← ListPinsFromDesignFile[file];
WritePinListsToFile[file.Cat[file, ".pins"], pinLists]};
ListPinsFromDesignFile: PUBLIC PROC[designFile: Rope.ROPE] RETURNS [lists: PinLists] = {
design: CD.Design ← CDIO.ReadDesign[designFile];
lists ← ListPinsFromDesign[design]};
ListPinsFromDesign: PUBLIC PROC[design: CD.Design] RETURNS [lists: PinLists] = {
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["\nList pins from design . . . no cell at [0, 0]\n"];
IF inst#NIL THEN {
TerminalIO.WriteRope["\nList pins from cell: "];
TerminalIO.WriteRope[CDOps.Info[inst.ob]];
IF ~CDCells.IsCell[inst.ob]
THEN TerminalIO.WriteRope[" is not a cell\n"]
ELSE lists ← ListPinsFromObject[inst.ob]}};
ListPinsFromObject: PUBLIC PROC[cell: CD.Object] RETURNS [lists: PinLists] = {
AddPinEntry:  PWPins.InstanceEnumerator = {
data:    PinData ← NEW[PinDataRec ← [
name:  CDPinObjects.GetName[inst],
side:  PWPins.GetSide[cell, inst].side,
size:  inst.ob.size,
pos:  inst.location ] ];
key: Key ← NEW[INT ← SidePosition[data.side, inst.location]];
RedBlackTree.Insert[tables[data.side], data, key]};
ListTable: PROC [userdata: RedBlackTree.UserData] RETURNS [stop: BOOLFALSE] = {
data:  PinData ← NARROW[userdata];
lists[data.side] ← CONS[data, lists[data.side]]};
tables: ARRAY Side OF RedBlackTree.Table;
FOR currentSide: Side IN Side DO
tables[currentSide] ← RedBlackTree.Create[getKey: GetKey, compare: Compare] ENDLOOP;
[] ← PWPins.EnumerateEdgePins[cell, AddPinEntry];
FOR currentSide: Side IN Side DO
RedBlackTree.EnumerateIncreasing[tables[currentSide], ListTable] ENDLOOP };
ReadPinListsFromFile: PUBLIC PROC [pinListFile: ROPE] RETURNS [lists: PinLists] = {
tbp: IO.BreakProc = {RETURN[SELECT char FROM
IN [IO.NUL .. IO.SP], ',, ':, ';      => sepr,
'[, '], '(, '), '{, '}, '", '+, '-, '*, '/, '@, '← => break,
ENDCASE          => other]};
in: IO.STREAMFS.StreamOpen[pinListFile];
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];
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: PinData ← NEW[PinDataRec ← [
name: name,
side: side,
pos: [posX, posY],
size: [sizeX, sizeY] ] ];
lists[side] ← CONS[data, lists[side] ] ENDLOOP;
in.Close[];
FOR side: Side IN Side DO
temp: PinList ← NIL;
FOR list: PinList ← lists[side], list.rest WHILE list # NIL
DO temp ← CONS[list.first, temp] ENDLOOP;
lists[side] ← temp ENDLOOP };
WritePinListsToFile: PUBLIC PROC[pinListFile: ROPE, lists: PinLists] = {
sideRope: ROPE;
node: TextNode.Ref;
out: IO.STREAMFS.StreamOpen[pinListFile, $create];
TerminalIO.WriteRope["\nWriting pin file: "];
TerminalIO.WriteRope[pinListFile];
TerminalIO.WriteRope[" . . . "];
FOR side: Side IN Side DO
sideRope ← SELECT side FROM
left  => "LEFT ",
right  => "RIGHT ",
top  => "TOP ",
bottom => "BOTTOM",
ENDCASE => ERROR;
FOR list: PinList ← lists[side], list.rest WHILE list#NIL DO
out.PutF["\n%g %6g",
IO.rope[list.first.name],
IO.rope[sideRope]];
out.PutF["%6g%6g%6g%6g",
IO.int[list.first.pos.x],
IO.int[list.first.pos.y],
IO.int[list.first.size.x],
IO.int[list.first.size.y]]
ENDLOOP
ENDLOOP;
out.PutRope["\n"];
out.Close[];
node ← PutGet.FromFile[pinListFile];
NodeProps.PutProp[node,$Postfix,"35 sp tabStops"];
[ ] ← PutGet.ToFile[pinListFile, node];
TerminalIO.WriteRope[" done\n"]};
SidePosition: PUBLIC PROC [side: Side, pos: CD.Position] RETURNS [INT] =
{RETURN[SELECT side FROM left, right => pos.y, ENDCASE => pos.x]};
GetKey:  PROC [userdata: RedBlackTree.UserData] RETURNS [RedBlackTree.Key] = {
data:  PinData ← NARROW[userdata];
RETURN[NEW[INT ← SidePosition[data.side, data.pos]]]};
Compare: PROC [k: RedBlackTree.Key, data: RedBlackTree.UserData]
RETURNS [Basics.Comparison] = {
dat:  PinData ← NARROW[data];
key: Key ← NARROW[k];
RETURN[Basics.CompareINT[SidePosition[dat.side, dat.pos], key^]]};
Commander.Register[proc: ListCellPinsCT, key: "CDPinList"];
CDSequencer.ImplementCommand[a: $PinList, p: ListCellPinsProc];
CDMenus.CreateEntry[$CellMenu, "List cell pins", $PinList];
TerminalIO.WriteRope["PinList program loaded\n"];
END.