SoftHdwAssemblyImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Barth, July 26, 1989 5:48:45 pm PDT
DIRECTORY CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDOps, CDProperties, CDRects, CDTexts, DABasics, ExtractOps, FS, IO, PW, RefTab, Rope, SoftHdwAssembly, SoftHdwBasics, SymTab, TerminalIO, ViewerClasses;
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;
};
Parse And Print
Geometric Constants and Utilities
Number: TYPE = DABasics.Number;
lambda: Number ← 8;
grainSize: Number ← 24*lambda;
longIndent: Number ← 16*lambda;
minorArraySpacing: Number ← 2*longIndent;
interChipSize: Number ← 32*lambda;
chipSpacing: Number ← 2*interChipSize;
chipMinorArrayOffset: Position ← [16*lambda, 16*lambda];
minorArrayGrainOffset: Position ← [minorArraySpacing, minorArraySpacing];
rotationToCDOrientation: ARRAY Rotation OF CD.Orientation ← [original, rotate90X];
orientationToCDOrientation: ARRAY Orientation OF CD.Orientation ← [rotate90X, original];
MinorArrayChipSize: PROC [sizes: ArrayPosition] RETURNS [minorArraySize: Position, chipSize: Position] = {
minorArraySize ← [sizes.grain.x*grainSize+minorArraySpacing, sizes.grain.y*grainSize+minorArraySpacing];
chipSize ← [sizes.minorArray.x*minorArraySize.x+chipSpacing, sizes.minorArray.y*minorArraySize.y+chipSpacing];
};
Parse
Parse: PUBLIC PROC [object: CD.Object] RETURNS [program: Program] = {
ParseRecursive: PROC [object: CD.Object] RETURNS [program: Program ← NIL, tileType: TileType ← InputEnabled] = {
program ← NARROW[RefTab.Fetch[map, object].val];
IF program=NIL THEN {
instances: ProgramInstances ← NIL;
tiles: ArrayPositions ← NIL;
base: Position ← CD.InterestBase[object];
One: CDCells.InstEnumerator = {
subProgram: Program;
subTileType: TileType;
trans: CD.Transformation ← [CDBasics.SubPoints[CDBasics.MapPoint[CD.InterestBase[inst.ob], inst.trans], base], inst.trans.orient];
IF CDTexts.IsText[inst.ob] THEN RETURN;
[subProgram, subTileType] ← ParseRecursive[inst.ob];
IF subProgram=NIL THEN {
p: ArrayPositionRec ← TransformationToTile[minorArraySize, chipSize, trans, subTileType];
tiles ← CTI[tiles, p.type, p.orientation, p.grain, p.minorArray, p.chip];
}
ELSE {
rotation: Rotation ← SELECT trans.orient FROM
original => None,
rotate90X => Rotate90FlipX,
ENDCASE => ERROR;
chip, minorArray: Position;
[chip, minorArray] ← OffsetToProgram[minorArraySize, chipSize, trans.off];
instances ← CPI[instances, subProgram, minorArray, chip, rotation];
};
};
leafName: Rope.ROPE;
UNTIL CDCells.IsCell[object] DO
object ← CDDirectory.Expand1[object].new;
ENDLOOP;
leafName ← NARROW[CDProperties.GetObjectProp[object, $SoftHdwLeaf]];
IF leafName#NIL THEN {
FOR index: TileType IN TileType DO
IF Rope.Equal[leafName, tileNames[index]] THEN {
tileType ← index;
RETURN;
};
ENDLOOP;
ERROR;
};
[] ← CDCells.EnumerateInstances[object, One];
program ← Create[instances, tiles, MinorArray, object];
IF NOT RefTab.Store[map, object, program] THEN ERROR;
};
};
map: RefTab.Ref ← RefTab.Create[];
minorArraySize, chipSize: Position;
sizes: ArrayPosition ← NEW[ArrayPositionRec];
sizes.chip ← [1, 1];
sizes.minorArray ← [LAST[Number], LAST[Number]];
sizes.grain ← [4, 4];
[minorArraySize, chipSize] ← MinorArrayChipSize[sizes];
program ← ParseRecursive[object].program;
IF program=NIL THEN ERROR; -- an isolated tile is not a program
};
OffsetToProgram: PROC [minorArraySize, chipSize: Position, offset: Position] RETURNS [chip, minorArray, remainder: Position] = {
chip ← [0,0]; -- hack, only parse MinorArray coordinate system for now
minorArray.x ← offset.x/minorArraySize.x;
minorArray.y ← offset.y/minorArraySize.y;
offset.x ← offset.x - minorArray.x*minorArraySize.x;
offset.y ← offset.y - minorArray.y*minorArraySize.y;
remainder ← offset;
};
TransformationToTile: PROC [minorArraySize, chipSize: Position, trans: CD.Transformation, type: TileType] RETURNS [tile: ArrayPositionRec] = {
tile.type ← type;
tile.orientation ← SELECT trans.orient FROM
original => Horizontal,
rotate90X => Vertical,
ENDCASE => ERROR;
[tile.chip, tile.minorArray, trans.off] ← OffsetToProgram[minorArraySize, chipSize, trans.off];
SELECT type FROM
OToP, RUToP, LDToP, LToP, PToI, PToRU, PToLD, PToL => ERROR;
ORUToI, LDToLD, OLDToI, ORUToL, Tristate, RUToRU, ORUToLD, LDToI, OLDToRU, LToI, RUToI, Inverter, FlipFlop, ParallelInput, InputEnabled => {
trans.off ← CDBasics.SubPoints[trans.off, minorArrayGrainOffset];
tile.grain.x ← trans.off.x/grainSize;
tile.grain.y ← trans.off.y/grainSize;
trans.off ← CDBasics.SubPoints[trans.off, [tile.grain.x*grainSize, tile.grain.y*grainSize]];
SELECT TRUE FROM
tile.grain.x>=0 AND tile.grain.y>=0 => {
tile.type ← InputEnabled;
tile.orientation ← SELECT trans.off FROM
[16*lambda, 12*lambda] => Vertical,
[12*lambda, 16*lambda] => Horizontal,
ENDCASE => ERROR;
};
tile.type=ParallelInput => {
SELECT TRUE FROM
tile.grain.x<0 => {
tile.orientation ← Horizontal;
tile.grain.x ← 0;
};
tile.grain.y<0 => {
tile.orientation ← Vertical;
tile.grain.y ← 0;
};
ENDCASE => ERROR;
}
ENDCASE => SELECT tile.orientation FROM
Horizontal => tile.grain.x ← 0;
Vertical => tile.grain.y ← 0;
ENDCASE => ERROR;
};
RAMEven, RAMOdd => IF trans.off#[0,0] OR tile.orientation#Horizontal THEN ERROR;
ENDCASE => ERROR;
};
CDToArrayPosition: PUBLIC PROC [sizes: ArrayPosition, coordinates: Coordinates, mouse: Position] RETURNS [ambiguous: BOOLFALSE, position: ArrayPosition ← NIL] = {
ProbeNodeType: TYPE = {pLong, pInput, pOutput, pLeftDown, pRightUp, pInputEnabled};
probeNodeTypeToNodeType: ARRAY ProbeNodeType OF NodeType = [Long, Input, Output, LeftDown, RightUp, InputEnabled];
probePositions: ARRAY Orientation OF ARRAY ProbeNodeType OF Position = [
[[4*lambda, 0*lambda], -- Vertical Long
[16*lambda, 0*lambda], -- Vertical Input
[20*lambda, 0*lambda], -- Vertical Output
[8*lambda, 0*lambda], -- Vertical LeftDown
[12*lambda, 0*lambda], -- Vertical RightUp
[20*lambda, 16*lambda]], -- Vertical InputEnabled
[[0*lambda, 4*lambda], -- Horizontal Long
[0*lambda, 16*lambda], -- Horizontal Input
[0*lambda, 20*lambda], -- Horizontal Output
[0*lambda, 8*lambda], -- Horizontal LeftUp
[0*lambda, 12*lambda], -- Horizontal RightDown
[16*lambda, 20*lambda]]]; -- Horizontal InputEnabled
minorArraySize, chipSize: Position;
minorMouse: Position;
[minorArraySize, chipSize] ← MinorArrayChipSize[sizes];
IF coordinates#MinorArray THEN ERROR; -- nyi
position ← NEW[ArrayPositionRec];
[position.chip, position.minorArray, mouse] ← OffsetToProgram[minorArraySize, chipSize, mouse];
minorMouse ← mouse;
mouse ← CDBasics.SubPoints[mouse, minorArrayGrainOffset];
position.grain ← [mouse.x/grainSize, mouse.y/grainSize];
mouse ← CDBasics.SubPoints[mouse, [position.grain.x*grainSize, position.grain.y*grainSize]];
SELECT TRUE FROM
minorMouse.x<minorArraySpacing AND mouse.y=probePositions[Horizontal][pLong].y => {
position.type ← Long;
position.orientation ← Horizontal;
};
minorMouse.x=minorArraySize.x => FOR pnt: ProbeNodeType IN ProbeNodeType DO
IF mouse.y=probePositions[Horizontal][pnt].y THEN {
position.type ← probeNodeTypeToNodeType[pnt];
position.orientation ← Horizontal;
EXIT;
};
REPEAT FINISHED => RETURN[TRUE, NIL]
ENDLOOP;
minorMouse.y<minorArraySpacing AND mouse.x=probePositions[Vertical][pLong].x => {
position.type ← Long;
position.orientation ← Vertical;
};
minorMouse.y=(minorArraySize.y-minorArraySpacing) => FOR pnt: ProbeNodeType IN ProbeNodeType DO
IF mouse.x=probePositions[Horizontal][pnt].x THEN {
position.type ← probeNodeTypeToNodeType[pnt];
position.orientation ← Vertical;
EXIT;
};
REPEAT FINISHED => RETURN[TRUE, NIL]
ENDLOOP;
ENDCASE => {
FOR orient: Orientation IN Orientation DO
FOR pnt: ProbeNodeType IN ProbeNodeType DO
IF probePositions[orient][pnt]=mouse THEN {
position.type ← probeNodeTypeToNodeType[pnt];
position.orientation ← orient;
GOTO found;
};
ENDLOOP;
REPEAT
found => NULL;
FINISHED => RETURN[TRUE, NIL];
ENDLOOP;
};
SELECT position.type FROM
InputEnabled => NULL;
Long => SELECT position.orientation FROM
Vertical => {
position.minorArray.y ← 0;
position.grain.y ← 0;
};
Horizontal => {
position.minorArray.x ← 0;
position.grain.x ← 0;
};
ENDCASE;
Input, Output, LeftDown, RightUp => SELECT position.orientation FROM
Vertical => position.grain.y ← 0;
Horizontal => position.grain.x ← 0;
ENDCASE;
ENDCASE => ERROR;
};
Print
Print: PUBLIC PROC [sizes: ArrayPosition, program: Program] RETURNS [object: CD.Object] = {
PrintRecursive: PROC [program: Program] RETURNS [object: CD.Object] = {
object ← NARROW[RefTab.Fetch[map, program].val];
IF object=NIL THEN {
ConsInstance: PROC [object: CD.Object, trans: CD.Transformation] = {
trans.off ← CDBasics.SubPoints[trans.off, CDBasics.OrientedSize[CD.InterestBase[object], trans.orient]];
il ← CONS[CDInstances.NewInst[object, trans], il];
};
il: CD.InstanceList ← NIL;
size: Position ← Size[program];
multiplier: Position ← SELECT program.coordinates FROM
Grain => ERROR,
MinorArray => minorArraySize,
Chip => chipSize,
ENDCASE => ERROR;
upperRight: Position ← [size.x*multiplier.x, size.y*multiplier.y];
FOR tiles: ArrayPositions ← program.tiles, tiles.rest UNTIL tiles=NIL DO
tile: ArrayPosition ← tiles.first;
subObject: CD.Object ← tileObjects[tile.type];
subTrans: CD.Transformation ← TileToTransformation[minorArraySize, chipSize, tile];
ConsInstance[subObject, subTrans];
ENDLOOP;
FOR instances: ProgramInstances ← program.instances, instances.rest UNTIL instances=NIL DO
instance: ProgramInstance ← instances.first;
subObject: CD.Object ← PrintRecursive[instance.program];
subTrans: CD.Transformation ← ProgramToTransformation[minorArraySize, chipSize, instance.chip, instance.minorArray];
subTrans.orient ← rotationToCDOrientation[instance.rotation];
IF instance.program.coordinates=MinorArray AND program.coordinates=Chip THEN subTrans.off ← CDBasics.AddPoints[subTrans.off, chipMinorArrayOffset];
Really need to adjust for any shift in coordinate systems.
ConsInstance[subObject, subTrans];
ENDLOOP;
IF program.coordinates=MinorArray THEN upperRight ← CDBasics.AddPoints[upperRight, [minorArraySpacing, minorArraySpacing]];
object ← PW.CreateCell[il, [0, 0, upperRight.x, upperRight.y]];
IF NOT RefTab.Store[map, program, object] THEN ERROR;
};
};
map: RefTab.Ref ← RefTab.Create[];
minorArraySize, chipSize: Position;
[minorArraySize, chipSize] ← MinorArrayChipSize[sizes];
IF sizes.grain # [4,4] THEN ERROR;
object ← PrintRecursive[program];
};
PrintAndDraw: PUBLIC PROC [sizes: ArrayPosition, program: Program] RETURNS [design: CD.Design] = {
il: CD.InstanceList ← NIL;
programObject: CD.Object ← Print[sizes, program];
arrayObject: CD.Object ← CreateArray[sizes, program];
programInterestBase: Position ← CD.InterestBase[programObject];
arrayInterestBase: Position ← CD.InterestBase[arrayObject];
il ← CONS[CDInstances.NewInst[programObject, [[-programInterestBase.x, -programInterestBase.y], original]], il];
il ← CONS[CDInstances.NewInst[arrayObject, [[-arrayInterestBase.x, -arrayInterestBase.y], original]], il];
design ← PW.Draw[PW.CreateCell[il]];
};
ProgramToTransformation: PROC [minorArraySize, chipSize: Position, chip: Position, minorArray: Position] RETURNS [trans: CD.Transformation ← [[0, 0], original]] = {
trans.off.x ← chip.x*chipSize.x;
trans.off.y ← chip.y*chipSize.y;
trans.off.x ← trans.off.x + minorArray.x*minorArraySize.x;
trans.off.y ← trans.off.y + minorArray.y*minorArraySize.y;
};
TileToTransformation : PROC [minorArraySize, chipSize: Position, tile: ArrayPosition] RETURNS [trans: CD.Transformation ← [[0, 0], original]] = {
typeOffset: Position ← SELECT tile.type FROM
OToP, RUToP, LDToP, LToP, PToI, PToRU, PToLD, PToL => ERROR,
ORUToI, LDToLD, OLDToI, ORUToL, Tristate, RUToRU, ORUToLD, LDToI, OLDToRU, LToI, RUToI, Inverter, FlipFlop, Master => [0, 32],
ParallelInput => [28, 48],
InputEnabled => [44, 48],
RAMEven, RAMOdd => [0, 0],
Input => [30, 48],
Output => [30, 52],
LeftDown => [32, 40],
RightUp => [32, 44],
Long => [16, 36],
ENDCASE => ERROR;
typeOffset ← [typeOffset.x*lambda, typeOffset.y*lambda];
trans ← ProgramToTransformation[minorArraySize, chipSize, tile.chip, tile.minorArray];
trans.orient ← orientationToCDOrientation[tile.orientation];
trans.off.x ← trans.off.x + tile.grain.x*grainSize;
trans.off.y ← trans.off.y + tile.grain.y*grainSize;
trans.off ← CDBasics.AddPoints[trans.off, SELECT tile.orientation FROM
Vertical => [typeOffset.y, typeOffset.x],
Horizontal => [typeOffset.x, typeOffset.y],
ENDCASE => ERROR];
};
CreateArray: PROC [sizes: ArrayPosition, program: Program] RETURNS [object: CD.Object] = {
minorArray: CD.Object ← baseObjects[MinorArray];
size: Position ← Size[program];
SELECT program.coordinates FROM
Grain => ERROR; -- should paint inside of minor array
MinorArray => {
should construct minor array from more primitive components
inner: CD.Object ← PW.Array[minorArray, size.x, size.y];
ir: CD.Rect ← CDBasics.Extend[CD.InterestRect[inner], 16*8];
object ← PW.CreateCell[LIST[CDInstances.NewInst[inner, [[0,0],original]]], ir];
};
Chip => {
inner: CD.Object ← PW.Array[minorArray, sizes.minorArray.x, sizes.minorArray.y];
boardTraces: CD.Object ← baseObjects[BoardTraces];
boardTracesSize: DABasics.Position ← CD.InterestSize[boardTraces];
corner: CD.Object ← baseObjects[Corner];
side: CD.Object ← PW.ArrayY[boardTraces, sizes.minorArray.y];
middle: CD.Object ← PW.AbutX[PW.FlipX[side], inner, side];
top: CD.Object ← PW.AbutX[corner, PW.ArrayX[PW.FlipX[PW.Rot90[boardTraces]], sizes.minorArray.x], corner];
bottom: CD.Object ← PW.AbutX[corner, PW.ArrayX[PW.FlipY[PW.FlipX[PW.Rot90[boardTraces]]], sizes.minorArray.x], corner];
chip: CD.Object ← PW.AbutY[bottom, middle, top];
object ← PW.Array[chip, size.x, size.y]
};
ENDCASE => ERROR;
};
Stats: PUBLIC PROC [program: Program] = {
RecursiveStats: PROC [program: Program] = {
FOR instances: ProgramInstances ← program.instances, instances.rest UNTIL instances=NIL DO
instance: ProgramInstance ← instances.first;
RecursiveStats[instance.program];
ENDLOOP;
FOR tiles: ArrayPositions ← program.tiles, tiles.rest UNTIL tiles=NIL DO
tile: ArrayPosition ← tiles.first;
IF tile.type=FlipFlop THEN {
TerminalIO.PutRope["\n"];
TerminalIO.PutRope[SoftHdwBasics.ArrayPositionToRope[tile]];
};
ENDLOOP;
};
RecursiveStats[program];
};
Pickle: PUBLIC PROC [program: Program, fileName: Rope.ROPE] = {
RecursivePickle: PROC [program: Program] = {
id: Rope.ROPENARROW[RefTab.Fetch[map, program].val];
IF id=NIL THEN {
size: INT ← 0;
id ← IO.PutFR["P%g", IO.int[nextID]];
nextID ← nextID + 1;
IF NOT RefTab.Insert[map, program, id] THEN ERROR;
IO.PutF[stream,"%g ", IO.rope[id]];
FOR instances: ProgramInstances ← program.instances, instances.rest UNTIL instances=NIL DO
size ← size + 1;
ENDLOOP;
IO.PutF[stream, "%g ", IO.int[size]];
FOR instances: ProgramInstances ← program.instances, instances.rest UNTIL instances=NIL DO
instance: ProgramInstance ← instances.first;
RecursivePickle[instance.program];
IO.PutF[stream, "%g ", IO.rope[SELECT instance.rotation FROM
None => "N",
Rotate90FlipX => "R",
ENDCASE => ERROR]];
PutPosition[instance.chip];
PutPosition[instance.minorArray];
ENDLOOP;
size ← 0;
FOR tiles: ArrayPositions ← program.tiles, tiles.rest UNTIL tiles=NIL DO
size ← size + 1;
ENDLOOP;
IO.PutF[stream, "%g ", IO.int[size]];
FOR tiles: ArrayPositions ← program.tiles, tiles.rest UNTIL tiles=NIL DO
tile: ArrayPosition ← tiles.first;
IO.PutF[stream, """%g"" ", IO.rope[SoftHdwBasics.ArrayPositionToRope[tile]]]
ENDLOOP;
IO.PutF[stream, "%g ", IO.rope[SELECT program.coordinates FROM
Grain => "G",
MinorArray => "M",
Chip => "C",
ENDCASE => ERROR]];
}
ELSE IO.PutF[stream,"%g ", IO.rope[id]];
};
PutPosition: PROC [position: Position] = {
IO.PutF[stream, "%g %g ", IO.int[position.x], IO.int[position.y]];
};
stream: IO.STREAMFS.StreamOpen[fileName, $create];
map: RefTab.Ref ← RefTab.Create[];
nextID: INT ← 0;
RecursivePickle[program];
IO.Close[stream];
};
Unpickle: PUBLIC PROC [fileName: Rope.ROPE] RETURNS [program: Program] = {
RecursiveUnpickle: PROC RETURNS [program: Program] = {
id: Rope.ROPEIO.GetID[stream];
IF (program ← NARROW[SymTab.Fetch[map, id].val])=NIL THEN {
size: INT ← 0;
program ← NEW[ProgramRec];
IF NOT SymTab.Insert[map, id, program] THEN ERROR;
size ← IO.GetInt[stream];
THROUGH [0..size) DO
instance: ProgramInstance ← NEW[ProgramInstanceRec];
instance.program ← RecursiveUnpickle[];
id ← IO.GetID[stream];
instance.rotation ← SELECT TRUE FROM
Rope.Equal[id, "N"] => None,
Rope.Equal[id, "R"] => Rotate90FlipX,
ENDCASE => ERROR;
instance.chip ← GetPosition[];
instance.minorArray ← GetPosition[];
program.instances ← CONS[instance, program.instances];
ENDLOOP;
size ← IO.GetInt[stream];
THROUGH [0..size) DO
program.tiles ← CONS[SoftHdwBasics.RopeToArrayPosition[ IO.GetRopeLiteral[stream]], program.tiles];
ENDLOOP;
id ← IO.GetID[stream];
program.coordinates ← SELECT TRUE FROM
Rope.Equal[id, "G"] => Grain,
Rope.Equal[id, "M"] => MinorArray,
Rope.Equal[id, "C"] => Chip,
ENDCASE => ERROR;
};
};
GetPosition: PROC RETURNS[position: Position] = {
position ← [IO.GetInt[stream], IO.GetInt[stream]];
};
stream: IO.STREAMFS.StreamOpen[fileName, $read];
map: SymTab.Ref ← SymTab.Create[];
program ← RecursiveUnpickle[];
IO.Close[stream];
};
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.ROPENIL] = {
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: INTSELECT 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];
};
LoadTiles[];
END.