DIRECTORY CD, CDBasics, CDCells, CDOrient, CDProperties, CDRects, CDSymbolicObjects, Convert, PW, PWPins, PWRoute, Rope, Route, RouteUtil, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCPrivate, SCRoutePinsUtil, SCRowUtil, SCUtil; SCRouteImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDProperties, CDRects, CDSymbolicObjects, Convert, PW, PWPins, PWRoute, Rope, RouteUtil, RTBasic, SC, SCChanUtil, SCInstUtil, SCNetUtil, SCRoutePinsUtil, SCRowUtil, SCUtil EXPORTS SCPrivate SHARES SC = BEGIN RowCellsRec: TYPE = ARRAY SCPrivate.MaxRowSr OF PW.Object; RowCells: TYPE = REF RowCellsRec; ExitCellsSideRec: TYPE = ARRAY SCPrivate.MaxChanSr OF PW.Object; ExitCellsSide: TYPE = REF ExitCellsSideRec; ExitCellsRec: TYPE = ARRAY LRSide OF ExitCellsSide; ExitCells: TYPE = REF ExitCellsRec; NumSeqRec: TYPE = RECORD [ c: SEQUENCE size: NAT OF REF SC.Number]; NumSeq: TYPE = REF NumSeqRec; LRSide: TYPE = SCPrivate.LRSide; TBSide: TYPE = SCPrivate.TBSide; LayoutData: TYPE = SCPrivate.LayoutData; ROPE: TYPE = Rope.ROPE; PQPos: TYPE = SCPrivate.PQPos; CreatePinsForChannel: PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan, rowCells: RowCells] = { AllPins: SCInstUtil.EachPinProc = { IF netPin.net #NIL THEN { IF side = SCInstUtil.PosOf[instance, netPin.pin].sideOn THEN { rect: CD.Rect _ SCInstUtil.RotateRect[instance, netPin.pin.rect]; position: CD.Position _ SCUtil.PQToXY[handle, [p: instance.offset + rect.x1, q: rect.y1]]; SCRoutePinsUtil.EnterPin[rect, position, netPin, RTBasic.OtherSide[side], rowCells[row]]}}}; ExternalPins: SCInstUtil.EachPinProc = { IF netPin.net #NIL AND netPin.net.externNet = externalNet THEN { IF side = SCInstUtil.PosOf[instance, netPin.pin].sideOn AND ExitOnSide[handle, netPin.net, side] THEN { rect: CD.Rect _ SCInstUtil.RotateRect[instance, netPin.pin.rect]; position: CD.Position _ SCUtil.PQToXY[handle, [p: instance.offset + rect.x1, q: rect.y1]]; SCRoutePinsUtil.EnterPin[rect, position, netPin, RTBasic.OtherSide[side], rowCells[row]]}}}; InternalPinsInstance: SCRowUtil.EachInstProc = { [] _ SCInstUtil.EnumeratePinsOnInst[instance, AllPins]}; ExternalPinsInstance: SCRowUtil.EachInstProc = { [] _ SCInstUtil.EnumeratePinsOnInst[instance, ExternalPins]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; chan: SCPrivate.MaxChanSr _ rowChan.chanNum; side: SC.Side; row: SCPrivate.MaxRowSr; IF chan = 1 THEN { side _ bottom; row _ 1; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, ExternalPinsInstance]} ELSE IF chan = lgRows.count + 1 THEN { side _ top; row _ lgRows.count; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, ExternalPinsInstance]} ELSE { side _ top; row _ chan - 1; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, InternalPinsInstance]; side _ bottom; row _ chan; [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, InternalPinsInstance]}}; CreateExitsForChannel: PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan, exitCells: ExitCells] = { cell: CD.Object; ExitPins: SCChanUtil.EachExitProc = {SCRoutePinsUtil.EnterExit[exit, lrSide, cell]}; FOR side: LRSide IN LRSide DO cell _ PW.CreateEmptyCell[]; [] _ SCChanUtil.EnumerateExits[handle, rowChan, side, ExitPins]; exitCells[side][rowChan.chanNum] _ cell; ENDLOOP}; FinishExitsForChannel: PROC [handle: SC.Handle, rowChan: SCPrivate.RowChan, exitCells: ExitCells] = { trunkWidth: SC.Number _ handle.rules.rowRules.trunkWidth; FOR side: LRSide IN LRSide DO rect: CD.Rect; cell: CD.Object _ exitCells[side][rowChan.chanNum]; SELECT side FROM -- pw needs a better way of finding sides left => rect _ [-trunkWidth, -trunkWidth, trunkWidth, 2*trunkWidth]; right => rect _ [0, -trunkWidth, 2*trunkWidth, 2*trunkWidth]; ENDCASE; CDCells.SetInterestRect[cell, rect]; -- set interestRect of cell PW.RepositionCell[cell]; ENDLOOP}; CreateWireAndContact: PROC [handle: SC.Handle, pin: PW.Instance, size: Route.Position, length: CD.Number, trunkLayer: CD.Layer, cdLambda: Route.Number] RETURNS [obj: CD.Object] = { branchLayer: CD.Layer _ CDSymbolicObjects.GetLayer[pin]; obj _ PW.CreateEmptyCell[]; [] _ PW.IncludeInCell[obj, CreateWireFromPin[handle, pin, length]]; RouteUtil.AddVia[obj, CDSymbolicObjects.GetName[pin], [length-size.x/2, size.y/2], size, trunkLayer, branchLayer, cdLambda]; PW.RepositionCell[obj]}; CreateWireFromPin: PROC [handle: SC.Handle, pin: PW.Instance, length: CD.Number] RETURNS [wire: CD.Object] = { wx: CD.Number _ length; wy: CD.Number _ pin.ob.size.y; wSize: CD.Position _ SCUtil.PQToXY[handle, [wx, wy]]; layer: CD.Layer _ CDSymbolicObjects.GetLayer[pin]; wire _ CDRects.CreateRect[wSize, layer]}; AlwaysExtendPin: PROC [handle: SC.Handle, inst: PW.Instance, extLen: CD.Number] RETURNS [obj: CD.Object _ NIL] = { IF CDSymbolicObjects.IsSymbolicOb[inst.ob] THEN { pinInst: CD.Instance; wire: CD.Object _ CreateWireFromPin[handle, inst, extLen]; pinOb: CD.Object _ CDSymbolicObjects.CreateSegment[inst.ob.size.y]; obj _ PW.CreateEmptyCell[]; pinInst _ PW.IncludeInCell[obj, pinOb, [extLen-pinOb.size.x, 0], CDSymbolicObjects.OrientFromDirection[east]]; [] _ PW.IncludeInCell[obj, wire]; CDSymbolicObjects.SetName[pinInst, CDSymbolicObjects.GetName[inst]]; CDSymbolicObjects.SetLayer[pinInst, CDSymbolicObjects.GetLayer[inst]]; PW.RepositionCell[obj]}}; ExtendPowerBuses: PROC [handle: SC.Handle, rowCells: RowCells] = { extLen: CD.Number; side: LRSide; abutOb: PW.Object; layoutData: LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; maxRowWidth: CD.Number _ lgRows.maxRowWidth; ExtendPin: PW.ForEachPinProc = { IF Rope.Equal[CDSymbolicObjects.GetName[inst], layoutData.powerBuses[side].name] THEN obj _ AlwaysExtendPin[handle, inst, extLen]}; FOR rowNum: SCPrivate.MaxRowSr IN [1 .. lgRows.count] DO row: SCPrivate.LgRow _ lgRows.rows[rowNum]; rowLength: SC.Number _ row.size.p; rowOffset: SC.Number _ row.rowOrg.p - lgRows.horzRowOrg; ext: ARRAY LRSide OF PW.Object _ ALL[NIL]; IF rowOffset > 0 AND rowLength < maxRowWidth THEN { -- needs filler on left and right side _ left; extLen _ rowOffset; ext[left] _ TransferCell[template: rowCells[rowNum], objSide: left, width: extLen, objProc: ExtendPin, stopEnumerateDeepPins: FALSE]; side _ right; extLen _ maxRowWidth - (rowOffset + rowLength); ext[right] _ TransferCell[template: rowCells[rowNum], objSide: right, width: extLen, objProc: ExtendPin, stopEnumerateDeepPins: FALSE]; abutOb _ PW.AbutListX[LIST[ext[left], rowCells[rowNum], ext[right]]]} ELSE IF rowLength < maxRowWidth THEN { -- rowOffset = 0, no filler on left side _ right; extLen _ maxRowWidth - rowLength; ext[right] _ TransferCell[template: rowCells[rowNum], objSide: right, width: extLen, objProc: ExtendPin, stopEnumerateDeepPins: FALSE]; abutOb _ PW.AbutListX[LIST[rowCells[rowNum], ext[right]]]} ELSE -- no filler needed abutOb _ rowCells[rowNum]; rowCells[rowNum] _ IncludeCell[abutOb, Rope.Cat["Row",Convert.RopeFromInt[rowNum]], FALSE]; ENDLOOP}; CreateRowCell: PROC [handle: SC.Handle, row: SCPrivate.MaxRowSr, rowCells: RowCells] = { ForEachInstance: SCRowUtil.EachInstProc = { thisObj: CD.Object; IF instance.curOrien = 1 THEN thisObj _ instance.object.cdOb ELSE thisObj _ PW.ChangeOrientation[instance.object.cdOb, SCInstUtil.CDOrien[instance]]; listOb _ CONS[thisObj, listOb]}; rowOb: PW.Object _ NIL; listOb: PW.ListOb _ NIL; rCell: CD.Object _ NIL; -- cell obtained from rowOb [] _ SCRowUtil.EnumerateAllInstsOnRow[handle, row, ForEachInstance]; listOb _ PW.Reverse[listOb]; rowOb _ PW.AbutListX[listOb]; rCell _ IncludeCell[rowOb, Rope.Cat["Row", Convert.RopeFromInt[row]], TRUE]; rowCells[row] _ rCell}; AbutRouteList: PROC [listOb, bottomOrLeftListOb, topOrRightListOb: PW.ListOb, params: PWRoute.RouterParams, rowChans: SCPrivate.RowChans] RETURNS [obj: PW.Object] = BEGIN newListObj: PW.ListOb _ NIL; obj1, obj2, topOrRightObj, bottomOrLeftObj, channel: PW.Object; result: Route.RoutingResult; chan: SCPrivate.MaxChanSr _ 1; IF listOb = NIL THEN RETURN[NIL]; obj1 _ listOb.first; listOb _ listOb.rest; newListObj _ CONS[obj1, NIL]; FOR l: PW.ListOb _ listOb, l.rest WHILE l # NIL DO obj2 _ l.first; IF topOrRightListOb = NIL THEN topOrRightObj _ NIL ELSE {topOrRightObj _ topOrRightListOb.first; topOrRightListOb _ topOrRightListOb.rest}; IF bottomOrLeftListOb = NIL THEN bottomOrLeftObj _ NIL ELSE {bottomOrLeftObj _ bottomOrLeftListOb.first; bottomOrLeftListOb _ bottomOrLeftListOb.rest}; result _ PWRoute.DoRoute[obj1, obj2, bottomOrLeftObj, topOrRightObj, params, FALSE, channel]; rowChans.chans[chan].routing _ result; channel _ PWRoute.GetRouting[result, NIL]; newListObj _ CONS[obj2, CONS[channel, newListObj]]; obj1 _ obj2; -- just before looping chan _ chan + 1; ENDLOOP; newListObj _ PW.Reverse[newListObj]; obj _ PW.AbutListY[newListObj]; END; LogicRoute: PROC [handle: SC.Handle] RETURNS [logicOb: PW.Object] = { ForEachRow: SCRowUtil.EachRowProc = { CreateRowCell[handle, row, rowCells]}; ForEachChannel: SCChanUtil.EachRowChanProc = { SCRoutePinsUtil.InitGetChanPins[handle]; IF 1 < rowChan.chanNum AND rowChan.chanNum < rowChans.count THEN CreateExitsForChannel[handle: handle, rowChan: rowChan, exitCells: exitCells]; CreatePinsForChannel[handle: handle, rowChan: rowChan, rowCells: rowCells]; SCRoutePinsUtil.EnterNetDat[handle, chan, MakeNetPin, MakeExit, NIL]; SCRoutePinsUtil.TermGetChanPins[handle]; IF 1 < rowChan.chanNum AND rowChan.chanNum < rowChans.count THEN FinishExitsForChannel[handle: handle, rowChan: rowChan, exitCells: exitCells]}; MakeExit: SCRoutePinsUtil.ExitProc = { pinOb: CD.Object _ CDSymbolicObjects.CreatePin[size: [trunkWidth, exit.net.trunkWidth]]; pinInst: CD.Instance _ PW.IncludeInCell[cell: cell, obj: pinOb]; CDSymbolicObjects.SetName[pinInst, exit.net.name]; CDSymbolicObjects.SetLayer[pinInst, exit.layer]}; MakeNetPin: SCRoutePinsUtil.PinProc = { pinOb: CD.Object _ CDSymbolicObjects.CreatePin[CDBasics.SizeOfRect[rect]]; pinInst: CD.Instance _ PW.IncludeInCell[cell: cell, obj: pinOb, position: position]; CDSymbolicObjects.SetName[pinInst, netPin.net.name]; CDSymbolicObjects.SetLayer[pinInst, netPin.pin.layer]}; exitCells: ExitCells _ NEW[ExitCellsRec]; rowCells: RowCells _ NEW[RowCellsRec _ ALL[NIL]]; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; rowChans: SCPrivate.RowChans _ layoutData.rowChans; parms: SCPrivate.Parms _ NARROW[handle.parms]; routerParams: PWRoute.RouterParams _ NEW[PWRoute.RouterParamsRec _ [trunkLayer: handle.rules.horizLayer, branchLayer: handle.rules.vertLayer, technologyKey: parms.cdDesign.technology.key, signalBreakAtExit: FALSE, signalSinglePinNets: TRUE]]; abutOb: PW.Object; exitCells[left] _ NEW[ExitCellsSideRec _ ALL[NIL]]; exitCells[right] _ NEW[ExitCellsSideRec _ ALL[NIL]]; SCInstUtil.AllOffsets[handle]; [] _ SCRowUtil.EnumerateRows[handle: handle, eachRow: ForEachRow]; [] _ SCChanUtil.EnumerateRowChans[handle: handle, eachRowChan: ForEachChannel]; ExtendPowerBuses[handle, rowCells]; abutOb _ AbutRouteList[ listOb: RowListConvert[handle, rowCells], bottomOrLeftListOb: ChanListConvert[handle, exitCells[left]], topOrRightListOb: ChanListConvert[handle, exitCells[right]], rowChans: rowChans, params: routerParams]; logicOb _ IncludeCell[abutOb, Rope.Cat[handle.name, "Logic"], FALSE]}; IncludeTrunkPin: PROC [handle: SC.Handle, cell: CD.Object, name: ROPE, tbSide: TBSide, trunkSize, trunkPos: PQPos, layer: CD.Layer] = { height: INT _ handle.rules.rowRules.trunkWidth; pin: CD.Object _ CDSymbolicObjects.CreatePin[[trunkSize.p, height]]; pinPos: PQPos _ [trunkPos.p, IF tbSide = top THEN trunkPos.q + trunkSize.q - height ELSE trunkPos.q]; pos: CD.Position _ SCUtil.PQToXY[handle, pinPos]; pinInst: CD.Instance _ PW.IncludeInCell[cell, pin, pos]; CDSymbolicObjects.SetName[pinInst, name]; CDSymbolicObjects.SetLayer[pinInst, layer]}; PowerRoute: PROC [handle: SC.Handle, pwOb: PW.Object] RETURNS [ob: PW.Object] = { ext: ARRAY LRSide OF PW.Object _ ALL[NIL]; rules: Route.DesignRules _ handle.rules.sideRules; trunkLayer: CD.Layer _ rules.trunkLayer; pwSide: PWPins.Side; pBus: SCPrivate.PowerBus; side: LRSide; trunk, abutOb: CD.Object; trunkSize, trunkPos: PQPos; extLen, width, trunkWidth: SC.Number; layoutData: LayoutData _ NARROW[handle.layoutData]; ExtendPin: PW.ForEachPinProc = { name: ROPE _ CDSymbolicObjects.GetName[inst]; otherPBus: SCPrivate.PowerBus = layoutData.powerBuses[RTBasic.OtherSide[side]]; SELECT TRUE FROM Rope.Equal[name, pBus.name] => obj _ CreateWireAndContact[handle, inst, [trunkWidth, RTBasic.IRSize[inst.ob].y], width, trunkLayer, handle.rules.sideRules.CDLambda]; Rope.Equal[name, otherPBus.name] => NULL; ENDCASE => obj _ AlwaysExtendPin[handle, inst, width]}; FOR side IN LRSide DO pBus _ layoutData.powerBuses[side]; width _ MAX[pBus.width, rules.trunkToTrunk]; trunkWidth _ width - rules.trunkSpacing; extLen _ rules.trunkSpacing; trunkSize _ [p: trunkWidth, q: RTBasic.IRSize[pwOb].y]; trunkPos _ [IF side = right THEN extLen ELSE 0, 0]; pwSide _ SELECT side FROM right => right, left => left, ENDCASE => ERROR; ext[side] _ TransferCell[template: pwOb, objSide: pwSide, width: width, objProc: ExtendPin, name: IF side = right THEN "RPower" ELSE "LPower", stopEnumerateDeepPins: FALSE]; trunk _ MakeTrunk[handle: handle, trunkSize: trunkSize, lev: trunkLayer]; [] _ PW.IncludeInCell[ext[side], trunk, SCUtil.PQToXY[handle, trunkPos]]; IF Rope.Equal[pBus.name, "Vdd"] THEN IncludeTrunkPin[handle, ext[side], pBus.name, top, trunkSize, trunkPos , trunkLayer]; IF Rope.Equal[pBus.name, "Gnd"] THEN IncludeTrunkPin[handle, ext[side], pBus.name, bottom, trunkSize, trunkPos , trunkLayer]; ENDLOOP; abutOb _ PW.AbutListX[LIST [ext[left], pwOb, ext[right]]]; ob _ IncludeCell[abutOb, Rope.Cat[handle.name, "WPower"], FALSE]}; MakeTrunk: PROC [handle: SC.Handle, trunkSize: PQPos, lev: CD.Layer] RETURNS [obj: CD.Object] = { obj _ CDRects.CreateRect[SCUtil.PQToXY[handle, trunkSize], lev]}; AcBusForName: PROC [handle: SC.Handle, side: LRSide, name: ROPE] RETURNS [acBus: SCPrivate.AcBus _ NIL, i: NAT] = { layoutData: LayoutData _ NARROW[handle.layoutData]; sigs: SCPrivate.AcBusSigs _ layoutData.acBuses[side].sigs; FOR i IN [0..sigs.size) DO IF Rope.Equal[name, sigs[i].name] THEN RETURN [sigs[i], i]; ENDLOOP}; ComputeTrunkEnd: PROC [trunkEnd: NumSeq, q: SC.Number, index: NAT, fromTB: TBSide] = { prev: REF SC.Number _ trunkEnd[index]; trunkEnd[index] _ NEW[SC.Number]; trunkEnd[index]^ _ IF prev = NIL THEN q ELSE SELECT fromTB FROM top => MIN[q, prev^], bottom => MAX[q, prev^], ENDCASE => ERROR}; CreateAcTrunks: PROC [handle: SC.Handle, cell: CD.Object, acBusSide: SCPrivate.AcBusSides, trunkEnd: NumSeq, layer: CD.Layer] = { side: LRSide; trunk: CD.Object; trunkSize, trunkPos: PQPos; bus: SCPrivate.AcBus; FOR i: NAT IN [0..acBusSide.sigs.size) DO bus _ acBusSide.sigs[i]; side _ bus.onSide; trunkPos.p _ SELECT side FROM left => RTBasic.IRSize[cell].x - bus.depth, right => bus.depth, ENDCASE => ERROR; trunkPos.q _ SELECT bus.fromTB FROM bottom => 0, top => trunkEnd[i]^, ENDCASE => ERROR; trunkSize.p _ bus.net.trunkWidth; trunkSize.q _ SELECT bus.fromTB FROM bottom => trunkEnd[i]^, top => RTBasic.IRSize[cell].y - trunkEnd[i]^, ENDCASE => ERROR; trunk _ MakeTrunk[handle: handle, trunkSize: trunkSize, lev: layer]; [] _ PW.IncludeInCell[cell, trunk, SCUtil.PQToXY[handle, trunkPos]]; IncludeTrunkPin[handle, cell, bus.name, bus.fromTB, trunkSize, trunkPos, layer]; ENDLOOP}; ClockRoute: PROC [handle: SC.Handle, pwOb: PW.Object] RETURNS [ob: PW.Object] = { trunkEnd: NumSeq; -- "q" coordinate of trunk end point ext: ARRAY LRSide OF PW.Object _ ALL[NIL]; trunkLayer: CD.Layer _ handle.rules.sideRules.trunkLayer; side: LRSide; abutOb: CD.Object; width: SC.Number; layoutData: LayoutData _ NARROW[handle.layoutData]; ExtendPin: PW.ForEachPinProc = { pinName: ROPE _ CDSymbolicObjects.GetName[inst]; acBus: SCPrivate.AcBus; sigIndex: NAT; [acBus, sigIndex] _ AcBusForName[handle, side, pinName]; IF acBus = NIL THEN obj _ AlwaysExtendPin[handle, inst, width] ELSE { ComputeTrunkEnd[trunkEnd: trunkEnd, q: inst.location.y, index: sigIndex, fromTB: acBus.fromTB]; obj _ CreateWireAndContact[handle, inst, [acBus.net.trunkWidth, acBus.net.branchWidth], acBus.depth, trunkLayer, handle.rules.sideRules.CDLambda]}}; FOR side IN LRSide DO pwSide: PWPins.Side; acBusSide: SCPrivate.AcBusSides _ layoutData.acBuses[side]; IF acBusSide = NIL OR acBusSide.sigs = NIL THEN LOOP; trunkEnd _ NEW[NumSeqRec[acBusSide.sigs.size]]; FOR i: NAT IN [0..trunkEnd.size) DO trunkEnd[i] _ NIL; ENDLOOP; pwSide _ SELECT side FROM right => right, left => left, ENDCASE => ERROR; width _ acBusSide.width; ext[side] _ TransferCell[template: pwOb, objSide: pwSide, width: width, objProc: ExtendPin, stopEnumerateDeepPins: FALSE]; CreateAcTrunks[handle, ext[side], acBusSide, trunkEnd, trunkLayer]; ENDLOOP; abutOb _ PW.AbutListX[LIST [ext[left], pwOb, ext[right]]]; ob _ IncludeCell[abutOb, Rope.Cat[handle.name, "WClocks"], FALSE]}; DetailRoute: PUBLIC PROC [handle: SC.Handle] RETURNS [result: SC.Result] = { pwOb: PW.Object _ NIL; pwOb _ LogicRoute[handle]; pwOb _ PowerRoute[handle, pwOb]; pwOb _ ClockRoute[handle, pwOb]; result _ NEW[SC.ResultRec _ []]; result.object _ pwOb; result.handle _ handle; CheckExports[result]}; IncludeCell: PROC [rowOb: PW.Object, name: Rope.ROPE _ NIL, stopEnumerateDeepPins: BOOLEAN _ TRUE] RETURNS [rCell: CD.Object] = { rCellPtr: CD.CellPtr; inst: CD.Instance; rCell _ PW.CreateEmptyCell[]; rCellPtr _ NARROW [rCell.specificRef]; inst _ NEW [CD.InstanceRep _ [ob: rowOb]]; CDProperties.PutInstanceProp[inst, $InstanceName, name]; IF stopEnumerateDeepPins THEN CDProperties.PutProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins]; rCellPtr.contents _ CONS [inst, rCellPtr.contents]; CDCells.SetInterestRect[rCell, CD.InterestRect[rowOb]]; [] _ PW.RepositionCell[rCell]}; TransferCell: PROC [template: PW.Object, objSide: PWPins.Side, width: INT, objProc: PW.ForEachPinProc, name: Rope.ROPE _ "Transfer", stopEnumerateDeepPins: BOOLEAN _ TRUE] RETURNS [cell: PW.Object] = { KeepPinOnEdge: PWPins.InstanceEnumerator = BEGIN newObj: PW.Object; side: PWPins.Side _ PWPins.GetSide[template, inst].side; IF side=objSide THEN { newObj _ objProc[inst]; IF newObj=NIL THEN RETURN; [] _ PW.IncludeInCell[cell, newObj, Position[inst, template, objSide], SideToOrient[objSide]]; }; END; iRect: CD.Rect; IF objSide=none THEN ERROR; cell _ PW.CreateEmptyCell[]; iRect _ CD.InterestRect[template]; -- copy interestRect of obj CDCells.SetInterestRect[cell, IRect[iRect, width, objSide]]; -- set interestRect of cell [] _ PWPins.EnumerateEdgePins[template, KeepPinOnEdge, stopEnumerateDeepPins]; PW.RepositionCell[cell]}; IRect: PROC [templateRect: CD.Rect, otherDim: INT, side: PWPins.Side] RETURNS [iRect: CD.Rect] = { iRect _ SELECT side FROM top, bottom => [0, 0, templateRect.x2-templateRect.x1, otherDim], left, right => [0, 0, otherDim, templateRect.y2-templateRect.y1], ENDCASE => ERROR}; SideToOrient: PROC [side: PWPins.Side] RETURNS [orient: CD.Orientation] ~ { orient _ SELECT side FROM bottom => CDOrient.rotate270, right => CDOrient.original, top => CDOrient.rotate90, left => CDOrient.rotate180, ENDCASE => ERROR}; Position: PROC [inst: CD.Instance, template: PW.Object, side: PWPins.Side] RETURNS [position: CD.Position] = { position _ PW.GetLocation[inst, template]; SELECT side FROM top, bottom => position.y _ 0; left, right => position.x _ 0; ENDCASE => ERROR}; RowListConvert: PROC [handle: SC.Handle, rowCells: RowCells] RETURNS [listOb: PW.ListOb _ NIL] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; FOR rowNum: SCPrivate.MaxRowSr DECREASING IN [1 .. layoutData.lgRows.count] DO listOb _ CONS[rowCells[rowNum], listOb]; ENDLOOP}; ChanListConvert: PROC [handle: SC.Handle, exitCells: ExitCellsSide] RETURNS [listOb: PW.ListOb _ NIL] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; FOR chanNum: SCPrivate.MaxChanSr DECREASING IN [2 .. layoutData.rowChans.count-1] DO listOb _ CONS[exitCells[chanNum], listOb]; ENDLOOP}; ExitOnSide: PROC [handle: SC.Handle, net: SCPrivate.Net, side: SC.Side] RETURNS [onThisSide: BOOLEAN] ~ { EachInstance: SCRowUtil.EachInstProc ~ { CheckPin: SCInstUtil.EachPinProc = { IF netPin.net = net THEN quit _ TRUE}; quit _ SCInstUtil.EnumeratePinsOnInst[instance, CheckPin]}; onThisSide _ SCRowUtil.EnumerateAllInstsOnSide[handle, side, EachInstance]}; CheckExports: PROC [result: SC.Result] ~ { KeepPinOnEdge: PWPins.InstanceEnumerator = { name: Rope.ROPE _ CDSymbolicObjects.GetName[inst]; IF ~Memb[name, exportsList] THEN exportsList _ CONS[name, exportsList]}; CheckNet: SCNetUtil.EachNetProc ~ { memb: BOOLEAN _ Memb[net.name, exportsList]; IF ~memb AND net.externNet = externalNet THEN SC.Signal[programmingError, Rope.Cat["Public net not exported: ", net.name]]}; exportsList: LIST OF Rope.ROPE _ NIL; [] _ PWPins.EnumerateEdgePins[result.object, KeepPinOnEdge, TRUE]; [] _ SCNetUtil.EnumerateNets[result.handle, CheckNet]}; Memb: PROC [rope: Rope.ROPE, list: LIST OF Rope.ROPE] RETURNS [BOOL] = { UNTIL list = NIL DO IF Rope.Equal[list.first, rope] THEN RETURN[TRUE]; list _ list.rest; ENDLOOP; RETURN[FALSE]; }; END. ²SCRouteImpl.mesa: Implementation of SC.DetailedRoute Copyright c 1986 by Xerox Corporation. All rights reserved. Frank Bowers June 3, 1986 10:58:48 am PDT Bryan Preas April 3, 1986 5:34:51 pm PST [instance: SCPrivate.Instance, pin: NAT, netPin: SCPrivate.PinNet] [instance: SCPrivate.Instance, pin: NAT, netPin: SCPrivate.PinNet] create wire and copy pin to end of wire extend power buses to length of longest row -- AbutRoute: uses a channel router to connect adjacent objects [rect: SC.Rect, position: CD.Position, netPin: SCPrivate.PinNet, cell: CD.Object] ext end power pins on edges and put in power rails [inst: Instance] RETURNS [obj: Object]; -- Start with an empty cell of appropriate interestRect (origin in 0,0) -- Parse the pins [instance: SCPrivate.Instance, pin: NAT, netPin: SCPrivate.PinNet] check to insure all exports are correct: pins representing exported wires and only exported wires are present on boundry Κ»˜šœ5™5Icodešœ Οmœ1™Jšœžœ9˜AJšœ žœN˜ZJšœ\˜\——J˜—šŸ œ˜(Jš $‘ ™BJ™šžœ žœžœ%žœ˜Cšžœ6žœ&žœ˜gJšœžœ9˜AJšœ žœN˜ZJšœ\˜\——J˜—šŸœ˜0Jšœ8˜8J˜—šŸœ˜0Jšœ=˜=J˜—Kšœ#žœ˜=Kšœ-˜-Jšœ,˜,Jšœžœ˜Jšœ˜šžœ žœ˜Jšœ˜JšœI˜I—šžœžœžœ˜&Jšœ˜JšœI˜I—šžœ˜Jšœ˜JšœI˜IJšœ˜JšœK˜K—J˜—šŸœžœ žœ>˜eJšœžœ˜J˜šŸœL˜TJ˜—šžœžœž˜Jšœžœ˜Kšœ@˜@Kšœ(˜(Kšžœ˜ —J˜—šŸœžœ žœ>˜eJšœ žœ+˜9J˜šžœžœž˜Jšœžœ˜Kšœžœ+˜3šžœžœΟc)˜:JšœD˜DJšœ=˜=Jšžœ˜—Jšœ%’˜@Jšžœ˜Kšžœ˜ —J˜—š Ÿœžœ žœžœ)žœžœ˜—Jšžœžœ ˜J˜Jšœ žœ)˜8Jšœžœ˜Jšœžœ<˜CJšœ|˜|Jšžœ˜J˜—š Ÿœžœ žœžœžœ˜PJšžœžœ ˜Jšœžœ˜Jšœžœ˜Jšœžœ,˜5Jšœžœ)˜2Jšœ)˜)J˜—š Ÿœžœ žœžœžœ ˜PJšžœžœ žœ˜"J™'J˜šžœ)žœ˜1Jšœ žœ ˜Jšœžœ2˜:Jšœžœ:˜CJšœžœ˜Jšœ žœb˜nJšœžœ˜!JšœD˜DJšœF˜FJšžœ˜—J˜—šŸœžœ žœ ˜BJšœ+™+J˜Jšœžœ˜J˜ Jšœžœ˜Jšœžœ˜3Jšœ-˜-Jšœ žœ˜,J˜šŸ œžœ˜ šžœOž˜UJšœ-˜-——J˜šžœžœžœ˜9Kšœ+˜+Kšœ žœ˜"Kšœ žœ+˜8Jš œžœ žœžœ žœžœ˜+šžœžœžœ’!˜UKšœ ˜ Kšœ~žœ˜…Kšœ=˜=Kšœ€žœ˜‡Jšœ žœ žœ+˜E—šžœžœžœ’#˜KKšœ/˜/Kšœ€žœ˜‡Jšœ žœ žœ ˜:—šžœ’˜Jšœ˜—JšœTžœ˜[Kšžœ˜ —J˜—šŸ œžœ žœ9˜XJ˜šŸœ˜+Jšœ žœ˜Jšžœžœ˜žœ˜FJ˜—š Ÿœžœ žœžœžœ5žœ ˜‡J˜Jšœ/˜/Jšœžœ=˜DJšœžœžœ#žœ ˜eJšœžœ*˜2Jšœ žœ žœ˜8Jšœ)˜)Jšœ-˜-J˜—šŸ œžœ žœžœ˜5Jšžœžœ ˜Jšœ3™3J™Jš œžœ žœžœ žœžœ˜+Jšœ2˜2Jšœ žœ˜(J˜J˜J˜ Jšœžœ˜Jšœ˜Jšœžœ˜%Jšœžœ˜3J˜šŸ œžœ˜ Jšœžœ#˜-JšœO˜Ošžœžœž˜šœ˜Jšœ‡˜‡—Jšœ$žœ˜)Jšžœ0˜7—J˜—šžœžœž˜Kšœ#˜#Kšœžœ!˜,Kšœ(˜(Kšœ˜Kšœ7˜7Kšœ žœžœžœ˜3Kš œ žœžœžœžœ˜IKš œbžœžœ žœ"žœ˜­KšœI˜IKšœžœB˜Išžœž˜$KšœU˜U—šžœž˜$KšœX˜X—Kšžœ˜—Jšœ žœ žœ ˜:Jšœ:žœ˜BJ˜—šŸ œžœ žœ žœ˜DJšžœžœ ˜KšœA˜AJ˜—šŸ œžœ žœžœžœžœžœ˜sJšœžœ˜3Jšœ:˜:šžœžœž˜Jšžœ žœžœ˜;Jšžœ˜ —J˜—šŸœžœžœžœ˜VJšœžœžœ˜&Jšœžœžœ ˜!J˜š œžœžœžœžœžœž˜?Jšœžœ ˜Jšœ žœ ˜Jšžœžœ˜—J˜—š Ÿœžœ žœžœCžœ ˜J˜ Jšœžœ˜Jšœ˜J˜J˜šžœžœžœž˜)Jšœ˜J˜šœ žœž˜Jšœ@žœžœ˜Q—šœ žœ ž˜#Jšœ"žœžœ˜3—J˜!šœžœ ž˜$JšœFžœžœ˜W—JšœD˜DJšœžœ=˜DJšœP˜PKšžœ˜ —J˜—šŸ œžœ žœžœ˜5Jšžœžœ ˜Jšœ’$˜6Jš œžœžœžœ žœžœ˜*Jšœ žœ+˜9J˜ Jšœžœ˜Jšœžœ˜Jšœžœ˜3J˜šŸ œžœ˜ Jšœžœ™'J™Jšœ žœ#˜0Jšœ˜Jšœ žœ˜Jšœ8˜8Jšžœ žœžœ+˜>šžœ˜Jšœ_˜_Jšœ”˜”——J˜šžœžœž˜J˜Jšœ;˜;Jš žœ žœžœžœžœžœ˜5Jšœ žœ!˜/Jš žœžœžœžœžœžœ˜?Kš œ žœžœžœžœ˜IJšœ˜Jšœsžœ˜zJ˜CJšžœ˜—Jšœ žœ žœ ˜:Jšœ;žœ˜CJ˜—š Ÿ œžœžœ žœ žœ žœ ˜LJšœžœ žœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ žœžœ˜ J˜Jšœ˜Jšœ˜J˜—šŸ œžœ žœžœžœžœžœžœ žœ ˜Jšœ žœ ˜Jšœžœ ˜J˜Jšœžœ˜Jšœ žœ˜&Jšœžœžœ˜*Jšœ8˜8šžœž˜JšœK˜K—Jšœžœ˜3Jšœžœ˜7Jšœžœ˜J˜—šŸ œžœ žœ&žœ žœžœ&žœžœžœžœ ˜ΙšŸ œ˜+Jšž˜Jšœžœ˜Jšœ8˜8šžœžœ˜Jš œžœžœžœžœ˜2JšœžœW˜^J˜—Jšžœ˜—Jšœžœ˜Jšœ+’™GJšžœžœžœ˜Jšœžœ˜Jšœžœ’˜@Jšœ=’˜XJ™JšœN˜NJšžœ˜J˜—š Ÿœžœžœžœžœ žœ ˜bšœžœž˜JšœA˜AJšœA˜AJšžœžœ˜—J˜—šŸ œžœžœ žœ˜Kšœ žœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—J˜—š Ÿœžœžœžœžœ žœ˜nJšœ žœ˜*šžœž˜Jšœ˜Jšœ˜Jšžœžœ˜——J˜š Ÿœžœ žœžœ žœΟbžœ˜bKšœ#žœ˜=šžœž œžœ žœ˜OKšœ žœ˜(Kšžœ˜ —J˜—š Ÿœžœ žœ#žœ žœ£žœ˜iKšœ#žœ˜=šžœž œžœ$žœ˜UKšœ žœ˜*Kšžœ˜ —J˜—š Ÿ œžœ žœ#žœžœžœ˜iK˜šŸ œ˜(šŸœ˜$Jš $‘ ™BJ™Kšžœžœ˜&K˜—Jšœ;˜;K˜—KšœL˜LK˜—šŸ œžœ žœ ˜*šœ(™(KšœO™O—K˜šŸ œ˜,Kšœ žœ#˜2Kšžœžœžœ˜H—J˜šŸœ˜#Jšœžœ˜,šžœžœž˜-KšžœL˜N—J˜—Jš œ žœžœžœžœ˜%Jšœ<žœ˜BKšœ7˜7—K˜šŸœžœ žœžœžœžœžœžœ˜Hšžœžœž˜Kšžœžœžœžœ˜2Kšœ˜Kšžœ˜—Kšžœžœ˜Kšœ˜K˜—J˜šžœ˜J˜J˜J˜J˜J˜J˜—J˜—…—R¦l