DIRECTORY Boole, BooleCore, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, RefTab, GList, IO, PW, PWCore, Rope, Sinix, Sisyph, TilingClass, TerminalIO; BooleCoreImpl: CEDAR PROGRAM IMPORTS Boole, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, CoreClasses, CoreCreate, CoreOps, CoreProperties, RefTab, GList, IO, PW, 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: RefTab.Ref, source: Expression] RETURNS [Expression] = { whenTrue, whenFalse: Expression; var: Variable = Boole.FindVar[source]; newVar: Variable _ NARROW [RefTab.Fetch[wireToRefInt, var].val]; 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.GeneratorProc = { 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 _ PW.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.TOS[]]; }; 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: RefTab.Ref _ RefTab.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; [] _ RefTab.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[NARROW[GList.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]]]; 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.RegisterGenerator[AddCaseCellsInLibrary, "AddCaseCellsInLibrary"]; END.  BooleCoreImpl.mesa Copyright ำ 1985, 1986, 1987 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet August 13, 1985 5:47:24 pm PDT Bertrand Serlet May 19, 1987 0:16:27 am PDT Louis Monier June 3, 1986 7:12:53 pm PDT Barth, April 2, 1987 11:37:41 am PST 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šœH™HJšœ6ฯk™9Jšœ+™+Kšœ%™(Kšœ$™$K™—š œ˜ Kšœ˜KšœC˜EKšœ8˜8Kšœœ˜Kšœ ˜ Kšœ˜Kšœ˜K˜ Kšœ ˜ —J˜•StartOfExpansion[]šะbn œœ˜Kšœœ…œœ6˜า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šœ˜——™ šŸ œœ0œ˜ZJšœ ˜ Jšœ&˜&Jšœœ'˜@Jšœ œœœ ˜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šœœ3˜˜>KšœL˜LKšœœœœ˜Kšœ'œœ ˜9KšœM˜MKšœ œ˜,Jšœœ ˜*Jšœœ˜#Kšœ œ3˜CKšœ˜K˜Kšœ˜—Kšœf˜fšœ œœ˜Kšœ(˜(Kšœ˜Kš œœœœœ˜Kš œœœœœ˜KšœA˜AKšœ œ+˜;KšœW˜Wšœ%œ˜+Kšœ ˜ Kšœ$˜$Kšœ@˜@K˜—Kšœœœœ˜Kš 9™9šœœœ˜*Jšœœ.˜8Jšœ0˜0Jšœ*œœ  ˜CJšœ<œ ˜Jš œœœœœœ˜BJšœA˜AJšœœœœ˜šœœ˜Jšœ œ$˜1Jšœ œ˜$Jšœ˜Jšœ˜—Jšœœœ˜Jšœ˜—Jšœ˜—Kšœt (˜œJšœ œ'˜4Jšœ œ˜+Kšœ œ3˜CKšœ˜Kšœ˜Kšœ˜—JšœFœ œ ˜cšœ˜Jšœ˜Jšœ!œ˜šœ!˜+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—Jšœ˜—Jšœ"˜"JšœCœœœœœ œœ ˜—Jšœฐ˜ฐKšœ˜——™JšœX˜XKšœœœC˜S—K˜Kšœ˜K˜—…—:2O-