IPTopEditOpsExtraImpl:
CEDAR
PROGRAM
IMPORTS CDOrient, IPCTG, IPCoTab, IPBasicOps, IPEditPrimitives, IPToolBox, IPTopOps, IPTopOpsPrivate
EXPORTS IPTopOps, IPTopOpsPrivate = BEGIN OPEN TOR: IPTopOpRecs, IPTopOps;
SpawnComps:
PUBLIC
PROC[top: IPTop.Ref, comp: IPCoTab.Component, negChildName, posChildName: Rope.
ROPE, negChildShape, posChildShape:
IP.ShapeRep, splitDirection:
IP.OrientationTypes, chkArgs, keepTrack:
BOOL, negChild, posChild: IPCoTab.Component ←
NIL]
RETURNS [fr:
TOR.FRSpawnComps, ir:
TOR.RComposite ←
NIL]={
--Having chkArgs is a change in format of TopOps.
-- In this way we won't need to do the trick as in FlipT
insertCoHint: [1..2] = 1;
chToSplit, negBnd, posBnd: IPCTG.Channel;
IF chkArgs AND ~ SpawnCompsChk[top, comp, negChildName, posChildName, negChildShape, posChildShape, splitDirection] THEN ERROR InvalidArgs[$SpawnComps]; --(1) Check Arguments
negChild ← IPCoTab.CreateComponent2[top.coTab, negChildName, negChildShape, FALSE, CDOrient.original, [0,0], negChild];
posChild ← IPCoTab.CreateComponent2[top.coTab, posChildName, posChildShape, FALSE, CDOrient.original, [0,0], posChild];
SELECT splitDirection
FROM
hor => {
chToSplit ← IPCoTab.GetPrinCh[comp, north];
negBnd ← IPCoTab.GetPrinCh[comp, west];
posBnd ← IPCoTab.GetPrinCh[comp, east];};
ver => {
chToSplit ← IPCoTab.GetPrinCh[comp, east];
negBnd ← IPCoTab.GetPrinCh[comp, south];
posBnd ← IPCoTab.GetPrinCh[comp, north];};
ENDCASE => ERROR;
ir ← CONS[NEW[TOR.IRDestroyComp2Rep ← [negChild]], ir];
ir ← CONS[NEW[TOR.IRDestroyComp2Rep ← [posChild]], ir];
ir ← CONS[SwapComponents[top, comp, negChild, FALSE].ir, ir];
ir ← CONS[IPTopOpsPrivate.InsertCo[top, posChild, chToSplit, negBnd, posBnd, neg, insertCoHint, FALSE].ir, ir];
ir ← CONS[NEW[TOR.IRCreateComp2Rep ← [comp]], ir];
fr ← NEW[TOR.FRSpawnCompsRep ← [comp, splitDirection, chkArgs, negChild, posChild]];
IPCoTab.DestroyComponent2[top.coTab, comp];
top.initialized ← FALSE;
IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?--
}; --SpawnComps
SpawnCompsChk:
PUBLIC
PROC[top: IPTop.Ref, comp: IPCoTab.Component, negChildName, posChildName: Rope.
ROPE, negChildShape, posChildShape:
IP.ShapeRep, splitDirection:
IP.OrientationTypes]
RETURNS [
BOOL]={
IF ~ IPCoTab.CoActive[comp] THEN RETURN [FALSE];
FOR corner: IPCoTab.CornerTypes
IN [sw..nw]
DO
--This restriction may be removed later.
IF IPCoTab.GetCornerChs[comp, corner] # NIL THEN RETURN [FALSE]
ENDLOOP;
IF IPCoTab.GetComponent[top.coTab, negChildName, FALSE] # NIL OR IPCoTab.GetComponent[top.coTab, posChildName, FALSE] # NIL THEN RETURN [FALSE];
RETURN [TRUE]
}; --SpawnCompsChk
SetCompShape:
PUBLIC
PROC[top: IPTop.Ref, comp: IPCoTab.Component, shape:
IP.ShapeRep, chkArgs, keepTrack:
BOOL]
RETURNS [fr, ir:
TOR.RSetCompShape]={
oShape: IP.ShapeRep;
IF chkArgs
AND ~ SetCompShapeChk[comp, shape]
THEN ERROR InvalidArgs[$SetCompShape]; --(1) Check Argument
oShape ← comp.shape;
IF comp.type =
NIL
THEN comp.shape ← shape
ELSE {
coType: REF IP.CoTypeRep ← comp.type;
refShape: REF IP.ShapeRep ← NEW[IP.ShapeRep ← shape];
IPToolBox.OrientShape[refShape, CDOrient.InverseOrient[comp.orient]];
coType.shapeInfo.shape ← refShape;
FOR l:
LIST
OF IPCoTab.Component ← coType.instances, l.rest
UNTIL l =
NIL
DO
l.first.shape ← IPToolBox.CopyShape[refShape, l.first.orient]^
ENDLOOP;};
ir ← NEW[TOR.RSetCompShapeRep ← [comp, oShape, chkArgs]];
fr ← NEW[TOR.RSetCompShapeRep ← [comp, shape, chkArgs]];
top.initialized ← FALSE;
IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?--
}; --SetCompShape
SetCompShapeChk:
PUBLIC
PROC[comp: IPCoTab.Component, shape:
IP.ShapeRep]
RETURNS [
BOOL] ={
shapeConflict:
PROC[inst: IPCoTab.Component]
RETURNS [
BOOL] ={
FOR corner: IPCoTab.CornerTypes
IN [sw..nw]
DO
IF IPCoTab.GetCornerChs[inst, corner] # NIL AND IPToolBox.GetCorner[shape, corner] = NIL THEN RETURN [TRUE]
ENDLOOP;
RETURN [FALSE]
}; --shapeConflict
FOR l: LIST OF REF IP.PinNetRep ← comp.pinNets, l.rest UNTIL l = NIL DO
IF l.first.physicalPins # NIL THEN RETURN [FALSE]
ENDLOOP;
--The above loop should be used. But since its absence is quite benign,
-- will let it be for the time being.
IF comp.type #
NIL
THEN {
FOR l:
LIST
OF IPCoTab.Component ← comp.type.instances, l.rest
UNTIL l =
NIL
DO
IF shapeConflict[l.first] THEN RETURN [FALSE]
ENDLOOP};
RETURN [NOT shapeConflict[comp]]
}; --SetCompShapeChk
FlipT:
PUBLIC
PROC[top: IPTop.Ref, chToBend, attachTo:
IPCTG.Channel, whichEnd:
IPCTG.Side, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRFlipT, ir:
TOR.RComposite] ={
endCh: IPCTG.Channel ← IPCTG.End[chToBend, whichEnd].ch;
endChSide: IPCTG.Side ← IPBasicOps.PTNot[whichEnd];
whichDirection: IPCTG.Side ← IF IPCTG.InCount[endCh, attachTo, endChSide] < IPCTG.InCount[endCh, chToBend, endChSide] THEN neg ELSE pos;
refComp: IPCoTab.Component ← IPCTG.NthComponent[chToBend, IPBasicOps.PTNot[whichDirection], -IPBasicOps.PTToInt[whichEnd]];
compCorner: IPCoTab.CornerTypes ←
IF chToBend.type = hor
THEN IPBasicOps.CTFromPTs[hor: endChSide, ver: whichDirection]
ELSE IPBasicOps.CTFromPTs[hor: whichDirection, ver: endChSide];
prevCornerSp: IPCoTab.CornerSpace ← GetCoCornerSp[refComp, compCorner];
flipTOk:
PROC
RETURNS [
BOOL] ={
tArmIntrsctn: IPCTG.Intersection ← IPCTG.NthIntersection[chToBend, IPBasicOps.PTNot[whichDirection], - IPBasicOps.PTToInt[whichEnd]];
IF tArmIntrsctn = NIL OR tArmIntrsctn.ch = NIL THEN RETURN [FALSE];
IF IPCoTab.GetCornerChs[refComp, compCorner] # NIL THEN RETURN [FALSE];
IF IPCTG.End[chToBend, whichEnd].type # IPCTG.TEnd THEN RETURN [FALSE];
IF ~ IPCTG.ArmOn[endCh, attachTo, endChSide] THEN RETURN [FALSE];
RETURN [TRUE];
}; --flipTOk
--The above are taken almost directly from IPTopEditOpsImpl.FlexKnee and LtoT
IF ~ flipTOk[] THEN ERROR IPTopOps.InvalidArgs[$FlipT]; --(1) Check args
{ir ←
LIST[SetCoCornerSp[refComp, compCorner, IPBasicOps.NuNatVector[0, 0]]]};
--DIRTY TRICK!
--The above is to keep a dummy IPCoTab.CornerSpace in that corner of comp
--to fool IPTopOps.FlexKnee in accepting the argument
fr ← NEW[TOR.FRFlipTRec ← [chToBend, attachTo, whichEnd]]; --(a) Setup fr
ir ← CONS[IPTopOps.FlexKnee[top, chToBend, attachTo, whichEnd, FALSE].ir, ir]; --(b1) Setup ir
ir← CONS[IPTopOps.LtoT[top, chToBend, whichEnd, FALSE].ir, ir]; -- (b2) Setup ir
{ir ←
CONS[SetCoCornerSp[refComp, compCorner, prevCornerSp], ir]};
--DIRTY TRICK!
--Undo the dirty trick above
IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?--
}; --FlipT
FlipTChk:
PUBLIC
PROC[top: IPTop.Ref, chToBend, attachTo:
IPCTG.Channel, whichEnd:
IPCTG.Side]
RETURNS [
BOOL] ={
-- Copied from FlipT above
endCh: IPCTG.Channel ← IPCTG.End[chToBend, whichEnd].ch;
endChSide: IPCTG.Side ← IPBasicOps.PTNot[whichEnd];
whichDirection: IPCTG.Side ← IF IPCTG.InCount[endCh, attachTo, endChSide] < IPCTG.InCount[endCh, chToBend, endChSide] THEN neg ELSE pos;
refComp: IPCoTab.Component ← IPCTG.NthComponent[chToBend, IPBasicOps.PTNot[whichDirection], -IPBasicOps.PTToInt[whichEnd]];
compCorner: IPCoTab.CornerTypes ←
IF chToBend.type = hor
THEN IPBasicOps.CTFromPTs[hor: endChSide, ver: whichDirection]
ELSE IPBasicOps.CTFromPTs[hor: whichDirection, ver: endChSide];
tArmIntrsctn: IPCTG.Intersection ← IPCTG.NthIntersection[chToBend, IPBasicOps.PTNot[whichDirection], - IPBasicOps.PTToInt[whichEnd]];
IF tArmIntrsctn = NIL OR tArmIntrsctn.ch = NIL THEN RETURN [FALSE];
IF IPCoTab.GetCornerChs[refComp, compCorner] # NIL THEN RETURN [FALSE];
IF IPCTG.End[chToBend, whichEnd].type # IPCTG.TEnd THEN RETURN [FALSE];
IF ~ IPCTG.ArmOn[endCh, attachTo, endChSide] THEN RETURN [FALSE];
RETURN [TRUE];
};--FlipTChk
FormZChk:
PUBLIC
PROC[top: IPTop.Ref, comp1, comp2: IPCoTab.Component, zType:
IPCTG.Side]
RETURNS [
BOOL] ={
--Copied from: IPTopEditOpsImpl.FormZ
et: IPCoTab.EdgeTypes ← south;
refCh: IPCTG.Channel ← NIL;
negComp, posComp: IPCoTab.Component;
THROUGH [0..4)
DO
IF IPCoTab.GetPrinCh[comp1, et] = IPCoTab.GetPrinCh[comp2, IPBasicOps.ETRotate[et, 2]]
THEN {refCh ← IPCoTab.GetPrinCh[comp1, et]; EXIT};
et ← IPBasicOps.ETRotate[et];
ENDLOOP;
IF IPBasicOps.ETDirectn[et] = neg
THEN {negComp ← comp2; posComp ← comp1}
ELSE {negComp ← comp1; posComp ← comp2};
IF refCh =
NIL
OR
NOT IPEditPrimitives.FormZChk[refCh, negComp, posComp, zType]
THEN RETURN [FALSE]
ELSE RETURN [TRUE];
}; --FormZChk
--##Strictly Private procedures ##--
GetCoCornerSp:
PROC[co: IPCoTab.Component, ct: IPCoTab.CornerTypes]
RETURNS [IPCoTab.CornerSpace] ={
-- This procedure is specially created to do the dirty trick in FlipT
OPEN coS: co.shape.cornerSpaces;
RETURN[
SELECT ct
FROM
sw => coS.sw,
se => coS.se,
ne => coS.ne,
nw => coS.nw,
ENDCASE => ERROR];
}; --GetCoCornerSp
SetCoCornerSp:
PUBLIC
PROC[co: IPCoTab.Component, ct: IPCoTab.CornerTypes, sp: IPCoTab.CornerSpace]
RETURNS [
REF IPTopOpRecs.IRSetCoCornerSpRec] ={
-- This procedure is specially created to do the dirty trick in FlipT
OPEN coS: co.shape.cornerSpaces;
oSpace: IPCoTab.CornerSpace;
SELECT ct
FROM
sw => {oSpace ← coS.sw; coS.sw ← sp};
se => {oSpace ← coS.se; coS.se ← sp};
ne => {oSpace ← coS.ne; coS.ne ← sp};
nw => {oSpace ← coS.nw; coS.nw← sp};
ENDCASE => ERROR;
RETURN [NEW[IPTopOpRecs.IRSetCoCornerSpRec ← [co, ct, oSpace]]]
}; --SetCoCornerSp
END.