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
DIRECTORY BitOps, CoreClasses, CoreCreate, CoreFlat, CoreOps, CoreProperties, Logic, LogicUtils, Ports, Rosemary, Static;
LogicArithImpl: 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: NATLAST[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: NATLAST[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 WRNIL;
pas: LIST OF PALIST[["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 CARDINALLOOPHOLE[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};
END.
 26-Dec-86 Frailong.pa Logic
Date: 26 Dec 86 15:47:01 PST
From: Frailong.pa
Subject: Logic
To: Monier
cc: Frailong
Reply-To: Frailong
A suggestion of improvement for the EqConstant icon: would it be possible to allow the v parameter to accept both a REF INT and a LIST OF INT (or REF thereof)? The idea is to allow a constant comparator to return a comparison for a set of constants. This occurs quite frequently (at least in my design). Of course, the obvious solution is to have a set on EqConstant's and to OR the results. Obviously, a noticeably more efficient implementation is produced by merging the comparators (the gain is the inverters for bits that need it, plus the final OR which may very often bee simplified). I'm not really sure this is worth the effort, but I would be interested if you find a very simple implementation.
Jean-Marc