LogicArithImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier August 26, 1987 5:41:22 pm PDT
Jean-Marc Frailong September 14, 1987 10:57:27 pm PDT
Christian LeCocq October 14, 1986 2:06:31 pm PDT
Barth, August 6, 1987 5:07:02 pm PDT
DIRECTORY BitOps, CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Ports, Rosemary, Static;
LogicArithImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Ports, Static
EXPORTS Logic
= BEGIN OPEN LogicUtils, CoreCreate;
Adder
Shared types & functions
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]] ← Ports.SumL[p[state.inA].ls[i], p[state.inB].ls[i], carry];
ENDLOOP;
p[state.carryOut].l ← carry;
};
Ripple carry adder
Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
adderName: ROPE = "Adder";
fullName: ROPE = IO.PutFR["Adder b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
SELECT b FROM
0 => Error["Please specify a number of bits for the adder"];
1 => {
ct ← Extract["oneBitAdder.sch"]; -- designed by Alfred
CacheStore[fullName, ct];
};
ENDCASE => {
ct ← SequenceCell[baseCell: Adder[1], count: b,
sequencePorts: Wires["A", "B", "Sum"],
stitchPorts: LIST[["carryOut", "carryIn"]],
name: adderName];
SimulateMacro[ct, RoseClass[adderName, AdderInit, AdderSimple]];
Ports.InitPorts[ct, l, none, "carryIn"]; Ports.InitPorts[ct, l, drive, "carryOut"];
Ports.InitPorts[ct, ls, none, "A", "B"]; Ports.InitPorts[ct, ls, drive, "Sum"];
CacheStore[fullName, ct];
};
};
Constant
Value must fit on 32-bit; sign-extended if b>32;
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: "Constant", public: Wires[gnd, vdd, output], instances: NIL];
};
Comparators
Shared code
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;
};
Full comparator
Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["Comparator b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify a number of bits for the comparator"];
ct ← Extract["comparator.sch", LIST[["b", b]]];
SimulateMacro[ct, RoseClass["Comparator", ComparatorInit, ComparatorSimple]];
Ports.InitPorts[ct, ls, none, "A", "B"]; Ports.InitPorts[ct, l, drive, "AEqB"];
CacheStore[fullName, ct];
};
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
EqConstant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = {
NOR all the zeros, AND all the ones, and AND2 these two together
eqConstantName: ROPE = "EqConstant";
vCard: CARD = LOOPHOLE[v];
n0, n1: NAT ← 0;
int0, int1: Wire;
in: Wire;
wr0, wr1: LIST OF WRNIL;
fullName: ROPE = IO.PutFR["EqConstant b=%g v=%g", IO.int[b], IO.int[v]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify a number of bits for the constant comparator"];
-- sort out the zeros from the ones, and create the internals
in ← Seq["In", b];
FOR i: NAT IN [0..b) DO
IF BitOps.EBFD[vCard, i, b] THEN {n1 ← n1+1; wr1 ← CONS[in[i], wr1]}
ELSE {n0 ← n0+1; wr0 ← CONS[in[i], wr0]};
ENDLOOP;
SELECT TRUE FROM
n0+n1#b => ERROR;  -- just a check
n0=0 => { -- and[b] is enough
ct ← Cell[name: eqConstantName,
public: Wires["Vdd", "Gnd", in, "out"],
instances: LIST[InstanceList[Logic.And[b], LIST[["X", "out"], ["I", in]]]]];
};
n1=0 => { -- nor[b] is enough
ct ← Cell[name: eqConstantName,
public: Wires["Vdd", "Gnd", in, "out"],
instances: LIST[InstanceList[Logic.Nor[b], LIST[["X", "out"], ["I", in]]]]];
};
ENDCASE => {
subCT: CellType = Extract["eqConstant2Inputs.sch", LIST[["n0", n0], ["n1", n1]]];
int0 ← WireList[wr0];
int1 ← WireList[wr1];
ct ← Cell[name: eqConstantName,
public: Wires["Vdd", "Gnd", in, "out"],
onlyInternal: Wires[int0, int1],
instances: LIST[InstanceList[subCT, LIST[["out", "out"], ["in0", int0], ["in1", int1]]]]];
};
CoreProperties.PutCellTypeProp[ct, $value, NEW[LONG CARDINALLOOPHOLE[v]]];
SimulateMacro[ct, RoseClass[eqConstantName, EqConstantInit, EqConstantSimple]];
Ports.InitPorts[ct, ls, none, "In"]; Ports.InitPorts[ct, l, drive, "out"];
CacheStore[fullName, ct];
};
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];
};
END.