SoftHdwAssemblyImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDTexts, ExtractOps, FS, IO, PW, RefTab, Rope, SoftHdwBasics, SymTab, TerminalIO
EXPORTS SoftHdwAssembly
= BEGIN OPEN SoftHdwAssembly;
Program Creation
Create:
PUBLIC
PROC [instances: ProgramInstances ←
NIL, tiles: ArrayPositions ←
NIL, coordinates: Coordinates ← MinorArray, object:
CD.Object ←
NIL]
RETURNS [program: Program] = {
program ←
NEW[ProgramRec ← [
tiles: tiles,
instances: instances,
coordinates: coordinates,
object: object]];
};
Instance:
PUBLIC
PROC [program: Program, minorArray: Position ← [0, 0], chip: Position ← [0, 0], rotation: Rotation ← None]
RETURNS [instance: ProgramInstance]= {
instance ←
NEW[ProgramInstanceRec ← [
program: program,
rotation: rotation,
chip: chip,
minorArray: minorArray]];
};
CPI:
PUBLIC
PROC [old: ProgramInstances, program: Program, minorArray: Position ← [0, 0], chip: Position ← [0, 0], rotation: Rotation ← None]
RETURNS [new: ProgramInstances] = {
new ← CONS[Instance[program, minorArray, chip, rotation], old];
};
CTI:
PUBLIC
PROC [old: ArrayPositions, type: TileType, orientation: Orientation, grain: Position, minorArray: Position ← [0, 0], chip: Position ← [0, 0]]
RETURNS [new: ArrayPositions] = {
tile: ArrayPosition ←
NEW[ArrayPositionRec ← [
type: type,
orientation: orientation,
chip: chip,
minorArray: minorArray,
grain: grain]];
IF NOT (type IN TileType) THEN ERROR;
new ← CONS[tile, old];
};
AbutX:
PUBLIC
PROC [t1, t2, t3, t4, t5, t6: Program ←
NIL]
RETURNS [program: Program] = {
subPrograms: Programs ← NIL;
IF t6#NIL THEN subPrograms ← CONS[t6, subPrograms];
IF t5#NIL THEN subPrograms ← CONS[t5, subPrograms];
IF t4#NIL THEN subPrograms ← CONS[t4, subPrograms];
IF t3#NIL THEN subPrograms ← CONS[t3, subPrograms];
IF t2#NIL THEN subPrograms ← CONS[t2, subPrograms];
IF t1#NIL THEN subPrograms ← CONS[t1, subPrograms];
program ← AbutXList[subPrograms];
};
AbutXList:
PUBLIC
PROC [subPrograms: Programs]
RETURNS [program: Program] = {
instances: ProgramInstances ← NIL;
position: Position ← [0, 0];
coordinates: Coordinates ← IF subPrograms=NIL THEN Grain ELSE subPrograms.first.coordinates;
FOR sp: Programs ← subPrograms, sp.rest
UNTIL sp=
NIL
DO
IF coordinates#sp.first.coordinates THEN ERROR;
instances ← ConsByCoordinate[instances, sp.first, position];
position.x ← position.x + Size[sp.first].x;
ENDLOOP;
program ← Create[instances: instances, coordinates: coordinates];
};
AbutY:
PUBLIC
PROC [t1, t2, t3, t4, t5, t6: Program ←
NIL]
RETURNS [program: Program] = {
subPrograms: Programs ← NIL;
IF t6#NIL THEN subPrograms ← CONS[t6, subPrograms];
IF t5#NIL THEN subPrograms ← CONS[t5, subPrograms];
IF t4#NIL THEN subPrograms ← CONS[t4, subPrograms];
IF t3#NIL THEN subPrograms ← CONS[t3, subPrograms];
IF t2#NIL THEN subPrograms ← CONS[t2, subPrograms];
IF t1#NIL THEN subPrograms ← CONS[t1, subPrograms];
program ← AbutYList[subPrograms];
};
AbutYList:
PUBLIC
PROC [subPrograms: Programs]
RETURNS [program: Program] = {
instances: ProgramInstances ← NIL;
position: Position ← [0, 0];
coordinates: Coordinates ← IF subPrograms=NIL THEN Grain ELSE subPrograms.first.coordinates;
FOR sp: Programs ← subPrograms, sp.rest
UNTIL sp=
NIL
DO
IF coordinates#sp.first.coordinates THEN ERROR;
instances ← ConsByCoordinate[instances, sp.first, position];
position.y ← position.y + Size[sp.first].y;
ENDLOOP;
program ← Create[instances: instances, coordinates: coordinates];
};
ArrayX:
PUBLIC
PROC [program: Program, nx:
INT]
RETURNS [array: Program] = {
instances: ProgramInstances ← NIL;
position: Position ← [0, 0];
xSize: INT ← Size[program].x;
FOR count:
INT
IN [0..nx)
DO
instances ← ConsByCoordinate[instances, program, position];
position.x ← position.x + xSize;
ENDLOOP;
array ← Create[instances: instances, coordinates: program.coordinates];
};
ArrayY:
PUBLIC
PROC [program: Program, ny:
INT]
RETURNS [array: Program] = {
instances: ProgramInstances ← NIL;
position: Position ← [0, 0];
ySize: INT ← Size[program].y;
FOR count:
INT
IN [0..ny)
DO
instances ← ConsByCoordinate[instances, program, position];
position.y ← position.y + ySize;
ENDLOOP;
array ← Create[instances: instances, coordinates: program.coordinates];
};
ConsByCoordinate:
PROC [old: ProgramInstances, program: Program, position: Position]
RETURNS [new: ProgramInstances] = {
new ←
SELECT program.coordinates
FROM
Grain => ERROR,
MinorArray => CPI[old: old, program: program, minorArray: position],
Chip => CPI[old: old, program: program, chip: position],
ENDCASE => ERROR;
};
Utilities
Size:
PUBLIC
PROC [program: Program]
RETURNS [size: Position] = {
Should check for overflow, requires sizes parameter.
Also should check for tile type and coordinate system compatibility.
min: Position ← [LAST[DABasics.Number], LAST[DABasics.Number]];
max: Position ← [0, 0];
FOR tiles: ArrayPositions ← program.tiles, tiles.rest
UNTIL tiles=
NIL
DO
tile: ArrayPosition ← tiles.first;
position: Position ←
SELECT program.coordinates
FROM
Grain => (IF tile.minorArray#[0,0] OR tile.chip#[0,0] THEN ERROR ELSE tile.grain),
MinorArray => (IF tile.chip#[0,0] THEN ERROR ELSE tile.minorArray),
Chip => tile.chip,
ENDCASE => ERROR;
min.x ← MIN[position.x, min.x];
min.y ← MIN[position.y, min.y];
max.x ← MAX[position.x, max.x];
max.y ← MAX[position.y, max.y];
ENDLOOP;
FOR instances: ProgramInstances ← program.instances, instances.rest
UNTIL instances=
NIL
DO
instance: ProgramInstance ← instances.first;
position: Position ←
SELECT program.coordinates
FROM
Grain => ERROR,
MinorArray => (IF instance.chip#[0,0] THEN ERROR ELSE instance.minorArray),
Chip => instance.chip,
ENDCASE => ERROR;
IF ORD[instance.program.coordinates]>ORD[program.coordinates] THEN ERROR; -- trying to embed a higher level construct inside a lower level construct
IF instance.rotation=None
THEN {
min.x ← MIN[position.x, min.x];
min.y ← MIN[position.y, min.y];
IF
ORD[instance.program.coordinates]=
ORD[program.coordinates]
THEN {
subSize: Position ← Size[instance.program];
max.x ← MAX[position.x+subSize.x-1, max.x];
max.y ← MAX[position.y+subSize.y-1, max.y];
};
}
ELSE {
min.x ← MIN[position.y, min.x];
min.y ← MIN[position.x, min.y];
IF
ORD[instance.program.coordinates]=
ORD[program.coordinates]
THEN {
subSize: Position ← Size[instance.program];
max.x ← MAX[position.y+subSize.y-1, max.x];
max.y ← MAX[position.x+subSize.x-1, max.y];
};
};
ENDLOOP;
size.x ← max.x - min.x + 1;
size.y ← max.y - min.y + 1;
size.x ← max.x + 1;
size.y ← max.y + 1;
};
EnumerateTiles:
PUBLIC
PROC [program: Program, eachTile: EachTileProc] = {
EnumerateTilesRecursive:
PROC [program: Program, chip: Position, minorArray: Position] = {
FOR tiles: ArrayPositions ← program.tiles, tiles.rest
UNTIL tiles=
NIL
DO
position^ ← tiles.first^;
position.chip ← CDBasics.AddPoints[chip, position.chip];
position.minorArray ← CDBasics.AddPoints[minorArray, position.minorArray];
eachTile[position];
ENDLOOP;
FOR instances: ProgramInstances ← program.instances, instances.rest
UNTIL instances=
NIL
DO
instance: ProgramInstance ← instances.first;
IF instance.rotation#None THEN ERROR;
EnumerateTilesRecursive[instance.program, CDBasics.AddPoints[chip, instance.chip], CDBasics.AddPoints[minorArray, instance.minorArray]];
ENDLOOP;
};
position: ArrayPosition ← NEW[ArrayPositionRec];
EnumerateTilesRecursive[program, [0,0], [0,0]];
};
OpenDesign:
PUBLIC
PROC [designName: Rope.
ROPE]
RETURNS [design:
CD.Design] = {
design ← PW.OpenDesign[designName];
CDOps.SetMutability[design, readonly];
IF NOT CDImports.LoadAndBindAll[design, false] THEN ERROR;
};
highlightRectangleWidth: Number = 3*lambda;
HighlightDesign:
PUBLIC PROC [design:
CD.Design, sizes: ArrayPosition, positions: ColoredArrayPositions ←
NIL, viewer: ViewerClasses.Viewer ←
NIL, label: Rope.
ROPE ←
NIL] = {
instances: CD.InstanceList ← NIL;
minorArraySize, chipSize: Position;
[minorArraySize, chipSize] ← MinorArrayChipSize[sizes];
FOR pl: ColoredArrayPositions ← positions, pl.rest
UNTIL pl=
NIL
DO
position: ArrayPosition ← pl.first.position;
object: CD.Object ← IF position.type=Long THEN CDRects.CreateRect[[(IF position.orientation=Vertical THEN sizes.minorArray.y*minorArraySize.y ELSE sizes.minorArray.x*minorArraySize.x), highlightRectangleWidth], colorToLayer[pl.first.color]] ELSE nodeHighlightObjects[position.type][pl.first.color];
transform: CD.Transformation ← TileToTransformation[minorArraySize, chipSize, position];
instance: CD.Instance;
transform.off ← CDBasics.SubPoints[transform.off, CDBasics.OrientedSize[CD.InterestBase[object], transform.orient]];
instance ←
NEW[
CD.InstanceRep ← [
ob: object,
trans: transform]];
instances ← CONS[instance, instances];
ENDLOOP;
ExtractOps.HighlightDesignList[design: design, highlight: instances, viewer: viewer, label: label];
};
LoadTile:
PUBLIC
PROC [design:
CD.Design, tileName: Rope.
ROPE]
RETURNS [program: Program] = {
object: CD.Object ← PW.Get[design, tileName];
program ← Parse[object];
};
Tile Loading
tileNames: ARRAY TileType OF Rope.ROPE ← ["OToP", "RUToP", "LDToP", "LToP", "PToI", "PToRU", "PToLD", "PToL", "ORUToI", "LDToLD", "OLDToI", "ORUToL", "Tristate", "RUToRU", "ORUToLD", "LDToI", "OLDToRU", "LToI", "RUToI", "Inverter", "FlipFlop", "Program", "Program", "RAMEven", "RAMOdd"];
tileObjects:
ARRAY TileType
OF
CD.Object ←
ALL[
NIL];
nodeHighlightObjects: ARRAY NodeType OF ARRAY HighlightColor OF CD.Object;
colorToLayer:
ARRAY HighlightColor
OF
CD.Layer ← [
CD.FetchLayer[
NIL, $red],
CD.FetchLayer[
NIL, $green],
CD.FetchLayer[
NIL, $blue],
CD.FetchLayer[
NIL, $yellow],
CD.FetchLayer[
NIL, $black]];
BaseType: TYPE = {MinorArray, BoardTraces, Corner};
baseNames: ARRAY BaseType OF Rope.ROPE ← ["MinorArray", "BoardTraces", "Corner"];
baseObjects:
ARRAY BaseType
OF
CD.Object ←
ALL[
NIL];
LoadTiles:
PROC = {
design: CD.Design ← PW.OpenDesign["SoftHdw.dale"];
CDOps.SetMutability[design, readonly];
FOR index: NodeType
IN NodeType
DO
FOR currentColor: HighlightColor
IN HighlightColor
DO
nodeHighlightObjects[index][currentColor] ← NIL;
ENDLOOP;
ENDLOOP;
FOR index: TileType
IN TileType
DO
tileObjects[index] ← PW.Get[design, tileNames[index]];
FOR currentColor: HighlightColor
IN HighlightColor
DO
instances: CD.InstanceList ← NIL;
One: CDCells.InstEnumerator = {
IF CDRects.IsSimpleRect[inst.ob]
THEN {
size: Position ← CD.InterestSize[inst.ob];
instance: CD.Instance;
IF size.x>size.y THEN size.y ← highlightRectangleWidth ELSE size.x ← highlightRectangleWidth;
instance ← CDInstances.NewInst[
CDRects.CreateRect[size, colorToLayer[currentColor]],
inst.trans];
instances ← CONS[instance, instances];
};
};
[] ← CDCells.EnumerateInstances[tileObjects[index], One];
IF instances=NIL THEN nodeHighlightObjects[index][currentColor] ← CDRects.CreateRect[CD.InterestSize[tileObjects[index]], CD.shadeLayer]
ELSE {
nodeHighlightObjects[index][currentColor] ← CDCells.CreateCell[il: instances, ir: CD.InterestRect[tileObjects[index]]];
CDCells.SetSimplificationTreshhold[nodeHighlightObjects[index][currentColor], 1.0];
};
ENDLOOP;
ENDLOOP;
FOR index: BaseType
IN BaseType
DO
baseObjects[index] ← PW.Get[design, baseNames[index]];
ENDLOOP;
FOR node: NodeType
IN [Master..RightUp]
DO
length:
INT ←
SELECT node
FROM
Input, Output => 98,
LeftDown, RightUp => 96,
Long => 1, -- hack, really must create these dynamically
Master => 8,
Interchip => 8, -- hack, don't really know what it is yet
ENDCASE => ERROR;
FOR currentColor: HighlightColor
IN HighlightColor
DO
nodeHighlightObjects[node][currentColor] ← CDRects.CreateRect[[length*lambda, highlightRectangleWidth], colorToLayer[currentColor]];
ENDLOOP;
ENDLOOP;
nodeHighlightObjects[Master] ← nodeHighlightObjects[FlipFlop];
};