BooleCoreImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet August 13, 1985 5:47:24 pm PDT
Bertrand Serlet May 8, 1986 6:28:06 pm PDT
Louis Monier June 3, 1986 7:12:53 pm PDT
Barth, May 22, 1986 3:50:53 pm PDT
DIRECTORY
Boole, BooleCore,
CD, CDDirectory, CDSymbolicObjects, CMosB,
Core, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties,
IO,
PW, PWCore,
Rope, RopeList,
Rosemary, Ports,
Sinix, Sisyph,
TerminalIO;
BooleCoreImpl: CEDAR PROGRAM
IMPORTS Boole, CD, CDDirectory, CDSymbolicObjects, CMosB, CoreClasses, CoreCreate, CoreIO, CoreOps, CoreProperties, IO, PW, PWCore, Rope, RopeList, Rosemary, Ports, Sinix, Sisyph, TerminalIO
EXPORTS BooleCore
SHARES Boole =
BEGIN OPEN BooleCore;
Utilities
false: Expression = Boole.false;
Signal: SIGNAL = CODE;
true: Expression = Boole.true;
debug: BOOLTRUE;
AlpsClass
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
];
alpsClass: 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];
Data field contains a record ExprVars.
Public[0] is named Input and contains the flat list of all complemented inputs (Plus, Minus)
Public[1] is named Output and contains a structured wire (Plus, Minus) expressing the output.
Public[2] is Gnd
Public[3] is Vdd
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: ROPENIL, props: Properties ← NIL] RETURNS [alps: CellType] = {
input: Wire ← CreatePlusMinusN[name: "Input", names: inputVars];
data: ExprVars ← NEW [ExprVarsRec ← [expr: expr, vars: inputVars]];
CheckVarsOfExprInVars[expr, inputVars];
alps ← CoreOps.CreateCellType[
class: alpsClass,
public: CoreOps.CreateWire[LIST [
InitPort[input], InitPort[CreatePlusMinus[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;
Output: NAT = 1;
Gnd: NAT = 2;
Vdd: NAT = 3;
Plus: NAT = 0;
Minus: NAT = 1;
InitAlps: Rosemary.InitProc = {
stateAny ← cellType;
};
inputXmeansX: PUBLIC BOOLTRUE;
PlusMinusLevel: PROC [p: Ports.Port] RETURNS [l: Ports.Level] = {
l ← SELECT TRUE FROM
p[Plus].l=L AND p[Minus].l=H => L,
p[Plus].l=H AND p[Minus].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];
Default case: we set the 2 outputs to X
p[Output][Plus].l ← X;
p[Output][Plus].d ← drive;
p[Output][Minus].l ← X;
p[Output][Minus].d ← drive;
If Gnd is not Gnd, we might as well stop here
IF p[Gnd].l#L THEN RETURN;
IF p[Vdd].l#H THEN RETURN;
First pass on the expression to simplify it as much as we can
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]] FROM
L   => expr ← Boole.Eval[var, expr].whenFalse;
H   => expr ← Boole.Eval[var, expr].whenTrue;
ENDCASE => {
IF ~inputXmeansX THEN
Not much simplification, now we are going to have to create new data structures
FOR i: NAT IN [0..p[Input].size) DO
rope: ROPE ← CoreOps.GetShortWireName[input[i]];
SELECT PlusMinusLevel[p[Input][i]] FROM
L => expr ← Boole.Eval[rope, expr].whenFalse;
H => expr ← Boole.Eval[rope, expr].whenTrue;
ENDCASE;
ENDLOOP;
EXIT;
};
ENDLOOP;
If the resulting expression is true or false, we set the corresponding result
SELECT expr FROM
false =>
{p[Output][Plus].d ← none; p[Output][Minus].l ← L; p[Output][Minus].d ← drive};
true =>
{p[Output][Plus].l ← L; p[Output][Plus].d ← drive; p[Output][Minus].d ← none};
ENDCASE;
};
RecastAlps: Core.RecastProc = {
AlpsArrayLine: TYPE = REF AlpsArrayLineRec;
AlpsArrayLineRec: TYPE = RECORD [c: SEQUENCE size: NAT OF ATOM];
AlpsArray: TYPE = REF AlpsArrayRec;
AlpsArrayRec: TYPE = RECORD [c: SEQUENCE size: NAT 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];
size: NAT ← Size[revVars, expr];
alpsArray: AlpsArray ← NEW [AlpsArrayRec[size]];
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];
};
Connection with CoreCreate
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[];
};
};
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.WriteF["*** Structured (Plus, Minus) 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] ← CreatePlusMinus[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];
};
Does an InitPort recursively
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: BOOLTRUE] 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;
};
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.
CreateAlpsRow: PROC [inputVars: LIST OF ROPE, output: OutputRec, name: ROPENIL, props: Properties ← NIL] RETURNS [recordCell: CellType, futureBindings: LIST OF PANIL] = {
instances: LIST OF CoreClasses.CellInstance ← NIL;
internal: Wire ← CreatePlusMinus[name: "OutputPlusMinus"];
bindings: LIST OF PALIST [["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"]];
CheckPlusMinus[output.driver.public, "Input"]; 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]];
};
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)
AlpsCell: PUBLIC PROC [public: Wire, inputs: Inputs, outputs: Outputs, name: ROPENIL, props: Properties ← NIL] RETURNS [recordCell: CellType] = {
nbIn, nbOut: NAT ← 0;
instances: LIST OF CoreClasses.CellInstance ← NIL;
inputVars: LIST OF ROPENIL;
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 INTNARROW [CoreProperties.GetCellTypeProp[cellType, $NbIn]];
nbIn: INT ← refNbIn^;
l: INT = CMosB.lambda;
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
refContactPolyMetal2: REF INTNARROW [CoreProperties.GetCellTypeProp[cellType, $ContactPolyMetal2]];
contactPolyMetal2: INTIF 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;
Make the contact line
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];
Input Drivers
BEGIN
inputDriversObjects: LIST OF CD.Object ← NIL;
WHILE i<nbIn DO
inputDriversObjects ← CONS [PWCore.Layout[data[i].type], inputDriversObjects];
i ← i + 1;
ENDLOOP;
lineObjects ← LIST [PW.AbutListX[PW.Reverse[CONS [CDCell[$FillerCornerDriver, FALSE], inputDriversObjects]]]];
END;
Alps lines
WHILE i<data.size DO
row: CD.Object ← PWCore.Layout[data[i].type];
rowSize: CD.Position ← CD.InterestSize[row];
nbSubRows: INT ← rowSize.y / (24*l);
distanceSinceLastContact ← distanceSinceLastContact + nbSubRows;
lineObjects ← CONS [row, lineObjects];
IF distanceSinceLastContact>=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<pos2.y OR (pos1.y=pos2.y AND pos1.x<pos2.x)];
};
PWCore.DecorateFlatten[cellType, obj, Sort];
};
WireVar: PUBLIC PROC [public: Wire, wr: WR] RETURNS [expr: Expression] = {
wire: Wire ← CoreCreate.FindWire[public, wr];
IF wire=NIL THEN Signal[];
expr ← Boole.Var[CoreOps.GetFullWireName[public, wire]];
};
EqualInt: PUBLIC PROC [public: Wire, wr: WR, int: INT] RETURNS [expr: Expression] = {
Andify: PROC [wire: Wire] = {
var: Expression;
max ← max / 2;
var ← Boole.Var[CoreOps.GetFullWireName[public, wire]];
IF int>=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[];
};
with
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;
};
Reorder: PUBLIC PROC [expr: Expression, public: Wire] RETURNS [newExpr: Expression] = {
vars: LIST OF ROPENIL;
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]];
};
coreBoolePermuteProp: PUBLIC ATOM ← CoreProperties.RegisterProperty[$BoolePermuteProp];
Permute: PUBLIC PROC [expr: Expression, public: Wire] RETURNS [bestPermutedExpr: Expression, bestPermutedWire: Wire] = {
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: INTLAST[INT];
permutations: LIST OF Wire ← EnumeratePermutedWires[public];
bestPermutedExpr ← expr;
bestPermutedWire ← public;
WHILE permutations#NIL DO
expr ← Reorder[bestPermutedExpr, permutations.first];
IF Size[expr]<min THEN {bestPermutedExpr ← expr; bestPermutedWire ← permutations.first; min ← Size[expr]};
permutations ← permutations.rest;
CedarProcess.CheckForAbort[! ANY => EXIT]; CedarProcess.Yield[];
ENDLOOP;
};
[] ← PWCore.RegisterLayoutAtom[$AlpsRow, AlpsRowLayout, PWCore.DecorateAbutX];
[] ← PWCore.RegisterLayoutAtom[$FullAlpsCell, FullAlpsCellLayout, DecorateFullAlpsCell];
IF debug THEN PW.Register[AddCaseCellsInLibrary, "AddCaseCellsInLibrary"];
END.