--These are the top level global operations on IPCTG--
Create:
PUBLIC
PROC[chipRose: IPChipRose.Ref, typeTab: IPTypeTab.Ref, netTab: IPNetTab.Ref]
RETURNS[Ref] = {
coTab: Ref ← NEW[Rep ← [SymTab.Create[]]];
eachInstProc: IPChipRose.EachInstanceAction ={
type: IPTypeTab.CoType ← typeTab.FetchCoType[val.type];
orient: IP.Orientation ← val.orient;
origin: IntVector ←
IF val.origin =
NIL
THEN [IPParams.CoDefaultPosition, IPParams.CoDefaultPosition]
ELSE val.origin^;
active: BOOL ← (val.origin # NIL);
pinNets: IPPinNets.PinNets ← NIL;
convertPinNet:
PROC [netRec: IPChipRose.PinNetRec]
RETURNS [IPPinNets.PinNet] = {
pin: IPTypeTab.Pin ← IPTypeTab.GetPin[type, netRec.pin];
phyPins: LIST OF REF IP.PhysicalPinRep ← IPTypeTab.MakePhysicalPins[type, pin, orient];
RETURN [NEW [IPPinNets.PinNetRep ← [netRec.pin, netTab.FetchNet[netRec.net], NIL, phyPins]]];
}; --convertPinNet
--Now make pinNets
FOR l:
LIST
OF IPChipRose.PinNetRec ← val.pinNets, l.rest
UNTIL l =
NIL
DO
pinNets ← CONS[convertPinNet[l.first], pinNets]
ENDLOOP;
-- Now Create Component
[] ← CreateComponent[coTab, instance, type, orient, pinNets, origin, active];
}; --eachInstProc
chipRose.Instances[eachInstProc];
RETURN[coTab]
}; -- Create--
DestroySelf:
PUBLIC
PROC[coTab: Ref] ={
eachComp: EachComponentAction ={
co.type ← NIL; --Break circularity 1: type -> type.instances -> co
IPPinNets.NilPinNetsNet[co.pinNets]; --Break circularity 2: pinNet.net -> net.pinNets
co.pinNets ← NIL; -- Break circularity 3 : pinNets -> pinNet -> pinNet.owner
}; --eachComp
Components[coTab, eachComp]
};--DestroySelf
DescribeSelf:
PUBLIC
PROC[coTab: Ref, stream:
IO.
STREAM] = {
pCC:
PROC [cc: CornerChannels] ={
IF cc =
NIL
THEN stream.PutF[" ()"]
ELSE stream.PutF[" (%g %g)", IO.rope[cc.hor.name], IO.rope[cc.ver.name]];
}; --pCC
pPN:
PROC[pN: IPPinNets.PinNet] ={
stream.PutF[" %g: %g ", IO.rope[pN.name], IO.refAny[pN.net.name]]; --name, "netName"
TB.PutPhysicalPins[stream, pN.physicalPins];
}; --pPN
pComp: EachComponentAction ={
OPEN pChs: co.prinChannels, cChs: co.cornerChannels;
--(1a) Print name, origin, active,
stream.PutF["%g:\t (%g %g) %g ", IO.rope[co.name], IO.int[co.origin.x], IO.int[co.origin.y], IO.bool[co.active]];
--(1b) Print type.name orient
stream.PutF["%g %g ", IO.rope[IF co.type = NIL THEN "NIL" ELSE co.type.name], IO.int[co.orient]];
--(2a) Print pinNets
stream.PutF["{"];
FOR l: IPPinNets.PinNets ← co.pinNets, l.rest
UNTIL l =
NIL
DO
pPN[l.first]
ENDLOOP;
stream.PutF["}"];
--(2b) Print shape?
IF co.type = NIL THEN IPToolBox.PutShape[stream, NEW[IP.ShapeRep ← co.shape]];
--(3) Print surrounding channes
IF pChs.south =
NIL
OR co.active =
FALSE
--This means ReconstructSelf cannot recover state of undo stack: ??
THEN {stream.PutF["\n"]; RETURN}
ELSE stream.PutF[";\n"];
stream.PutF["\t\t%g %g %g %g", IO.rope[pChs.south.name], IO.rope[pChs.east.name], IO.rope[pChs.north.name], IO.rope[pChs.west.name]];
pCC[cChs.sw]; pCC[cChs.se]; pCC[cChs.ne]; pCC[cChs.nw];
stream.PutF["\n"]
}; --pComp--
stream.PutF["\nBeginCoTab"];
stream.PutF["\n%g \t--Number of components\n", IO.int[Size[coTab]]];
AllComponents[coTab, pComp];
stream.PutF["EndCoTab\n"];
}; --DescribeSelf--
ReconstructSelf:
PUBLIC
PROC[stream:
IO.
STREAM, typeTab: IPTypeTab.Ref, netTab: IPNetTab.Ref, ctg:
IPCTG.Ref ←
NIL]
RETURNS [coTab: Ref] ={
getPinNet:
PROC
RETURNS [pN: IPPinNets.PinNet] ={
name: Rope.ROPE ← TB.GetIdRope[stream];
net: IPPinNets.Net ← netTab.FetchNet[IO.GetRopeLiteral[stream]];
phyPins: LIST OF REF IP.PhysicalPinRep ← TB.GetPhysicalPins[stream]; --Get phyPins
RETURN [NEW[IPPinNets.PinNetRep ← [name, net, NIL, phyPins]]];
}; --getPinNet
getCC:
PROC
RETURNS [cC: CornerChannels] ={
[] ← stream.GetCedarTokenRope;
IF stream.PeekChar = ')
THEN cC ← NIL
ELSE cC ← NEW[CornerChannelsRep ← [ctg.GetChannel[stream.GetID], ctg.GetChannel[stream.GetID]]];
[] ← stream.GetCedarTokenRope;
}; --getCC--
makeCo:
PROC
RETURNS [Component] ={
name: Rope.ROPE ← TB.GetIdRope[stream];
origin: IntVector ← TB.GetIntVector[stream]^;
active: BOOL ← stream.GetBool;
type: IPTypeTab.CoType ← typeTab.FetchCoType[stream.GetID, FALSE];
orient: CDOrient.Orientation ← stream.GetInt;
pinNets: IPPinNets.PinNets ← NIL;
--Get pinNets
TB.EnterBlock[stream];
UNTIL
TB.ExitBlock[stream]
DO
pinNets ← CONS [getPinNet[], pinNets];
ENDLOOP;
--Get shape?
IF type =
NIL
THEN {
shape: IP.ShapeRep ← IPToolBox.GetShape[stream]^;
RETURN [CreateComponent2[coTab, name, shape, active, orient, origin, NIL]]}
ELSE RETURN [CreateComponent[coTab, name, type, orient, pinNets, origin, active]];
}; --makeCo--
insertCo:
PROC[co: Component] ={
south: Channel ← ctg.GetChannel[stream.GetID];
east: Channel ← ctg.GetChannel[stream.GetID];
north: Channel ← ctg.GetChannel[stream.GetID];
west: Channel ← ctg.GetChannel[stream.GetID];
swCh: CornerChannels ← getCC[];
seCh: CornerChannels ← getCC[];
neCh: CornerChannels ← getCC[];
nwCh: CornerChannels ← getCC[];
InsertComponent[co, south, east, north, west, swCh, seCh, neCh, nwCh]
}; --insertCo--
coTab ← NEW[Rep ← [SymTab.Create[]]];
THROUGH [0..stream.GetInt)
DO
comp: Component ← makeCo[];
IF stream.PeekChar = ';
THEN {[] ← stream.GetLineRope}
ELSE LOOP;
IF ctg = NIL THEN {[] ← stream.GetLineRope; LOOP};
insertCo[comp];
ENDLOOP;
IF NOT Rope.Equal[stream.GetID, "EndCoTab"] THEN ERROR;
};--ReconstructSelf--
CheckSelf:
PUBLIC
PROC[coTab: Ref] ={
pCo: EachComponentAction ={
OPEN cP: co.prinChannels, cC: co.cornerChannels, cS: co.shape.cornerSpaces;
IF GetComponent[coTab, co.name] # co THEN ERROR; --Name Conclict--
IF NOT co.active THEN RETURN; -- No need further checking--
IF NOT IPCTG.ComponentOn[cP.south, co, pos] THEN ERROR;
IF NOT IPCTG.ComponentOn[cP.east, co, neg] THEN ERROR;
IF NOT IPCTG.ComponentOn[cP.north, co, neg] THEN ERROR;
IF NOT IPCTG.ComponentOn[cP.west, co, pos] THEN ERROR;
IF cC.sw #
NIL
THEN {
IF cS.sw = NIL THEN ERROR;
IF IPCTG.NthComponent[cC.sw.hor, pos, -1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.sw.ver, pos, -1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.sw.hor, neg, -1] # IPCTG.NthComponent[cC.sw.ver, neg, -1] THEN ERROR;};
IF cC.se #
NIL
THEN {
IF cS.se = NIL THEN ERROR;
IF IPCTG.NthComponent[cC.se.hor, pos, 1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.se.ver, neg, -1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.se.hor, neg, 1] # IPCTG.NthComponent[cC.se.ver, pos, -1] THEN ERROR;};
IF cC.ne #
NIL
THEN {
IF cS.ne = NIL THEN ERROR;
IF IPCTG.NthComponent[cC.ne.hor, neg, 1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.ne.ver, neg, 1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.ne.hor, pos, 1] # IPCTG.NthComponent[cC.ne.ver, pos, 1] THEN ERROR;};
IF cC.nw #
NIL
THEN {
IF cS.nw = NIL THEN ERROR;
IF IPCTG.NthComponent[cC.nw.hor, neg, -1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.nw.ver, pos, 1] # co THEN ERROR;
IF IPCTG.NthComponent[cC.nw.hor, pos, -1] # IPCTG.NthComponent[cC.nw.ver, neg, 1] THEN ERROR;};
};--pCo--
AllComponents[coTab, pCo]
}; --CheckSelf--
PaintSelf:
PUBLIC
PROC [coTab: Ref, context: Imager.Context, xOffset, yOffset:
REAL ← 0.0, scaleFactor:
REAL ← 1.0, coStipple:
CARDINAL ← IPConstants.White, showCoNames, showPhyPinNames:
BOOL ←
TRUE] ={
p: EachComponentAction ={
PaintComponent[co, context, xOffset, yOffset, scaleFactor, coStipple, showCoNames];
IPPinNets.PaintPinNets[co, context, xOffset, yOffset, scaleFactor, showPhyPinNames];
}; --p--
Components[coTab, p];
}; --PaintSelf--
CreateComponent:
PUBLIC
PROC[coTab: Ref, name: Rope.
ROPE, type: IPTypeTab.CoType, orient: CDOrient.Orientation, pinNets: IPPinNets.PinNets ←
NIL, origin: IntVector ← [IPParams.CoDefaultPosition, IPParams.CoDefaultPosition], active:
BOOL ←
TRUE]
RETURNS[co: Component] = {
--assumed pinNets are already properly oriened and coord updated
shape: IP.ShapeRep ← TB.CopyShape[IPTypeTab.GetShape[type], orient]^;
co ← NEW[ComponentRep ← [name: name, origin: origin, active: active, shape: shape, type: type, orient: orient, pinNets: pinNets]];
IF coTab.comps.Insert[name, co]
THEN
NULL
ELSE
ERROR
IP.Error[doubleRegistration, name];
--This always has be done before setting circular pointer, ow. may mess up
IPTypeTab.AddInstance[type, co]; --Set up circular pointer: co.type -> type -> type.instances
IPPinNets.SetPinNetsOwner[pinNets, co]; --Set up circular pointer: co.pinNets-> pinNet.owner
IF active THEN IPPinNets.AddPinNetsToNets[pinNets]; --Set up circular pointer: pinNet.net -> net.pinNets
}; -- CreateComponent--
CreateComponent2:
PUBLIC
PROC[coTab: Ref, name: Rope.
ROPE, shape:
IP.ShapeRep, active:
BOOL, orient: CDOrient.Orientation, origin: IntVector, from: Component ←
NIL]
RETURNS[co: Component] ={
IF from =
NIL
THEN co ← NEW[ComponentRep ← [name: name, origin: origin, active: active, shape: shape, orient: orient]]
ELSE co ← from;
IF co.type # NIL THEN IPTypeTab.AddInstance[co.type, co];
IF coTab.comps.Insert[co.name, co] THEN NULL ELSE ERROR IP.Error[doubleRegistration, name];
}; --CreateComponent2
DestroyComponent2:
PUBLIC
PROC[coTab: Ref, co: Component] = {
IF co.type # NIL THEN IPTypeTab.RemInstance[co.type, co];
IF co.pinNets #
NIL
THEN {
IPPinNets.RemPinNetsFromNets[co.pinNets];
co.pinNets ← NIL};
[] ← coTab.comps.Delete[co.name];
}; --DestroyComponent --
Size:
PUBLIC
PROC[coTab: Ref]
RETURNS[
NAT]= {
RETURN[coTab.comps.GetSize]}; --Size--
CountComponents:
PUBLIC
PROC[coTab: Ref]
RETURNS [active, nonActive:
INT ← 0] ={
action: EachComponentAction ={
IF co.active
THEN active ← active.SUCC
ELSE nonActive ← nonActive.SUCC;
}; --action
AllComponents[coTab, action];
}; --CountComponents
GetComponent:
PUBLIC
PROC[coTab: Ref, name: Rope.
ROPE, raiseError:
BOOL ←
TRUE]
RETURNS[component: Component ←
NIL] ={
findName: EachComponentAction = {
IF Rope.Equal[name, co.name] THEN {component ← co; quit ← TRUE}}; -- findName--
AllComponents[coTab, findName];
IF component = NIL AND raiseError THEN ERROR IP.Error[missingRegistration, Rope.Cat[name, " is not a component name"]];
}; --GetComponent--
Components:
PUBLIC
PROC[coTab: Ref, p: EachComponentAction] = {
p1: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = {co: Component ← NARROW[val]; RETURN[IF co.active THEN p[co] ELSE FALSE]};-- p1--
[] ← coTab.comps.Pairs[p1];
}; -- Components--
AllComponents:
PUBLIC
PROC[coTab: Ref, p: EachComponentAction] = {
p1: SymTab.EachPairAction -- [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] -- = {RETURN[p[NARROW[val, Component]]]};-- p1--
[] ← coTab.comps.Pairs[p1];
}; -- AllComponents--
SetName:
PUBLIC
PROC[coTab: Ref, co: Component, name: Rope.
ROPE] = {
IF co.name = name THEN RETURN;
IF coTab.comps.Fetch[name].found THEN ERROR IP.Error[doubleRegistration, Rope.Cat[name, " has already been used"]];
[] ← coTab.comps.Delete[co.name]; --Remove old name--
co.name ←name;
[] ← coTab.comps.Store[name, co];
}; --SetName --
--These are operations on individual component --
GetDim:
PUBLIC
PROC[co: Component]
RETURNS[x, y:
NAT] ={
IF CDOrient.IncludesOddRot90[co.orient]
THEN [y, x] ← co.shape.dim^
ELSE [x, y] ← co.shape.dim^;
}; --GetDim
DeActivateComponent:
PUBLIC
PROC[co: Component] = {
co.active ← FALSE;
IPPinNets.RemPinNetsFromNets[co.pinNets];
}; --DeActivateComponent
ReActivateComponent:
PUBLIC
PROC[co: Component] = {
co.active ← TRUE;
IPPinNets.AddPinNetsToNets[co.pinNets];
};--ReActivateComponent
GetBRect:
PUBLIC
PROC[co: Component]
RETURNS[Misc.Rect] ={
dimX, dimY: NAT;
[dimX, dimY] ← GetDim[co];
RETURN[Misc.RectCreate[co.origin.x, co.origin.y, co.origin.x + dimX, co.origin.y + dimY]]
}; --GetBRect--
GetCornerRects:
PUBLIC
PROC[co: Component, crop:
INT ← 1]
RETURNS[sw, se, ne, nw: Misc.Rect ←
NIL] ={
swCS, seCS, neCS, nwCS: CornerSpace;
origin: IntVector ← co.origin;
dimX, dimY: NAT;
[dimX, dimY] ← GetDim[co];
[swCS, seCS, neCS, nwCS] ← GetCornerSps[co];
IF swCS # NIL THEN sw ← Misc.RectCreate[origin.x, origin.y, origin.x + swCS.x - crop, origin.y + swCS.y - crop];
IF seCS # NIL THEN se ← Misc.RectCreate[origin.x + dimX - seCS.x + crop, origin.y, origin.x + dimX, origin.y + seCS.y - crop];
IF neCS # NIL THEN ne ← Misc.RectCreate[origin.x+ dimX - neCS.x + crop, origin.y+dimY - neCS.y + crop, origin.x+ dimX, origin.y+dimY];
IF nwCS# NIL THEN nw ← Misc.RectCreate[origin.x, origin.y + dimY - nwCS.y + crop, origin.x + nwCS.x - crop, origin.y + dimY];
}; --GetCornerRect--
FindEdgeType:
PUBLIC
PROC[co: Component, ch:
IPCTG.Channel]
RETURNS [EdgeTypes] ={
et: EdgeTypes ← south;
THROUGH [0..4)
DO
IF GetPrinCh[co, et] = ch THEN RETURN [et];
et ← BO.ETRotate[et];
ENDLOOP;
ERROR IP.Error[callingError, Rope.Cat[IPCTG.GetName[ch], " is not a principal channel of ", co.name]];
}; --FindEdgeType--
GetPrinCh:
PUBLIC
PROC[co: Component, et: EdgeTypes]
RETURNS [Channel] ={
OPEN cPC: co.prinChannels;
SELECT et
FROM
south => RETURN [cPC.south];
east => RETURN [cPC.east];
north => RETURN [cPC.north];
west => RETURN [cPC.west];
ENDCASE => ERROR;}; -- GetPrinCh--
SetPrinCh:
PUBLIC
PROC[co: Component, et: EdgeTypes, ch: Channel] ={
OPEN cPC: co.prinChannels;
SELECT et
FROM
south => cPC.south ← ch;
east => cPC.east ← ch;
north => cPC.north ← ch;
west => cPC.west ← ch;
ENDCASE => ERROR;}; -- SetPrinCh--
FindCornerType:
PUBLIC
PROC[co: Component, ch:
IPCTG.Channel]
RETURNS [CornerTypes] ={
ct: CornerTypes ← sw;
THROUGH [0..4)
DO
IF GetCornerChFor[co, ct, ch.type] = ch THEN RETURN [ct];
ct ← BO.CTRotate[ct];
ENDLOOP;
ERROR IP.Error[callingError, Rope.Cat[IPCTG.GetName[ch], " is not a corner channel of ", co.name]];
}; --FindCornerType--
GetCornerChs:
PUBLIC
PROC[co: Component, ct: CornerTypes]
RETURNS [CornerChannels] ={
OPEN cCC: co.cornerChannels;
SELECT ct
FROM
sw => RETURN [cCC.sw];
se => RETURN [cCC.se];
ne => RETURN [cCC.ne];
nw => RETURN [cCC.nw];
ENDCASE => ERROR;}; -- GetCornerChs--
SetCornerChs:
PUBLIC
PROC[co: Component, ct: CornerTypes, cc: CornerChannels] ={
OPEN cCC: co.cornerChannels;
SELECT ct
FROM
sw => cCC.sw ← cc;
se => cCC.se ← cc;
ne => cCC.ne ← cc;
nw => cCC.nw ← cc;
ENDCASE => ERROR;}; -- SetCornerChs--
GetCornerChFor: PUBLIC PROC[co: Component, ct: CornerTypes, ot: BO.OrientationTypes] RETURNS [IPCTG.Channel] = {RETURN [CCGetCh[GetCornerChs[co, ct], ot]]}; --GetCornerChFor--
SetCornerChs2:
PUBLIC
PROC[co: Component, ct: CornerTypes, horCh, verCh:
IPCTG.Channel] ={
cornerChs: CornerChannels;
IF (cornerChs ← GetCornerChs[co, ct]) =
NIL
THEN SetCornerChs[co, ct, NEW[CornerChannelsRep ← [horCh, verCh]]]
ELSE {cornerChs.hor ← horCh; cornerChs.ver ← verCh};
}; --SetCornerChs2--
GetCornerSp:
PUBLIC
PROC[co: Component, ct: CornerTypes]
RETURNS [cs: CornerSpace] ={
OPEN coS: co.shape.cornerSpaces;
cs
← SELECT ct
FROM
sw => coS.sw,
se => coS.se,
ne => coS.ne,
nw => coS.nw,
ENDCASE => ERROR;
IF cs #
NIL
AND CDOrient.IncludesOddRot90[co.orient]
THEN cs ← NEW [NatVector ← [cs.y, cs.x]]; --else RETURN[cs]
}; --GetCornerSp --
GetCornerSps:
PUBLIC PROC[co: Component]
RETURNS [sw, se, ne, nw: CornerSpace] ={
OPEN coS: co.shape.cornerSpaces;
flipXY: BOOL ← CDOrient.IncludesOddRot90[co.orient];
IF (sw ← coS.sw) #
NIL
AND flipXY
THEN sw ← NEW [NatVector ← [sw.y, sw.x]]; --else just sw
IF (se ← coS.se) #
NIL
AND flipXY
THEN se ← NEW [NatVector ← [se.y, se.x]]; --else just se
IF (ne ← coS.ne) #
NIL
AND flipXY
THEN ne ← NEW [NatVector ← [ne.y, ne.x]]; --else just ne
IF (nw ← coS.nw) #
NIL
AND flipXY
THEN nw ← NEW [NatVector ← [nw.y, nw.x]]; --else just nw
}; --GetCornerSps
GetChOnSide:
PUBLIC
PROC[co: Component, side:
IP.PinSideType, useParrallel:
BOOL]
RETURNS [
IPCTG.Channel] ={
OPEN coP: co.prinChannels, coC: co.cornerChannels;
SELECT side
FROM
south => RETURN [coP.south];
east => RETURN [coP.east];
north => RETURN [coP.north];
west => RETURN [coP.west];
swHor =>
IF coC.sw =
NIL
THEN RETURN [IF useParrallel THEN coP.south ELSE coP.west]
ELSE RETURN [coC.sw.hor];
seHor =>
IF coC.se =
NIL
THEN RETURN [IF useParrallel THEN coP.south ELSE coP.east]
ELSE RETURN [coC.se.hor];
neHor =>
IF coC.ne =
NIL
THEN RETURN [IF useParrallel THEN coP.north ELSE coP.east]
ELSE RETURN [coC.ne.hor];
nwHor =>
IF coC.nw =
NIL
THEN RETURN [IF useParrallel THEN coP.north ELSE coP.west]
ELSE RETURN [coC.nw.hor];
swVer =>
IF coC.sw =
NIL
THEN RETURN [IF useParrallel THEN coP.west ELSE coP.south]
ELSE RETURN [coC.sw.ver];
seVer =>
IF coC.se =
NIL
THEN RETURN [IF useParrallel THEN coP.east ELSE coP.south]
ELSE RETURN [coC.se.ver];
neVer =>
IF coC.ne =
NIL
THEN RETURN [IF useParrallel THEN coP.east ELSE coP.north]
ELSE RETURN [coC.ne.ver];
nwVer =>
IF coC.nw =
NIL
THEN RETURN [IF useParrallel THEN coP.west ELSE coP.north]
ELSE RETURN [coC.nw.ver];
interior, unknown => RETURN [NIL];
ENDCASE => ERROR;
}; --GetChOnSide
PaintComponent:
PUBLIC
PROC [co: Component, context: Imager.Context, xOffset, yOffset:
REAL ← 0.0, scaleFactor:
REAL ← 1.0, stipple:
CARDINAL ← IPConstants.Black, showName:
BOOL ←
TRUE] ={
path: ImagerPath.Trajectory;
sw, se, ne, nw: CornerSpace;
originX, originY: REAL;
dimX, dimY: REAL;
[originX, originY] ← co.origin;
originX ← xOffset + (originX * scaleFactor);
originY ← yOffset + (originY *scaleFactor);
[dimX, dimY] ← GetDim[co];
dimX ← dimX * scaleFactor;
dimY ← dimY * scaleFactor;
[sw, se, ne, nw] ← GetCornerSps[co];
IF sw #
NIL
THEN {
path ← ImagerPath.MoveTo[[originX, originY + sw.y * scaleFactor]];
path ← ImagerPath.LineToX[path, originX + sw.x * scaleFactor];
path ← ImagerPath.LineToY[path, originY]} ELSE {
path ← ImagerPath.MoveTo[[originX, originY]]};
IF se #
NIL
THEN {
path ← ImagerPath.LineToX[path, originX+ dimX - se.x * scaleFactor];
path ← ImagerPath.LineToY[path, originY + se.y * scaleFactor];
path ← ImagerPath.LineToX[path, originX + dimX];} ELSE{
path ← ImagerPath.LineToX[path, originX + dimX];};
IF ne #
NIL
THEN {
path ← ImagerPath.LineToY[path, originY +dimY - ne.y * scaleFactor];
path ← ImagerPath.LineToX[path, originX + dimX - ne.x * scaleFactor];
path ← ImagerPath.LineToY[path, originY + dimY];} ELSE {
path ← ImagerPath.LineToY[path, originY + dimY]};
IF nw #
NIL
THEN {
path ← ImagerPath.LineToX[path, originX + nw.x * scaleFactor];
path ← ImagerPath.LineToY[path, originY + dimY - nw.y * scaleFactor];
path ← ImagerPath.LineToX[path, originX];} ELSE {
path ← ImagerPath.LineToX[path, originX]};
IF sw #
NIL
THEN {
path ← ImagerPath.LineToY[path, originY + sw.y * scaleFactor];} ELSE {
path ← ImagerPath.LineToY[path, originY]};
IF stipple = IPConstants.White
THEN Imager.MaskStrokeTrajectory[context, path]
ELSE {Imager.SetGray[context, stipple]; Imager.MaskFillTrajectory[context, path];};
IF showName
THEN {
offSet: REAL ← (IPParams.PinMaxDistFromEdge + scaleFactor * IPParams.PhyPinRectSize);
v: Imager.VEC;
v ← ImagerPath.LastPoint[path];
Imager.SetXY[context, [v.x + offSet, v.y + offSet]];
Imager.ShowRope[context, co.name]};
}; --PaintComponent--
InsertComponent:
PUBLIC
PROC [co: Component, south, east, north, west: Channel, sw, se, ne,nw: CornerChannels ←
NIL] = {
negBnd, posBnd: Channel;
co.prinChannels ← [south, east, north, west];
co.cornerChannels ← [sw, se, ne, nw];
negBnd ← IF sw # NIL THEN sw.ver ELSE west;
posBnd ← IF se # NIL THEN se.ver ELSE east;
IPCTG.InsertCoBetween[south, co, negBnd, posBnd, pos];
negBnd ← IF se # NIL THEN se.hor ELSE south;
posBnd ← IF ne # NIL THEN ne.hor ELSE north;
IPCTG.InsertCoBetween[east, co, negBnd, posBnd, neg];
negBnd ← IF nw # NIL THEN nw.ver ELSE west;
posBnd ← IF ne # NIL THEN ne.ver ELSE east;
IPCTG.InsertCoBetween[north, co, negBnd, posBnd, neg];
negBnd ← IF sw # NIL THEN sw.hor ELSE south;
posBnd ← IF nw # NIL THEN nw.hor ELSE north;
IPCTG.InsertCoBetween[west, co, negBnd, posBnd, pos];
IF sw # NIL THEN {IPCTG.InsertCoAt[sw.hor, co, pos, pos]; IPCTG.InsertCoAt[sw.ver, co, pos, pos]};
IF se # NIL THEN {IPCTG.InsertCoAt[se.hor, co, pos, neg]; IPCTG.InsertCoAt[se.ver, co, neg, pos]};
IF ne # NIL THEN {IPCTG.InsertCoAt[ne.hor, co, neg, neg]; IPCTG.InsertCoAt[ne.ver, co, neg, neg]};
IF nw # NIL THEN {IPCTG.InsertCoAt[nw.hor, co, neg, pos]; IPCTG.InsertCoAt[nw.ver, co, pos, neg]};
}; --InsertComponent --
PositionComponent:
PUBLIC
PROC[co: Component, southCoeff, eastCoeff, northCoeff, westCoeff:
NAT ← 0] = {
OPEN cPC: co.prinChannels, cCC: co.cornerChannels;
xMin, yMin, xMax, yMax, xP, yP: INT;
IF (southCoeff + northCoeff) = 0 THEN {southCoeff ← northCoeff ← 1};
IF (eastCoeff + westCoeff) = 0 THEN {eastCoeff ← westCoeff ← 1};
yMin ← FromEdge[co, south, cPC.south.coord + cPC.south.width/2];
xMax ← FromEdge[co, east, cPC.east.coord - cPC.east.width/2];
yMax ← FromEdge[co, north, cPC.north.coord - cPC.north.width/2];
xMin ← FromEdge[co, west, cPC.west.coord + cPC.west.width/2];
IF cCC.sw #
NIL
THEN {
[xP, yP] ← FromCorner[co, sw, cCC.sw.ver.coord + cCC.sw.ver.width/2, cCC.sw.hor.coord + cCC.sw.hor.width/2];
xMin ← MAX[xP, xMin];
yMin ← MAX[yP, yMin]};
IF cCC.se #
NIL
THEN {
[xP, yP] ← FromCorner[co, se, cCC.se.ver.coord - cCC.se.ver.width/2, cCC.se.hor.coord + cCC.se.hor.width/2];
xMax ← MIN[xP, xMax];
yMin ← MAX[yP, yMin]};
IF cCC.ne #
NIL
THEN {
[xP, yP] ← FromCorner[co, ne, cCC.ne.ver.coord - cCC.ne.ver.width/2, cCC.ne.hor.coord - cCC.ne.hor.width/2];
xMax ← MIN[xP, xMax];
yMax ← MIN[yP, yMax]};
IF cCC.nw #
NIL
THEN {
[xP, yP] ← FromCorner[co, nw, cCC.nw.ver.coord + cCC.nw.ver.width/2, cCC.nw.hor.coord - cCC.nw.hor.width/2];
xMin ← MAX[xP, xMin];
yMax ← MIN[yP, yMax]};
IF eastCoeff = westCoeff
THEN xP ← (xMin+xMax)/2
ELSE xP ← (eastCoeff * xMin + westCoeff * xMax)/ (eastCoeff + westCoeff);
IF southCoeff = northCoeff
THEN yP ← (yMin+yMax)/2
ELSE yP ← (southCoeff * yMin + northCoeff * yMax)/ (southCoeff + northCoeff);
co.origin ← IntVector[xP, yP];
}; -- PositionComponent--
ConstrainChannels:
PUBLIC
PROC[co: Component, chs:
IPCTG.Ref] = {
south, east, north, west: Channel;
dimX, dimY: NAT;
[dimX, dimY] ← GetDim[co];
[south, east, north, west] ← co.prinChannels;
IPCTG.ConstrainChannels[chs, south, north, dimY];
IPCTG.ConstrainChannels[chs, west, east, dimX];
{
OPEN co.cornerChannels;
swCS, seCS, neCS, nwCS: CornerSpace;
[swCS, seCS, neCS, nwCS] ← GetCornerSps[co];
IF sw #
NIL
THEN{
IF ne #
NIL
THEN {
IPCTG.ConstrainChannels[chs, sw.hor, ne.hor, dimY - swCS.y - neCS.y];
IPCTG.ConstrainChannels[chs, sw.ver, ne.ver, dimX - swCS.x - neCS.x]};
IF se # NIL THEN IPCTG.ConstrainChannels[chs, sw.ver, se.ver, dimX - swCS.x - seCS.x];
IF nw # NIL THEN IPCTG.ConstrainChannels[chs, sw.hor, nw.hor, dimY - swCS.y - nwCS.y];
IPCTG.ConstrainChannels[chs, sw.ver, east, dimX - swCS.x];
IPCTG.ConstrainChannels[chs, sw.hor, north, dimY - swCS.y]};
IF se #
NIL
THEN{
IF nw #
NIL
THEN {
IPCTG.ConstrainChannels[chs, se.hor, nw.hor, dimY - seCS.y - nwCS.y]};
IF ne # NIL THEN IPCTG.ConstrainChannels[chs, se.hor, ne.hor, dimY - seCS.y - neCS.y];
IPCTG.ConstrainChannels[chs, se.hor, north, dimY - seCS.y];
IPCTG.ConstrainChannels[chs, west, se.ver, dimX - seCS.x];
};
IF nw #
NIL
THEN{
IF se #
NIL
THEN {
IPCTG.ConstrainChannels[chs, nw.ver, se.ver, dimX - nwCS.x - seCS.x]};
IF ne # NIL THEN IPCTG.ConstrainChannels[chs, nw.ver, ne.ver, dimX - nwCS.x - neCS.x];
IPCTG.ConstrainChannels[chs, south, nw.hor, dimY - nwCS.y];
IPCTG.ConstrainChannels[chs, nw.ver, east, dimX - nwCS.x];
};
IF ne #
NIL
THEN{
IPCTG.ConstrainChannels[chs, south, ne.hor, dimY - neCS.y];
IPCTG.ConstrainChannels[chs, west, ne.ver, dimX - neCS.x]};
}
}; -- ConstrainChannels--
FromEdge:
PUBLIC
PROC[co: Component, edge: EdgeTypes, edgeAt:
INT]
RETURNS [coord:
INT] ={
SELECT edge
FROM
south => RETURN [edgeAt];
east => RETURN [edgeAt - GetDim[co].x];
north => RETURN [edgeAt - GetDim[co].y];
west => RETURN [edgeAt];
ENDCASE => ERROR;
};--FromEdge--
FromCorner:
PUBLIC
PROC[co: Component, corner: CornerTypes, CornerAtX, CornerAtY:
INT]
RETURNS [xCoord, yCoord:
INT] ={
cornerX, cornerY: NAT;
[cornerX, cornerY] ← GetCornerSp[co, corner]^;
SELECT corner
FROM
sw => {xCoord ← CornerAtX - cornerX; yCoord ← CornerAtY - cornerY;};
se => {xCoord ← CornerAtX - GetDim[co].x + cornerX; yCoord ← CornerAtY - cornerY;};
ne => {xCoord ← CornerAtX - GetDim[co].x + cornerX; yCoord ← CornerAtY - GetDim[co].y + cornerY;};
nw => {xCoord ← CornerAtX - cornerX; yCoord ← CornerAtY - GetDim[co].y + cornerY;};
ENDCASE => ERROR;
}; --FromCorner--
CCGetCh: PUBLIC PROC[cc: CornerChannels, ot: BO.OrientationTypes] RETURNS [IPCTG.Channel] = {IF cc = NIL THEN RETURN [NIL] ELSE RETURN [IF ot = hor THEN cc.hor ELSE cc.ver];}; --CCGetCh--
OrientCoShapeChk:
PUBLIC
PROC[co:
REF
IP.ComponentRep, operation:
IP.Orientation]
RETURNS [
BOOL] ={
IF (operation = CDOrient.original)
OR ~ co.active
THEN
RETURN [
TRUE];
-- (i) do nothing
-- (ii)Can always rotate a non-placed component
FOR corner: CornerTypes
IN [sw..nw]
DO
IF GetCornerChs[co, corner] #NIL AND GetCornerSp[co, BO.CTOrient[corner, operation]] = NIL THEN RETURN [FALSE]
ENDLOOP;
RETURN [TRUE]
}; --OrientCoShapeChk
OrientCoShape:
PUBLIC PROC[co:
REF
IP.ComponentRep, operation:
IP.Orientation] ={
OPEN cSC: co.shape.cornerSpaces;
--(1) Do Rotate90
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← co.shape.cornerSpaces;
SELECT (operation/2)
MOD 4
FROM
0 => NULL;
1, -3 => {cSC.sw ← nw; cSC.se ← sw; cSC.ne ← se; cSC.nw ← ne};
2, -2 => {cSC.sw ← ne; cSC.se ← nw; cSC.ne ← sw; cSC.nw ← se};
3, -1 => {cSC.nw ← sw; cSC.sw ← se; cSC.se ← ne; cSC.ne ← nw};
ENDCASE => ERROR;
-- (2) Do MirrorX
IF CDOrient.IncludesMirrorX[operation]
THEN {
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← co.shape.cornerSpaces;
--(a) Swap bottom
cSC.sw ← se;
cSC.se ← sw;
--(b) Swap top
cSC.nw ← ne;
cSC.ne ← nw;
}; --endIF
}; --OrientCoShape
END.