SmallCacheDataPathImpl.mesa
Copyright © 1985 by Xerox Corporation.  All rights reserved.
Don Curry, March 16, 1988 5:11:45 pm PST
 
SmallCacheDataPathImpl: 
CEDAR 
PROGRAM
IMPORTS CoreClasses, CoreOps, DataPath, IO, Ports, Rosemary
EXPORTS SmallCacheDataPath =
 
Exports
Structure: 
PUBLIC PROC[wds, bits: 
NAT] 
RETURNS [public: Core.Wires] = {-- strc and flat
Transforms a flat bus of w*b bits into a structured bus of w words of b bits
flat[i] = strc[i/w][i MOD w]
 
strc: Core.Wire ← CoreOps.CreateWires[wds,  "strc"];
flat: Core.Wire ← CoreOps.CreateWires[wds*bits, "flat"];
IF bits=0 OR wds=0 THEN ERROR; -- Please provide parameters for Structure
FOR wd: 
NAT 
IN [0..wds) 
DO
strc[wd] ← CoreOps.CreateWires[bits];
FOR bit: 
NAT 
IN [0..bits) 
DO
flat[wd*bits + bit] ← strc[wd][bit] ← CoreOps.CreateWires[0] ENDLOOP ENDLOOP;
 
 
public ← LIST [strc, flat]};
 
BusShort: 
PUBLIC 
PROC[size: 
INT] 
RETURNS[wire: Core.Wire] = {
sub: Core.Wire ← CoreOps.CreateWires[0, "sw"];
wire ← CoreOps.CreateWires[size, "w"];
FOR i: INT IN [0..size) DO wire[i] ← sub ENDLOOP};
 
Trans: 
PUBLIC 
PROC[type: CoreClasses.TransistorType, length, width: 
INT]
RETURNS [cellType: Core.CellType] = {
name: 
IO.
ROPE ← 
IO.PutFR["%g%gx%g",
IO.rope[CoreClasses.transistorTypeNames[type]],
IO.int[length],
IO.int[width]];
cellType ← CoreClasses.CreateTransistor[type, length, width, name]};
 
 
DPFF
DP32FFName: IO.ROPE = Rosemary.Register
["DP32FFSeq", DPFFSeqInit, DPFFSeqSimple, NIL, TRUE];
 
DP64FFName: IO.ROPE = Rosemary.Register
["DP64FFSeq", DPFFSeqInit, DPFFSeqSimple, NIL, TRUE];
 
DPFFSeqState:  TYPE = REF DPFFSeqStateRec;
DPFFSeqStateRec: 
TYPE = 
RECORD [
in, out, ck: Ports.Port ← NIL,
master, slave: Ports.LevelSequence];
DPFFSeqInit: Rosemary.InitProc = {
state: DPFFSeqState;
IF oldStateAny=
NIL
THEN {
size: NAT ← p[Ports.PortIndex[cellType.public, "D"]].ls.size;
state   ← NEW[DPFFSeqStateRec];
state.master ← NEW[Ports.LevelSequenceRec[size]];
state.slave ← NEW[Ports.LevelSequenceRec[size]]}
 
ELSE state  ← NARROW[oldStateAny];
 
state.ck ← p[Ports.PortIndex[cellType.public, "CK"]];
state.in ← p[Ports.PortIndex[cellType.public, "D"]];
state.out ← p[Ports.PortIndex[cellType.public, "Q"]];
Ports.PutDrive[state.out, drive];
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
Ports.SetLS[state.out.ls, X];
stateAny ← state};
 
DPFFSeqSimple: Rosemary.EvalProc = {
state: DPFFSeqState ← NARROW[stateAny];
IF ~clockEval 
THEN {
SELECT state.ck.l 
FROM
L => Ports.CopyLS[from: state.in.ls, to: state.master];
H => Ports.CopyLS[from: state.master, to: state.slave];
ENDCASE => {
IF state.slave#state.master THEN Ports.SetLS[state.slave, X];
IF state.master#state.in.ls THEN Ports.SetLS[state.master, X]}};
 
 
 
Ports.CopyLS[from: state.slave, to: state.out.ls]};
 
 
DPEnFF
DP32EnFFName: IO.ROPE = Rosemary.Register
["DP32EnFFSeq", DPEnFFSeqInit, DPEnFFSeqSimple, NIL, TRUE];
 
DP64EnFFName: IO.ROPE = Rosemary.Register
["DP64EnFFSeq", DPEnFFSeqInit, DPEnFFSeqSimple, NIL, TRUE];
 
DPEnFFSeqState:  TYPE = REF DPEnFFSeqStateRec;
DPEnFFSeqStateRec: 
TYPE = 
RECORD [
in, out, ck, en, dis: Ports.Port ← NIL,
master, slave: Ports.LevelSequence];
DPEnFFSeqInit: Rosemary.InitProc = {
state: DPEnFFSeqState;
IF oldStateAny=
NIL
THEN {
size: NAT ← p[Ports.PortIndex[cellType.public, "D"]].ls.size;
state   ← NEW[DPEnFFSeqStateRec];
state.master ← NEW[Ports.LevelSequenceRec[size]];
state.slave ← NEW[Ports.LevelSequenceRec[size]]}
 
ELSE state  ← NARROW[oldStateAny];
 
state.ck ← p[Ports.PortIndex[cellType.public, "CK"]];
state.in ← p[Ports.PortIndex[cellType.public, "D"]];
state.out ← p[Ports.PortIndex[cellType.public, "Q"]];
state.en ← p[Ports.PortIndex[cellType.public, "En"]];
state.dis ← p[Ports.PortIndex[cellType.public, "nEn"]];
Ports.PutDrive[state.out, drive];
Ports.SetLS[state.master, X];
Ports.SetLS[state.slave, X];
Ports.SetLS[state.out.ls, X];
stateAny ← state};
 
DPEnFFSeqSimple: Rosemary.EvalProc = {
state: DPEnFFSeqState ← NARROW[stateAny];
IF ~clockEval 
THEN {
SELECT state.ck.l 
FROM
L => 
IF state.en.l=state.dis.l
THEN Ports.SetLS[state.master, X]
ELSE 
IF state.en.l=H
THEN Ports.CopyLS[from: state.slave, to: state.master]
ELSE Ports.CopyLS[from: state.in.ls, to: state.master];
 
H => Ports.CopyLS[from: state.master, to: state.slave];
ENDCASE => {
IF state.slave#state.master THEN Ports.SetLS[state.slave, X];
IF state.master#state.in.ls THEN Ports.SetLS[state.master, X]}};
 
 
 
Ports.CopyLS[from: state.slave, to: state.out.ls]};
 
 
DPLatch
DP32LatchName: IO.ROPE = Rosemary.Register
["DP32LatchSeq", DPLatchSeqInit, DPLatchSeqSimple, NIL, FALSE];
 
DP64LatchName: IO.ROPE = Rosemary.Register
["DP64LatchSeq", DPLatchSeqInit, DPLatchSeqSimple, NIL, FALSE];
 
DPLatchSeqState:  TYPE = REF DPLatchSeqStateRec;
DPLatchSeqStateRec: 
TYPE = 
RECORD [
in, out, en: Ports.Port ← NIL,
slave: Ports.LevelSequence ];
DPLatchSeqInit: Rosemary.InitProc = {
state: DPLatchSeqState;
IF oldStateAny=
NIL
THEN {
size: NAT  ← p[Ports.PortIndex[cellType.public, "D"]].ls.size;
state   ← NEW[DPLatchSeqStateRec];
state.slave ← NEW[Ports.LevelSequenceRec[size]]}
 
ELSE state ← NARROW[oldStateAny];
 
state.in ← p[Ports.PortIndex[cellType.public, "D"]];
state.out ← p[Ports.PortIndex[cellType.public, "Q"]];
state.en ← p[Ports.PortIndex[cellType.public, "En"]];
Ports.PutDrive[state.out, drive];
Ports.SetLS[state.out.ls, X];
Ports.SetLS[state.slave, X];
stateAny ← state};
 
DPLatchSeqSimple: Rosemary.EvalProc = {
state: DPLatchSeqState ← NARROW[stateAny];
IF state.en.l=H
THEN Ports.CopyLS[from: state.in.ls, to: state.slave];
 
Ports.CopyLS[from: state.slave, to: state.out.ls]; 
Ports.PutDrive[state.out, drive]};
 
 
DPComp
DP32CompName: IO.ROPE = Rosemary.Register
["DP32CompSeq", DPCompSeqInit, DPCompSeqSimple];
 
DP64CompName: IO.ROPE = Rosemary.Register
["DP64CompSeq", DPCompSeqInit, DPCompSeqSimple];
 
DPCompSeqState:  TYPE = REF DPCompSeqStateRec;
DPCompSeqStateRec: 
TYPE = 
RECORD [a, b, mat: Ports.Port];
DPCompSeqInit: Rosemary.InitProc = {
state: DPCompSeqState ← 
IF oldStateAny=
NIL
THEN NEW[DPCompSeqStateRec]
ELSE NARROW[oldStateAny];
state.a  ← p[Ports.PortIndex[cellType.public, "A"]];
state.b  ← p[Ports.PortIndex[cellType.public, "B"]];
state.mat ← p[Ports.PortIndex[cellType.public, "Match"]];
stateAny ← state};
 
DPCompSeqSimple: Rosemary.EvalProc = {
state: DPCompSeqState ← NARROW[stateAny];
level: Ports.Level ← H;
FOR index: 
NAT 
IN [0..state.a.ls.size) 
DO
SELECT 
TRUE 
FROM
state.a.ls[index]=X,
state.b.ls[index]=X     => {level ← X; EXIT};
state.a.ls[index] # state.b.ls[index] => {level ← L};
ENDCASE ENDLOOP;
 
 
IF level=H
THEN Ports.PutDrive[state.mat,   none]
ELSE Ports.PutLevel[state.mat, level, drive]};
 
 
 
DPMux2
DP32MuxName: IO.ROPE = Rosemary.Register
["DP32Mux2Seq", DPMux2SingSelSeqInit, DPMux2SingSelSeqSimple];
 
DP64MuxName: IO.ROPE = Rosemary.Register
["DP64Mux2Seq", DPMux2DualSelSeqInit, DPMux2DualSelSeqSimple];
 
DPMux2SingSelSeqState:  TYPE = REF DPMux2SingSelSeqStateRec;
DPMux2DualSelSeqState:  TYPE = REF DPMux2DualSelSeqStateRec;
DPMux2SingSelSeqStateRec: TYPE = RECORD [in0, in1, sel0,  out: Ports.Port];
DPMux2DualSelSeqStateRec: 
TYPE = 
RECORD [in0, in1, sel0, sel1, out: Ports.Port];
DPMux2SingSelSeqInit: Rosemary.InitProc = {
state: DPMux2SingSelSeqState ← 
IF oldStateAny=
NIL
THEN NEW[DPMux2SingSelSeqStateRec]
ELSE NARROW[oldStateAny];
state.in0  ← p[Ports.PortIndex[cellType.public, "In0"]];
state.in1  ← p[Ports.PortIndex[cellType.public, "In1"]];
state.sel0  ← p[Ports.PortIndex[cellType.public, "Sel0"]];
state.out  ← p[Ports.PortIndex[cellType.public, "Out"]];
Ports.PutDrive[state.out, drive];
stateAny  ← state};
 
DPMux2DualSelSeqInit: Rosemary.InitProc = {
state: DPMux2DualSelSeqState ← 
IF oldStateAny=
NIL
THEN NEW[DPMux2DualSelSeqStateRec]
ELSE NARROW[oldStateAny];
state.in0  ← p[Ports.PortIndex[cellType.public, "In0"]];
state.in1  ← p[Ports.PortIndex[cellType.public, "In1"]];
state.sel0  ← p[Ports.PortIndex[cellType.public, "Sel0"]];
state.sel1  ← p[Ports.PortIndex[cellType.public, "Sel1"]];
state.out  ← p[Ports.PortIndex[cellType.public, "Out"]];
Ports.PutDrive[state.out, drive];
stateAny  ← state};
 
DPMux2SingSelSeqSimple: Rosemary.EvalProc = {
state: DPMux2SingSelSeqState ← NARROW[stateAny];
FOR index: 
NAT 
IN [0..state.in0.ls.size) 
DO
state.out.ls[index] ← 
IF state.sel0.l=H
THEN state.in0.ls[index]
ELSE state.in1.ls[index] ENDLOOP};
 
 
DPMux2DualSelSeqSimple: Rosemary.EvalProc = {
state: DPMux2DualSelSeqState ← NARROW[stateAny];
FOR index: 
NAT 
IN [0..state.in0.ls.size) 
DO
state.out.ls[index] ← 
IF state.sel0.l=state.sel1.l 
THEN X 
ELSE 
IF state.sel0.l=H
THEN state.in0.ls[index]
ELSE state.in1.ls[index] ENDLOOP};
 
 
 
DPTst
DP32TstName: IO.ROPE = Rosemary.Register
["DP32TstSeq", DPTstSingEnSeqInit, DPTstSingEnSeqSimple];
 
DP64TstName: IO.ROPE = Rosemary.Register
["DP64TstSeq", DPTstDualEnSeqInit, DPTstDualEnSeqSimple];
 
DP64TstFlipYName: IO.ROPE = Rosemary.Register
["DP64TstFlipYSeq", DPTstDualEnSeqInit, DPTstDualEnSeqSimple];
 
DPTstSingEnSeqState:  TYPE = REF DPTstSingEnSeqStateRec;
DPTstDualEnSeqState:  TYPE = REF DPTstDualEnSeqStateRec;
DPTstSingEnSeqStateRec: TYPE = RECORD [in, out, en:  Ports.Port];
DPTstDualEnSeqStateRec: TYPE = RECORD [in, out, en, dis: Ports.Port];
DPTstSingEnSeqInit: Rosemary.InitProc = {
state: DPTstSingEnSeqState ← 
IF oldStateAny=
NIL
THEN NEW[DPTstSingEnSeqStateRec]
ELSE NARROW[oldStateAny];
state.in ← p[Ports.PortIndex[cellType.public, "In"]];
state.out ← p[Ports.PortIndex[cellType.public, "Out"]];
state.en ← p[Ports.PortIndex[cellType.public, "En"]];
Ports.PutDrive[state.out, drive];
stateAny ← state};
 
DPTstDualEnSeqInit: Rosemary.InitProc = {
state: DPTstDualEnSeqState ← 
IF oldStateAny=
NIL
THEN NEW[DPTstDualEnSeqStateRec]
ELSE NARROW[oldStateAny];
state.in ← p[Ports.PortIndex[cellType.public, "In"]];
state.out ← p[Ports.PortIndex[cellType.public, "Out"]];
state.en ← p[Ports.PortIndex[cellType.public, "En"]];
state.dis ← p[Ports.PortIndex[cellType.public, "nEn"]];
Ports.PutDrive[state.out, drive];
stateAny ← state};
 
DPTstSingEnSeqSimple: Rosemary.EvalProc = {
state: DPTstSingEnSeqState ← NARROW[stateAny];
IF state.en.l=H
 THEN {
Ports.CopyLS[state.in.ls, state.out.ls];
Ports.PutDrive[state.out, drive]}};
 
 
DPTstDualEnSeqSimple: Rosemary.EvalProc = {
state: DPTstDualEnSeqState ← NARROW[stateAny];
IF state.en.l=state.dis.l
THEN {Ports.SetLS[state.out.ls, X]; Ports.PutDrive[state.out, drive]}
ELSE {
Ports.CopyLS[state.in.ls, state.out.ls];
Ports.PutDrive[state.out, (IF state.en.l=H THEN drive ELSE none)]}};
 
 
 
 
Spec Registration
DataPath.RegisterDataPathSpec["SmallCache64", 
NEW[DataPath.DPSpecRec ← [
layDWidth: 65*CMosB.lambda]]];
DataPath.RegisterDataPathSpec["SmallCache32", NEW[DataPath.DPSpecRec ← [
layDWidth: 162*CMosB.lambda]]];