DIRECTORY Boole, TrueAlps, CD, CDDirectory, CDSymbolicObjects, CMosB, Core, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, IO, PW, PWCore, Rope, RopeList, Rosemary, Ports, Sinix, Sisyph, TerminalIO; TrueAlpsImpl: CEDAR PROGRAM IMPORTS Boole, CD, CDDirectory, CDSymbolicObjects, CMosB, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, IO, PW, PWCore, Rope, RopeList, Rosemary, Ports, Sinix, Sisyph, TerminalIO EXPORTS TrueAlps SHARES Boole = BEGIN OPEN TrueAlps; false: Expression = Boole.false; Signal: SIGNAL = CODE; true: Expression = Boole.true; debug: BOOL _ TRUE; ExprVars: TYPE = REF ExprVarsRec; ExprVarsRec: TYPE = RECORD [ expr: Expression, vars: LIST OF ROPE, -- the order in which variables should be size: NAT _ 0 -- filled by the recast proc: nb of lines for this ordering ]; trueAlpsClass: PUBLIC Core.CellClass _ CoreIO.RegisterClass[ Rosemary.BindCellClass[NEW [Core.CellClassRec _ [name: "Alps", recast: RecastAlps, properties: CoreProperties.Props[[PWCore.layoutAtomProp, $Recast]]]], Rosemary.Register["AlpsRoseClass", InitAlps, EvalAlps]], WriteAlps, ReadAlps]; WriteAlps: CoreIO.ClassWriteProc = { data: ExprVars _ NARROW[cellType.data]; CoreIO.WriteRope[h, Boole.ToRope[data.expr, LAST[INT]]]; CoreIO.WriteListOfRope[h, data.vars]; CoreIO.WriteInt[h, data.size]; }; ReadAlps: CoreIO.ClassReadProc = { data: ExprVars _ NEW[ExprVarsRec]; data.expr _ Boole.FromRope[CoreIO.ReadRope[h]]; data.vars _ CoreIO.ReadListOfRope[h]; data.size _ CoreIO.ReadInt[h]; cellType.data _ data; }; CreateAlps: PROC [inputVars: LIST OF ROPE, expr: Expression, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [alps: CellType] = { input: Wire _ CreatePlusMinusN[name: "Input", names: inputVars]; inputNot: Wire _ CreatePlusMinusN[name: "InputNot", names: inputVars]; data: ExprVars _ NEW [ExprVarsRec _ [expr: expr, vars: inputVars]]; CheckVarsOfExprInVars[expr, inputVars]; alps _ CoreOps.CreateCellType[ class: trueAlpsClass, public: CoreOps.CreateWire[LIST [ InitPort[input], InitPort[inputNot], InitPort[CoreOps.CreateWire[name: "Output"]], InitPort[CoreOps.CreateWire[name: "Gnd"]], InitPort[CoreOps.CreateWire[name: "Vdd"]] ]], data: data, name: name, props: props ]; [] _ Rosemary.AddCutSets[alps, "AlpsCell"]; }; Input: NAT = 0; InputNot: NAT = 1; Output: NAT = 2; Gnd: NAT = 3; Vdd: NAT = 4; InitAlps: Rosemary.InitProc = {stateAny _ cellType}; inputXmeansX: PUBLIC BOOL _ TRUE; PlusMinusLevel: PROC [p, notp: Ports.Port] RETURNS [l: Ports.Level] = { l _ SELECT TRUE FROM p.l=L AND notp.l=H => L, p.l=H AND notp.l=L => H, ENDCASE => X; }; EvalAlps: Rosemary.EvalProc = { cellType: CellType _ NARROW [stateAny]; exprVars: ExprVars _ NARROW [cellType.data]; expr: Expression _ exprVars.expr; vars: LIST OF ROPE _ exprVars.vars; input: Wire _ cellType.public[Input]; p[Output].l _ X; p[Output].d _ drive; IF p[Gnd].l#L THEN RETURN; IF p[Vdd].l#H THEN RETURN; WHILE Boole.FindVar[expr]#NIL DO var: ROPE _ Boole.FindVar[expr]; index: NAT _ 0; UNTIL Rope.Equal[CoreOps.GetShortWireName[input[index]], var] DO index _ index + 1 ENDLOOP; SELECT PlusMinusLevel[p[Input][index], p[InputNot][index]] FROM L => expr _ Boole.Eval[var, expr].whenFalse; H => expr _ Boole.Eval[var, expr].whenTrue; ENDCASE => { IF ~inputXmeansX THEN FOR i: NAT IN [0..p[Input].size) DO rope: ROPE _ CoreOps.GetShortWireName[input[i]]; SELECT PlusMinusLevel[p[Input][i], p[InputNot][i]] FROM L => expr _ Boole.Eval[rope, expr].whenFalse; H => expr _ Boole.Eval[rope, expr].whenTrue; ENDCASE; ENDLOOP; EXIT; }; ENDLOOP; SELECT expr FROM false => p[Output].l _ L; true => p[Output].l _ H; ENDCASE; }; maxLines: NAT = 20; -- maximum number of lines for a given expression. RecastAlps: Core.RecastProc = { HTile: TYPE = {HId, HOne, HZero, HNor, HNand}; VTile: TYPE = {VId, VIdNot, VNand, VNandNot, VNor, VNorNot, VNull}; AlpsArrayLine: TYPE = REF AlpsArrayLineRec; AlpsArrayLineRec: TYPE = RECORD [lineEnd: HTile, c: SEQUENCE size: NAT OF VTile]; AlpsArray: TYPE = REF AlpsArrayRec; AlpsArrayRec: TYPE = RECORD [size: NAT _ 0, lines: ARRAY [0 .. maxLines) OF AlpsArrayLine]; exprVars: ExprVars _ NARROW [me.data]; expr: Expression _ exprVars.expr; vars: LIST OF ROPE _ exprVars.vars; nbInput: NAT = me.public[Input].size; revVars: LIST OF ROPE _ RopeList.Reverse[vars]; alpsArray: AlpsArray _ NEW [AlpsArrayRec]; 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 alpsArray[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 alpsArray[i][j] _ $CaseNull ENDLOOP; ENDLOOP; }; var: ROPE _ CoreOps.GetShortWireName[me.public[Input][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[revVars, whenTrue]; sizeFalse: NAT _ Size[revVars, 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; }; instances: LIST OF CoreCreate.CellInstance _ NIL; exprVars.size _ size; FOR i: NAT IN [0 .. size) DO alpsArray[i] _ NEW [AlpsArrayLineRec[nbInput]]; FOR j: NAT IN [0 .. nbInput) DO alpsArray[i][j] _ $Undefined ENDLOOP; ENDLOOP; FillArray[expr, nbInput, 0, size]; FOR i: NAT DECREASING IN [0 .. size) DO linePublic: Wire _ CoreOps.CopyWire[me.public]; line: CellType; abutInstances: LIST OF PWCore.AbutInstance _ LIST [[ CDCell[SELECT TRUE FROM size=1 => $AlpsRouteNone, i=size-1 => $AlpsRouteTop, i=0 => $AlpsRouteBottom, ENDCASE => $AlpsRoute], LIST [ ["Plus", linePublic[Output][Plus]], ["Minus", linePublic[Output][Minus]], ["Gnd", linePublic[Gnd]], ["Vdd", linePublic[Vdd]] ] ]]; FOR j: NAT DECREASING IN [0 .. nbInput) DO abutInstances _ CONS [ [CDCell[alpsArray[i][j]], LIST [ ["Input", linePublic[Input][j][Plus]], ["NotInput", linePublic[Input][j][Minus]] ]], abutInstances]; ENDLOOP; line _ PWCore.AbutCell[linePublic, abutInstances, TRUE, FALSE]; instances _ CONS [CoreCreate.Instance[line], instances]; ENDLOOP; TerminalIO.WriteF["%gExpression %g laid out: %g lines.\n", IO.rope[IF size=1 THEN NIL ELSE "*** "], IO.rope[Boole.ToRope[expr]], IO.int[size]]; IF size=1 THEN RETURN [instances.first.type]; new _ CoreCreate.Cell[public: CoreOps.CopyWire[me.public], instances: instances]; PWCore.SetAbutY[new]; }; CheckAtomic: PROC [public: Wire, name: ROPE] = { wire: Wire _ CoreCreate.FindWire[public, name]; IF wire=NIL OR wire.size#0 THEN { TerminalIO.WriteF["*** Atomic wire %g does not appear correctly in public\n", IO.rope[name]]; Signal[]; }; }; CheckVarsOfExprInVars: PROC [expr: Expression, vars: LIST OF ROPE] = { var: ROPE _ Boole.FindVar[expr]; whenTrue, whenFalse: Expression; IF var=NIL THEN RETURN; IF ~RopeList.Memb[vars, var] THEN { TerminalIO.WriteF["*** Expression contains %g which is not an input\n", IO.rope[var]]; Signal[]; }; [whenTrue, whenFalse] _ Boole.Eval[var, expr]; CheckVarsOfExprInVars[whenTrue, vars]; CheckVarsOfExprInVars[whenFalse, vars]; }; CreatePlusMinusN: PUBLIC PROC [name: ROPE, names: LIST OF ROPE] RETURNS [wire: Wire] = { wire _ CoreOps.CreateWires[size: RopeList.Length[names], name: name]; FOR i: NAT IN [0 .. NAT [RopeList.Length[names]]) DO wire[i] _ CoreOps.CreateWire[name: names.first]; names _ names.rest; ENDLOOP; }; CreatePlusMinus: PUBLIC PROC [name: ROPE] RETURNS [wire: Wire] = { wire _ CoreOps.CreateWire[ elements: LIST [CoreOps.CreateWire[name: "Plus"], CoreOps.CreateWire[name: "Minus"]], name: name]; }; InitPort: PROC [wire: Core.Wire] RETURNS [sameWire: Core.Wire] = { sameWire _ IF wire.size=0 THEN Ports.InitPort[wire, l] ELSE wire; FOR i: NAT IN [0 .. wire.size) DO [] _ InitPort[wire[i]] ENDLOOP; }; cellLibrary: PUBLIC CD.Design _ PW.OpenDesign["BooleLibrary"]; cx: PUBLIC Sisyph.Context _ Sisyph.Create[cellLibrary]; CDCell: PROC [case: ATOM, makeCellType: BOOL _ TRUE] RETURNS [obj: CD.Object] = { cellType: CellType; schCell: CD.Object _ CDDirectory.Fetch[cellLibrary, IO.PutR[IO.atom[case], IO.rope[".sch"]]].object; IF schCell=NIL THEN { maskCell: CD.Object _ CDDirectory.Fetch[cellLibrary, IO.PutR[IO.atom[case], IO.rope[".mask"]]].object; IF maskCell=NIL THEN Signal[]; IF makeCellType THEN cellType _ PWCore.FromLayoutWithoutPublic[maskCell]; RETURN [maskCell]; }; cellType _ NARROW [Sinix.Extract[schCell, Sisyph.sisyphMode, NIL, cx].result]; PWCore.SetGet[cellType, cellLibrary]; obj _ PWCore.Layout[cellType]; }; 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[cellLibrary, "AtomicNope.mask"], PW.Get[cellLibrary, "AtomicGnd.mask"], PW.Get[cellLibrary, "AtomicTrans.mask"]]; IncludePin: PROC [cell: CD.Object, name: ROPE, layer: CD.Layer, pos: CD.Position, size: CD.Position] = { pin: CD.Instance _ PW.IncludeInCell[cell, CDSymbolicObjects.CreatePin[size], pos]; CDSymbolicObjects.SetName[pin, name]; CDSymbolicObjects.SetLayer[pin, layer]; }; Square: PROC [name: ATOM, upLeft, upRight, lowLeft, lowRight: AtomicTile] RETURNS [cell: CD.Object] = { cell _ PW.CreateEmptyCell[]; [] _ PW.IncludeInCell[cell, masks[upLeft], [0, size.y]]; [] _ PW.IncludeInCell[cell, masks[upRight], size, 1]; [] _ PW.IncludeInCell[cell, masks[lowLeft], [0, 0], 5]; [] _ PW.IncludeInCell[cell, masks[lowRight], [size.x, 0], 4]; CDCells.SetInterestRect[cell, [0, 0, 2*size.x, 2*size.y]]; IncludePin[cell, "Input", CMosB.pol, [3*l, 0], [2*l, 2*size.y]]; IncludePin[cell, "Input", CMosB.met2, [2*l, 0], [4*l, 2*size.y]]; IncludePin[cell, "NotInput", CMosB.pol, [11*l, 0], [2*l, 2*size.y]]; IncludePin[cell, "NotInput", CMosB.met2, [10*l, 0], [4*l, 2*size.y]]; IncludePin[cell, "Gnd", CMosB.met, [0, 10*l], [2*size.x, 4*l]]; IncludePin[cell, "Plus", CMosB.met, [14*l, 18*l], [2*l, 4*l]]; IncludePin[cell, "Minus", CMosB.met, [14*l, 2*l], [2*l, 4*l]]; IF upLeft=trans OR upRight=trans THEN IncludePin[cell, "PlusLeft", CMosB.met, [0, 18*l], [2*l, 4*l]]; IF lowLeft=trans OR lowRight=trans THEN IncludePin[cell, "MinusLeft", CMosB.met, [0, 2*l], [2*l, 4*l]]; PW.RepositionCell[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] ]]]; }; FindWires: PROC [name: ROPE, internals: Wires] RETURNS [wire: Wire _ NIL] = { WHILE internals#NIL DO IF Rope.Equal[CoreOps.GetShortWireName[internals.first], name] THEN RETURN [internals.first]; internals _ internals.rest; ENDLOOP; }; CreateAlpsRow: PROC [inputVars: LIST OF ROPE, output: OutputRec, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType, futureBindings: LIST OF PA _ NIL] = { instances: LIST OF CoreClasses.CellInstance _ NIL; internal: Wire _ CreatePlusMinus[name: "OutputPlusMinus"]; bindings: LIST OF PA _ LIST [["Input", internal]]; input: Wire _ CreatePlusMinusN[name: "Input", names: inputVars]; publics: Wires _ LIST [input, CoreOps.CreateWire[name: "Output"], CoreOps.CreateWire[name: "Gnd"], CoreOps.CreateWire[name: "Vdd"]]; CheckAtomic[output.driver.public, "Input"]; CheckAtomic[output.driver.public, "InputNot"]; CheckAtomic[output.driver.public, "Output"]; FOR i: NAT IN [0 .. output.driver.public.size) DO name: ROPE _ CoreOps.GetShortWireName[output.driver.public[i]]; new: Wire _ CoreOps.CopyWire[output.driver.public[i]]; IF CoreOps.GetWireIndex[CoreOps.CreateWire[publics], name]#-1 THEN LOOP; publics _ CONS [new, publics]; FOR pas: LIST OF PA _ output.pas, pas.rest WHILE pas#NIL DO pub: Wire _ CoreCreate.FindWire[output.driver.public, pas.first.public]; IF pub=NIL THEN ERROR; IF pub=output.driver.public[i] THEN { futureBindings _ CONS [[new, pas.first.actual], futureBindings]; bindings _ CONS [[pub, new], bindings]; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; ENDLOOP; recordCell _ CoreCreate.Cell[ public: CoreOps.CreateWire[publics], onlyInternal: CoreOps.CreateWire[LIST [internal]], instances: LIST [ CoreCreate.Instance[CreateAlps[inputVars, Boole.Not[output.expr]], ["Output", internal]], -- Not because of current output drivers CoreCreate.InstanceList[output.driver, bindings] ] ]; PWCore.SetLayout[recordCell, $AlpsRow]; }; AlpsRowLayout: PWCore.LayoutProc = { data: CoreClasses.RecordCellType _ NARROW [cellType.data]; alpsOb: CD.Object _ PWCore.Layout[data[0].type]; alpsData: ExprVars _ NARROW [data[0].type.data]; l: INT = CMosB.lambda; outputDecoderObjects: LIST OF CD.Object _ LIST [PWCore.Layout[data[1].type]]; IF ((CD.InterestSize[alpsOb].y) MOD (24*l))#0 OR ((CD.InterestSize[alpsOb].x-15*l) MOD (16*l))#0 THEN ERROR; IF alpsData.size=1 THEN RETURN [PW.AbutX[alpsOb, outputDecoderObjects.first]]; FOR j: NAT IN [0 .. alpsData.size-1) DO outputDecoderObjects _ CONS [CDCell[$FillerOutputDriver, FALSE], outputDecoderObjects]; ENDLOOP; obj _ PW.AbutX[alpsOb, PW.AbutListY[outputDecoderObjects]]; }; AlpsCell: PUBLIC PROC [public: Wire, inputs: Inputs, outputs: Outputs, name: ROPE _ NIL, props: Properties _ NIL] RETURNS [recordCell: CellType] = { nbIn, nbOut: NAT _ 0; instances: LIST OF CoreClasses.CellInstance _ NIL; inputVars: LIST OF ROPE _ NIL; structuredInputs: Wire; inputWires: Wires _ NIL; 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]; inputName: ROPE _ CoreOps.GetFullWireName[public, input]; drivedInput: Wire _ CreatePlusMinus[inputName]; IF input=NIL THEN ERROR; CheckAtomic[driver.public, "Input"]; CheckPlusMinus[driver.public, "Output"]; inputVars _ CONS [inputName, inputVars]; 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; inputVars _ RopeList.Reverse[inputVars]; structuredInputs _ CoreOps.CreateWire[elements: CoreOps.Reverse[inputWires], name: "PlusMinusInputs"]; WHILE outputs#NIL DO row: CellType; futureBindings: LIST OF PA; output: Wire _ CoreCreate.FindWire[public, outputs.first.output]; outputName: ROPE _ CoreOps.GetFullWireName[public, output]; IF output=NIL THEN ERROR; [row, futureBindings] _ CreateAlpsRow[inputVars, outputs.first, outputName]; futureBindings _ CONS [["Input", structuredInputs], futureBindings]; futureBindings _ CONS [["Output", output], futureBindings]; instances _ CONS [CoreCreate.InstanceList[row, futureBindings], instances]; outputs _ outputs.rest; nbOut _ nbOut + 1; ENDLOOP; PW.WriteF["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, FALSE], CDCell[$ContactPolyMetal2OutputFiller, FALSE]]; THROUGH [0 .. nbIn) DO contacts _ CONS [CDCell[$ContactPolyMetal2, FALSE], 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=max THEN int _ int - max ELSE var _ Boole.Not[var]; expr _ Boole.And[var, expr]; }; wire: Wire _ NARROW [wr]; 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.VisitAtomicWires[wire, Andify]; IF int#0 THEN Signal[]; }; Size: PUBLIC PROC [vars: LIST OF ROPE, expr: Expression] RETURNS [size: INT _ 1] = { whenTrue, whenFalse: Expression; IF vars=NIL THEN {IF expr#true AND expr#false THEN ERROR; RETURN}; [whenTrue, whenFalse] _ Boole.Eval[vars.first, expr]; SELECT Boole.Case[whenTrue, whenFalse] FROM $Case11, $Case00, $Case10, $Case01 => RETURN; $Case1X, $Case0X, $CaseXX => RETURN [Size[vars.rest, whenFalse]]; $CaseX1, $CaseX0 => RETURN [Size[vars.rest, whenTrue]]; $CaseXY => RETURN [Size[vars.rest, whenTrue] + Size[vars.rest, whenFalse]]; ENDCASE => ERROR; }; coreBoolePermuteProp: PUBLIC ATOM _ CoreProperties.RegisterProperty[$BoolePermuteProp]; Permute: PUBLIC PROC [expr: Expression, public: Wire] RETURNS [bestPermutedExpr: Expression, bestPermutedWire: Wire] = { }; [] _ PWCore.RegisterLayoutAtom[$AlpsRow, AlpsRowLayout, PWCore.DecorateAbutX]; [] _ PWCore.RegisterLayoutAtom[$FullAlpsCell, FullAlpsCellLayout, DecorateFullAlpsCell]; IF debug THEN PW.Register[AddCaseCellsInLibrary, "AddCaseCellsInLibrary"]; END. ¦TrueAlpsImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet June 22, 1986 10:33:11 pm PDT Bertrand Serlet June 22, 1986 10:59:27 pm PDT Utilities AlpsClass Data field contains a record ExprVars. Public[0] is named Input and contains the flat list of all positive inputs Public[1] is named InputNot and contains the flat list of all negative inputs Public[2] is named Output and contains the output. Public[3] is Gnd Public[4] is Vdd Default case: we set the output to X If Gnd is not Gnd, we might as well stop here First pass on the expression to simplify it as much as we can Not much simplification, now we are going to have to create new data structures If the resulting expression is true or false, we set the corresponding result Connection with CoreCreate Does an InitPort recursively Assembles an output and a driver to form a row. 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. 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) Make the contact line Input Drivers Alps lines with Reorder: PUBLIC PROC [expr: Expression, public: Wire] RETURNS [newExpr: Expression] = { vars: LIST OF ROPE _ NIL; AddToVars: PROC [wire: Wire] = {vars _ CONS [CoreOps.GetShortWireName[wire], vars]}; CoreOps.VisitAtomicWires[public, AddToVars]; vars _ RopeList.Reverse[vars]; RETURN [ReorderVars[expr, vars]]; }; Reorders expr using vars. vars.first is the head of the binary decision tree. ReorderVars: PUBLIC PROC [expr: Expression, vars: LIST OF ROPE] RETURNS [newExpr: Expression] = { var: ROPE; whenTrue, whenFalse: Expression; IF expr=true OR expr=false THEN RETURN [expr]; var _ vars.first; [whenTrue, whenFalse] _ Boole.Eval[var, expr]; newExpr _ IF Boole.Equal[whenTrue, whenFalse] THEN ReorderVars[whenTrue, vars.rest] ELSE Boole.If[Boole.Var[var], ReorderVars[whenTrue, vars.rest], ReorderVars[whenFalse, vars.rest]]; }; SeqListWire: TYPE = REF SeqListWireRec; SeqListWireRec: TYPE = RECORD [c: SEQUENCE size: NAT OF LIST OF Wire]; CartesianProduct: PROC [seqListWire: SeqListWire, permutations: LIST OF Wire] RETURNS [newPermutations: LIST OF Wire] = { size: NAT _ seqListWire.size; wire: Wire; FOR i: NAT IN [0 .. size) DO IF seqListWire[i].rest#NIL THEN { seqListWire1: SeqListWire _ NEW [SeqListWireRec[size]]; seqListWire2: SeqListWire _ NEW [SeqListWireRec[size]]; FOR j: NAT IN [0 .. size) DO IF i#j THEN {seqListWire1[j] _ seqListWire[j]; seqListWire2[j] _ seqListWire[j]} ELSE {seqListWire1[j] _ LIST [seqListWire[j].first]; seqListWire2[j] _ seqListWire[j].rest}; ENDLOOP; newPermutations _ CartesianProduct[seqListWire1, CartesianProduct[seqListWire2, permutations]]; RETURN; }; ENDLOOP; wire _ NEW [WireRec _ [structure: record, elements: NEW [WireSequenceRec[size]]]]; FOR i: NAT IN [0 .. size) DO wire.elements[i] _ seqListWire[i].first; ENDLOOP; newPermutations _ CONS [wire, permutations]; }; PermuteSeqListWire: PROC [rank: NAT, seqListWire: SeqListWire, permutations: LIST OF SeqListWire] RETURNS [newPermutations: LIST OF SeqListWire] = { size: NAT _ seqListWire.size; newPermutations _ permutations; IF rank=0 THEN RETURN [CONS[seqListWire, newPermutations]]; FOR i: NAT IN [0 .. rank] DO newSeqListWire: SeqListWire _ NEW [SeqListWireRec[size]]; FOR j: NAT IN [0 .. size) DO newSeqListWire[j] _ seqListWire[IF j=i THEN rank ELSE IF j=rank THEN i ELSE j]; ENDLOOP; newPermutations _ PermuteSeqListWire[rank-1, newSeqListWire, newPermutations]; ENDLOOP; }; EnumeratePermutedWires: PROC [wire: Wire] RETURNS [permutations: LIST OF Wire] = { size: NAT; IF wire.structure=atom THEN RETURN [LIST[wire]]; size _ wire.elements.size; SELECT CoreProperties.GetProp[wire.properties, coreBoolePermuteProp] FROM $DoNot => RETURN [LIST[wire]]; $DoNotButDoSons => { seqListWire: SeqListWire _ NEW [SeqListWireRec[size]]; FOR i: NAT IN [0 .. size) DO seqListWire[i] _ EnumeratePermutedWires[wire.elements[i]]; ENDLOOP; permutations _ CartesianProduct[seqListWire, NIL]; }; $DoNotApartReverse => { seqListWire: SeqListWire _ NEW [SeqListWireRec[size]]; revSeqListWire: SeqListWire _ NEW [SeqListWireRec[size]]; FOR i: NAT IN [0 .. size) DO seqListWire[i] _ EnumeratePermutedWires[wire.elements[i]]; ENDLOOP; FOR i: NAT IN [0 .. size) DO revSeqListWire[i] _ seqListWire[size-i-1]; ENDLOOP; permutations _ CartesianProduct[seqListWire, NIL]; permutations _ CartesianProduct[revSeqListWire, permutations]; } ENDCASE => { seqListWire: SeqListWire _ NEW [SeqListWireRec[size]]; listSeqListWire: LIST OF SeqListWire; FOR i: NAT IN [0 .. size) DO seqListWire[i] _ EnumeratePermutedWires[wire.elements[i]]; ENDLOOP; listSeqListWire _ PermuteSeqListWire[size-1, seqListWire, NIL]; WHILE listSeqListWire#NIL DO permutations _ CartesianProduct[listSeqListWire.first, permutations]; listSeqListWire _ listSeqListWire.rest; ENDLOOP; }; }; min: INT _ LAST[INT]; permutations: LIST OF Wire _ EnumeratePermutedWires[public]; bestPermutedExpr _ expr; bestPermutedWire _ public; WHILE permutations#NIL DO expr _ Reorder[bestPermutedExpr, permutations.first]; IF Size[expr] EXIT]; CedarProcess.Yield[]; ENDLOOP; Κ– "cedar" style˜codešœ™Jšœ Οmœ1™Jšœžœ‘;˜KJ˜J˜—šœžœ'˜Jšœžœ-˜7J˜š œžœžœžœžœžœžœ ˜QJ˜Jš œ žœ)žœžœ žœ˜dšžœ žœžœ˜Jš œ žœ)žœžœ žœ˜fJšžœ žœžœ ˜Jšžœžœ5˜IJšžœ ˜J˜—Jšœ žœ,žœ˜NJšœ%˜%Jšœ˜J˜J˜—šŸœžœ ˜&JšΟgœžœ˜Jšœžœ’ ˜ Jšœ žœ˜'Jš œžœ žœžœ žœ&žœ%žœ'˜ š  œžœžœžœ žœ žœžœ˜hJšœžœ žœ=˜RJšœ%˜%Jšœ'˜'J˜—š  œžœžœ2žœžœ ˜gJšœžœ˜Jšœžœ1˜8Jšœžœ.˜5Jšœžœ0˜7Jšœžœ6˜=J˜:Jšœ(’œ ’œ ˜@Jšœ)’œ ’œ ˜AJšœ,’œ ’œ ˜DJšœ-’œ ’œ ˜EJšœ*’œ’œ˜?Jš œ(’œ’œ’œ’œ˜>Jš œ)’œ’œ’œ’œ˜>šžœžœ˜!Jšžœ0’œ’œ’œ˜D—šžœžœ˜#Jšžœ0’œ’œ’œ˜D—Jšžœ˜Jšœ'žœžœ˜KJšœIžœ˜PJ˜J˜—šžœžœ žœ˜Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ&˜&Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ(˜(Jšœ*˜*J˜)J˜—J˜—J˜š   œžœžœžœžœ˜Mšžœ žœžœ˜Jšžœ=žœžœ/˜yJšžœ˜—Jšœ˜J˜—Jšœ—™—š  œžœ žœžœžœžœžœžœžœ(žœžœžœžœ˜°Kšœ žœžœžœ˜2Kšœ:˜:Kš œ žœžœžœžœ˜2Kšœ@˜@Kšœžœo˜„Kšœ‡˜‡šžœžœžœ"ž˜1Jšœžœ5˜?Jšœ7˜7Jšžœ<žœžœ˜HJšœ žœ˜š žœžœžœžœžœžœž˜;JšœH˜HJšžœžœžœžœ˜šžœžœ˜%Jšœžœ,˜AJšœ žœ˜'Jšžœ˜J˜—Jšžœžœžœ˜Jšžœ˜—Jšžœ˜—šœ˜Jšœ$˜$Kšœ!žœ ˜2šœ žœ˜KšœZ‘(˜‚Kšœ0˜0Kšœ˜—Kšœ˜—Jšœ'˜'K˜K˜—š  œ˜$Jšœ#žœ˜:Jšœžœ&˜0Jšœžœ˜0Jš’œžœ˜Kš œžœžœžœ žœ˜MKšžœžœžœ’œžœžœ’œžœ’œžœžœ˜lKšžœžœžœžœ,˜Nšžœžœžœžœ˜(Kšœžœžœ˜WKšžœ˜—Kšœžœžœ"˜;J˜J˜—™CJ™6Jšœ2™2—š œžœžœ8žœžœžœžœ˜”Kšœ žœ˜Kšœ žœžœžœ˜2Kš œ žœžœžœžœ˜Kšœ˜Kšœžœ˜Kšœ7˜7šžœžœžœ˜Kšœ(˜(Kšœžœžœžœ˜$Kšœ>˜>Kšœ žœ*˜9Kšœ/˜/Kšžœžœžœžœ˜KšœM˜MKšœ žœ˜(Kšœ žœ˜,Jšœžœ ˜*Jšœžœ˜#Kšœ žœ3˜CKšœ˜K˜Kšžœ˜—Jšœ(˜(Kšœf˜fšžœ žœžœ˜Kšœ˜Kšœžœžœžœ˜KšœA˜AKšœ žœ+˜;Kšžœžœžœžœ˜KšœL˜LJšœžœ/˜DJšœžœ&˜;Kšœ žœ;˜KKšœ˜Kšœ˜Kšžœ˜—Jšžœ>žœ žœ ˜]šœ˜Jšœ˜Jšœ!žœ˜™>J™—šžœ ™Jšœžœ™6Jšœžœžœ ™%šžœžœžœ žœ™Jšœ:™:Jšžœ™—Jšœ:žœ™?šžœžœž™JšœE™EKšœ'™'Kšžœ™—Kšœ™——J™—Jšœžœžœžœ™Jšœžœžœ'™