--File: IPToolBoxImpl.mesa
Last Edited by: Preas, August 2, 1986 10:09:59 am PDT
DIRECTORY
CD,
CDBasics,
CDInstances,
CDSymbolicObjects,
FileNames,
IO,
IP,
IPBasicOps,
IPOrient,
IPToolBox,
Misc,
Rope,
RTBasic,
RTStructure;
IPToolBoxImpl: CEDAR PROGRAM
IMPORTS CDBasics, CDInstances, CDSymbolicObjects, FileNames, IO, IPBasicOps, IPOrient, Misc, Rope, RTStructure
EXPORTS IPToolBox = BEGIN OPEN BO: IPBasicOps, IPToolBox;
IPPinsFromCDPins: PUBLIC PROC [cdObj: CD.Object]
RETURNS [iPins: LIST OF REF IP.PinRep ← NIL] ={
EachPin: CDSymbolicObjects.InstEnumerator ~ {
rect: CD.Rect ← CDInstances.InstRectI[inst];
pLoc: CD.Position ← CDBasics.BaseOfRect[rect];
pSize: CD.Position ← CDBasics.SizeOfRect[rect];
coord: IntVector ← [pLoc.x + pSize.x/2, pLoc.y + pSize.y/2]; --use the center
phyPins: PhysicalPins ← LIST[NEW[IP.PhysicalPinRep ← [coord]]];
pin: REF IP.PinRep ← NEW[IP.PinRep ← [CDSymbolicObjects.GetName[inst], phyPins]];
iPins ← CONS[pin, iPins];
};
[] ← CDSymbolicObjects.EnumerateSymbolicObs[cdObj, EachPin];
}; --IPPinsFromCDPins
-- IPPinFromCDPin: PROC [cdPin: CD.Instance] RETURNS [REF IP.PinRep] = {
-- physicalPins: PROC RETURNS [phyPins: PhysicalPins ← NIL] = {
-- FOR pPins: LIST OF REF CDPins.PhysicalPin ← cdPin.physicalPin, pPins.rest UNTIL pPins = NIL DO
-- pRect: CD.Rect ← pPins.first.rect;
-- coord: IntVector ← [(pRect.x1 + pRect.x2)/2, (pRect.y1 + pRect.y2)/2];
-- phyPins ← CONS[NEW[IP.PhysicalPinRep ← [coord]], phyPins];
-- ENDLOOP;
-- };
--physicalPins
-- RETURN [NEW[IP.PinRep ← [cdPin.pinName, physicalPins[]]]]
-- };
--IPPinFromCDPin
MakeIPPins: PUBLIC PROC[ipPins: LIST OF REF IP.PinRep, origin: IntVector ← [0, 0], coShape: REF IP.ShapeRep ← NIL, cutOff: NAT ← 0] RETURNS [newPins: LIST OF REF IP.PinRep ← NIL] ={
makePhyPin: PROC [phyPin: REF IP.PhysicalPinRep] RETURNS [REF IP.PhysicalPinRep] = {
coord: IntVector ← [phyPin.coord.x - origin.x, phyPin.coord.y - origin.y];
side: IP.PinSideType ← NearestSide[coShape, coord, cutOff].side;
RETURN [NEW[IP.PhysicalPinRep ← [coord, side, phyPin.active]]];
}; --makePhyPin
makeIPPins: PROC[ipPin: REF IP.PinRep] RETURNS [REF IP.PinRep] ={
phyPins: PhysicalPins ← NIL;
FOR l: PhysicalPins ← ipPin.physicalPins, l.rest UNTIL l = NIL DO
phyPins ← CONS[makePhyPin[l.first], phyPins];
ENDLOOP;
RETURN [NEW[IP.PinRep ← [ipPin.name, phyPins, ipPin.auxInfo]]]
}; --makeIPPins
WHILE ipPins # NIL DO
newPins ← CONS[makeIPPins[ipPins.first], newPins];
ipPins ← ipPins.rest;
ENDLOOP;
}; --MakeIPPins
MakeIPPinsFromStructure: PUBLIC PROC[object: RTStructure.Object, origin: IntVector ← [0, 0], coShape: REF IP.ShapeRep ← NIL, cutOff: NAT ← 0] RETURNS [newPins: LIST OF REF IP.PinRep ← NIL] ={
MakeIPPins: RTStructure.EachObjectPinAction ={
MakePhyPin: RTStructure.EachPhysicalPinAction = {
coord: IntVector ← RTStructure.PosOfObjectPin[object, pPin];
side: IP.PinSideType ← NearestSide[coShape, coord, cutOff].side;
phyPins ← CONS[NEW[IP.PhysicalPinRep ← [coord, side, TRUE]], phyPins];
}; --makePhyPin
phyPins: PhysicalPins ← NIL;
[] ← RTStructure.EnumeratePhysicalPins[oPin, MakePhyPin];
newPins ← CONS[NEW[IP.PinRep ← [oPin.name, phyPins, NIL]], newPins];
}; --MakeIPPins
[] ← RTStructure.EnumerateObjectPins[object, MakeIPPins];
}; --MakeIPPinsFromStructure
SSideToPSide: PROC [sSide: RTBasic.SideOrNone] RETURNS [pSide: IP.PinSideType] ~ {
pSide ← SELECT sSide FROM
bottom => south,
right => east,
top => north,
left => west,
ENDCASE => unknown};
NearestSide: PUBLIC PROC [shape: REF IP.ShapeRep, point: IntVector, cutOff: NAT ← 0] RETURNS [inShape: BOOL, side: IP.PinSideType] ={
minDist: INTLAST[INT];
--(1) Check if point is in shape
inShape ← Misc.RectContainPt[GetBRect[shape], point.x, point.y];
FOR corner: IP.CornerTypes IN [sw..nw] DO
IF Misc.RectContainPt[GetCornerRect[shape, corner], point.x, point.y]
THEN inShape ← FALSE;
ENDLOOP;
--(2) Now find nearest side (this is not very efficient but is ok?)
FOR pSide: IP.PinSideType IN [south..nwVer] DO
newDist: INT ← DistFromSide[shape, point, pSide];
IF newDist < minDist THEN {minDist ← newDist; side ← pSide};
ENDLOOP;
IF minDist > cutOff THEN side ← interior;
}; --NearestSide
DistFromSide: PUBLIC PROC[shape: REF IP.ShapeRep, point: IntVector, side: IP.PinSideType] RETURNS [INT] ={
ptCoord, ptProj, sdCoord: INT;
sdIntl: Misc.Interval;
rect: Misc.Rect;
--Algorithm: IF ptProj IN sdIntl
--THEN distance = ABS[ptCoord - sdCoord]
--ELSE (also for any other patho cases) distance = LAST[INT]
--(0) For patho cases simply return infinity
IF shape = NIL THEN RETURN [LAST[INT]];
--(1) Compute ptCoord, ptProj
SELECT side FROM
south, north, swHor, seHor, neHor, nwHor => {ptProj ← point.x; ptCoord ← point.y};
east, west, swVer, seVer, neVer, nwVer => {ptProj ← point.y; ptCoord ← point.x};
interior, unknown => RETURN [LAST [INT]]; -- no need to do anything
ENDCASE => ERROR;
--(3) Compute sdCoord and sdIntl
IF side IN [south..west]
THEN {
rect ← GetBRect[shape];
SELECT side FROM
south => {sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, sw]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, se]]];};
east => {sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, se]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, ne]]];};
north => {sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, ne]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, nw]]];};
west => {sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, nw]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, sw]]];};
ENDCASE => ERROR;
}
ELSE {
SELECT side FROM
swHor => {rect ← GetCornerRect[shape, sw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];};
seHor => {rect ← GetCornerRect[shape, se, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];};
neHor => {rect ← GetCornerRect[shape, ne, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];};
nwHor => {rect ← GetCornerRect[shape, nw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];};
swVer => {rect ← GetCornerRect[shape, sw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];};
seVer => {rect ← GetCornerRect[shape, se, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];};
neVer => {rect ← GetCornerRect[shape, ne, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];};
nwVer => {rect ← GetCornerRect[shape, nw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];};
ENDCASE => ERROR;
};
IF Misc.IntlContainPt[sdIntl, ptProj]
THEN RETURN [ABS[ptCoord - sdCoord]]
ELSE RETURN [LAST[INT]];
}; --DistFromSide
GetCorner: PUBLIC PROC [shape: IP.ShapeRep, corner: IP.CornerTypes] RETURNS [REF IP.NatVector] ={
-- REMARK: Here is okay to use 'IP.ShapeRep' as argument instead of `REF IP.ShapeRep'
-- because callers do not intend to modify shape. Remember that parameters are pass by
-- value in Cedar
SELECT corner FROM
sw => RETURN [shape.cornerSpaces.sw];
se => RETURN [shape.cornerSpaces.se];
ne => RETURN [shape.cornerSpaces.ne];
nw => RETURN [shape.cornerSpaces.nw];
ENDCASE => ERROR;
};--GetCorner
GetBRect: PUBLIC PROC[shape: REF IP.ShapeRep, origin: IntVector ← [0, 0]] RETURNS [Misc.Rect] ={
IF shape = NIL THEN RETURN [NIL];
RETURN[Misc.RectCreate[origin.x, origin.y, origin.x + shape.dim.x, origin.y + shape.dim.y ]]
}; --GetBRect
GetCornerRect: PUBLIC PROC[shape: REF IP.ShapeRep, corner: IP.CornerTypes, origin: IntVector ← [0, 0], crop: INT ← 1] RETURNS [Misc.Rect] ={
cSpace: REF IP.NatVector ← GetCorner[shape^, corner];
IF cSpace = NIL THEN RETURN [NIL];
BEGIN
OPEN s: shape.cornerSpaces;
SELECT corner FROM
sw => RETURN [Misc.RectCreate[origin.x, origin.y, origin.x + s.sw.x - crop, origin.y + s.sw.y - crop]];
se => RETURN [Misc.RectCreate[origin.x + shape.dim.x - s.se.x + crop, origin.y, origin.x + shape.dim.x, origin.y + s.se.y - crop]] ;
ne => RETURN [Misc.RectCreate[origin.x+ shape.dim.x - s.ne.x + crop, origin.y+shape.dim.y - s.ne.y + crop, origin.x+ shape.dim.x, origin.y+shape.dim.y]];
nw => RETURN [Misc.RectCreate[origin.x, origin.y + shape.dim.y - s.nw.y + crop, origin.x + s.nw.x - crop, origin.y + shape.dim.y]];
ENDCASE => ERROR;
END;
};--GetCornerRect
GetCornerRects: PUBLIC PROC[shape: REF IP.ShapeRep, origin: IntVector ← [0, 0], crop: INT ← 1] RETURNS [sw, se, ne, nw: Misc.Rect ← NIL] ={
IF shape = NIL THEN RETURN;
BEGIN OPEN s: shape.cornerSpaces;
IF s.sw # NIL THEN sw ← Misc.RectCreate[origin.x, origin.y, origin.x + s.sw.x - crop, origin.y + s.sw.y - crop];
IF s.se # NIL THEN se ← Misc.RectCreate[origin.x + shape.dim.x - s.se.x + crop, origin.y, origin.x + shape.dim.x, origin.y + s.se.y - crop];
IF s.ne # NIL THEN ne ← Misc.RectCreate[origin.x+ shape.dim.x - s.ne.x + crop, origin.y+shape.dim.y - s.ne.y + crop, origin.x+ shape.dim.x, origin.y+shape.dim.y];
IF s.nw # NIL THEN nw ← Misc.RectCreate[origin.x, origin.y + shape.dim.y - s.nw.y + crop, origin.x + s.nw.x - crop, origin.y + shape.dim.y];
END;
};--GetCornerRects
CopyShape: PUBLIC PROC[oShape: REF IP.ShapeRep, orient: CD.Orientation] RETURNS [nShape: REF IP.ShapeRep] ={
nShape ← BO.Copy1Shape[oShape];
OrientShape[nShape, orient];
}; --CopyShape
OrientShape: PUBLIC PROC[shape: REF IP.ShapeRep, orient: IP.Orientation] ={
--Decompose orient into its basis and calls MirrorXShape and Rotate90Shape
IF IPOrient.IncludesMirrorX[orient] THEN MirrorXShape[shape];
Rotate90Shape[shape, IPOrient.OrientD2[orient]];
}; --OrientShape
MirrorXShape: PUBLIC PROC[shape: REF IP.ShapeRep] ={
--modifies shape: (shape.dim <=> shape.dim; shape.sw <=> shape.se; shape.ne <=> shape.nw)
OPEN sC: shape.cornerSpaces;
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← shape.cornerSpaces;
--(1) Swap bottom
sC.sw ← se;
sC.se ← sw;
--(2) Swap top
sC.nw ← ne;
sC.ne ← nw;
};--MirrorXShape
Rotate90Shape: PUBLIC PROC [shape: REF IP.ShapeRep, numberOfRot: INT ← 1] ={
modifies shape: if numberOfRot = 1 then
--(shape.dim <=> shape.dim; se ← sw, ne ← se, nw ← ne, sw← nw)
--numberOfRot can be any positive or negative
OPEN sC: shape.cornerSpaces;
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← shape.cornerSpaces;
SELECT numberOfRot MOD 4 FROM
0 => NULL;
1, -3 => {sC.sw ← nw; sC.se ← sw; sC.ne ← se; sC.nw ← ne};
2, -2 => {sC.sw ← ne; sC.se ← nw; sC.ne ← sw; sC.nw ← se};
3, -1 => {sC.nw ← sw; sC.sw ← se; sC.se ← ne; sC.ne ← nw};
ENDCASE => ERROR;
}; --Rotate90Shape
--Simple parsing routines
ParseError: PUBLIC ERROR [reason: ATOM, at: REF] = CODE;
GetIdRope: PUBLIC PROC[stream: IO.STREAM] RETURNS [Rope.ROPE]={
id: Rope.ROPE ← stream.GetID[];
char: CHAR;
--Need to search further because "Input[0]" could be a valid name
WHILE (char ← stream.GetChar) # ': DO
id ← Rope.Cat[id, Rope.FromChar[char]]
ENDLOOP;
RETURN [id];
}; --GetIdRope--
GetIdAtom: PUBLIC PROC[stream: IO.STREAM] RETURNS [ATOM]={
id: ATOM ← stream.GetAtom[];
char: CHAR;
IF (char ← stream.GetChar) = ':
THEN RETURN [id]
ELSE ERROR ParseError[$syntaxError, NEW[CHAR ← char]];
}; --GetIdRope--
EnterBlock: PUBLIC PROC [stream: IO.STREAM] = {
char: CHAR;
[] ← stream.SkipWhitespace[];
IF (char ← stream.GetChar) # '{
THEN ERROR ParseError[$noBegin, NEW[CHAR ← char]];
}; --EnterBlock
ExitBlock: PUBLIC PROC [stream: IO.STREAM] RETURNS [BOOLTRUE]= {
[] ← stream.SkipWhitespace[];
IF stream.PeekChar = '}
THEN [] ← stream.GetChar
ELSE RETURN [FALSE]
}; --ExitBlock
RemoveBlock: PUBLIC PROC [stream: IO.STREAM] = {
EnterBlock[stream];
UNTIL ExitBlock[stream] DO
IF stream.GetChar = '{ THEN RemoveBlock[stream];
ENDLOOP;
}; --RemoveBlock
GetNatVector: PUBLIC PROC[stream: IO.STREAM] RETURNS [REF IP.NatVector] = {
refPair: LIST OF REF ANYNARROW[stream.GetRefAny];
x, y: NAT;
IF refPair = NIL THEN RETURN [NIL];
x ← NARROW[refPair.first, REF INT]^;
y ← NARROW[refPair.rest.first, REF INT]^;
RETURN [BO.NuNatVector[x, y]]
}; --GetNatVector--
GetIntVector: PUBLIC PROC[stream: IO.STREAM] RETURNS [REF IntVector] = {
refPair: LIST OF REF ANYNARROW[stream.GetRefAny];
x, y: INT;
IF refPair = NIL THEN RETURN [NIL];
x ← NARROW[refPair.first, REF INT]^;
y ← NARROW[refPair.rest.first, REF INT]^;
RETURN [BO.NuIntVector[x, y]]
}; --GetIntVector--
GetShape: PUBLIC PROC [stream: IO.STREAM] RETURNS [shape: REF IP.ShapeRep] = {
OPEN sC: shape.cornerSpaces;
EnterBlock[stream];
shape ← NEW[IP.ShapeRep ← [dim: GetNatVector[stream]]];
UNTIL ExitBlock[stream] DO
token: ATOM ← GetIdAtom[stream];
SELECT token FROM
$sw => sC.sw ← GetNatVector[stream]; --$sw
$se => sC.se ← GetNatVector[stream]; --$se
$ne => sC.ne ← GetNatVector[stream]; --$ne
$nw => sC.nw ← GetNatVector[stream]; --$nw
ENDCASE => ERROR ParseError[$badToken, token];
ENDLOOP;
}; --GetShape
GetPhysicalPins: PUBLIC PROC[stream: IO.STREAM] RETURNS [phyPins: PhysicalPins ← NIL] ={
getPhyPin: PROC RETURNS [REF IP.PhysicalPinRep] ={
coord: IntVector ← GetIntVector[stream]^;
side: IP.PinSideType ← GetPinSide[stream];
active: BOOL ← stream.GetBool;
RETURN [NEW [IP.PhysicalPinRep ← [coord, side, active]]]
}; --getPhyPin
EnterBlock[stream];
UNTIL ExitBlock[stream] DO
phyPins ← CONS [getPhyPin[], phyPins];
ENDLOOP;
}; --GetPhysicalPins
PutShape: PUBLIC PROC[stream: IO.STREAM, shape: REF IP.ShapeRep] ={
stream.PutF["{"];
IF shape # NIL THEN { OPEN sC: shape.cornerSpaces;
stream.PutF["(%g %g) ", IO.int[shape.dim.x], IO.int[shape.dim.y]];
IF sC.sw # NIL THEN stream.PutF["sw: (%g %g) ", IO.int[sC.sw.x], IO.int[sC.sw.y]];
IF sC.se # NIL THEN stream.PutF["se: (%g %g) ", IO.int[sC.se.x], IO.int[sC.se.y]];
IF sC.ne # NIL THEN stream.PutF["ne: (%g %g) ", IO.int[sC.ne.x], IO.int[sC.ne.y]];
IF sC.nw # NIL THEN stream.PutF["nw: (%g %g) ", IO.int[sC.nw.x], IO.int[sC.nw.y]];
}; --endIF
stream.PutF["}"];
};--PutShape
PutPhysicalPins: PUBLIC PROC[stream: IO.STREAM, physicalPins: PhysicalPins] ={
stream.PutF["{"];
WHILE physicalPins # NIL DO
phyPin: REF IP.PhysicalPinRep ← physicalPins.first;
stream.PutF[" (%g %g) %g %g",
IO.int[phyPin.coord.x],
IO.int[phyPin.coord.y],
IO.atom[IPPinSideToAtom[phyPin.side]],
IO.bool[phyPin.active],
];
physicalPins ← physicalPins.rest;
ENDLOOP;
stream.PutF["}"];
}; --PutShape
OrientPhysicalPins: PUBLIC PROC [phyPins: PhysicalPins, cellDim: IP.NatVector, cellOrient: IP.Orientation, cellOrigin: IntVector ← [0, 0]] ={
WHILE phyPins # NIL DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← IPOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], cellOrient, cellOrigin];
pPin.side ← OrientPinSide[pPin.side, cellOrient];
phyPins ← phyPins.rest;
ENDLOOP;
}; --OrientPhysicalPins
MirrorXPhysicalPins: PUBLIC PROC [phyPins: PhysicalPins, cellDim: IP.NatVector, cellOrigin: IntVector ← [0, 0]] ={
WHILE phyPins # NIL DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← IPOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], mirrorX, cellOrigin];
pPin.side ← MirrorXPinSide[pPin.side];
phyPins ← phyPins.rest;
ENDLOOP;
};--MirrorXPhysicalPins
Rotate90PhysicalPins: PUBLIC PROC [phyPins: PhysicalPins, cellDim: IP.NatVector, numberOfRot: INT ← 1, cellOrigin: IntVector ← [0, 0]] ={
CDRotn: IPOrient.Orientation;
SELECT numberOfRot MOD 4 FROM
0 => CDRotn ← original;
1, -3 => CDRotn ← rotate90;
2, -2 => CDRotn ← rotate180;
3, -1 => CDRotn ← rotate270;
ENDCASE => ERROR;
WHILE phyPins # NIL DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← IPOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], CDRotn, cellOrigin];
pPin.side ← Rotate90PinSide[pPin.side, numberOfRot];
phyPins ← phyPins.rest;
ENDLOOP;
};--Rotate90PhysicalPins
OrientPinSide: PUBLIC PROC[side: IP.PinSideType, orient: IP.Orientation] RETURNS [IP.PinSideType] ={
IF IPOrient.IncludesMirrorX[orient] THEN side ← MirrorXPinSide[side];
RETURN [Rotate90PinSide[side, IPOrient.OrientD2[orient]]];
}; --OrientPinSide
MirrorXPinSide: PUBLIC PROC[side: IP.PinSideType] RETURNS [IP.PinSideType] ={
RETURN [
SELECT side FROM
south, north, interior, unknown => side,
east => west,
west => east,
swHor => seHor,
seHor => swHor,
neHor => nwHor,
nwHor => neHor,
swVer => seVer,
seVer => swVer,
neVer => nwVer,
nwVer => neVer,
ENDCASE => ERROR
];
};--MirrorXPinSide
Rotate90PinSide: PUBLIC PROC [side: IP.PinSideType, numberOfRot: INT ← 1] RETURNS [IP.PinSideType]={
rot1: PROC [s: IP.PinSideType] RETURNS [IP.PinSideType] = {
RETURN [SELECT s FROM
south => east,
east => north,
north => west,
west => south,
swHor => seVer,
seVer => neHor,
neHor => nwVer,
nwVer => swHor,
swVer => seHor,
seHor => neVer,
neVer => nwHor,
nwHor => swVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot1
rot2: PROC [s: IP.PinSideType] RETURNS [IP.PinSideType] = {
RETURN [SELECT s FROM
south => north,
north => south,
east => west,
west => east,
swHor => neHor,
swVer => neVer,
seHor => nwHor,
seVer => nwVer,
neHor => swHor,
neVer => swVer,
nwHor => seHor,
nwVer => seVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot2
rot3: PROC [s: IP.PinSideType] RETURNS [IP.PinSideType] = {
RETURN [SELECT s FROM
south => west,
west => north,
north => east,
east => south,
swHor => nwVer,
nwVer => neHor,
neHor => seVer,
seVer => swHor,
swVer => nwHor,
nwHor => neVer,
neVer => seHor,
seHor => swVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot3
RETURN [SELECT numberOfRot MOD 4 FROM
0 => side,
1, -3 => rot1[side],
2, -2 => rot2[side],
3, -1 => rot3[side],
ENDCASE => ERROR];
}; --Rotate90PinSide
CoChannels: PUBLIC PROC[co: REF IP.ComponentRep, action: PROC[REF IP.ChannelRep] RETURNS [quit: BOOL]] ={
OPEN coP: co.prinChannels, coC: co.cornerChannels;
IF action[coP.south] THEN RETURN;
IF action[coP.east] THEN RETURN;
IF action[coP.north] THEN RETURN;
IF action[coP.west] THEN RETURN;
IF coC.sw # NIL THEN {
IF action[coC.sw.hor] THEN RETURN;
IF action[coC.sw.ver] THEN RETURN;
};
IF coC.se # NIL THEN {
IF action[coC.se.hor] THEN RETURN;
IF action[coC.se.ver] THEN RETURN;
};
IF coC.ne # NIL THEN {
IF action[coC.ne.hor] THEN RETURN;
IF action[coC.ne.ver] THEN RETURN;
};
IF coC.nw # NIL THEN {
IF action[coC.nw.hor] THEN RETURN;
IF action[coC.nw.ver] THEN RETURN;
};
}; --CoChannels
--###Low level Private routines###--
IPPinSideToAtom: PROC[side: IP.PinSideType] RETURNS [ATOM] ={
RETURN[
SELECT side FROM
south => $south,
east => $east,
north => $north,
west => $west,
swHor => $swHor,
seHor => $seHor,
neHor => $neHor,
nwHor => $nwHor,
swVer => $swVer,
seVer => $seVer,
neVer => $neVer,
nwVer => $nwVer,
interior => $interior,
unknown => $unknown,
ENDCASE => ERROR];
}; --IPPinSideToAtom
GetPinSide: PROC[stream: IO.STREAM] RETURNS [IP.PinSideType] ={
token: ATOM ← stream.GetAtom;
RETURN [SELECT token FROM
$south => south,
$east => east,
$north => north,
$west => west,
$swHor => swHor,
$seHor => seHor,
$neHor => neHor,
$nwHor => nwHor,
$swVer => swVer,
$seVer => seVer,
$neVer => neVer,
$nwVer => nwVer,
$interior => interior,
$unknown => unknown,
ENDCASE => ERROR ParseError[$badToken, token]];
}; --GetPinSide
ConstructFileName: PUBLIC PROC[defaultDir, inputFile, defaultExt: Rope.ROPE]
RETURNS[fullName: Rope.ROPE] = {
dirPart: Rope.ROPE ← FileNames.Directory[inputFile];
IF Rope.IsEmpty[inputFile] THEN RETURN[NIL];
IF Rope.IsEmpty[dirPart] THEN dirPart ← defaultDir;
fullName ← Rope.Cat[dirPart, FileNames.GetShortName[inputFile]];
IF Rope.Find[inputFile, "."] < 0 AND Rope.Find[inputFile, "!"] < 0 THEN
fullName ← Rope.Cat[fullName, ".", defaultExt];
}; -- ConstructFileName
END.