<> <> <> <<>> 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. <<>> <<>>