LogicMacrosImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier August 7, 1986 1:05:33 am PDT
DIRECTORY BitHacks, CoreClasses, CoreCreate, CoreProperties, Logic, Ports, Rosemary, Sisyph;
LogicMacrosImpl: CEDAR PROGRAM
IMPORTS BitHacks, CoreClasses, CoreCreate, CoreProperties, Logic, Rosemary, Sisyph
EXPORTS Logic
= BEGIN OPEN Logic, CoreCreate;
Register
RegisterName: ROPE = "Register";
RegisterRName: ROPE = "RegisterR";
registerVdd, registerGnd, registerCK, registerInput, registerOutput, registerEnable: NAT;
registerRVdd, registerRGnd, registerRCK, registerRInput, registerROutput, registerREnable, registerRReset: NAT;
Register: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← SequenceCell[name: RegisterName,
baseCell: Sisyph.ES["reg1B.sch", cx],
count: b,
sequencePorts: Wires["Input", "Output"]];
[registerVdd, registerGnd, registerCK, registerInput, registerOutput, registerEnable] ← PortIndexes[ct.public, "Vdd", "Gnd", "CK", "Input", "Output", "en"];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, drive, "Output"];
};
RegisterR: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← SequenceCell[name: RegisterRName,
baseCell: Sisyph.ES["reg1BitReset.sch", cx],
count: b,
sequencePorts: Wires["Input", "Output"]];
[registerRVdd, registerRGnd, registerRCK, registerRInput, registerROutput, registerREnable, registerRReset] ← PortIndexes[ct.public, "Vdd", "Gnd", "CK", "Input", "Output", "en", "r"];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en", "r"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, drive, "Output"];
};
Tristate Buffer
TstBufferName: ROPE = Rosemary.Register[roseClassName: "TstBuffer", evalSimple: TstBufferSimple];
TstBufferInvName: ROPE = Rosemary.Register[roseClassName: "TstBufferInv", evalSimple: TstBufferInvSimple];
tstBufferVdd, tstBufferGnd, tstBufferInput, tstBufferOutput, tstBufferEnable: NAT;
tstBufferInvVdd, tstBufferInvGnd, tstBufferInvInput, tstBufferInvOutput, tstBufferInvEnable: NAT;
TristateBuffer: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: TstBufferName,
public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferName];
[tstBufferVdd, tstBufferGnd, tstBufferInput, tstBufferOutput, tstBufferEnable] ← PortIndexes[ct.public, "Vdd", "Gnd", "Input", "Output", "enable"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "enable"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, none, "Output"];
};
TristateBufferInv: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: TstBufferInvName,
public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferInvName];
[tstBufferInvVdd, tstBufferInvGnd, tstBufferInvInput, tstBufferInvOutput, tstBufferInvEnable] ← PortIndexes[ct.public, "Vdd", "Gnd", "Input", "Output", "enable"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "enable"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, none, "Output"];
};
TstBufferSimple: Rosemary.EvalProc = {
IF p[tstBufferEnable].l=H THEN {
p[tstBufferOutput].d ← drive;
CopyLS[from: p[tstBufferInput].ls, to: p[tstBufferOutput].ls];
}
ELSE p[tstBufferOutput].d ← none;
};
TstBufferInvSimple: Rosemary.EvalProc = {
IF p[tstBufferInvEnable].l=H THEN {
p[tstBufferInvOutput].d ← drive;
CopyLS[from: p[tstBufferInvInput].ls, to: p[tstBufferInvOutput].ls];
}
ELSE p[tstBufferInvOutput].d ← none;
};
Adder
AdderName: ROPE = Rosemary.Register[roseClassName: "Adder", evalSimple: AdderSimple];
adderVdd, adderGnd, adderA, adderB, adderSum, adderCarryIn, adderCarryOut: NAT;
-- b>1 please
-- Sum[0] is the (wrong Mesa order) high-order bit
Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
oneBitAdder: CellType ← Sisyph.ES["oneBitAdder.sch", cx]; -- designed by Alfred
insts: CellInstances ← LIST[Instance[oneBitAdder,
["A", "A[0]"], ["B", "B[0]"], ["Sum", "Sum[0]"], ["Cout", "carryOut"], ["C", "carry[0]"]]];
IF b<2 THEN ERROR;  -- we'll be more graceful soon!!!
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];
[adderVdd, adderGnd, adderA, adderB, adderSum, adderCarryIn, adderCarryOut] ← PortIndexes[ct.public, "Vdd", "Gnd", "A", "B", "Sum", "carryIn", "carryOut"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "carryIn"];
[] ← InitPorts[ct, l, drive, "carryOut"];
[] ← InitPorts[ct, ls, none, "A", "B"];
[] ← InitPorts[ct, ls, drive, "Sum"];
};
AdderSimple: Rosemary.EvalProc = {
carry: Ports.Level ← p[adderCarryIn].l;
FOR i: NAT DECREASING IN [0..p[adderSum].ls.size) DO
[carry, p[adderSum].ls[i]] ← SumL[p[adderA].ls[i], p[adderB].ls[i], carry];
ENDLOOP;
p[adderCarryOut].l ← carry;
};
Constant
ConstantName: ROPE = Rosemary.Register[roseClassName: "Constant", init: ConstantInit, evalSimple: ConstantSimple];
constantVdd, constantGnd, constantOutput: NAT;
Constant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: ConstantName,
public: Wires["Vdd", "Gnd", Seq["Output", b]]];
CoreProperties.PutCellTypeProp[ct, $value, NEW[INT ← v]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ConstantName];
[constantVdd, constantGnd, constantOutput] ← PortIndexes[ct.public, "Vdd", "Gnd", "Output"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd"];
[] ← InitPorts[ct, lc, drive, "Output"];
};
ConstantInit: Rosemary.InitProc = {
stateAny ← NARROW[CoreProperties.GetCellTypeProp[cellType, $value]];
};
ConstantSimple: Rosemary.EvalProc = {
val: INTNARROW[stateAny, REF INT]^;
p[constantOutput].lc ← val;
};
Comparator
ComparatorName: ROPE = Rosemary.Register[roseClassName: "Comparator", evalSimple: ComparatorSimple];
comparatorVdd, comparatorGnd, comparatorA, comparatorB, comparatorAEqB: NAT;
Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: ComparatorName,
public: Wires["Vdd", "Gnd", Seq["A", b], Seq["B", b], "AEqB"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ComparatorName];
[comparatorVdd, comparatorGnd, comparatorA, comparatorB, comparatorAEqB] ← PortIndexes[ct.public, "Vdd", "Gnd", "A", "B", "AEqB"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd"];
[] ← InitPorts[ct, ls, none, "A", "B"];
[] ← InitPorts[ct, l, drive, "AEqB"];
};
ComparatorSimple: Rosemary.EvalProc = {
p[comparatorAEqB].l ← H;
FOR i: NAT IN [0..p[comparatorA].ls.size) DO
IF p[comparatorA].ls[i]#p[comparatorB].ls[i] THEN p[comparatorAEqB].l ← L;
ENDLOOP;
};
Muxes
Mux2Name: ROPE = Rosemary.Register[roseClassName: "Mux2", evalSimple: Mux2Simple];
mux2Vdd, mux2Gnd, mux2Select, mux2In0, mux2In1, mux2Output: NAT;
Mux2: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: Mux2Name,
public: Wires["Vdd", "Gnd", "Select", Seq["In0", b], Seq["In1", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: Mux2Name];
[mux2Vdd, mux2Gnd, mux2Select, mux2In0, mux2In1, mux2Output] ← PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "Output"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "Select"];
[] ← InitPorts[ct, ls, none, "In0", "In1"];
[] ← InitPorts[ct, ls, drive, "Output"];
};
Mux2Simple: Rosemary.EvalProc = {
SELECT p[mux2Select].l FROM
L => CopyLS[from: p[mux2In0].ls, to: p[mux2Output].ls];
H => CopyLS[from: p[mux2In1].ls, to: p[mux2Output].ls];
ENDCASE => SetLS[p[mux2In0].ls, X];
};
Mux3Name: ROPE = Rosemary.Register[roseClassName: "Mux3", evalSimple: Mux3Simple];
mux3Vdd, mux3Gnd, mux3Select, mux3In0, mux3In1, mux3In2, mux3Output: NAT;
Mux3: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: Mux3Name,
public: Wires["Vdd", "Gnd", Seq["Select", 2], Seq["In0", b], Seq["In1", b], Seq["In2", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: Mux3Name];
[mux3Vdd, mux3Gnd, mux3Select, mux3In0, mux3In1, mux3In2, mux3Output] ← PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "In2", "Output"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd"];
[] ← InitPorts[ct, c, none, "Select"];
[] ← InitPorts[ct, ls, none, "In0", "In1", "In2"];
[] ← InitPorts[ct, ls, drive, "Output"];
};
Mux3Simple: Rosemary.EvalProc = {
SELECT p[mux3Select].c FROM
0 => CopyLS[from: p[mux3In0].ls, to: p[mux3Output].ls];
1 => CopyLS[from: p[mux3In1].ls, to: p[mux3Output].ls];
2 => CopyLS[from: p[mux3In2].ls, to: p[mux3Output].ls];
ENDCASE => ERROR;
};
Mux4Name: ROPE = Rosemary.Register[roseClassName: "Mux4", evalSimple: Mux4Simple];
mux4Vdd, mux4Gnd, mux4Select, mux4In0, mux4In1, mux4In2, mux4In3, mux4Output: NAT;
Mux4: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: Mux4Name,
public: Wires["Vdd", "Gnd", Seq["Select", 2],
Seq["In0", b], Seq["In1", b], Seq["In2", b], Seq["In3", b], Seq["Output", b]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: Mux4Name];
[mux4Vdd, mux4Gnd, mux4Select, mux4In0, mux4In1, mux4In2, mux4In3, mux4Output] ← PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "In2", "In3", "Output"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd"];
[] ← InitPorts[ct, c, none, "Select"];
[] ← InitPorts[ct, ls, none, "In0", "In1", "In2", "In3"];
[] ← InitPorts[ct, ls, drive, "Output"];
};
Mux4Simple: Rosemary.EvalProc = {
SELECT p[mux4Select].c FROM
0 => CopyLS[from: p[mux4In0].ls, to: p[mux4Output].ls];
1 => CopyLS[from: p[mux4In1].ls, to: p[mux4Output].ls];
2 => CopyLS[from: p[mux4In2].ls, to: p[mux4Output].ls];
3 => CopyLS[from: p[mux4In3].ls, to: p[mux4Output].ls];
ENDCASE => ERROR;
};
Decoder
DecoderName: ROPE = Rosemary.Register[roseClassName: "Decoder", evalSimple: DecoderSimple];
decoderVdd, decoderGnd, decoderAd, decoderNSel, decoderNEnable: NAT;
Decoder: PUBLIC PROC [a: NAT, s: NAT ← 0] RETURNS [ct: CellType] = {
IF s=0 THEN s ← BitHacks.TwoToThe[a];
ct ← CoreClasses.CreateUnspecified[name: DecoderName,
public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["nSelect", s], "nEnable"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: DecoderName];
[decoderVdd, decoderGnd, decoderAd, decoderNSel, decoderNEnable] ← PortIndexes[ct.public, "Vdd", "Gnd", "Address", "nSelect", "nEnable"];
[] ← Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "nEnable"];
[] ← InitPorts[ct, c, none, "Address"];
[] ← InitPorts[ct, ls, none, "nSelect"];
};
DecoderSimple: Rosemary.EvalProc = {
ad: NAT ← p[decoderAd].c;
IF ad>p[decoderNSel].size THEN ERROR;
SELECT p[decoderNEnable].l FROM
H => {p[decoderNSel].d ← drive; SetLS[p[decoderNSel].ls, H]; p[decoderNSel].ls[ad] ← L};
L => {p[decoderNSel].d ← none;};
ENDCASE => SetLS[p[decoderNSel].ls, X];
};
Counter
CounterName: ROPE = "Counter";
counterVdd, counterGnd, counters0, counters1, counterCin, counterCout, counterClock, counternInput, counterOutput: NAT;
Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
counter1B: CellType ← Sisyph.ES["counter1B.sch", cx]; -- designed by Alfred
insts: CellInstances ← NIL;
IF b<2 THEN ERROR;  -- we'll be more graceful soon!!!
FOR i: NAT IN [0..b) DO
insts ← CONS[
Instance[counter1B,
["dataIn", Index["Input", i]], ["Output", Index["Output", i]],
["carryIn", IF i=b-1 THEN "Cin" ELSE Index["carry", i]],
["carryOut", IF i=0 THEN "Cout" ELSE Index["carry", i-1]],
["nCount", "s1"], ["LoadOrDown", "s0"]],
insts];
ENDLOOP;
ct ← Cell[
name: CounterName,
public: Wires["Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", Seq["Input", b], Seq["Output", b]],
onlyInternal: Wires[Seq["carry", b-1]],
instances: insts];
[counterVdd, counterGnd, counters0, counters1, counterCin, counterCout, counterClock, counternInput, counterOutput] ← PortIndexes[ct.public, "Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", "Input", "Output"];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, none, "Output"];
};
ShiftReg
ShiftRegName: ROPE = "ShiftReg";
shiftRegVdd, shiftRegGnd, shiftRegs0, shiftRegs1, shiftRegClock, shiftRegInL, shiftRegInR, shiftRegnInput, shiftRegOutput: NAT;
ShiftReg: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
ff: CellType ← BasicFlipFlop[];
insts: CellInstances ← NIL;
IF b<2 THEN ERROR;  -- we'll be more graceful soon!!!
FOR i: NAT IN [0..b) DO
insts ← CONS[
Instance[ff,
["D0", IF i=0 THEN "inL" ELSE Index["Output", i-1]],
["D1", IF i=b-1 THEN "inR" ELSE Index["Output", i+1]],
["D2", Index["Output", i]],
["D3", Index["Input", i]],
["Q", Index["Output", i]],
["NQ", Index["fake", i]],
["s0", "s0"], ["s1", "s0"], ["s2", "s1"]],
insts];
ENDLOOP;
ct ← Cell[
name: ShiftRegName,
public: Wires["Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", Seq["Input", b], Seq["Output", b]],
onlyInternal: Wires[Seq["fake", b]],
instances: insts];
[shiftRegVdd, shiftRegGnd, shiftRegs0, shiftRegs1, shiftRegClock, shiftRegInL, shiftRegInR, shiftRegnInput, shiftRegOutput] ← PortIndexes[ct.public, "Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", "Input", "Output"];
[] ← InitPorts[ct, l, none, "Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR"];
[] ← InitPorts[ct, ls, none, "Input"];
[] ← InitPorts[ct, ls, none, "Output"];
};
END.