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"]; CreateBase: PUBLIC PROC [sizes: ArrayPosition, useConnectionMachine: BOOL _ FALSE] 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; }; 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: BOOL _ FALSE] 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.STREAM _ IO.RIS[rope]; token: Rope.ROPE _ IO.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: CARDINAL _ ORD[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: BOOL _ FALSE] = { 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: BOOL _ IF 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: BOOL _ SELECT 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: CARDINAL _ SELECT 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: BOOL _ NOT (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: BOOL _ NOT (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: BOOL _ SELECT 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: BOOL _ FALSE; 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: BOOL _ SELECT 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: CARDINAL _ SELECT 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: BOOL _ IF 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. ’SoftHdwBasicsImpl.mesa Copyright Σ 1988 by Xerox Corporation. All rights reserved. Barth, June 28, 1989 3:27:01 pm PDT SunRPC Stubs State Κv– "cedar" style˜codešœ™K™Kšœ˜šœœ˜'šœ2œ˜:Kšœ˜K˜$K˜—Kšœ1˜5K˜—šœ˜šœ2œ˜:Kšœ˜K˜$K˜—Kšœ1˜5K˜—Kšœœ"˜=Kšœ˜šœ˜ šœ ˜ Kšœ"˜"Kšœ˜K˜—šœ˜Kšœ ˜ Kšœ˜K˜—Kšœœ˜—šœ œœ˜)šœ˜ Kšœ*˜*Kšœ,˜,Kšœœ˜—Kšœ5œ˜;Kšœ.œ"˜VKšœ˜—Kšœ˜K˜šœ˜ šœ ˜ Kšœ˜Kšœ˜K˜—šœ˜Kšœ˜Kšœ˜K˜—Kšœœ˜—Kšœœ"˜9Kšœœœœ˜!šœœœ˜2šœœœ˜*Kšœ%˜%Kšœ˜K˜—Kšœœœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœœ"˜;Kšœ˜šœ˜ Kšœ@˜@KšœD˜DKšœœ˜—K˜—Kšœœ˜0KšœT˜TJšœœ˜%Kšœ#˜#Kšœ4˜4Kšœ:˜:Kšœ>˜>Kšœ;˜;Jšœ˜J˜—šœœœ˜>K˜—šžœœR˜gK˜šœ œœ˜+Kšœ˜šœ œœ˜+Kšœ˜šœœœ˜2Kšœ$˜$šœœœ˜2Kšœ$˜$Kšœ˜Kšœ ˜ šœœœ˜-Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ"˜"šœœœ˜-Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Jšœ˜J˜—šžœœR˜jKšœ˜šœ œœ˜+Kšœ˜šœ œœ˜+Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜šœœœ˜2Kšœ$˜$šœœœ˜-Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ"˜"Kšœ˜Kšœ˜šœœœ˜2Kšœ$˜$šœœœ˜-Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜K˜—šžœœR˜lKšœ˜Kšœ ˜ Kšœ˜Kšœ˜šœ œœ˜+Kšœ˜šœ œœ˜+Kšœ˜šœœœ˜2Kšœ$˜$šœœœ˜2Kšœ$˜$Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—Jšœ˜J˜—š žœœœœ œ˜XKšœœœ/œ!˜mKšœœœœ˜_šœœœ˜'Kšœœœœ˜jKšœ!œœ˜UKšœœœœ˜A—šœœœ˜'Kšœœœœ˜hKšœ!œœ˜PKšœœœ˜<—K˜K˜—š žœœœ œœ˜Xš ž œœœœœ˜\Kšœœ˜&Kšœœœœ˜)šœ œ˜Kšœœ˜&Kšœœœœ˜)K˜—Kšœ œ ˜Kšœœ˜&Kšœœœœ˜)šœ œ˜Kšœœ˜&Kšœœœœ˜)K˜—Kšœ œ ˜Kšœœ˜&Kšœœœœ˜)K˜—Kš œœœœœ˜Kšœ œœ ˜Kšœ œ˜!šœœ ˜.šœ2œ˜:Kšœ#˜#Kšœ˜K˜—Kšœœœ˜Kšœ˜—Kšœœ ˜šœœ ˜!šœ$œ˜,Kšœ˜Kšœ˜K˜—Kšœœœ˜Kšœ˜—Kšœ˜Kšœ@œAœ ˜§KšœCœIœ ˜²K˜K˜—šžœœ˜/Kšœœ˜!Kšœœ˜!Kšœ ˜K˜K˜—šžœœ˜-šžœœ˜#K˜K˜K˜—šžœœœ˜Kšœ˜Kšœ˜K˜—šžœœœ˜&Kšœœ˜(K˜—Kšœœ˜Kšœœœ ˜šœœ˜*Kšœ˜Kšœ˜Kšœœ˜—K˜Kšœ˜Kšœ˜Kšœ˜ K˜K˜—šžœœ˜,šž œ˜$šœœ œ˜Kšœœ˜Kšœœ˜Kšœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜šœœœ˜)Kšœ0œ˜6Kšœ˜—K˜—K˜—Kšœœ˜"Kšœ;˜;K˜K˜—š ž œœ.œœ œ˜ašž œœœ˜+K˜K˜Kšœœ6˜DK˜ K˜—šœ ˜KšœAœ˜Gšœž˜žK˜šœœ ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜—Kšœ˜—šœ ˜ Kšœœ6˜QKšœ˜K˜—šœ˜K˜ Kšœœ˜šœ˜˜ Kšœ˜K˜K˜K˜K˜—˜Kšœ˜K˜K˜K˜K˜—Kšœœ˜—Kšœ6˜6K˜—šœ˜Kšœ˜K˜Kšœ˜Kšœœ6˜DK˜ šœœ ˜Kšœ˜Kšœ˜Kšœœ˜—K˜—Kšœœ˜—K˜K˜—šž œœ/œ˜Hšž œœœ˜+K˜K˜Kšœœ6˜DK˜ K˜—šžœœœœ˜8Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ œœ˜K˜—šœ ˜KšœAœ˜Gšœž˜žK˜šœ ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ!˜!Kšœ˜Kšœ!˜!Kšœ˜Kšœ#˜#Kšœ-˜-Kšœ#˜#Kšœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ#˜#Kšœ!˜!Kšœœ˜—KšœS˜Sšœœœ˜$Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜—Kšœ/˜/šœœœ˜$Kšœ˜Kšœ˜Kšœ˜—Kšœ.˜.Kšœ,˜,Kšœ.˜.Kšœ*˜*KšœV˜VKšœ˜Kšœ*˜*Kšœ)˜)Kšœ*˜*Kšœ˜—šœ ˜ Kšœœ6˜QKšœœ&˜AK˜—šœ˜K˜ Kšœœ˜šœ˜˜ Kšœ˜K˜K˜K˜K˜—˜Kšœ˜K˜K˜K˜K˜—Kšœœ˜—Kšœ6˜6K˜K˜—šœ˜Kšœ˜K˜Kšœ˜Kšœ˜Kšœœ6˜DK˜ šœ ˜Kšœ!˜!Kšœ˜Kšœœ˜—Kšœ!˜!šœœœ˜ KšœP˜PKšœR˜RKšœ˜—K˜—Kšœœ˜—K˜K˜—šžœœ˜/šžœ˜-šœœ˜šœ˜šœœ˜Kš œœœœœœ˜Gšœœ˜Kšœ˜Kšœ˜Kšœ*˜*K˜—K˜—K˜—šœ˜šœœœœ˜Kšœ.˜.Kšœœ˜1Kšœœ˜—šœœ˜ Kšœœ ˜)Kšœœ ˜)Kšœœ ˜)šœœœœ˜!Kšœœ ˜Kšœ ˜ Kšœ ˜ Kšœ˜ —Kšœ0˜0šœœœ˜ Kšœ%˜%Kšœœ˜šœœ˜ šœ2œ˜:Kšœ3˜3Kšœ!˜!K˜—Kšœ˜—šœ˜šœ@œ˜HKšœ>˜>Kšœ!˜!K˜—Kšœ˜—Kšœ˜—K˜—K˜—Kšœ˜—K˜—KšœD˜DK˜K˜—šž œœ˜'šœœ!œ˜QK˜+Kšœ˜šœœœ˜Kšœ.˜.Kšœœ˜Kšœ˜K˜—Kšœ)˜)šœœœ˜Kšœ8˜8Kšœœ˜Kšœ˜K˜—Kšœ˜—K˜K˜—šž œœ%˜5šœœœœœœœ˜sKš œ œœœœœ˜wšœœ˜!Kšœ˜Kšœ*˜*Kšœœœ-˜hK˜—K˜—šœœœ˜!Kš œ œœœœœ˜ušœœ˜Kšœ˜Kšœœœ-˜hKšœ)˜)K˜—K˜—šœ˜šœœœ˜+Kš œœœœœœ ˜FKšœ˜Kš œœœœœœ˜MKšœ˜Kšœ˜Kš œœœœœœ˜MKšœœ˜—Kšœ˜šœœœ˜Kšœœ œ˜'šœœ˜Kšœ˜Kšœ*˜*K˜—K˜—K˜—šœ˜Kšœœœ˜šœœœ˜)šœ/œœ.œ˜lKšœ œ˜Kšœ˜K˜—Kšœ˜—Kš œœœ œ œ˜>šœœ˜Kšœ˜Kšœ˜Kšœ*˜*Kšœ)˜)K˜—K˜—Kšœœœœœœœœœ"œ3˜έK˜K˜—šžœœ*˜?šœœœœ˜Kšœ-˜-Kšœœ˜0Kšœœ˜—šœœ˜ Kšœœ˜(Kšœœ˜(Kšœœ˜(šœœœœ˜!Kšœœ ˜K˜ K˜ Kšœ˜ —Kšœ0˜0šœœœ˜ Kšœ%˜%Kš œœœœ.œ9˜‚šœœ˜Kšœ˜Kšœ˜Kšœœœ+˜JK˜—Kšœ˜—K˜—K˜K˜—šž œœ˜(K˜K˜—šžœœ%˜Fšœœœ˜)Kšœ=˜=Kšœ˜—K˜K˜—šž œœ%˜8š œœœœœ˜+Kšœœ˜K˜.K˜$K˜—K˜K˜—šž œœ/œ˜JKšœ˜šœœœ˜,Kšœ*˜*Kšœœ!˜@Kšœ˜—K˜K˜—šžœœ*˜Bš œœœœœ˜+Kšœœ˜Kšœ8˜8Kšœ)˜)K˜—K˜K˜——Kšœ˜—…—g|†„