<> <> <> <> <> DIRECTORY CD, CDBasics, CDCells, CDProperties, CDRects, CDRoutingObjects, Convert, Core, CoreRouteFlat, CoreRouteFlatProcs, DABasics, D2Orient, GC, GCPrivate, IP, IPCTG, IPTop, RefTab, Rope, Route, RTBasic, SymTab; GCDetailRouteImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDProperties, CDRects, CDRoutingObjects, Convert, CoreRouteFlat, CoreRouteFlatProcs, GC, GCPrivate, IPCTG, Route, RefTab, Rope, RTBasic, SymTab EXPORTS GCPrivate = BEGIN <> NetInChan: TYPE = REF NetInChanRec; -- routing description for a net on a channel NetInChanRec: TYPE = RECORD [ segmentCount: INT _ 0, -- count of existing segments segsInNet: LIST OF Segment _ NIL]; -- segments for this net on this channel Segment: TYPE = REF SegmentRec; SegmentRec: TYPE = RECORD[ name, lookUpName: Rope.ROPE _ NIL, trunkSize: INT _ 0, leftOrBottomExit: BOOL _ FALSE, -- used for channels only (not SB's) rightOrTopExit: BOOL _ FALSE, -- used for channels only (not SB's) pinsInSeg: LIST OF Pin _ NIL]; -- pins for this net on this channel Pin: TYPE = REF PinRec; -- pin description for pins in a net on a channel PinRec: TYPE = RECORD[ min: CD.Number _ 0, max: CD.Number _ 0, <> layer: CD.Layer, side: DABasics.Side]; <> DoDetailRoute: PUBLIC PROC [context: GC.Context, layoutStyle: GC.LayoutStyle] RETURNS [result: GC.Result] = { <> <<>> MakeChannel: GCPrivate.EachChannelAction ~ { <> <> InitNet: SymTab.EachPairAction = {net: CoreRouteFlat.Net _ NARROW[val]; net.any _ NIL}; rulesParameters: Route.DesignRulesParameters _ IF channel.direction = horizontal THEN context.rules.horizParams ELSE context.rules.vertParams; rules: Route.DesignRules _ IF channel.direction = horizontal THEN context.rules.horizRules ELSE context.rules.vertRules; lower, upper: RTBasic.PQPos; channelSize: CD.Position; [] _ SymTab.Pairs[context.structure.nets, InitNet]; GCPrivate.AssignCoordinates[context]; lower _ GCPrivate.LowerChannelPQ[channel]; upper _ GCPrivate.UpperChannelPQ[channel]; SELECT TRUE FROM channel.ch = bottomChannel => { channel.topOrRightShell _ MakeSide[context, rules, channel, top, TRUE, layoutStyle]; channel.bottomOrLeftShell _ MakeSide[context, rules, channel, bottom, FALSE, layoutStyle]}; channel.ch = rightChannel => { channel.bottomOrLeftShell _ MakeSide[context, rules, channel, left, TRUE, layoutStyle]; channel.topOrRightShell _ MakeSide[context, rules, channel, right, FALSE, layoutStyle]}; channel.ch = topChannel => { channel.bottomOrLeftShell _ MakeSide[context, rules, channel, bottom, TRUE, layoutStyle]; channel.topOrRightShell _ MakeSide[context, rules, channel, top, FALSE, layoutStyle]}; channel.ch = leftChannel => { channel.topOrRightShell _ MakeSide[context, rules, channel, right, TRUE, layoutStyle]; channel.bottomOrLeftShell _ MakeSide[context, rules, channel, left, FALSE, layoutStyle]}; ENDCASE => { channel.bottomOrLeftShell _ MakeSide[context, rules, channel, ChanSide[channel, bottom], TRUE, layoutStyle]; channel.topOrRightShell _ MakeSide[context, rules, channel, ChanSide[channel, top], TRUE, layoutStyle]}; MakeEnd[context, rules, channel, ChanSide[channel, left]]; -- lower end of channel MakeEnd[context, rules, channel, ChanSide[channel, right]]; -- upper end of channel channel.intermediateResult _ Route.ChannelRoute[enumerateNets: EnumerateChannelNets, min: lower.p, max: upper.p, rulesParameters: rulesParameters, rules: rules, name: NIL, enumerateObstructions: NIL, channelData: context, optimization: context.parms.opt, signalSinglePinNets: context.parms.signalSinglePinNets]; channel.cdObject _ Route.ChannelRetrieve[intermediateResult: channel.intermediateResult, enumerateNets: EnumerateChannelNets, brokenNets: NIL, channelData: context, retrieveRect: NIL].object; channelSize _ CDBasics.SizeOfRect[channel.intermediateResult.resultData.routingRect]; channel.width _ IF channel.direction = horizontal THEN channelSize.y ELSE channelSize.x; <> <> <> <> <> <> <> <> IPCTG.SetWidth[channel.ch, channel.width]}; IncludeChannel: GCPrivate.EachChannelAction ~ { <> <> <> IF channel.cdObject # NIL THEN { chanInst: CD.Instance _ GCPrivate.IncludeOb[cell: object, ob: channel.cdObject, position: channel.position]; CDProperties.PutInstanceProp[chanInst, $InstanceName, Rope.Cat["Channel", channel.name]]}; <> SELECT TRUE FROM channel.ch = bottomChannel => { IF channel.topOrRightShell # NIL THEN { [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: [channel.position.x, channel.position.y + channel.width]]}}; channel.ch = rightChannel => { IF channel.bottomOrLeftShell # NIL THEN { [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: [channel.position.x - CD.InterestSize[channel.bottomOrLeftShell].x, channel.position.y]]}}; channel.ch = topChannel => { IF channel.bottomOrLeftShell # NIL THEN { [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: [channel.position.x, channel.position.y - CD.InterestSize[channel.bottomOrLeftShell].y]]}}; channel.ch = leftChannel => { IF channel.topOrRightShell # NIL THEN { [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: [channel.position.x + channel.width, channel.position.y]]}}; ENDCASE => { IF channel.topOrRightShell # NIL THEN { topPos: CD.Position _ IF channel.direction = horizontal THEN [channel.position.x, channel.position.y + channel.width] ELSE [channel.position.x + channel.width, channel.position.y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.topOrRightShell, position: topPos]}; IF channel.bottomOrLeftShell # NIL THEN { bottomPos: CD.Position _ IF channel.direction = horizontal THEN [channel.position.x, channel.position.y - CD.InterestSize[channel.bottomOrLeftShell].y] ELSE [channel.position.x - CD.InterestSize[channel.bottomOrLeftShell].x, channel.position.y]; [] _ GCPrivate.IncludeOb[cell: object, ob: channel.bottomOrLeftShell, position: bottomPos]}}}; IncludeInstances: CoreRouteFlatProcs.EachInstanceAction ~ { <> IF instance.layObject # NIL THEN { cdInst: CD.Instance _ GCPrivate.IncludeOb [object, instance.layObject, instance.position, instance.orientation]; CDProperties.PutInstanceProp[cdInst, $InstanceName, instance.name]}; IF instance.layShell # NIL THEN { <> <<[object, instance.layShell, instance.position, instance.orientation];>> <> } }; topology: IPTop.Ref _ NARROW[context.topology]; bottomChannel, rightChannel, topChannel, leftChannel: IPCTG.Channel; object: CD.Object _ CDCells.CreateEmptyCell[]; [bottomChannel, rightChannel, topChannel, leftChannel] _ IPCTG.GetBoundingChannels[topology.ctg]; [] _ GCPrivate.EnumerateChannelsInTopologicalOrder[context, MakeChannel]; GCPrivate.AssignCoordinates[context]; [] _ GCPrivate.EnumerateChannelsInTopologicalOrder[context, IncludeChannel]; [] _ CoreRouteFlatProcs.EnumerateInstances[context.structure, IncludeInstances]; <> <<-- add Gnd layer to channel>> <> <> <> <> <> <> result _ NEW[GC.ResultRec _ [context: context, object: object]]}; <> MakeSide: PROC [context: GC.Context, rules: Route.DesignRules, channel: GCPrivate.Channel, chanSide: DABasics.Side, internal: BOOLEAN, layoutStyle: GC.LayoutStyle] RETURNS [shell: CD.Object _ NIL] ~ { <> DoExternalPins: IPCTG.EachComponentAction ~ { <> <> IF co # NIL THEN { instance: CoreRouteFlat.Instance _ NARROW[co.any]; sideOfCell: DABasics.Side _ IF internal THEN otherSide ELSE chanSide; FOR nns: LIST OF CoreRouteFlat.NetONode _ instance.netONodes, nns.rest WHILE nns#NIL DO isPowerNet: BOOLEAN _ Rope.Equal[nns.first.net.name, "Vdd"] OR Rope.Equal[nns.first.net.name, "Gnd"]; IF ExternalNet[context.structure, nns.first.net] AND (layoutStyle = ic OR ~isPowerNet) THEN { <> sidesForExternalNet: DABasics.Sides _ SidesForExternalNet[context.structure, nns.first.net]; FOR pins: LIST OF CoreRouteFlat.Pin _ nns.first.oNode.pins, pins.rest WHILE pins#NIL DO phyPin: GCPrivate.PhyPinDesc _ NEW[GCPrivate.PhyPinDescRec _ [instance, nns.first.oNode, pins.first]]; netDesc: GCPrivate.NetDesc _ NARROW [RefTab.Fetch[channel.connections, nns.first.net].val]; IF pins.first.layer = rules.branchLayer AND ~GCPrivate.PinOnList[netDesc, phyPin] AND sidesForExternalNet[sideOfCell] AND ((pins.first.side = otherSide AND internal) OR (pins.first.side = chanSide AND ~internal)) THEN { <> tabIndex: Rope.ROPE _ Rope.Cat[nns.first.net.name, "@", instance.name, "@", Convert.RopeFromInt[pins.first.range.min]]; netDat: NetInChan _ IF nns.first.net.any = NIL THEN NEW[NetInChanRec] ELSE NARROW[nns.first.net.any]; range: CoreRouteFlat.Range _ CoreRouteFlat.TranslateRange[instance, pins.first]; AddPin[nns.first.net, netDat, nns.first.net.name, tabIndex, range, rules.branchLayer, chanSide, defaultTrunkWidth]; maxWidth _ MAX[maxWidth, IncludePin[ phyPin: NEW[GCPrivate.PhyPinDescRec _ [instance, nns.first.oNode, pins.first]], name: tabIndex, side: chanSide, lower: lower, upper: upper, nodes: nodes ] ] }; ENDLOOP}; ENDLOOP} }; EachNet: RefTab.EachPairAction ~ { <> <> netDesc: GCPrivate.NetDesc _ NARROW[val]; FOR list: LIST OF GCPrivate.PhyPinDesc _ netDesc.pinList, list.rest WHILE list # NIL DO net: CoreRouteFlat.Net _ NARROW[key]; phyPin: GCPrivate.PhyPinDesc _ list.first; netDat: NetInChan _ IF net.any = NIL THEN NEW[NetInChanRec] ELSE NARROW[net.any]; range: CoreRouteFlat.Range _ CoreRouteFlat.TranslateRange[phyPin.instance, phyPin.pPin]; externalNet: BOOLEAN _ IPCTG.IsBoundingChannel[topology.ctg, channel.ch] AND ExternalNet[context.structure, net]; IF phyPin.pPin.layer # rules.branchLayer THEN GC.Signal[programmingError, "Call Maintainer"]; maxWidth _ MAX[maxWidth, IncludePin [list.first, net.name, chanSide, lower, upper, nodes]]; IF phyPin.pPin.side = otherSide THEN AddPin[net, netDat, net.name, net.name, range, rules.branchLayer, chanSide, defaultTrunkWidth]; IF externalNet THEN { sidesForExternalNet: DABasics.Sides _ SidesForExternalNet[context.structure, net]; sideOfCell: DABasics.Side _ IF internal THEN otherSide ELSE chanSide; IF ~internal AND sidesForExternalNet[sideOfCell] AND phyPin.pPin.side = chanSide THEN AddPin[net, netDat, net.name, net.name, range, rules.branchLayer, chanSide, defaultTrunkWidth]}; ENDLOOP}; DoChannelIntersection: IPCTG.EachIntersectionAction ~ { <> <> EachExit: PublicEnumerator ~ { <<[name: Rope.ROPE, min, max: INT, side: DABasics.Side, layer: CD.Layer] RETURNS [quit: BOOL _ FALSE] >> net: CoreRouteFlat.Net _ NARROW[SymTab.Fetch[context.structure.nets, name].val]; sidesForExternalNet: DABasics.Sides _ SidesForExternalNet[context.structure, net]; sideOfCell: DABasics.Side _ IF internal THEN otherSide ELSE chanSide; IF (internal AND side = otherSide) OR (~internal AND sidesForExternalNet[sideOfCell] AND side = chanSide) THEN { range: CoreRouteFlat.Range _ SELECT chanSide FROM bottom, top => [otherChannel.position.x + min, otherChannel.position.x + max], left, right => [otherChannel.position.y + min, otherChannel.position.y + max], ENDCASE => GC.Error[programmingError, "Call maintainer"]; netDat: NetInChan _ IF net.any = NIL THEN NEW[NetInChanRec] ELSE NARROW[net.any]; AddPin[net, netDat, name, name, range, rules.branchLayer, chanSide, defaultTrunkWidth]}}; otherChannel: GCPrivate.Channel _ NARROW[i.ch.any]; [] _ EnumerateEdgePins[context, otherChannel, EachExit]}; <> <> <> <<>> <> <> <> <> < instance.position.y - upper.q,>> < lower.q - instance.position.x - instSize.x,>> < lower.q - instance.position.y - instSize.y,>> < instance.position.x - upper.q,>> < GC.Error[programmingError, "Not suppose to happen"];>> <<>> < 0 THEN {>> <> <> < CDRects.CreateRect[[instSize.x, width], vddLayer],>> < CDRects.CreateRect[[[width, instSize.y], width], vddLayer],>> < GC.Error[programmingError, "Not suppose to happen"];>> <> <