/** * **************************************************************************** * 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.mlp; import archimulator.common.Simulation; import archimulator.common.SimulationEvent; import archimulator.common.SimulationType; import archimulator.uncore.dram.BasicMemoryController; import archimulator.uncore.dram.MemoryController; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; /** * DRAM Bank level parallelism (BLP) profiling helper. * * @author Min Cai */ public class BLPProfilingHelper { /** * DRAM Bank access BLP profiled event */ public class BankAccessBLPProfiledEvent extends SimulationEvent { private PendingDramBankAccess pendingDramBankAccess; /** * Create a DRAM bank access BLP profiled event. * * @param pendingDramBankAccess the pending bank access */ public BankAccessBLPProfiledEvent(PendingDramBankAccess pendingDramBankAccess) { super(memoryController); this.pendingDramBankAccess = pendingDramBankAccess; } /** * Get the pending DRAM bank access. * * @return the pending DRAM bank access */ public PendingDramBankAccess getPendingDramBankAccess() { return pendingDramBankAccess; } /** * Get the memory controller. * * @return the memory controller */ public MemoryController getMemoryController() { return memoryController; } } private MemoryController memoryController; private Function<Integer, Integer> blpCostQuantizer; private Map<Integer, PendingDramBankAccess> pendingDRAMBankAccesses; private SummaryStatistics statDramBankAccessNumCycles; private SummaryStatistics statDramBankAccessBlpCosts; /** * Create a BLP profiling helper. * * @param simulation the simulation */ public BLPProfilingHelper(Simulation simulation) { this.memoryController = simulation.getProcessor().getMemoryHierarchy().getMemoryController(); this.blpCostQuantizer = rawValue -> { if (rawValue < 0) { throw new IllegalArgumentException(); } else if (rawValue <= 42) { return 0; } else if (rawValue <= 85) { return 1; } else if (rawValue <= 128) { return 2; } else if (rawValue <= 170) { return 3; } else if (rawValue <= 213) { return 4; } else if (rawValue <= 246) { return 5; } else if (rawValue <= 300) { return 6; } else { return 7; } }; this.pendingDRAMBankAccesses = new LinkedHashMap<>(); this.statDramBankAccessNumCycles = new SummaryStatistics(); this.statDramBankAccessBlpCosts = new SummaryStatistics(); memoryController.getBlockingEventDispatcher().addListener(BasicMemoryController.BeginAccessEvent.class, this::profileBeginServicingL2Miss); memoryController.getBlockingEventDispatcher().addListener(BasicMemoryController.EndAccessEvent.class, this::profileEndServicingL2Miss); memoryController.getCycleAccurateEventQueue().getPerCycleEvents().add(() -> { if (simulation.getType() != SimulationType.FAST_FORWARD) { updateBlpCostsPerCycle(); } }); } /** * To be invoked per cycle for updating BLP-costs for in-flight DRAM bank accesses. */ private void updateBlpCostsPerCycle() { for (PendingDramBankAccess pendingDramBankAccess : this.pendingDRAMBankAccesses.values()) { pendingDramBankAccess.setBlpCost(pendingDramBankAccess.getBlpCost() + (double) 1 / this.pendingDRAMBankAccesses.size()); } } /** * Profile the beginning of servicing a DRAM bank access. * * @param event the begin access event */ private void profileBeginServicingL2Miss(BasicMemoryController.BeginAccessEvent event) { PendingDramBankAccess pendingDramBankAccess = new PendingDramBankAccess(event.getAddress(), event.getBank(), memoryController.getCycleAccurateEventQueue().getCurrentCycle()); if (this.pendingDRAMBankAccesses.containsKey(event.getAddress())) { throw new IllegalArgumentException(event + ""); } this.pendingDRAMBankAccesses.put(event.getAddress(), pendingDramBankAccess); } /** * Profile the end of servicing a DRAM bank access. * * @param event the end access event */ private void profileEndServicingL2Miss(BasicMemoryController.EndAccessEvent event) { PendingDramBankAccess pendingDramBankAccess = this.pendingDRAMBankAccesses.get(event.getAddress()); pendingDramBankAccess.setEndCycle(this.memoryController.getCycleAccurateEventQueue().getCurrentCycle()); this.pendingDRAMBankAccesses.remove(event.getAddress()); this.statDramBankAccessNumCycles.addValue(pendingDramBankAccess.getNumCycles()); this.statDramBankAccessBlpCosts.addValue(pendingDramBankAccess.getBlpCost()); this.memoryController.getBlockingEventDispatcher().dispatch(new BankAccessBLPProfiledEvent(pendingDramBankAccess)); } /** * Get the BLP-cost quantizer. * * @return the BLP-cost quantizer */ public Function<Integer, Integer> getBlpCostQuantizer() { return blpCostQuantizer; } /** * Get the summary statistics of the number of cycles for the DRAM bank accesses. * * @return the summary statistics of the number of cycles for the DRAM bank accesses */ public SummaryStatistics getStatDramBankAccessNumCycles() { return statDramBankAccessNumCycles; } /** * Get the summary statistics of the MLP-costs for the DRAM bank accesses. * * @return the summary statistics of the MLP-costs for the DRAM bank accesses */ public SummaryStatistics getStatDramBankAccessBlpCosts() { return statDramBankAccessBlpCosts; } }