diff --git a/css/application.css b/css/application.css index 851b7e5..651d646 100755 --- a/css/application.css +++ b/css/application.css @@ -129,4 +129,55 @@ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cecece', end rect.draw2d_ResizeHandle { display: none; +} + + +/****************************************************************** + * CSS for custom menu + ******************************************************************/ + +.custom-menu { + margin: 0; + display: none; + z-index: 1000; + position: absolute; + overflow: hidden; + border: 1px solid #CCC; + white-space: nowrap; + font-family: sans-serif; + background: #FFF; + color: #333; + border-radius: 5px; + padding: 0; +} + +.custom-menu .title { + padding: 8px 12px; + font-size: 13px; + color: rgb(61, 113, 130); + border-bottom: 1px solid #CCC; +} + +.custom-menu ul { + margin: 0; + padding: 0; +} + +/* Each of the items in the list */ +.custom-menu li { + padding: 8px 12px; + cursor: pointer; + list-style-type: none; + transition: all .3s ease; + user-select: none; +} + +.custom-menu li.clear { + border-top: 1px solid #CCC; + color: red; + +} + +.custom-menu li:hover { + background-color: #DEF; } \ No newline at end of file diff --git a/gui/HoverConnection.js b/gui/HoverConnection.js index cd06fb0..2fa6caf 100644 --- a/gui/HoverConnection.js +++ b/gui/HoverConnection.js @@ -2,6 +2,108 @@ var defaultRouterClassName = "draw2d.layout.connection.SplineConnectionRouter"; var defaultRouter = new draw2d.layout.connection.SplineConnectionRouter(); +function showCustomConfigs(x, y, connection) { + + let canvas = connection.getCanvas(); + + // If the document is clicked somewhere + $(document).bind("mousedown", function (e) { + // If the clicked element is not the menu, hide the menu + // and remove the config connection + if (!$(e.target).parents(".custom-menu.mult").length > 0) { + $(".custom-menu.mult").hide(100); + // Also remove it from the stack + canvas.getCommandStack().undostack.pop(); + canvas.remove(connection); + + $(document).unbind("mousedown"); + $(".custom-menu.mult li").unbind("click"); + } + }); + + // If the menu element is clicked + $(".custom-menu.mult li").one("click", function () { + // Get the nodes + let node1 = connection.sourcePort.parent; + let node2 = connection.targetPort.parent; + + // Check if either nodes has connections and display + // a warning message, if accepted, then remove all + // current connections + let node1_connections = node1.getAllConnections(); + let node2_connections = node2.getAllConnections(); + + let continueAction = true; + + if ((node1 instanceof NodeShape && node1_connections.length) || (node2 instanceof NodeShape && node2_connections.length)) { + continueAction = confirm("The current connections will be overrided, do you want to continue?"); + } + + // Remove the config connection from the commands stack + canvas.getCommandStack().undostack.pop(); + + if (!continueAction) { + // Remove the config connection + canvas.remove(connection); + return; + } + + // Delete current connections if it's not a switch + if (node1 instanceof NodeShape) { + delete_connections(node1_connections, canvas); + } + if (node2 instanceof NodeShape) { + delete_connections(node2_connections, canvas); + } + + // This is the triggered action name + switch ($(this).attr("data-action")) { + // Connect the nodes based on the action + case "one-by-one": + if (node1 instanceof NodeShape && node2 instanceof NodeShape) { + connectBasedOnConfig([node1, node2], "one-by-one"); + } else { + // One of the nodes is a switch + + let node = node1; + let eth_switch = node2; + + if (node1 instanceof SwitchShape) { + node = node2; + eth_switch = node1; + } + + connectBasedOnConfig([node], "one-by-one", eth_switch) + } + + break; + case "second": + alert("second"); + break; + case "third": + alert("Third"); + break; + } + + // Remove the config connection without adding it to the command stack + canvas.remove(connection); + + + // Hide it AFTER the action was triggered + $(".custom-menu.mult").hide(100); + $(document).unbind("mousedown"); + $(".custom-menu.mult li").unbind("click"); + }); + + + + $(".custom-menu.mult").finish().toggle(100).css({ + top: y + "px", + left: x + "px" + }); +} + + var HoverConnection = draw2d.Connection.extend({ init: function (sourcePort, targetPort) { @@ -17,6 +119,15 @@ var HoverConnection = draw2d.Connection.extend({ color: "b9dd69" }); + // Show custom configs only for config ports + setTimeout(() => { + if (self.sourcePort.name.includes("config_port")) { + let x = this.start.x - 60 + ((this.end.x - this.start.x) / 2) + let y = this.start.y + ((this.end.y - this.start.y) / 2) + showCustomConfigs(x, y, self); + } + }, 10); + // this.installEditPolicy(new SelectionMenuPolicy()); // this.on("dragEnter", function (emitter, event) { diff --git a/gui/NodeShape.js b/gui/NodeShape.js index bcdec18..dd0a50d 100755 --- a/gui/NodeShape.js +++ b/gui/NodeShape.js @@ -105,13 +105,30 @@ ChannelShape = draw2d.shape.basic.Label.extend({ port.on("dragstart", function (e) { + toggle_config_ports(app.view.figures.data, false); + if (siblingChannel) { siblingChannel.setVisible(true) siblingChannel.setVisible(true) } + + // Intel nodes cannot connect to a switch so if I am + // an intel node, then hide all switch ports + // Loop over all figures and all ports and hide all config ports + if (self.getFPGA().getNode().getType() == "Intel") { + toggle_all_switch_ports(app.view.figures.data, false) + } + }, port); port.on("dragend", function () { + toggle_config_ports(app.view.figures.data, true); + if (siblingChannel) siblingChannel.setVisible(false) + + // Show switch ports again + if (self.getFPGA().getNode().getType() == "Intel") { + toggle_all_switch_ports(app.view.figures.data, true) + } }, port); // this.orientation = attr.orientation; @@ -291,7 +308,7 @@ FPGAShape = draw2d.shape.layout.FlexGridLayout.extend({ getChannelFromFpgalink: function (string_channel, isSibling) { // ch0, ch1, ch2, ch3" // n00, .. - + var num = parseInt(string_channel.substring(2)) * 2 + (isSibling ? 0 : 1); return this.getChildren().get(1).getChildren().get(num); }, @@ -330,7 +347,7 @@ FPGAShape = draw2d.shape.layout.FlexGridLayout.extend({ this.fpgaLabel.__cellConstraint.row = prop.labelRow; this.channelLayout.__cellConstraint.row = prop.channelLayoutRow; - + gridDef[`def_${prop.arrangement[0]}s`] = Array(1).fill(-1); gridDef[`def_${prop.arrangement[1]}s`] = Array(this.getChannels().getSize() / 2).fill(-1); @@ -360,28 +377,34 @@ NodeShape = draw2d.shape.layout.FlexGridLayout.extend({ labelRow: 0, fpgaLayoutRow: 1, arrangement: ["row", "col"], + port_locator: new draw2d.layout.locator.XYRelPortLocator(100, 10) }, [OrientationEnum.east]: { // labelPadding: {left: 25, right: 25}, labelRow: 0, fpgaLayoutRow: 1, arrangement: ["col", "row"], + port_locator: new draw2d.layout.locator.XYRelPortLocator(101, 3) }, [OrientationEnum.south]: { // labelPadding: {left: 100, right: 100}, labelRow: 1, fpgaLayoutRow: 0, arrangement: ["row", "col"], + port_locator: new draw2d.layout.locator.XYRelPortLocator(100, 90) }, [OrientationEnum.west]: { // labelPadding: {left: 25, right: 25}, labelRow: 0, fpgaLayoutRow: 1, arrangement: ["col", "row"], + port_locator: new draw2d.layout.locator.XYRelPortLocator(0, 3) }, }), init: function (attr) { + let self = this; + this._super($.extend({ bgColor: "#dbddde", color: "#d7d7d7", @@ -414,6 +437,23 @@ NodeShape = draw2d.shape.layout.FlexGridLayout.extend({ this.installEditPolicy(new SelectionMenuPolicy()); this.orientation = orientation; + + + + let config_port = this.createPort("hybrid", prop.port_locator); + config_port.setName("config_port_" + this.id); + config_port.setMaxFanOut(1); + config_port.setName(`config_port_` + this.id); + config_port.setBackgroundColor("#00FF00"); + config_port.setColor("#000000"); + + config_port.on("dragstart", function (e) { + toggle_non_config_ports(app.view.figures.data, "hide", self.getType()); + }, config_port); + + config_port.on("dragend", function () { + toggle_non_config_ports(app.view.figures.data, "show", self.getType()); + }, config_port); }, addFPGA: function (string_acl, channelsCount) { @@ -459,6 +499,8 @@ NodeShape = draw2d.shape.layout.FlexGridLayout.extend({ fpga.setOrientation(orientation, false); }); + this.getHybridPort(0).setLocator(prop.port_locator); + this.height = 0; this.width = 0; @@ -476,6 +518,40 @@ NodeShape = draw2d.shape.layout.FlexGridLayout.extend({ return this.orientation; }, + getType: function () { + return this.getFPGAs().data.length == 3 ? "Xilinx" : "Intel"; + }, + + getChannelPorts: function () { + let ports = []; + + let fpgas = this.getFPGAs().data; + for (let j = 0; j < fpgas.length; j++) { + const fpga = fpgas[j]; + let channels = fpga.getChannels().data; + + for (let k = 0; k < channels.length; k++) { + const channel = channels[k]; + ports.push(...channel.hybridPorts.data); + } + } + + return ports; + }, + + getAllConnections: function () { + let connections = []; + + let ports = this.getChannelPorts(); + for (let i = 0; i < ports.length; i++) { + const p = ports[i]; + + connections.push(...p.connections.data); + } + + return connections; + }, + getFPGAFromFpgalink: function (string_acl) { // acl0 = FPGA 0 // acl1 = FPGA 1 diff --git a/gui/SelectionMenuPolicy.js b/gui/SelectionMenuPolicy.js index 8247fa7..a8453f6 100755 --- a/gui/SelectionMenuPolicy.js +++ b/gui/SelectionMenuPolicy.js @@ -65,12 +65,16 @@ var SelectionMenuPolicy = draw2d.policy.figure.SelectionPolicy.extend({ let deleteBtn = $("
"); let rotateLeftBtn = $("
"); let rotateRightBtn = $("
"); + let options = $("
"); this.overlay.append(deleteBtn); - // if (figure instanceof NodeShape) { - this.overlay.append(rotateLeftBtn); - this.overlay.append(rotateRightBtn); - // } + this.overlay.append(rotateLeftBtn); + this.overlay.append(rotateRightBtn); + + if (figure instanceof NodeShape) { + this.overlay.append(options); + } + $("body").append(this.overlay); rotateLeftBtn.on("click", function () { @@ -160,6 +164,75 @@ var SelectionMenuPolicy = draw2d.policy.figure.SelectionPolicy.extend({ // var command= new draw2d.command.CommandDelete(figure); // canvas.getCommandStack().execute(command); }) + + options.on("click", function(ev) { + + // If the document is clicked somewhere + $(document).bind("mousedown", function (e) { + // If the clicked element is not the menu, hide the menu + // and remove the config connection + if (!$(e.target).parents(".custom-menu.single").length > 0) { + $(".custom-menu.single").hide(100); + + $(document).unbind("mousedown"); + $(".custom-menu.single li").unbind("click"); + } + }); + + // Hide Intel-only configs for Xilinx Nodes + if (figure.getType() == "Xilinx") { + $(".custom-menu.single .intel-only").hide(); + } else { + $(".custom-menu.single .intel-only").show(); + } + + // If the menu element is clicked + $(".custom-menu.single li").one("click", function () { + // This is the triggered action name + + // Check if the node has any connection and display + // a warning message, if accepted, then remove all + // current connections + let node_connections = figure.getAllConnections(); + let continueAction = true; + + if (node_connections.length) { + continueAction = confirm("The current connections will be deleted, do you want to continue?"); + } + + if (!continueAction) return; + + // Delete current connections + delete_connections(node_connections, canvas); + + let action = $(this).attr("data-action"); + switch (action) { + case "loopback": + connectBasedOnConfig([figure], "loopback"); + break; + case "channel": + connectBasedOnConfig([figure], "channel"); + break; + case "clear": + break; + default: + app.toolbar.createNodesAndConnections(action, 1, [figure], []) + break; + } + + // Hide it AFTER the action was triggered + $(".custom-menu.single").hide(100); + $(document).unbind("mousedown"); + $(".custom-menu.single li").unbind("click"); + }); + + + + $(".custom-menu.single").finish().toggle(100).css({ + top: ev.clientY + "px", + left: ev.clientX + "px" + }); + }); } this.posOverlay(figure); }, diff --git a/gui/SwitchShape.js b/gui/SwitchShape.js index 2bc57e4..39e8d7c 100755 --- a/gui/SwitchShape.js +++ b/gui/SwitchShape.js @@ -34,26 +34,40 @@ SwitchShape = draw2d.shape.basic.Label.extend({ this.connector; this.isDrawn = false; - // Create 7 ports + + // Create 8 normal ports for (let i = 0; i < 8; i++) { let port = this.createPort("hybrid"); port.setName(`inout_${i}` + this.id); + + port.on("dragstart", function (e) { + toggle_config_ports(app.view.figures.data, false); + }, port); + + port.on("dragend", function (e) { + toggle_config_ports(app.view.figures.data, true); + }, port); } + // Create config port + let config_port = this.createPort("hybrid"); + config_port.setName(`config_port_` + this.id); + config_port.setBackgroundColor("#00FF00"); + config_port.setColor("#000000"); - // port.setMaxFanOut(1); - // port.on("connect", function () { - // this.setVisible(false); - // }, port); - // port.on("disconnect", function () { - // this.setVisible(true); - // }, port); + config_port.on("dragstart", function (e) { + toggle_non_config_ports(app.view.figures.data, "hide", "Switch"); + }, config_port); + + config_port.on("dragend", function (e) { + toggle_non_config_ports(app.view.figures.data, "show", "Switch"); + }, config_port); - // this.orientation = attr.orientation; - this.setOrientation(attr.orientation, false); + + + this.setOrientation(attr.orientation, false); this.installEditPolicy(new SelectionMenuPolicy()); - // this.getFPGA().channelLayout.add(this); }, setLinksToChannel: function (partner) { @@ -81,6 +95,23 @@ SwitchShape = draw2d.shape.basic.Label.extend({ return this.connector; }, + getAllConnections: function () { + let connections = []; + + let ports = this.hybridPorts.data; + // -1 is to skip last port which is the config port + for (let i = 0; i < ports.length - 1; i++) { + const p = ports[i]; + connections.push(...p.connections.data); + } + + return connections; + }, + + getName: function() { + return "eth" + this.getText().substr(-2); + }, + getOrientation: function () { return this.orientation; }, diff --git a/gui/Toolbar.js b/gui/Toolbar.js index 88b73cf..1375694 100755 --- a/gui/Toolbar.js +++ b/gui/Toolbar.js @@ -163,12 +163,17 @@ example.Toolbar = Class.extend({ }, - getNodeIdFpgalink: function (string_n) { + getNodeIdFpgalink: function (string_n, fpganodes) { // n00, .. - return parseInt(string_n.substring(1)); + for (let i = 0; i < fpganodes.length; i++) { + const node = fpganodes[i]; + if (node.getName() == string_n) { + return node; + } + } }, - getSwitchFromName: function(name, switches) { + getSwitchFromName: function (name, switches) { // e.g: name eth00 let switch_number = name.substring(3) for (let i = 0; i < switches.length; i++) { @@ -207,6 +212,7 @@ example.Toolbar = Class.extend({ }, srunApply: function (srun_raw, node_type) { + // Get number of fpganodes: -N 1 var srun_N_needle = "-N "; var srun_N = -1; @@ -272,7 +278,7 @@ example.Toolbar = Class.extend({ } else { mapS.set(result[5], 1); } - + // console.log(result); } @@ -295,7 +301,7 @@ example.Toolbar = Class.extend({ var command = new draw2d.command.CommandAdd(this.view, eth_switch, pos_x, pos_y); this.view.getCommandStack().execute(command); - + if (i % 2 == 0) { pos_x += 200; } else { @@ -322,8 +328,8 @@ example.Toolbar = Class.extend({ let num_fpgas = node_type == NodeTypeEnum.intel ? 2 : 3; let num_channels = node_type == NodeTypeEnum.intel ? 4 : 2; - for(var f = 0; f < num_fpgas; f++) { - node.addFPGA("acl"+f, num_channels); + for (var f = 0; f < num_fpgas; f++) { + node.addFPGA("acl" + f, num_channels); } fpganodes.push(node); @@ -362,457 +368,456 @@ example.Toolbar = Class.extend({ full_match = full_match.substring(0, 1) == "\"" ? full_match.substring(1) : full_match; full_match = full_match.substring(full_match.length - 1) == "\"" ? full_match.substring(0, full_match.length - 1) : full_match; - // Look for topologies or custom links. - switch (full_match) { - case "pair": - // Idea: - // - // Within each node, all channels of one FPGA board are connected to the - // respective channel of the other FPGA board. - // No connections between nodes are made. - - // Go over all nodes - for (i = 0; i < srun_N; i++) { - var node = fpganodes[i]; - // var shape = node.getShape(); - - // Connect all channels from first FPGA to second FPGA. - var fpga0 = node.getFPGAFromFpgalink("acl0"); - var fpga1 = node.getFPGAFromFpgalink("acl1"); - - // Go over all channels of FPGA. - var k = 0; - for (k = 0; k < 4; k++) { - this.connectChannels(fpga0.getChannelFromFpgalink("ch" + k), fpga1.getChannelFromFpgalink("ch" + k)); - } - } + this.createNodesAndConnections(full_match, srun_N, fpganodes, eth_switches); - // Arrange nodes for better visualization. - this.arrangeTopology("pair", fpganodes); + // Remove found link. + srun_raw_copy = srun_raw_copy.substring(next_space); + } - break; - case "clique": - // Only clique of 2 nodes is supported. - if (srun_N != 2) { - alert("Only clique of 2 nodes is supported."); - break; - } + // Parse and add fpga links: n00:acl0:ch0-n00:acl1:ch0 + if (srun_raw.indexOf(srun_fpgalinks_needle) == -1) { + // Array(7) [ "n00:acl1:ch0-n00:acl1:ch1", "00", "1", "0", "00", "1", "1" ] + // Array(9)["n00:acl0:ch1-eth", "n00:acl0:ch1", "n00", "acl0", "ch1", "eth", undefined, undefined, undefined] + for (var i = 0; i < fpgalinks.length; i++) { + // Parse and add fpga links: n00:acl0:ch0-n00:acl1:ch0 + var links = fpgalinks[i][0].split("-"); - // Get both nodes. - var n00 = fpganodes[0]; - var n01 = fpganodes[1]; + // Point 1 (think of source). + // value: n00:acl0:ch0 or eth (for Ethernet switch). + var link_p1 = links[0].split(":"); + // Point 2 (think of destination). + // value: n00:acl0:ch0 or eth (for Ethernet switch). + var link_p2 = links[1].split(":"); - // Get all fpgas - var fpga_n00_0 = n00.getFPGAFromFpgalink("acl0"); - var fpga_n00_1 = n00.getFPGAFromFpgalink("acl1"); - var fpga_n01_0 = n01.getFPGAFromFpgalink("acl0"); - var fpga_n01_1 = n01.getFPGAFromFpgalink("acl1"); + // Channels to connect. Logic is required to differentiate if + // the channel is between FPGAs or to/from Ethernet switch. + let chan0; + let chan1; - // Connect channels specific to clique - this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch0"), fpga_n01_0.getChannelFromFpgalink("ch0")); - this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch1"), fpga_n00_1.getChannelFromFpgalink("ch1")); - this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch2"), fpga_n01_1.getChannelFromFpgalink("ch2")); - this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch3"), fpga_n01_1.getChannelFromFpgalink("ch3")); + if (link_p1.length == 3) { + // Channel is from FPGA node. + // Get node. + var tnode_p1 = this.getNodeIdFpgalink(link_p1[0], fpganodes); + // Get FPGA. + var tfpga_p1 = tnode_p1.getFPGAFromFpgalink(link_p1[1]); - this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch0"), fpga_n01_1.getChannelFromFpgalink("ch0")); - this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch2"), fpga_n01_0.getChannelFromFpgalink("ch2")); - this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch3"), fpga_n01_0.getChannelFromFpgalink("ch3")); + // Get channel. + chan0 = tfpga_p1.getChannelFromFpgalink(link_p1[2]); + } else { + // Channel is to ethernet switch. + chan0 = this.getSwitchFromName(link_p1[0], eth_switches); + } - this.connectChannels(fpga_n01_0.getChannelFromFpgalink("ch1"), fpga_n01_1.getChannelFromFpgalink("ch1")); + if (link_p2.length == 3) { + // Channel is to FPGA node. - // Arrange nodes for better visualization. - this.arrangeTopology("clique", fpganodes); + // Get node. + var tnode_p2 = this.getNodeIdFpgalink(link_p2[0], fpganodes); + // Get FPGA. + var tfpga_p2 = tnode_p2.getFPGAFromFpgalink(link_p2[1]); - break; - // Ring - case "ringO": - // Idea: - // Special handling for first and last node in ring (peel, remainder), - // Loop for in-between nodes. - var j; - for (j = 0; j < srun_N; j++) { - // Get both nodes. - // Previous - var nPrev; - if (j == 0) { - nPrev = fpganodes[0]; - } else { - nPrev = fpganodes[j - 1]; - } - // current node - var nCurrent = fpganodes[j]; - // next - var nNext; - if (j == srun_N - 1) { - nNext = fpganodes[j]; - } else { - nNext = fpganodes[j + 1]; - } + chan1 = tfpga_p2.getChannelFromFpgalink(link_p2[2]); + } else { + // Channel is to ethernet switch. + chan1 = this.getSwitchFromName(link_p2[0], eth_switches); + } - // Get all fpgas. - var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); - var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); - var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); - var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); - var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); - var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); - - // Connect channels specific to rinO - // - // A. - var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); - var A_dst; - if (j == srun_N - 1) { - A_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch0"); - } else { - A_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; - } - // - // B. - var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); - var B_dst; - if (j == 0) { - B_dst = fpga_nCurrent_acl0.getChannelFromFpgalink("ch0"); - } else { - B_dst = fpga_nPrev_acl1.getChannelFromFpgalink("ch0");; - } - // - // C. - var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); - var C_dst; - if (j == srun_N - 1) { - C_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch2"); - } else { - C_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; - } - // - // D. - var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); - var D_dst; - if (j == 0) { - D_dst = fpga_nCurrent_acl0.getChannelFromFpgalink("ch2"); - } else { - D_dst = fpga_nPrev_acl1.getChannelFromFpgalink("ch2");; - } + // Get channels, connect and draw them. + this.connectChannels(chan0, chan1); + } + } - this.connectChannels(A_src, A_dst); - this.connectChannels(B_src, B_dst); - this.connectChannels(C_src, C_dst); - this.connectChannels(D_src, D_dst); - // // Set color for up. - // C_src.getConnector().setColor(ColorEnum.red); - // D_src.getConnector().setColor(ColorEnum.red); - } - // Arrange nodes for better visualization. - this.arrangeTopology("ringO", fpganodes); + }, - break; - case "ringN": - // ringN, going down in acl0 column and back up in acl1 column - // Idea: - // Special handling for first and last node in ring (peel, remainder), - // Loop for in-between nodes. - var j; - for (j = 0; j < srun_N; j++) { - // Get nodes. - var nFirst = fpganodes[0]; - // Previous - var nPrev; - if (j == 0) { - nPrev = fpganodes[0]; - } else { - nPrev = fpganodes[j - 1]; - } - // current node - var nCurrent = fpganodes[j]; - // next - var nNext; - if (j == srun_N - 1) { - nNext = fpganodes[j]; - } else { - nNext = fpganodes[j + 1]; - } + createNodesAndConnections: function (full_match, srun_N, fpganodes, eth_switches) { + // Look for topologies or custom links. + switch (full_match) { + case "pair": + // Idea: + // + // Within each node, all channels of one FPGA board are connected to the + // respective channel of the other FPGA board. + // No connections between nodes are made. - // Get all fpgas. - var fpga_nFirst_acl0 = nFirst.getFPGAFromFpgalink("acl0"); - var fpga_nFirst_acl1 = nFirst.getFPGAFromFpgalink("acl1"); - var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); - var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); - var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); - var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); - var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); - var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); - - // Connect channels specific to rinO - // - // A. - var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); - var A_dst; - if (j == srun_N - 1) { - A_dst = fpga_nFirst_acl1.getChannelFromFpgalink("ch0"); - } else { - A_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; - } - // - // B. - var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); - var B_dst; - if (j == srun_N - 1) { - B_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch0"); - } else { - B_dst = fpga_nNext_acl1.getChannelFromFpgalink("ch0");; - } - // - // C. - var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); - var C_dst; - if (j == srun_N - 1) { - C_dst = fpga_nFirst_acl1.getChannelFromFpgalink("ch2"); - } else { - C_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; - } - // - // D. - var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); - var D_dst; - if (j == srun_N - 1) { - D_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch2"); - } else { - D_dst = fpga_nNext_acl1.getChannelFromFpgalink("ch2");; - } + // Go over all nodes + for (i = 0; i < srun_N; i++) { + var node = fpganodes[i]; + // var shape = node.getShape(); - this.connectChannels(A_src, A_dst); - this.connectChannels(B_src, B_dst); - this.connectChannels(C_src, C_dst); - this.connectChannels(D_src, D_dst); + // Connect all channels from first FPGA to second FPGA. + var fpga0 = node.getFPGAFromFpgalink("acl0"); + var fpga1 = node.getFPGAFromFpgalink("acl1"); - // Set color for up. - // C_src.getConnector().setColor(ColorEnum.red); - // D_src.getConnector().setColor(ColorEnum.red); + // Go over all channels of FPGA. + var k = 0; + for (k = 0; k < 4; k++) { + this.connectChannels(fpga0.getChannelFromFpgalink("ch" + k), fpga1.getChannelFromFpgalink("ch" + k)); } + } + + // Arrange nodes for better visualization. + this.arrangeTopology("pair", fpganodes); - // Arrange nodes for better visualization. - this.arrangeTopology("ringN", fpganodes); + break; + case "clique": + // Only clique of 2 nodes is supported. + if (srun_N != 2) { + alert("Only clique of 2 nodes is supported."); break; - case "ringZ": - // Ring with two links per direction, acl0 and acl1 neighbors - // Idea: - // Special handling for first and last node in ring (peel, remainder), - // Loop for in-between nodes. - var j; - for (j = 0; j < srun_N; j++) { - // Get nodes. - var nFirst = fpganodes[0]; - // Previous - var nPrev; - if (j == 0) { - nPrev = fpganodes[0]; - } else { - nPrev = fpganodes[j - 1]; - } - // current node - var nCurrent = fpganodes[j]; - // next - var nNext; - if (j == srun_N - 1) { - nNext = fpganodes[j]; - } else { - nNext = fpganodes[j + 1]; - } + } - // Get all fpgas. - var fpga_nFirst_acl0 = nFirst.getFPGAFromFpgalink("acl0"); - var fpga_nFirst_acl1 = nFirst.getFPGAFromFpgalink("acl1"); - var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); - var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); - var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); - var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); - var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); - var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); - - // Connect channels specific to rinO - // - // A. - var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); - var A_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch0"); - // - // B. - var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); - var B_dst; - if (j == srun_N - 1) { - B_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch0"); - } else { - B_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; - } - // - // C. - var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); - var C_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch2");; - // - // D. - var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); - var D_dst; - if (j == srun_N - 1) { - D_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch2"); - } else { - D_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; - } + // Get both nodes. + var n00 = fpganodes[0]; + var n01 = fpganodes[1]; - this.connectChannels(A_src, A_dst); - this.connectChannels(B_src, B_dst); - this.connectChannels(C_src, C_dst); - this.connectChannels(D_src, D_dst); + // Get all fpgas + var fpga_n00_0 = n00.getFPGAFromFpgalink("acl0"); + var fpga_n00_1 = n00.getFPGAFromFpgalink("acl1"); + var fpga_n01_0 = n01.getFPGAFromFpgalink("acl0"); + var fpga_n01_1 = n01.getFPGAFromFpgalink("acl1"); - // Set color for up. - // C_src.getConnector().setColor(ColorEnum.red); - // D_src.getConnector().setColor(ColorEnum.red); - } + // Connect channels specific to clique + this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch0"), fpga_n01_0.getChannelFromFpgalink("ch0")); + this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch1"), fpga_n00_1.getChannelFromFpgalink("ch1")); + this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch2"), fpga_n01_1.getChannelFromFpgalink("ch2")); + this.connectChannels(fpga_n00_0.getChannelFromFpgalink("ch3"), fpga_n01_1.getChannelFromFpgalink("ch3")); - // Arrange nodes for better visualization. - this.arrangeTopology("ringZ", fpganodes); + this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch0"), fpga_n01_1.getChannelFromFpgalink("ch0")); + this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch2"), fpga_n01_0.getChannelFromFpgalink("ch2")); + this.connectChannels(fpga_n00_1.getChannelFromFpgalink("ch3"), fpga_n01_0.getChannelFromFpgalink("ch3")); - break; - // Torus - case "torus2": - // Torus with 2 FPGAs per row. - this.torusTopo(srun_N, 2, fpganodes); + this.connectChannels(fpga_n01_0.getChannelFromFpgalink("ch1"), fpga_n01_1.getChannelFromFpgalink("ch1")); - // Arrange nodes for better visualization. - this.arrangeTopology("torus2", fpganodes); + // Arrange nodes for better visualization. + this.arrangeTopology("clique", fpganodes); - break; - case "torus3": - // At least 2 nodes are required. - if (srun_N < 2) { - alert("Topology torus3 requires at least 2 nodes."); - break; + break; + // Ring + case "ringO": + // Idea: + // Special handling for first and last node in ring (peel, remainder), + // Loop for in-between nodes. + var j; + for (j = 0; j < srun_N; j++) { + // Get both nodes. + // Previous + var nPrev; + if (j == 0) { + nPrev = fpganodes[0]; + } else { + nPrev = fpganodes[j - 1]; + } + // current node + var nCurrent = fpganodes[j]; + // next + var nNext; + if (j == srun_N - 1) { + nNext = fpganodes[j]; + } else { + nNext = fpganodes[j + 1]; } - this.torusTopo(srun_N, 3, fpganodes); - - // Arrange nodes for better visualization. - this.arrangeTopology("torus3", fpganodes); + // Get all fpgas. + var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); + var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); + var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); + var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); + var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); + var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); - break; - case "torus4": - // At least 2 nodes are required. - if (srun_N < 2) { - alert("Topology torus4 requires at least 2 nodes."); - break; + // Connect channels specific to rinO + // + // A. + var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); + var A_dst; + if (j == srun_N - 1) { + A_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch0"); + } else { + A_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; + } + // + // B. + var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); + var B_dst; + if (j == 0) { + B_dst = fpga_nCurrent_acl0.getChannelFromFpgalink("ch0"); + } else { + B_dst = fpga_nPrev_acl1.getChannelFromFpgalink("ch0");; + } + // + // C. + var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); + var C_dst; + if (j == srun_N - 1) { + C_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch2"); + } else { + C_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; + } + // + // D. + var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); + var D_dst; + if (j == 0) { + D_dst = fpga_nCurrent_acl0.getChannelFromFpgalink("ch2"); + } else { + D_dst = fpga_nPrev_acl1.getChannelFromFpgalink("ch2");; } - this.torusTopo(srun_N, 4, fpganodes); + this.connectChannels(A_src, A_dst); + this.connectChannels(B_src, B_dst); + this.connectChannels(C_src, C_dst); + this.connectChannels(D_src, D_dst); - // Arrange nodes for better visualization. - this.arrangeTopology("torus4", fpganodes); + // // Set color for up. + // C_src.getConnector().setColor(ColorEnum.red); + // D_src.getConnector().setColor(ColorEnum.red); + } - break; - case "torus5": - // At least 3 nodes are required. - if (srun_N < 3) { - alert("Topology torus5 requires at least 3 nodes."); - break; - } + // Arrange nodes for better visualization. + this.arrangeTopology("ringO", fpganodes); - this.torusTopo(srun_N, 5, fpganodes); + break; + case "ringN": + // ringN, going down in acl0 column and back up in acl1 column + // Idea: + // Special handling for first and last node in ring (peel, remainder), + // Loop for in-between nodes. + var j; + for (j = 0; j < srun_N; j++) { + // Get nodes. + var nFirst = fpganodes[0]; + // Previous + var nPrev; + if (j == 0) { + nPrev = fpganodes[0]; + } else { + nPrev = fpganodes[j - 1]; + } + // current node + var nCurrent = fpganodes[j]; + // next + var nNext; + if (j == srun_N - 1) { + nNext = fpganodes[j]; + } else { + nNext = fpganodes[j + 1]; + } - // Arrange nodes for better visualization. - this.arrangeTopology("torus5", fpganodes); - break; - case "torus6": - // At least 3 nodes are required. - if (srun_N < 3) { - alert("Topology torus6 requires at least 3 nodes."); - break; + // Get all fpgas. + var fpga_nFirst_acl0 = nFirst.getFPGAFromFpgalink("acl0"); + var fpga_nFirst_acl1 = nFirst.getFPGAFromFpgalink("acl1"); + var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); + var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); + var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); + var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); + var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); + var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); + + // Connect channels specific to rinO + // + // A. + var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); + var A_dst; + if (j == srun_N - 1) { + A_dst = fpga_nFirst_acl1.getChannelFromFpgalink("ch0"); + } else { + A_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; + } + // + // B. + var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); + var B_dst; + if (j == srun_N - 1) { + B_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch0"); + } else { + B_dst = fpga_nNext_acl1.getChannelFromFpgalink("ch0");; + } + // + // C. + var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); + var C_dst; + if (j == srun_N - 1) { + C_dst = fpga_nFirst_acl1.getChannelFromFpgalink("ch2"); + } else { + C_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; + } + // + // D. + var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); + var D_dst; + if (j == srun_N - 1) { + D_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch2"); + } else { + D_dst = fpga_nNext_acl1.getChannelFromFpgalink("ch2");; } - this.torusTopo(srun_N, 6, fpganodes); + this.connectChannels(A_src, A_dst); + this.connectChannels(B_src, B_dst); + this.connectChannels(C_src, C_dst); + this.connectChannels(D_src, D_dst); - // Arrange nodes for better visualization. - this.arrangeTopology("torus6", fpganodes); + // Set color for up. + // C_src.getConnector().setColor(ColorEnum.red); + // D_src.getConnector().setColor(ColorEnum.red); + } - break; + // Arrange nodes for better visualization. + this.arrangeTopology("ringN", fpganodes); - // Custom link with format: n00:acl0:ch0-n00:acl1:ch0 - default: - // Parse and add fpga links: n00:acl0:ch0-n00:acl1:ch0 - var links = full_match.split("-"); - - // Point 1 (think of source). - // value: n00:acl0:ch0 or eth00 (for Ethernet switch). - var link_p1 = links[0].split(":"); - // Point 2 (think of destination). - // value: n00:acl0:ch0 or eth00 (for Ethernet switch). - var link_p2 = links[1].split(":"); - - // Channels to connect. Logic is required to differentiate if - // the channel is between FPGAs or to/from Ethernet switch. - let chan0; - let chan1; - - if (link_p1.length == 3) { - // Channel is from FPGA node. - // Get node. - var tnode_p1 = fpganodes[this.getNodeIdFpgalink(link_p1[0])]; - // Get FPGA. - var tfpga_p1 = tnode_p1.getFPGAFromFpgalink(link_p1[1]); - - // Get channel. - chan0 = tfpga_p1.getChannelFromFpgalink(link_p1[2]); + break; + case "ringZ": + // Ring with two links per direction, acl0 and acl1 neighbors + // Idea: + // Special handling for first and last node in ring (peel, remainder), + // Loop for in-between nodes. + var j; + for (j = 0; j < srun_N; j++) { + // Get nodes. + var nFirst = fpganodes[0]; + // Previous + var nPrev; + if (j == 0) { + nPrev = fpganodes[0]; } else { - // Channel is to ethernet switch. - chan0 = this.getSwitchFromName(link_p1[0], eth_switches) + nPrev = fpganodes[j - 1]; + } + // current node + var nCurrent = fpganodes[j]; + // next + var nNext; + if (j == srun_N - 1) { + nNext = fpganodes[j]; + } else { + nNext = fpganodes[j + 1]; } - if (link_p2.length == 3) { - // Channel is to FPGA node. - - // Get node. - var tnode_p2 = fpganodes[this.getNodeIdFpgalink(link_p2[0])]; - // Get FPGA. - var tfpga_p2 = tnode_p2.getFPGAFromFpgalink(link_p2[1]); - var isSibling = link_p2[0] == link_p1[0] && link_p2[1] == link_p1[1] && link_p2[2] == link_p1[2]; - chan1 = tfpga_p2.getChannelFromFpgalink(link_p2[2], isSibling); + // Get all fpgas. + var fpga_nFirst_acl0 = nFirst.getFPGAFromFpgalink("acl0"); + var fpga_nFirst_acl1 = nFirst.getFPGAFromFpgalink("acl1"); + var fpga_nPrev_acl0 = nPrev.getFPGAFromFpgalink("acl0"); + var fpga_nPrev_acl1 = nPrev.getFPGAFromFpgalink("acl1"); + var fpga_nCurrent_acl0 = nCurrent.getFPGAFromFpgalink("acl0"); + var fpga_nCurrent_acl1 = nCurrent.getFPGAFromFpgalink("acl1"); + var fpga_nNext_acl0 = nNext.getFPGAFromFpgalink("acl0"); + var fpga_nNext_acl1 = nNext.getFPGAFromFpgalink("acl1"); + + // Connect channels specific to rinO + // + // A. + var A_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch1"); + var A_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch0"); + // + // B. + var B_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch1"); + var B_dst; + if (j == srun_N - 1) { + B_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch0"); } else { - // Channel is to ethernet switch. - chan1 = this.getSwitchFromName(link_p2[0], eth_switches) + B_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch0");; } + // + // C. + var C_src = fpga_nCurrent_acl0.getChannelFromFpgalink("ch3"); + var C_dst = fpga_nCurrent_acl1.getChannelFromFpgalink("ch2");; + // + // D. + var D_src = fpga_nCurrent_acl1.getChannelFromFpgalink("ch3"); + var D_dst; + if (j == srun_N - 1) { + D_dst = fpga_nFirst_acl0.getChannelFromFpgalink("ch2"); + } else { + D_dst = fpga_nNext_acl0.getChannelFromFpgalink("ch2");; + } + + this.connectChannels(A_src, A_dst); + this.connectChannels(B_src, B_dst); + this.connectChannels(C_src, C_dst); + this.connectChannels(D_src, D_dst); + + // Set color for up. + // C_src.getConnector().setColor(ColorEnum.red); + // D_src.getConnector().setColor(ColorEnum.red); + } + + // Arrange nodes for better visualization. + this.arrangeTopology("ringZ", fpganodes); + + break; + // Torus + case "torus2": + // Torus with 2 FPGAs per row. + this.torusTopo(srun_N, 2, fpganodes); + + // Arrange nodes for better visualization. + this.arrangeTopology("torus2", fpganodes); + + break; + case "torus3": + // At least 2 nodes are required. + if (srun_N < 2) { + alert("Topology torus3 requires at least 2 nodes."); + break; + } - // Get channels, connect and draw them. - // console.log(srun_raw); - // console.log(eth_switches); - // console.log("The 2 channels are: ", chan0, chan1); - this.connectChannels(chan0, chan1); + this.torusTopo(srun_N, 3, fpganodes); - // if(link_p1[2] == "ch0") { - // tfpga_p1.getChannelFromFpgalink(link_p1[2]).getConnector().setColor(ColorEnum.red); - // } + // Arrange nodes for better visualization. + this.arrangeTopology("torus3", fpganodes); + break; + case "torus4": + // At least 2 nodes are required. + if (srun_N < 2) { + alert("Topology torus4 requires at least 2 nodes."); break; - } + } - // Remove found link. - srun_raw_copy = srun_raw_copy.substring(next_space); - } + this.torusTopo(srun_N, 4, fpganodes); - - // Parse and add fpga links: n00:acl0:ch0-n00:acl1:ch0 - if (srun_raw.indexOf(srun_fpgalinks_needle) == -1) { - // Array(7) [ "n00:acl1:ch0-n00:acl1:ch1", "00", "1", "0", "00", "1", "1" ] - // Array(9)["n00:acl0:ch1-eth", "n00:acl0:ch1", "n00", "acl0", "ch1", "eth", undefined, undefined, undefined] - for (var i = 0; i < fpgalinks.length; i++) { + // Arrange nodes for better visualization. + this.arrangeTopology("torus4", fpganodes); + + break; + case "torus5": + // At least 3 nodes are required. + if (srun_N < 3) { + alert("Topology torus5 requires at least 3 nodes."); + break; + } + + this.torusTopo(srun_N, 5, fpganodes); + + // Arrange nodes for better visualization. + this.arrangeTopology("torus5", fpganodes); + break; + case "torus6": + // At least 3 nodes are required. + if (srun_N < 3) { + alert("Topology torus6 requires at least 3 nodes."); + break; + } + + this.torusTopo(srun_N, 6, fpganodes); + + // Arrange nodes for better visualization. + this.arrangeTopology("torus6", fpganodes); + + break; + + // Custom link with format: n00:acl0:ch0-n00:acl1:ch0 + default: // Parse and add fpga links: n00:acl0:ch0-n00:acl1:ch0 - var links = fpgalinks[i][0].split("-"); + var links = full_match.split("-"); // Point 1 (think of source). - // value: n00:acl0:ch0 or eth (for Ethernet switch). + // value: n00:acl0:ch0 or eth00 (for Ethernet switch). var link_p1 = links[0].split(":"); // Point 2 (think of destination). - // value: n00:acl0:ch0 or eth (for Ethernet switch). + // value: n00:acl0:ch0 or eth00 (for Ethernet switch). var link_p2 = links[1].split(":"); // Channels to connect. Logic is required to differentiate if @@ -823,7 +828,7 @@ example.Toolbar = Class.extend({ if (link_p1.length == 3) { // Channel is from FPGA node. // Get node. - var tnode_p1 = fpganodes[this.getNodeIdFpgalink(link_p1[0])]; + var tnode_p1 = this.getNodeIdFpgalink(link_p1[0], fpganodes); // Get FPGA. var tfpga_p1 = tnode_p1.getFPGAFromFpgalink(link_p1[1]); @@ -831,30 +836,35 @@ example.Toolbar = Class.extend({ chan0 = tfpga_p1.getChannelFromFpgalink(link_p1[2]); } else { // Channel is to ethernet switch. - chan0 = this.getSwitchFromName(link_p1[0], eth_switches); + chan0 = this.getSwitchFromName(link_p1[0], eth_switches) } if (link_p2.length == 3) { // Channel is to FPGA node. // Get node. - var tnode_p2 = fpganodes[this.getNodeIdFpgalink(link_p2[0])]; + var tnode_p2 = this.getNodeIdFpgalink(link_p2[0], fpganodes); // Get FPGA. var tfpga_p2 = tnode_p2.getFPGAFromFpgalink(link_p2[1]); - - chan1 = tfpga_p2.getChannelFromFpgalink(link_p2[2]); + var isSibling = link_p2[0] == link_p1[0] && link_p2[1] == link_p1[1] && link_p2[2] == link_p1[2]; + chan1 = tfpga_p2.getChannelFromFpgalink(link_p2[2], isSibling); } else { // Channel is to ethernet switch. - chan1 = this.getSwitchFromName(link_p2[0], eth_switches); + chan1 = this.getSwitchFromName(link_p2[0], eth_switches) } // Get channels, connect and draw them. + // console.log(srun_raw); + // console.log(eth_switches); + // console.log("The 2 channels are: ", chan0, chan1); this.connectChannels(chan0, chan1); - } - } - - + // if(link_p1[2] == "ch0") { + // tfpga_p1.getChannelFromFpgalink(link_p1[2]).getConnector().setColor(ColorEnum.red); + // } + + break; + } }, makeGrid: function (N, width) { @@ -909,7 +919,7 @@ example.Toolbar = Class.extend({ // 0: n00 // 1: acl0 // Get node. - var tnode_p1 = fpganodes[this.getNodeIdFpgalink(link_p1[0])]; + var tnode_p1 = this.getNodeIdFpgalink(link_p1[0], fpganodes); // Get FPGA. var tfpga_p1 = tnode_p1.getFPGAFromFpgalink(link_p1[1]); @@ -918,7 +928,7 @@ example.Toolbar = Class.extend({ // 0: n00 // 1: acl0 // Get node. - var tnode_p2 = fpganodes[this.getNodeIdFpgalink(link_p2[0])]; + var tnode_p2 = this.getNodeIdFpgalink(link_p2[0], fpganodes); // Get FPGA. var tfpga_p2 = tnode_p2.getFPGAFromFpgalink(link_p2[1]); @@ -927,7 +937,7 @@ example.Toolbar = Class.extend({ // 0: n00 // 1: acl0 // Get node. - var tnode_p3 = fpganodes[this.getNodeIdFpgalink(link_p3[0])]; + var tnode_p3 = this.getNodeIdFpgalink(link_p3[0], fpganodes); // Get FPGA. var tfpga_p3 = tnode_p3.getFPGAFromFpgalink(link_p3[1]); @@ -943,10 +953,10 @@ example.Toolbar = Class.extend({ } }, - printTopo : function(list, format='acl:ch', separator=' <-> ', prefix='') { + printTopo: function (list, format = 'acl:ch', separator = ' <-> ', prefix = '') { var row = 0; - for(row = 0; row < list.length; row++) { - console.log(prefix+separator+((list[row]))) + for (row = 0; row < list.length; row++) { + console.log(prefix + separator + ((list[row]))) } }, @@ -959,43 +969,43 @@ example.Toolbar = Class.extend({ // // Draw connection only ones. // if (!tchannel_p1.getIsDrawn()) { - var c = new HoverConnection(); - - // In case of ethernet switch, distirbute the connections over all - // ports, this is just visiual optimization - // Idea: get all ports, and pick the first port with least amount of connections - - function getLeastPort(ch) { - let port = ch.getPorts().data[0]; - if (ch.getPorts().data.length > 1) { - for (let i = 0; i < ch.getPorts().data.length; i++) { - const p = ch.getPorts().data[i]; - if (p.connections.data.length < port.connections.data.length) { - port = p; - } + var c = new HoverConnection(); + + // In case of ethernet switch, distirbute the connections over all + // ports, this is just visiual optimization + // Idea: get all ports, and pick the first port with least amount of connections + + function getLeastPort(ch) { + let port = ch.getPorts().data[0]; + if (ch.getPorts().data.length > 1) { + for (let i = 0; i < ch.getPorts().data.length; i++) { + const p = ch.getPorts().data[i]; + if (p.connections.data.length < port.connections.data.length) { + port = p; } } - - return port; } - let sourcePort = getLeastPort(tchannel_p1); - let targetPort = getLeastPort(tchannel_p2); - - c.setSource(sourcePort); - c.setTarget(targetPort); + return port; + } - // Add connector to model. - tchannel_p1.setConnector(c); - tchannel_p2.setConnector(c); + let sourcePort = getLeastPort(tchannel_p1); + let targetPort = getLeastPort(tchannel_p2); - // // Flag both connectors as drawn. - // tchannel_p1.setIsDrawn(true); - // tchannel_p2.setIsDrawn(true); + c.setSource(sourcePort); + c.setTarget(targetPort); - // create a command for the undo/redo support - var command = new draw2d.command.CommandAdd(this.view, c, 0, 0); - this.view.getCommandStack().execute(command); + // Add connector to model. + tchannel_p1.setConnector(c); + tchannel_p2.setConnector(c); + + // // Flag both connectors as drawn. + // tchannel_p1.setIsDrawn(true); + // tchannel_p2.setIsDrawn(true); + + // create a command for the undo/redo support + var command = new draw2d.command.CommandAdd(this.view, c, 0, 0); + this.view.getCommandStack().execute(command); // } }, @@ -1053,7 +1063,7 @@ example.Toolbar = Class.extend({ // See: https://wikis.uni-paderborn.de/pc2doc/FPGA_Serial_Channels#Ring_topology node_fpga0_channels.get(1).getHybridPort(0).getConnections().get(0).setColor(ColorEnum.blue) node_fpga0_channels.get(3).getHybridPort(0).getConnections().get(0).setColor(ColorEnum.blue) - } + } break; // Torus diff --git a/gui/Util.js b/gui/Util.js index 92d4898..1a0cc2d 100644 --- a/gui/Util.js +++ b/gui/Util.js @@ -1,59 +1,173 @@ const ColorEnum = Object.freeze({ - "red": "f3546a", - "yellow": "FFFF99", - "green": "b9dd69", - "blue": "00A8F0" + "red": "f3546a", + "yellow": "FFFF99", + "green": "b9dd69", + "blue": "00A8F0" }); function pad_node_name(num) { - var s = "0" + num; - return "n" + s.substr(s.length - 2); + var s = "0" + num; + return "n" + s.substr(s.length - 2); } function generate_fpgalink_output(channel) { - let fpgalink = ""; - // channel is either of type ChannelShape (if connected to FPGA node) - // or "Ethernet Switch" (if connected to the switch) - if(channel.getText().includes("Ethernet Switch")) { - num = channel.getText().split(" ")[2] - fpgalink = "eth" + num; - } else { - var parent_fpga = channel.getFPGA(); - var parent_node = parent_fpga.getNode(); + let fpgalink = ""; + // channel is either of type ChannelShape (if connected to FPGA node) + // or "Ethernet Switch" (if connected to the switch) + if (channel.getText().includes("Ethernet Switch")) { + num = channel.getText().split(" ")[2] + fpgalink = "eth" + num; + } else { + var parent_fpga = channel.getFPGA(); + var parent_node = parent_fpga.getNode(); - var channelName = "ch" + channel.getText().substring(8) + var channelName = "ch" + channel.getText().substring(8) - fpgalink = parent_node.getName() + ":" + parent_fpga.getName() + ":" + channelName; - } + fpgalink = parent_node.getName() + ":" + parent_fpga.getName() + ":" + channelName; + } - return fpgalink; + return fpgalink; } function get_number_of_fpga_nodes(figures) { - let number_of_fpga_nodes = 0; + let number_of_fpga_nodes = 0; - let figure = figures.data; + let figure = figures.data; - for(let i = 0; i < figure.length; i++) { - if (figure.at(i).NAME == "NodeShape") { - number_of_fpga_nodes++ + for (let i = 0; i < figure.length; i++) { + if (figure.at(i).NAME == "NodeShape") { + number_of_fpga_nodes++ + } } - } - return number_of_fpga_nodes; + return number_of_fpga_nodes; } function get_number_of_switch_nodes(figures) { - let number_of_switch_nodes = 0; + let number_of_switch_nodes = 0; + + let figure = figures.data; + + for (let i = 0; i < figure.length; i++) { + if (figure.at(i).NAME == "SwitchShape") { + number_of_switch_nodes++ + } + } + + return number_of_switch_nodes; +} + +function toggle_non_config_ports(figures, action, myType) { + // Loop over all figures and all ports and hide all non-config ports + config-ports from other node type + for (let i = 0; i < figures.length; i++) { + const figure = figures[i]; + if (figure instanceof NodeShape) { + + if (action == "hide") { + // If its not same type as me, hide its config_port + if ((myType != "Switch" && figure.getType() != myType) || (myType == "Switch" && figure.getType() == "Intel")) { + figure.getHybridPort(0).setVisible(false); + } + } else { + // Show all config_port again + figure.getHybridPort(0).setVisible(true); + } + + let channelPorts = figure.getChannelPorts(); + + for (let k = 0; k < channelPorts.length; k++) { + const p = channelPorts[k]; + + if (action == "hide") { + p.setVisible(false); + } else { + // Show only ports that does not have any connection + if (!p.connections.data.length && p.parent.siblingChannel) { + p.setVisible(true); + } + } + } + } else if (figure instanceof SwitchShape) { + // toggle all ports execpt last one (it is the config port) + for (let i = 0; i < figure.hybridPorts.data.length - 1; i++) { + const p = figure.hybridPorts.data[i]; + p.setVisible(action == "show"); + } + + // If I am a switch, toggle the config port + if (myType == "Switch" || myType == "Intel") { + figure.getHybridPort(8).setVisible(action == "show"); + } + } + } +} - let figure = figures.data; +function toggle_config_ports(figures, isVisible) { + // Loop over all figures and all ports and hide all config ports + for (let i = 0; i < figures.length; i++) { + const figure = figures[i]; + if (figure instanceof NodeShape) { + figure.getHybridPort(0).setVisible(isVisible); + } else if (figure instanceof SwitchShape) { + // The config port is the last port + figure.getHybridPort(figure.hybridPorts.data.length - 1).setVisible(isVisible) + } + } +} - for(let i = 0; i < figure.length; i++) { - if (figure.at(i).NAME == "SwitchShape") { - number_of_switch_nodes++ +function toggle_all_switch_ports(figures, isVisible) { + for (let i = 0; i < figures.length; i++) { + const figure = figures[i]; + if (figure instanceof SwitchShape) { + // The config port is the last port + figure.hybridPorts.data.forEach(port => { + port.setVisible(isVisible) + }); + } } - } +} + +function delete_connections(connections, canvas, addToStack=true) { + for (let i = 0; i < connections.length; i++) { + const conn = connections[i]; - return number_of_switch_nodes; + if (addToStack) { + var cmd = new draw2d.command.CommandDelete(conn); + canvas.getCommandStack().execute(cmd); + } else { + canvas.remove(conn); + } + } } + +function connectBasedOnConfig(nodes, config, eth_switch) { + // Both are for sure same type + let nodeType = nodes[0].getType(); + let nbOfFPGAs = nodeType == "Intel" ? 2 : 3; + let nbOfChannels = nodeType == "Intel" ? 4 : 2; + + for (let i = 0; i < nbOfFPGAs; i++) { + for (let j = 0; j < nbOfChannels; j++) { + + if (config == "one-by-one") { + if (eth_switch) { + let fpgalink_cmd = `${nodes[0].getName()}:acl${i}:ch${j}-${eth_switch.getName()}`; + app.toolbar.createNodesAndConnections(fpgalink_cmd, 2, nodes, [eth_switch]) + } else { + let fpgalink_cmd = `${nodes[0].getName()}:acl${i}:ch${j}-${nodes[1].getName()}:acl${i}:ch${j}`; + app.toolbar.createNodesAndConnections(fpgalink_cmd, 2, nodes, []) + } + } else if (config == "loopback") { + let fpgalink_cmd = `${nodes[0].getName()}:acl${i}:ch${j}-${nodes[0].getName()}:acl${i}:ch${j}`; + app.toolbar.createNodesAndConnections(fpgalink_cmd, 2, nodes, []) + } else if (config == "channel") { + if (j % 2 == 0) { + let fpgalink_cmd = `${nodes[0].getName()}:acl${i}:ch${j}-${nodes[0].getName()}:acl${i}:ch${j + 1}`; + app.toolbar.createNodesAndConnections(fpgalink_cmd, 1, nodes, []) + } + } + + } + } +} \ No newline at end of file diff --git a/index.html b/index.html index 30542e9..eead10a 100755 --- a/index.html +++ b/index.html @@ -66,14 +66,17 @@ for (let i = 0; i < connections.getSize(); i++) { var connection = connections.get(i); - // Parent is ChannelShape. - let source_channel = connection.getSource().getParent(); - let target_channel = connection.getTarget().getParent(); + // Ignore in case this is a config connection + if (!connection.sourcePort.name.includes("config_port")) { + // Parent is ChannelShape. + let source_channel = connection.getSource().getParent(); + let target_channel = connection.getTarget().getParent(); - let source_fpgalink_text = generate_fpgalink_output(source_channel); - let target_fpgalink_text = generate_fpgalink_output(target_channel); + let source_fpgalink_text = generate_fpgalink_output(source_channel); + let target_fpgalink_text = generate_fpgalink_output(target_channel); - srun_export += " --fpgalink=" + source_fpgalink_text + "-" + target_fpgalink_text + ""; + srun_export += " --fpgalink=" + source_fpgalink_text + "-" + target_fpgalink_text + ""; + } } // Export --fpgalink. @@ -99,9 +102,6 @@ // Special case to replace eth with eth00 srun_cmd = srun_cmd.replace(/eth(?!\d{2})/g, 'eth00') - console.log( "hi9" ,srun_cmd); - - var get_node_type = ""; if (urlParams.has('node-type') && @@ -188,7 +188,32 @@
-
+
+ + +
+
+ + +
+
Configure Connection:
+ +
Rings
+ +