<SwitchTypeCells.Mesa>> <> 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 [ct: CellType] RETURNS [ioAsAny: REF ANY] --IOCreator-- = BEGIN sjd: SplitJoinData _ NARROW[ct.typeData]; ioAsAny _ 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; <> <> <> <> <> <> END.