/** * **************************************************************************** * Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com). * <p> * This file is part of the Archimulator multicore architectural simulator. * <p> * Archimulator is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p> * Archimulator is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <p> * You should have received a copy of the GNU General Public License * along with Archimulator. If not, see <http://www.gnu.org/licenses/>. * **************************************************************************** */ package archimulator.uncore.noc; import archimulator.common.NoCEnvironment; import archimulator.uncore.noc.routers.FlitState; import archimulator.uncore.noc.routing.RoutingAlgorithmFactory; import archimulator.uncore.noc.selection.SelectionAlgorithmFactory; import archimulator.util.event.CycleAccurateEventQueue; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Network. * * @author Min Cai */ public class Network { long currentPacketId; private NoCEnvironment environment; private CycleAccurateEventQueue cycleAccurateEventQueue; private int numNodes; private List<Node> nodes; private RoutingAlgorithmFactory routingAlgorithmFactory; private SelectionAlgorithmFactory selectionAlgorithmFactory; private int width; private List<Packet> inflightPackets; private boolean acceptPacket; private long numPacketsReceived; private long numPacketsTransmitted; private long totalPacketDelays; private long maxPacketDelay; private long totalPacketHops; private long maxPacketHops; private long numPayloadPacketsReceived; private long numPayloadPacketsTransmitted; private long totalPayloadPacketDelays; private long maxPayloadPacketDelay; private long totalPayloadPacketHops; private long maxPayloadPacketHops; private Map<Class<? extends Packet>, Long> numPacketsReceivedPerType; private Map<Class<? extends Packet>, Long> numPacketsTransmittedPerType; private Map<Class<? extends Packet>, Long> totalPacketDelaysPerType; private Map<Class<? extends Packet>, Long> maxPacketDelayPerType; private Map<Class<? extends Packet>, Long> totalPacketHopsPerType; private Map<Class<? extends Packet>, Long> maxPacketHopsPerType; private Map<FlitState, Long> numFlitPerStateDelaySamples; private Map<FlitState, Long> totalFlitPerStateDelays; private Map<FlitState, Long> maxFlitPerStateDelay; /** * Create a network. * * @param environment the environment * @param cycleAccurateEventQueue the cycle accurate event queue * @param numNodes the number of nodes * @param selectionAlgorithmFactory the node factory * @param routingAlgorithmFactory the routing algorithm factory */ public Network( NoCEnvironment environment, CycleAccurateEventQueue cycleAccurateEventQueue, int numNodes, SelectionAlgorithmFactory selectionAlgorithmFactory, RoutingAlgorithmFactory routingAlgorithmFactory ) { this.environment = environment; this.currentPacketId = 0; this.cycleAccurateEventQueue = cycleAccurateEventQueue; this.numNodes = numNodes; this.width = (int) Math.sqrt(this.numNodes); if(this.width * this.width != this.numNodes) { throw new RuntimeException("Only 2D meshes are supported"); } this.selectionAlgorithmFactory = selectionAlgorithmFactory; this.routingAlgorithmFactory = routingAlgorithmFactory; this.nodes = new ArrayList<>(); for(int i = 0; i < this.numNodes; i++) { Node node = new Node(this, i); node.setSelectionAlgorithm(this.selectionAlgorithmFactory.create(node)); node.setRoutingAlgorithm(this.routingAlgorithmFactory.create(node)); this.nodes.add(node); } this.inflightPackets = new ArrayList<>(); this.acceptPacket = true; this.numPacketsReceived = 0; this.numPacketsTransmitted = 0; this.totalPacketDelays = 0; this.maxPacketDelay = 0; this.totalPacketHops = 0; this.maxPacketHops = 0; this.numPayloadPacketsReceived = 0; this.numPayloadPacketsTransmitted = 0; this.totalPayloadPacketDelays = 0; this.maxPayloadPacketDelay = 0; this.totalPayloadPacketHops = 0; this.maxPayloadPacketHops = 0; this.numPacketsReceivedPerType = new HashMap<>(); this.numPacketsTransmittedPerType = new HashMap<>(); this.totalPacketDelaysPerType = new HashMap<>(); this.maxPacketDelayPerType = new HashMap<>(); this.totalPacketHopsPerType = new HashMap<>(); this.maxPacketHopsPerType = new HashMap<>(); this.numFlitPerStateDelaySamples = new HashMap<>(); this.totalFlitPerStateDelays = new HashMap<>(); this.maxFlitPerStateDelay = new HashMap<>(); } /** * Log the event when a packet is received. * * @param packet the packet that is received */ public void logPacketReceived(Packet packet) { this.numPacketsReceived++; if(packet.hasPayload()) { this.numPayloadPacketsReceived++; } Class<? extends Packet> packetCls = packet.getClass(); if(!this.numPacketsReceivedPerType.containsKey(packetCls)) { this.numPacketsReceivedPerType.put(packetCls, 0L); } this.numPacketsReceivedPerType.put(packetCls, this.numPacketsReceivedPerType.get(packetCls) + 1); } /** * Log the event when a packet is transmitted. * * @param packet the packet that is transmitted */ public void logPacketTransmitted(Packet packet) { this.numPacketsTransmitted++; if(packet.hasPayload()) { this.numPayloadPacketsTransmitted++; } Class<? extends Packet> packetCls = packet.getClass(); if(!this.numPacketsTransmittedPerType.containsKey(packetCls)) { this.numPacketsTransmittedPerType.put(packetCls, 0L); } this.numPacketsTransmittedPerType.put(packetCls, this.numPacketsTransmittedPerType.get(packetCls) + 1); this.totalPacketDelays += packet.delay(); this.totalPacketHops += packet.hops(); if(packet.hasPayload()) { this.totalPayloadPacketDelays += packet.delay(); this.totalPayloadPacketHops += packet.hops(); } if(!this.totalPacketDelaysPerType.containsKey(packetCls)) { this.totalPacketDelaysPerType.put(packetCls, 0L); } if(!this.totalPacketHopsPerType.containsKey(packetCls)) { this.totalPacketHopsPerType.put(packetCls, 0L); } this.totalPacketDelaysPerType.put(packetCls, this.totalPacketDelaysPerType.get(packetCls) + packet.delay()); this.totalPacketHopsPerType.put(packetCls, this.totalPacketHopsPerType.get(packetCls) + packet.hops()); this.maxPacketDelay = Math.max(this.maxPacketDelay, packet.delay()); this.maxPacketHops = Math.max(this.maxPacketHops, packet.hops()); if(packet.hasPayload()) { this.maxPayloadPacketDelay = Math.max(this.maxPayloadPacketDelay, packet.delay()); this.maxPayloadPacketHops = Math.max(this.maxPayloadPacketHops, packet.hops()); } if(!this.maxPacketDelayPerType.containsKey(packetCls)) { this.maxPacketDelayPerType.put(packetCls, 0L); } if(!this.maxPacketHopsPerType.containsKey(packetCls)) { this.maxPacketHopsPerType.put(packetCls, 0L); } this.maxPacketDelayPerType.put(packetCls, Math.max(this.maxPacketDelayPerType.get(packetCls), packet.delay())); this.maxPacketHopsPerType.put(packetCls, Math.max(this.maxPacketHopsPerType.get(packetCls), packet.hops())); } /** * Log the flit per-state delay. * * @param state the flit state * @param delay the delay that the flit is spent in the state */ public void logFlitPerStateDelay(FlitState state, int delay) { if(!this.numFlitPerStateDelaySamples.containsKey(state)) { this.numFlitPerStateDelaySamples.put(state, 0L); } this.numFlitPerStateDelaySamples.put(state, this.numFlitPerStateDelaySamples.get(state) + 1); if(!this.totalFlitPerStateDelays.containsKey(state)) { this.totalFlitPerStateDelays.put(state, 0L); } this.totalFlitPerStateDelays.put(state, this.totalFlitPerStateDelays.get(state) + delay); if(!this.maxFlitPerStateDelay.containsKey(state)) { this.maxFlitPerStateDelay.put(state, 0L); } this.maxFlitPerStateDelay.put(state, Math.max(this.maxFlitPerStateDelay.get(state), delay)); } /** * Receives a packet. * * @param packet the packet that is received * @return a boolean value indicating whether the packet is received or not */ public boolean receive(Packet packet) { if(!this.nodes.get(packet.getSrc()).getRouter().injectPacket(packet)) { this.cycleAccurateEventQueue.schedule(this, () -> receive(packet), 1); return false; } this.inflightPackets.add(packet); this.logPacketReceived(packet); return true; } /** * Calculate a random destination node ID for the specified source node ID. * * @param src the source node ID * @return a newly calculated random destination node ID for the specified source node ID */ public int randDest(int src) { while (true) { int i = this.environment.getRandom().nextInt(this.numNodes); if(i != src) { return i; } } } /** * Get the throughput. * * @return the throughput */ public double throughput() { return (double) this.numPacketsTransmitted / this.cycleAccurateEventQueue.getCurrentCycle() / this.numNodes; } /** * Get the average packet delay. * * @return the average packet delay */ public double averagePacketDelay() { if(this.numPacketsTransmitted > 0) { return (double) this.totalPacketDelays / this.numPacketsTransmitted; } return 0.0; } /** * Get the average number of hops that a packet traverses. * * @return the average number of hops that a packet traverses */ public double averagePacketHops() { if(this.numPacketsTransmitted > 0) { return (double) this.totalPacketHops / this.numPacketsTransmitted; } return 0.0; } /** * Get the payload throughput. * * @return the payload throughput */ public double payloadThroughput() { return (double) this.numPayloadPacketsTransmitted / this.cycleAccurateEventQueue.getCurrentCycle() / this.numNodes; } /** * Get the average payload packet delay. * * @return the average payload packet delay */ public double averagePayloadPacketDelay() { if(this.numPayloadPacketsTransmitted > 0) { return (double) this.totalPayloadPacketDelays / this.numPayloadPacketsTransmitted; } return 0.0; } /** * Get the average number of hops that a payload packet traverses. * * @return the average number of hops that a payload packet traverses */ public double averagePayloadPacketHops() { if(this.numPayloadPacketsTransmitted > 0) { return (double) this.totalPayloadPacketHops / this.numPayloadPacketsTransmitted; } return 0.0; } /** * Get the throughput for the specified packet type. * * @param packetCls the packet type * @return the throughput for the specified packet type */ public double throughputPerType(Class<? extends Packet> packetCls) { return (double) this.numPacketsTransmittedPerType.get(packetCls) / this.cycleAccurateEventQueue.getCurrentCycle() / this.numNodes; } /** * Get the average delay for the specified packet type. * * @param packetCls the packet type * @return the average delay for the specified packet type */ public double averagePacketDelayPerType(Class<? extends Packet> packetCls) { if(this.numPacketsTransmittedPerType.get(packetCls) > 0) { return (double) this.totalPacketDelaysPerType.get(packetCls) / this.numPacketsTransmittedPerType.get(packetCls); } return 0.0; } /** * Get the average number of hops that a packet of the specified type traverses. * * @param packetCls the packet type * @return the average number of hops that a packet of the specified type traverses */ public double averagePacketHopsPerType(Class<? extends Packet> packetCls) { if(this.numPacketsTransmittedPerType.get(packetCls) > 0) { return (double) this.totalPacketHopsPerType.get(packetCls) / this.numPacketsTransmittedPerType.get(packetCls); } return 0.0; } /** * Get the average delay that a flit spends in the specified state. * * @param state the flit state * @return the average delay that a flit spends in the specified state */ public double averageFlitPerStateDelay(FlitState state) { if(this.numFlitPerStateDelaySamples.containsKey(state) && this.numFlitPerStateDelaySamples.get(state) > 0) { return (double) this.totalFlitPerStateDelays.get(state) / this.numFlitPerStateDelaySamples.get(state); } return 0.0; } /** * Get the cycle accurate event queue. * * @return the cycle accurate event queue */ public CycleAccurateEventQueue getCycleAccurateEventQueue() { return cycleAccurateEventQueue; } /** * Get the number of nodes. * * @return the number of nodes */ public int getNumNodes() { return numNodes; } /** * Get the list of nodes. * * @return the list of nodes */ public List<Node> getNodes() { return nodes; } /** * Get the routing algorithm factory. * * @return the routing algorithm factory */ public RoutingAlgorithmFactory getRoutingAlgorithmFactory() { return routingAlgorithmFactory; } /** * Get the selection algorithm factory. * * @return the selection algorithm factory */ public SelectionAlgorithmFactory getSelectionAlgorithmFactory() { return selectionAlgorithmFactory; } /** * Get the width. * * @return the width */ public int getWidth() { return width; } /** * Get the list of inflight packets. * * @return the list of inflight packets */ public List<Packet> getInflightPackets() { return inflightPackets; } /** * Get a boolean value indicating whether the network can accept new packets or not. * * @return a boolean value indicating whether the network can accept new packets or not */ public boolean isAcceptPacket() { return acceptPacket; } /** * Set a boolean value indicating whether the network can accept new packets or not. * * @param acceptPacket a boolean value indicating whether the network can accept new packets or not */ public void setAcceptPacket(boolean acceptPacket) { this.acceptPacket = acceptPacket; } /** * Get the number of packets that the network has received. * * @return the number of packets that the network has received */ public long getNumPacketsReceived() { return numPacketsReceived; } /** * Get the number of packets that the network has transmitted. * * @return the number of packets that the network has transmitted */ public long getNumPacketsTransmitted() { return numPacketsTransmitted; } /** * Get the maximum delay that a packet experiences. * * @return the maximum delay that a packet experiences */ public long getMaxPacketDelay() { return maxPacketDelay; } /** * Get the maximum number of hops that a packet traverses. * * @return the maximum number of hops that a packet traverses */ public long getMaxPacketHops() { return maxPacketHops; } /** * Get the number of payload packets that the network has received. * * @return the number of payload packets that the network has received */ public long getNumPayloadPacketsReceived() { return numPayloadPacketsReceived; } /** * Get the number of payload packets that the network has transmitted. * * @return the number of payload packets that the network has transmitted */ public long getNumPayloadPacketsTransmitted() { return numPayloadPacketsTransmitted; } /** * Get the maximum delay that a payload packet experiences. * * @return the maximum delay that a payload packet experiences */ public long getMaxPayloadPacketDelay() { return maxPayloadPacketDelay; } /** * Get the maximum number of hops that a payload packet traverses. * * @return the maximum number of hops that a payload packet traverses */ public long getMaxPayloadPacketHops() { return maxPayloadPacketHops; } /** * Get the map of the number of packets that the network has received. * * @return the map of the number of packets that the network has received */ public Map<Class<? extends Packet>, Long> getNumPacketsReceivedPerType() { return numPacketsReceivedPerType; } /** * Get the map of the number of packets that the network has transmitted. * * @return the map of the number of packets that the network has transmitted */ public Map<Class<? extends Packet>, Long> getNumPacketsTransmittedPerType() { return numPacketsTransmittedPerType; } /** * Get the map of the maximum delay that a packet experiences. * * @return the map of the maximum delay that a packet experiences */ public Map<Class<? extends Packet>, Long> getMaxPacketDelayPerType() { return maxPacketDelayPerType; } /** * Get the map of the maximum number of hops that a packet traverses. * * @return the map of the maximum number of hops that a packet traverses */ public Map<Class<? extends Packet>, Long> getMaxPacketHopsPerType() { return maxPacketHopsPerType; } /** * Get the map of the maximum per-state delay that a flit spends. * * @return the map of the maximum per-state delay that a flit spends */ public Map<FlitState, Long> getMaxFlitPerStateDelay() { return maxFlitPerStateDelay; } /** * Get the environment. * * @return the environment */ public NoCEnvironment getEnvironment() { return environment; } }