TamarinRegFileImpl .mesa
Copyright © 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Alan Bell October 1, 1987 10:57:45 pm PDT
Krivacic June 26, 1987 10:02:31 am PDT
DIRECTORY
CD,
CDSequencer,
Core USING [CellType],
CoreCreate,
CoreClasses,
Ports,
TerminalIO,
IO,
List,
Sisyph USING [Context, ES],
Tam,
TamarinUtil,
TilingClass USING [CreateTiling, SchematicsNeighborX, SchematicsNeighborY,
TileArray, TileArrayRec, TileRec, TileRowRec];
TamarinRegFileImpl: CEDAR PROGRAM
IMPORTS CoreCreate, Sisyph, TamarinUtil, TilingClass, CoreClasses, Ports, TerminalIO, IO
EXPORTS Tam = BEGIN
LORA: TYPE = List.LORA;
Wire: TYPE = CoreCreate.Wire;
WR: TYPE = CoreCreate.WR;
lastTile: TilingClass.TileArray ← NIL;
extractRegFile: BOOLTRUE;
CreateRealRegArray: PUBLIC PROC [tamarinCx: Sisyph.Context, nbrBanks, regLength, segments: NAT] RETURNS [cellType: Core.CellType] = {
Create the Internal RegFile Array. Build the Reg Array such that there are 34 MemQuad cells across (which makes 4 words per row). Divide these cells into segments and place taps between them based on segments. regLength is the number of words per register bank, and banks is the # of register banks to create.
-- Constants
RowType: TYPE = {Top, MemUp, MemDown, SenseDrive, DMap};
busSize: NAT = 34;
bankDecoderSize: NAT = 4;
addrDecoderSize: NAT = 5;
decoderSize: NAT = bankDecoderSize+addrDecoderSize;
totalColumns: NAT = 1+busSize+(busSize / segments)+2+(decoderSize-2);
-- Vars
totalRows: NAT ← (IF nbrBanks=5 AND regLength>31 THEN (nbrBanks-1) * (regLength / 4) + 3 + 4 ELSE nbrBanks * (regLength / 4) + 3);
tileArray: TilingClass.TileArray ← NEW[TilingClass.TileArrayRec[totalRows]];
rowIndex: NAT ← 0;
-- Wire Sequences
nextRegAddr: Wire ← CoreCreate.Seq["NextRegAddr", decoderSize];
rbus: Wire ← CoreCreate.Seq["R", busSize];
d1: Wire ← CoreCreate.Seq["D1", busSize];
d2: Wire ← CoreCreate.Seq["D2", busSize];
rd1addr: Wire ← CoreCreate.Seq["RD1addr", 4];
rd2addr: Wire ← CoreCreate.Seq["RD2addr", 4];
-- Cells
regMemCellLeftTop: Core.CellType ← Sisyph.ES["RegMemCellLeftTop.sch", tamarinCx];
regMemCellTapTop: Core.CellType ← Sisyph.ES["RegMemCellTapTop.sch", tamarinCx];
regMemQuadTop: Core.CellType ← Sisyph.ES["RegMemQuadTop.sch", tamarinCx];
regMemDriverTop: Core.CellType ← Sisyph.ES["RegDriverTop.sch", tamarinCx];
regMemCellDecodeTop: Core.CellType ← Sisyph.ES["RegDecodeTop.sch", tamarinCx];
regMemCellPullupTop: Core.CellType ← Sisyph.ES["RegDecPullupTop.sch", tamarinCx];
regMemCellLeftUp: Core.CellType ← Sisyph.ES["RegMemCellLeftUp.sch", tamarinCx];
regMemCellTapUp: Core.CellType ← Sisyph.ES["RegMemCellTapUp.sch", tamarinCx];
regMemQuadUp: Core.CellType ← Sisyph.ES["RegMemQuadUp.sch", tamarinCx];
regMemDriverUp: Core.CellType ← Sisyph.ES["RegDriverUp.sch", tamarinCx];
regMemCellDecode0Up: Core.CellType ← Sisyph.ES["RegDecode0Up.sch", tamarinCx];
regMemCellDecode1Up: Core.CellType ← Sisyph.ES["RegDecode1Up.sch", tamarinCx];
regMemCellPullupUp: Core.CellType ← Sisyph.ES["RegDecPullupUp.sch", tamarinCx];
regMemCellLeftDown: Core.CellType ← Sisyph.ES["RegMemCellLeftDown.sch", tamarinCx];
regMemCellTapDown: Core.CellType ← Sisyph.ES["RegMemCellTapDown.sch", tamarinCx];
regMemQuadDown: Core.CellType ← Sisyph.ES["RegMemQuadDown.sch", tamarinCx];
regMemDriverDown: Core.CellType ← Sisyph.ES["RegDriverDown.sch", tamarinCx];
regMemCellDecode0Down: Core.CellType ← Sisyph.ES["RegDecode0Down.sch", tamarinCx];
regMemCellDecode1Down: Core.CellType ← Sisyph.ES["RegDecode1Down.sch", tamarinCx];
regMemCellPullupDown: Core.CellType ← Sisyph.ES["RegDecPullupDown.sch", tamarinCx];
regSenseDriveLeft: Core.CellType ← Sisyph.ES["RegSenseDriveLeft.sch", tamarinCx];
regSenseDriveTap: Core.CellType ← Sisyph.ES["RegSenseDriveTap.sch", tamarinCx];
regSenseDriveQuad: Core.CellType ← Sisyph.ES["RegSenseDriveQuad.sch", tamarinCx];
regSenseDriveDriver: Core.CellType ← Sisyph.ES["RegSenseDriveDriver.sch", tamarinCx];
regSenseDriveDecode: Core.CellType ← Sisyph.ES["RegSenseDriveDecode.sch", tamarinCx];
regSenseDriveDecodeLsb: Core.CellType ← Sisyph.ES["RegSenseDriveDecodeLsb.sch", tamarinCx];
regSenseDrivePullup: Core.CellType ← Sisyph.ES["RegSenseDrivePullup.sch", tamarinCx];
regDMapperLeft: Core.CellType ← Sisyph.ES["DMapperLeft.sch", tamarinCx];
regDMapperTap: Core.CellType ← Sisyph.ES["DMapperTap.sch", tamarinCx];
regDMapperQuad: Core.CellType ← Sisyph.ES["DMapperQuad.sch", tamarinCx];
regDMapperDriver: Core.CellType ← Sisyph.ES["DMapperDriver.sch", tamarinCx];
regDMapperDecode: Core.CellType ← Sisyph.ES["DMapperDecode.sch", tamarinCx];
regDMapperPullup: Core.CellType ← Sisyph.ES["DMapperPullup.sch", tamarinCx];
MakeRow: PROC [type: RowType, rowIndex, bankAddr, rowAddr: NAT] RETURNS [] = {
MakeLeftColumn: PROC [type: RowType, rowIndex, colIndex: NAT] = {
-- Make a Tap Column
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: (SELECT type FROM
DMap => regDMapperLeft,
SenseDrive => regSenseDriveLeft,
MemUp => regMemCellLeftUp,
MemDown => regMemCellLeftDown,
Top => regMemCellLeftTop,
ENDCASE => ERROR),
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
};
MakeTapColumn: PROC [type: RowType, rowIndex, colIndex: NAT] = {
-- Make a Tap Column
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: (SELECT type FROM
DMap => regDMapperTap,
SenseDrive => regSenseDriveTap,
MemUp => regMemCellTapUp,
MemDown => regMemCellTapDown,
Top => regMemCellTapTop,
ENDCASE => ERROR),
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
};
MakeMemColumn: PROC [type: RowType, rowIndex, colIndex, bit: NAT] = {
SELECT type FROM
-- DMapper Row
DMap => 
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regDMapperQuad,
renaming: LIST[
["Vdd", "Vdd"], ["Gnd", "Gnd"],
["R", rbus[bit]],
["D1", d1[bit]],
["D2", d2[bit]]]
]];
-- Sense & Drive Row
SenseDrive =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regSenseDriveQuad,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
-- Ram Row
MemUp =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemQuadUp,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
MemDown =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemQuadDown,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Top =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemQuadTop,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
ENDCASE => ERROR;
};
MakeDriverColumn: PROC [type: RowType, rowIndex, colIndex: NAT] = {
SELECT type FROM
-- DMapper Row
DMap =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regDMapperDriver,
renaming: LIST[
["Vdd", "Vdd"], ["Gnd", "Gnd"],
["WriteBack", "WriteBack"],
["WriteOk", "WriteOk"],
["WriteOctal", "WriteOctal"],
["DSwap", "DSwap"],
["nClock", "nClock"],
["nClock2", "nClock2"],
["RD1addr", rd1addr],
["RD2addr", rd2addr],
["NextRegAddrNextLsb", nextRegAddr[decoderSize-2]],
["NextRegAddrLsb", nextRegAddr[decoderSize-1]]]
]];
-- Sense & Drive Row
SenseDrive =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regSenseDriveDriver,
renaming: LIST[
["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
-- Memory Row
MemUp =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemDriverUp,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
MemDown =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemDriverDown,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Top =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemDriverTop,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
ENDCASE => ERROR;
};
MakeDecodeColumn: PROC [type: RowType, rowIndex, colIndex: NAT, polFlag: BOOLEAN, wire: WR, lsbpos: BOOLEANFALSE] = {
SELECT type FROM
DMapper Row
DMap =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regDMapperDecode,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"], ["NextRegAddr", wire]]
]];
Sense & Drive Row
SenseDrive =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: (IF lsbpos THEN regSenseDriveDecodeLsb ELSE regSenseDriveDecode),
flatten: FALSE,
renaming: LIST[
["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Memory Row
MemUp =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: (IF polFlag THEN regMemCellDecode1Up ELSE regMemCellDecode0Up),
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
MemDown =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: (IF polFlag THEN regMemCellDecode1Down ELSE regMemCellDecode0Down),
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Top =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemCellDecodeTop,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
ENDCASE => ERROR;
};
MakePullupColumn: PROC [type: RowType, rowIndex, colIndex: NAT] = {
SELECT type FROM
DMapper Row
DMap =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regDMapperPullup,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Sense & Drive Row
SenseDrive =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regSenseDrivePullup,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Memory Row
MemUp =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemCellPullupUp,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
MemDown =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemCellPullupDown,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
Top =>
tileArray[rowIndex][colIndex] ← NEW[TilingClass.TileRec ← [
type: regMemCellPullupTop,
renaming: LIST[["Vdd", "Vdd"], ["Gnd", "Gnd"]]
]];
ENDCASE => ERROR
};
colIndex: NAT ← 0;
tileArray[rowIndex] ← NEW[TilingClass.TileRowRec[totalColumns]];
-- Make 1st Tap at Begining of row
MakeLeftColumn[type, rowIndex, 0];
-- Loop through the Row Entries, Making taps on the way.
colIndex ← 1;
FOR i: NAT IN [0..busSize) DO
MakeMemColumn[type, rowIndex, colIndex, (IF i>31 THEN i-32 ELSE i+2)];
colIndex ← colIndex + 1;
IF ((i+1) MOD segments) = 0 THEN {
MakeTapColumn[type, rowIndex, colIndex];
colIndex ← colIndex + 1 };
ENDLOOP;
-- Add Drivers & Decoders
MakeDriverColumn[type, rowIndex, colIndex];
colIndex ← colIndex + 1;
FOR i: NAT IN [0..bankDecoderSize) DO
MakeDecodeColumn[type, rowIndex, colIndex, TamarinUtil.BitOnP[bankAddr, bankDecoderSize - 1 - i], nextRegAddr[i]];
colIndex ← colIndex + 1;
ENDLOOP;
FOR i: NAT IN [0..addrDecoderSize-2) DO
MakeDecodeColumn[type, rowIndex, colIndex, TamarinUtil.BitOnP[rowAddr, addrDecoderSize - 1 - i], nextRegAddr[bankDecoderSize+i], i = (addrDecoderSize - 3)];
colIndex ← colIndex + 1;
ENDLOOP;
MakePullupColumn[type, rowIndex, colIndex];
colIndex ← colIndex + 1;
IF colIndex # totalColumns THEN ERROR;
};
-- Start of CreateRegArray procedure
TerminalIO.PutF["Creating RegisterFileTile %g x %g \n",IO.int[nbrBanks],IO.int[regLength]];
-- Error Checking
IF (busSize MOD segments) # 0 THEN ERROR;
IF (regLength MOD 8) # 0 THEN ERROR;
-- Build each bank of the Reg Array
MakeRow[DMap, 0, 0, 0];
MakeRow[SenseDrive, 1, 0, 0];
rowIndex ← 2;
FOR bank: NAT IN [0..nbrBanks) DO
FOR counter: NAT IN [0..regLength/8) DO
MakeRow[MemDown, rowIndex, bank, counter*8];
MakeRow[MemUp, rowIndex+1, bank, counter*8+4];
rowIndex ← rowIndex + 2;
IF bank=4 AND regLength>31 AND counter=1 THEN EXIT;
ENDLOOP;
ENDLOOP;
MakeRow[Top, rowIndex, 0, 0];
rowIndex ← rowIndex + 1;
IF rowIndex # totalRows THEN ERROR;
lastTile ← tileArray;
cellType ← TilingClass.CreateTiling[
name: "RegFile",
public: CoreCreate.WireList[LIST["Vdd", "Gnd", d1, d2, rbus, nextRegAddr, rd1addr, rd2addr, "DSwap", "WriteOk", "WriteBack", "WriteOctal", "nClock2", "nClock"]],
tileArray: tileArray,
neighborX: TilingClass.SchematicsNeighborX,
neighborY: TilingClass.SchematicsNeighborY
];
};
CreateRegArray: PUBLIC PROC [tamarinCx: Sisyph.Context, nbrBanks, regLength, segments: NAT] RETURNS [cellType: Core.CellType] = {
IF extractRegFile THEN cellType ← CreateRealRegArray[tamarinCx, nbrBanks, regLength, segments]
ELSE {
cellType ← CoreClasses.CreateUnspecified[
CoreCreate.WireList[LIST[CoreCreate.Seq["D1", 34], CoreCreate.Seq["D2", 34], CoreCreate.Seq["R", 34], "WriteBack", "WriteOk", CoreCreate.Seq["NextRegAddr", 9], "nClock2", "nClock", "WriteOctal", "DSwap", CoreCreate.Seq["RD1addr", 4], CoreCreate.Seq["RD2addr", 4], "Vdd", "Gnd"]], "RegisterFileTile"];
[] ← Rosemary.BindCellType[cellType: cellType, roseClassName: regFileName];
[] ← CoreFlat.CellTypeCutLabels[ct, Logic.logicCutSet];
[] ← Ports.InitPorts[ct, l, none, "Vdd", "Gnd"];
[] ← Ports.InitPorts[cellType, ls, none, "R", "NextRegAddr", "RD1addr", "RD2addr"];
[] ← Ports.InitPorts[cellType, l, none, "WriteOctal", "DSwap", "WriteBack", "WriteOk", "nClock2", "nClock"];
[] ← Ports.InitPorts[cellType, ls, drive, "D1", "D2"];
TerminalIO.PutRope["Creating Behavioral Proc for RegisterFileTile \n"];
};
};
END.