/**
* ****************************************************************************
* 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.cache.setDueling;
import archimulator.uncore.cache.Cache;
import java.util.*;
/**
* Set dueling unit.
*
* @author Min Cai
*/
public abstract class AbstractSetDuelingUnit<SetDuelingMonitorT extends AbstractSetDuelingUnit.SetDuelingMonitor> {
/**
* Set dueling monitor.
*/
public class SetDuelingMonitor {
private int threadId;
private int policyId;
/**
* Create a set dueling monitor.
*
* @param threadId the thread ID
* @param policyId the policy ID
*/
public SetDuelingMonitor(int threadId, int policyId) {
this.threadId = threadId;
this.policyId = policyId;
}
/**
* Get the thread ID.
*
* @return the thread ID
*/
public int getThreadId() {
return threadId;
}
/**
* Get the policy ID.
*
* @return the policy ID
*/
public int getPolicyId() {
return policyId;
}
}
/**
* Binding.
*/
protected class Binding {
private int set;
private int threadId;
private int policyId;
/**
* Create a binding.
*
* @param set the set index
* @param threadId the thread ID
* @param policyId the policy ID
*/
private Binding(int set, int threadId, int policyId) {
this.set = set;
this.threadId = threadId;
this.policyId = policyId;
}
/**
* Get the set index.
*
* @return the set index
*/
public int getSet() {
return set;
}
/**
* Get the thread ID.
*
* @return the thread ID
*/
public int getThreadId() {
return threadId;
}
/**
* Get the policy ID.
*
* @return the policy ID
*/
public int getPolicyId() {
return policyId;
}
}
/**
* Followers.
*/
public static final int FOLLOWERS = -1;
private Cache<?> cache;
private int numThreads;
private int numSetDuelingMonitorsPerThread;
private int numSetsPerSetDuelingMonitor;
private List<Binding> bindings;
private Map<Integer, List<SetDuelingMonitorT>> setDuelingMonitors;
private Random random;
/**
* Create a set dueling unit.
*
* @param cache the parent cache
* @param numThreads the number of threads
* @param numSetDuelingMonitorsPerThread the number of set dueling monitors per thread
* @param numSetsPerSetDuelingMonitor the number of sets per set dueling monitor
*/
public AbstractSetDuelingUnit(final Cache<?> cache, int numThreads, final int numSetDuelingMonitorsPerThread, int numSetsPerSetDuelingMonitor) {
this.cache = cache;
this.numThreads = numThreads;
this.numSetDuelingMonitorsPerThread = numSetDuelingMonitorsPerThread;
this.numSetsPerSetDuelingMonitor = numSetsPerSetDuelingMonitor;
this.random = new Random(13);
this.bindings = new ArrayList<>();
for (int i = 0; i < this.cache.getNumSets(); i++) {
this.bindings.add(new Binding(i, -1, FOLLOWERS));
}
this.setDuelingMonitors = new TreeMap<>();
for (int threadId = 0; threadId < this.numThreads; threadId++) {
this.setDuelingMonitors.put(threadId, new ArrayList<>());
for (int policyId = 0; policyId < this.numSetDuelingMonitorsPerThread; policyId++) {
this.setDuelingMonitors.get(threadId).add(this.createSetDuelingMonitor(threadId, policyId));
}
}
this.initializeSetDuelingMonitorsRandomly();
}
/**
* Randomly assign sets to set dueling monitors.
*/
private void initializeSetDuelingMonitorsRandomly() {
if (this.cache.getNumSets() < this.numSetsPerSetDuelingMonitor * this.numSetDuelingMonitorsPerThread * this.numThreads) {
throw new IllegalArgumentException();
}
for (int threadId = 0; threadId < this.numThreads; threadId++) {
for (int policyId = 0; policyId < this.numSetDuelingMonitorsPerThread; policyId++) {
for (int k = 0; k < this.numSetsPerSetDuelingMonitor; k++) {
int set;
do {
set = this.random.nextInt(this.cache.getNumSets());
}
while (this.bindings.get(set).policyId != FOLLOWERS);
this.bindings.set(set, new Binding(set, threadId, policyId));
}
}
}
}
/**
* Create a set dueling monitor for the specified thread ID and policy ID.
*
* @param threadId the thread ID
* @param policyId the policy ID
* @return a set dueling monitor created for the specified thread ID and policy ID
*/
protected abstract SetDuelingMonitorT createSetDuelingMonitor(int threadId, int policyId);
/**
* Get the policy ID for the specified set.
*
* @param set the set index
* @param threadId the thread ID
* @return the policy ID for the specified set
*/
public int getPolicyId(int set, int threadId) {
Binding binding = this.getBinding(set);
if (binding.threadId == threadId) {
return binding.policyId;
}
return getBestPolicyId(threadId);
}
/**
* Get the list of set dueling monitors for the specified thread ID.
*
* @param threadId the thread ID
* @return the list of set dueling monitors for the specified thread ID
*/
public List<SetDuelingMonitorT> getSetDuelingMonitors(int threadId) {
return this.setDuelingMonitors.get(threadId);
}
/**
* Get the set dueling monitor for the specified thread ID and policy ID.
*
* @param threadId the thread ID
* @param policyId the policy ID
* @return the set dueling monitor for the specified thread ID and policy ID
*/
public SetDuelingMonitorT getSetDuelingMonitor(int threadId, int policyId) {
return this.setDuelingMonitors.get(threadId).get(policyId);
}
/**
* Get the binding for the specified set index.
*
* @param set the set index
* @return the binding for the specified set index
*/
public Binding getBinding(int set) {
return this.bindings.get(set);
}
/**
* Get the best policy ID.
*
* @return the best policy ID
*/
public abstract int getBestPolicyId(int threadId);
/**
* Get the parent cache.
*
* @return the parent cache
*/
public Cache<?> getCache() {
return cache;
}
/**
* Get the number of threads.
*
* @return the number of threads
*/
public int getNumThreads() {
return numThreads;
}
/**
* Get the number of set dueling monitors per thread.
*
* @return the number of set dueling monitors per thread
*/
public int getNumSetDuelingMonitorsPerThread() {
return numSetDuelingMonitorsPerThread;
}
/**
* Get the number of sets per set dueling monitor.
*
* @return the number of sets per set dueling monitor
*/
public int getNumSetsPerSetDuelingMonitor() {
return numSetsPerSetDuelingMonitor;
}
}