<> <> <> <> <> <<>> DIRECTORY AlpsBool, AlpsHeur, AlpsTile, AlpsPWGen, CD, CDCells, CDDirectory, CDExtras, CDPinObjects, CDIO, CMos, Convert, MC, MCCtl, PW, PWCmos, PWPins, Rope; MCCtlImpl: CEDAR PROGRAM IMPORTS AlpsBool, AlpsHeur, AlpsPWGen, CD, CDCells, CDDirectory, CDExtras, CDPinObjects, CDIO, Convert, CMos, MC, PW, PWPins, Rope EXPORTS MCCtl = BEGIN OPEN AlpsBool, MCCtl; ctlOutNames: PUBLIC LIST OF Rope.ROPE; InitCtlOutNames: PUBLIC PROC [] = { ctlOutNames _ NIL; }; AddListToCtlOutNames: PUBLIC PROC[names: LIST OF Rope.ROPE] = { FOR l: LIST OF Rope.ROPE _ names, l.rest UNTIL l=NIL DO ctlOutNames _ CONS[l.first, ctlOutNames]; ENDLOOP; }; AddTableToCtlOutNames: PUBLIC PROC [table: TableOfVariables] = { FOR l: LIST OF OutputRef _ table.outputs, l.rest UNTIL l=NIL DO ctlOutNames _ CONS[l.first.name, ctlOutNames]; ENDLOOP; }; CreateTable: PUBLIC PROC [names: LIST OF ROPE] RETURNS [table: TableOfVariables] = { count: INT _ 1; FOR list: LIST OF ROPE _ names, list.rest WHILE list#NIL DO count _ count+1 ENDLOOP; table _ InitTableOfVariables[count]; count _ 1; FOR list: LIST OF ROPE _ names, list.rest WHILE list#NIL DO table[count].name _ list.first; count _ count + 1; ENDLOOP; }; EqualInt: PUBLIC PROC [table: TableOfVariables, rope: ROPE, start, end, value: INT] RETURNS [Expression] = { expr: Expression; IF start>end THEN RETURN[true]; expr _ Find[table, MC.IndexedName[rope, end]]; RETURN [And[table, IF (value MOD 2) = 1 THEN expr ELSE Not[expr], EqualInt[table, rope, start, end-1, value/2]]]; }; FindInternal: PUBLIC PROC [table: TableOfVariables, rope: ROPE] RETURNS [internalIndex: INT] = { FOR i: INT IN [1..table.size) DO IF Rope.Equal[rope, table[i].name] THEN RETURN [i]; ENDLOOP; ERROR; }; Find: PUBLIC PROC [table: TableOfVariables, rope: ROPE] RETURNS [Expression] = { RETURN [Var[FindInternal[table, rope]]]; }; DefaultDontCare: PUBLIC PROC [] RETURNS [Expression] = { RETURN[false]; }; GenerateLayout: PUBLIC PROC [design: CD.Design, table: TableOfVariables, distanceBetweenGlue: INT _ 5] RETURNS [obj: CD.ObPtr] = { <<>> <> BEGIN file: ROPE _ "AlpsCells"; IF CDDirectory.Fetch[design, file].found THEN Output["AlpsCells already present in design\n"] ELSE BEGIN to: CD.Design _ design; Check: PROC [design: CD.Design] RETURNS [ok: BOOL] = BEGIN ok _ design.technology=to.technology; IF ~ok THEN Output["Technology mismatch: includee is ", design.technology.name, "\n"]; END; from: CD.Design _ CDIO.ReadDesign[file, Check]; Output["Design AlpsCells read and included in the design"]; [] _ CDExtras.MergeIn[design: to, from: from, name: file]; END; END; <> BEGIN input, aux, output, latch: INT; [input, aux, output, latch] _ AlpsBool.NbOfVars[table]; Output[" Input: ", Convert.RopeFromInt[input], " Aux: ", Convert.RopeFromInt[aux], " Output: ", Rope.Cat[Convert.RopeFromInt[output], " Latch: ", Convert.RopeFromInt[latch], "\n"]]; END; <<>> <> BEGIN alpsTileContext: AlpsTile.Context _ NEW[AlpsTile.ContextRec _ [design: design, table: table, distanceBetweenGlue: distanceBetweenGlue, distanceBetweenContacts: 20, debug: FALSE]]; Output["\nLet's start Layout!"]; obj _ AlpsPWGen.TableToLayout[alpsTileContext]; Output["Done!"]; END; }; InputsFromTable: PUBLIC PROC [table: TableOfVariables] RETURNS [inputs: LIST OF ROPE _ NIL] = { FOR i: INT DECREASING IN [1..table.size) DO inputs _ CONS[table[i].name, inputs] ENDLOOP; }; Permute: PUBLIC PROC [table: TableOfVariables, permute: PermuteFlags _ permuteFast] RETURNS [newTable: TableOfVariables] = { SELECT permute FROM dontPermute => newTable _ table; permuteFast => newTable _ AlpsHeur.BestPermuteInfinitely[table, AlpsHeur.ImproveAreaAndDelay]; permuteAllCases => newTable _ AlpsHeur.AllPermute[table, AlpsHeur.ImproveAreaAndDelay, 200]; -- Increase if it writes "Aborted" on the terminal and you want to try more. ENDCASE => ERROR; }; ListSize: PUBLIC PROC [list: LIST OF ROPE] RETURNS [size: INT _ 0] = { FOR l: LIST OF ROPE _ list, l.rest UNTIL l=NIL DO size _ size+1 ENDLOOP; }; ListCat: PUBLIC PROC [l1, l2: LIST OF ROPE] RETURNS[l3: LIST OF ROPE] = { l3 _ l2; FOR l: LIST OF Rope.ROPE _ l1, l.rest UNTIL l=NIL DO l3 _ CONS[l.first, l3]; ENDLOOP; }; MakeAlpsLatchandDrive: PUBLIC PROC [design: CD.Design, target: PW.ObPtr] RETURNS [result: PW.ObPtr] = { phASlice: PW.ObPtr _ PW.Get[design, "phALatchandDriveSlice"]; phBSlice: PW.ObPtr _ PW.Get[design, "phBLatchandDriveSlice"]; unLatchedDriveSlice: PW.ObPtr _ PW.Get[design, "unLatchedDriveSlice"]; targetIR: CD.Rect _ CD.InterestRect[target]; sliceIR: CD.Rect _ CD.InterestRect[phASlice]; resultIR: CD.Rect _ [0, 0, targetIR.x2-targetIR.x1, sliceIR.y2-sliceIR.y1]; attatchment: PW.ObPtr; attatchmentIR: CD.Rect; targetPinPosInResult: CD.Position; attatchmentIRPosInResult: CD.Position _ [0, 0]; ProcessTargetPin: PWPins.AppEnumerator = { <<[app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE]>> side: PWPins.Side _ PWPins.GetSide[target, app].side; name: ROPE _ CDPinObjects.GetName[app]; layer: CD.Layer _ CDPinObjects.GetLayer[app]; ProcessAttatchmentPin: PWPins.AppEnumerator = { <<[app: CD.ApplicationPtr] RETURNS [quit: BOOL _ FALSE]>> side: PWPins.Side _ PWPins.GetSide[attatchment, app].side; IF side=PWPins.top THEN attatchmentIRPosInResult.x _ targetPinPosInResult.x-(app.location.x-attatchmentIR.x1); }; NewName: PWPins.RenameProc = {newRope _ name}; targetPinPosInResult _ [app.location.x-targetIR.x1, sliceIR.y2-sliceIR.y1]; IF side=PWPins.bottom AND (layer=CMos.met) AND (Rope.Index[name, 0, "Not"]#0) THEN { SELECT TRUE FROM Rope.Match["xAB", name] => attatchment _ PWPins.RenamePins[design, phASlice, NewName]; Rope.Match["xBA", name] => attatchment _ PWPins.RenamePins[design, phBSlice, NewName]; ENDCASE => attatchment _ PWPins.RenamePins[design, unLatchedDriveSlice, NewName]; attatchmentIR _ CD.InterestRect[attatchment]; [] _ PWPins.EnumerateEdgePins[phASlice, ProcessAttatchmentPin]; PW.IncludeInCell[design, result, attatchment, [attatchmentIRPosInResult.x, attatchmentIRPosInResult.y]] }; }; result _ PW.CreateEmptyCell[]; CDCells.SetInterestRect[result, resultIR]; [] _ PWPins.EnumerateEdgePins[target, ProcessTargetPin]; <<>> <> BEGIN leftFillDist: INT _ attatchmentIRPosInResult.x; rightFillDist: INT _ (resultIR.x2-resultIR.x1)- (attatchmentIRPosInResult.x+attatchmentIR.x2-attatchmentIR.x1); IF leftFillDist > 0 THEN PW.IncludeInCell[design, result, MC.LeftFillerCell[design, attatchment, leftFillDist], [0, 0]]; IF rightFillDist > 0 THEN PW.IncludeInCell[design, result, MC.RightFillerCell[design, attatchment, rightFillDist], [attatchmentIRPosInResult.x+attatchmentIR.x2-attatchmentIR.x1, 0]]; END; PW.IncludeInDirectory[design, result, "LatchResult"]; }; MakeFeedBackLatchandDrive: PUBLIC PROC[design: CD.Design, signals: LIST OF ROPE] RETURNS [result: PW.ObPtr] = { nbFedBackInputs: INT _ ListSize[signals]; phASlice: PW.ObPtr _ PW.Get[design, "FBphAlatchandDriveSlice"]; phBSlice: PW.ObPtr _ PW.Get[design, "FBphBLatchandDriveSlice"]; unLatchedDriveSlice: PW.ObPtr _ PW.Get[design, "FBunLatchedDriveSlice"]; glue: PW.ObPtr _ PW.Get[design, "FeedBackLatchToOutputLatchGlue"]; sliceIR: CD.Rect _ CD.InterestRect[phASlice]; -- all slices must have same IR glueIR: CD.Rect _ CD.InterestRect[glue]; resultIR: CD.Rect _ [0, 0, nbFedBackInputs*(sliceIR.x2-sliceIR.x1)+glueIR.x2-glueIR.x1, sliceIR.y2-sliceIR.y1]; sliceNum: INT _ 0; name: ROPE; NewName: PWPins.RenameProc = { index: INT; newRope _ oldRope; IF Rope.Equal[oldRope, "in"] OR Rope.Equal[oldRope, "out"] THEN newRope _ name; IF Rope.Equal[oldRope, "Notout"] THEN newRope _ Rope.Cat["Not", name]; IF Rope.Find[name, "CyclexAB"] # -1 THEN RETURN; IF Rope.Equal[oldRope, "out"] AND (index _ Rope.Find[name, "xAB"])#-1 THEN newRope _ Rope.Replace[name, index, 3, "xBA"]; IF Rope.Equal[oldRope, "Notout"] AND (index _ Rope.Find[name, "xAB"])#-1 THEN newRope _ Rope.Cat["Not", Rope.Replace[name, index, 3, "xBA"]]; IF Rope.Equal[oldRope, "out"] AND (index _ Rope.Find[name, "xBA"])#-1 THEN newRope _ Rope.Replace[name, index, 3, "xAB"]; IF Rope.Equal[oldRope, "Notout"] AND (index _ Rope.Find[name, "xBA"])#-1 THEN newRope _ Rope.Cat["Not", Rope.Replace[name, index, 3, "xAB"]]; }; SpecialNewName: PWPins.RenameProc = { index: INT; IF Rope.Equal[oldRope, "out"] THEN newRope _ name; IF Rope.Equal[oldRope, "Notout"] THEN newRope _ Rope.Cat["Not", name]; IF Rope.Equal[oldRope, "in"] AND (index _ Rope.Find[name, "xBA"])#-1 THEN newRope _ Rope.Replace[name, index, 3, "xAB"]; }; result _ PW.CreateEmptyCell[]; CDCells.SetInterestRect[result, resultIR]; FOR l: LIST OF ROPE _ signals, l.rest WHILE l#NIL DO slice: PW.ObPtr; name _ l.first; SELECT TRUE FROM Rope.Find[name, "CyclexAB"] # -1 => slice _ PWPins.RenamePins[design, unLatchedDriveSlice, NewName]; Rope.Find[name, "CyclexBA"] # -1 => slice _ PWPins.RenamePins[design, phBSlice, SpecialNewName]; Rope.Find[name, "xAB"] # -1 => slice _ PWPins.RenamePins[design, phBSlice, NewName]; Rope.Find[name, "xBA"] # -1 => slice _ PWPins.RenamePins[design, phASlice, NewName]; ENDCASE => slice _ PWPins.RenamePins[design, unLatchedDriveSlice, NewName]; PW.IncludeInCell[design, result, slice, [sliceNum*(sliceIR.x2-sliceIR.x1), 0]]; sliceNum _ sliceNum+1; ENDLOOP; PW.IncludeInCell[design, result, glue, [nbFedBackInputs*(sliceIR.x2-sliceIR.x1), 0]]; PW.IncludeInDirectory[design, result, "FeedBackLatchandDrive"]; }; MakeFeedBack: PUBLIC PROC [design: CD.Design, alpsTarget, latchTarget: PW.ObPtr] RETURNS [result: PW.ObPtr] = { alpsTargetIR: CD.Rect _ CD.InterestRect[alpsTarget]; latchTargetIR: CD.Rect _ CD.InterestRect[latchTarget]; resultIR: CD.Rect _ [0, 0, latchTargetIR.x2-latchTargetIR.x1, alpsTargetIR.y2-alpsTargetIR.y1]; bus: PW.ObPtr; SelectPin: MC.SelectPinProc -- [pin: CD.ApplicationPtr] RETURNS [sel: BOOL] -- = { sel _ (CDPinObjects.GetLayer[pin]=CMos.met2); }; result _ PW.CreateEmptyCell[]; CDCells.SetInterestRect[result, resultIR]; <> PW.IncludeInCell[design, result, bus _ MC.LeftFillerCell[design, alpsTarget, resultIR.x2-resultIR.x1, SelectPin], [0, 0]]; <> PW.IncludeInCell[design, result, MC.ConnectTopToBus[design, latchTarget, bus], [0, 0]]; PW.IncludeInDirectory[design, result, "FeedBack"]; }; <<>> END.