DIRECTORY Boole, BooleCore, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, HashTable, IO, PW, PWObjects, PWCore, Rope, Sinix, Sisyph, TilingClass, TerminalIO; BooleCoreImpl: CEDAR PROGRAM IMPORTS Boole, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, CoreClasses, CoreCreate, CoreOps, CoreProperties, HashTable, IO, PW, PWObjects, PWCore, Rope, Sinix, Sisyph, TilingClass, TerminalIO EXPORTS BooleCore SHARES Boole = BEGIN OPEN BooleCore; false: Expression = Boole.false; true: Expression = Boole.true; Signal: SIGNAL = CODE; debug: BOOL _ TRUE; cellLibrary: PRIVATE CD.Design _ NIL; GetCellLibrary: PUBLIC PROC RETURNS [CD.Design] = { IF cellLibrary#NIL THEN RETURN [cellLibrary]; cellLibrary _ PW.OpenDesign["BooleLibrary"]; RETURN [cellLibrary]; }; GetCellLibraryCell: PUBLIC PROC [name: ROPE] RETURNS [CellType _ NIL] = { name _ Rope.Cat[name, ".sch"]; IF CDDirectory.Fetch[GetCellLibrary[], name].object=NIL THEN RETURN [NIL]; RETURN [Sisyph.ES[name, Sisyph.Create[GetCellLibrary[]]]]; }; EqualInt: PUBLIC PROC [wire: Wire, int: INT] RETURNS [expr: Expression] = { Andify: PROC [wire: Wire] = { var: Variable _ wire; max _ max / 2; IF int>=max THEN int _ int - max ELSE var _ Boole.Not[var]; expr _ Boole.And[var, expr]; }; count: NAT _ CoreOps.WireBits[wire]; max: INT _ 1; WHILE count>0 DO max _ max * 2; count _ count -1 ENDLOOP; IF int>=max THEN Signal[]; expr _ true; CoreOps.VisitRootAtomics[wire, Andify]; IF int#0 THEN Signal[]; }; TranslateVar: PROC [wireToRefInt: HashTable.Table, source: Expression] RETURNS [Expression] = { whenTrue, whenFalse: Expression; var: Variable = Boole.FindVar[source]; newVar: Variable _ NARROW [HashTable.Fetch[wireToRefInt, var].value]; IF source=true OR source=false THEN RETURN [source]; [whenTrue, whenFalse] _ Boole.Eval[var, source]; IF newVar=NIL THEN ERROR; -- variable is not an input wire! RETURN [Boole.If[newVar, TranslateVar[wireToRefInt, whenTrue], TranslateVar[wireToRefInt, whenFalse]]]; }; CheckAtomic: PROC [public: Wire, name: ROPE] = { wire: Wire _ CoreCreate.FindWire[public, name]; IF wire=NIL OR wire.size#0 THEN { TerminalIO.PutF["*** Atomic wire %g does not appear correctly in public\n", IO.rope[name]]; Signal[]; }; }; CheckPlusMinus: PROC [public: Wire, name: ROPE] = { wire: Wire _ CoreCreate.FindWire[public, name]; IF wire=NIL OR wire.size#2 OR ~Rope.Equal[CoreOps.GetShortWireName[wire[0]], "Plus"] OR wire[0].size#0 OR ~Rope.Equal[CoreOps.GetShortWireName[wire[1]], "Minus"] OR wire[1].size#0 THEN { TerminalIO.PutF["*** Structured (Plus, Minus) wire %g does not appear correctly in public\n", IO.rope[name]]; Signal[]; }; }; CreatePlusMinus: PUBLIC PROC [name: ROPE] RETURNS [wire: Wire] = { wire _ CoreOps.CreateWire[ elements: LIST [CoreOps.CreateWire[name: "Plus"], CoreOps.CreateWire[name: "Minus"]], name: name]; }; CDCell: PROC [case: ATOM] RETURNS [obj: CD.Object] = { obj _ CDDirectory.Fetch[GetCellLibrary[], IO.PutR[IO.atom[case], IO.rope[".mask"]]].object; }; CoreCell: PROC [case: ATOM] RETURNS [cellType: CellType] = { schCell: CD.Object _ CDDirectory.Fetch[GetCellLibrary[], IO.PutR[IO.atom[case], IO.rope[".sch"]]].object; IF schCell=NIL THEN { obj: CD.Object _ CDDirectory.Fetch[GetCellLibrary[], IO.PutR[IO.atom[case], IO.rope[".mask"]]].object; cellType _ PWCore.FromLayoutWithoutPublic[obj]; RETURN; }; cellType _ NARROW [Sinix.Extract[schCell, Sisyph.mode, NIL, Sisyph.Create[GetCellLibrary[]]].result]; }; AddCaseCellsInLibrary: PW.UserProc = { l: INT = CMosB.lambda; size: CD.Position = [8*l, 12*l]; AtomicTile: TYPE = {nope, gnd, trans}; masks: ARRAY AtomicTile OF CD.Object _ [PW.Get[GetCellLibrary[], "AtomicNope.mask"], PW.Get[GetCellLibrary[], "AtomicGnd.mask"], PW.Get[GetCellLibrary[], "AtomicTrans.mask"]]; Square: PROC [name: ATOM, upLeft, upRight, lowLeft, lowRight: AtomicTile] RETURNS [cell: CD.Object] = { IncludeMask: PROC [mask: CD.Object, pos: CD.Position, orient: CD.Orientation] = { instances _ CONS [CDInstances.NewInst[mask, [CDBasics.SubPoints[pos, CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[mask], [[0, 0], orient]]]], orient]], instances]; }; IncludePin: PROC [name: ROPE, layer: CD.Layer, pos: CD.Position, size: CD.Position] = { inst: CD.Instance = CDInstances.NewInst[CDRects.CreateRect[size, layer], [pos]]; instances _ CONS [inst, instances]; CDProperties.PutInstanceProp[inst, $SignalName, name]; }; instances: CD.InstanceList _ NIL; IncludeMask[masks[upLeft], [0, size.y], original]; IncludeMask[masks[upRight], size, mirrorX]; IncludeMask[masks[lowLeft], [0, 0], rotate180X]; IncludeMask[masks[lowRight], [size.x, 0], rotate180]; IncludePin["Input", CMosB.pol, [3*l, 0], [2*l, 2*size.y]]; IncludePin["Input", CMosB.met2, [2*l, 0], [4*l, 2*size.y]]; IncludePin["NotInput", CMosB.pol, [11*l, 0], [2*l, 2*size.y]]; IncludePin["NotInput", CMosB.met2, [10*l, 0], [4*l, 2*size.y]]; IncludePin["Gnd", CMosB.met, [0, 10*l], [2*size.x, 4*l]]; IncludePin["Plus", CMosB.met, [14*l, 19*l], [2*l, 3*l]]; IncludePin["Minus", CMosB.met, [14*l, 2*l], [2*l, 3*l]]; IF upLeft=trans OR upRight=trans THEN IncludePin["PlusLeft", CMosB.met, [0, 19*l], [2*l, 3*l]]; IF lowLeft=trans OR lowRight=trans THEN IncludePin["MinusLeft", CMosB.met, [0, 2*l], [2*l, 3*l]]; cell _ PWObjects.CreateCell[instances, [0, 0, 2*size.x, 2*size.y]]; cell _ PW.Flatten[cell]; [] _ CDDirectory.Include[design, cell, IO.PutFR["%g.mask", IO.atom[name]]]; CoreOps.Print[Sinix.Extract[cell, PWCore.extractMode].result, TerminalIO.CreateStream[]]; }; RETURN [PW.AbutListX[LIST [ Square[$Case11, gnd, gnd, nope, nope], Square[$Case00, nope, nope, gnd, gnd], Square[$Case10, gnd, nope, nope, gnd], Square[$Case01, nope, gnd, gnd, nope], Square[$Case1X, gnd, nope, nope, trans], Square[$Case0X, nope, trans, gnd, nope], Square[$CaseX1, nope, gnd, trans, nope], Square[$CaseX0, trans, nope, nope, gnd], Square[$CaseXX, nope, nope, nope, nope], Square[$CaseTX, trans, nope, trans, nope], Square[$CaseXT, nope, trans, nope, trans] ]]]; }; AlpsCell: PUBLIC PROC [public: Wire, inputs: Inputs, outputs: Outputs, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType] = { wireToRefInt: HashTable.Table _ HashTable.Create[]; nbIn, nbOut: NAT _ 0; instances: LIST OF CoreClasses.CellInstance _ NIL; structuredInputs: Wire; -- each of the nbIn wires is a Plus-Minus inputWires: Wires _ NIL; -- aux. var. CheckAtomic[public, "Gnd"]; CheckAtomic[public, "Vdd"]; WHILE inputs#NIL DO driver: CellType _ inputs.first.driver; pas: LIST OF PA _ inputs.first.pas; input: Wire _ CoreCreate.FindWire[public, inputs.first.input]; drivedInput: Wire _ CreatePlusMinus[CoreOps.GetFullWireName[public, input]]; IF input=NIL THEN ERROR; [] _ HashTable.Store[wireToRefInt, input, NEW [INT _ nbIn]]; CheckAtomic[driver.public, "Input"]; CheckPlusMinus[driver.public, "Output"]; inputWires _ CONS [drivedInput, inputWires]; pas _ CONS [["Output", drivedInput], pas]; pas _ CONS [["Input", input], pas]; instances _ CONS [CoreCreate.InstanceList[driver, pas], instances]; inputs _ inputs.rest; nbIn _ nbIn + 1; ENDLOOP; structuredInputs _ CoreOps.CreateWire[elements: CoreOps.Reverse[inputWires], name: "PlusMinusInputs"]; WHILE outputs#NIL DO driver: CellType = outputs.first.driver; row: CellType; subPas: LIST OF PA _ NIL; rowPas: LIST OF PA _ NIL; output: Wire _ CoreCreate.FindWire[public, outputs.first.output]; outputName: ROPE _ CoreOps.GetFullWireName[public, output]; subInput: Wire = CoreOps.SetShortWireName[CoreOps.CopyWire[structuredInputs], "Input"]; subPublic: Wire _ CoreOps.CreateWire[LIST [ subInput, CoreOps.CreateWire[name: "Output"], CoreOps.CreateWire[name: "Gnd"], CoreOps.CreateWire[name: "Vdd"] ]]; IF output=NIL THEN ERROR; FOR i: NAT IN [0 .. driver.public.size) DO name: ROPE _ CoreOps.GetShortWireName[driver.public[i]]; new: Wire _ CoreOps.CopyWire[driver.public[i]]; IF CoreOps.GetWireIndex[subPublic, name]#-1 THEN LOOP; -- easy one! subPublic _ CoreOps.UnionWire[subPublic, CoreOps.CreateWire[LIST [new]]]; FOR pas: LIST OF PA _ outputs.first.pas, pas.rest WHILE pas#NIL DO pub: Wire _ CoreCreate.FindWire[driver.public, pas.first.public]; IF pub=NIL THEN ERROR; IF pub=driver.public[i] THEN { subPas _ CONS [[new, pas.first.actual], subPas]; rowPas _ CONS [[pub, new], rowPas]; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; ENDLOOP; row _ CreateAlps[subPublic, TranslateVar[wireToRefInt, Boole.Not[outputs.first.expr]], driver, rowPas, outputName]; -- Not because of current output drivers subPas _ CONS [["Input", structuredInputs], subPas]; subPas _ CONS [["Output", output], subPas]; instances _ CONS [CoreCreate.InstanceList[row, subPas], instances]; outputs _ outputs.rest; nbOut _ nbOut + 1; ENDLOOP; TerminalIO.PutF["Core for AlpsCell done: %g inputs and %g outputs\n", IO.int[nbIn], IO.int[nbOut]]; recordCell _ CoreCreate.Cell[ public: public, onlyInternal: CoreOps.CreateWire[LIST [structuredInputs]], instances: CoreClasses.ReverseCellInstances[instances], name: name, props: props ]; CoreProperties.PutCellTypeProp[recordCell, $NbIn, NEW [INT _ nbIn]]; PWCore.SetLayout[recordCell, $FullAlpsCell]; }; FullAlpsCellLayout: PWCore.LayoutProc = { refNbIn: REF INT _ NARROW [CoreProperties.GetCellTypeProp[cellType, $NbIn]]; nbIn: INT _ refNbIn^; l: INT = CMosB.lambda; data: CoreClasses.RecordCellType _ NARROW [cellType.data]; refContactPolyMetal2: REF INT _ NARROW [CoreProperties.GetCellTypeProp[cellType, $ContactPolyMetal2]]; contactPolyMetal2: INT _ IF refContactPolyMetal2=NIL THEN LAST [INT] ELSE refContactPolyMetal2^; distanceSinceLastContact: INT _ 0; i: NAT _ 0; lineObjects: LIST OF CD.Object; -- lines from top to bottom (during construction) contactLine: CD.Object; contacts: LIST OF CD.Object _ LIST [CDCell[$ContactPolyMetal2Route], CDCell[$ContactPolyMetal2OutputFiller]]; THROUGH [0 .. nbIn) DO contacts _ CONS [CDCell[$ContactPolyMetal2], contacts] ENDLOOP; contactLine _ PW.AbutListX[contacts]; BEGIN inputDriversObjects: LIST OF CD.Object _ NIL; WHILE i=contactPolyMetal2 THEN { lineObjects _ CONS [contactLine, lineObjects]; distanceSinceLastContact _ 0; }; i _ i + 1; ENDLOOP; obj _ PW.AbutListY[PW.Reverse[lineObjects]]; }; DecorateFullAlpsCell: PWCore.DecorateProc = { Sort: PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = { RETURN [pos1.y RETURN; $Case1X, $Case0X, $CaseXX => RETURN [Size[input-1, whenFalse]]; $CaseX1, $CaseX0 => RETURN [Size[input-1, whenTrue]]; $CaseXY => RETURN [Size[input-1, whenTrue] + Size[input-1, whenFalse]]; ENDCASE => ERROR; }; FillArray: PROC [expr: Expression, input: NAT, minLine, nbLines: NAT] = { FillSubColumn: PROC [case: ATOM, min: NAT, nb: NAT] = { FOR i: NAT IN [min .. min+nb) DO Tile [i, input-1, case, LIST [ ["Input", Input[input-1][Plus]], ["NotInput", Input[input-1][Minus]], ["Gnd", "Gnd"] ]]; ENDLOOP; }; FillColumn: PROC [case: ATOM] = {FillSubColumn[case, minLine, nbLines]}; Empty: PROC = { FOR i: NAT IN [minLine .. minLine+nbLines) DO FOR j: NAT IN [0 .. input-1) DO Tile[i, j, $CaseNull, LIST [ ["Input", Input[j][Plus]], ["NotInput", Input[j][Minus]], ["Gnd", "Gnd"] ]]; ENDLOOP; ENDLOOP; }; var: Variable _ NEW [INT _ input-1]; whenTrue, whenFalse: Expression; case: ATOM; [whenTrue, whenFalse] _ Boole.Eval[var, expr]; case _ Boole.Case[whenTrue, whenFalse]; SELECT case FROM $Case11, $Case00, $Case10, $Case01 => {FillColumn[case]; Empty[]}; $Case1X, $Case0X, $CaseXX => { FillColumn[case]; FillArray[whenFalse, input-1, minLine, nbLines]; }; $CaseX1, $CaseX0 => { FillColumn[case]; FillArray[whenTrue, input-1, minLine, nbLines]; }; $CaseXY => { sizeTrue: NAT _ Size[input-1, whenTrue]; sizeFalse: NAT _ Size[input-1, whenFalse]; IF sizeTrue+sizeFalse#nbLines THEN Signal[]; FillSubColumn[$CaseTX, minLine, sizeTrue]; FillArray[whenTrue, input-1, minLine, sizeTrue]; FillSubColumn[$CaseXT, minLine+sizeTrue, sizeFalse]; FillArray[whenFalse, input-1, minLine+sizeTrue, sizeFalse]; }; ENDCASE => ERROR; }; inputIndex: INT _ CoreOps.GetWireIndex[public, "Input"]; Input: Wire = public[NAT[inputIndex]]; -- this avoid CoreOps.FindWire[public, "Input"] which cost much, much more (creates a name cache) nbInput: NAT = Input.size; size: NAT = Size[nbInput, expr]; alpsArray: TilingClass.TileArray = NEW [TilingClass.TileArrayRec[size]]; CheckPlusMinus[driver.public, "Input"]; CheckAtomic[driver.public, "Output"]; pas _ CONS [["Gnd", "Gnd"], pas]; pas _ CONS [["Vdd", "Vdd"], pas]; pas _ CONS [["Output", "Output"], pas]; FOR i: NAT IN [0 .. size) DO alpsArray[i] _ NEW [TilingClass.TileRowRec[nbInput+2]]; -- last Tiles is for pseudo-routing and driver Tile[ i, nbInput, SELECT TRUE FROM size=1 => $AlpsRouteNone, i=size-1 => $AlpsRouteTop, i=0 => $AlpsRouteBottom, ENDCASE => $AlpsRoute, LIST [["Gnd", "Gnd"], ["Vdd", "Vdd"]] ]; alpsArray[i][nbInput+1] _ IF i=0 THEN NEW [TilingClass.TileRec _ [type: driver, renaming: pas]] ELSE NEW [TilingClass.TileRec _ [type: CoreCell[$FillerOutputDriver], flatten: TRUE]]; ENDLOOP; FillArray[expr, nbInput, 0, size]; TerminalIO.PutF["%gTiling done for Expression '%g' : %g lines.\n", IO.rope[IF size=1 THEN NIL ELSE "*** "], IO.rope[Boole.ToRope[expr]], IO.int[size]]; alps _ TilingClass.CreateTiling[public: public, tileArray: alpsArray, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: name, props: props]; }; [] _ PWCore.RegisterLayoutAtom[$FullAlpsCell, FullAlpsCellLayout, DecorateFullAlpsCell]; IF debug THEN PW.Register[AddCaseCellsInLibrary, "AddCaseCellsInLibrary"]; END. BooleCoreImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet August 13, 1985 5:47:24 pm PDT Bertrand Serlet March 15, 1987 6:54:36 pm PST Louis Monier June 3, 1986 7:12:53 pm PDT Barth, May 22, 1986 3:50:53 pm PDT Basics Connection with Core Utilities Connection with CoreCreate: making the array The order of instances of the returned recordCell is the following: each input driver (left to right) (in the given order) each alps row (bottom to top) (in the given order) -- let us add the top level wires of output.driver.public Make the contact line Input Drivers Alps lines Alps Class and related utilities public is the public of the Alps Cell. The resulting public is Input (2 levels of structure), Output (1 level of structure), Gnd, Vdd, and all the others found in the output driver that are not "Gnd", "Vdd", "Input", "Output" or the ones found in the pas of the driver. expr contains variables which are REF INT, public[INT] being the variable Initialization Κλ– "cedar" style˜codešœ™Jšœ Οmœ7™BJšœ6Οk™9Jšœ-™-Kšœ%ž™(Kšœž™"K™—šž œ˜ Kšœ˜KšžœC˜EKšœ8˜8Kšœ žœ˜Kšžœ˜Kšœ˜Kšœ˜K˜ Kšœ ˜ —J˜•StartOfExpansion[]šΠbn œžœž˜KšžœžœžœžœA˜ΩKšžœ ˜Kšžœ ˜Kšžœžœ ˜—head™Kšœ ˜ šœ˜K˜—KšΟnœžœžœ˜šœžœžœ˜K˜—Kšœ žœžœ žœ˜%š  œžœžœžœžœ ˜3Kšžœ žœžœžœ˜-Kšœžœ˜,Kšžœ˜K˜K˜—š  œžœžœžœžœ žœ˜IJšœ˜Jš žœ2žœžœžœžœ˜JJšžœ žœ)˜:J˜——™š  œžœžœžœžœ˜KšŸœžœ˜Kšœ˜Kšœ˜Kšžœ žœžœ˜;Kšœ˜Kšœ˜—Kšœžœ˜$Kšœžœ˜ Kšžœ žœ!žœ˜9Kšžœ žœ ˜Kšœ ˜ Kšœ'˜'Kšžœžœ ˜Kšœ˜——™ š  œžœ5žœ˜_Jšœ ˜ Jšœ&˜&Jšœžœ,˜EJšžœ žœžœžœ ˜4Jšœ0˜0Jš žœžœžœžœΟc!˜;Jšžœa˜gJ˜J˜—š  œžœžœ˜0Kšœ/˜/šžœžœžœ žœ˜!KšœLžœ ˜[Kšœ ˜ Kšœ˜—Kšœ˜J˜—š œžœžœ˜3Kšœ/˜/šžœžœžœ žœ8žœžœ9žœžœ˜ΊKšœ^žœ ˜mKšœ ˜ Kšœ˜—Kšœ˜J˜—š  œžœžœžœžœ˜Bšœ˜Kšœ žœH˜VKšœ ˜ —Kšœ˜K˜—š  œžœžœžœžœ ˜6Jšœ*žœžœ žœ˜[J˜J˜—š œžœžœžœ˜Jšœ'’œ ’œ ˜?Jšœ$’œ’œ˜9Jš œ"’œ’œ’œ’œ˜8Jš œ#’œ’œ’œ’œ˜8šžœžœ˜!Jšžœ*’œ’œ’œ˜>—šžœžœ˜#Jšžœ*’œ’œ’œ˜>—JšœC˜CJšœžœ˜Jšœ'žœžœ˜KJšœY˜YJ˜J˜—šžœžœ žœ˜Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ*˜*J˜)J˜—J˜——šœ,™,™CJ™6Jšœ2™2—š œžœžœ8žœžœžœžœ˜”K˜3Kšœ žœ˜Kšœ žœžœžœ˜2Kšœ‘)˜AKšœžœ‘ ˜%Kšœ7˜7šžœžœžœ˜Kšœ(˜(Kšœžœžœžœ˜$Kšœ>˜>KšœL˜LKšžœžœžœžœ˜Kšœ*žœžœ ˜šžœ!ž˜+Jšœ&žœ˜-Jšœžœ˜BJšœžœ˜;Jšœžœ6˜OJšžœ žœ˜—J˜—š  œžœžœžœ˜Iš   œžœžœžœžœ˜7šžœžœžœžœ˜!šœžœ˜Jšœ!˜!Jšœ$˜$J˜Jšœ˜—Jšžœ˜—J˜—Jš  œžœžœ,˜Hš œžœ˜šžœžœžœžœ˜.šžœžœžœžœ˜ šœžœ˜Jšœ˜Jšœ˜J˜Jšœ˜—Jšžœ˜—Jšžœ˜—Jšœ˜—Jšœžœžœ ˜$Jšœ ˜ Jšœžœ˜ Jšœ.˜.Jšœ'˜'šžœž˜JšœC˜Cšœ!˜!JšœB˜BJšœ˜—šœ˜JšœA˜AJšœ˜—šœ˜Jšœ žœ˜)Jšœ žœ˜*Jšžœžœ ˜,Jšœ[˜[Jšœp˜pJ˜—Jšžœ žœ˜—J˜—Jšœ žœ)˜8Jš œžœ‘a˜ˆJšœ žœ˜Jšœžœ˜!Jšœ#žœ"˜HKšœM˜MJšœžœ˜!Jšœžœ˜!Jšœžœ˜'šžœžœžœ ž˜Jšœžœ&‘.˜fšœ˜Jšœ ˜ šžœžœž˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—Kšžœ!˜%Kšœ˜—šœžœ˜!Jšžœžœ6˜>JšžœžœGžœ˜V—Jšžœ˜—Jšœ"˜"JšœCžœžœžœžœžœ žœžœ ˜—Jšœ°˜°Kšœ˜——™JšœX˜XKšžœžœžœ:˜J—K˜Kšžœ˜K˜—…—: Nϋ