LogicSimpleImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier March 17, 1987 8:11:47 pm PST
Christian LeCocq October 17, 1986 6:05:34 pm PDT
Barth, October 10, 1986 5:38:40 pm PDT
Alfred Permuy September 11, 1986 10:19:56 pm PDT
Pradeep Sindhu September 11, 1986 11:38:39 pm PDT
This package contains all basic cells present in the library (nand2, flip-flop, ...) and very simple macros: n-inputs and gates, buffer of arbitrary size, ...
DIRECTORY CoreClasses, CoreCreate, CoreFlat, IO, Logic, LogicUtils, Ports, Rosemary;
LogicSimple
Impl:
CEDAR
PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, IO, Logic, LogicUtils, Ports, Rosemary
EXPORTS Logic
= BEGIN OPEN Logic, CoreCreate;
-- Corresponding to very common types of publics
IXRef: TYPE = REF IXRec;
IXRec: TYPE = RECORD [in, out: NAT ← LAST[NAT]];
I4XRef: TYPE = REF I4XRec;
I4XRec: TYPE = RECORD [in0, in1, in2, in3, out: NAT ← LAST[NAT]];
IXInit: Rosemary.InitProc = {
state: IXRef ← IF oldStateAny=NIL THEN NEW[IXRec] ELSE NARROW[oldStateAny];
[state.in, state.out] ← Ports.PortIndexes[cellType.public, "I", "X"];
stateAny ← state;
};
I2XInit: Rosemary.InitProc = {
state: I4XRef ← IF oldStateAny=NIL THEN NEW[I4XRec] ELSE NARROW[oldStateAny];
[state.in0, state.in1, state.out] ← Ports.PortIndexes[cellType.public, "I-A", "I-B", "X"];
stateAny ← state;
};
Inverter(s)
InvName: ROPE = Rosemary.Register[roseClassName: "Inv", init: InvInit, evalSimple: InvSimple];
Inv:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "inv", width: 2,
name: InvName, public: Wires["Vdd", "Gnd", "I", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
InvInit: Rosemary.InitProc = {
state: IXRef ← IF oldStateAny=NIL THEN NEW[IXRec] ELSE NARROW[oldStateAny];
[state.in, state.out] ← Ports.PortIndexes[cellType.public, "I", "X"];
stateAny ← state};
InvSimple: Rosemary.EvalProc = {
state: IXRef ← NARROW[stateAny];
p[state.out].l ← SELECT p[state.in].l FROM L => H, H => L, ENDCASE => X;
};
BufferName: ROPE = Rosemary.Register[roseClassName: "Buffer", init: InvInit, evalSimple: InvSimple];
-- A buffer of drive d is equivalent to d inverters connected in parallel
Buffer:
PUBLIC
PROC[d:
NAT]
RETURNS [ct: CellType] = {
buffer2: CellType ← LogicUtils.MakeSC[nameInLib: "invBuffer", width: 3,
name: BufferName, public: Wires["Vdd", "Gnd", "I", "X"]];
ct ← SequenceCell[name: BufferName, baseCell: buffer2, count: MAX[d/2, 1]];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
Tristate Driver
TstRef: TYPE = REF TstRec;
TstRec: TYPE = RECORD [in, out, en, nEn: NAT ← LAST[NAT]];
TstInit: Rosemary.InitProc = {
state: TstRef ← IF oldStateAny=NIL THEN NEW[TstRec] ELSE NARROW[oldStateAny];
[state.in, state.out, state.en, state.nEn] ← Ports.PortIndexes[cellType.public, "I", "X", "EN", "NEN"];
stateAny ← state;
};
TstDriverName: ROPE = Rosemary.Register[roseClassName: "TstDriver", init: TstInit, evalSimple: TstDriverSimple];
TstDriver:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "tstDriver", width: 4,
name: TstDriverName, public: Wires["Vdd", "Gnd", "I", "X", "EN", "NEN"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "I", "EN", "NEN", "X"];
};
TstDriverSimple: Rosemary.EvalProc = {
-- by Pradeep
state: TstRef ← NARROW[stateAny];
{OPEN state;
IF p[en].l#L
AND p[in].l#L
THEN {
-- N-Section of TstDriver
p[out].d ← drive;
IF p[en].l=H AND p[in].l=H THEN p[out].l ← L ELSE p[out].l ← X;
RETURN;
};
IF p[nEn].l#H
AND p[in].l#H
THEN {
-- P-Section of TstDriver
p[out].d ← drive;
IF p[nEn].l=L AND p[in].l=L THEN p[out].l ← H ELSE p[out].l ← X;
RETURN;
};
p[out].d ← none;
}};
TristateI: PUBLIC PROC RETURNS [ct: CellType] ~ {ct ← LogicUtils.Extract["3BufferI.icon", TRUE]};
TristateNI: PUBLIC PROC RETURNS [ct: CellType] ~ {ct ← LogicUtils.Extract["3BufferNI.icon", TRUE]};
Common to the And, Nand, Or, Nor
B4: TYPE = {and, nand, or, nor};
nameInLib: ARRAY B4 OF ROPE = ["and", "nand", "or", "nor"];
nameOfCT: ARRAY B4 OF ROPE = ["And", "Nand", "Or", "Nor"];
rootCT: ARRAY B4 OF B4 = [nor, nand, nand, nor];
leafCT: ARRAY B4 OF B4 = [nand, and, nor, or];
InternalB4:
PROC [b4: B4, n:
NAT]
RETURNS [ct: CellType] = {
scPublic: Wire ←
SELECT n
FROM
2 => Wires["Vdd", "Gnd", "I-A", "I-B", "X"],
3 => Wires["Vdd", "Gnd", "I-A", "I-B", "I-C", "X"],
4 => Wires["Vdd", "Gnd", "I-A", "I-B", "I-C", "I-D", "X"],
ENDCASE => ERROR;
nameLib: ROPE ← IO.PutFR["%g%g", IO.rope[nameInLib[b4]], IO.int[n]];
nameCT: ROPE ← IO.PutFR["%g%g", IO.rope[nameOfCT[b4]], IO.int[n]];
sc: CellType ← LogicUtils.MakeSC[
nameInLib: nameLib,
name: nameCT,
width: n+1+(IF b4=and OR b4=or THEN 1 ELSE 0),
public: scPublic];
pas: LIST OF PA ← LIST[["I-A", "I[0]"], ["I-B", "I[1]"]];
IF n>2 THEN pas ← CONS[["I-C", "I[2]"], pas];
IF n>3 THEN pas ← CONS[["I-D", "I[3]"], pas];
ct ← Cell[name:
IO.PutFR["Normalized%g",
IO.rope[nameCT]],
public: Wires["Vdd", "Gnd", Seq["I", n], "X"],
instances: LIST[InstanceList[sc, pas]]];
};
-- and -> nor2(nand)
-- nand -> nand2(and)
-- or -> nand2(nor)
-- nor -> nor2(or)
B4Large:
PROC [b4: B4, n:
NAT]
RETURNS [ct: CellType] ~ {
input: Wire = Seq["I", n];
n1: NAT ← n/2;
root, c1, c2: CellInstance;
SELECT n
FROM
0, 1 => LogicUtils.Error["@@@ This should never happen, call implementor @@@"];
2, 3, 4 => RETURN[InternalB4[b4, n]];
ENDCASE => NULL; -- for n>4, see further
root ← Instance[InternalB4[rootCT[b4], 2], ["I", Wires["One", "Two"]]];
c1 ← Instance[B4Large[leafCT[b4], n1], ["X", "One"], ["I", Range[input, 0, n1]]];
c2 ← Instance[B4Large[leafCT[b4], n-n1], ["X", "Two"], ["I", Range[input, n1, n-n1]]];
ct ← Cell[name:
IO.PutFR["%g%g",
IO.rope[nameOfCT[b4]],
IO.int[n]],
public: Wires["Vdd", "Gnd", input, "X"],
onlyInternal: Wires["One", "Two"],
instances: LIST[root, c1, c2]];
};
And
AndName: ROPE = Rosemary.Register[roseClassName: "And", init: IXInit, evalSimple: AndSimple];
And:
PUBLIC
PROC[n:
NAT]
RETURNS [ct: CellType] = {
IF n=0 THEN LogicUtils.Error["Please specify the number of inputs of the `and' gate"];
IF n=1 THEN LogicUtils.Error["What the hell is a 1-input `and' gate???"];
ct ← B4Large[and, n];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: AndName];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
AndSimple: Rosemary.EvalProc = {
state: IXRef ← NARROW[stateAny];
allHigh: BOOL ← TRUE;
FOR i:
NAT
IN [0..p[state.in].ls.size)
DO
IF p[state.in].ls[i]=L THEN {p[state.out].l ← L; RETURN};
allHigh ← allHigh AND p[state.in].ls[i]=H;
ENDLOOP;
p[state.out].l ←
SELECT
TRUE
FROM
allHigh => H,
ENDCASE => X;
};
Nand
NandName: ROPE = Rosemary.Register[roseClassName: "Nand", init: IXInit, evalSimple: NandSimple];
Nand:
PUBLIC
PROC[n:
NAT]
RETURNS [ct: CellType] = {
IF n=0 THEN LogicUtils.Error["Please specify the number of inputs of the `nand' gate"];
IF n=1 THEN LogicUtils.Error["What the hell is a 1-input `nand' gate???"];
ct ← B4Large[nand, n];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: NandName];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
NandSimple: Rosemary.EvalProc = {
state: IXRef ← NARROW[stateAny];
allHigh: BOOL ← TRUE;
FOR i:
NAT
IN [0..p[state.in].ls.size)
DO
IF p[state.in].ls[i]=L THEN {p[state.out].l ← H; RETURN};
allHigh ← allHigh AND p[state.in].ls[i]=H;
ENDLOOP;
p[state.out].l ←
SELECT
TRUE
FROM
allHigh => L,
ENDCASE => X;
};
Or
OrName: ROPE = Rosemary.Register[roseClassName: "Or", init: IXInit, evalSimple: OrSimple];
Or:
PUBLIC
PROC[n:
NAT]
RETURNS [ct: CellType] = {
IF n=0 THEN LogicUtils.Error["Please specify the number of inputs of the `or' gate"];
IF n=1 THEN LogicUtils.Error["What the hell is a 1-input `or' gate???"];
ct ← B4Large[or, n];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: OrName];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
OrSimple: Rosemary.EvalProc = {
state: IXRef ← NARROW[stateAny];
allLow: BOOL ← TRUE;
FOR i:
NAT
IN [0..p[state.in].ls.size)
DO
IF p[state.in].ls[i]=H THEN {p[state.out].l ← H; RETURN};
allLow ← allLow AND p[state.in].ls[i]=L;
ENDLOOP;
p[state.out].l ←
SELECT
TRUE
FROM
allLow => L,
ENDCASE => X;
};
Nor
NorName: ROPE = Rosemary.Register[roseClassName: "Nor", init: IXInit, evalSimple: NorSimple];
Nor:
PUBLIC
PROC[n:
NAT]
RETURNS [ct: CellType] = {
IF n=0 THEN LogicUtils.Error["Please specify the number of inputs of the `nor' gate"];
IF n=1 THEN LogicUtils.Error["What the hell is a 1-input `nor' gate???"];
ct ← B4Large[nor, n];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: NorName];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
Ports.InitPorts[ct, ls, none, "I"];
Ports.InitPorts[ct, l, drive, "X"];
};
NorSimple: Rosemary.EvalProc = {
state: IXRef ← NARROW[stateAny];
allLow: BOOL ← TRUE;
FOR i:
NAT
IN [0..p[state.in].ls.size)
DO
IF p[state.in].ls[i]=H THEN {p[state.out].l ← L; RETURN};
allLow ← allLow AND p[state.in].ls[i]=L;
ENDLOOP;
p[state.out].l ←
SELECT
TRUE
FROM
allLow => H,
ENDCASE => X;
};
Xor and Xnor
Xor2Name: ROPE = Rosemary.Register[roseClassName: "Xor2", init: I2XInit, evalSimple: Xor2Simple];
Xnor2Name: ROPE = Rosemary.Register[roseClassName: "Xnor2", init: I2XInit, evalSimple: Xnor2Simple];
Xor2:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "xor2", name: Xor2Name, width: 6,
public: Wires["Vdd", "Gnd", "I-A", "I-B", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "I-A", "I-B"];
Ports.InitPorts[ct, l, drive, "X"];
};
Xor2Simple: Rosemary.EvalProc = {
state: I4XRef ← NARROW[stateAny];
p[state.out].l ←
SELECT
TRUE
FROM
p[state.in0].l=X OR p[state.in1].l=X => X,
p[state.in0].l=p[state.in1].l => L,
ENDCASE => H;
};
Xnor2:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "xnor2", name: Xnor2Name, width: 6,
public: Wires["Vdd", "Gnd", "I-A", "I-B", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "I-A", "I-B"];
Ports.InitPorts[ct, l, drive, "X"];
};
Xnor2Simple: Rosemary.EvalProc = {
state: I4XRef ← NARROW[stateAny];
p[state.out].l ←
SELECT
TRUE
FROM
p[state.in0].l=X OR p[state.in1].l=X => X,
p[state.in0].l=p[state.in1].l => H,
ENDCASE => L;
};
Complex gates
A22o2iName: ROPE = Rosemary.Register[roseClassName: "A22o2i", init: CG4Init, evalSimple: A22o2iSimple];
A21o2iName: ROPE = Rosemary.Register[roseClassName: "A21o2i", init: CG3Init, evalSimple: A21o2iSimple];
O22a2iName: ROPE = Rosemary.Register[roseClassName: "O22a2i", init: CG4Init, evalSimple: O22a2iSimple];
CG4Init: Rosemary.InitProc = {
state: I4XRef ← IF oldStateAny=NIL THEN NEW[I4XRec] ELSE NARROW[oldStateAny];
[state.in0, state.in1, state.in2, state.in3, state.out] ← Ports.PortIndexes[cellType.public, "A", "B", "C", "D", "X"];
stateAny ← state;
};
CG3Init: Rosemary.InitProc = {
state: I4XRef ← IF oldStateAny=NIL THEN NEW[I4XRec] ELSE NARROW[oldStateAny];
[state.in0, state.in1, state.in2, state.out] ← Ports.PortIndexes[cellType.public, "A", "B", "C", "X"];
stateAny ← state;
};
A22o2i:
PUBLIC
PROC[]
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "a22o2i", width: 5,
name: A22o2iName, public: Wires["Vdd", "Gnd", "A", "B", "C", "D", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "A", "B", "C", "D"];
Ports.InitPorts[ct, l, drive, "X"];
};
A22o2iSimple: Rosemary.EvalProc = {
state: I4XRef ← NARROW[stateAny];
p[state.out].l ←
SELECT
TRUE
FROM
(p[state.in0].l=H AND p[state.in1].l=H) OR (p[state.in2].l=H AND p[state.in3].l=H) => L,
(p[state.in0].l=L OR p[state.in1].l=L) AND (p[state.in2].l=L OR p[state.in3].l=L) => H,
ENDCASE => X;
};
A21o2i:
PUBLIC
PROC[]
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "a21o2i", width: 4,
name: A21o2iName, public: Wires["Vdd", "Gnd", "A", "B", "C", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "A", "B", "C"];
Ports.InitPorts[ct, l, drive, "X"];
};
A21o2iSimple: Rosemary.EvalProc = {
state: I4XRef ← NARROW[stateAny];
p[state.out].l ←
SELECT
TRUE
FROM
(p[state.in0].l=H AND p[state.in1].l=H) OR p[state.in2].l=H => L,
(p[state.in0].l=L OR p[state.in1].l=L) AND p[state.in2].l=L => H,
ENDCASE => X;
};
O22a2i:
PUBLIC
PROC[]
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "o22a2i", width: 5,
name: O22a2iName, public: Wires["Vdd", "Gnd", "A", "B", "C", "D", "X"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "A", "B", "C", "D"];
Ports.InitPorts[ct, l, drive, "X"];
};
O22a2iSimple: Rosemary.EvalProc = {
state: I4XRef ← NARROW[stateAny];
p[state.out].l ←
SELECT
TRUE
FROM
(p[state.in0].l=H OR p[state.in1].l=H) AND (p[state.in2].l=H OR p[state.in3].l=H) => L,
(p[state.in0].l=L AND p[state.in1].l=L) OR (p[state.in2].l=L AND p[state.in3].l=L) => H,
ENDCASE => X;
};
Edge-Triggered Flip-Flop (one input, one clock, complementary outputs)
FFName: ROPE = Rosemary.Register[roseClassName: "FF", init: FFInit, evalSimple: FFSimple];
FlipFlop:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "ff", width: 10,
name: FFName, public: Wires["Vdd", "Gnd", "D", "Q", "NQ", "CK"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "D", "CK"];
Ports.InitPorts[ct, l, drive, "Q", "NQ"];
};
FFRef: TYPE = REF FFRec;
FFRec:
TYPE =
RECORD [
ffD, ffQ, ffNQ, ffClock: NAT ← LAST[NAT],
master, slave: Ports.Level];
FFInit: Rosemary.InitProc = {
state: FFRef ← IF oldStateAny=NIL THEN NEW[FFRec] ELSE NARROW[oldStateAny];
state.master ← state.slave ← X;
[state.ffD, state.ffQ, state.ffNQ, state.ffClock] ← Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK"];
p[state.ffQ].l ← p[state.ffNQ].l ← X;
stateAny ← state;
};
FFSimple: Rosemary.EvalProc = {
-- of course state.master is the inverse of the physical master level in the current CMosB implementation, but nobody has access to the real value, so let's keep things simple...
state: FFRef ← NARROW[stateAny];
SELECT p[state.ffClock].l
FROM
L => state.master ← p[state.ffD].l;
H => state.slave ← state.master;
ENDCASE => {
IF state.slave#state.master THEN state.slave ← X;
IF state.master#p[state.ffD].l THEN state.master ← X;
};
p[state.ffQ].l ← state.slave; p[state.ffNQ].l ← Ports.NotL[state.slave];
};
Edge-Triggered Flip-Flop (with data enable)
FFenName: ROPE = Rosemary.Register[roseClassName: "FFen", init: FFenInit, evalSimple: FFenSimple];
FlipFlopEnable:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "ffEn", width: 14,
name: FFenName, public: Wires["Vdd", "Gnd", "D", "Q", "NQ", "CK", "en", "nEn"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "D", "CK", "en", "nEn"];
Ports.InitPorts[ct, l, drive, "Q", "NQ"];
};
FFenRef: TYPE = REF FFenRec;
FFenRec:
TYPE =
RECORD [
ffD, ffQ, ffNQ, ffClock, ffen, ffnEn: NAT ← LAST[NAT],
master, slave: Ports.Level];
FFenInit: Rosemary.InitProc = {
state: FFenRef ← IF oldStateAny=NIL THEN NEW[FFenRec] ELSE NARROW[oldStateAny];
state.master ← state.slave ← X;
[state.ffD, state.ffQ, state.ffNQ, state.ffClock, state.ffen, state.ffnEn, ] ← Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK", "en", "nEn"];
p[state.ffQ].l ← p[state.ffNQ].l ← X;
stateAny ← state;
};
FFenSimple: Rosemary.EvalProc = {
-- of course state.master is the inverse of the physical master level in the current CMosB implementation, but nobody has access to the real value, so let's keep things simple...
state: FFenRef ← NARROW[stateAny];
SELECT p[state.ffClock].l
FROM
L => {
state.master ←
SELECT
TRUE
FROM
p[state.ffen].l=H AND p[state.ffnEn].l=L => p[state.ffD].l,
p[state.ffen].l=L AND p[state.ffnEn].l=H => state.slave,
ENDCASE => X;
};
H => state.slave ← state.master;
ENDCASE => {
IF state.slave#state.master THEN state.slave ← X;
IF state.master#p[state.ffD].l THEN state.master ← X;
};
p[state.ffQ].l ← state.slave; p[state.ffNQ].l ← Ports.NotL[state.slave];
};
Edge-Triggered Flip-Flop (with asynchronous reset)
FFARName: ROPE = Rosemary.Register[roseClassName: "FFAR", init: FFARInit, evalSimple: FFARSimple];
FlipFlopAsyncReset:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: FFARName,
public: Wires["Vdd", "Gnd", "D", "Q", "NQ", "CK", "r"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "D", "CK", "r"];
Ports.InitPorts[ct, l, drive, "Q", "NQ"];
};
FFARRef: TYPE = REF FFARRec;
FFARRec:
TYPE =
RECORD [
ffD, ffQ, ffNQ, ffClock, ffR: NAT ← LAST[NAT],
master, slave: Ports.Level];
FFARInit: Rosemary.InitProc = {
state: FFARRef ← IF oldStateAny=NIL THEN NEW[FFARRec] ELSE NARROW[oldStateAny];
state.master ← state.slave ← X;
[state.ffD, state.ffQ, state.ffNQ, state.ffClock, state.ffR] ← Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK", "r"];
p[state.ffQ].l ← p[state.ffNQ].l ← X;
stateAny ← state;
};
FFARSimple: Rosemary.EvalProc = {
state: FFARRef ← NARROW[stateAny];
SELECT p[state.ffR].l
FROM
L =>
-- normal mode of operation
SELECT p[state.ffClock].l
FROM
L => state.master ← p[state.ffD].l;
H => state.slave ← state.master;
ENDCASE => {
IF state.slave#state.master THEN state.slave ← X;
IF state.master#p[state.ffD].l THEN state.master ← X;
};
H => state.slave ← state.master ← L; -- asynchronous reset
ENDCASE => state.slave ← state.master ← X; -- mushy reset
p[state.ffQ].l ← state.slave; p[state.ffNQ].l ← Ports.NotL[state.slave];
};
RS Flip-Flop (not a SC)
RSName: ROPE = Rosemary.Register[roseClassName: "RS", init: RSInit, evalSimple: RSSimple];
RS:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← CoreClasses.CreateUnspecified[name: RSName,
public: Wires["Vdd", "Gnd", "R", "S", "Q", "nQ"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "R", "S"];
Ports.InitPorts[ct, l, drive, "Q", "NQ"];
};
RSRef: TYPE = REF RSRec;
RSRec:
TYPE =
RECORD [
r, s, q, nq: NAT ← LAST[NAT],
bit: Ports.Level]; -- a copy of Q
RSInit: Rosemary.InitProc = {
state: RSRef ← IF oldStateAny=NIL THEN NEW[RSRec] ELSE NARROW[oldStateAny];
state.bit ← X;
[state.r, state.s, state.q, state.nq] ← Ports.PortIndexes[cellType.public, "R", "S", "Q", "nQ"];
p[state.q].l ← p[state.nq].l ← X;
stateAny ← state;
};
RSSimple: Rosemary.EvalProc = {
state: RSRef ← NARROW[stateAny];
SELECT
TRUE
FROM
p[state.r].l=H => {
state.bit ← p[state.q].l ← L;
p[state.nq].l ← Ports.NotL[p[state.s].l];
};
p[state.r].l=L
AND p[state.s].l=H => {
state.bit ← p[state.q].l ← H;
p[state.nq].l ← L;
};
p[state.r].l=L
AND p[state.s].l=L => {
p[state.q].l ← state.bit;
p[state.nq].l ← Ports.NotL[state.bit];
};
ENDCASE => state.bit ← p[state.q].l ← p[state.nq].l ← X;
};
Edge-Triggered Flip-Flops (2 and 4 inputs)
FF2: PUBLIC PROC RETURNS [ct: CellType] = {ct ← LogicUtils.Extract["ff2.sch", TRUE]};
FF4: PUBLIC PROC RETURNS [ct: CellType] = {ct ← LogicUtils.Extract["ff4.sch", TRUE]};
Storage (not a SC)
StorageName: ROPE = Rosemary.Register[roseClassName: "Storage", init: StorageInit, evalSimple: StorageSimple];
Storage:
PUBLIC
PROC
RETURNS [ct: CellType] = {
bit, nBit: NAT;
ct ← CoreClasses.CreateUnspecified[name: StorageName,
public: Wires["Vdd", "Gnd", "bit", "nbit"]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: StorageName];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "bit", "nbit"];
[bit, nBit] ← Ports.PortIndexes[ct.public, "bit", "nbit"];
[] ← Rosemary.SetWire[wire: ct.public[bit], memory: TRUE];
[] ← Rosemary.SetWire[wire: ct.public[nBit], memory: TRUE];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
};
StorageRef: TYPE = REF StorageRec;
StorageRec: TYPE = RECORD [bit, nBit: NAT ← LAST[NAT]];
StorageInit: Rosemary.InitProc = {
state: StorageRef ← NEW[StorageRec];
{
OPEN state;
[bit, nBit] ← Ports.PortIndexes[cellType.public, "bit", "nbit"];
p[bit].l ← X;
p[bit].d ← driveWeak;
p[nBit].l ← X;
p[nBit].d ← driveWeak};
stateAny ← state};
StorageSimple: Rosemary.EvalProc = {NULL}; -- cf. Pradeep
Latch (1 input)
DLName: ROPE = Rosemary.Register[roseClassName: "DL", init: DLInit, evalSimple: DLSimple];
DLatch:
PUBLIC
PROC
RETURNS [ct: CellType] = {
ct ← LogicUtils.MakeSC[nameInLib: "dLatch", width: 9,
name: DLName, public: Wires["Vdd", "Gnd", "D", "Q", "S"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "D", "S"];
Ports.InitPorts[ct, l, drive, "Q"];
};
DLRef: TYPE = REF DLRec;
DLRec:
TYPE =
RECORD [
dlD, dlQ, dlS: NAT ← LAST[NAT],
mem: Ports.Level];
DLInit: Rosemary.InitProc = {
state: DLRef ← IF oldStateAny=NIL THEN NEW[DLRec] ELSE NARROW[oldStateAny];
state.mem ← X;
[state.dlD, state.dlQ, state.dlS] ← Ports.PortIndexes[cellType.public, "D", "Q", "S"];
p[state.dlQ].l ← X;
stateAny ← state;
};
DLSimple: Rosemary.EvalProc = {
state: DLRef ← NARROW[stateAny];
IF p[state.dlS].l=H
THEN state.mem ← p[state.dlD].l
ELSE
IF p[state.dlS].l=X
THEN
IF p[state.dlD].l#state.mem THEN state.mem ← X;
p[state.dlQ].l ← state.mem;
};
END.