LogicArithImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier January 5, 1987 9:12:44 pm PST
Christian LeCocq October 14, 1986 2:06:31 pm PDT
Barth, October 10, 1986 5:33:40 pm PDT
LogicArith
Impl:
CEDAR
PROGRAM
IMPORTS BitOps, CoreCreate, CoreFlat, CoreOps, CoreProperties, Logic, LogicUtils, Ports, Rosemary, Static
EXPORTS Logic
= BEGIN OPEN Logic, CoreCreate;
Adder
AdderName: ROPE = Rosemary.Register[roseClassName: "Adder", init: AdderInit, evalSimple: AdderSimple];
-- b>1 please
-- Sum[0] is the (wrong Mesa order) high-order bit
Adder:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
oneBitAdder: CellType ← LogicUtils.Extract["oneBitAdder.sch", TRUE]; -- designed by Alfred
insts: CellInstances ←
LIST[Instance[oneBitAdder,
["A", "A[0]"], ["B", "B[0]"], ["Sum", "Sum[0]"], ["Cout", "carryOut"], ["C", "carry[0]"]]];
IF b=0 THEN LogicUtils.Error["Please specify a number of bits for the adder"];
IF b=1
THEN
RETURN[
Cell[name: AdderName,
public: Wires["Vdd", "Gnd", "carryIn", "A", "B", "Sum", "carryOut"],
instances: LIST[Instance[oneBitAdder, ["A", "A"], ["B", "B"], ["C", "carryIn"], ["Sum", "Sum"], ["Cout", "carryOut"]]]]];
FOR i:
NAT
IN [1..b-1)
DO
insts ←
CONS[
Instance[oneBitAdder,
["A", Index["A", i]], ["B", Index["B", i]], ["Sum", Index["Sum", i]],
["Cout", Index["carry", i-1]], ["C", Index["carry", i]]],
insts];
ENDLOOP;
insts ←
CONS[
Instance[oneBitAdder,
["A", Index["A", b-1]], ["B", Index["B", b-1]], ["Sum", Index["Sum", b-1]],
["Cout", Index["carry", b-2]], ["C", "carryIn"]],
insts];
ct ← Cell[
name: AdderName,
public: Wires["Vdd", "Gnd", "carryIn", Seq["A", b], Seq["B", b], Seq["Sum", b], "carryOut"],
onlyInternal: Wires[Seq["carry", b-1]],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: AdderName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "carryIn"];
Ports.InitPorts[ct, l, drive, "carryOut"];
Ports.InitPorts[ct, ls, none, "A", "B"];
Ports.InitPorts[ct, ls, drive, "Sum"];
};
AdderState: TYPE = REF AdderStateRec;
AdderStateRec:
TYPE =
RECORD [
inA, inB, sum, carryIn, carryOut: NAT ← LAST[NAT]];
AdderInit: Rosemary.InitProc = {
state: AdderState ← IF oldStateAny=NIL THEN NEW[AdderStateRec] ELSE NARROW[oldStateAny];
[state.inA, state.inB, state.sum, state.carryIn, state.carryOut] ← Ports.PortIndexes[cellType.public, "A", "B", "Sum", "carryIn", "carryOut"];
stateAny ← state};
AdderSimple: Rosemary.EvalProc = {
state: AdderState ← NARROW[stateAny];
carry: Ports.Level ← p[state.carryIn].l;
FOR i:
NAT
DECREASING
IN [0..p[state.sum].ls.size)
DO
[carry, p[state.sum].ls[i]] ← SumL[p[state.inA].ls[i], p[state.inB].ls[i], carry];
ENDLOOP;
p[state.carryOut].l ← carry;
};
Constant
-- Value must fit on 32-bit; sign-extended if b>32;
ConstantName: ROPE = "Constant";
Constant:
PUBLIC
PROC [b:
NAT, v:
INT]
RETURNS [ct: CellType] = {
vCard: CARD = LOOPHOLE[v];
gnd: Wire ← Static.UnconnectedOK[CoreOps.CreateWire[name: "Gnd"]];
vdd: Wire ← Static.UnconnectedOK[CoreOps.CreateWire[name: "Vdd"]];
output: Wire ← Static.UnconnectedOK[CoreOps.CreateWires[size: b, name: "Output"]];
SELECT b
FROM
<=32 =>
FOR i:
NAT
IN [0..b)
DO
output[i] ← IF BitOps.EBFD[vCard, i, b] THEN vdd ELSE gnd;
ENDLOOP;
>32 =>
{sign: Wire ← IF v<0 THEN vdd ELSE gnd;
FOR i: NAT IN [0..b-32) DO output[i] ← sign; ENDLOOP;
FOR i:
NAT
IN [b-32..b)
DO
output[i] ← IF BitOps.EBFD[vCard, i-b+32, 32] THEN vdd ELSE gnd;
ENDLOOP;
};
ENDCASE => ERROR;
ct ← Cell[name: ConstantName, public: Wires[gnd, vdd, output], instances: NIL];
};
Comparator
ComparatorName: ROPE = Rosemary.Register[roseClassName: "Comparator", init: ComparatorInit, evalSimple: ComparatorSimple];
Comparator:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
xnorSeq: CellType;
insts: CellInstances;
IF b=0 THEN LogicUtils.Error["Please specify a number of bits for the comparator"];
xnorSeq ← SequenceCell[name: "XnorSequence",
baseCell: Xnor2[],
count: b,
sequencePorts: Wires["I-A", "I-B", "X"]];
insts ←
LIST[
Instance[xnorSeq, ["I-A", "A"], ["I-B", "B"], ["X", "Output"]],
Instance[And[b], ["I", "Output"], ["X", "AEqB"]]
];
ct ← Cell[
name: ComparatorName,
public: Wires["Vdd", "Gnd", Seq["A", b], Seq["B", b], "AEqB"],
onlyInternal: Wires[Seq["Output", b]],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ComparatorName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "A", "B"];
Ports.InitPorts[ct, l, drive, "AEqB"];
};
ComparatorState: TYPE = REF ComparatorStateRec;
ComparatorStateRec: TYPE = RECORD [a, b, eq: NAT ← LAST[NAT]];
ComparatorInit: Rosemary.InitProc = {
state: ComparatorState ← IF oldStateAny=NIL THEN NEW[ComparatorStateRec] ELSE NARROW[oldStateAny];
[state.a, state.b, state.eq] ← Ports.PortIndexes[cellType.public, "A", "B", "AEqB"];
stateAny ← state};
ComparatorSimple: Rosemary.EvalProc = {
state: ComparatorState ← NARROW[stateAny];
p[state.eq].l ← LSEqual[p[state.a].ls, p[state.b].ls];
};
Comparator with a constant
EqConstantName: ROPE = Rosemary.Register[roseClassName: "EqConstant", init: EqConstantInit, evalSimple: EqConstantSimple];
EqConstant:
PUBLIC
PROC [b:
NAT, v:
INT]
RETURNS [ct: CellType] = {
vCard: CARD = LOOPHOLE[v];
insts: CellInstances ← NIL;
internals: LIST OF WR ← NIL;
pas: LIST OF PA ← LIST[["X", "out"]]; -- output of the nor
in: Wire ← Seq["In", b];
inv: CellType ← Inv[];
nor: CellType ← Nor[b];
norInput: Wire ← FindWire[nor.public, "I"];
IF b=0 THEN LogicUtils.Error["Please specify a number of bits for the comparator to a constant"];
FOR i:
NAT
IN [0..b)
DO
IF BitOps.
EBFD[vCard, i, b]
THEN {
-- add inverter
newWire: Wire ← Wires[];
internals ← CONS[newWire, internals];
insts ← CONS[Instance[inv, ["I", in[i]], ["X", newWire]], insts];
pas ← CONS[[norInput[i], newWire], pas];
}
ELSE {pas ← CONS[[norInput[i], in[i]], pas]};
ENDLOOP;
insts ← CONS[InstanceList[nor, pas], insts];
ct ← Cell[
name: EqConstantName,
public: Wires["Vdd", "Gnd", in, "out"],
onlyInternal: IF internals=NIL THEN NIL ELSE WireList[internals],
instances: insts];
CoreProperties.PutCellTypeProp[ct, $value, NEW[LONG CARDINAL ← LOOPHOLE[v]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: EqConstantName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "In"];
Ports.InitPorts[ct, l, drive, "out"];
};
EqConstantState: TYPE = REF EqConstantStateRec;
EqConstantStateRec:
TYPE =
RECORD [
eqIn, eqOut: NAT, val: Ports.LevelSequence];
EqConstantInit: Rosemary.InitProc = {
state: EqConstantState ← IF oldStateAny=NIL THEN NEW[EqConstantStateRec] ELSE NARROW[oldStateAny];
[state.eqIn, state.eqOut] ← Ports.PortIndexes[cellType.public, "In", "out"];
state.val ← NEW[Ports.LevelSequenceRec[cellType.public[state.eqIn].size]];
Ports.LCToLS[NARROW[CoreProperties.GetCellTypeProp[cellType, $value], REF LONG CARDINAL]^, state.val];
stateAny ← state;
};
EqConstantSimple: Rosemary.EvalProc = {
state: EqConstantState ← NARROW[stateAny];
p[state.eqOut].l ← LSEqual[p[state.eqIn].ls, state.val];
};
LSEqual:
PROC [ls1, ls2: Ports.LevelSequence]
RETURNS [eq: Ports.Level] ~ {
IF ls1.size#ls2.size THEN ERROR;
eq ← H;
FOR i:
NAT
IN [0..ls1.size)
DO
eq ← Ports.AndL[eq, LEqual[ls1[i], ls2[i]]];
ENDLOOP;
};
LEqual:
PROC [l1, l2: Ports.Level]
RETURNS [eq: Ports.Level] ~ {
eq ←
SELECT l1
FROM
L => Ports.NotL[l2],
H => l2,
ENDCASE => X;
};
SumL:
PROC [a, b, c: Ports.Level]
RETURNS [carry, s: Ports.Level] ~ {
v: ARRAY Ports.Level OF NAT ← [0, 1, 0]; -- value of the level
d: ARRAY Ports.Level OF NAT ← [0, 0, 1]; -- possible delta
lower, higher: NAT;
cl, ch, sl, sh: Ports.Level;
lower ← v[a]+v[b]+v[c]; -- lower sum
higher ← lower+d[a]+d[b]+d[c]; -- higher sum
[cl, sl] ← TwoBitsToLevels[lower];
[ch, sh] ← TwoBitsToLevels[higher];
carry ← MergeLevels[cl, ch];
s ← IF carry#X THEN MergeLevels[sl, sh] ELSE X;
};
TwoBitsToLevels:
PROC [n:
NAT]
RETURNS [c, s: Ports.Level] ~ {
SELECT n
FROM
0 => RETURN[L, L];
1 => RETURN[L, H];
2 => RETURN[H, L];
3 => RETURN[H, H];
ENDCASE => ERROR;
};
MergeLevels:
PROC [b1, b2: Ports.Level]
RETURNS [l: Ports.Level] ~ {
l ← IF b1=b2 THEN b1 ELSE X};