<> <> <> <<>> <<>> DIRECTORY CD, CDCells, CDExtras, CDFrame, CDIO, CDOps, CDOrient, CDPinObjects, CDProperties, CDRects USING [CreateRect], CDSequencer, CDSil, CDSimpleOps, CDViewer, Convert, Commander, DragOpsCross, IFUPW, IO, PW, PWPins, Rope, ViewerClasses; IFUPWImpl: CEDAR PROGRAM IMPORTS CD, CDCells, CDExtras, CDFrame, CDIO, CDOps, CDPinObjects, CDProperties, CDRects, CDSequencer, CDSil, CDSimpleOps, CDViewer, Convert, IO, IFUPW, PW, PWPins, Rope EXPORTS IFUPW = BEGIN OPEN IFUPW; Error: PUBLIC ERROR[msg: ROPE] = CODE; log: PUBLIC IO.STREAM _ CDFrame.GetLog[]; GND: PUBLIC Rope.ROPE _ "GND"; VDD: PUBLIC Rope.ROPE _ "VDD"; IFUDataColSeq: PUBLIC RowParams _ NEW[RowParamsRec _ [seq: TRUE] ]; IFUDataColNSeq: PUBLIC RowParams _ NEW[RowParamsRec _ [seq: FALSE] ]; ChangePinName: PUBLIC PROC[obj: CD.Object, oldName, newName: ROPE] = { pins: CD.InstanceList _ CDPinObjects.FindPins[obj, oldName]; FOR pins _ pins, pins.rest WHILE pins#NIL DO CDPinObjects.SetName[pins.first, newName] ENDLOOP }; ConnSpec: TYPE = REF ConnSeqRec; ConnSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF CnntRec]; CnntRec: TYPE = RECORD[name: Rope.ROPE, y: INT]; BuildConnSpec: PROC[in, out: List, topY, botY, refY: INT, refCell: CD.Object] RETURNS[connSpec: ConnSpec] = { done: BOOL _ FALSE; size, index: CARDINAL _ ListLength[in] + ListLength[out] + 2; connSpec _ NEW[ConnSeqRec[size]]; connSpec[size-1].name _ NIL; connSpec[size-1].y _ topY; connSpec[0].name _ NIL; connSpec[0].y _ botY; index _ 1; FOR ii: INT IN [0..ListLength[in]) DO connSpec[index].name _ in.first; in _ in.rest; connSpec[index].y _ refY + CDPinObjects.FindPins[refCell, IO.PutFR["In%g", IO.int[ii]]].first.location.y; index _ index + 1 ENDLOOP; FOR ii: INT IN [0..ListLength[out]) DO connSpec[index].name _ out.first; out _ out.rest; connSpec[index].y _ refY + CDPinObjects.FindPins[refCell, IO.PutFR["Out%g", IO.int[ii]]].first.location.y; index _ index + 1 ENDLOOP; WHILE NOT done DO done _ TRUE; FOR ii: INT IN [0..size-1) DO ty: INT _ connSpec[ii].y; tname: Rope.ROPE _ connSpec[ii].name; IF connSpec[ii].y <= connSpec[ii+1].y THEN LOOP; done _ FALSE; connSpec[ii].y _ connSpec[ii+1].y; connSpec[ii].name _ connSpec[ii+1].name; connSpec[ii+1].y _ ty; connSpec[ii+1].name _ tname ENDLOOP ENDLOOP }; IOConnect: PUBLIC PROC[ design: CD.Design, cell: CD.Object, top: List, in: List, out: List, bot: List, refcell: CD.Object, refX: INT, refY: INT, topY: INT, botY: INT ] = { PurgeNILLsFromList: PUBLIC PROC [list: List] RETURNS[clean: List] = { IF list = NIL THEN RETURN[NIL]; clean _ PurgeNILLsFromList[list.rest]; IF list.first#NIL THEN clean _ CONS[list.first, clean]}; Same: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = {RETURN[Rope.Equal[connSpec[idx1].name, connSpec[idx2].name]]}; connSpec: ConnSpec; tIdx, bIdx: CARDINAL _ 0; in _ PurgeNILLsFromList[in]; out _ PurgeNILLsFromList[out]; connSpec _ BuildConnSpec[in, out, topY, botY, refY, refcell]; tIdx _ connSpec.size-1; bIdx _ 0; FOR i: INT IN [0..nofVWires) DO Add: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = { IF ~Same[idx1, idx2] THEN RETURN[FALSE]; loc.y _ connSpec[idx1].y; size.y _ connSpec[idx2].y - connSpec[idx1].y; IF size.y < 0 THEN ERROR; AddRet[cell:cell, size: size, loc: loc, level: cmosMet]; RETURN[TRUE]}; size: Size _ [metW, 0]; loc: Location _ [refX+i*metPitch+leftTail, 0]; connSpec[tIdx].name _ ListIndexItem[top, i]; connSpec[bIdx].name _ ListIndexItem[bot, i]; IF connSpec[tIdx].name#NIL THEN FOR ii: INT IN [bIdx..tIdx) DO IF Add[ ii, tIdx] THEN EXIT; REPEAT FINISHED => ERROR Error [IO.PutFR["Orphan top signal: %g", IO.rope[connSpec[tIdx].name]]] ENDLOOP; IF connSpec[bIdx].name#NIL THEN FOR ii: INT DECREASING IN (bIdx..tIdx) DO IF Add[ bIdx, ii] THEN EXIT; REPEAT FINISHED => IF ~Same[bIdx, tIdx] THEN ERROR Error[IO.PutFR["Orphan bottom signal: %g", IO.rope[connSpec[bIdx].name]]] ENDLOOP; ENDLOOP; <> IF ListLength[out]#0 THEN FOR i: INT IN [0..nofVWires) DO AddCnt: PROC[idx: CARDINAL] = { ctct, wire: CD.Object; IF ~Same[idx, tIdx] AND ~Same[idx, bIdx] THEN RETURN; wLoc.y _ connSpec[idx].y; ctct _ Contact[cmosPoly]; wire _ CDRects.CreateRect[[wLen, polW], cmosPoly]; [] _ PW.IncludeInCell[cell, ctct, [wLoc.x-(cnctSize-metW)/2, wLoc.y-(cnctSize-polW)/2]]; [] _ PW.IncludeInCell[cell, wire, wLoc] }; wLen: INT _ (nofVWires-1-i)*metPitch + cnctSize; wLoc: Location _ [refX+i * metPitch +leftTail, 0]; connSpec[tIdx].name _ ListIndexItem[top, i]; connSpec[bIdx].name _ ListIndexItem[bot, i]; FOR ii: INT IN (bIdx..tIdx) DO AddCnt[ii] ENDLOOP; ENDLOOP }; AddMetalPins: PUBLIC PROC [cell: CD.Object, top, bot: List, refX, topY, botY: INT, realNames: BOOL] = { length: INT _ MAX[ListLength[top], ListLength[bot]]; FOR i: INT IN [0..length) DO tName: ROPE _ ListIndexItem[top, i]; bName: ROPE _ ListIndexItem[bot, i]; size: Size _ [metW, metW]; loc: Location _ [refX+i*metPitch+leftTail, topY-size.y]; IF tName #NIL THEN PutPin [cell, size, loc, cmosMet, (IF realNames THEN tName ELSE NIL)]; IF bName #NIL THEN PutPin [cell, size, [loc.x, botY], cmosMet, (IF realNames THEN bName ELSE NIL)]; ENDLOOP }; AddRet: PUBLIC PROC [cell: CD.Object, size: Size, loc: Location, level: CD.Layer] = { <> IF size.x<0 OR size.y<0 THEN ERROR Error[IO.PutFR ["Strange rectangle size [%g, %g]", IO.int[size.x], IO.int[size.y]]]; IF size.x=0 OR size.y=0 THEN RETURN; [] _ PW.IncludeInCell[cell, CDRects.CreateRect[size, level], loc]}; PutPin: PUBLIC PROC[cell:CD.Object, size:Size, loc:Location, level:CD.Layer, name:ROPE] = { pinApl: CD.Instance _ PW.IncludeInCell[cell, CDPinObjects.CreatePinOb[size], loc]; CDPinObjects.SetName[pinApl, name]; CDPinObjects.SetLayer[pinApl, level]}; <> <> <> <> <> <> <> <> <> <<[ ] _ PW.IncludeInCell[obj, obj1, [0, 0]];>> <