Register
-- this type is shared among all registers
RegRef: TYPE = REF RegRec;
RegRec:
TYPE =
RECORD [
ck, in, out, nOut, enable, reset: NAT ← LAST[NAT],
prevCK: Ports.Level,
master, slave: Ports.LevelSequence];
RegisterName: ROPE = Rosemary.Register[roseClassName: "Register", init: RegInit, evalSimple: RegSimple];
Register:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
cell: CellType ← LogicUtils.Extract["reg1B.sch", TRUE];
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of register"];
ENDCASE => ct ← SequenceCell[name: RegisterName,
baseCell: cell, count: b,
sequencePorts: Wires["Input", "Output", "nOutput"]];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
};
RegInit: Rosemary.InitProc = {
state: RegRef ← NEW[RegRec];
b: NAT;
[state.ck, state.in, state.out, state.nOut, state.enable] ← Ports.PortIndexes[cellType.public, "CK", "Input", "Output", "nOutput", "en"];
b ← p[state.in].ls.size;
state.master ← NEW[Ports.LevelSequenceRec[b]];
state.slave ← NEW[Ports.LevelSequenceRec[b]];
state.prevCK ← X;
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
Ports.SetLS[p[state.out].ls, X];
Ports.SetLS[p[state.nOut].ls, X];
stateAny ← state;
};
RegSimple: Rosemary.EvalProc = {
state: RegRef ← NARROW[stateAny];
IF p[state.ck].l=L THEN Ports.CopyLS[from: p[state.in].ls, to: state.master]
ELSE IF (state.prevCK=L AND p[state.ck].l=H AND p[state.enable].l=H) THEN Ports.CopyLS[from: state.master, to: state.slave];
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
state.prevCK ← p[state.ck].l;
};
RegisterRName: ROPE = Rosemary.Register[roseClassName: "RegisterR", init: RegRInit, evalSimple: RegRSimple];
RegisterR:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
cell: CellType ← LogicUtils.Extract["reg1BitReset.sch", TRUE];
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of register"];
ENDCASE => ct ← SequenceCell[name: RegisterRName,
baseCell: cell, count: b,
sequencePorts: Wires["Input", "Output", "nOutput"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en", "r"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
};
RegRInit: Rosemary.InitProc = {
state: RegRef ← NEW[RegRec];
b: NAT;
[state.ck, state.in, state.out, state.nOut, state.enable, state.reset] ← Ports.PortIndexes[cellType.public, "CK", "Input", "Output", "nOutput", "en", "r"];
b ← p[state.in].ls.size;
state.master ← NEW[Ports.LevelSequenceRec[b]];
state.slave ← NEW[Ports.LevelSequenceRec[b]];
state.prevCK ← X;
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
Ports.SetLS[p[state.out].ls, X];
Ports.SetLS[p[state.nOut].ls, X];
stateAny ← state;
};
RegRSimple: Rosemary.EvalProc = {
state: RegRef ← NARROW[stateAny];
IF p[state.ck].l=L THEN Ports.CopyLS[from: p[state.in].ls, to: state.master]
ELSE
IF (state.prevCK=L
AND p[state.ck].l=H)
THEN {
IF p[state.reset].l=H THEN {Ports.SetLS[state.master, L]; Ports.SetLS[state.slave, L]}
ELSE IF p[state.enable].l=H THEN Ports.CopyLS[from: state.master, to: state.slave]};
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
state.prevCK ← p[state.ck].l;
};
RegisterSimpleName: ROPE = Rosemary.Register[roseClassName: "RegisterSimple", init: RegSInit, evalSimple: RegSSimple];
RegisterSimple:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of register"];
ENDCASE => ct ← SequenceCell[name: RegisterSimpleName,
baseCell: LogicUtils.Extract["reg1BSimple.sch", TRUE], count: b,
sequencePorts: Wires["Input", "Output", "nOutput"]];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "CK"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
};
RegSInit: Rosemary.InitProc = {
state: RegRef ← NEW[RegRec];
b: NAT;
[state.ck, state.in, state.out, state.nOut] ← Ports.PortIndexes[cellType.public, "CK", "Input", "Output", "nOutput"];
b ← p[state.in].ls.size;
state.master ← NEW[Ports.LevelSequenceRec[b]];
state.slave ← NEW[Ports.LevelSequenceRec[b]];
state.prevCK ← X;
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
Ports.SetLS[p[state.out].ls, X];
Ports.SetLS[p[state.nOut].ls, X];
stateAny ← state;
};
RegSSimple: Rosemary.EvalProc = {
state: RegRef ← NARROW[stateAny];
IF p[state.ck].l=L THEN Ports.CopyLS[from: p[state.in].ls, to: state.master]
ELSE IF (state.prevCK=L AND p[state.ck].l=H) THEN Ports.CopyLS[from: state.master, to: state.slave];
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
state.prevCK ← p[state.ck].l;
};
Tristate Buffer
-- "Vdd", "Gnd", Seq["I", b], Seq["X", b]
InvSeq:
PROC [b:
NAT]
RETURNS [ct: CellType] ~ {
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of inverters' sequence"];
ENDCASE => ct ← SequenceCell[name: "InverterSequence",
baseCell: Inv[], count: b,
sequencePorts: Wires["I", "X"]];
};
-- "Vdd", "Gnd", Seq["I", b], Seq["X", b], "EN", "NEN"
TristateSeq:
PROC [b:
NAT]
RETURNS [ct: CellType] ~ {
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of tristate drivers' sequence"];
ENDCASE => ct ← SequenceCell[name: "TristateSequence",
baseCell: TstDriver[], count: b,
sequencePorts: Wires["I", "X"]];
};
TstState: TYPE = REF TstStateRec;
TstStateRec:
TYPE =
RECORD [
in, out, enable: NAT ← LAST[NAT]];
TstBufferName: ROPE = Rosemary.Register[roseClassName: "TstBuffer", init: TstBufferInit, evalSimple: TstBufferSimple];
TristateBuffer:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
insts: CellInstances ←
LIST[
Instance[InvSeq[b], ["I", "Input"], ["X", "nInput"]],
Instance[TristateBufferInv[b], ["Input", "nInput"], ["Output", "Output"]]
];
ct ← Cell[
name: TstBufferName,
public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"],
onlyInternal: Wires[Seq["nInput", b]],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferName];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "enable"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, none, "Output"];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
};
TstBufferInit: Rosemary.InitProc = {
state: TstState ← NEW[TstStateRec];
{
OPEN state;
[in, out, enable] ← Ports.PortIndexes[cellType.public, "Input", "Output", "enable"]};
stateAny ← state};
TstBufferSimple: Rosemary.EvalProc = {
state: TstState ← NARROW[stateAny];
{OPEN state;
IF p[enable].l=H
THEN {
p[out].d ← drive;
Ports.CopyLS[from: p[in].ls, to: p[out].ls];
}
ELSE p[out].d ← none;
}};
TstBufferInvName: ROPE = Rosemary.Register[roseClassName: "TstBufferInv", init: TstBufferInvInit, evalSimple: TstBufferInvSimple];
TristateBufferInv:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] = {
insts: CellInstances ←
LIST[
Instance[TristateSeq[b], ["I", "Input"], ["X", "Output"], ["EN", "enable"], ["NEN", "nEnable"]],
Instance[Inv[], ["I", "enable"], ["X", "nEnable"]]
];
ct ← Cell[
name: TstBufferInvName,
public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"],
onlyInternal: Wires["nEnable"],
instances: insts];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferInvName];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "enable"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, none, "Output"];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
};
TstBufferInvInit: Rosemary.InitProc = {
state: TstState ← NEW[TstStateRec];
{
OPEN state;
[in, out, enable] ← Ports.PortIndexes[cellType.public, "Input", "Output", "enable"]};
stateAny ← state};
TstBufferInvSimple: Rosemary.EvalProc = {
state: TstState ← NARROW[stateAny];
{OPEN state;
IF p[enable].l=H
THEN {
p[out].d ← drive;
Ports.NotLS[p[in].ls, p[out].ls];
}
ELSE p[out].d ← none;
}};
Latch:
PUBLIC
PROC [b:
NAT]
RETURNS [ct: CellType] ~ {
array: CellType;
SELECT b
FROM
<=0 => LogicUtils.Error["Please specify size of latch"];
ENDCASE => array ← SequenceCell[name: LatchName,
baseCell: DLatch[], count: b,
sequencePorts: Wires["D", "Q"]];
ct ← Cell[name: LatchName,
public: Wires["Vdd", "Gnd", "CK", Seq["Input", b], Seq["Output", b]],
instances: LIST[Instance[array, ["D", "Input"], ["Q", "Output"], ["S", "CK"]]]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: LatchName];
Ports.InitPorts[ct, l, none, "Vdd", "Gnd", "CK"];
Ports.InitPorts[ct, ls, none, "Input"];
Ports.InitPorts[ct, ls, drive, "Output"];
[] ← CoreFlat.CellTypeCutLabels[ct, macroCutSet];
};