IPPlaceKitImpl: 
CEDAR 
PROGRAM
IMPORTS OrderedRefArray, IP, IPBasicOps, IPCoTab, IPCTG, IPCB, IPTopOps
EXPORTS IPPlaceKit = BEGIN OPEN IPPlaceKit;
-- Operation to execute a trial
Execute: 
PUBLIC 
PROC[top: IPTop.Ref, trial: 
REF] ={
WITH trial 
SELECT 
FROM
gr: REF GrowRec => [] ← IPTopOps.Grow[top, gr.co, gr.chToSplit, gr.negBnd, gr.posBnd, TRUE];
com: IPTopOpRecs.RComposite => IPTopOps.Redo[top, com];
ENDCASE => ERROR IP.Error[callingError, "Execute doesnt know about this type"]
 
}; --Execute
 
--Trials Generating Primitives: : 
CreateChEnumData: 
PUBLIC 
PROC[refCh: 
IPCTG.Channel] 
RETURNS [ChEnumData] ={
RETURN [NEW[ChEnumDataRep ← [IPCB.End[refCh.boundary, neg].ch, IPCB.End[refCh.boundary, pos].ch, refCh.boundary.negSideHd, refCh.boundary.posSideHd]]]};--CreateChEnumData
 
GetChSucc: 
PUBLIC 
PROC[data: ChEnumData, getXOnce: 
BOOL ← 
TRUE] 
RETURNS [
IPCTG.Channel] ={
countXOnce: BOOL ← TRUE;
chSucc: IPCTG.Channel ← data.nextCh;
negSide: LIST OF REF IP.IntersectionNodeRep ← data.negSidePtr;
posSide: LIST OF REF IP.IntersectionNodeRep ← data.posSidePtr;
IF negSide = 
NIL 
OR posSide = 
NIL 
THEN {
--(0) chSucc = NIL
IF chSucc = NIL THEN RETURN [NIL];
--(1) negSide # NIL
IF negSide # NIL THEN {data.nextCh ← negSide.first.intersection.ch; data.negSidePtr ← data.negSidePtr.rest};
--(2) posSide # NIL
IF posSide # NIL THEN {data.nextCh ←posSide.first.intersection.ch; data.posSidePtr ← data.posSidePtr.rest};
--(3) Both NILs 
IF negSide = 
NIL 
AND  posSide = 
NIL 
THEN {
IF chSucc = data.finalCh 
THEN data.nextCh ← NIL
ELSE data.nextCh ← data.finalCh;};
 
 
}
 
ELSE {
negCh: IPCTG.Channel ← negSide.first.intersection.ch;
posCh: IPCTG.Channel ← posSide.first.intersection.ch;
IF 
IPCTG.GetCoord[negCh] > 
IPCTG.GetCoord[posCh] 
THEN {data.nextCh ← posCh; data.posSidePtr ← data.posSidePtr.rest}
ELSE {data.nextCh ← negCh; data.negSidePtr ← data.negSidePtr.rest};
 
IF getXOnce 
AND negCh = posCh 
THEN data.posSidePtr ← data.posSidePtr.rest;
-- negCh = posCh => IPCTG.GetCoord[negCh] = IPCTG.GetCoord[posCh]
-- => data.negSidePtr has been incremented. 
-- So if getXOnce then need to increment data.posSidePtr 
 
};  --endIF
 
 
RETURN [chSucc];
};--GetChSucc
 
AllChGrowSites: 
PUBLIC 
PROC[refCh: 
IPCTG.Channel, action: EachChGrowSiteAction] ={
negBnd: ChEnumData ← CreateChEnumData[refCh];
posBnd: ChEnumData ← CreateChEnumData[refCh];
negCh, posCh: IPCTG.Channel;
DO
negCh ← GetChSucc[negBnd, TRUE];
IF negCh = NIL THEN EXIT;
posBnd^ ← negBnd^;
DO
next, quit: BOOL;
posCh ← GetChSucc[posBnd, TRUE];
IF posCh = NIL THEN EXIT; 
[next, quit] ← action[negCh, posCh];
IF quit THEN RETURN;
IF next THEN EXIT;
ENDLOOP;
 
ENDLOOP;
 
}; --AllChGrowSites
 
ChGrowSites: 
PUBLIC 
PROC[refCh: 
IPCTG.Channel, whichSide: 
IP.PolarityTypes, action: EachChGrowSiteAction]= {
filterSites: EachChGrowSiteAction ={
IF ~
IPCTG.ArmOn[refCh, negBnd, whichSide] 
OR ~
IPCTG.ArmOn[refCh, posBnd, whichSide]
THEN RETURN;
 
[next, quit] ← action[negBnd, posBnd]
}; --filterSites
AllChGrowSites[refCh, filterSites]
}; --ChGrowSites
 
AllTopGrow1Sites: 
PUBLIC 
PROC[top: IPTop.Ref, action: EachTopGrow1SiteAction] ={
eachComp: IPCoTab.EachComponentAction = {
FOR corner: IPCoTab.CornerTypes 
IN [sw..nw] 
UNTIL quit 
DO
IF CoCornerFree[co, corner] THEN quit ← action[co, corner]
ENDLOOP;
 
}; --eachComp
IPCoTab.Components[top.coTab, eachComp]
}; --AllTopGrow1Sites
 
SideComponents: 
PUBLIC 
PROC[refCh: 
IPCTG.Channel, which: 
IPCTG.Side, action: IPCoTab.EachComponentAction] ={
filteredAction: IPCTG.EachComponentAction ={
IF co # NIL THEN RETURN [action[co]]}; --filteredAction
[] ← IPCTG.Components[refCh, which, filteredAction]
}; --SideComponents
 
SideChannels: 
PUBLIC 
PROC[refCh: 
IPCTG.Channel, which: 
IPCTG.Side, action: 
IPCTG.EachChannelAction] ={
intersectionAction: 
IPCTG.EachIntersectionAction ={
RETURN [action[i.ch]]
}; --intersectionAction
[] ← IPCTG.Intersections[refCh, which, intersectionAction]
}; --SideChannels
 
-- Useful routines
NonActiveComps: 
PUBLIC 
PROC [top: IPTop.Ref, action: IPCoTab.EachComponentAction] ={
nonActiveComps: IPCoTab.EachComponentAction ={
IF IPCoTab.CoActive[co] 
THEN NULL
ELSE RETURN [action[co]]
 
}; --nonActiveComps
IPCoTab.AllComponents[top.coTab, nonActiveComps];
}; --NonActiveComps
 
CountComps: 
PUBLIC 
PROC[comps: Components] 
RETURNS [count: 
NAT ← 0] ={
UNTIL comps = 
NIL 
DO
count ← count.SUCC;
comps ← comps.rest;
ENDLOOP
 
}; --CountComps
 
CopyCompsHead: 
PUBLIC 
PROC[comps: Components, head: 
NAT] 
RETURNS [compHd, compRest: Components] ={
IF head = 0 
OR comps = 
NIL 
THEN RETURN [NIL, comps]
ELSE {
compTl: Components ← LIST[comps.first];
compHd ← compTl;
DO
head ← head.PRED;
comps ← comps.rest;
IF comps = NIL OR head = 0 THEN {compRest ← comps; EXIT};
compTl.rest ← LIST[comps.first];
compTl ← compTl.rest
ENDLOOP;
 
};
 
 
}; --CopyCompsHead
 
GetComponents: 
PUBLIC 
PROC[remTrack: 
LIST 
OF 
REF] 
RETURNS [comps: Components ← 
NIL] ={
getCo: 
PROC[step: 
REF] ={
WITH step 
SELECT 
FROM
s1: IPTopOpRecs.FRShrink1 => comps ← CONS[s1.co, comps];
rc: IPTopOpRecs.FRRemoveCo => comps ← CONS[rc.co, comps];
cm: IPTopOpRecs.RComposite => getCo[cm.first];
ENDCASE => 
ERROR IP.Error[callingError, "GetComponents doesn't know about this type"];
 
 
}; --getCo
UNTIL remTrack = 
NIL 
DO
getCo[remTrack.first];
remTrack ← remTrack.rest
ENDLOOP;
 
}; --GetComponents
 
GetComponentArea: 
PUBLIC PROC[comp: IPCoTab.Component, minusUsedCorners, minusFreeCorners: 
BOOL ← 
TRUE] 
RETURNS [area: 
INT] ={
xDim, yDim: INT;
--(1) Compute area of outline
[xDim, yDim] ← IPCoTab.GetDim[comp];
area ← (xDim * yDim);
--(2) Subtract area of corners
FOR corner: 
IP.CornerTypes 
IN [sw..nw] 
DO
cornerChs: IPCoTab.CornerChannels ← IPCoTab.GetCornerChs[comp, corner];
cornerSp: IPCoTab.CornerSpace ← IPCoTab.GetCornerSp[comp, corner];
areaDecr: INT;
IF cornerSp = 
NIL 
THEN areaDecr ← 0
ELSE {
[xDim, yDim] ← cornerSp^;
areaDecr ← (xDim * yDim);
};
 
 
IF cornerChs = 
NIL 
THEN {
IF minusFreeCorners THEN area ← (area - areaDecr)
}
 
ELSE {
IF minusUsedCorners THEN area ← (area - areaDecr)
}
 
 
ENDLOOP;
 
}; --GetComponentArea
 
CoCornerFree: 
PUBLIC 
PROC[co: IPCoTab.Component, corner: IPCoTab.CornerTypes]
 RETURNS [
BOOL] ={
RETURN [IPCoTab.GetCornerSp[co, corner] # NIL AND (IPCoTab.GetCornerChs[co, corner] = NIL OR  ~IPCoTab.CoActive[co])]
}; --CoCornerBitible
 
ComputeZType: 
PUBLIC 
PROC[corner: IPCoTab.CornerTypes, refChType: 
IPCTG.ChType] 
RETURNS [
IP.PolarityTypes] ={
SELECT refChType 
FROM
hor => RETURN [IF corner = sw OR corner = ne THEN pos ELSE neg];
ver => RETURN [IF corner = sw OR corner = ne THEN neg ELSE pos];
ENDCASE => ERROR;
 
}; --ComputeZType
 
--High level routines
CompactComp0: 
PUBLIC 
PROC[
top: IPTop.Ref,
comp: IPCoTab.Component,
direction: IPCTG.ChType,
placeEval: PlaceEvaluator, -- Simply use as an eval function no prunning
results: OrderedRefArray.Ref,
resultsAfter: NAT,
keepInitTrack: BOOL ← TRUE, --Provided for convenience
formZOk: BOOL ← TRUE -- This means okay to formz during compaction
] ={
directnFlipped: IPCTG.ChType ← IPBasicOps.OTFlip[direction];
addTrack: 
PROC ={
value: INT ← placeEval[top, NIL].value;
OrderedRefArray.Insert[results, IPTopOps.GetTrack[top, resultsAfter], value]
}; --addTrack
biteCorner: 
PROC[corner: IPCoTab.CornerTypes] ={
IF IPCoTab.GetCornerSp[comp, corner] # 
NIL 
THEN {
refCh: IPCTG.Channel ← IPCoTab.GetPrinCh[comp, IPBasicOps.CTResolveFor[corner, directnFlipped]];
chSide: IPCTG.Side ← IPBasicOps.CTDirectnFor[corner, direction];
tToLAction: 
IPCTG.EachChannelAction ={
[] ← IPTopOps.TtoL[top, comp, ch, IPBasicOps.CTDirectnFor[corner, directnFlipped],  TRUE];
addTrack[];
IF corner # nw THEN biteCorner[corner.SUCC];
[] ← IPTopOps.Undo1[top];
};--tToLAction
fZAction: IPCoTab.EachComponentAction ={
cornerDiag: IPCoTab.CornerTypes ← IPBasicOps.CTDiag[corner];
IF IPTopOps.FormZChk[top, co, comp, ComputeZType[corner, directnFlipped]]
THEN {
[] ← IPTopOps.FormZ[top, co, comp, ComputeZType[corner, directnFlipped], TRUE];
addTrack[];
IF corner # nw THEN biteCorner[corner.SUCC];
[] ← IPTopOps.Undo1[top];
};
 
 
}; --fZAction
SideChannels[refCh, chSide, tToLAction];
IF formZOk THEN SideComponents[refCh, chSide, fZAction];
}; --endIf
 
IF corner # nw THEN biteCorner[corner.SUCC];
};--biteCorner
IF keepInitTrack THEN addTrack[];
biteCorner[sw];
}; --CompactComp0
 
CompactComp1: 
PUBLIC PROC[
top: IPTop.Ref,
comp: IPCoTab.Component,
direction: IPCTG.ChType,
placeEval: PlaceEvaluator, -- Simply use as an eval function no prunning
results: OrderedRefArray.Ref, -- improvement added here
resultsAfter: NAT,
keepInitTrack: BOOL ← TRUE --Provided for convenience
] ={
eachNeighborAction: IPCoTab.EachComponentAction = {
CompactComp0[top, comp, direction, placeEval, results, resultsAfter, FALSE, FALSE]
}; --eachNeighborAction
--(1) Apply compaction to comp
CompactComp0[top, comp, direction, placeEval, results, resultsAfter, keepInitTrack, TRUE];
SELECT direction 
FROM
hor => {
SideComponents[IPCoTab.GetPrinCh[comp, west], neg, eachNeighborAction];
SideComponents[IPCoTab.GetPrinCh[comp, east], pos, eachNeighborAction];
direction ← IPBasicOps.OTFlip[direction];
SideComponents[IPCoTab.GetPrinCh[comp, south], neg, eachNeighborAction];
SideComponents[IPCoTab.GetPrinCh[comp, north], pos, eachNeighborAction];
};
ver => {
SideComponents[IPCoTab.GetPrinCh[comp, south], neg, eachNeighborAction];
SideComponents[IPCoTab.GetPrinCh[comp, north], pos, eachNeighborAction];
direction ← IPBasicOps.OTFlip[direction];
SideComponents[IPCoTab.GetPrinCh[comp, west], neg, eachNeighborAction];
SideComponents[IPCoTab.GetPrinCh[comp, east], pos, eachNeighborAction];
};
ENDCASE => ERROR;
 
}; --CompactComp1
 
FTPerturbTop: 
PUBLIC PROC[  
--FT = FlipT
top: IPTop.Ref,
placeEval: PlaceEvaluator, -- Simply use as an eval function no prunning
depth: NAT,
results: OrderedRefArray.Ref,
resultsAfter: NAT,
keepInitTrack: BOOL ← TRUE --Provided for convenience
] ={
whichEnd: IP.PolarityTypes;
eachTrialAction: EachChGrowSiteAction ={
-- Perhaps should do prunning, but how??
IF IPTopOps.FlipTChk[top, negBnd, posBnd, whichEnd] 
THEN {
[] ← IPTopOps.FlipT[top, negBnd, posBnd, whichEnd, TRUE];
FTPerturbTop[top, placeEval, depth.PRED, results, resultsAfter, TRUE];
[] ← IPTopOps.Undo1[top]
};
 
IF IPTopOps.FlipTChk[top, posBnd, negBnd, whichEnd] 
THEN {
[] ← IPTopOps.FlipT[top, posBnd, negBnd, whichEnd, TRUE];
FTPerturbTop[top, placeEval, depth.PRED, results, resultsAfter, TRUE];
[] ← IPTopOps.Undo1[top]
};
 
}; --eachTrackAction
eachChAction:  
IPCTG.EachChannelAction = {
whichEnd ← neg; -- info used above
ChGrowSites[ch, neg, eachTrialAction];
whichEnd ← pos; -- info used above
ChGrowSites[ch, pos, eachTrialAction];
}; --eachChAction
IF keepInitTrack THEN OrderedRefArray.Insert[results, IPTopOps.GetTrack[top, resultsAfter], placeEval[top, NIL].value];
IF depth > 0 THEN [] ← IPCTG.Channels[top.ctg, eachChAction]
};--FTPerturbTop
 
END.