--File: IPNetTabImpl.mesa
Last Edited by: CSChow, February 2, 1985 2:15:11 am PST
Preas, August 26, 1986 6:57:48 pm PDT
DIRECTORY
CDBasics,
Imager USING [Context, PathProc, SetGray, SetXY, ShowRope, MaskBox, MaskStroke],
IO,
IP,
IPConstants,
IPBasicOps,
IPToolBox,
IPChipRose,
IPCTG,
IPNetTab,
Rope,
Set USING [Handle, New, Put, Enumerate],
SymTab,
RTStructure;
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: BOOLTRUE] 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: BOOLFALSE] ={
ch: IPCTG.Channel ← NARROW[e];
chInt: INT ← ChAndRectOverlap[ch, netBRect];
chLength: INTIPCTG.Length[ch];
chStatIncr: REALIF 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: BOOLFALSE] ={
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.ROPETB.GetIdRope[stream]; -- First get the name
net: REF IP.NetRep ← NEW[IP.NetRep ← [name]];
TB.EnterBlock[stream];
UNTIL TB.ExitBlock[stream] DO
token: ATOMTB.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: INTIPCTG.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: INTLAST[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: INTBO.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: INTLAST[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: INTBO.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.