<<-- File: IPCoTabImpl.mesa>> <<-- Last Edited by: CSChow, January 27, 1985 6:20:42 am PST>> <> <<--Note: IPCoTab = ComponentTable>> <<>> <<--Documentation will come later after consolidating the design -->> <<>> DIRECTORY Misc USING [Rect, RectCreate], Imager USING [Context, VEC, MaskStrokeTrajectory, SetGray, MaskFillTrajectory, SetXY, ShowRope], ImagerPath USING [Trajectory, MoveTo, LineToX, LineToY, LastPoint], IO, IP, IPConstants, IPParams, IPBasicOps, IPCTG, IPOrient, IPTypeTab, IPNetTab, IPToolBox, IPChipRose, IPPinNets, IPCoTab, Rope, RTStructure, SymTab; IPCoTabImpl: CEDAR PROGRAM IMPORTS IPOrient, Misc, IO, Imager, ImagerPath, IP, IPParams, IPBasicOps, IPToolBox, IPNetTab, IPTypeTab, IPCTG, IPChipRose, IPPinNets, Rope, RTStructure, SymTab 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-- CreateFromStructure: PUBLIC PROC[structure: RTStructure.Structure, typeTab: IPTypeTab.Ref, netTab: IPNetTab.Ref] RETURNS[Ref] = { EachInstProc: RTStructure.EachInstanceAction ~ { ConvertPinNet: RTStructure.EachInstancePinAction ~ { pin: IPTypeTab.Pin _ IPTypeTab.GetPin[type, iPin.oPin.name]; phyPins: LIST OF REF IP.PhysicalPinRep _ IPTypeTab.MakePhysicalPins[type, pin, orient]; pinNets _ CONS [NEW [IPPinNets.PinNetRep _ [iPin.oPin.name, netTab.FetchNet[iPin.net.name], NIL, phyPins]], pinNets]; }; --ConvertPinNet orient: IP.Orientation _ instance.orientation; origin: IntVector _ IF ~instance.placed THEN [IPParams.CoDefaultPosition, IPParams.CoDefaultPosition] ELSE instance.position; pinNets: IPPinNets.PinNets _ NIL; type: IPTypeTab.CoType; IF instance.object.heirarchyLevel = this THEN { component: IPCoTab.Component; type _ IPTypeTab.FetchCoType[typeTab, instance.object.name]; <<--Now make pinNets>> [] _ RTStructure.EnumerateInstancePins[instance, ConvertPinNet]; <<>> <<-- Now Create the Component>> component _ CreateComponent[coTab, instance.name, type, orient, pinNets, origin, instance.placed]; component.any _ instance; instance.any _ component}; }; --eachInstProc coTab: Ref _ NEW[Rep _ [SymTab.Create[]]]; [] _ RTStructure.EnumerateInstances[structure, 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 co.any _ NIL; }; --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[IPOrient.CDOrienToInt[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: IPOrient.Orientation _ IPOrient.CDIntToOrien[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: IPOrient.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: IPOrient.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 IPOrient.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 IPOrient.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 _ IPOrient.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 _ (westCoeff * xMin + eastCoeff * 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 = 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 IPOrient.OrientD2[operation] 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 IPOrient.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. <<>>