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:
ROPE ←
NIL]
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:
ROPE ←
IO.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 ROPE ← ALL[NIL];
wordOffset, fieldOffset, curPort, portCount: ARRAY Side OF INTEGER ← ALL[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: INTEGER ← MIN[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:
BOOL ←
FALSE] =
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.