IPNetTabImpl:
CEDAR
PROGRAM
IMPORTS CDBasics, IO, Imager, IP, IPChipRose, IPBasicOps, IPToolBox, IPCTG, IPNetTab, Rope, Set, RTStructure, SymTab
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] = {
eachNet:
CR.EachNetAction ={
[] ← nets.Store[net, NEW[NetRep ← [name: net]]];
}; --eachNet
nets: SymTab.Ref ← SymTab.Create[];
chipRose.Nets[eachNet];
RETURN [NEW[Rep ← [nets]]];
}; --Create
CreateFromStructure:
PUBLIC
PROC[structure: RTStructure.Structure]
RETURNS [Ref] = {
EachNet: RTStructure.EachNetAction ={
[] ← SymTab.Store[nets, net.name, NEW[NetRep ← [name: net.name]]];
}; --eachNet
nets: SymTab.Ref ← SymTab.Create[];
[] ← RTStructure.EnumerateNets[structure, 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 <pinName>@<componentName>
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 {
The pin is inside the rectangle, so if it is the first, then it is the best
bestP ← l.first;
bestP.active ←
TRUE;
Set the "best" pin to active
FOR ll: PhysicalPins ← l.rest, ll.rest
UNTIL ll =
NIL
DO ll.first.active ←
FALSE;
ENDLOOP;
Set all of the other pins to be NOT active
RETURN [bRect];
};
IF newDistFromRect < bestDistFromRect
THEN {
This pin is outside the rectangle, and better than any we have seen before
bestP ← l.first;
bestDistFromRect ← newDistFromRect;
bestCoord ← newCoord;
};
ENDLOOP;
IF bestP #
NIL THEN {
A non-empty pin list
bestP.active ←
TRUE;
Set the "best" pin to active
bRect ← BO.RectExtendToPt[bRect, bestCoord];
};
RETURN [bRect];
}; --NuBRectNActivatePin
END.