RamBuilder.mesa
Copyright © 1985-1986 by Xerox Corporation. All rights reversed.
Last Edited by: Ross July 23, 1986 12:52:43 pm PDT
DIRECTORY PW, TamLib;
RamBuilder: CEDAR PROGRAMIMPORTS PW, TamLib =
BEGIN OPEN PW, TamLib;
Generate: UserProc = {
Library for design:
myLib: PW.Design ← PW.OpenDesign["///Users/ross.pa/tamarin/ram.dale"];
Constant Declarations:
NUMFRAMES: INT = 5;
NUMTOPFRAMES: INT = 3;
NUMWORDSPERFRAME: INT = 40;
NUMBITSPERWORD: INT = 32;
NUMDECODEBITS: INT = 6;
NUMFRAMEBITS: INT = 3;
NUMBITSPERBLOCK: INT = 4;
YTap frequency is not currently implemented. Instead it was observed that the "right" amount of taps was to have each fram tapped at each end.
NUMBITBLOCKS: INT = 4; -- Tap frequency for poly RD & WT lines (per 2 bits)
TAPFREQY: INT = 10 ; -- Tap frequency for poly decode lines
NUMBOTFRAMES: INT = NUMFRAMES - NUMTOPFRAMES;
NUMROWSPERFRAME: INT = NUMWORDSPERFRAME/2;
NUMDBLROWSPERFRAME: INT = NUMROWSPERFRAME/2;
NUMWORDS: INT = (NUMFRAMES * NUMWORDSPERFRAME) / 2;
NUMDBLBITSPERWORD: INT = NUMBITSPERWORD/2;
NUMDBLWORDS: INT = NUMWORDS/2;
Library for cells: see TamLib.mesa and TamLibImpl.mesa
Start out by building the decoder and then the separate ram halves.
This procedure uses the global values NUMDECODEBITS and NUMWORDS.
TopDecodeGen: PROC [] RETURNS [decoder: PW.Object] = {
decoderow: PW.Object ← NIL;
decoderowlist: LIST OF PW.Object ← NIL;
pullupcolumn: PW.Object ← NIL;
drveven: PW.Object ← NIL;
drvodd: PW.Object ← NIL;
norcellsgnd: PW.Object ← ArrayX[norcellgnd, NUMDECODEBITS];
decspacerow: PW.Object ← ArrayX[norplym2cnt, NUMDECODEBITS];
framedec: PW.Object ← NIL;
framedeclist: LIST OF PW.Object ← NIL;
framedecbits: PW.Object;
framedecbitslist: LIST OF PW.Object ← NIL;
decodeblock: PW.Object ← NIL;
decodeblocklist: LIST OF PW.Object ← NIL;
yspacer: PW.Object ← NIL;
Build the decoder hunk for a frame:
FOR rowindex: INT IN [0..NUMROWSPERFRAME) DO
decoderowlist ← NIL;
FOR colindex: INT IN [0..NUMDECODEBITS) DO
IF XthBitOfN[colindex, rowindex] THEN decoderowlist ← CONS[nordecode1, decoderowlist] ELSE decoderowlist ← CONS[nordecode0, decoderowlist];
ENDLOOP;
decoderow ← PW.AbutListX[decoderowlist];
framedeclist ← CONS[decoderow, framedeclist];
ENDLOOP;
framedec ← PW.AbutListY[framedeclist];
pullupcolumn ← PW.ArrayY[decodepullup, NUMDBLROWSPERFRAME];
drveven ← PW.ArrayY[decdrveven, NUMDBLROWSPERFRAME];
drvodd ← PW.ArrayY[decdrvodd, NUMDBLROWSPERFRAME];
yspacer ← PW.AbutX[drvevenyspacer, PW.ArrayX[norplym2cnt, NUMDECODEBITS+NUMFRAMEBITS], norpullupyspacer, drvoddyspacer];
FOR frameindex: INT IN [0..NUMTOPFRAMES) DO
framedecbitslist ← NIL;
decodeblock ← NIL;
FOR colindex: INT IN [0..NUMFRAMEBITS) DO
IF XthBitOfN[colindex, frameindex] THEN framedecbitslist ← CONS[nordecode1, framedecbitslist] ELSE framedecbitslist ← CONS[nordecode0, framedecbitslist];
ENDLOOP;
framedecbits ← PW.ArrayY[PW.AbutListX[framedecbitslist], NUMROWSPERFRAME];
decodeblock ← PW.AbutX[drveven, framedecbits, framedec, pullupcolumn, drvodd];
decodeblocklist ← CONS[yspacer, decodeblocklist];
decodeblocklist ← CONS[decodeblock, decodeblocklist];
ENDLOOP;
decodeblocklist ← CONS[yspacer, decodeblocklist];
decoder ← PW.AbutListY[decodeblocklist];
RETURN[decoder];
};
This procedure uses the global values NUMDBLBITSPERWORD and NUMDBLWORDS.
TopRamHalfGen: PROC [] RETURNS [ramhalf: PW.Object] = {
rowlist: LIST OF PW.Object ← NIL;
ramrow: PW.Object ← NIL;
spacerrow: PW.Object ← NIL;
ramhalfgnd: PW.Object ← NIL;
gndrow: PW.Object ← NIL;
ramblock: PW.Object ← NIL;
Build a bit row (and a spacer row) and then replicate it in the Y-direction...
rowlist ← LIST[yxspacerend, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], PW.FlipX[yxspacerend]];
spacerrow ← PW.AbutListX[rowlist];
rowlist ← LIST[spacerend, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], PW.FlipX[spacerend]];
ramrow ← PW.AbutListX[rowlist];
ramblock ← PW.AbutY[PW.ArrayY[ramrow, NUMDBLROWSPERFRAME], spacerrow];
ramhalf ← PW.AbutY[spacerrow, PW.ArrayY[ramblock, NUMTOPFRAMES]];
RETURN[ramhalf];
};
ramarray: PW.Object;
InitRam[myLib];
ramarray ← PW.AbutX[TopRamHalfGen[], TopDecodeGen[], PW.FlipX[TopRamHalfGen[]]];
RETURN[ramarray];
};
Generate2: UserProc = {
Library for design:
myLib: PW.Design ← PW.OpenDesign["///Users/ross.pa/tamarin/ram.dale"];
Constant Declarations:
NUMFRAMES: INT = 5;
NUMTOPFRAMES: INT = 3;
NUMWORDSPERFRAME: INT = 40;
NUMBITSPERWORD: INT = 32;
NUMDECODEBITS: INT = 6;
NUMFRAMEBITS: INT = 3;
NUMBITSPERBLOCK: INT = 4;
YTap frequency is not currently implemented. Instead it was observed that the "right" amount of taps was to have each fram tapped at each end.
NUMBITBLOCKS: INT = 4; -- Tap frequency for poly RD & WT lines (per 2 bits)
TAPFREQY: INT = 10 ; -- Tap frequency for poly decode lines
NUMBOTFRAMES: INT = NUMFRAMES - NUMTOPFRAMES;
NUMROWSPERFRAME: INT = NUMWORDSPERFRAME/2;
NUMDBLROWSPERFRAME: INT = NUMROWSPERFRAME/2;
NUMWORDS: INT = (NUMFRAMES * NUMWORDSPERFRAME) / 2;
NUMDBLBITSPERWORD: INT = NUMBITSPERWORD/2;
NUMDBLWORDS: INT = NUMWORDS/2;
Library for cells: see TamLib.mesa and TamLibImpl.mesa
Start out by building the decoder and then the separate ram halves.
This procedure uses the global values NUMDECODEBITS and NUMWORDS.
BotDecodeGen: PROC [] RETURNS [decoder: PW.Object] = {
decoderow: PW.Object ← NIL;
decoderowlist: LIST OF PW.Object ← NIL;
pullupcolumn: PW.Object ← NIL;
drveven: PW.Object ← NIL;
drvodd: PW.Object ← NIL;
norcellsgnd: PW.Object ← ArrayX[norcellgnd, NUMDECODEBITS];
decspacerow: PW.Object ← ArrayX[norplym2cnt, NUMDECODEBITS];
framedec: PW.Object ← NIL;
framedeclist: LIST OF PW.Object ← NIL;
framedecbits: PW.Object;
framedecbitslist: LIST OF PW.Object ← NIL;
decodeblock: PW.Object ← NIL;
decodeblocklist: LIST OF PW.Object ← NIL;
yspacer: PW.Object ← NIL;
Build the decoder hunk for a frame:
FOR rowindex: INT IN [0..NUMROWSPERFRAME) DO
decoderowlist ← NIL;
FOR colindex: INT IN [0..NUMDECODEBITS) DO
IF XthBitOfN[colindex, rowindex] THEN decoderowlist ← CONS[nordecode1, decoderowlist] ELSE decoderowlist ← CONS[nordecode0, decoderowlist];
ENDLOOP;
decoderow ← PW.AbutListX[decoderowlist];
framedeclist ← CONS[decoderow, framedeclist];
ENDLOOP;
framedec ← PW.AbutListY[framedeclist];
pullupcolumn ← PW.ArrayY[decodepullup, NUMDBLROWSPERFRAME];
drveven ← PW.ArrayY[decdrveven, NUMDBLROWSPERFRAME];
drvodd ← PW.ArrayY[decdrvodd, NUMDBLROWSPERFRAME];
yspacer ← PW.AbutX[drvevenyspacer, PW.ArrayX[norplym2cnt, NUMDECODEBITS+NUMFRAMEBITS], norpullupyspacer, drvoddyspacer];
FOR frameindex: INT IN [NUMTOPFRAMES..NUMFRAMES) DO
framedecbitslist ← NIL;
decodeblock ← NIL;
FOR colindex: INT IN [0..NUMFRAMEBITS) DO
IF XthBitOfN[colindex, frameindex] THEN framedecbitslist ← CONS[nordecode1, framedecbitslist] ELSE framedecbitslist ← CONS[nordecode0, framedecbitslist];
ENDLOOP;
framedecbits ← PW.ArrayY[PW.AbutListX[framedecbitslist], NUMROWSPERFRAME];
decodeblock ← PW.AbutX[drveven, framedecbits, framedec, pullupcolumn, drvodd];
decodeblocklist ← CONS[yspacer, decodeblocklist];
decodeblocklist ← CONS[decodeblock, decodeblocklist];
ENDLOOP;
decodeblocklist ← CONS[yspacer, decodeblocklist];
decoder ← PW.AbutListY[decodeblocklist];
RETURN[decoder];
};
This procedure uses the global values NUMDBLBITSPERWORD and NUMDBLWORDS.
BotRamHalfGen: PROC [] RETURNS [ramhalf: PW.Object] = {
rowlist: LIST OF PW.Object ← NIL;
ramrow: PW.Object ← NIL;
spacerrow: PW.Object ← NIL;
ramhalfgnd: PW.Object ← NIL;
gndrow: PW.Object ← NIL;
ramblock: PW.Object ← NIL;
Build a bit row (and a spacer row) and then replicate it in the Y-direction...
rowlist ← LIST[yxspacerend, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], yxspacer, PW.ArrayX[bitcellyspacer, NUMBITSPERBLOCK], PW.FlipX[yxspacerend]];
spacerrow ← PW.AbutListX[rowlist];
rowlist ← LIST[spacerend, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], spacer, PW.ArrayX[bitcell, NUMBITSPERBLOCK], PW.FlipX[spacerend]];
ramrow ← PW.AbutListX[rowlist];
ramblock ← PW.AbutY[PW.ArrayY[ramrow, NUMDBLROWSPERFRAME], spacerrow];
ramhalf ← PW.AbutY[spacerrow, PW.ArrayY[ramblock, NUMBOTFRAMES]];
RETURN[ramhalf];
};
ramarray: PW.Object;
InitRam[myLib];
ramarray ← PW.AbutX[BotRamHalfGen[], BotDecodeGen[], PW.FlipX[BotRamHalfGen[]]];
RETURN[ramarray];
};
Register[Generate, "RamTopBuilder"];
Register[Generate2, "RamBotBuilder"];
END.