--File: IPTopEditOpsExtraImpl.mesa
Last Edited by: CSChow, January 27, 1985 7:00:32 am PST
DIRECTORY
IP,
IPCTG,
IPCoTab,
IPOrient,
IPTop,
IPToolBox,
IPTopOpRecs,
IPBasicOps,
IPEditPrimitives,
IPTopOpsPrivate,
IPTopOps,
Rope;
IPTopEditOpsExtraImpl: CEDAR PROGRAM
IMPORTS IPBasicOps, IPCTG, IPCoTab, IPEditPrimitives, IPOrient, IPToolBox, IPTopOps, IPTopOpsPrivate
EXPORTS IPTopOps, IPTopOpsPrivate = BEGIN OPEN 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: IPTopOpRecs.FRSpawnComps, ir: IPTopOpRecs.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, original, [0,0], negChild];
posChild ← IPCoTab.CreateComponent2[top.coTab, posChildName, posChildShape, FALSE, 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[IPTopOpRecs.IRDestroyComp2Rep ← [negChild]], ir];
ir ← CONS[NEW[IPTopOpRecs.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[IPTopOpRecs.IRCreateComp2Rep ← [comp]], ir];
fr ← NEW[IPTopOpRecs.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: IPTopOpRecs.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, IPOrient.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[IPTopOpRecs.RSetCompShapeRep ← [comp, oShape, chkArgs]];
fr ← NEW[IPTopOpRecs.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: BOOLFALSE] RETURNS [fr: IPTopOpRecs.FRFlipT, ir: IPTopOpRecs.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[IPTopOpRecs.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.