-- File: IPCoTabImpl.mesa
-- Last Edited by: CSChow, January 27, 1985 6:20:42 am PST
Preas, August 2, 1986 8:41:04 pm PDT
--Note: IPCoTab = ComponentTable
--Documentation will come later after consolidating the design --
DIRECTORY
Imager USING [Context, VEC, MaskStrokeTrajectory, SetGray, MaskFillTrajectory, SetXY, ShowRope],
ImagerPath USING [Trajectory, MoveTo, LineToX, LineToY, LastPoint],
IO,
Rope USING [Equal, Cat, ROPE],
SymTab,
CDOrient,
Misc USING [Rect, RectCreate],
IP,
IPConstants,
IPParams,
IPBasicOps,
IPCTG,
IPTypeTab,
IPNetTab,
IPToolBox,
IPChipRose,
IPPinNets,
IPCoTab;
IPCoTabImpl: CEDAR PROGRAM
IMPORTS IO, Imager, ImagerPath, Rope, SymTab, CDOrient, Misc, IP, IPParams, IPBasicOps, IPToolBox, IPNetTab, IPTypeTab, IPCTG, IPChipRose, IPPinNets
EXPORTS IPCoTab = BEGIN OPEN BO: IPBasicOps, TB: IPToolBox, IPCoTab;
--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.ROPETB.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: BOOLTRUE] ={
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: BOOLTRUE] 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: BOOLTRUE] 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: BOOLTRUE] ={
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.