DIRECTORY Basics, CD, CDSymbolicObjects, Core, CoreGeometry, CoreProperties, FS, IO, RedBlackTree, Rope, RTBasic, SC, SCInstUtil, SCPrivate, SCUtil, TerminalIO; SCUtilImpl: CEDAR PROGRAM IMPORTS Basics, CoreProperties, FS, IO, RedBlackTree, Rope, RTBasic, SC, SCInstUtil, TerminalIO EXPORTS SCUtil SHARES SC = BEGIN FindPin: PUBLIC PROCEDURE [object: SCPrivate.Object, pinName: Rope.ROPE] RETURNS [pin: SCPrivate.ObjectPin _ NIL] = BEGIN pins: SCPrivate.ObjectPins _ object.pins; FOR pinIndex: NAT IN [0 .. object.numPins) WHILE pin = NIL DO IF Rope.Equal[pinName, pins.p[pinIndex].name] THEN pin _ pins.p[pinIndex]; ENDLOOP; END; FindPinByWire: PUBLIC PROCEDURE [object: SCPrivate.Object, wire: Core.Wire] RETURNS [pin: SCPrivate.ObjectPin _ NIL] = BEGIN pins: SCPrivate.ObjectPins _ object.pins; FOR pinIndex: NAT IN [0 .. object.numPins) WHILE pin = NIL DO IF wire = pins.p[pinIndex].publicWire THEN pin _ pins.p[pinIndex]; ENDLOOP; END; FindNet: PUBLIC PROCEDURE [handle: SC.Handle, netName: Rope.ROPE] RETURNS [net: SCPrivate.Net _ NIL] = BEGIN structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; nets: SCPrivate.Nets _ structureData.nets; FOR netIndex: NAT IN [1 .. nets.count] WHILE net = NIL DO IF Rope.Equal[netName, nets.nets[netIndex].name] THEN net _ nets.nets[netIndex]; ENDLOOP; END; FindNetByWire: PUBLIC PROCEDURE [handle: SC.Handle, wire: Core.Wire] RETURNS [net: SCPrivate.Net _ NIL] = BEGIN structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; nets: SCPrivate.Nets _ structureData.nets; FOR netIndex: NAT IN [1 .. nets.count] WHILE net = NIL DO IF wire = nets.nets[netIndex].wire THEN net _ nets.nets[netIndex]; ENDLOOP; END; FindObject: PUBLIC PROCEDURE [handle: SC.Handle, objectName: Rope.ROPE] RETURNS [object: SCPrivate.Object _ NIL] = BEGIN structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; objects: SCPrivate.Objects _ structureData.objects; FOR objectIndex: NAT IN [1 .. objects.count] WHILE object = NIL DO IF Rope.Equal[objectName, objects.ob[objectIndex].name] THEN object _ objects.ob[objectIndex]; ENDLOOP; END; FindObjectByCell: PUBLIC PROCEDURE [handle: SC.Handle, cellType: Core.CellType] RETURNS [object: SCPrivate.Object _ NIL] = BEGIN objects: SCPrivate.Objects _ NARROW[handle.structureData, SCPrivate.StructureData].objects; FOR objectIndex: NAT IN [1 .. objects.count] WHILE object = NIL DO IF cellType = objects.ob[objectIndex].cellType THEN object _ objects.ob[objectIndex]; ENDLOOP; END; FindInstance: PUBLIC PROCEDURE [handle: SC.Handle, instanceName: Rope.ROPE] RETURNS [instance: SCPrivate.Instance _ NIL] = BEGIN structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; instances: SCPrivate.Instances _ structureData.instances; FOR instanceIndex: NAT IN [1 .. instances.count] WHILE instance = NIL DO IF Rope.Equal[instanceName, instances.inst[instanceIndex].name] THEN instance _ instances.inst[instanceIndex]; ENDLOOP; END; IsPowerName: PUBLIC PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [found: BOOLEAN _ FALSE] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; powerBuses: SCPrivate.PowerBuses _ layoutData.powerBuses; IF Rope.Equal[name, powerBuses[left].name, FALSE] OR Rope.Equal[name, powerBuses[right].name, FALSE] THEN found _ TRUE}; DirectionFromSide: PUBLIC PROC [side: CoreGeometry.Side] RETURNS [CDSymbolicObjects.Direction] ~ { RETURN[SELECT side FROM bottom=> south, right => east, top => north, left => west, ENDCASE => SC.Error[callingError, "Not suppose to happen."]]}; WriteResults: PUBLIC PROCEDURE [title: Rope.ROPE, handle: SC.Handle, startArea: SC.Number] RETURNS [area: SC.Number] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lambda: SC.Number _ handle.rules.rowParms.technology.lambda; width: SC.Number _ layoutData.totWidth/lambda; height: SC.Number _ layoutData.totHeight/lambda; area _ width*height; TerminalIO.PutRope[title]; TerminalIO.PutF1[" width = %g", IO.int[width]]; TerminalIO.PutF1[", height = %g", IO.int[height]]; TerminalIO.PutF1[", area = %g", IO.int[area]]; IF startArea > 0 THEN { reduction: SC.Number _ (startArea - area)*100/startArea; TerminalIO.PutRope[IO.PutFR[" reduction = %g%%\n", IO.real[reduction]]]}; TerminalIO.PutRope["\n"]; }; WriteStructure: PUBLIC PROCEDURE [handle: SC.Handle] = { EachInstance: SCInstUtil.EachInstanceProc = { EachPin: SCInstUtil.EachPinProc = { TerminalIO.PutRope[Rope.Cat[" Pin: ", netPin.pin.name, " Net: ", netPin.net.name, "\n"]]}; TerminalIO.PutRope[Rope.Cat[" Instance: ", instance.name, " Object: ", instance.object.name, "\n"]]; [] _ SCInstUtil.EnumeratePinsOnInst[instance, EachPin]}; TerminalIO.PutRope[Rope.Cat["Handle: ", handle.name, "\n"]]; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInstance]}; XYToPQ: PUBLIC PROC [handle: SC.Handle, pos: SC.Pos] RETURNS [pqPos: RTBasic.PQPos] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; rowDirection: SC.Direction _ layoutData.layoutParms.rowDirection; RETURN[RTBasic.XYToPQ[rowDirection, pos]]}; PQToXY: PUBLIC PROC [handle: SC.Handle, pqPos: RTBasic.PQPos] RETURNS [pos: SC.Pos] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; rowDirection: SC.Direction _ layoutData.layoutParms.rowDirection; RETURN[RTBasic.PQToXY[rowDirection, pqPos]]}; DestroyRules: PUBLIC PROC [handle: SC.Handle] ~ { rules: SC.DesignRules _ handle.rules; rules.rowRules _ NIL; rules.sideRules _ NIL; handle.rules _ NIL}; DestroyParms: PUBLIC PROC [handle: SC.Handle] = { parms: SCPrivate.Parms _ NARROW[handle.parms]; parms.libDesign _ NIL; parms.ftObject _ NIL; parms.portObject _ NIL; handle.parms _ NIL}; Memb: PROC [rope: Rope.ROPE, list: LIST OF Rope.ROPE] RETURNS [BOOL] = { UNTIL list = NIL DO IF Rope.Equal[list.first, rope] THEN RETURN[TRUE]; list _ list.rest; ENDLOOP; RETURN[FALSE]; }; GetCoreInvestmentProp: PUBLIC PROC [cellType: Core.CellType, prop: ATOM] RETURNS [SC.HowLongToWork] ~ { value: ATOM _ NARROW[CoreProperties.GetCellTypeProp[cellType, prop]]; investment: SC.HowLongToWork _ SELECT value FROM SC.veryLongValue => veryLong, SC.longValue => long, SC.mediumValue => medium, SC.shortValue => short, SC.veryShortValue => veryShort, ENDCASE => noInvestmentProp; RETURN[investment]}; WriteTWFiles: PUBLIC PROC [handle: SC.Handle] ~ { EachInstance: SCInstUtil.EachInstanceProc ~ { EachPin: SCInstUtil.EachPinProc ~ { IF netPin.net # NIL THEN AddPin[celStream, instance, netPin.pin, netPin.net, first]; -- for TimberWolf .cel file first _ FALSE}; first: BOOLEAN _ TRUE; IF instance.whichClass = logic THEN { -- for TimberWolf .cel file AddCell[celStream, instance]; [] _ SCInstUtil.EnumeratePinsOnInst[instance, EachPin]} ELSE IF instance.whichClass = io THEN AddPad[padTable, instance]}; netStream: FS.STREAM _ FS.StreamOpen[Rope.Cat[handle.name, ".net"], $create]; parStream: FS.STREAM _ FS.StreamOpen[Rope.Cat[handle.name, ".par"], $create]; blkStream: FS.STREAM _ FS.StreamOpen[Rope.Cat[handle.name, ".blk"], $create]; celStream: FS.STREAM _ FS.StreamOpen[Rope.Cat[handle.name, ".cel"], $create]; padTable: RedBlackTree.Table _ RedBlackTree.Create[GetKey, Compare]; parms: SCPrivate.Parms _ NARROW[handle.parms]; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; IO.Put[netStream, IO.rope["allnets HVweights 1.0 1.0\n"]]; IO.Flush[netStream]; IO.Close[netStream]; IO.Put[parStream, IO.rope["indent 1.0\n"]]; IO.Put[parStream, IO.rope["rowSep 1.0\n"]]; IO.Put[parStream, IO.rope["implicit.feed.thru.range 0.25\n"]]; IO.Put[parStream, IO.rope["feedThruWidth "], IO.int[parms.ftObject.size.p], IO.rope["\n"]]; IO.Flush[parStream]; IO.Close[parStream]; FOR row: INT IN [1 .. layoutData.lgRows.count] DO IO.Put[blkStream, IO.rope["block height "], IO.int[parms.ftObject.size.q], IO.rope[" class 1\n"]]; ENDLOOP; IO.Flush[blkStream]; IO.Close[blkStream]; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInstance]; CopyPadToCel[celStream, padTable]; -- pads must go at the end in position order IO.Flush[celStream]; IO.Close[celStream]}; AddCell: PROC [celStream: FS.STREAM, instance: SCPrivate.Instance] ~ { middleX: INT _ instance.object.orgin.p + instance.object.size.p/2; middleY: INT _ instance.object.orgin.q + instance.object.size.q/2; IO.Put[celStream, IO.rope["cell "], IO.int[instance.num]]; IO.Put[celStream, IO.rope[" "], IO.rope[instance.name]]; IO.Put[celStream, IO.rope["\n"]]; IO.Put[celStream, IO.rope[" left "], IO.int[instance.object.orgin.p - middleX]]; IO.Put[celStream, IO.rope[" right "], IO.int[instance.object.orgin.p + instance.object.size.p - middleX]]; IO.Put[celStream, IO.rope[" bottom "], IO.int[instance.object.orgin.q - middleY]]; IO.Put[celStream, IO.rope[" top "], IO.int[instance.object.orgin.q + instance.object.size.q - middleY], IO.rope["\n"]]}; AddPin: PROC [celStream: FS.STREAM, instance: SCPrivate.Instance, pin: SCPrivate.ObjectPin, net: SCPrivate.Net, first: BOOLEAN] ~ { middleX: INT _ instance.object.orgin.p + instance.object.size.p/2; middleY: INT _ instance.object.orgin.q + instance.object.size.q/2; pinPos: CD.Position _ SELECT pin.pinPos.side FROM bottom => [pin.pinPos.location - middleX, instance.object.orgin.q - middleY], top => [pin.pinPos.location - middleX, instance.object.orgin.q + instance.object.size.q - middleY], left => [instance.object.orgin.p - middleX, pin.pinPos.location - middleY], right => [instance.object.orgin.p + instance.object.size.p - middleX, pin.pinPos.location - middleY], ENDCASE => SC.Error[callingError, "pin on invalid side"]; IF first THEN { IO.Put[celStream, IO.rope[" pin name "], IO.rope[pin.name]]; IO.Put[celStream, IO.rope[" signal "], IO.rope[net.name]]} ELSE IO.Put[celStream, IO.rope[" equiv name "], IO.rope[pin.name]]; IO.Put[celStream, IO.rope[" "], IO.int[pinPos.x]]; IO.Put[celStream, IO.rope[" "], IO.int[pinPos.y]]; IO.Put[celStream, IO.rope["\n"]]}; Pad: TYPE = REF PadRec; PadRec: TYPE = RECORD [ instance: SCPrivate.Instance, pathName: Rope.ROPE]; AddPad: PROC [padTable: RedBlackTree.Table, instance: SCPrivate.Instance] ~ { pad: Pad _ NEW[PadRec _ [instance: instance, pathName: instance.name]]; RedBlackTree.Insert[padTable, pad, instance]}; CopyPadToCel: PROC [celStream: FS.STREAM, padTable: RedBlackTree.Table] ~ { WriteNode: RedBlackTree.EachNode ~ { pad: Pad _ NARROW[data]; sideRope: Rope.ROPE _ SELECT pad.instance.curSide FROM bottom => "B", right => "R", top => "T", left => "L", ENDCASE => "NONE"; orient: INT _ SELECT pad.instance.curSide FROM bottom => 0, right => 6, top => 3, left => 7, ENDCASE => 0; IO.Put[celStream, IO.rope["pad "], IO.int[pad.instance.num]]; IO.Put[celStream, IO.rope[" "], IO.rope[pad.pathName]]; IO.Put[celStream, IO.rope[" orient "], IO.int[orient], IO.rope["\n"]]; IO.Put[celStream, IO.rope[" padside "], IO.rope[sideRope], IO.rope["\n"]]; IO.Put[celStream, IO.rope[" left "], IO.int[-pad.instance.object.size.p]]; IO.Put[celStream, IO.rope[" right "], IO.int[pad.instance.object.size.p]]; IO.Put[celStream, IO.rope[" bottom "], IO.int[-pad.instance.object.size.q]]; IO.Put[celStream, IO.rope[" top "], IO.int[pad.instance.object.size.q], IO.rope["\n"]]; IO.Put[celStream, IO.rope[" pin name io signal "], IO.rope[pad.pathName]]; IO.Put[celStream, IO.rope[" "], IO.int[0]]; IO.Put[celStream, IO.rope[" "], IO.int[pad.instance.object.size.q]]; IO.Put[celStream, IO.rope["\n"]]}; RedBlackTree.EnumerateIncreasing[padTable, WriteNode]}; GetKey: RedBlackTree.GetKey ~ { pad: Pad _ NARROW[data]; RETURN[pad.instance]}; Compare: RedBlackTree.Compare ~ { instance: SCPrivate.Instance _ NARROW[k]; pad: Pad _ NARROW[data]; instanceSide: Rope.ROPE _ SELECT instance.curSide FROM bottom => "B", right => "R", top => "T", left => "L", ENDCASE => "NONE"; padSide: Rope.ROPE _ SELECT pad.instance.curSide FROM bottom => "B", right => "R", top => "T", left => "L", ENDCASE => "NONE"; result: Basics.Comparison _ Rope.Compare[padSide, instanceSide]; IF result = Basics.Comparison[equal] THEN result _ Basics.CompareInt[pad.instance.fnlPos, instance.fnlPos]; IF result = Basics.Comparison[equal] THEN result _ Rope.Compare[pad.instance.name, instance.name]; RETURN[result]}; ReadTWPlace: PUBLIC PROC [handle: SC.Handle]~ { placeStream: FS.STREAM _ FS.StreamOpen[Rope.Cat[handle.name, ".pl1"], $read]; [] _ IO.SkipWhitespace[placeStream]; WHILE ~IO.EndOf[placeStream] DO name: Rope.ROPE _ IO.GetTokenRope[placeStream, IO.IDProc].token; left: INT _ IO.GetInt[placeStream]; lower: INT _ IO.GetInt[placeStream]; right: INT _ IO.GetInt[placeStream]; upper: INT _ IO.GetInt[placeStream]; orient: INT _ IO.GetInt[placeStream]; row: INT _ IO.GetInt[placeStream]; dontCare: INT _ IO.SkipWhitespace[placeStream]; instance: SCPrivate.Instance _ FindInstance[handle, name]; IF instance # NIL THEN { SELECT instance.whichClass FROM logic => {instance.fnlRow _ row; instance.fnlPos _ left}; io => {SELECT orient FROM 0 => {instance.fnlPos _ left; instance.fnlSide _ bottom}; 6 => {instance.fnlPos _ lower; instance.fnlSide _ right}; 3 => {instance.fnlPos _ left; instance.fnlSide _ top}; 7 => {instance.fnlPos _ lower; instance.fnlSide _ left}; ENDCASE => {instance.fnlPos _ 0; instance.fnlSide _ none}}; ENDCASE} ELSE ERROR; -- the TW file & the extraction disagree... ENDLOOP; IO.Close[placeStream]}; translate: PUBLIC ARRAY SC.Side OF ARRAY SCPrivate.OrientationOrNone OF SC.Side; translate[bottom] _ [bottom, bottom, left, top, right, bottom, top, left, right]; translate[left] _ [left, left, top, right, bottom, right, left, bottom, top]; translate[top] _ [top, top, right, bottom, left, top, bottom, right, left]; translate[right] _ [right, right, bottom, left, top, left, right, top, bottom]; END. ~SCUtilImpl.mesa Copyright Σ 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Bryan Preas, August 20, 1987 12:26:24 pm PDT Christian Le Cocq July 9, 1987 3:02:26 pm PDT convert a position from x-y to p-q space. convert a position from p-q to x-y space. rules.rowRules.technology _ NIL; rules.sideRules.technology _ NIL; get an investment property from a cell write the timberWolf files PROC [instance: SCPrivate.Instance] RETURNS [quit: BOOL _ FALSE]; PROC [instance: SCPrivate.Instance, pin: NAT, netPin: SCPrivate.PinNet] RETURNS [quit: BOOL _ FALSE]; first the net file next the parameter file next the row definitions finally the connectivity add a cell to the .cel file add a pin to the .cel file record to save pad information; TimberWolf requires the pads to be sorted insert a pad into an ordered table pads must be at the end of the .cel file; write to .cel from the ordered symbol table PROC [data: UserData] RETURNS [stop: BOOL _ FALSE]; Callback proc: Given the user data in a node, return the key PROC [data: UserData] RETURNS [Key]; Callback proc type: Given a key and the user data in a node, return the comparison of the keys PROC [k: Key, data: UserData] RETURNS [Basics.Comparison]; read timberWolf placement HACK !!! TimberWolf does not provide side information. Have to use orientation BUG: TimberWolf sometimes provides identical locations for pads on same side!! ΚΊ˜šœ™JšœH™HJšœ-™-Icode™-—J˜šΟk ˜ Jš œœ9œœœ,˜–—J˜šΠbn œœœ˜Jšœœœœ˜_Jšœ˜Jšœœ˜ Jš˜K˜—š Οnœœ œ*œœœ˜sK˜Kš˜Kšœ)˜)š œ œœœœ˜=Kšœ,œ˜JKšœ˜—Kšœ˜K˜—š Ÿ œœ œ-œœ˜vK˜Kš˜Kšœ)˜)š œ œœœœ˜=Kšœ$œ˜BKšœ˜—Kšœ˜K˜—šŸœœ œ œœœœ˜fKš˜Kšœ)œ˜FKšœ*˜*š œ œœœœ˜9Kšœ/œ˜PKšœ˜—Kšœ˜K˜—š Ÿ œœ œ œœœ˜iKš˜Kšœ)œ˜FKšœ*˜*š œ œœœœ˜9Kšœ!œ˜BKšœ˜—Kšœ˜K˜—šŸ œœ œ œœœœ˜rKš˜Kšœ)œ˜FKšœ3˜3š œœœœ œ˜BKšœ6œ"˜^Kšœ˜—Kšœ˜K˜—š Ÿœœ œ œ"œœ˜zKš˜Kšœœ8˜[š œœœœ œ˜BKšœ-œ"˜UKšœ˜—Kšœ˜K˜—šŸ œœ œ œœœ!œ˜zKš˜Kšœ)œ˜FKšœ9˜9š œœœœ œ˜HKšœ>œ*˜nKšœ˜—Kšœ˜K˜—šŸ œœ œ œœœ œœ˜gK˜Kšœ#œ˜=Kšœ9˜9Jš œ)œœ*œœ œ˜xK˜—šŸœœœœ"˜bšœœ˜Kšœ;œœ1˜y—K˜—šŸ œœ œœ œœ œœ ˜xJ˜Jšœ#œ˜=Jšœœ2˜Kšœœœœ ˜[Kšœœ˜)K˜Kšœ™šœœœ ˜1Kšœœœœ˜bKšœ˜—Kšœœ˜)K˜Kšœ™K˜Kšœ<˜