LogicRegsImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Louis Monier September 30, 1987 7:07:54 pm PDT
Jean-Marc Frailong October 21, 1987 10:10:30 pm PDT
Christian LeCocq October 14, 1986 2:10:45 pm PDT
Barth, October 10, 1986 5:30:59 pm PDT
DIRECTORY CoreClasses, CoreCreate, IO, Logic, LogicUtils, Ports, Rosemary;
LogicRegsImpl: CEDAR PROGRAM
IMPORTS CoreCreate, IO, LogicUtils, Ports
EXPORTS Logic
= BEGIN OPEN LogicUtils, CoreCreate;
Registers
Shared types
RegRef: TYPE = REF RegRec; -- state information for registers
RegRec: TYPE = RECORD [
ck, in, out, nOut, enable, reset: NATLAST[NAT],
master, slave: Ports.LevelSequence];
Register with Enable
RegisterRoseClass: ROPE = RoseClass["Register", RegInit, RegSimple, TRUE];
Register: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["Register b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of register"];
ct ← Extract["register.sch", LIST[["b", b]]];
SimulateMacro[ct, RegisterRoseClass];
Ports.InitPorts[ct, l, none, "CK", "en"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
CacheStore[fullName, ct];
};
RegInit: Rosemary.InitProc = {
state: RegRef ← IF oldStateAny=NIL THEN NEW[RegRec] ELSE NARROW[oldStateAny];
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]];
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 ~clockEval THEN SELECT p[state.ck].l FROM
L => { -- load each master bit
in: Ports.LevelSequence = p[state.in].ls;
en: Ports.Level = p[state.enable].l;
nEn: Ports.Level = Ports.NotL[en];
FOR i: NAT IN [0..in.size) DO
state.master[i] ← Ports.OrL[Ports.AndL[in[i], en], Ports.AndL[state.slave[i], nEn]];
ENDLOOP;
};
H => Ports.CopyLS[from: state.master, to: state.slave]; -- load slave bits
ENDCASE => {Ports.SetLS[state.master, X]; Ports.SetLS[state.slave, X]}; -- conservative
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
};
Register with Enable and Reset
RegisterRRoseClass: ROPE = RoseClass["RegisterR", RegRInit, RegRSimple, TRUE];
RegisterR: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["RegisterR b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of register with reset"];
ct ← Extract["registerWithReset.sch", LIST[["b", b]]];
SimulateMacro[ct, RegisterRRoseClass];
Ports.InitPorts[ct, l, none, "CK", "en", "r"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
CacheStore[fullName, ct];
};
RegRInit: Rosemary.InitProc = {
state: RegRef ← IF oldStateAny=NIL THEN NEW[RegRec] ELSE NARROW[oldStateAny];
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]];
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 ~clockEval THEN SELECT p[state.ck].l FROM
L => { -- load each master bit
in: Ports.LevelSequence = p[state.in].ls;
en: Ports.Level = p[state.enable].l;
nEn: Ports.Level = Ports.NotL[en];
nReset: Ports.Level = Ports.NotL[p[state.reset].l];
FOR i: NAT IN [0..in.size) DO
state.master[i] ← Ports.AndL[Ports.OrL[Ports.AndL[in[i], en], Ports.AndL[state.slave[i], nEn]], nReset];
ENDLOOP;
};
H => Ports.CopyLS[from: state.master, to: state.slave]; -- load slave bits
ENDCASE => {Ports.SetLS[state.master, X]; Ports.SetLS[state.slave, X]}; -- conservative
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
};
Basic Register ( no Enable, no Reset)
RegisterSimpleRoseClass: ROPE = RoseClass["RegisterSimple", RegSInit, RegSSimple, TRUE];
RegisterSimple: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
registerSimpleName: ROPE = "RegisterSimple";
fullName: ROPE = IO.PutFR["RegisterSimple b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of register"];
ct ← SequenceCell[name: registerSimpleName, baseCell: Extract["reg1BSimple.sch"], count: b, sequencePorts: Wires["Input", "Output", "nOutput"]];
SimulateMacro[ct, RegisterSimpleRoseClass];
Ports.InitPorts[ct, l, none, "CK"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output", "nOutput"];
CacheStore[fullName, ct];
};
RegSInit: Rosemary.InitProc = {
state: RegRef ← IF oldStateAny=NIL THEN NEW[RegRec] ELSE NARROW[oldStateAny];
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]];
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 ~clockEval THEN SELECT p[state.ck].l FROM
L => Ports.CopyLS[from: p[state.in].ls, to: state.master]; -- load master bits
H => Ports.CopyLS[from: state.master, to: state.slave]; -- load slave bits
ENDCASE => {Ports.SetLS[state.master, X]; Ports.SetLS[state.slave, X]}; -- conservative
Ports.CopyLS[from: state.slave, to: p[state.out].ls];
Ports.NotLS[p[state.out].ls, p[state.nOut].ls];
};
Latch
LatchRoseClass: ROPE = RoseClass["Latch", LatchInit, LatchSimple];
Latch: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] ~ {
fullName: ROPE = IO.PutFR["Latch b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of latch"];
ct ← SequenceCell[name: "Latch", baseCell: Extract["latch1B.sch"], count: b, sequencePorts: Wires["Input", "Output"]];
SimulateMacro[ct, LatchRoseClass];
Ports.InitPorts[ct, l, none, "CK"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, drive, "Output"];
CacheStore[fullName, ct];
};
LatchInit: Rosemary.InitProc = {
state: RegRef ← IF oldStateAny=NIL THEN NEW[RegRec] ELSE NARROW[oldStateAny];
[state.ck, state.in, state.out] ← Ports.PortIndexes[cellType.public, "CK", "Input", "Output"];
state.master ← NEW[Ports.LevelSequenceRec[p[state.in].ls.size]];
Ports.SetLS[state.master, X];
Ports.SetLS[p[state.out].ls, X];
stateAny ← state;
};
LatchSimple: Rosemary.EvalProc = {
state: RegRef ← NARROW[stateAny];
SELECT p[state.ck].l FROM
H => Ports.CopyLS[from: p[state.in].ls, to: state.master];
X => Ports.SetLS[state.master, X];
ENDCASE => NULL;
Ports.CopyLS[from: state.master, to: p[state.out].ls];
};
Tristate Buffers
Shared types
TstState: TYPE = REF TstStateRec;
TstStateRec: TYPE = RECORD [in, out, enable: NATLAST[NAT]];
TstBufferAllInit: Rosemary.InitProc = {
state: TstState ← IF oldStateAny=NIL THEN NEW[TstStateRec] ELSE NARROW[oldStateAny];
[state.in, state.out, state.enable] ← Ports.PortIndexes[cellType.public, "Input", "Output", "enable"];
stateAny ← state;
};
Inverting TS buffer
TstBufferInvRoseClass: ROPE = RoseClass["TstBufferInv", TstBufferAllInit, TstBufferInvSimple];
TristateBufferInv: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["TristateBufferInv b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of inverting tristate buffer"];
ct ← Extract["3BufferP.sch", LIST[["b", b]]];
SimulateMacro[ct, TstBufferInvRoseClass];
Ports.InitPorts[ct, l, none, "enable"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, none, "Output"];
CacheStore[fullName, ct];
};
TstBufferInvSimple: Rosemary.EvalProc = {
state: TstState ← NARROW[stateAny];
SELECT p[state.enable].l FROM
H => {p[state.out].d ← drive; Ports.NotLS[p[state.in].ls, p[state.out].ls]};
L => p[state.out].d ← none;
ENDCASE => {p[state.out].d ← drive; Ports.SetLS[p[state.out].ls, X]};
};
Non-inverting TS buffer
TstBufferRoseClass: ROPE = RoseClass["TstBuffer", TstBufferAllInit, TstBufferSimple];
TristateBuffer: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = {
fullName: ROPE = IO.PutFR["TristateBuffer b=%g", IO.int[b]];
ct ← CacheFetch[fullName];
IF ct#NIL THEN RETURN[ct];
IF b=0 THEN Error["Please specify size of tristate buffer"];
ct ← Extract["3Buffer.sch", LIST[["b", b]]];
SimulateMacro[ct, TstBufferRoseClass];
Ports.InitPorts[ct, l, none, "enable"];
Ports.InitPorts[ct, ls, none, "Input"]; Ports.InitPorts[ct, ls, none, "Output"];
CacheStore[fullName, ct];
};
TstBufferSimple: Rosemary.EvalProc = {
state: TstState ← NARROW[stateAny];
SELECT p[state.enable].l FROM
H => {p[state.out].d ← drive; Ports.CopyLS[from: p[state.in].ls, to: p[state.out].ls]};
L => p[state.out].d ← none;
ENDCASE => {p[state.out].d ← drive; Ports.SetLS[p[state.out].ls, X]};
};
END.