SoftHdwRasterImpl.mesa
Copyright Ó 1989 by Xerox Corporation. All rights reserved.
Barth, April 28, 1989 5:48:04 pm PDT
DIRECTORY CD, BitmapViewers, BitOps, Imager, ImagerPixel, ImagerSample, Rope, SF, SoftHdwAssembly, SoftHdwRaster, SoftHdwSimulate, ViewerClasses;
SoftHdwRasterImpl: CEDAR PROGRAM
IMPORTS BitmapViewers, BitOps, ImagerPixel, ImagerSample, SoftHdwAssembly, SoftHdwSimulate
EXPORTS SoftHdwRaster
= BEGIN OPEN SoftHdwAssembly, SoftHdwRaster;
RasterTileType: TYPE = {StartStopStateSlow, StartStopStateFast, BoxDecodeToDataPath, FullAdder};
rasterTileNames: ARRAY RasterTileType OF Rope.ROPE ← ["StartStopStateSlow", "StartStopStateFast", "BoxDecodeToDataPath", "FullAdder"];
RasterTileType: TYPE = {StartStopStateSlow, StartStopStateFast, BoxDecodeToDataPath, SampleMapCount, SampleMapExtension, SampleMapMux, SampleMapRam};
rasterTileNames: ARRAY RasterTileType OF Rope.ROPE ← ["StartStopStateSlow", "StartStopStateFast", "BoxDecodeToDataPath", "SampleMapCount", "SampleMapExtension", "SampleMapMux", "SampleMapRam"];
rasterPrograms: ARRAY RasterTileType OF Program ← ALL[NIL];
rasterBaseSizes: ArrayPosition ←
NEW[ArrayPositionRec ← [
chip: [1, 1],
minorArray: [16, 6],
grain: [4, 4]]];
LoadTiles: PROC = {
design: CD.Design ← OpenDesign["SoftHdwRaster.dale"];
FOR index: RasterTileType IN RasterTileType DO
rasterPrograms[index] ← LoadTile[design, rasterTileNames[index]];
ENDLOOP;
};
CreateHi: PUBLIC PROC [sizes: MachineSizes] RETURNS [program: Program] = {
ConnectAddress: PROC [minorY: INT, minorXOffset: INT, bits: INT] = {
FOR index: INT IN [0..2*bits) DO
xGrain: INT ← index MOD 4;
xMinorArray: INT ← minorXOffset + (index/4);
tl ← CTI[old: tl,
type: RDToI,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorY]];
tl ← CTI[old: tl,
type: RDToRD,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorY]];
IF (minorY MOD 2) = 0 THEN tl ← CTI[old: tl,
type: Inverter,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorY]];
ENDLOOP;
};
hLeft: Program ← CreateBox[sizes, [[50,50],[200,60]]];
hBar: Program ← CreateBox[sizes, [[125,50],[135,100]]];
hRight: Program ← CreateBox[sizes, [[50,100],[200,110]]];
iTop: Program ← CreateBox[sizes, [[50,150],[60,200]]];
iPost: Program ← CreateBox[sizes, [[50,170],[200,180]]];
iBottom: Program ← CreateBox[sizes, [[190,150],[200,200]]];
decodeWidth: INT ← Size[hLeft].x-(sizes.pixelsPerChunk+3)/4;
pl: ProgramInstances ← NIL;
tl: ArrayPositions ← NIL;
pl ← CPI[old: pl,
program: hLeft,
minorArray: [0, 0]];
pl ← CPI[old: pl,
program: hBar,
minorArray: [0, 1]];
pl ← CPI[old: pl,
program: hRight,
minorArray: [0, 2]];
pl ← CPI[old: pl,
program: iTop,
minorArray: [0, 3]];
pl ← CPI[old: pl,
program: iPost,
minorArray: [0, 4]];
pl ← CPI[old: pl,
program: iBottom,
minorArray: [0, 5]];
FOR minorYIndex: INT IN [1..6) DO
ConnectAddress[minorYIndex, 0, sizes.sAddressBits];
ConnectAddress[minorYIndex, ((sizes.sAddressBits+1)/2)+1, sizes.fAddressBits];
FOR dataIndex: INT IN [0..sizes.pixelsPerChunk) DO
xGrain: INT ← dataIndex MOD 4;
xMinorArray: INT ← decodeWidth + (dataIndex/4);
tl ← CTI[old: tl,
type: OLUToI,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorYIndex]];
tl ← CTI[old: tl,
type: Inverter,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorYIndex]];
tl ← CTI[old: tl,
type: ParallelInput,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, minorYIndex]];
ENDLOOP;
ENDLOOP;
program ← Create[sizes: rasterBaseSizes, instances: pl, tiles: tl];
};
CreateBox: PUBLIC PROC [sizes: MachineSizes, box: SF.Box] RETURNS [program: Program] = {
decodeProgram: Program ← CreateBoxDecode[sizes, box];
decodeWidth: INT ← Size[decodeProgram].x;
pl: ProgramInstances ← NIL;
tl: ArrayPositions ← NIL;
pl ← CPI[old: pl,
program: decodeProgram,
minorArray: [0, 0]];
IF sizes.bitsPerPixel#1 THEN ERROR; -- not yet implemented
FOR dataIndex: INT IN [0..sizes.pixelsPerChunk) DO
xGrain: INT ← dataIndex MOD 4;
xMinorArray: INT ← decodeWidth + (dataIndex/4);
tl ← CTI[old: tl,
type: InputEnabled,
orientation: Vertical,
grain: [xGrain, 2],
minorArray: [xMinorArray, 0]];
IF dataIndex >= (box.min.f MOD sizes.pixelsPerChunk) THEN tl ← CTI[old: tl,
type: InputEnabled,
orientation: Vertical,
grain: [xGrain, 0],
minorArray: [xMinorArray, 0]];
IF dataIndex < (box.max.f MOD sizes.pixelsPerChunk) THEN tl ← CTI[old: tl,
type: InputEnabled,
orientation: Vertical,
grain: [xGrain, 1],
minorArray: [xMinorArray, 0]];
ENDLOOP;
FOR minorIndex: INT IN [1..(sizes.pixelsPerChunk+3)/4) DO
FOR grain: INT IN [0..2] DO
tl ← CTI[old: tl,
type: RDToRD,
orientation: Horizontal,
grain: [0, grain],
minorArray: [minorIndex+decodeWidth, 0]];
tl ← CTI[old: tl,
type: RDToI,
orientation: Horizontal,
grain: [0, grain],
minorArray: [minorIndex+decodeWidth, 0]];
IF (minorIndex MOD 2) = 1 THEN tl ← CTI[old: tl,
type: Inverter,
orientation: Horizontal,
grain: [0, grain],
minorArray: [minorIndex+decodeWidth, 0]];
ENDLOOP;
ENDLOOP;
program ← Create[sizes: rasterBaseSizes, instances: pl, tiles: tl];
};
CreateBoxDecode: PROC [sizes: MachineSizes, box: SF.Box] RETURNS [program: Program] = {
slowProgram: Program ← CreateStartStop[sizes.sAddressBits, box.min.s, box.max.s, rasterPrograms[StartStopStateSlow]];
slowSize: INT ← Size[slowProgram].x;
fastProgram: Program ← CreateStartStop[sizes.fAddressBits, box.min.f/sizes.pixelsPerChunk, box.max.f/sizes.pixelsPerChunk, rasterPrograms[StartStopStateFast]];
fastSize: INT ← Size[fastProgram].x;
abut: Program ← AbutX[slowProgram, fastProgram, rasterPrograms[BoxDecodeToDataPath]];
pl: ProgramInstances ← NIL;
tl: ArrayPositions ← NIL;
pl ← CPI[old: pl,
program: abut,
minorArray: [0, 0]];
tl ← CTI[old: tl,
type: OLUToRD,
orientation: Horizontal,
grain: [0, 3],
minorArray: [slowSize, 0]];
FOR minorIndex: INT IN [1..fastSize-1) DO
tl ← CTI[old: tl,
type: RDToRD,
orientation: Horizontal,
grain: [0, 3],
minorArray: [minorIndex+slowSize, 0]];
ENDLOOP;
IF (sizes.fAddressBits MOD 2) = 0 THEN tl ← CTI[old: tl,
type: Inverter,
orientation: Horizontal,
grain: [0, 3],
minorArray: [slowSize+fastSize, 0]];
program ← Create[sizes: rasterBaseSizes, instances: pl, tiles: tl];
};
CreateStartStop: PROC [bits: INT, start, stop: INT, logicProgram: Program] RETURNS [program: Program] = {
startProgram: Program ← CreateDecoder[bits, start, 0];
IF start=stop THEN {
ERROR; -- single chunk height or width boxes not yet implemented
}
ELSE {
stopProgram: Program ← CreateDecoder[bits, stop, 1];
pl: ProgramInstances ← NIL;
pl ← CPI[old: pl,
program: startProgram,
minorArray: [0, 0]];
pl ← CPI[old: pl,
program: stopProgram,
minorArray: [0, 0]];
pl ← CPI[old: pl,
program: logicProgram,
minorArray: [(bits+1)/2, 0]];
program ← Create[sizes: rasterBaseSizes, instances: pl];
};
};
CreateDecoder: PROC [bits: INT, constant: INT, grainY: INT] RETURNS [program: Program] = {
tl: ArrayPositions ← NIL;
FOR bitIndex: INT IN [0..bits) DO
tl ← CTI[old: tl,
type: InputEnabled,
orientation: Horizontal,
grain: [2*(bitIndex MOD 2) + (IF BitOps.EBFD[constant, bitIndex, bits] THEN 1 ELSE 0), grainY],
minorArray: [bitIndex/2, 0]];
ENDLOOP;
FOR minorIndex: INT IN [0..((bits+1)/2)-1) DO
tl ← CTI[old: tl,
type: OLUToI,
orientation: Horizontal,
grain: [0, grainY],
minorArray: [minorIndex+1, 0]];
tl ← CTI[old: tl,
type: Inverter,
orientation: Horizontal,
grain: [0, grainY],
minorArray: [minorIndex+1, 0]];
tl ← CTI[old: tl,
type: ParallelInput,
orientation: Horizontal,
grain: [0, grainY],
minorArray: [minorIndex+1, 0]];
ENDLOOP;
program ← Create[sizes: rasterBaseSizes, tiles: tl];
};
chunksPerRAM: INT = 8;
bitsPerRAMROMPair: INT = 8;
CreateSampleMap: PUBLIC PROC [sizes: MachineSizes, position: ImagerSample.Vec, map: ImagerSample.SampleMap] RETURNS [program: Program] = {
EmitRAM: PROC [y: INT] = {
FOR index: INT IN [0..sizes.pixelsPerChunk/bitsPerRAMROMPair) DO
x: INT ← decodeWidth-tileWidth+2*index*minorSize;
il ← CONS[InstantiateTile[SampleMapRam, [x, y]], il];
ENDLOOP;
};
box: SF.Box ← SF.Displace[ImagerSample.GetBox[map], position];
widthInChunks: INT ← ((box.max.f-1)/sizes.pixelsPerChunk) - (box.min.f/sizes.pixelsPerChunk) + 1;
heightInChunks: INT ← box.max.s-box.min.s;
chunkCount: INT ← widthInChunks*heightInChunks;
decodeObject: CD.Object ← CreateBoxDecode[sizes, box];
decodeWidth: INTCD.InterestSize[decodeObject].x;
il: CD.InstanceList ← NIL;
IF ImagerSample.GetBitsPerSample[map]#1 THEN ERROR; -- not yet implemented
IF sizes.bitsPerPixel#ImagerSample.GetBitsPerSample[map] THEN ERROR;
IF (sizes.pixelsPerChunk MOD bitsPerRAMROMPair)#0 THEN ERROR; -- not yet implemented
il ← CONS[CreateInstance[decodeObject, [0, 0]], il];
il ← CONS[InstantiateTile[SampleMapCount, [decodeWidth - tileWidth - 7*minorSize, -minorSize]], il];
FOR index: INT IN [0..sizes.pixelsPerChunk/bitsPerRAMROMPair) DO
x: INT ← decodeWidth-tileWidth+2*index*minorSize;
il ← CONS[InstantiateTile[SampleMapMux, [x, 0]], il];
ENDLOOP;
EmitRAM[-minorSize];
FOR index: INT IN [1..(chunkCount/chunksPerRAM)-1] DO
y: INT ← -(index+1)*minorSize;
il ← CONS[InstantiateTile[SampleMapExtension, [decodeWidth - tileWidth - 4*minorSize, y]], il];
EmitRAM[y];
ENDLOOP;
object ← PW.CreateCell[il, [0, -(chunkCount/chunksPerRAM)*minorSize, decodeWidth + ((sizes.pixelsPerChunk+3)/4)*minorSize, minorSize+tileWidth]];
sample: ImagerSample.Sample ← ImagerSample.Get[map, [s, f]];
};
Test: PROC = {
StoreAddress: PROC [offset: INT, size: INT, value: INT] = {
FOR index: INT IN [0..size) DO
bit: BOOL ← BitOps.EBFD[value, index, size];
position.minorArray ← [offset + index/addressBitsPerMinorArray, 0];
position.grain ← [2*(index MOD addressBitsPerMinorArray), 0];
position.type ← Input;
SoftHdwSimulate.Store[simulation, position, NOT bit];
position.type ← RightDown;
SoftHdwSimulate.Store[simulation, position, NOT bit];
position.grain.x ← position.grain.x + 1;
position.type ← Input;
SoftHdwSimulate.Store[simulation, position, bit];
position.type ← RightDown;
SoftHdwSimulate.Store[simulation, position, bit];
ENDLOOP;
};
sizes: MachineSizes ← NEW[MachineSizesRec ← [sAddressBits: 8, fAddressBits: 5, pixelsPerChunk: 8, bitsPerPixel: 1]];
addressBitsPerMinorArray: INT ← 2;
slowDecodeWidth: INT ← ((sizes.sAddressBits+addressBitsPerMinorArray-1) / addressBitsPerMinorArray) + 1;
decodeWidth: INT ← slowDecodeWidth + ((sizes.fAddressBits+addressBitsPerMinorArray-1) / addressBitsPerMinorArray) + 2;
program: Program ← CreateHi[sizes];
programHeight: INT ← Size[program].y;
simulation: SoftHdwSimulate.Simulation ← SoftHdwSimulate.Create["Box Test", program];
position: ArrayPosition ← NEW[ArrayPositionRec];
rasterDisplay: RasterDisplay ← RasterDisplayCreate[sizes];
position.chip ← [0, 0];
position.orientation ← Vertical;
SoftHdwSimulate.Initialize[simulation];
FOR dataIndex: INT IN [0..sizes.pixelsPerChunk) DO
position.minorArray ← [decodeWidth + (dataIndex/4), 0];
position.grain ← [dataIndex MOD 4, 0];
position.type ← Input;
SoftHdwSimulate.Store[simulation, position, FALSE];
ENDLOOP;
FOR sAddress: INT IN [0..BitOps.TwoToThe[sizes.sAddressBits]) DO
StoreAddress[0, sizes.sAddressBits, sAddress];
FOR fAddress: INT IN [0..BitOps.TwoToThe[sizes.fAddressBits]) DO
StoreAddress[slowDecodeWidth, sizes.fAddressBits, fAddress];
SoftHdwSimulate.Relax[simulation];
SoftHdwSimulate.MasterToSlave[simulation];
SoftHdwSimulate.Relax[simulation];
SoftHdwSimulate.Sample[simulation];
position.type ← Output;
FOR dataIndex: INT IN [0..sizes.pixelsPerChunk) DO
position.minorArray ← [decodeWidth + (dataIndex/4), programHeight-1];
position.grain ← [dataIndex MOD 4, 0];
RasterDisplayStore[rasterDisplay, [fAddress*sizes.pixelsPerChunk+dataIndex, sAddress], IF SoftHdwSimulate.Fetch[simulation, position] THEN 1 ELSE 0];
ENDLOOP;
ENDLOOP;
BitmapViewers.Refresh[rasterDisplay.viewer];
ENDLOOP;
};
TestFullAdder: PROC = {
program: Program ← rasterPrograms[FullAdder];
simulation: SoftHdwSimulate.Simulation ← SoftHdwSimulate.Create["FullAdder Test", program];
position: ArrayPosition ← NEW[ArrayPositionRec];
position.chip ← [0, 0];
position.minorArray.x ← 0;
SoftHdwSimulate.Initialize[simulation];
FOR xIndex: INT IN [0..2) DO
x: BOOLIF xIndex=0 THEN FALSE ELSE TRUE;
position.type ← Input;
position.orientation ← Vertical;
position.grain ← [0, 0];
position.minorArray.y ← 1;
SoftHdwSimulate.Store[simulation, position, x];
position.minorArray.y ← 2;
SoftHdwSimulate.Store[simulation, position, x];
FOR yIndex: INT IN [0..2) DO
y: BOOLIF yIndex=0 THEN FALSE ELSE TRUE;
position.type ← Input;
position.orientation ← Vertical;
position.grain ← [1, 0];
position.minorArray.y ← 0;
SoftHdwSimulate.Store[simulation, position, y];
position.minorArray.y ← 2;
SoftHdwSimulate.Store[simulation, position, y];
FOR cIndex: INT IN [0..2) DO
c: BOOLIF cIndex=0 THEN FALSE ELSE TRUE;
sum: BOOL ← (x AND y AND c) OR (NOT x AND NOT y AND c) OR (NOT x AND y AND NOT c) OR (x AND NOT y AND NOT c);
carry: BOOL ← (x AND y) OR (x AND c) OR (y AND c);
position.type ← Input;
position.orientation ← Horizontal;
position.grain ← [0, 0];
position.minorArray.y ← 2;
SoftHdwSimulate.Store[simulation, position, NOT c];
SoftHdwSimulate.Relax[simulation];
position.type ← Output;
position.orientation ← Vertical;
position.grain ← [3, 0];
position.minorArray.y ← 0;
IF SoftHdwSimulate.Fetch[simulation, position]#sum THEN ERROR;
position.type ← Output;
position.orientation ← Horizontal;
position.grain ← [0, 0];
position.minorArray.y ← 2;
IF NOT SoftHdwSimulate.Fetch[simulation, position]#carry THEN ERROR;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
Raster Display
RasterDisplay: TYPE = REF RasterDisplayRec;
RasterDisplayRec: TYPE = RECORD [
viewer: ViewerClasses.Viewer,
sampleMap: Imager.SampleMap,
bitMap: Imager.PixelMap];
RasterDisplayCreate: PROC [sizes: MachineSizes] RETURNS [rasterDisplay: RasterDisplay] = {
rasterDisplay ← NEW[RasterDisplayRec];
rasterDisplay.viewer ← BitmapViewers.CreateBitmapViewer[$SoftHdwRasterViewers, [name: "Soft Hardware Raster"]];
rasterDisplay.sampleMap ← ImagerSample.NewSampleMap[box: [min: SF.zeroVec, max: [BitOps.TwoToThe[sizes.fAddressBits]*sizes.pixelsPerChunk, BitOps.TwoToThe[sizes.sAddressBits]]], bitsPerSample: sizes.bitsPerPixel];
rasterDisplay.bitMap ← ImagerPixel.MakePixelMap[rasterDisplay.sampleMap];
rasterDisplay.viewer.data ← rasterDisplay;
};
RasterDisplayStore: PROC [rasterDisplay: RasterDisplay, position: Position, sample: WORD] = {
vec: SF.Vec ← [s: position.y, f: position.x];
ImagerSample.Put[rasterDisplay.sampleMap, vec, sample];
};
RasterDisplayNotifier: BitmapViewers.NotifyAdjustmentProc = {
vd: BitmapViewers.ViewDescription ← BitmapViewers.Describe[viewer];
IF NOT vd.visible THEN BitmapViewers.SetBitmap[viewer, NIL]
ELSE {
rasterDisplay: RasterDisplay ← NARROW[viewer.data];
BitmapViewers.SetBitmap[viewer: viewer, bitmap: rasterDisplay.bitMap];
BitmapViewers.Refresh[viewer];
};
};
LoadTiles[];
BitmapViewers.RegisterBitmapViewerClass[$SoftHdwRasterViewers, [], RasterDisplayNotifier];
END.