DIRECTORY Boole, BooleCore, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, Core, CoreCreate, CoreOps, CoreProperties, RefTab, IO, PW, PWCore, Rope, Sinix, Sisyph, TilingClass, TerminalIO; BooleCoreImpl: CEDAR PROGRAM IMPORTS Boole, CD, CDBasics, CDDirectory, CDInstances, CDProperties, CDRects, CMosB, CoreCreate, CoreOps, CoreProperties, RefTab, 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]]]; }; InputLength: PROC [inputs: Inputs] RETURNS [length: NAT _ 0] = { WHILE inputs#NIL DO length _ length + 1; inputs _ inputs.rest ENDLOOP; }; OutputLength: PROC [outputs: Outputs] RETURNS [length: NAT _ 0] = { WHILE outputs#NIL DO length _ length + 1; outputs _ outputs.rest ENDLOOP; }; 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[]; }; }; 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]; }; TILE: PROC [cell: ATOM] RETURNS [TilingClass.Tile] = { RETURN [NEW [TilingClass.TileRec _ [CoreCell[cell]]]]; }; AppendOneRow: PROC [old: TilingClass.TileArray, row: TilingClass.TileRow] RETURNS [new: TilingClass.TileArray] = { new _ NEW [TilingClass.TileArrayRec[old.size+1]]; FOR i: NAT IN [0 .. old.size) DO new[i] _ old[i] ENDLOOP; new[old.size] _ row; }; AddCaseCellsInLibrary: PW.GeneratorProc = { l: INT = design.technology.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 [alps: CellType] = { nbIn: NAT = InputLength[inputs]; nbOut: NAT = OutputLength[outputs]; array: TilingClass.TileArray _ NEW [TilingClass.TileArrayRec[0]]; wireToRefInt: RefTab.Ref _ RefTab.Create[]; CheckAtomic[public, "Gnd"]; CheckAtomic[public, "Vdd"]; BEGIN inputDrivers: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[nbIn+2]]; subIndex: NAT _ 0; WHILE inputs#NIL DO driver: CellType _ inputs.first.driver; input: Wire _ CoreCreate.FindWire[public, inputs.first.input]; IF input=NIL THEN ERROR; [] _ RefTab.Store[wireToRefInt, input, NEW [INT _ subIndex]]; CheckAtomic[driver.public, "Input"]; CheckPlusMinus[driver.public, "Output"]; inputDrivers[subIndex] _ NEW [TilingClass.TileRec _ [driver, CONS [["Input", input], inputs.first.pas]]]; subIndex _ subIndex + 1; inputs _ inputs.rest; ENDLOOP; inputDrivers[nbIn] _ TILE[$FillerInputRoute]; inputDrivers[nbIn+1] _ TILE[$FillerDriverCorner]; array _ AppendOneRow[array, inputDrivers]; END; BEGIN refContactPolyMetal2: REF INT _ NARROW [CoreProperties.GetProp[props, $ContactPolyMetal2]]; contactPolyMetal2: INT _ IF refContactPolyMetal2=NIL THEN LAST [INT] ELSE refContactPolyMetal2^; distSinceLastContact: INT _ 0; WHILE outputs#NIL DO arr: TilingClass.TileArray; driver: CellType = outputs.first.driver; output: Wire _ CoreCreate.FindWire[public, outputs.first.output]; rowPas: LIST OF PA _ outputs.first.pas; IF output=NIL THEN ERROR; rowPas _ CONS [["Output", output], rowPas]; FOR i: NAT IN [0 .. driver.public.size) DO name: ROPE _ CoreOps.GetShortWireName[driver.public[i]]; IF name=NIL THEN ERROR; IF Rope.Equal[name, "Output"] OR Rope.Equal[name, "Input"] OR Rope.Equal[name, "Plus"] OR Rope.Equal[name, "Minus"] THEN LOOP; FOR pas: LIST OF PA _ rowPas, 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 EXIT; REPEAT FINISHED => rowPas _ CONS [[name, name], rowPas]; ENDLOOP; ENDLOOP; arr _ CreateOneOuputArray[nbIn, TranslateVar[wireToRefInt, Boole.Not[outputs.first.expr]], driver, rowPas]; FOR i: NAT IN [0 .. arr.size) DO array _ AppendOneRow[array, arr[i]] ENDLOOP; distSinceLastContact _ distSinceLastContact + arr.size; outputs _ outputs.rest; IF distSinceLastContact>=contactPolyMetal2 THEN { row: TilingClass.TileRow _ NEW [TilingClass.TileRowRec[nbIn+2]]; FOR j: NAT IN [0 .. nbIn) DO row[j] _ TILE[$ContactPolyMetal2] ENDLOOP; row[nbIn] _ TILE[$ContactPolyMetal2Route]; row[nbIn+1] _ TILE[$ContactPolyMetal2OutputFiller]; array _ AppendOneRow[array, row]; distSinceLastContact _ 0; }; ENDLOOP; END; TerminalIO.PutF["Tiling for AlpsCell: %g inputs and %g outputs\n", IO.int[nbIn], IO.int[nbOut]]; alps _ TilingClass.CreateTiling[public: public, tileArray: array, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: name, props: props]; }; CreateOneOuputArray: PROC [nbInput: NAT, expr: Expression, driver: CellType, pas: LIST OF PA] RETURNS [alpsArray: TilingClass.TileArray] = { Tile: PROC [i, j: NAT, case: ATOM] = {alpsArray[i][j] _ TILE[case]}; Size: PROC [input: NAT, expr: Expression] RETURNS [size: INT _ 1] = { whenTrue, whenFalse: Expression; IF input=0 THEN {IF expr#true AND expr#false THEN ERROR; RETURN}; [whenTrue, whenFalse] _ Boole.Eval[NEW [INT _ input-1], expr]; SELECT Boole.Case[whenTrue, whenFalse] FROM $Case11, $Case00, $Case10, $Case01 => 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] 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] 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; }; size: NAT = Size[nbInput, expr]; alpsArray _ NEW [TilingClass.TileArrayRec[size]]; 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 ]; alpsArray[i][nbInput+1] _ IF i=0 THEN NEW [TilingClass.TileRec _ [type: driver, renaming: pas]] ELSE TILE[$FillerOutputDriver]; ENDLOOP; FillArray[expr, nbInput, 0, size]; }; 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 September 1, 1987 11:40:30 pm 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 This function is not a very efficient primitive, but who cares?? 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) Generating a single ouput Assumed are "Output", "Gnd", "Vdd". expr contains variables which are REF INT, public[INT] being the variable Initialization Κ– "cedar" style˜codešœ™JšœH™HJšœ6Οk™9Jšœ1™1Kšœ%™(Kšœ!™$K™—š œ˜ Kšœ˜KšœC˜EKšœ+˜+Kšœœ˜ Kšœ ˜ Kšœ˜Kšœ˜K˜ Kšœ ˜ —J˜•StartOfExpansion[]šΠbn œœ˜Kšœœqœœ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˜—šŸ œœœ œ ˜@Jšœœœ+œ˜FJ˜J˜—šŸ œœœ œ ˜CJšœ œœ-œ˜IJ˜J˜—šŸ œœœ˜0Kšœ/˜/šœœœ œ˜!KšœLœ ˜[Kšœ ˜ Kšœ˜—Kšœ˜J˜—šŸœœœ˜3Kšœ/˜/šœœœ œ8œœ9œœ˜ΊKšœ^œ ˜mKšœ ˜ Kšœ˜—Kšœ˜J˜—š Ÿœœœœœ ˜6Jšœ*œœ œ˜[J˜J˜—šŸœœœœ˜Jšœ'‘œ ‘œ ˜?Jšœ$‘œ‘œ˜9Jš œ"‘œ‘œ‘œ‘œ˜8Jš œ#‘œ‘œ‘œ‘œ˜8šœœ˜!Jšœ*‘œ‘œ‘œ˜>—šœœ˜#Jšœ*‘œ‘œ‘œ˜>—Jšœœ3˜˜>Kšœœœœ˜Kšœ'œœ˜=KšœM˜MKšœœ!œ(˜iKšœ˜Kšœ˜Kšœ˜—Kšœœ˜-Kšœœ˜1Kšœ*˜*Kšœ˜Kš˜Jšœœœœ5˜[Jšœœœœœœœœ˜`Jšœœ˜šœ œœ˜Kšœ˜Kšœ(˜(KšœA˜AKšœœœœ˜'Kšœœœœ˜Kšœ œ˜+šœœœ˜*Jšœœ.˜8Jšœœœœ˜Jš œœœœœœ˜~š œœœœœœ˜7JšœA˜AJšœœœœ˜Jšœœœ˜"Jšœœ œ˜8Jšœ˜—Jšœ˜—Kšœk˜kKš œœœœ%œ˜MJšœ7˜7Kšœ˜šœ)œ˜1Kšœœ"˜@Kš œœœ œ œœ˜GKšœ œ˜+Kšœœ"˜4Kšœ!˜!Kšœ˜K˜—Kšœ˜—Jšœ˜JšœCœ œ ˜`Jšœ¬˜¬Jšœ˜——™Jšœ#™#Jšœ"œœ œ™IšŸœœ œ+œœœœ'˜ŒJš Ÿœœœœœ˜Dš Ÿœœ œœœ ˜EJšœ ˜ Jšœ œœ œ œœœ˜AJšœ#œœ˜>šœ!˜+Jšœ&œ˜-Jšœœ˜BJšœœ˜;Jšœœ6˜OJšœ œ˜—J˜—šŸ œœœœ˜Iš Ÿ œœœœœ˜7Jš œœœœœ˜@J˜—JšŸ œœœ,˜HšŸœœ˜šœœœœ˜.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šœœ˜!Jšœ œ"˜1šœœœ ˜Jšœœ& .˜fšœœœ˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœœ˜!Jšœœ6˜>Jšœœ˜—Jšœ˜—Jšœ"˜"Kšœ˜——™KšœœœC˜S—K˜Kšœ˜K˜—…—/ @(