Rosemary.DF=>SwitchTypeCells.Mesa
Last Edited by: Spreitzer, August 18, 1984 9:18:40 pm PDT
DIRECTORY IO, List, Rope, RoseCreate, RoseRun, RoseTypes, SwitchTypes, SwitchTypesPrivate;
SwitchTypeCells: CEDAR PROGRAM
IMPORTS IO, Rope, RoseCreate, RoseRun, SwitchTypes
EXPORTS SwitchTypes, SwitchTypesPrivate =
BEGIN OPEN RoseTypes, SwitchTypes, SwitchTypesPrivate;
Side: TYPE = {A, B};
NumberedPortList: TYPE = LIST OF NumberedPort;
NumberedPort: TYPE = RECORD [index: CARDINAL, port: Port];
SwitchMakeSplitJoin: PUBLIC PROC [within: Cell, a, b: StretchList, writeA, writeB: BOOLEAN, for: ExpansionReceiver] RETURNS [cell: Cell] =
BEGIN
Add: PROC [old, sep, nu1, nu2, nu3: ROPENIL] RETURNS [new: ROPE] =
BEGIN
new ← old.Cat[IF old.Length[] > 0 THEN sep ELSE "", nu1, nu2, nu3];
END;
Hello: PROC [stretch: Stretch, side: Side] RETURNS [length: INTEGER] =
{oside: Side ← IF side = A THEN B ELSE A;
bits: INTEGER ← stretch.node.type.procs.Bits[stretch.node.type];
words: INTEGER ← (bits + 15)/16;
portName: ROPEIO.PutFR["%g%g",
IO.rope[SELECT side FROM A => "A", B => "B", ENDCASE => ERROR],
IO.int[portCount[side]]];
fieldOff: INTEGER ← 0;
rawLength: INTEGER ← 1;
IF NOT IsSwitchType[stretch.node.type] THEN ERROR;
WITH stretch SELECT FROM
ss: SubStretch => BEGIN
WITH stretch.node.type SELECT FROM
ant: ArrayNodeType => BEGIN
IF ss.first < ant.first OR ss.last > ant.last THEN ERROR;
fieldOff ← ss.first - ant.first;
rawLength ← 1 + ant.last - ant.first;
END;
ant: AtomNodeType => ERROR;
ENDCASE => ERROR;
length ← 1 + ss.last - ss.first;
END;
ss: SingleStretch => length ← 1;
ENDCASE => ERROR;
connections ← Add[connections, ", ", portName, ":", stretch.node.name];
instanceNames[side] ← Add[instanceNames[side], ",", stretch.node.name];
typeNames[side] ← Add[typeNames[side], ",", stretch.node.type.procs.UserDescription[stretch.node.type]];
wordOffset[side] ← nextWordOffset;
nextWordOffset ← nextWordOffset + words;
portList ← CONS[
[nextPort,
[wordOffset[side], words, portName, stretch.node.type, write[oside], write[side]]],
portList];
fieldOffset[side] ← ((switchValsPerWord - (rawLength MOD switchValsPerWord)) MOD switchValsPerWord) + fieldOff;
curPort[side] ← nextPort;
portCount[side] ← portCount[side] + 1;
nextPort ← nextPort + 1;
};
sjd: SplitJoinData ← NEW [SplitJoinDataRep ← []];
connections: ROPE;
instanceNames, typeNames: ARRAY Side OF ROPEALL[NIL];
wordOffset, fieldOffset, curPort, portCount: ARRAY Side OF INTEGERALL[0];
nextWordOffset: INTEGER ← 1;
nextPort: INTEGER ← 0;
write: ARRAY Side OF BOOLEAN = [writeA, writeB];
portList: NumberedPortList;
aList, bList: StretchList;
aLength, bLength: INTEGER ← 0;
sjd.direction ← IF writeA
THEN (IF writeB THEN both ELSE toA)
ELSE (IF writeB THEN toB ELSE ERROR);
aLength ← Hello[(aList ← a).first, A];
bLength← Hello[(bList ← b).first, B];
DO
length: INTEGERMIN[aLength, bLength];
sjd.parts ← CONS[
[
aWordOffset: wordOffset[A], aFieldOffset: fieldOffset[A],
bWordOffset: wordOffset[B], bFieldOffset: fieldOffset[B],
length: length,
ports: [curPort[A], curPort[B]]],
sjd.parts];
fieldOffset[A] ← fieldOffset[A] + length;
fieldOffset[B] ← fieldOffset[B] + length;
IF (aLength ← aLength - length) = 0 THEN aList ← aList.rest;
IF (bLength ← bLength - length) = 0 THEN bList ← bList.rest;
IF (aList = NIL) # (bList = NIL) THEN ERROR;
IF aList = NIL THEN EXIT;
IF aLength = 0 THEN aLength ← Hello[aList.first, A];
IF bLength = 0 THEN bLength ← Hello[bList.first, B];
ENDLOOP;
sjd.words ← nextWordOffset - 1;
cell ← for.class.CellInstance[
erInstance: for.instance,
instanceName: IO.PutFR[
"[%g]-[%g]",
IO.rope[instanceNames[A]],
IO.rope[instanceNames[B]]],
typeName: EnsureSplitJoin[
portList,
nextPort,
sjd,
IO.PutFR["SwitchSplitter[%g]%g-%g[%g]",
IO.rope[typeNames[A]],
IO.rope[IF writeA THEN "<" ELSE ""],
IO.rope[IF writeB THEN ">" ELSE ""],
IO.rope[typeNames[B]]]].name,
interfaceNodes: connections];
END;
IsSwitchType: PUBLIC PROC [nt: NodeType] RETURNS [switchy: BOOLEAN] = {
WITH nt SELECT FROM
ant: ArrayNodeType => switchy ← IsSwitchType[ant.element];
ant: AtomNodeType => switchy ← ant = bitType;
ENDCASE => ERROR};
SplitJoinDataList: TYPE = LIST OF SplitJoinDataRep;
SplitJoinData: TYPE = REF SplitJoinDataRep;
SplitJoinDataRep: TYPE = RECORD [
parts: PartList ← NIL,
words: INTEGER ← 0,
direction: Direction ← toB];
Direction: TYPE = {toA, toB, both};
PartList: TYPE = LIST OF Part;
Part: TYPE = RECORD [
aWordOffset, bWordOffset, aFieldOffset, bFieldOffset, length: INTEGER,
ports: ARRAY Side OF CARDINAL
];
splitters: LIST OF CellType ← NIL;
EnsureSplitJoin: PROC [portList: NumberedPortList, portCount: CARDINAL, sjd: SplitJoinData, typeName: ROPE] RETURNS [type: CellType] =
BEGIN
ports: Ports;
pl: NumberedPortList;
FOR cl: LIST OF CellType ← splitters, cl.rest WHILE cl # NIL DO
i: CARDINAL;
type ← cl.first;
IF type.ports.length # portCount THEN LOOP;
pl ← portList;
FOR i IN [0 .. portCount) DO
IF pl.first.port # type.ports[pl.first.index] THEN EXIT;
pl ← pl.rest;
ENDLOOP;
IF i < portCount THEN LOOP;
IF pl # NIL THEN ERROR;
RETURN;
ENDLOOP;
ports ← NEW [PortsRep[portCount]];
pl ← portList;
FOR i: CARDINAL IN [0 .. portCount) DO
ports[pl.first.index] ← pl.first.port;
pl ← pl.rest;
ENDLOOP;
type ← RoseCreate.RegisterCellType[
name: typeName,
ioCreator: CreateSplitterIO,
initializer: InitializeSplitter,
evals: [
--should be spurrious: ValsChanged: SplitterValsChanged,--
PropQ: SplitterPropQ,
PropUD: SplitterPropUD,
FindVicinity: SplitterFindVicinity],
ports: ports,
typeData: sjd];
splitters ← CONS[type, splitters];
END;
Words: TYPE = REF WordsRep;
WordsRep: TYPE = RECORD [words: SEQUENCE length: CARDINAL OF CARDINAL];
CreateSplitterIO: PROC [cell: Cell] --IOCreator-- =
BEGIN
sjd: SplitJoinData ← NARROW[cell.type.typeData];
cell.realCellStuff.switchIO ← NEW [WordsRep[sjd.words]];
cell.realCellStuff.newIO ← NEW [WordsRep[sjd.words]];
cell.realCellStuff.oldIO ← NEW [WordsRep[sjd.words]];
END;
InitializeSplitter: PROCEDURE [cell: Cell, leafily: BOOLEAN] --Initializer-- = {cell.realCellStuff.state ← cell.type.typeData};
SplitterPropQ: CellProc--PROC [cell: Cell]-- = TRUSTED
BEGIN
sjd: SplitJoinData ← NARROW[cell.realCellStuff.state];
a, b: Switches;
FOR pl: PartList ← sjd.parts, pl.rest WHILE pl # NIL DO
p: Part ← pl.first;
a ← LOOPHOLE[cell.realCellStuff.switchIOAsWP + p.aWordOffset];
b ← LOOPHOLE[cell.realCellStuff.switchIOAsWP + p.bWordOffset];
IF sjd.direction # toB THEN
FOR i: INTEGER IN [0 .. p.length) DO
a[p.aFieldOffset+i].s[q] ← MAX[a[p.aFieldOffset+i].s[q], b[p.bFieldOffset+i].s[q]]
ENDLOOP;
IF sjd.direction # toA THEN
FOR i: INTEGER IN [0 .. p.length) DO
b[p.bFieldOffset+i].s[q] ← MAX[a[p.aFieldOffset+i].s[q], b[p.bFieldOffset+i].s[q]]
ENDLOOP;
ENDLOOP;
END;
SplitterPropUD: CellProc--PROC [cell: Cell]-- = TRUSTED
BEGIN
sjd: SplitJoinData ← NARROW[cell.realCellStuff.state];
a, b: Switches;
FOR pl: PartList ← sjd.parts, pl.rest WHILE pl # NIL DO
p: Part ← pl.first;
a ← LOOPHOLE[cell.realCellStuff.switchIOAsWP + p.aWordOffset];
b ← LOOPHOLE[cell.realCellStuff.switchIOAsWP + p.bWordOffset];
IF sjd.direction # toB THEN
FOR i: INTEGER IN [0 .. p.length) DO
a[p.aFieldOffset+i].s[u] ← MAX[a[p.aFieldOffset+i].s[u], b[p.bFieldOffset+i].s[u]];
a[p.aFieldOffset+i].s[d] ← MAX[a[p.aFieldOffset+i].s[d], b[p.bFieldOffset+i].s[d]];
ENDLOOP;
IF sjd.direction # toA THEN
FOR i: INTEGER IN [0 .. p.length) DO
b[p.bFieldOffset+i].s[u] ← MAX[a[p.aFieldOffset+i].s[u], b[p.bFieldOffset+i].s[u]];
b[p.bFieldOffset+i].s[d] ← MAX[a[p.aFieldOffset+i].s[d], b[p.bFieldOffset+i].s[d]];
ENDLOOP;
ENDLOOP;
END;
SplitterFindVicinity: PROC [cell: Cell, portIndex: CARDINAL, evenIfInput: BOOLFALSE] =
BEGIN
sjd: SplitJoinData ← NARROW[cell.realCellStuff.state];
IF portIndex = noPort THEN RETURN;
FOR pl: PartList ← sjd.parts, pl.rest WHILE pl # NIL DO
IF pl.first.ports[A] = portIndex AND sjd.direction # toA THEN RoseRun.FindExteriorVicinity[cell, pl.first.ports[B], evenIfInput];
IF pl.first.ports[B] = portIndex AND sjd.direction # toB THEN RoseRun.FindExteriorVicinity[cell, pl.first.ports[A], evenIfInput];
ENDLOOP;
END;
SplitterValsChanged: CellProc--PROC [cell: Cell]-- =
BEGIN
sjd: SplitJoinData ← NARROW[cell.realCellStuff.state];
IF sjd.direction # toSub THEN RoseRun.PerturbPort[cell, 0];
IF sjd.direction # fromSub THEN RoseRun.PerturbPort[cell, 1];
END;
END.