<<--File: IPNetTabImpl.mesa>> <> <> <<>> <<>> DIRECTORY Rope, Imager USING [Context, PathProc, SetGray, SetXY, ShowRope, MaskBox, MaskStroke], IO, SymTab, Set USING [Handle, New, Put, Enumerate], CDBasics, IP, IPConstants, IPBasicOps, IPToolBox, IPChipRose, IPCTG, IPNetTab; IPNetTabImpl: CEDAR PROGRAM IMPORTS IO, Imager, SymTab, Rope, Set, CDBasics, IP, IPChipRose, IPBasicOps, IPToolBox, IPCTG, IPNetTab EXPORTS IPNetTab = BEGIN OPEN TB: IPToolBox, CR: IPChipRose, BO: IPBasicOps, IPNetTab; SimpleChNetFactorEstimator: PUBLIC ChNetFactorEstimator ={horFactor _ (netBRect.x2 - netBRect.x1); verFactor _ (netBRect.y2 - netBRect.y1)}; --SimpleChNetFactorEstimator Create: PUBLIC PROC[chipRose: CR.Ref] RETURNS [Ref] = { nets: SymTab.Ref _ SymTab.Create[]; eachNet: CR.EachNetAction ={ [] _ nets.Store[net, NEW[NetRep _ [name: net]]]; }; --eachNet chipRose.Nets[eachNet]; RETURN [NEW[Rep _ [nets]]]; }; --Create FetchNet: PUBLIC PROC[netTab: Ref, name: Rope.ROPE, raiseError: BOOL] RETURNS [Net] ={ found: BOOL; val: REF; [found, val] _ netTab.nets.Fetch[name]; IF found THEN RETURN [NARROW[val]]; IF raiseError THEN ERROR IP.Error[missingRegistration, Rope.Cat[name, " is not a net name"]] ELSE RETURN [NIL]; }; --FetchNet Size: PUBLIC PROC[netTab: Ref] RETURNS [INT] ={ RETURN [SymTab.GetSize[netTab.nets]]}; --Size Nets: PUBLIC PROC[netTab: Ref, action: EachNetAction] ={ p: SymTab.EachPairAction = {RETURN[action[NARROW[val]]]};--p [] _ netTab.nets.Pairs[p]; }; --Nets TotalNetLength: PUBLIC PROC[netTab: Ref, netFactorProc: ChNetFactorEstimator] RETURNS [totalLength: INT _ 0] ={ eachNetProc: EachNetAction ={ totalLength _ totalLength + NetLength[net, netFactorProc]}; --eachNetProc Nets[netTab, eachNetProc]; }; --TotalNetLength CountNets: PUBLIC PROC[netTab: Ref] RETURNS [active, nonActive: INT _ 0] ={ eachNetProc: EachNetAction ={ IF NetActive[net] THEN active _ active.SUCC ELSE nonActive _ nonActive.SUCC; }; --eachNetProc Nets[netTab, eachNetProc]; }; --CountNets CountAllPins: PUBLIC PROC[netTab: Ref, activeNetsOnly: BOOL _ TRUE] RETURNS [active, nonActive: INT _ 0] ={ eachNetProc: EachNetAction ={ IF activeNetsOnly AND ~ NetActive[net] THEN NULL ELSE { aIncr, nIncr: INT; [aIncr, nIncr] _ CountPins[net]; active _ active + aIncr; nonActive _ nonActive + nIncr;};}; --eachNetProc Nets[netTab, eachNetProc]; }; --CountAllPins CheckSelf: PUBLIC PROC[netTab: Ref] ={NULL}; --CheckSelf DescribeSelf: PUBLIC PROC[netTab: Ref, stream: IO.STREAM, debug: BOOL] ={ pNet: EachNetAction ={ <<--(1) Print net name>> stream.PutF["%g: \t{", IO.rope[net.name]]; <<--(2) Print pinNet: NOT used, for debugging>> IF debug THEN { stream.PutF["pinNets: {"]; FOR l: PinNets _ net.pinNets, l.rest UNTIL l = NIL DO <<--Print out @ >> stream.PutF[" %g@%g", IO.rope[l.first.name], IO.rope[l.first.owner.name]] ENDLOOP; stream.PutF["}"]; }; --endIF stream.PutF["}\n"]; };--pNet stream.PutF["\nBeginNetTab\n"]; stream.PutF["\n%g \t--Number of Nets\n", IO.int[netTab.nets.GetSize[]]]; Nets[netTab, pNet]; stream.PutF["EndNetTab\n"]; }; --DescribeSelf ReconstructSelf: PUBLIC PROC[stream: IO.STREAM] RETURNS [Ref] ={ nets: SymTab.Ref _ SymTab.Create[]; THROUGH [0..stream.GetInt) DO name: Rope.ROPE; net: REF IP.NetRep; [name, net] _ GetNet[stream]; [] _ nets.Store[name, net]; ENDLOOP; IF stream.GetAtom[] # $EndNetTab THEN ERROR; RETURN [NEW[Rep _ [nets]]]; }; --ReconstructSelf NetLength: PUBLIC PROC[net: Net, netFactorProc: ChNetFactorEstimator] RETURNS [INT] ={ netBRect: Rect _ GetNetBRect[net]; IF NetActive[net] AND netFactorProc # NIL THEN { <<-- netFactorProc # NIL => assign channel.statistics.netFactor (for all relevant channel)>> activePins, nonActivePins: INT; horFactor, verFactor: REAL; horChSum, verChSum: INT _ 0; chSet: Set.Handle _ Set.New[]; eachChAction: PROC[e: REF ANY] RETURNS [stop: BOOL _ FALSE] ={ ch: IPCTG.Channel _ NARROW[e]; chInt: INT _ ChAndRectOverlap[ch, netBRect]; chLength: INT _ IPCTG.Length[ch]; chStatIncr: REAL _ IF ch.type = hor THEN (horFactor * chInt * chInt) /(horChSum * chLength) ELSE (verFactor * chInt * chInt) /(verChSum * chLength); ch.statistics.netFactor _ ch.statistics.netFactor + chStatIncr; }; --eachChAction <<>> <<--(a) Calculate horFactor and verFactor for net>> [activePins, nonActivePins] _ CountPins[net]; [horFactor, verFactor] _ netFactorProc[netBRect, activePins, nonActivePins]; <<--(b) Find relevant channel and calculate horChSum and verChSum>> FOR l: PinNets _ net.pinNets, l.rest UNTIL l = NIL DO comp: REF IP.ComponentRep _ l.first.owner; -- get the component coChAction: PROC[ch: IPCTG.Channel] RETURNS [quit: BOOL _ FALSE] ={ overLap: INT _ ChAndRectOverlap[ch, netBRect]; IF overLap > 0 THEN { SELECT ch.type FROM hor => horChSum _ horChSum + overLap; ver => verChSum _ verChSum + overLap; ENDCASE => ERROR; [] _ Set.Put[chSet, ch]}; }; --eachCoChAction IPToolBox.CoChannels[comp, coChAction]; ENDLOOP; <<--(c) Assign ch.statistics.netFactor for each channel in chSet>> [] _ Set.Enumerate[chSet, eachChAction]; }; --endIF RETURN [(netBRect.x2- netBRect.x1) + (netBRect.y2 - netBRect.y1)]; --This is the semi-perimeter of the net's bounding box }; --NetLength CountPins: PUBLIC PROC[net: Net] RETURNS [active, nonActive: INT _ 0] ={ FOR l: PinNets _ net.pinNets, l.rest UNTIL l = NIL DO FOR phyPins: PhysicalPins _ l.first.physicalPins, phyPins.rest UNTIL phyPins = NIL DO IF phyPins.first.active THEN active _ active.SUCC ELSE nonActive _ nonActive.SUCC; ENDLOOP; ENDLOOP; }; --CountPins PaintNet: PUBLIC PROC [net: Net, context: Imager.Context, xOffset, yOffset, scaleFactor: REAL, stipple: CARDINAL, showNetName: BOOL] ={ xMin, yMin, xMax, yMax: REAL; [[xMin, yMin, xMax, yMax]] _ GetNetBRect[net]; xMin _ xOffset + (xMin * scaleFactor); yMin _ yOffset + (yMin * scaleFactor); xMax _ xOffset + (xMax * scaleFactor); yMax _ yOffset + (yMax * scaleFactor); IF stipple = IPConstants.White THEN { path: Imager.PathProc ~ { moveTo[[xMin, yMin]]; lineTo[[xMax, yMin]]; lineTo[[xMax, yMax]]; lineTo[[xMin, yMax]]; lineTo[[xMin, yMin]];}; Imager.MaskStroke[context, path];} ELSE { Imager.SetGray[context, stipple]; Imager.MaskBox[context, [xMin, yMin, xMax, yMax]];}; IF showNetName THEN { Imager.SetXY[context, [(xMin + xMax)/2.0, (yMin + yMax)/2.0]]; --place at center Imager.ShowRope[context, net.name]}; };--PaintNet <<--###Private Types & Procedures####-->> GetNet: PROC[stream: IO.STREAM] RETURNS [Rope.ROPE, REF IP.NetRep] ={ name: Rope.ROPE _ TB.GetIdRope[stream]; -- First get the name net: REF IP.NetRep _ NEW[IP.NetRep _ [name]]; TB.EnterBlock[stream]; UNTIL TB.ExitBlock[stream] DO token: ATOM _ TB.GetIdAtom[stream]; SELECT token FROM <<--I used format to impl GetNet to make it more general/extensible>> $pinNets => TB.RemoveBlock[stream]; --list of pinNet names, not used ENDCASE => ERROR; ENDLOOP; RETURN[name, net]; }; --GetNet <<-- Related to computing channel's netFactor >> ChAndRectOverlap: PROC[ch: IPCTG.Channel, rect: Rect] RETURNS [NAT]= { chCoord: INT _ IPCTG.GetCoord[ch]; chNegBnd, chPosBnd, rectNegBnd, rectPosBnd: INT; [chNegBnd, chPosBnd] _ IPCTG.Bounds[ch]; SELECT ch.type FROM hor => IF chCoord < rect.y1 OR rect.y2 < chCoord THEN RETURN [0] ELSE {rectNegBnd _ rect.x1; rectPosBnd _ rect.x2}; ver => IF chCoord < rect.x1 OR rect.x2 < chCoord THEN RETURN [0] ELSE {rectNegBnd _ rect.y1; rectPosBnd _ rect.y2}; ENDCASE => ERROR; IF chNegBnd > rectPosBnd OR chPosBnd < rectNegBnd THEN RETURN [0] ELSE RETURN [1 + MIN[rectPosBnd, chPosBnd] - MAX[chNegBnd, rectNegBnd]] }; --ChAndRectOverlap <<>> <<--Related to computing bounding of net and deciding pin active/nonActive>> GetNetBRect: PROC [net: Net] RETURNS [bRect: Rect _ [0, 0, 0, 0]] = { pinNets: PinNets _ net.pinNets; IF pinNets = NIL THEN RETURN; --No pinNets IF pinNets.rest = NIL THEN { -- ONE pinNet but need at least two FOR l: PhysicalPins _ pinNets.first.physicalPins, l.rest UNTIL l = NIL DO l.first.active _ FALSE ENDLOOP; RETURN}; <<>> <<--Have two pinNets can do something>> <<--The algorithm is:>> <<-- (1) Find center of mass (ctrMass) of all physical pins>> <<--(2) Use ctrMass to find the closest physical pin's coord and use that as >> <<-- the starting Net Bounding Rect.(set to xMin, yMin, xMax yMax)>> <<--(3) With the starting Bounding Rect chose a physicalPin representative >> <<-- from each pinNet (and set that active.) This physical Pin is chosen >> <<-- so that it will increase the Bounding Rect minimally (increase is 0 if it lies >> <<-- inside Rect.) >> BEGIN ctrMass: IP.IntVector _ FindPhyPinsCM[pinNets]; bRect _ FindInitialNetBRect[pinNets, ctrMass]; FOR l: PinNets _ pinNets, l.rest UNTIL l = NIL DO bRect _ NuBRectNActivatePin[l.first, bRect]; ENDLOOP; END; }; --GetNetBRect FindPhyPinsCM: PROC[pinNets: PinNets] RETURNS [IP.IntVector] ={ totalMass: IP.IntVector _ [0, 0]; totalPhyPins: NAT _ 0; WHILE pinNets # NIL DO incrMass: IP.IntVector _ [0, 0]; incrPhyPins: NAT _ 0; phyPinsOrigin: IP.IntVector _ IPToolBox.GetCoOrigin[pinNets.first.owner]; FOR l: PhysicalPins _ pinNets.first.physicalPins, l.rest UNTIL l = NIL DO incrPhyPins _ incrPhyPins.SUCC; incrMass _ CDBasics.AddPoints[incrMass, l.first.coord]; ENDLOOP; totalMass _ CDBasics.AddPoints[totalMass, incrMass]; totalMass _ CDBasics.AddPoints[totalMass, BO.IntVectorScale[phyPinsOrigin, incrPhyPins]]; totalPhyPins _ totalPhyPins + incrPhyPins; pinNets _ pinNets.rest ENDLOOP; RETURN [BO.IntVectorDivide[totalMass, totalPhyPins]]; }; --FindPhyPinsCM FindInitialNetBRect: PROC[pinNets: PinNets, target: IP.IntVector] RETURNS [Rect] ={ bestPosition: IP.IntVector _ [0, 0]; bestDist: INT _ LAST[INT]; WHILE pinNets # NIL DO coOrigin: IP.IntVector _ IPToolBox.GetCoOrigin[pinNets.first.owner]; nTarget: IP.IntVector _ CDBasics.SubPoints[target, coOrigin]; FOR l: PhysicalPins _ pinNets.first.physicalPins, l.rest UNTIL l = NIL DO newDist: INT _ BO.IntVectorMDistance[nTarget, l.first.coord]; IF newDist < bestDist THEN {bestDist _ newDist; bestPosition _ CDBasics.AddPoints[l.first.coord, coOrigin]}; ENDLOOP; pinNets _ pinNets.rest ENDLOOP; RETURN [Rect[bestPosition.x, bestPosition.y, bestPosition.x, bestPosition.y]] }; --FindInitialNetBRect NuBRectNActivatePin: PROC[pinNet: REF IP.PinNetRep, bRect: Rect] RETURNS [Rect] ={ bestP: REF IP.PhysicalPinRep _ NIL; bestCoord: IP.IntVector; bestDistFromRect: INT _ LAST[INT]; coOrigin: IP.IntVector _ IPToolBox.GetCoOrigin[pinNet.owner]; FOR l: PhysicalPins _ pinNet.physicalPins, l.rest UNTIL l = NIL DO newCoord: IP.IntVector _ CDBasics.AddPoints[l.first.coord, coOrigin]; newDistFromRect: INT _ BO.RectMDistanceToPt[bRect, newCoord]; l.first.active _ FALSE; IF newDistFromRect <= 0 THEN { <> bestP _ l.first; bestP.active _ TRUE; <> FOR ll: PhysicalPins _ l.rest, ll.rest UNTIL ll = NIL DO ll.first.active _ FALSE; ENDLOOP; <> RETURN [bRect]; }; IF newDistFromRect < bestDistFromRect THEN { <> bestP _ l.first; bestDistFromRect _ newDistFromRect; bestCoord _ newCoord; }; ENDLOOP; IF bestP # NIL THEN { <> bestP.active _ TRUE; <> bRect _ BO.RectExtendToPt[bRect, bestCoord]; }; RETURN [bRect]; }; --NuBRectNActivatePin END.