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:
ROPE ←
NIL, 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 BOOL ← TRUE;
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:
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;
};
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:
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"]];
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:
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;
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 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]];
};
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: 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]<min THEN {bestPermutedExpr ← expr; bestPermutedWire ← permutations.first; min ← Size[expr]};
permutations ← permutations.rest;
CedarProcess.CheckForAbort[! ANY => EXIT]; CedarProcess.Yield[];
ENDLOOP;
};
[] ← PWCore.RegisterLayoutAtom[$FullAlpsCell, FullAlpsCellLayout, DecorateFullAlpsCell];