/** * **************************************************************************** * 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.*; import archimulator.common.report.ReportNode; import archimulator.common.report.Reportable; import archimulator.uncore.noc.prediction.RouterCongestionStatusPredictionHelper; import archimulator.uncore.noc.routers.FlitState; import archimulator.uncore.noc.selection.aco.ACOSelectionAlgorithm; import archimulator.uncore.noc.selection.aco.Pheromone; import archimulator.uncore.noc.traffics.HotspotTrafficGenerator; import archimulator.uncore.noc.traffics.TransposeTrafficGenerator; import archimulator.uncore.noc.traffics.UniformTrafficGenerator; import archimulator.util.dateTime.DateHelper; import archimulator.util.event.BlockingEvent; import archimulator.util.event.BlockingEventDispatcher; import archimulator.util.event.CycleAccurateEventQueue; import org.apache.commons.lang.time.DurationFormatUtils; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; /** * NoC experiment. * * @author Min Cai */ public class NoCExperiment extends Experiment<NoCExperimentConfig> implements NoCEnvironment, Reportable { /** * NoC experiment started event. */ public class NoCExperimentStartedEvent implements BlockingEvent { } /** * NoC experiment advance one cycle event. */ public class NoCExperimentAdvanceOneCycleEvent implements BlockingEvent { } /** * NoC experiment ended event. */ public class NoCExperimentEndedEvent implements BlockingEvent { } private String outputDirectory; private Random random; private int numNodes; private int maxCycles; private int maxPackets; private boolean noDrain; private long beginTime; private long endTime; private CycleAccurateEventQueue cycleAccurateEventQueue; private BlockingEventDispatcher<BlockingEvent> blockingEventDispatcher; private Network network; private RouterCongestionStatusPredictionHelper routerCongestionStatusPredictionHelper; /** * Create a NoC experiment. */ public NoCExperiment(String outputDirectory, int numNodes, int maxCycles, int maxPackets, boolean noDrain) { super(new NoCExperimentConfig()); this.outputDirectory = outputDirectory; this.numNodes = numNodes; this.maxCycles = maxCycles; this.maxPackets = maxPackets; this.noDrain = noDrain; this.random = this.getConfig().getRandSeed() != -1 ? new Random(this.getConfig().getRandSeed()) : new Random(); this.cycleAccurateEventQueue = new CycleAccurateEventQueue(); this.blockingEventDispatcher = new BlockingEventDispatcher<>(); } /** * Simulate. */ @Override protected void simulate() { Logger.info(Logger.SIMULATOR, "", this.cycleAccurateEventQueue.getCurrentCycle()); this.network = NetworkFactory.create(this, this.cycleAccurateEventQueue, this.numNodes); switch (this.getConfig().getDataPacketTraffic()) { case "uniform": new UniformTrafficGenerator( network, this.getConfig().getDataPacketInjectionRate(), (src, dest, size) -> new DataPacket(network, src, dest, size, () -> {}), this.getConfig().getDataPacketSize(), maxPackets ); break; case "transpose": new TransposeTrafficGenerator( network, this.getConfig().getDataPacketInjectionRate(), (src, dest, size) -> new DataPacket(network, src, dest, size, () -> {}), this.getConfig().getDataPacketSize(), maxPackets ); break; case "hotspot": new HotspotTrafficGenerator( network, this.getConfig().getDataPacketInjectionRate(), (src, dest, size) -> new DataPacket(network, src, dest, size, () -> {}), this.getConfig().getDataPacketSize(), maxPackets ); break; } this.routerCongestionStatusPredictionHelper = new RouterCongestionStatusPredictionHelper(this.network); this.blockingEventDispatcher.dispatch(new NoCExperimentStartedEvent()); this.beginTime = DateHelper.toTick(new Date()); while ((this.getMaxCycles() == -1 || cycleAccurateEventQueue.getCurrentCycle() < this.getMaxCycles()) && (this.getMaxPackets() == -1 || network.getNumPacketsReceived() < this.getMaxPackets())) { cycleAccurateEventQueue.advanceOneCycle(); this.blockingEventDispatcher.dispatch(new NoCExperimentAdvanceOneCycleEvent()); } if (!this.isNoDrain()) { network.setAcceptPacket(false); while (network.getNumPacketsReceived() != network.getNumPacketsTransmitted()) { cycleAccurateEventQueue.advanceOneCycle(); this.blockingEventDispatcher.dispatch(new NoCExperimentAdvanceOneCycleEvent()); } } this.endTime = DateHelper.toTick(new Date()); this.collectStats(); Logger.info(Logger.SIMULATION, "Simulation completed successfully.", this.getCycleAccurateEventQueue().getCurrentCycle()); this.blockingEventDispatcher.dispatch(new NoCExperimentEndedEvent()); } /** * Collect the statistics. */ private void collectStats() { final List<ExperimentStat> stats = new ArrayList<>(); ReportNode rootReportNode = new ReportNode(null, ""); this.dumpStats(rootReportNode); rootReportNode.traverse(node -> stats.add(new ExperimentStat("", node.getPath(), node.getValue()))); this.getStats().addAll(stats); } /** * Dump the statistics into the specified report node. * * @param reportNode the report node */ @Override public void dumpStats(ReportNode reportNode) { reportNode.getChildren().add(new ReportNode(reportNode, "simulation") {{ getChildren().add(new ReportNode(this, "beginTimeAsString", getBeginTimeAsString())); getChildren().add(new ReportNode(this, "endTimeAsString", getEndTimeAsString())); getChildren().add(new ReportNode(this, "duration", getDuration())); getChildren().add(new ReportNode(this, "durationInSeconds", getDurationInSeconds() + "")); getChildren().add(new ReportNode(this, "cycleAccurateEventQueue/currentCycle", getCycleAccurateEventQueue().getCurrentCycle() + "")); }}); reportNode.getChildren().add(new ReportNode(reportNode, "noc") {{ routerCongestionStatusPredictionHelper.dumpStats(this); getChildren().add( new ReportNode( this, "numPacketsReceived", String.format("%d", network.getNumPacketsReceived()) ) ); getChildren().add( new ReportNode( this, "numPacketsTransmitted", String.format("%d", network.getNumPacketsTransmitted()) ) ); getChildren().add( new ReportNode( this, "throughput", String.format("%s", network.throughput()) ) ); getChildren().add( new ReportNode( this, "averagePacketDelay", String.format("%s", network.averagePacketDelay()) ) ); getChildren().add( new ReportNode( this, "averagePacketHops", String.format("%s", network.averagePacketHops()) ) ); getChildren().add( new ReportNode( this, "maxPacketDelay", String.format("%d", network.getMaxPacketDelay()) ) ); getChildren().add( new ReportNode( this, "maxPacketHops", String.format("%d", network.getMaxPacketHops()) ) ); getChildren().add( new ReportNode( this, "numPayloadPacketsReceived", String.format("%d", network.getNumPayloadPacketsReceived()) ) ); getChildren().add( new ReportNode( this, "numPayloadPacketsTransmitted", String.format("%d", network.getNumPayloadPacketsTransmitted()) ) ); getChildren().add( new ReportNode( this, "payloadThroughput", String.format("%s", network.payloadThroughput()) ) ); getChildren().add( new ReportNode( this, "averagePayloadPacketDelay", String.format("%s", network.averagePayloadPacketDelay()) ) ); getChildren().add( new ReportNode( this, "averagePayloadPacketHops", String.format("%s", network.averagePayloadPacketHops()) ) ); getChildren().add( new ReportNode( this, "maxPayloadPacketDelay", String.format("%d", network.getMaxPayloadPacketDelay()) ) ); getChildren().add( new ReportNode( this, "maxPayloadPacketHops", String.format("%d", network.getMaxPayloadPacketHops()) ) ); for (FlitState state : FlitState.values()) { getChildren().add( new ReportNode( this, String.format("averageFlitPerStateDelay::%s", state), String.format("%s", network.averageFlitPerStateDelay(state)) ) ); } for (FlitState state : FlitState.values()) { getChildren().add( new ReportNode( this, String.format("maxFlitPerStateDelay::%s", state), network.getMaxFlitPerStateDelay().containsKey(state) ? String.format("%d", network.getMaxFlitPerStateDelay().get(state)) : String.format("%s", 0.0) ) ); } if (getConfig().getSelection().equals("aco")) { for (Node srcNode : getNetwork().getNodes()) { for (Node destNode : getNetwork().getNodes()) { if (srcNode != destNode) { ACOSelectionAlgorithm selectionAlgorithm = (ACOSelectionAlgorithm) srcNode.getSelectionAlgorithm(); for (Pheromone pheromone : selectionAlgorithm.getPheromoneTable().getPheromones().get(destNode.getId()).values()) { getChildren().add( new ReportNode( this, String.format("node_%d.pheromones[node_%d][%s]", srcNode.getId(), destNode.getId(), pheromone.getDirection()), String.format("%s", pheromone.getValue()) ) ); } } } } } }}); } /** * Get the network. * * @return the network */ public Network getNetwork() { return network; } /** * Get the router congestion status prediction helper. * * @return the router congestion status prediction helper */ public RouterCongestionStatusPredictionHelper getRouterCongestionStatusPredictionHelper() { return routerCongestionStatusPredictionHelper; } /** * Get the output directory. * * @return the output directory */ @Override protected String getOutputDirectory() { return outputDirectory; } /** * Get the random object. * * @return the random object */ @Override public Random getRandom() { return random; } /** * Get a boolean value indicating whether it is currently in the detailed simulation mode or not. * * @return a boolean value indicating whether it is currently in the detailed simulation mode or not */ @Override public boolean isInDetailedSimulationMode() { return true; } /** * Get the number of nodes. * * @return the number of nodes */ public int getNumNodes() { return numNodes; } /** * Get the time in ticks when the simulation begins. * * @return the time in ticks when the simulation begins */ public long getBeginTime() { return beginTime; } /** * Get the time in ticks when the simulation ends. * * @return the time in ticks when the simulation ends */ public long getEndTime() { return endTime; } /** * Get the string representation of the time when the simulation begins. * * @return the string representation of the time when the simulation begins */ public String getBeginTimeAsString() { return DateHelper.toString(beginTime); } /** * Get the string representation of the time when the simulation ends. * * @return the string representation of the time when the simulation ends */ public String getEndTimeAsString() { return DateHelper.toString(endTime); } /** * Get the duration in seconds that the simulation lasts. * * @return the duration in seconds that the simulation lasts */ public long getDurationInSeconds() { return (this.getEndTime() - this.getBeginTime()) / 1000; } /** * Get the string representation of the duration that the simulation lasts. * * @return the string representation of the duration that the simulation lasts */ public String getDuration() { return DurationFormatUtils.formatDurationHMS(this.getEndTime() - this.getBeginTime()); } /** * Get the cycle accurate event queue. * * @return the cycle accurate event queue */ public CycleAccurateEventQueue getCycleAccurateEventQueue() { return cycleAccurateEventQueue; } /** * Get the blocking event dispatcher. * * @return the blocking event dispatcher */ public BlockingEventDispatcher<BlockingEvent> getBlockingEventDispatcher() { return blockingEventDispatcher; } /** * Get the maximum number of cycles to be simulated. * * @return the maximum number of cycles to be simulated */ public int getMaxCycles() { return maxCycles; } /** * Get the maximum number of packets to be simulated. * * @return the maximum number of packets to be simulated */ public int getMaxPackets() { return maxPackets; } /** * Get a boolean value indicating whether draining packets is disabled or not. * * @return a boolean value indicating whether draining packets is disabled or not */ public boolean isNoDrain() { return noDrain; } }