LogicMuxesImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier January 5, 1987 9:13:57 pm PST
Pradeep Sindhu February 27, 1987 2:51:12 pm PST
Barth, October 10, 1986 5:30:37 pm PDT
DIRECTORY BitOps, CoreCreate, CoreFlat, Logic, LogicUtils, Ports, Rosemary;
LogicMuxesImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreCreate, CoreFlat, Logic, LogicUtils, Ports, Rosemary
EXPORTS Logic
= BEGIN OPEN Logic, CoreCreate;
Decoded 1-Bit multiplexer
-- Public: "Vdd", "Gnd", Seq["Select", n], Seq["In", n], "Output"
MuxDN1Name: ROPE = "MuxDN1";
MuxDN1: PUBLIC PROC [n: NAT] RETURNS [ct: CellType] ~ {
SELECT n FROM
0 => LogicUtils.Error["Please provide parameters for 1-bit decoded multiplexer"];
1 => LogicUtils.Error["What the hell is a 1-input decoded multiplexer ???"];
2 => RETURN[LogicUtils.Extract["NormalizedMuxD21.sch", TRUE]];
3 => RETURN[LogicUtils.Extract["NormalizedMuxD31.sch", TRUE]];
4 => RETURN[LogicUtils.Extract["NormalizedMuxD41.sch", TRUE]];
ENDCASE => {
-- the output is through a single inverter
insts: CellInstances ← LIST[Instance[Inv[], ["I", "nOutput"], ["X", "Output"]]];
-- In[i] is connected to an inverting tristate driver whose enable is Select[i]
seq: CellType ← CoreCreate.SequenceCell[
baseCell: TristateI[], count: n,
sequencePorts: Wires["I", "EN"]];
insts ← CONS[Instance[seq, ["I", "In"], ["EN", "Select"], ["X", "nOutput"]],
insts];
ct ← Cell[
name: MuxDN1Name,
public: Wires["Vdd", "Gnd", Seq["Select", n], Seq["In", n], "Output"],
onlyInternal: Wires["nOutput"],
instances: insts];
};
};
Encoded 1-Bit multiplexer
-- Public: "Vdd", "Gnd", Seq["Select", s], Seq["In", n], "Output", with s=NbBits[n]
MuxN1Name: ROPE = "MuxN1";
MuxN1: PUBLIC PROC [n: NAT] RETURNS [ct: CellType] = {
SELECT n FROM
0 => LogicUtils.Error["Please provide parameters for 1-bit encoded multiplexer"];
1 => LogicUtils.Error["What the hell is a 1-input encoded multiplexer ???"];
2 => RETURN[LogicUtils.Extract["NormalizedMux21.sch", TRUE]];
3 => RETURN[LogicUtils.Extract["NormalizedMux31.sch", TRUE]];
4 => RETURN[LogicUtils.Extract["NormalizedMux41.sch", TRUE]];
ENDCASE => {
s: INT ← BitOps.NBits[n];
insts: CellInstances ← LIST[
Instance[MuxDN1[n], ["Select", "decoded"], ["In", "In"], ["Output", "Output"]],
Instance[DecoderS[s, n], ["Address", "Select"], ["Select", "decoded"]]];
ct ← Cell[name: MuxN1Name,
public: Wires["Vdd", "Gnd", Seq["Select", s], Seq["In", n], "Output"],
onlyInternal: Wires[Seq["decoded", n]],
instances: insts];
};
};
Decoded b-Bit n-Input multiplexer
-- A simple sequence of muxDN1; easier to layout and faster than the encoded version!
-- I still have to add the buffers on the select lines (*)
MuxDName: ROPE = Rosemary.Register[roseClassName: "MuxD", init: MuxInit, evalSimple: MuxDSimple];
MuxD: PUBLIC PROC [n, b: NAT] RETURNS [ct: CellType] = {
wl: LIST OF WRNIL;
muxDN1: CellType ← MuxDN1[n];
inputOfMux: Wire ← FindWire[muxDN1.public, "In"];
insts: CellInstances ← NIL;
input: Wire ← Seq["In", n, Seq[size: b]];
output: Wire ← Seq["Output", b];
select: Wire ← Seq["Select", n];
IF n=0 OR b=0 THEN LogicUtils.Error["Please provide parameters for decoded multiplexer"];
IF b=1 THEN LogicUtils.Error["Please use the 1-bit version of the multiplexer"];
IF n=1 THEN LogicUtils.Error["What the hell is a 1-input decoded multiplexer ???"];
-- Create b instances of type MuxDN1[n], with pretty complex bindings
FOR bit: NAT IN [0..b) DO
pas: LIST OF PA;
actual: Wire;
wrs: LIST OF WRNIL;
FOR choice: NAT DECREASING IN [0..n) DO
wrs ← CONS[input[choice][bit], wrs];
ENDLOOP;
actual ← WireList[wrs];
wl ← CONS[actual, wl];
pas ← LIST[["Output", output[bit]], ["Select", select], [inputOfMux, actual]];
insts ← CONS[InstanceList[muxDN1, pas], insts];
ENDLOOP;
ct ← Cell[
name: MuxName,
public: Wires["Vdd", "Gnd", select, input, output],
onlyInternal: WireList[wl],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: MuxDName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "Select"];
Ports.InitPorts[ct, ls, drive, "Output"];
FOR i: NAT IN [0..n) DO Ports.InitPorts[ct, ls, none, input[i]]; ENDLOOP;
};
WhichSingleHigh: PROC [ls: Ports.LevelSequence] RETURNS [n: NATLAST[NAT], ok: BOOLFALSE] ~ {
FOR i: NAT IN [0..ls.size) DO
SELECT TRUE FROM
ls[i]=X => RETURN[i, FALSE];  -- invalid select line
ls[i]=H AND ok => RETURN[n, FALSE]; -- more than one high
ls[i]=H AND ~ok => {n ← i; ok ← TRUE}; -- remember this one
ENDCASE => NULL;
ENDLOOP;
};
MuxDSimple: Rosemary.EvalProc = {
state: MuxState ← NARROW[stateAny];
n: NAT; ok: BOOL;
[n, ok] ← WhichSingleHigh[p[state.select].ls];
IF ok THEN Ports.CopyLS[from: p[state.in][n].ls, to: p[state.out].ls]
ELSE Ports.SetLS[p[state.out].ls, X];
};
Encoded Muxes
-- Make a special case for n=2, 3, 4 using the 1-bit decoded vesion and buffers (*)
MuxName: ROPE = Rosemary.Register[roseClassName: "Mux", init: MuxInit, evalSimple: MuxSimple];
Mux: PUBLIC PROC [n, b: NAT] RETURNS [ct: CellType] = {
sizeSel: INT ← BitOps.NBits[n];
input: Wire ← Seq["In", n, Seq[size: b]];
insts: CellInstances ← LIST[
Instance[DecoderS[sizeSel, n], ["Address", "Select"], ["Select", "decoded"]],
Instance[MuxD[n, b], ["Select", "decoded"], ["In", "In"], ["Output", "Output"]]];
ct ← Cell[
name: MuxName,
public: Wires["Vdd", "Gnd", Seq["Select", sizeSel], input, Seq["Output", b]],
onlyInternal: Wires[Seq["decoded", n]],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: MuxName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "Select"];
Ports.InitPorts[ct, ls, drive, "Output"];
FOR i: NAT IN [0..n) DO Ports.InitPorts[ct, ls, none, input[i]]; ENDLOOP;
};
MuxState: TYPE = REF MuxStateRec;
MuxStateRec: TYPE = RECORD [
select, in, out: NATLAST[NAT]];
MuxInit: Rosemary.InitProc = {
state: MuxState ← NEW[MuxStateRec];
[state.select, state.in, state.out] ← Ports.PortIndexes[cellType.public, "Select", "In", "Output"];
stateAny ← state};
MuxSimple: Rosemary.EvalProc = {
state: MuxState ← NARROW[stateAny];
IF LogicUtils.HasX[p[state.select].ls] THEN Ports.SetLS[p[state.out].ls, X]
ELSE {
sel: NAT ← Ports.LSToC[p[state.select].ls];
IF sel>=p[state.in].size THEN Rosemary.Stop[];
Ports.CopyLS[from: p[state.in][sel].ls, to: p[state.out].ls];
};
};
Decoder
-- The simple decoder is implemented as "s" a-input nors; each input is inverted twice to produce complementary values, and the inputs of the nors are chosen among those.
DecoderSName: ROPE = Rosemary.Register[roseClassName: "DecoderS", init: DecoderSInit, evalSimple: DecoderSSimple];
DecoderS: PUBLIC PROC [a: NAT, s: NAT ← 0] RETURNS [ct: CellType] = {
inv, nor: CellType;
norInput, address, nAd, nnAd, select: Wire;
insts: CellInstances ← NIL;
IF a=0 THEN LogicUtils.Error["Please provide parameter(s) for decoder"];
IF s=0 THEN s ← BitOps.TwoToThe[a];
IF a=1 THEN SELECT s FROM
1 => RETURN[LogicUtils.Extract["decoder11.sch", TRUE]];
2 => RETURN[LogicUtils.Extract["decoder12.sch", TRUE]];
ENDCASE => NULL;
inv ← Inv[];
nor ← Nor[a];
norInput ← FindWire[nor.public, "I"];
address ← Seq["Address", a];
nAd ← Seq["nAd", a];
nnAd ← Seq["nnAd", a];
select ← Seq["Select", s];
-- inverter pairs on all inputs
FOR i: NAT IN [0..a) DO
insts ← CONS[Instance[inv, ["I", address[i]], ["X", nAd[i]] ], insts];
insts ← CONS[Instance[inv, ["I", nAd[i]], ["X", nnAd[i]] ], insts];
ENDLOOP;
-- one a-input nor per output
FOR i: NAT IN [0..s) DO
pas: LIST OF PALIST[["X", select[i]]];
-- recognize the input "i"
FOR in: NAT IN [0..a) DO
pas ← CONS[[norInput[in], IF BitOps.EBFW[i, in, a] THEN nAd[in] ELSE nnAd[in]], pas];
ENDLOOP;
insts ← CONS[InstanceList[nor, pas], insts];
ENDLOOP;
ct ← Cell[name: DecoderSName,
public: Wires["Vdd", "Gnd", address, select],
onlyInternal: Wires[nAd, nnAd],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: DecoderSName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "Address"];
Ports.InitPorts[ct, ls, drive, "Select"];
};
DecoderState: TYPE = REF DecoderStateRec;
DecoderStateRec: TYPE = RECORD [
decoderAd, decoderSel, decoderEnable: NATLAST[NAT]];
DecoderSInit: Rosemary.InitProc = {
state: DecoderState ← NEW[DecoderStateRec];
[state.decoderAd, state.decoderSel] ← Ports.PortIndexes[cellType.public, "Address", "Select"];
stateAny ← state};
DecoderSSimple: Rosemary.EvalProc = {
state: DecoderState ← NARROW[stateAny];
ad: NAT;
IF LogicUtils.HasX[p[state.decoderAd].ls] THEN {Ports.SetLS[p[state.decoderSel].ls, X]; RETURN};
ad ← Ports.LSToC[p[state.decoderAd].ls];
IF ad>p[state.decoderSel].ls.size THEN LogicUtils.Error["The address is out of bounds"];
Ports.SetLS[p[state.decoderSel].ls, L];
p[state.decoderSel].ls[ad] ← H;
};
-- The decoder with enable: if enable=L all outputs are low
DecoderName: ROPE = Rosemary.Register[roseClassName: "Decoder", init: DecoderInit, evalSimple: DecoderSimple];
Decoder: PUBLIC PROC [a: NAT, s: NAT ← 0] RETURNS [ct: CellType] = {
inv: CellType ← Inv[];
nor: CellType ← Nor[a+1]; -- one more input for nEnable
norInput: Wire ← FindWire[nor.public, "I"];
insts: CellInstances ← LIST[Instance[inv, ["I", "Enable"], ["X", "nEnable"]]]; -- invert enable
address: Wire ← Seq["Address", a];
nAd: Wire ← Seq["nAd", a];
nnAd: Wire ← Seq["nnAd", a];
select: Wire;
IF s=0 THEN s ← BitOps.TwoToThe[a];
select ← Seq["Select", s];
-- inverter pairs on all inputs
FOR i: NAT IN [0..a) DO
insts ← CONS[Instance[inv, ["I", address[i]], ["X", nAd[i]] ], insts];
insts ← CONS[Instance[inv, ["I", nAd[i]], ["X", nnAd[i]] ], insts];
ENDLOOP;
-- one (a+1)-input nor per output
FOR i: NAT IN [0..s) DO
pas: LIST OF PALIST[["X", select[i]], [norInput[a], "nEnable"]];
-- recognize the input "i"
FOR in: NAT IN [0..a) DO
pas ← CONS[[norInput[in], IF BitOps.EBFW[i, in, a] THEN nAd[in] ELSE nnAd[in]], pas];
ENDLOOP;
insts ← CONS[InstanceList[nor, pas], insts];
ENDLOOP;
ct ← Cell[name: DecoderName,
public: Wires["Vdd", "Gnd", address, select, "Enable"],
onlyInternal: Wires[nAd, nnAd, "nEnable"],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: DecoderName];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "Enable"];
Ports.InitPorts[ct, ls, none, "Address"];
Ports.InitPorts[ct, ls, drive, "Select"];
};
DecoderInit: Rosemary.InitProc = {
state: DecoderState ← NEW[DecoderStateRec];
[state.decoderAd, state.decoderSel, state.decoderEnable] ← Ports.PortIndexes[cellType.public, "Address", "Select", "Enable"];
stateAny ← state};
DecoderSimple: Rosemary.EvalProc = {
state: DecoderState ← NARROW[stateAny];
SELECT p[state.decoderEnable].l FROM
L => Ports.SetLS[p[state.decoderSel].ls, L];
H => {
ad: NAT;
IF LogicUtils.HasX[p[state.decoderAd].ls] THEN {Ports.SetLS[p[state.decoderSel].ls, X]; RETURN};
ad ← Ports.LSToC[p[state.decoderAd].ls];
IF ad>p[state.decoderSel].ls.size THEN LogicUtils.Error["The address is out of bounds"];
Ports.SetLS[p[state.decoderSel].ls, L]; p[state.decoderSel].ls[ad] ← H};
ENDCASE => Ports.SetLS[p[state.decoderSel].ls, X];
};
END.