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 ROPE ← NEW[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:
BOOL ←
FALSE] = {
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.STREAM ← FS.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.STREAM ← FS.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.