<> <> <<-- InstWidth - find width of component at current orientation>> <<-- InstHeight - find height of component at current orientation>> <<-- BpHeight - find height of bp when considering side it is on>> <<-- BpWidth - find width of bp when considering side it is on>> <<-- MinMaxBPOffset - find min and max offsets of bonding pads on side>> <<-- BpOffsets - find offsets of bonding pads on side>> <<-- BpPos - find position of inst on side>> <<-- PosOf- find the position (side, x, and y) of a component on a pin>> <<-- PowerPosOf- find the position (x, and y) of a power pin>> <<-- RotateRect- Rotate a rectangle of a cell>> <<-- LgOffsets- determine offsets of components in row>> <<-- AllOffsets - determine all component offsets>> <<-- AsgnChanPos - assign current positions to horizontal and vertical channels>> <<-- CheckInsts - check row and position of comps>> <<-- CheckInst - check row and position of a inst>> <<-- EnumeratePinsOnInst - enumerate the net pins on an instance>> DIRECTORY CoreClasses, Rope, SC, SCInstUtil, SCPrivate, SCRowUtil, SCUtil, RTSets; SCInstUtilImpl: CEDAR PROGRAM IMPORTS SC, SCInstUtil, SCRowUtil, SCUtil, Rope, RTSets EXPORTS SCInstUtil SHARES SC = BEGIN defltLgOrien: PUBLIC SCPrivate.Orientation _ 1; defltBpOrien: PUBLIC ARRAY SC.Side OF SCPrivate.Orientation _ [3, 1, 4, 2]; <> InstWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] = BEGIN <> orien: SCPrivate.OrientationOrNone _ inst.curOrien; <> SELECT orien FROM 0, 1, 3, 5, 6 => width _ inst.object.size.p; 2, 4, 7, 8 => width _ inst.object.size.q; ENDCASE; END; <> InstHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] = BEGIN <> orien: SCPrivate.OrientationOrNone _ inst.curOrien; <> SELECT orien FROM 0, 1, 3, 5, 6 => height _ inst.object.size.q; 2, 4, 7, 8 => height _ inst.object.size.p; ENDCASE; END; <> <<(this is, the dimension perpendicular to side) >> BpHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] = { IF inst.whichClass # io THEN SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]]; SELECT inst.curSide FROM top, bottom => height _ InstHeight[inst]; left, right => height _ InstWidth[inst]; ENDCASE => SC.Error[programmingError, NIL]}; <> <> BpWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] = { IF inst.whichClass # io THEN SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]]; SELECT inst.curSide FROM top, bottom => width _ InstWidth[inst]; left, right => width _ InstHeight[inst]; ENDCASE => SC.Error[programmingError, NIL]}; <<>> <> MinMaxBPOffset: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side] RETURNS [minOffset, maxOffset: SC.Number] = { InstProc: SCRowUtil.EachInstProc = { minOffset _ MIN[minOffset, instance.offset]; maxOffset _ MAX[maxOffset, instance.offset]}; minOffset _ LAST[INT]; maxOffset _ -minOffset; [] _ SCRowUtil.EnumerateAllInstsOnSide[handle, side, InstProc]}; <> BpOffsets: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side, pos1, pos2: SCPrivate.ZMaxPosSr] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; offset: SC.Number; posA: SCPrivate.ZMaxPosSr _ MIN[pos1, pos2]; posB: SCPrivate.ZMaxPosSr _ MAX[pos1, pos2]; IF posA <= 1 THEN {posA _ 1; offset _ 0} ELSE {inst: SCPrivate.Instance _ bpRow.bpsOnSide[posA-1]; offset _ inst.offset + InstWidth[inst] + bpRow.bpSpacing}; IF posB = 0 OR posB > bpRow.nBpsOnSide THEN posB _ bpRow.nBpsOnSide; FOR posIndex: SCPrivate.ZMaxPosSr IN [posA .. posB] DO inst: SCPrivate.Instance _ bpRow.bpsOnSide[posIndex]; width: SC.Number _ BpWidth[inst]; IF side = bottom OR side = right THEN inst.offset _ offset ELSE inst.offset _ offset + width; offset _ offset + width + bpRow.bpSpacing; ENDLOOP}; <> <> BpPos: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] RETURNS[result: SC.Number] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[inst.curSide]; IF inst.whichClass # io THEN SC.Error[programmingError, " "]; SELECT inst.curSide FROM right => result _ bpRow.sideOrg.q + inst.offset; bottom => result _ bpRow.sideOrg.p + inst.offset; left => result _ bpRow.sideOrg.q - inst.offset; top => result _ bpRow.sideOrg.p - inst.offset; ENDCASE}; <> PosOf: PUBLIC PROCEDURE[inst: SCPrivate.Instance, pin: SCPrivate.ObjectPin] RETURNS [pinDes: SCInstUtil.PinDescription] = { x, y: SC.Number; <<>> <> SELECT pin.pinPos.side FROM bottom => {x _ pin.pinPos.location; y _ pin.pinPos.depth}; right => {x _ InstWidth[inst] - pin.pinPos.depth; y _ pin.pinPos.location}; top => {x _ InstWidth[inst] - pin.pinPos.location; y _ InstHeight[inst] - pin.pinPos.depth}; left => {x _ pin.pinPos.depth; y _ InstHeight[inst] - pin.pinPos.location}; ENDCASE; <> SELECT inst.curOrien FROM 0, 1 => {pinDes.xPos _ x; pinDes.yPos _ y}; 2 => {pinDes.xPos _ y; pinDes.yPos _ InstWidth[inst] - x}; 3 => {pinDes.xPos _ InstWidth[inst] - x; pinDes.yPos _ InstHeight[inst] - y}; 4 => {pinDes.xPos _ InstHeight[inst] - y; pinDes.yPos _ x}; 5 => {pinDes.xPos _ InstWidth[inst] - x; pinDes.yPos _ y}; 6 => {pinDes.xPos _ x; pinDes.yPos _ InstHeight[inst] - y}; 7 => {pinDes.xPos _ y; pinDes.yPos _ x}; 8 => {pinDes.xPos _ InstHeight[inst] - y; pinDes.yPos _ InstWidth[inst] - x}; ENDCASE; pinDes.sideOn _ SCUtil.SideTranslate[pin.pinPos.side, inst.curOrien]}; <> PowerPosOf: PUBLIC PROCEDURE[handle: SC.Handle, row: SCPrivate.ZMaxRowSr, net: SCPrivate.Net, lRSide: SCPrivate.LRSide] RETURNS [xPos, yPos: SC.Number _ 0, found: BOOLEAN _ FALSE] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRow: SCPrivate.LgRow _ layoutData.lgRows.rows[row]; maxPos: SCPrivate.ZMaxPosSr _ lgRow.nLgsOnRow; pd: SCInstUtil.PinDescription _ [0, 0, bottom]; inst: SCPrivate.Instance; IF maxPos > 0 THEN { pin: SCPrivate.ObjectPin; SELECT lRSide FROM left => inst _ lgRow.lgsOnRow[1]; right => inst _ lgRow.lgsOnRow[maxPos]; ENDCASE; pin _ SCUtil.FindPin[inst.object, net.name]; IF pin # NIL THEN {pd _ PosOf[inst, pin]; found _ TRUE} ELSE -- this is a hack until cells have power pins {IF Rope.Equal[net.name, layoutData.powerBuses[lRSide].name] THEN {SELECT lRSide FROM left => {pd.xPos _ 0; pd.yPos _ InstHeight[inst] - handle.rules.sideRules.trunkWidth/2; found _ TRUE}; right => {pd.xPos _ InstWidth[inst]; pd.yPos _ handle.rules.sideRules.trunkWidth/2; found _ TRUE}; ENDCASE}}}; xPos _ lgRow.rowOrg.p + inst.offset + pd.xPos; yPos _ lgRow.rowOrg.q + pd.yPos}; <> RotateRect: PUBLIC PROCEDURE[inst: SCPrivate.Instance, defRect: SC.Rect] RETURNS [newRect: SC.Rect] = { <> SELECT inst.curOrien FROM 1 => {newRect.x1 _ defRect.x1; newRect.y1 _ defRect.y1; newRect.x2 _ defRect.x2; newRect.y2 _ defRect.y2}; 2 => {newRect.x1 _ defRect.y1; newRect.y1 _ InstWidth[inst] - defRect.x1; newRect.x2 _ defRect.y2; newRect.y2 _ InstWidth[inst] - defRect.x2}; 3 => {newRect.x1 _ InstWidth[inst] - defRect.x1; newRect.y1 _ InstHeight[inst] - defRect.y1; newRect.x2 _ InstWidth[inst] - defRect.x2; newRect.y2 _ InstHeight[inst] - defRect.y2}; 4 => {newRect.x1 _ InstHeight[inst] - defRect.y1; newRect.y1 _ defRect.x1; newRect.x2 _ InstHeight[inst] - defRect.y2; newRect.y2 _ defRect.x2}; 5 => {newRect.x1 _ InstWidth[inst] - defRect.x1; newRect.y1 _ defRect.y1; newRect.x2 _ InstWidth[inst] - defRect.x2; newRect.y2 _ defRect.y2}; 6 => {newRect.x1 _ defRect.x1; newRect.y1 _ InstHeight[inst] - defRect.y1; newRect.x2 _ defRect.x2; newRect.y2 _ InstHeight[inst] - defRect.y2}; 7 => {newRect.x1 _ defRect.y1; newRect.y1 _ defRect.x1; newRect.x2 _ defRect.y2; newRect.y2 _ defRect.x2}; 8 => {newRect.x1 _ InstHeight[inst] - defRect.y1; newRect.y1 _ InstWidth[inst] - defRect.x1; newRect.x2 _ InstHeight[inst] - defRect.y2; newRect.y2 _ InstWidth[inst] - defRect.x2}; ENDCASE}; <> LgOffsets: PUBLIC PROCEDURE[handle: SC.Handle, row: SCPrivate.ZMaxRowSr, pos1, pos2: SCPrivate.ZMaxPosSr] = { <> layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; lgRow: SCPrivate.LgRow _ lgRows.rows[row]; offset: SC.Number; posA: SCPrivate.ZMaxPosSr _ MIN[pos1, pos2]; posB: SCPrivate.ZMaxPosSr _ MAX[pos1, pos2]; IF posA <= 1 THEN {posA _ 1; offset _ 0} ELSE {inst: SCPrivate.Instance _ lgRow.lgsOnRow[posA-1]; offset _ inst.offset + InstWidth[inst]}; IF posB = 0 OR posB > lgRow.nLgsOnRow THEN posB _ lgRow.nLgsOnRow; FOR posIndex: SCPrivate.MaxPosSr IN [posA .. posB] DO inst: SCPrivate.Instance _ lgRow.lgsOnRow[posIndex]; SELECT inst.whichClass FROM ft, logic => {inst.offset _ offset; offset _ offset + InstWidth[inst]}; ENDCASE; ENDLOOP; <> IF posB = lgRow.nLgsOnRow THEN {lgRow.size.p _ offset; IF lgRow.size.p >= lgRows.maxRowWidth THEN {lgRows.maxRowWidth _ lgRow.size.p; lgRows.numMaxRows _ 1} ELSE [lgRows.maxRowWidth, lgRows.numMaxRows] _ SCRowUtil.FindMaxRow[handle]}}; <> AllOffsets: PUBLIC PROCEDURE [handle: SC.Handle] = { RowRroc: SCRowUtil.EachRowProc = { LgOffsets[handle, row, 0, 0]}; SideProc: SCRowUtil.EachSideProc = { BpOffsets[handle, side, 0, 0]}; [] _ SCRowUtil.EnumerateRows[handle, RowRroc]; [] _ SCRowUtil.EnumerateSides[handle, SideProc]}; <> AsgnChanPos: PUBLIC PROCEDURE[handle: SC.Handle] = BEGIN <> EachSide: SCRowUtil.EachSideProc = { sideDim[side] _ bpRows[side].size.p + (bpRows[side].nBpsOnSide -1) * bpRows[side].bpSpacing}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; bpRows: SCPrivate.BpRows _ layoutData.bpRows; sideChans: SCPrivate.SideChans _ layoutData.sideChans; rowChans: SCPrivate.RowChans _ layoutData.rowChans; nRows: SCPrivate.MaxRowSr _ lgRows.count; nChans: SCPrivate.MaxChanSr _ rowChans.count; sideDim: ARRAY SC.Side OF SC.Number; upperActiveLimit, rightActiveLimit, realTotHeight: SC.Number; [] _ SCRowUtil.EnumerateSides[handle, EachSide]; FOR row: SCPrivate.MaxRowSr IN [1 .. nRows] DO IF lgRows.rows[row].dimInvalid THEN SCRowUtil.ComputeRowHeight[handle, row]; ENDLOOP; <> IF bpRows[left].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, left]; IF bpRows[bottom].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, bottom]; rowChans.chans[1].chanPos _ bpRows[bottom].size.q; sideChans[left].sideChanPos _ bpRows[left].size.q; lgRows.horzRowOrg _ bpRows[left].size.q + sideChans[left].sideChanResult; lgRows.rows[1].rowOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth - lgRows.rows[1].size.p)/2; lgRows.rows[1].rowOrg.q _ rowChans.chans[1].chanPos + rowChans.chans[1].chanResult; <> FOR chan: SCPrivate.MaxChanSr IN [2 .. nChans] DO rowChans.chans[chan].chanPos _ lgRows.rows[chan-1].rowOrg.q + lgRows.rows[chan-1].size.q; IF chan <= nRows THEN { lgRows.rows[chan].rowOrg.q _ rowChans.chans[chan].chanPos + MAX[rowChans.chans[chan].chanWidth, rowChans.chans[chan].minChanWidth]; lgRows.rows[chan].rowOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth - lgRows.rows[chan].size.p)/2}; ENDLOOP; <> sideChans[right].sideChanPos _ lgRows.horzRowOrg + lgRows.maxRowWidth; <> upperActiveLimit _ rowChans.chans[nChans].chanPos + MAX[rowChans.chans[nChans].chanWidth, rowChans.chans[nChans].minChanWidth]; layoutData.totHeight _ realTotHeight _ upperActiveLimit + bpRows[top].size.q; rightActiveLimit _ sideChans[right].sideChanPos + MAX[sideChans[right].sideChanWidth, sideChans[right].minSideChanWidth]; layoutData.totWidth _ rightActiveLimit + bpRows[right].size.q; <> bpRows[bottom].sideOrg.q _ 0; bpRows[bottom].sideOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth - sideDim[bottom]) / 2; <> IF bpRows[top].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, top]; IF bpRows[right].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, right]; bpRows[right].sideOrg.p _ rightActiveLimit; bpRows[right].sideOrg.q _ (realTotHeight - sideDim[right])/ 2; <> bpRows[top].sideOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth + sideDim[top])/ 2; bpRows[top].sideOrg.q _ upperActiveLimit; <> bpRows[left].sideOrg.p _ 0; bpRows[left].sideOrg.q _ (realTotHeight +sideDim[left])/ 2; END; <> ChansForInsts: PUBLIC PROCEDURE[handle: SC.Handle, insts: SCPrivate.InstanceList] RETURNS [touchesChan: SCPrivate.ChanSet _ RTSets.RTMdSetEmpty] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; FOR instList: SCPrivate.InstanceList _ insts, instList.rest WHILE instList # NIL DO inst: SCPrivate.Instance _ instList.first; SELECT inst.whichClass FROM ft, logic => {IF inst.curRow > 0 THEN {touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(inst.curRow+1)-1]]; touchesChan _ RTSets.RTMdSetUnion[touchesChan , RTSets.RTMdSetGenerateElement[(inst.curRow)-1]]}}; io => {IF inst.curSide = bottom THEN touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(1)-1]]; IF inst.curSide = top THEN touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(layoutData.rowChans.count)-1]]}; ENDCASE; ENDLOOP}; <> CheckInst: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; SELECT inst.whichClass FROM logic, ft => {row: SC.Number _ inst.curRow; pos: SC.Number _ inst.curPos; lgRow: SCPrivate.LgRow _ layoutData.lgRows.rows[row]; IF row <= 0 OR row > layoutData.rowChans.count THEN {IF ~(row = 0 AND pos = 0 AND inst.whichClass = ft) THEN SC.Error[programmingError, " "]} ELSE IF pos <= 0 OR pos > lgRow.nLgsOnRow THEN SC.Error[programmingError, " "] ELSE {trialInst: SCPrivate.Instance _ lgRow.lgsOnRow[pos]; IF inst # trialInst THEN SC.Error[programmingError, " "]}}; io => {side: SC.Side _ inst.curSide; pos: SC.Number _ inst.curPos; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; IF side = none THEN SC.Error[programmingError, " "] ELSE IF pos <= 0 OR pos > bpRow.nBpsOnSide THEN SC.Error[programmingError, " "] ELSE {trialInst: SCPrivate.Instance _ bpRow.bpsOnSide[pos]; IF inst # trialInst THEN SC.Error[programmingError, " "]}}; ENDCASE}; <> CheckInsts: PUBLIC PROCEDURE[handle: SC.Handle] = { EachInst: SCInstUtil.EachInstanceProc = { CheckInst[handle, instance]}; [] _ SCInstUtil.EnumerateInstances[handle, EachInst]}; EnumerateInstances: PUBLIC PROC [handle: SC.Handle, eachInstance: SCInstUtil.EachInstanceProc] RETURNS [quit: BOOL] = { structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; FOR inst: SCPrivate.MaxInstanceSr IN [1 .. structureData.instances.count] DO [] _ eachInstance[structureData.instances.inst[inst]]; ENDLOOP}; EnumeratePinsOnInst: PUBLIC PROC [instance: SCPrivate.Instance, eachPin: SCInstUtil.EachPinProc] RETURNS [quit: BOOL _ FALSE] = { FOR pin: NAT IN [0 .. instance.pinNets.size) WHILE ~quit DO quit _ eachPin[instance, pin, instance.pinNets.n[pin]]; ENDLOOP}; DefineInstance: PUBLIC PROCEDURE [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, coreInstance: CoreClasses.CellInstance, equivName: Rope.ROPE _ NIL] RETURNS [instance: SCPrivate.Instance _ NIL] = { <<>> <> structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; instances: SCPrivate.Instances _ structureData.instances; object.numTimesUsed _ object.numTimesUsed + 1; <> SELECT object.typeClass FROM logic => {instance _ NEW[logic SCPrivate.InstanceRec]; instance.whichClass _ logic; instances.numLogics _ instances.numLogics + 1}; ft => {instance _ NEW[ft SCPrivate.InstanceRec]; instance.whichClass _ ft; instances.numFts _ instances.numFts + 1}; io => {instance _ NEW[io SCPrivate.InstanceRec]; instance.equivPortClass _ equivName; instance.whichClass _ io; instances.numIOs _ instances.numIOs + 1}; ENDCASE => SC.Error[callingError, Rope.Cat["Feedthrus not allowed in input: ", instance.name, ", object: ", object.name, "\n"]]; instance.name _ instanceName; instance.object _ object; <> instance.pinNets _ NEW[SCPrivate.PinNetsRec[object.numPins]]; instances.count _ instances.count + 1; instance.instanceNum _ instances.count; instances.inst[instances.count] _ instance}; NumInstsOnList: PUBLIC PROCEDURE [instances: SCPrivate.InstanceList] RETURNS [count: SCPrivate.ZMaxInstanceSr _ 0] = { FOR instList: SCPrivate.InstanceList _ instances, instList.rest WHILE instList # NIL DO count _ count + 1; ENDLOOP}; END.