SoftHdwBasicsImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Barth, June 28, 1989 3:27:01 pm PDT
DIRECTORY Arpa, ArpaName, IO, PBasics, RefTab, Rope, SoftHdwBasics, SunAuthUnix, SunPMap, SunPMapClient, SunRPC, SunRPCAuth, UserCredentials;
SoftHdwBasicsImpl: CEDAR PROGRAM
IMPORTS ArpaName, IO, PBasics, RefTab, Rope, SunAuthUnix, SunPMapClient, SunRPC, SunRPCAuth, UserCredentials
EXPORTS SoftHdwBasics
= BEGIN OPEN SoftHdwBasics;
timeout: CARD = 2000;
retry: CARD = 5;
host: Rope.ROPE ← "cmsun";
program: INT = 555002207;
version : INT = 1;
CREATEBASE: INT = 1;
INITIALIZE: INT = 2;
FETCH: INT = 3;
STORE: INT = 4;
MASTERTOSLAVE: INT = 5;
RELAX: INT = 6;
SAMPLE: INT = 7;
nodeNames: PUBLIC ARRAY NodeType OF Rope.ROPE ← ["OToP", "RUToP", "LDToP", "LToP", "PToI", "PToRU", "PToLD", "PToL", "ORUToI", "LDToLD", "OLDToI", "ORUToL", "Tristate", "RUToRU", "ORUToLD", "LDToI", "OLDToRU", "LToI", "RUToI", "Inverter", "FlipFlop", "ParallelInput", "InputEnabled", "RAMEven", "RAMOdd", "Master", "Input", "Interchip", "Long", "Output", "LeftDown", "RightUp"];
orientationNames: PUBLIC ARRAY Orientation OF Rope.ROPE ← ["Vertical", "Horizontal"];
SunRPC Stubs
CreateBase: PUBLIC PROC [sizes: ArrayPosition, useConnectionMachine: BOOLFALSE] RETURNS [array: ArrayBase] = {
array ← NEW[ArrayBaseRec];
array.sizes ← sizes;
array.useConnectionMachine ← useConnectionMachine;
IF useConnectionMachine THEN {
addr: Arpa.Address; status: ArpaName.ReplyStatus;
myName, myPassword: Rope.ROPE;
port: CARD ← 0;
[addr, status] ← ArpaName.NameToAddress[host];
IF status#ok THEN ERROR;
array.h ← SunRPC.Create[addr, PBasics.HFromCard16[SunPMap.udpPort]];
[myName, myPassword] ← UserCredentials.Get[];
array.c ← SunRPCAuth.Initiate[SunRPCAuth.nullFlavor, SunAuthUnix.FixNameForUnix[myName], myPassword];
port ← SunPMapClient.GetPort[array.h, array.c, program, version, SunPMap.ipProtocolUDP];
IF port = 0 THEN ERROR;
array.h ← SunRPC.SetRemote[array.h, addr, PBasics.HFromCard16[PBasics.LowHalf[port]]];
SunRPC.StartCall[array.h, array.c, program, version, CREATEBASE];
PutArrayPosition[array.h, sizes];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
array.id ← SunRPC.GetCard32[array.h];
SunRPC.ReleaseReply[array.h];
}
ELSE CreateBaseState[array];
};
Initialize: PUBLIC PROC [array: ArrayBase] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, INITIALIZE];
SunRPC.PutCard32[array.h, array.id];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
[] ← SunRPC.GetCard32[array.h]; -- throw away bogus return value to make RPC work
SunRPC.ReleaseReply[array.h];
}
ELSE InitializeState[array];
};
Fetch: PUBLIC PROC [array: ArrayBase, bit: ArrayPosition, time: INT ← -1] RETURNS [value: BOOL] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, FETCH];
SunRPC.PutCard32[array.h, array.id];
PutArrayPosition[array.h, bit];
SunRPC.PutCard32[array.h, time];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
value ← GetBool[array.h];
SunRPC.ReleaseReply[array.h];
}
ELSE value ← FetchState[array, bit, time];
};
Store: PUBLIC PROC [array: ArrayBase, bit: ArrayPosition, value: BOOL] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, STORE];
SunRPC.PutCard32[array.h, array.id];
PutArrayPosition[array.h, bit];
PutBool[array.h, value];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
[] ← SunRPC.GetCard32[array.h]; -- throw away bogus return value to make RPC work
SunRPC.ReleaseReply[array.h];
}
ELSE StoreState[array, bit, value];
};
MasterToSlave: PUBLIC PROC [array: ArrayBase] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, MASTERTOSLAVE];
SunRPC.PutCard32[array.h, array.id];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
[] ← SunRPC.GetCard32[array.h]; -- throw away bogus return value to make RPC work
SunRPC.ReleaseReply[array.h];
}
ELSE MasterToSlaveState[array];
};
Relax: PUBLIC PROC [array: ArrayBase] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, RELAX];
SunRPC.PutCard32[array.h, array.id];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
[] ← SunRPC.GetCard32[array.h]; -- throw away bogus return value to make RPC work
SunRPC.ReleaseReply[array.h];
}
ELSE RelaxState[array];
};
Sample: PUBLIC PROC [array: ArrayBase] = {
IF array.useConnectionMachine THEN {
SunRPC.StartCall[array.h, array.c, program, version, SAMPLE];
SunRPC.PutCard32[array.h, array.id];
[] ← SunRPC.SendCallAndReceiveReply[array.h, timeout, retry];
[] ← SunRPC.GetCard32[array.h]; -- throw away bogus return value to make RPC work
SunRPC.ReleaseReply[array.h];
}
ELSE SampleState[array];
};
PutArrayPosition: PROC [h: SunRPC.Handle, position: ArrayPosition] = {
SunRPC.PutCard32[h, ORD[position.type]];
SunRPC.PutCard32[h, ORD[position.orientation]];
PutPosition[h, position.chip];
PutPosition[h, position.minorArray];
PutPosition[h, position.grain];
};
PutPosition: PROC [h: SunRPC.Handle, position: Position] = {
SunRPC.PutInt32[h, position.x];
SunRPC.PutInt32[h, position.y];
};
PutBool: PROC [h: SunRPC.Handle, value: BOOL] = {
SunRPC.PutInt32[h, IF value THEN 1 ELSE 0];
};
GetBool: PROC [h: SunRPC.Handle] RETURNS [value: BOOL] = {
value ← IF SunRPC.GetCard32[h]=0 THEN FALSE ELSE TRUE;
};
State
CreateBaseState: PROC [array: ArrayBase] = {
CreateGrain: EnumeratePositionsProc = {
positionRef: ArrayPosition ← NEW[ArrayPositionRec];
grain: Grain ← NEW[GrainRec[SELECT position.orientation FROM
Vertical => array.sizes.grain.x,
Horizontal => array.sizes.grain.y,
ENDCASE => ERROR]];
grain.vertical ← position.orientation=Vertical;
ScheduleGrain[array, grain];
positionRef^ ← position^;
grain.key ← positionRef;
IF NOT RefTab.Store[map, positionRef, grain] THEN ERROR;
};
CreateLongLine: EnumeratePositionsProc = {
positionRef: ArrayPosition ← NEW[ArrayPositionRec];
longLine: LongLine ← NEW[LongLineRec[SELECT position.orientation FROM
Vertical => array.sizes.minorArray.y,
Horizontal => array.sizes.minorArray.x,
ENDCASE => ERROR]];
positionRef^ ← position^;
longLine.key ← positionRef;
IF NOT RefTab.Store[map, positionRef, longLine] THEN ERROR;
};
CreateMinorArray: EnumeratePositionsProc = {
positionRef: ArrayPosition ← NEW[ArrayPositionRec];
minor: MinorArray ← NEW[MinorArrayRec];
minor.vertical ← NEW[GrainSeqRec[array.sizes.grain.x]];
minor.horizontal ← NEW[GrainSeqRec[array.sizes.grain.y]];
ScheduleMinorArray[array, minor];
positionRef^ ← position^;
minor.key ← positionRef;
IF NOT RefTab.Store[map, positionRef, minor] THEN ERROR;
};
FillGrainNeighbors: EnumeratePositionsProc = {
grain: Grain ← NARROW[RefTab.Fetch[map, position].val];
temp: ArrayPositionRec ← position^;
IF position.orientation=Vertical THEN {
IF position.minorArray.y=0 THEN {
position.minorArray.y ← array.sizes.minorArray.y-1;
position.chip.y ← position.chip.y-1;
}
ELSE position.minorArray.y ← position.minorArray.y-1;
}
ELSE {
IF position.minorArray.x=0 THEN {
position.minorArray.x ← array.sizes.minorArray.x-1;
position.chip.x ← position.chip.x-1;
}
ELSE position.minorArray.x ← position.minorArray.x-1;
};
grain.leftDownGrain ← NARROW[RefTab.Fetch[map, position].val];
position^ ← temp;
IF position.orientation=Vertical THEN {
IF position.minorArray.y=array.sizes.minorArray.y-1 THEN {
position.minorArray.y ← 0;
position.chip.y ← position.chip.y+1;
}
ELSE position.minorArray.y ← position.minorArray.y+1;
}
ELSE {
IF position.minorArray.x=array.sizes.minorArray.x-1 THEN {
position.minorArray.x ← 0;
position.chip.x ← position.chip.x+1;
}
ELSE position.minorArray.x ← position.minorArray.x+1;
};
grain.rightUpGrain ← NARROW[RefTab.Fetch[map, position].val];
position^ ← temp;
SELECT position.orientation FROM
Vertical => {
position.orientation ← Horizontal;
position.grain.x ← 0;
};
Horizontal => {
position.orientation ← Vertical;
position.grain.y ← 0;
};
ENDCASE => ERROR;
FOR grainIndex: INT IN [0..grain.size) DO
SELECT position.orientation FROM
Vertical => position.grain.x ← grainIndex;
Horizontal => position.grain.y ← grainIndex;
ENDCASE => ERROR;
grain.perpendicularGrains[grainIndex].inputEnabled ← FALSE;
grain.perpendicularGrains[grainIndex].grain ← NARROW[RefTab.Fetch[map, position].val];
ENDLOOP;
position^ ← temp;
position.type ← Long;
SELECT position.orientation FROM
Vertical => {
position.minorArray.y ← 0;
position.grain.y ← 0;
};
Horizontal => {
position.minorArray.x ← 0;
position.grain.x ← 0;
};
ENDCASE => ERROR;
grain.longLine ← NARROW[RefTab.Fetch[map, position].val];
IF grain.longLine=NIL THEN ERROR;
FOR index: CARDINAL IN [0..grain.longLine.size) DO
IF grain.longLine.grains[index]=NIL THEN {
grain.longLine.grains[index] ← grain;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
position^ ← temp;
position.type ← RAMEven;
position.orientation ← Vertical;
position.grain.x ← 0;
position.grain.y ← 0;
grain.minorArray ← NARROW[RefTab.Fetch[map, position].val];
position^ ← temp;
SELECT position.orientation FROM
Vertical => grain.minorArray.vertical[position.grain.x] ← grain;
Horizontal => grain.minorArray.horizontal[position.grain.y] ← grain;
ENDCASE => ERROR;
};
position: ArrayPosition ← NEW[ArrayPositionRec];
map: RefTab.Ref ← RefTab.Create[equal: ArrayPositionEqual, hash: ArrayPositionHash];
array.state ← NEW[ArrayBaseStateRec];
array.state.positionToEntity ← map;
EnumerateGrains[array.sizes, position, CreateGrain];
EnumerateLongLines[array.sizes, position, CreateLongLine];
EnumerateMinorArrays[array.sizes, position, CreateMinorArray];
EnumerateGrains[array.sizes, position, FillGrainNeighbors];
};
EnumeratePositionsProc: TYPE = PROC [position: ArrayPosition];
EnumerateGrains: PROC [sizes: ArrayPosition, position: ArrayPosition, call: EnumeratePositionsProc] = {
position.type ← Output;
FOR chipXIndex: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipXIndex;
FOR chipYIndex: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipYIndex;
FOR minorXIndex: INT IN [0..sizes.minorArray.x) DO
position.minorArray.x ← minorXIndex;
FOR minorYIndex: INT IN [0..sizes.minorArray.y) DO
position.minorArray.y ← minorYIndex;
position.grain.y ← 0;
position.orientation ← Vertical;
FOR grainXIndex: INT IN [0..sizes.grain.x) DO
position.grain.x ← grainXIndex;
call[position];
ENDLOOP;
position.grain.x ← 0;
position.orientation ← Horizontal;
FOR grainYIndex: INT IN [0..sizes.grain.y) DO
position.grain.y ← grainYIndex;
call[position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
EnumerateLongLines: PROC [sizes: ArrayPosition, position: ArrayPosition, call: EnumeratePositionsProc] = {
position.type ← Long;
FOR chipXIndex: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipXIndex;
FOR chipYIndex: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipYIndex;
position.orientation ← Vertical;
position.minorArray.y ← 0;
position.grain.y ← 0;
FOR minorXIndex: INT IN [0..sizes.minorArray.x) DO
position.minorArray.x ← minorXIndex;
FOR grainXIndex: INT IN [0..sizes.grain.x) DO
position.grain.x ← grainXIndex;
call[position];
ENDLOOP;
ENDLOOP;
position.orientation ← Horizontal;
position.minorArray.x ← 0;
position.grain.x ← 0;
FOR minorYIndex: INT IN [0..sizes.minorArray.y) DO
position.minorArray.y ← minorYIndex;
FOR grainYIndex: INT IN [0..sizes.grain.y) DO
position.grain.y ← grainYIndex;
call[position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
EnumerateMinorArrays: PROC [sizes: ArrayPosition, position: ArrayPosition, call: EnumeratePositionsProc] = {
position.type ← RAMEven;
position.orientation ← Vertical;
position.grain.x ← 0;
position.grain.y ← 0;
FOR chipXIndex: INT IN [0..sizes.chip.x) DO
position.chip.x ← chipXIndex;
FOR chipYIndex: INT IN [0..sizes.chip.y) DO
position.chip.y ← chipYIndex;
FOR minorXIndex: INT IN [0..sizes.minorArray.x) DO
position.minorArray.x ← minorXIndex;
FOR minorYIndex: INT IN [0..sizes.minorArray.y) DO
position.minorArray.y ← minorYIndex;
call[position];
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
ArrayPositionToRope: PUBLIC PROC [position: ArrayPosition] RETURNS [rope: Rope.ROPE] = {
rope ← IO.PutFR["%g %g", IO.rope[orientationNames[position.orientation]], IO.rope[nodeNames[position.type]]];
rope ← Rope.Cat[rope, IO.PutFR[" [%g, %g]", IO.int[position.chip.x], IO.int[position.chip.y]]];
rope ← Rope.Cat[rope, (SELECT TRUE FROM
position.type#Long => IO.PutFR[" [%g, %g]", IO.int[position.minorArray.x], IO.int[position.minorArray.y]],
position.orientation=Vertical => IO.PutFR[" [%g, -]", IO.int[position.minorArray.x]],
ENDCASE => IO.PutFR[" [-, %g]", IO.int[position.minorArray.y]])];
rope ← Rope.Cat[rope, (SELECT TRUE FROM
position.type=InputEnabled => IO.PutFR[" [%g, %g]", IO.int[position.grain.x], IO.int[position.grain.y]],
position.orientation=Vertical => IO.PutFR[" [%g, -]", IO.int[position.grain.x]],
ENDCASE => IO.PutFR[" [-, %g]", IO.int[position.grain.y]])];
};
RopeToArrayPosition: PUBLIC PROC [rope: Rope.ROPE] RETURNS [position: ArrayPosition] = {
GetPosition: PROC [firstDash, secondDash: BOOLFALSE] RETURNS [pos: Position ← [0, 0]] = {
token ← IO.GetCedarTokenRope[s].token;
IF NOT Rope.Equal[token, "["] THEN ERROR;
IF firstDash THEN {
token ← IO.GetCedarTokenRope[s].token;
IF NOT Rope.Equal[token, "-"] THEN ERROR;
}
ELSE pos.x ← IO.GetInt[s];
token ← IO.GetCedarTokenRope[s].token;
IF NOT Rope.Equal[token, ","] THEN ERROR;
IF secondDash THEN {
token ← IO.GetCedarTokenRope[s].token;
IF NOT Rope.Equal[token, "-"] THEN ERROR;
}
ELSE pos.y ← IO.GetInt[s];
token ← IO.GetCedarTokenRope[s].token;
IF NOT Rope.Equal[token, "]"] THEN ERROR;
};
s: IO.STREAMIO.RIS[rope];
token: Rope.ROPEIO.GetID[s];
position ← NEW[ArrayPositionRec];
FOR orientation: Orientation IN Orientation DO
IF Rope.Equal[token, orientationNames[orientation]] THEN {
position.orientation ← orientation;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
token ← IO.GetID[s];
FOR type: NodeType IN NodeType DO
IF Rope.Equal[token, nodeNames[type]] THEN {
position.type ← type;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
position.chip ← GetPosition[];
position.minorArray ← GetPosition[firstDash: position.type=Long AND position.orientation=Horizontal, secondDash: position.type=Long AND position.orientation=Vertical];
position.grain ← GetPosition[firstDash: position.type#InputEnabled AND position.orientation=Horizontal, secondDash: position.type#InputEnabled AND position.orientation=Vertical];
};
ArrayPositionEqual: PUBLIC RefTab.EqualProc = {
p1: ArrayPosition ← NARROW[key1];
p2: ArrayPosition ← NARROW[key2];
RETURN[p1^=p2^];
};
ArrayPositionHash: PUBLIC RefTab.HashProc = {
FoldPair: PROC [pair: Position] = {
FoldOne[pair.x];
FoldOne[pair.y];
};
FoldOne: PROC [one: INT] = {
Fold[Basics.HighHalf[one]];
Fold[Basics.LowHalf[one]];
};
Fold: PROC [sixteenBits: CARDINAL] = {
hash ← Basics.BITXOR[hash, sixteenBits];
};
p: ArrayPosition ← NARROW[key];
hash: CARDINALORD[p.type];
hash ← 2*hash + (SELECT p.orientation FROM
Vertical => 0,
Horizontal => 1,
ENDCASE => ERROR);
FoldPair[p.chip];
FoldPair[p.minorArray];
FoldPair[p.grain];
RETURN[hash];
};
InitializeState: PROC [array: ArrayBase] = {
GrainInit: RefTab.EachPairAction = {
IF ISTYPE[val, Grain] THEN {
grain: Grain ← NARROW[val];
grain.scheduled ← FALSE;
ScheduleGrain[array, grain];
grain.leftDown ← FALSE;
grain.rightUp ← FALSE;
grain.input ← FALSE;
grain.output ← FALSE;
grain.longLine.long ← FALSE;
grain.flipFlop ← FALSE;
grain.master ← FALSE;
grain.invert ← FALSE;
grain.parallelInput ← FALSE;
FOR index: CARDINAL IN [0..grain.size) DO
grain.perpendicularGrains[index].inputEnabled ← FALSE;
ENDLOOP;
};
};
array.state.scheduledGrains ← NIL;
[] ← RefTab.Pairs[array.state.positionToEntity, GrainInit];
};
FetchState: PROC [array: ArrayBase, bit: ArrayPosition, time: INT ← -1] RETURNS [value: BOOL] = {
FetchGrain: PROC RETURNS [grain: Grain] = {
temp: ArrayPositionRec ← bit^;
bit.type ← Output;
grain ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
bit^ ← temp;
};
SELECT bit.type FROM
OToP, RUToP, LDToP, LToP, PToI, PToRU, PToLD, PToL, Interchip => ERROR;
ORUToI, OLDToI, LDToI, LToI, RUToI, LDToLD, ORUToLD, RUToRU, OLDToRU, ORUToL, ParallelInput, FlipFlop, Master, Inverter, Input, Output, LeftDown, RightUp => {
grain: Grain ← FetchGrain[];
value ← SELECT bit.type FROM
ORUToI => grain.ORUToI,
OLDToI => grain.OLDToI,
LDToI => grain.LDToI,
LToI => grain.LToI,
RUToI => grain.RUToI,
LDToLD => grain.LDToLD,
ORUToLD => grain.ORUToLD,
RUToRU => grain.RUToRU,
OLDToRU => grain.OLDToRU,
ORUToL => grain.ORUToL,
Tristate => grain.Tristate,
ParallelInput => grain.parallelInput,
FlipFlop => grain.flipFlop,
Master => grain.master,
Inverter => grain.invert,
Input => grain.input,
Output => grain.output,
LeftDown => grain.leftDown,
RightUp => grain.rightUp,
ENDCASE => ERROR;
};
Long => {
longLine: LongLine ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
value ← longLine.long;
};
InputEnabled => {
grain: Grain;
index: CARDINAL;
SELECT bit.orientation FROM
Vertical => {
index ← bit.grain.y;
bit.grain.y ← 0;
grain ← FetchGrain[];
bit.grain.y ← index;
};
Horizontal => {
index ← bit.grain.x;
bit.grain.x ← 0;
grain ← FetchGrain[];
bit.grain.x ← index;
};
ENDCASE => ERROR;
value ← grain.perpendicularGrains[index].inputEnabled;
};
RAMEven, RAMOdd => {
minor: MinorArray;
temp: ArrayPositionRec ← bit^;
bit.type ← RAMEven;
minor ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
bit^ ← temp;
value ← SELECT bit.type FROM
RAMEven => minor.RAMEven,
RAMOdd => minor.RAMOdd,
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
StoreState: PROC [array: ArrayBase, bit: ArrayPosition, value: BOOL] = {
FetchGrain: PROC RETURNS [grain: Grain] = {
temp: ArrayPositionRec ← bit^;
bit.type ← Output;
grain ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
bit^ ← temp;
};
DieIfMoreThanOne: PROC [a, b, c, d, e: BOOLFALSE] = {
count: CARDINAL ← 0;
IF a THEN count ← count + 1;
IF b THEN count ← count + 1;
IF c THEN count ← count + 1;
IF d THEN count ← count + 1;
IF e THEN count ← count + 1;
IF count>1 THEN ERROR;
};
SELECT bit.type FROM
OToP, RUToP, LDToP, LToP, PToI, PToRU, PToLD, PToL, Interchip => ERROR;
ORUToI, OLDToI, LDToI, LToI, RUToI, LDToLD, ORUToLD, RUToRU, OLDToRU, ORUToL, ParallelInput, FlipFlop, Master, Inverter, Input, Output, LeftDown, RightUp => {
grain: Grain ← FetchGrain[];
SELECT bit.type FROM
ORUToI => grain.ORUToI ← value;
OLDToI => grain.OLDToI ← value;
LDToI => grain.LDToI ← value;
LToI => grain.LToI ← value;
RUToI => grain.RUToI ← value;
LDToLD => grain.LDToLD ← value;
ORUToLD => grain.ORUToLD ← value;
RUToRU => grain.RUToRU ← value;
OLDToRU => grain.OLDToRU ← value;
ORUToL => grain.ORUToL ← value;
Tristate => grain.Tristate ← value;
ParallelInput => grain.parallelInput ← value;
FlipFlop => grain.flipFlop ← value;
Master => grain.master ← value;
Inverter => grain.invert ← value;
Input => grain.input ← value;
Output => grain.output ← value;
LeftDown => grain.leftDown ← value;
RightUp => grain.rightUp ← value;
ENDCASE => ERROR;
DieIfMoreThanOne[grain.ORUToI, grain.OLDToI, grain.LDToI, grain.LToI, grain.RUToI];
grain.inputSelect ← SELECT TRUE FROM
grain.ORUToI => oru,
grain.OLDToI => old,
grain.LDToI => ld,
grain.LToI => l,
grain.RUToI => ru,
ENDCASE => none;
DieIfMoreThanOne[grain.ORUToL, grain.Tristate];
grain.longControl ← SELECT TRUE FROM
grain.ORUToL => on,
grain.Tristate => old,
ENDCASE => off;
DieIfMoreThanOne[grain.LDToLD, grain.ORUToLD];
grain.leftDownSelectLeftDown ← grain.LDToLD;
DieIfMoreThanOne[grain.RUToRU, grain.OLDToRU];
grain.rightUpSelectRightUp ← grain.RUToRU;
DieIfMoreThanOne[grain.flipFlop, grain.minorArray.RAMEven OR grain.minorArray.RAMOdd];
ScheduleGrain[array, grain];
ScheduleGrain[array, grain.leftDownGrain];
ScheduleGrain[array, grain.rightUpGrain];
SchedulePerpendicularGrains[array, grain];
};
Long => {
longLine: LongLine ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
IF longLine.long#value THEN ScheduleLong[array, longLine, value];
};
InputEnabled => {
grain: Grain;
index: CARDINAL;
SELECT bit.orientation FROM
Vertical => {
index ← bit.grain.y;
bit.grain.y ← 0;
grain ← FetchGrain[];
bit.grain.y ← index;
};
Horizontal => {
index ← bit.grain.x;
bit.grain.x ← 0;
grain ← FetchGrain[];
bit.grain.x ← index;
};
ENDCASE => ERROR;
grain.perpendicularGrains[index].inputEnabled ← value;
ScheduleGrain[array, grain];
};
RAMEven, RAMOdd => {
minor: MinorArray;
temp: ArrayPositionRec ← bit^;
bit.type ← RAMEven;
bit.orientation ← Vertical;
minor ← NARROW[RefTab.Fetch[array.state.positionToEntity, bit].val];
bit^ ← temp;
SELECT bit.type FROM
RAMEven => minor.RAMEven ← value;
RAMOdd => minor.RAMOdd ← value;
ENDCASE => ERROR;
ScheduleMinorArray[array, minor];
FOR index: CARDINAL IN [0..4) DO
DieIfMoreThanOne[minor.vertical[index].flipFlop, minor.RAMEven OR minor.RAMOdd];
DieIfMoreThanOne[minor.horizontal[index].flipFlop, minor.RAMEven OR minor.RAMOdd];
ENDLOOP;
};
ENDCASE => ERROR;
};
MasterToSlaveState: PROC [array: ArrayBase] = {
GrainMasterToSlave: RefTab.EachPairAction = {
WITH val SELECT FROM
grain: Grain => {
IF grain.flipFlop THEN {
master: BOOLIF grain.invert THEN NOT grain.master ELSE grain.master;
IF master # grain.input THEN {
grain.input ← master;
ScheduleGrain[array, grain];
SchedulePerpendicularGrains[array, grain];
};
};
};
minor: MinorArray => {
we: BOOLSELECT TRUE FROM
minor.RAMEven => minor.horizontal[3].leftDown,
minor.RAMOdd => NOT minor.horizontal[3].leftDown,
ENDCASE => FALSE;
IF we THEN {
wa0: BOOL ← minor.horizontal[0].leftDown;
wa1: BOOL ← minor.horizontal[1].leftDown;
wa2: BOOL ← minor.horizontal[2].leftDown;
word: CARDINALSELECT TRUE FROM
wa1 AND wa2 => 3,
wa1 => 2,
wa2 => 1,
ENDCASE => 0;
horizontalGrain: Grain ← minor.horizontal[word];
FOR index: CARDINAL IN [0..4) DO
grain: Grain ← minor.vertical[index];
bit: BOOL ← grain.rightUp;
IF wa0 THEN {
IF bit#grain.perpendicularGrains[word].inputEnabled THEN {
grain.perpendicularGrains[word].inputEnabled ← bit;
ScheduleMinorArray[array, minor];
};
}
ELSE {
IF bit # horizontalGrain.perpendicularGrains[ index].inputEnabled THEN {
horizontalGrain.perpendicularGrains[index].inputEnabled ← bit;
ScheduleMinorArray[array, minor];
};
};
ENDLOOP;
};
};
ENDCASE;
};
[] ← RefTab.Pairs[array.state.positionToEntity, GrainMasterToSlave];
};
RelaxState: PROC [array: ArrayBase] = {
UNTIL array.state.scheduledGrains=NIL AND array.state.scheduledMinorArrays=NIL DO
grain: Grain ← array.state.scheduledGrains;
minor: MinorArray;
IF grain#NIL THEN {
array.state.scheduledGrains ← grain.nextGrain;
grain.scheduled ← FALSE;
RelaxGrain[array, grain];
};
minor ← array.state.scheduledMinorArrays;
IF minor#NIL THEN {
array.state.scheduledMinorArrays ← minor.nextMinorArray;
minor.scheduled ← FALSE;
RelaxMinorArray[array, minor];
};
ENDLOOP;
};
RelaxGrain: PROC [array: ArrayBase, grain: Grain] = {
IF grain.rightUpGrain#NIL AND NOT (grain.vertical AND (grain.minorArray.RAMEven OR grain.minorArray.RAMOdd)) THEN {
leftDown: BOOLNOT (IF grain.leftDownSelectLeftDown THEN grain.rightUpGrain.leftDown ELSE grain.rightUpGrain.output);
IF leftDown#grain.leftDown THEN {
grain.leftDown ← leftDown;
ScheduleGrain[array, grain.leftDownGrain];
IF grain.minorArray.RAMEven OR grain.minorArray.RAMOdd THEN ScheduleMinorArray[array, grain.minorArray];
};
};
IF grain.leftDownGrain#NIL THEN {
rightUp: BOOLNOT (IF grain.rightUpSelectRightUp THEN grain.leftDownGrain.rightUp ELSE grain.leftDownGrain.output);
IF rightUp#grain.rightUp THEN {
grain.rightUp ← rightUp;
IF grain.minorArray.RAMEven OR grain.minorArray.RAMOdd THEN ScheduleMinorArray[array, grain.minorArray];
ScheduleGrain[array, grain.rightUpGrain];
};
};
{
input: BOOLSELECT grain.inputSelect FROM
none => IF grain.flipFlop OR grain.invert THEN ERROR ELSE grain.input,
oru => grain.output,
old => IF grain.leftDownGrain=NIL THEN FALSE ELSE grain.leftDownGrain.output,
ld => grain.leftDown,
l => grain.longLine.long,
ru => IF grain.leftDownGrain=NIL THEN FALSE ELSE grain.leftDownGrain.rightUp,
ENDCASE => ERROR;
grain.master ← input;
IF NOT grain.flipFlop THEN {
IF grain.invert THEN input ← NOT input;
IF input#grain.input THEN {
grain.input ← input;
SchedulePerpendicularGrains[array, grain];
};
};
};
{
output: BOOLFALSE;
FOR index: CARDINAL IN [0..grain.size) DO
IF grain.perpendicularGrains[index].inputEnabled AND NOT grain.perpendicularGrains[index].grain.input THEN {
output ← TRUE;
EXIT;
};
ENDLOOP;
IF grain.parallelInput AND NOT grain.input THEN output ← TRUE;
IF output#grain.output THEN {
grain.output ← output;
ScheduleGrain[array, grain];
ScheduleGrain[array, grain.leftDownGrain];
ScheduleGrain[array, grain.rightUpGrain];
};
};
IF (grain.longControl=on OR (grain.longControl=old AND (IF grain.leftDownGrain=NIL THEN FALSE ELSE grain.leftDownGrain.output))) AND grain.longLine.long#grain.output THEN ScheduleLong[array, grain.longLine, grain.output];
};
RelaxMinorArray: PROC [array: ArrayBase, minor: MinorArray] = {
re: BOOLSELECT TRUE FROM
minor.RAMEven => minor.horizontal[3].rightUp,
minor.RAMOdd => NOT minor.horizontal[3].rightUp,
ENDCASE => FALSE;
IF re THEN {
ra0: BOOL ← minor.horizontal[0].rightUp;
ra1: BOOL ← minor.horizontal[1].rightUp;
ra2: BOOL ← minor.horizontal[2].rightUp;
word: CARDINALSELECT TRUE FROM
ra1 AND ra2 => 3,
ra1 => 2,
ra2 => 1,
ENDCASE => 0;
horizontalGrain: Grain ← minor.horizontal[word];
FOR index: CARDINAL IN [0..4) DO
grain: Grain ← minor.vertical[index];
bit: BOOLIF ra0 THEN grain.perpendicularGrains[word].inputEnabled ELSE horizontalGrain.perpendicularGrains[index].inputEnabled;
IF bit#grain.leftDown THEN {
grain.leftDown ← bit;
ScheduleGrain[array, grain];
IF grain.leftDownGrain#NIL THEN ScheduleGrain[array, grain.leftDownGrain];
};
ENDLOOP;
};
};
SampleState: PROC [array: ArrayBase] = {
};
SchedulePerpendicularGrains: PROC [array: ArrayBase, grain: Grain] = {
FOR index: CARDINAL IN [0..grain.size) DO
ScheduleGrain[array, grain.perpendicularGrains[index].grain];
ENDLOOP;
};
ScheduleGrain: PROC [array: ArrayBase, grain: Grain] = {
IF grain#NIL AND NOT grain.scheduled THEN {
grain.scheduled ← TRUE;
grain.nextGrain ← array.state.scheduledGrains;
array.state.scheduledGrains ← grain;
};
};
ScheduleLong: PROC [array: ArrayBase, longLine: LongLine, value: BOOL] = {
longLine.long ← value;
FOR index: CARDINAL IN [0..longLine.size) DO
longGrain: Grain ← longLine.grains[index];
IF longGrain.inputSelect=l THEN ScheduleGrain[array, longGrain];
ENDLOOP;
};
ScheduleMinorArray: PROC [array: ArrayBase, minor: MinorArray] = {
IF minor#NIL AND NOT minor.scheduled THEN {
minor.scheduled ← TRUE;
minor.nextMinorArray ← array.state.scheduledMinorArrays;
array.state.scheduledMinorArrays ← minor;
};
};
END.