Commit 3fbf3094 authored by uahhx's avatar uahhx

sync

TODO: test slinky buffer
implement strategies
parent 034cd782
......@@ -2,11 +2,13 @@ package FunnelNetSim;
public class DataPacket {
private messageType mType;
private messageState mState;
private int originNode;
private static int packetIDCounter = 0; //just for behavioral evaluation (beeva)
private int packetID;
private int latencyCounter;
private boolean processed; //just for beeva
private int timeStamp; //for beeva, but also used by global timestamp strategy
//private boolean isControlPacket; //might want to implement just unsing a bool later on, for info it might be better to use the enum though
public enum messageType {
......@@ -14,21 +16,42 @@ public class DataPacket {
}
public enum messageState {
UNPROCESSED, PROCESSED, REJECTED, OUTDATED, DROPPED
UNPROCESSED, PROCESSED, REJECTED, DROP
}
public DataPacket(int originNode, int timeStamp) {
initDataPacket(originNode, timeStamp, messageType.REGULAR, messageState.UNPROCESSED);
}
public DataPacket(int originNode, int timeStamp, messageType mType) {
initDataPacket(originNode, timeStamp, mType, messageState.UNPROCESSED);
}
public DataPacket(int originNode, int timeStamp, messageType mType, messageState mState) {
initDataPacket(originNode, timeStamp, mType, mState);
}
public DataPacket(int originNode, messageType mType) {
private void initDataPacket(int originNode, int timeStamp, messageType mType, messageState mState) {
this.originNode = originNode;
this.mType = mType;
this.packetID = mType == messageType.REGULAR ? packetIDCounter++ : -1;
this.mState = mState;
this.timeStamp = timeStamp;
resetLatencyCounter();
processed = false;
}
public messageType getMType() {
return this.mType;
}
public void setMState(messageState newMState) {
mState = newMState;
}
public messageState getMState() {
return mState;
}
public int getOrigin() {
return originNode;
}
......@@ -46,15 +69,11 @@ public class DataPacket {
return --latencyCounter <= 0;
}
public void markProcessed() {
processed = true;
}
public boolean isProcessed() {
return processed;
}
public int getPacketID() {
return packetID;
}
public int getTimeStamp() {
return timeStamp;
}
}
......@@ -4,22 +4,25 @@ import java.util.HashSet;
import FunnelNetSim.Nodes.*;
import FunnelNetSim.Strategies.Strategy;
import FunnelNetSim.Strategies.TestStrategy;
public class FunnelNet {
//TODO: de-static that mess
public static final Strategy strat = new TestStrategy();
public final Strategy strategy;
private int cycleCounter = 0;
public static final boolean verbose = true;
public static final int packetLatency = 1; //in cycles
public static final int controlPacketSize = 1; //for slinkyBuffer. warning: if this changes from 1, handling of sending multiple segments has to be implemented
//public static final int dataWidth = 64/8; //dataWidth in number of segments per transmission. this should be a round number even if it wasn't forced by type.
public static final int bufferSize = 16; //max # of packets per buffer
public static final int bufferSize = 8; //max # of packets per buffer
//public static final int bufferSize = 4 + packetLatency*2; //max # of packets per buffer
public final int realTimeConstraint = 10000; //RTC in ns
public final int nodeClock = 125; //node Clockspeed in MHz
public final int rtcCycles = (realTimeConstraint*nodeClock)/1000;
public static final int numDownConnections = 1;//7; //total number of connections is this+1
private static final int numSlaves = 1; //7*7*7*7;
......@@ -33,7 +36,8 @@ public class FunnelNet {
public static int packetCounter = 0;
public FunnelNet() { //for now no numUpConnections
public FunnelNet(Strategy strategy) { //for now no numUpConnections
this.strategy = strategy;
createNet();
System.out.println("Number of Layers: " + numLayers);
System.out.println("Number of Slaves: " + numSlaves);
......@@ -41,7 +45,7 @@ public class FunnelNet {
private void createNet() {
int layerNumber = 0;
master = new MasterNode(layerNumber, 0);
master = new MasterNode(layerNumber, 0, this);
master.setSuperNeighbor(null);
HashSet<Node> curLayerNodes = new HashSet<Node>();
......@@ -63,7 +67,7 @@ public class FunnelNet {
for(Node curNode : prevLayerNodes) {
NetNode[] newNetNodes = new NetNode[numNewNodes];
for (int i = 0; i < newNetNodes.length; i++) {
NetNode curNewNode = new NetNode(layerNumber, curNode.getNodeNumber()*numNewNodes+i);
NetNode curNewNode = new NetNode(layerNumber, curNode.getNodeNumber()*numNewNodes+i, this);
curNewNode.setSuperNeighbor(curNode);
newNetNodes[i] = curNewNode;
netNodes.add(curNewNode);
......@@ -90,7 +94,7 @@ public class FunnelNet {
//for (int i = 0; i < newSlaveNodes.length - homogeneousReduction - (inhomogeneousReduction > 0 ? 1 : 0); i++) {
SlaveNode[] newSlaveNodes = new SlaveNode[numNewNodes - homogeneousReduction - (inhomogeneousReduction > 0 ? 1 : 0)];
for (int i = 0; i < newSlaveNodes.length; i++) {
SlaveNode curNewNode = new SlaveNode(layerNumber, curNode.getNodeNumber()*numNewNodes+i);
SlaveNode curNewNode = new SlaveNode(layerNumber, curNode.getNodeNumber()*numNewNodes+i, this);
curNewNode.setSuperNeighbor(curNode);
curNewNode.setSubNeighbors(new Node[0]);
newSlaveNodes[i] = curNewNode;
......@@ -113,11 +117,10 @@ public class FunnelNet {
}
public int tickNet() {
cycleCounter++;
for(Node curNode : allNodes)
curNode.updateLines();
curNode.preTickUpdateLines();
for(Node curNode : allNodes)
curNode.tick();
return cycleCounter;
return cycleCounter++;
}
}
}
\ No newline at end of file
package FunnelNetSim.Nodes;
import FunnelNetSim.DataPacket;
import FunnelNetSim.FunnelNet;
public class MasterNode extends Node {
public MasterNode(int layerNumber, int nodeNumber) {
super(layerNumber, nodeNumber);
public MasterNode(int layerNumber, int nodeNumber, FunnelNet parentNet) {
super(layerNumber, nodeNumber, parentNet);
}
@Override
public void updateLines() {
public void preTickUpdateLines() {
updateSubLines();
}
......@@ -17,8 +20,10 @@ public class MasterNode extends Node {
//select receive element
superIncoming = selectFromFrontRow(); //uses the superIncoming variable because downwardCom refers to it. /should/ run smoothly. TODO: make sure this actually does run smoothly
if (superIncoming != null)
superIncoming.markProcessed();
if (superIncoming != null) {
System.out.println("Master processing " + superIncoming.toString());
superIncoming.setMState(DataPacket.messageState.PROCESSED);
}
downwardCom();
//send element back
}
......
package FunnelNetSim.Nodes;
public class NetNode extends Node {
import FunnelNetSim.FunnelNet;
public class NetNode extends Node {
public NetNode(int layerNumber, int nodeNumber) {
super(layerNumber, nodeNumber);
public NetNode(int layerNumber, int nodeNumber, FunnelNet parentNet) {
super(layerNumber, nodeNumber, parentNet);
}
@Override
public void updateLines() {
public void preTickUpdateLines() {
updateSuperLine();
updateSubLines();
}
......@@ -17,7 +18,8 @@ public class NetNode extends Node {
public void tick() {
super.tick();
send(selectFromFrontRow(), superNeighbor);
if (superSendEnableS)
send(selectFromFrontRow(), superNeighbor);
downwardCom();
}
......
......@@ -2,6 +2,7 @@ package FunnelNetSim.Nodes;
import FunnelNetSim.DataPacket;
import FunnelNetSim.FunnelNet;
import FunnelNetSim.SimHost;
import FunnelNetSim.Strategies.Strategy;
import java.util.ArrayList;
......@@ -11,29 +12,32 @@ public abstract class Node {
private int layerNumber;
private int nodeNumber; //only slave nodes actually require this, but it helps with the overview if every node holds it
public final FunnelNet parentNet;
protected Strategy strategy = null;
protected Node superNeighbor;
private Node[] subNeighbors;
protected Node superNeighbor = null;
private Node[] subNeighbors = null;
protected ArrayList<SlinkyBuffer<DataPacket>> superBuffers;
private LinkedList<DataPacket> superIncomingLine;
protected DataPacket superIncoming;
protected ArrayList<SlinkyBuffer<DataPacket>> superBuffers = null;
private LinkedList<DataPacket> superIncomingLine = null;
protected DataPacket superIncoming = null;
protected ArrayList<SlinkyBuffer<DataPacket>> subBuffers;
private ArrayList<LinkedList<DataPacket>> subIncomingLines;
protected DataPacket[] subIncoming;
protected ArrayList<SlinkyBuffer<DataPacket>> subBuffers = null;
private ArrayList<LinkedList<DataPacket>> subIncomingLines = null;
protected DataPacket[] subIncoming = null;
//subFirstElement could be skipped by putting the incomings into the buffer and immediatly reading them from there,
//but muliplexing incomings and buffered data is to emulate how the hardware would work and make code adaptation easier
protected DataPacket[] subFrontRow;
protected DataPacket[] subFrontRow = null;
protected boolean superSendEnableS; //this is >received< from super. S for slave
private boolean[] subSendEnableM; //this is >sent< to subs. M for master
public Node(int layerNumber, int nodeNumber) {
public Node(int layerNumber, int nodeNumber, FunnelNet parentNet) {
this.layerNumber = layerNumber;
this.nodeNumber = nodeNumber;
this.subIncoming = null;
this.superIncoming = null;
this.strategy = parentNet.strategy.makeNew();
this.parentNet = parentNet;
}
public void setSuperNeighbor(Node superNeighbor) {
......@@ -79,7 +83,7 @@ public abstract class Node {
}
//handle incoming data. call all nodes pretick before tick to keep things "parallel"
public abstract void updateLines();
public abstract void preTickUpdateLines();
protected void updateSuperLine() {
superIncoming = updateLine(superIncomingLine);
......@@ -96,6 +100,8 @@ public abstract class Node {
if (line.get(i).decrementLatencyCounter()) {
if(i != line.size()-1)
System.out.println("Warning: Line holds Packets beyond the currently forwarded one!");
if (SimHost.verbose)
System.out.println("Packet reached " + this.toString());
return line.remove(i);
}
return null;
......@@ -106,8 +112,9 @@ public abstract class Node {
//doesn't hurt the master to keep this
if (superIncoming != null) {
DataPacket.messageType mT = superIncoming.getMType();
if (mT != DataPacket.messageType.REGULAR) {
superSendEnableS = mT == DataPacket.messageType.STOPSTART;
if (mT == DataPacket.messageType.STOPSTART) {
lockNodeToggle();
//superSendEnableS ^= true;
superIncoming = null; //remove packet so it doesn't get handled by the code for regular data packets. in vhdl this will need to be multiplexed
}
}
......@@ -122,7 +129,7 @@ public abstract class Node {
/**
* Builds an array containing the first elements of all incoming lines, returns the DataPacket selected by the set strategy
* Removes the selected DataPacket from its source in the process!
* !! Removes the selected DataPacket from its source in the process !!
* @return DataPacket selected for forwarding by the set strategy
*/
protected DataPacket selectFromFrontRow() {
......@@ -133,7 +140,7 @@ public abstract class Node {
subFrontRow[i] = subBuffers.get(i).lookAtBuffer();
}
int subSelect = FunnelNet.strat.selectForwardingSub(subFrontRow);
int subSelect = strategy.selectForwardingSub(subFrontRow);
if(subSelect >= 0) {
if(subBuffers.get(subSelect).isEmpty())
......@@ -155,24 +162,41 @@ public abstract class Node {
int superIncDest = superIncoming != null ? getLocalOrigin(superIncoming.getOrigin()) : -1;
SlinkyBuffer<DataPacket> curSubBuf;
SlinkyBuffer<DataPacket> curSuperBuf;
DataPacket selectedMessage;
DataPacket selectedMessage = null;
for (int i = 0; i < subNeighbors.length; i++) {
curSubBuf = subBuffers.get(i);
curSuperBuf = superBuffers.get(i);
curSubBuf.add(subIncoming[i]);
if (curSubBuf.limitReached() == subSendEnableM[i]) { //if the limit is reached and the sub is currently allowed to send (or vice versa), send control packet
subSendEnableM[i] = !curSubBuf.limitReached();
send(new DataPacket(-1, DataPacket.messageType.STOPSTART), subNeighbors[i]); //send StartStop K-Flagged segment.
if (subFrontRow[i] != null && subFrontRow[i].getMState() != DataPacket.messageState.UNPROCESSED) {
DataPacket message = subFrontRow[i];
if (subIncoming[i] == message)
subIncoming[i] = null;
else
subBuffers.get(i).takeFromBuffer();
if (message.getMState() == DataPacket.messageState.REJECTED)
selectedMessage = message;
subFrontRow[i] = null; //just to make sure.
}
//TODO: insert rejection method here
else if (!curSuperBuf.isEmpty() || superIncDest == i) {
send(curSuperBuf.isEmpty() ? superIncoming : curSuperBuf.takeFromBuffer(), subNeighbors[i]);
if (!curSuperBuf.isEmpty() && superIncDest == i) {
curSuperBuf.add(superIncoming);
if (curSuperBuf.limitReached())
System.out.println("a superbuffer ran over! this should not be happening!"); //NOTE: use this <PLACE> to check super buffer fill state later (implement buffer.size())
if (selectedMessage == null) {
curSubBuf.add(subIncoming[i]);
if (curSubBuf.limitReached() == subSendEnableM[i]) { //if the limit is reached and the sub is currently allowed to send (or vice versa), send control packet
subSendEnableM[i] = !curSubBuf.limitReached();
selectedMessage = new DataPacket(-1, parentNet.getCycleCounter(), DataPacket.messageType.STOPSTART); //send StartStop K-Flagged segment.
}
else if (!curSuperBuf.isEmpty() || superIncDest == i) {
selectedMessage = curSuperBuf.isEmpty() ? superIncoming : curSuperBuf.takeFromBuffer();
if (curSuperBuf.isEmpty())
superIncoming = null;
}
}
if (superIncDest == i && superIncoming != null) {
curSuperBuf.add(superIncoming);
superIncoming = null;
if (curSuperBuf.limitReached())
System.out.println("a superbuffer ran over! this should not be happening!"); //NOTE: use this <PLACE> to check super buffer fill state later (implement buffer.size())
}
if (selectedMessage != null)
send(selectedMessage, subNeighbors[i]);
}
}
......@@ -220,14 +244,14 @@ public abstract class Node {
public void receive(DataPacket message, int subNumber) {
if (subNumber == -2) {
System.out.println("Received Message from an unconnected source!");
return;
//return;
}
LinkedList<DataPacket> incomingLine = subNumber < 0 ? superIncomingLine : subIncomingLines.get(subNumber);
message.resetLatencyCounter();
incomingLine.addFirst(message);
if (FunnelNet.verbose)
System.out.println(nodeID() + " received Message no. " + message.getPacketID() + " from " + (subNumber < -1 ? "unconnected" : (subNumber == -1 ? superNeighbor.nodeID() : (subNumber >= 0 ? subNeighbors[subNumber].nodeID() : subNumber))));
if (SimHost.verbose)
System.out.println(nodeID() + " receiving Message no. " + message.getPacketID() + " from " + (subNumber < -1 ? "unconnected" : (subNumber == -1 ? superNeighbor.nodeID() : (subNumber >= 0 ? subNeighbors[subNumber].nodeID() : subNumber))));
}
public String nodeID() {
......@@ -249,4 +273,21 @@ public abstract class Node {
public int getNodeNumber() {
return nodeNumber;
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
/**
* Force toggles the nodes ability to forward messages upward for testing purposes, return's the new value.
* @return superSendEnableS
*/
public boolean lockNodeToggle() {
this.superSendEnableS ^= true;
return this.superSendEnableS;
}
}
package FunnelNetSim.Nodes;
import FunnelNetSim.DataPacket;
import FunnelNetSim.FunnelNet;
import FunnelNetSim.SimHost;
public class SlaveNode extends Node {
public SlaveNode(int layerNumber, int nodeNumber) {
super(layerNumber, nodeNumber);
public SlaveNode(int layerNumber, int nodeNumber, FunnelNet parentNet) {
super(layerNumber, nodeNumber, parentNet);
}
@Override
public void updateLines() {
public void preTickUpdateLines() {
updateSuperLine();
}
......@@ -18,7 +19,8 @@ public class SlaveNode extends Node {
public void tick() {
super.tick();
if (superIncoming != null)
System.out.println("Message no. " + superIncoming.getPacketID() + " from " + superIncoming.getOrigin() + " returned to " + getNodeNumber());
System.out.println("Message no. " + superIncoming.getPacketID() + " from " + superIncoming.getOrigin() +
" returned to " + getNodeNumber() + " after " + (parentNet.getCycleCounter()-superIncoming.getTimeStamp()) + " cycles");
}
public void tick(boolean spawnPacket) {
......@@ -29,10 +31,14 @@ public class SlaveNode extends Node {
public boolean createPacket() {
if (superBuffers.isEmpty() && superSendEnableS) {
DataPacket newPacket = new DataPacket(this.getNodeNumber(), DataPacket.messageType.REGULAR);
DataPacket newPacket = new DataPacket(this.getNodeNumber(), parentNet.getCycleCounter(), DataPacket.messageType.REGULAR);
send(newPacket, superNeighbor);
if (SimHost.verbose)
System.out.println("created new Packet");
return true;
}
if (SimHost.verbose)
System.out.println("could not create new Packet!");
return false;
}
......
package FunnelNetSim.Nodes;
import FunnelNetSim.FunnelNet;
import FunnelNetSim.SimHost;
import java.util.LinkedList;
......@@ -16,12 +17,16 @@ public class SlinkyBuffer<T> {
* @param newPkt Packet to be insertet at the start of the buffer. Disregards null;
*/
public void add(T newPkt) {
if (newPkt != null && buffer.size() < FunnelNet.bufferSize)
if (newPkt != null) // && buffer.size() < FunnelNet.bufferSize)
buffer.addFirst(newPkt);
//warning remove me:
if(buffer.size() >= FunnelNet.bufferSize)
System.out.println("This should not be happening, buffer got overfilled by: " + (FunnelNet.bufferSize - buffer.size() + 1));
if (SimHost.verbose) {
if (buffer.size() == FunnelNet.bufferSize)
System.out.println("Warning - buffer full : " + this.toString());
else if (buffer.size() > FunnelNet.bufferSize)
System.out.println("This should not be happening, buffer got overfilled by: " + (buffer.size() - FunnelNet.bufferSize) + " : " + this.toString());
}
}
/**
......@@ -31,6 +36,8 @@ public class SlinkyBuffer<T> {
public T takeFromBuffer() {
if (buffer.size() <= 0)
return null;
if (SimHost.verbose && buffer.size() == FunnelNet.bufferSize)
System.out.println("Buffer free again : " + this.toString());
return buffer.removeLast();
}
......@@ -48,7 +55,11 @@ public class SlinkyBuffer<T> {
* @return true if the slinky buffer system should stop feeding this buffer.
*/
public boolean limitReached() {
return buffer.size() + 2*FunnelNet.packetLatency >= FunnelNet.bufferSize;
//return buffer.size() + 2*FunnelNet.packetLatency -1 >= FunnelNet.bufferSize; //this actually makes it hit the buffer limit, better be careful around that
boolean result = buffer.size() + 2*FunnelNet.packetLatency >= FunnelNet.bufferSize;
if (result && SimHost.verbose)
System.out.println(this.toString() + " reached its limit");
return result;
}
public boolean isEmpty() {
......
......@@ -6,28 +6,35 @@ import FunnelNetSim.Strategies.TestStrategy;
public class SimHost {
public static final boolean verbose = false;//true;
public static void main(String[] args) {
run();
}
private static void run() {
FunnelNet net = new FunnelNet();
FunnelNet net = new FunnelNet(new TestStrategy());
net.master.listTree();
int a = 2;
int b = 5;
int c = 30;
int b = a+30;
int c = b+30;
net.master.getSubNeighbors()[0].lockNodeToggle();
for (int i = 0; i < a; i++) {
System.out.println(net.tickNet());
}
for (int i = a; i < b; i++) {
int cycleNo = net.tickNet();
for (SlaveNode slave : net.slavesNodes) {
slave.createPacket();
}
System.out.println(net.tickNet());
System.out.println(cycleNo);
}
net.master.getSubNeighbors()[0].lockNodeToggle();
for (int i = b; i < c; i++) {
System.out.println(net.tickNet());
}
......
package FunnelNetSim.Strategies;
import FunnelNetSim.DataPacket;
public class GlobalTimeStamp extends Strategy {
@Override
public int selectForwardingSub(DataPacket[] frontRow) {
DataPacket oldest;
int oldestStamp = Integer.MAX_VALUE;
for (int i = 0; i < frontRow.length; i++) {
DataPacket curPacket = frontRow[i];
if (curPacket != null && !shouldReject(curPacket)) {
if (curPacket.getTimeStamp() < oldestStamp) {
oldest = curPacket;
oldestStamp = curPacket.getTimeStamp();
}
}
return i;//packet.setMState(DataPacket.messageState.REJECTED);
//return i;
}
return -1;
}
@Override
protected boolean shouldReject(DataPacket packet) {
//TODO: implement a predictive rejection (reject if it can't make the trip, based on optimal layer latency
if (parentNode.parentNet.getCycleCounter() - packet.getTimeStamp() > parentNode.parentNet.rtcCycles) {
packet.setMState(dropPackets ? DataPacket.messageState.DROP : DataPacket.messageState.REJECTED);
return true;
}
return false;
}
@Override
public Strategy makeNew() {
return new GlobalTimeStamp();
}
}
package FunnelNetSim.Strategies;
import FunnelNetSim.DataPacket;
import FunnelNetSim.Nodes.Node;
public interface Strategy {
public abstract class Strategy {
public int selectForwardingSub(DataPacket[] frontRow);
protected boolean dropPackets = false;
protected Node parentNode = null;
//public boolean shouldReject(DataPacket[] frontRow);
public abstract int selectForwardingSub(DataPacket[] frontRow);
protected abstract boolean shouldReject(DataPacket packet);
public abstract Strategy makeNew();
//TODO: LOOK AT ME! LOOK AT ALL MAH GLORY!
public int testi(DataPacket[] frontRow) {
return selectForwardingSub(frontRow);
}
}
......@@ -2,15 +2,26 @@ package FunnelNetSim.Strategies;
import FunnelNetSim.DataPacket;
public class TestStrategy implements Strategy {
public class TestStrategy extends Strategy {
@Override
public int selectForwardingSub(DataPacket[] frontRow) {
for (int i = 0; i < frontRow.length; i++) {
DataPacket packet = frontRow[i];
if (packet != null)
return i;
return i;//packet.setMState(DataPacket.messageState.REJECTED);
//return i;
}
return -1;
}
@Override
protected boolean shouldReject(DataPacket packet) {
return true;
}
@Override
public Strategy makeNew() {
return new TestStrategy();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment