<> <> <> <> <> <<>> DIRECTORY CD, CDOrient, CDCells, CDPinObjects, CDProperties, CMos, Convert, MC, MCCtl, PW, TerminalIO, PWCmos, PWPins, Rope; MCImpl: CEDAR PROGRAM IMPORTS CD, CDOrient, CDCells, CDPinObjects, CDProperties, CMos, Convert, TerminalIO, PWCmos, PWPins, PW, Rope EXPORTS MC = BEGIN nLines: PUBLIC INT _ 32; nCamColumns: PUBLIC INT _ 20; nRamColumns: PUBLIC INT _ 44; nEntriesPerLine: PUBLIC INT _ 4; VddRingWidth: PUBLIC INT _ 100* GndRingWidth: PUBLIC INT _ 100* CellToIR: PUBLIC PROC [cellpos: CD.Position, obj: CD.ObPtr] RETURNS [irpos: CD.Position] = { ir: CD.Rect _ CD.InterestRect[obj]; irpos _ [cellpos.x-ir.x1, cellpos.y-ir.y1]; }; IRToCell: PUBLIC PROC [irpos: CD.Position, obj: CD.ObPtr] RETURNS [cellpos: CD.Position] = { ir: CD.Rect _ CD.InterestRect[obj]; cellpos _ [irpos.x+ir.x1, irpos.y+ir.y1]; }; SelectAll: PUBLIC MC.SelectPinProc = {sel _ TRUE}; IndexedName: PUBLIC PROC [name: Rope.ROPE, index: INT] RETURNS [Rope.ROPE] = { RETURN[Rope.Cat[name, "[", Convert.RopeFromInt[index], "]"]]; }; TTYOut: PUBLIC PROC [r1, r2, r3, r4, r5, r6: Rope.ROPE _ NIL] = { TerminalIO.WriteRope[Rope.Cat[r1, r2, r3, r4, r5, r6]]; }; CreateFillerCell: PUBLIC PROC [design: CD.Design, size: CD.Position] RETURNS [result: PW.ObPtr] = { result _ PW.CreateEmptyCell[]; CDCells.SetInterestRect[result, [0, 0, size.x, size.y]]; PW.IncludeInCell[design, result, CDPinObjects.CreatePinOb[[2, 2]], [size.x/2, size.y/2]]; PW.IncludeInDirectory[design, result, "FillerCell"]; }; TopFillerCell: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, fillDist: INT, selectPinProc: MC.SelectPinProc _ SelectAll] RETURNS [result: PW.ObPtr] = { objIR: CD.Rect _ CD.InterestRect[obj]; resultPtr: CD.CellPtr; ProcessEdgePin: PWPins.AppEnumerator = { side: PWPins.Side _ PWPins.GetSide[obj, app].side; newPin: CD.ApplicationPtr; IF side=PWPins.top AND selectPinProc[app] THEN { pinSize: CD.Position _ CDOrient.OrientedSize[app.ob.size, app.orientation]; <> PW.IncludeInCell[design, result, PWCmos.Rect[CDPinObjects.GetLayer[app], [pinSize.x, fillDist]], -- size [app.location.x-objIR.x1, 0]]; -- location <> newPin _ NEW[CD.Application _ [ ob: CDPinObjects.CreatePinOb[app.ob.size], location: [app.location.x-objIR.x1, fillDist-pinSize.y], orientation: app.orientation, properties: CDProperties.CopyProps[app.properties]]]; CDPinObjects.SetName[newPin, CDPinObjects.GetName[app]]; resultPtr.contents _ CONS[newPin, resultPtr.contents]; }; }; IF fillDist<=0 THEN ERROR; result _ PW.CreateEmptyCell[]; resultPtr _ NARROW[result.specificRef]; CDCells.SetInterestRect[result, [0, 0, objIR.x2-objIR.x1, fillDist]]; [] _ PWPins.EnumerateEdgePins[obj, ProcessEdgePin]; PW.IncludeInDirectory[design, result, "Filler"]; result _ PWPins.RenamePins[design, result]; }; LeftFillerCell: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, fillDist: INT, selectPinProc: MC.SelectPinProc _ SelectAll] RETURNS [result: PW.ObPtr] = { RETURN[PW.Rot90[design, TopFillerCell[design, PW.Rot270[design, obj], fillDist, selectPinProc]]]; }; RightFillerCell: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, fillDist: INT, selectPinProc: MC.SelectPinProc _ SelectAll] RETURNS [result: PW.ObPtr] = { RETURN[PW.Rot270[design, TopFillerCell[design, PW.Rot90[design, obj], fillDist, selectPinProc]]]; }; MakeBusX: PUBLIC PROC [design: CD.Design, layer: CD.Layer, names: LIST OF Rope.ROPE, wireLength, wireThickness, wireSeparation: INT] RETURNS [result: PW.ObPtr] = { resultPtr: CD.CellPtr; nWires: INT _ 0; IF wireLength<=0 OR wireThickness<=0 THEN ERROR; result _ PW.CreateEmptyCell[]; resultPtr _ NARROW[result.specificRef]; FOR l: LIST OF Rope.ROPE _ names, l.rest UNTIL l=NIL DO leftPin, rightPin: CD.ApplicationPtr; wireLocation: CD.Position _ [0, wireSeparation+nWires*(wireThickness+wireSeparation)]; PW.IncludeInCell[design, result, PWCmos.Rect[layer, [wireLength, wireThickness]], wireLocation]; <> leftPin _ NEW[CD.Application _ [ ob: CDPinObjects.CreatePinOb[[2, wireThickness]], location: wireLocation, orientation: CDOrient.original]]; rightPin _ NEW[CD.Application _ [ ob: CDPinObjects.CreatePinOb[[2, wireThickness]], location: [wireLength-2, wireLocation.y], orientation: CDOrient.original]]; CDPinObjects.SetName[leftPin, l.first]; CDPinObjects.SetName[rightPin, l.first]; CDPinObjects.SetLayer[leftPin, layer]; CDPinObjects.SetLayer[rightPin, layer]; resultPtr.contents _ CONS[leftPin, resultPtr.contents]; resultPtr.contents _ CONS[rightPin, resultPtr.contents]; nWires _ nWires+1; ENDLOOP; CDCells.SetInterestRect[result, [0, 0, wireLength, wireSeparation+nWires*(wireThickness+wireSeparation)]]; PW.IncludeInDirectory[design, result, "Bus"]; }; MakeBusY: PUBLIC PROC [design: CD.Design, layer: CD.Layer, names: LIST OF Rope.ROPE, wireLength, wireThickness, wireSeparation: INT] RETURNS [result: PW.ObPtr] = { result _ PW.Rot270[design, MakeBusX[design, layer, names, wireLength, wireThickness, wireSeparation]]; }; ConnectTopToBus: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, bus: PW.ObPtr] RETURNS[result: PW.ObPtr] = { objIR: CD.Rect _ CD.InterestRect[obj]; busIR: CD.Rect _ CD.InterestRect[bus]; resultIR: CD.Rect _ [0, 0, objIR.x2-objIR.x1, busIR.y2-busIR.y1]; ProcessObjPin: PWPins.AppEnumerator = { <<[app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE]>> side: PWPins.Side _ PWPins.GetSide[obj, app].side; objPinName: Rope.ROPE _ CDPinObjects.GetName[app]; objPinLayer: CD.Layer _ CDPinObjects.GetLayer[app]; busPin: CD.ApplicationPtr _ NIL; SetBusPin: PWPins.AppEnumerator = { <<[app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE]>> side: PWPins.Side _ PWPins.GetSide[bus, app].side; IF Rope.Equal[CDPinObjects.GetName[app], objPinName] AND side=PWPins.left THEN busPin _ app; }; IF side=PWPins.top THEN { appSize: CD.Position _ CDOrient.OrientedSize[app.ob.size, app.orientation]; busPinSize: CD.Position; <> [] _ PWPins.EnumerateEdgePins[bus, SetBusPin]; IF busPin=NIL THEN { <> TTYOut[" MCImpl: ", objPinName, " "]; RETURN; }; busPinSize _ CDOrient.OrientedSize[busPin.ob.size, busPin.orientation]; <> PW.IncludeInCell[design, result, PWCmos.Rect[CDPinObjects.GetLayer[app], [appSize.x, busPin.location.y+busPinSize.y-busIR.y1]], -- size [app.location.x-objIR.x1, 0]]; -- location <> PW.IncludeInCell[design, result, PWCmos.Contact[CMos.met, CMos.met2], [app.location.x-objIR.x1-2, busPin.location.y-busIR.y1]]; }; }; result _ PW.CreateEmptyCell[]; CDCells.SetInterestRect[result, resultIR]; [] _ PWPins.EnumerateEdgePins[obj, ProcessObjPin]; PW.IncludeInDirectory[design, result, "ExtensionTopToBus"]; }; ConnectBotToBus: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, bus: PW.ObPtr] RETURNS[result: PW.ObPtr] = { result _ PW.FlipY[design, ConnectTopToBus[design, PW.FlipY[design, obj], PW.FlipY[design, bus]]]; }; ConnectRightToBus: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, bus: PW.ObPtr] RETURNS[result: PW.ObPtr] = { result _ PW.Rot270[design, ConnectTopToBus[design, PW.Rot90[design, obj], PW.Rot90[design, bus]]]; }; ConnectLeftToBus: PUBLIC PROC [design: CD.Design, obj: PW.ObPtr, bus: PW.ObPtr] RETURNS[result: PW.ObPtr] = { result _ PW.Rot90[design, ConnectTopToBus[design, PW.Rot270[design, obj], PW.Rot270[design, bus]]]; }; END.