/**
* ****************************************************************************
* 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.core;
import archimulator.core.functionalUnit.FunctionalUnitPool;
import archimulator.uncore.MemoryAccessInitiatedEvent;
import archimulator.uncore.MemoryHierarchyAccess;
import archimulator.uncore.MemoryHierarchyAccessType;
import archimulator.util.math.Counter;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract basic core.
*
* @author Min Cai
*/
public abstract class AbstractBasicCore extends AbstractMemoryHierarchyCore implements Core {
/**
* The list of threads.
*/
protected List<Thread> threads;
/**
* The functional unit pool.
*/
protected FunctionalUnitPool functionalUnitPool;
/**
* The waiting instruction queue.
*/
protected List<AbstractReorderBufferEntry> waitingInstructionQueue;
/**
* The ready instruction queue.
*/
protected List<AbstractReorderBufferEntry> readyInstructionQueue;
/**
* The ready load queue.
*/
protected List<AbstractReorderBufferEntry> readyLoadQueue;
/**
* The waiting store queue.
*/
protected List<AbstractReorderBufferEntry> waitingStoreQueue;
/**
* The ready store queue.
*/
protected List<AbstractReorderBufferEntry> readyStoreQueue;
/**
* The out-of-order event queue.
*/
protected List<AbstractReorderBufferEntry> oooEventQueue;
/**
* Create an abstract basic core.
*
* @param processor the parent processor
* @param num the number of the core
*/
public AbstractBasicCore(Processor processor, int num) {
super(processor, num);
this.threads = new ArrayList<>();
this.functionalUnitPool = new FunctionalUnitPool(this);
this.waitingInstructionQueue = new ArrayList<>();
this.readyInstructionQueue = new ArrayList<>();
this.readyLoadQueue = new ArrayList<>();
this.waitingStoreQueue = new ArrayList<>();
this.readyStoreQueue = new ArrayList<>();
this.oooEventQueue = new ArrayList<>();
}
@Override
public void doMeasurementOneCycle() {
this.commit();
this.writeBack();
this.refreshLoadStoreQueue();
this.wakeUp();
this.issue();
this.dispatch();
this.registerRename();
this.fetch();
this.updatePerCycleStats();
}
/**
* Fetch.
*/
protected abstract void fetch();
/**
* Do register renaming.
*/
protected abstract void registerRename(); //TODO: to be merged with dispatch()
/**
* Dispatch.
*/
protected abstract void dispatch();
/**
* Wake up.
*/
protected abstract void wakeUp(); //TODO: to be removed
/**
* Issue.
*/
protected abstract void issue();
/**
* Write back.
*/
protected abstract void writeBack();
/**
* Refresh the load/store queue.
*/
protected abstract void refreshLoadStoreQueue();
/**
* Commit.
*/
protected abstract void commit();
@Override
public void removeFromQueues(AbstractReorderBufferEntry reorderBufferEntry) {
this.oooEventQueue.remove(reorderBufferEntry);
this.readyInstructionQueue.remove(reorderBufferEntry);
this.waitingInstructionQueue.remove(reorderBufferEntry);
this.readyLoadQueue.remove(reorderBufferEntry);
this.readyStoreQueue.remove(reorderBufferEntry);
this.waitingStoreQueue.remove(reorderBufferEntry);
reorderBufferEntry.setSquashed();
}
@Override
public boolean canIfetch(Thread thread, int virtualAddress) {
int physicalTag = this.getL1IController().getCache().getTag(thread.getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress));
return this.getL1IController().canAccess(MemoryHierarchyAccessType.IFETCH, physicalTag);
}
@Override
public boolean canLoad(Thread thread, int virtualAddress) {
int physicalTag = this.getL1DController().getCache().getTag(thread.getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress));
return this.getL1DController().canAccess(MemoryHierarchyAccessType.LOAD, physicalTag);
}
@Override
public boolean canStore(Thread thread, int virtualAddress) {
int physicalTag = this.getL1DController().getCache().getTag(thread.getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress));
return this.getL1DController().canAccess(MemoryHierarchyAccessType.STORE, physicalTag);
}
@Override
public void ifetch(Thread thread, int virtualAddress, int virtualPc, final Runnable onCompletedCallback) {
final int physicalAddress = thread.getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress);
final int physicalTag = this.getL1IController().getCache().getTag(physicalAddress);
final Counter counterPending = new Counter(0);
counterPending.increment();
MemoryHierarchyAccess alias = this.getL1IController().findAccess(physicalTag);
MemoryHierarchyAccess access = this.getL1IController().beginAccess(null, thread, MemoryHierarchyAccessType.IFETCH, virtualPc, physicalAddress, physicalTag, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
if (alias == null) {
counterPending.increment();
thread.getItlb().access(access, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
this.getL1IController().receiveIfetch(access, () -> getL1IController().endAccess(physicalTag));
}
this.getBlockingEventDispatcher().dispatch(new MemoryAccessInitiatedEvent(thread, virtualPc, physicalAddress, physicalTag, MemoryHierarchyAccessType.IFETCH));
}
@Override
public void load(DynamicInstruction dynamicInstruction, int virtualAddress, int virtualPc, final Runnable onCompletedCallback) {
final int physicalAddress = dynamicInstruction.getThread().getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress);
final int physicalTag = this.getL1DController().getCache().getTag(physicalAddress);
final Counter counterPending = new Counter(0);
counterPending.increment();
MemoryHierarchyAccess alias = this.getL1DController().findAccess(physicalTag);
MemoryHierarchyAccess access = this.getL1DController().beginAccess(dynamicInstruction, dynamicInstruction.getThread(), MemoryHierarchyAccessType.LOAD, virtualPc, physicalAddress, physicalTag, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
if (alias == null) {
counterPending.increment();
dynamicInstruction.getThread().getDtlb().access(access, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
this.getL1DController().receiveLoad(access, () -> getL1DController().endAccess(physicalTag));
}
this.getBlockingEventDispatcher().dispatch(new MemoryAccessInitiatedEvent(dynamicInstruction.getThread(), virtualPc, physicalAddress, physicalTag, MemoryHierarchyAccessType.LOAD));
}
@Override
public void store(DynamicInstruction dynamicInstruction, int virtualAddress, int virtualPc, final Runnable onCompletedCallback) {
final int physicalAddress = dynamicInstruction.getThread().getContext().getProcess().getMemory().getPhysicalAddress(virtualAddress);
final int physicalTag = this.getL1DController().getCache().getTag(physicalAddress);
final Counter counterPending = new Counter(0);
counterPending.increment();
MemoryHierarchyAccess alias = this.getL1DController().findAccess(physicalTag);
MemoryHierarchyAccess access = this.getL1DController().beginAccess(dynamicInstruction, dynamicInstruction.getThread(), MemoryHierarchyAccessType.STORE, virtualPc, physicalAddress, physicalTag, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
if (alias == null) {
counterPending.increment();
dynamicInstruction.getThread().getDtlb().access(access, () -> {
counterPending.decrement();
if (counterPending.getValue() == 0) {
onCompletedCallback.run();
}
});
this.getL1DController().receiveStore(access, () -> getL1DController().endAccess(physicalTag));
}
this.getBlockingEventDispatcher().dispatch(new MemoryAccessInitiatedEvent(dynamicInstruction.getThread(), virtualPc, physicalAddress, physicalTag, MemoryHierarchyAccessType.STORE));
}
@Override
public boolean canIfetch(MemoryHierarchyThread thread, int virtualAddress) {
return canIfetch((Thread)thread, virtualAddress);
}
@Override
public boolean canLoad(MemoryHierarchyThread thread, int virtualAddress) {
return canLoad((Thread)thread, virtualAddress);
}
@Override
public boolean canStore(MemoryHierarchyThread thread, int virtualAddress) {
return canStore((Thread)thread, virtualAddress);
}
@Override
public void ifetch(MemoryHierarchyThread thread, int virtualAddress, int virtualPc, Runnable onCompletedCallback) {
ifetch((Thread)thread, virtualAddress, virtualPc, onCompletedCallback);
}
@Override
public void load(MemoryHierarchyDynamicInstruction dynamicInstruction, int virtualAddress, int virtualPc, Runnable onCompletedCallback) {
load((DynamicInstruction)dynamicInstruction, virtualAddress, virtualPc, onCompletedCallback);
}
@Override
public void store(MemoryHierarchyDynamicInstruction dynamicInstruction, int virtualAddress, int virtualPc, Runnable onCompletedCallback) {
store((DynamicInstruction)dynamicInstruction, virtualAddress, virtualPc, onCompletedCallback);
}
@Override
public List<Thread> getThreads() {
return threads;
}
@Override
public FunctionalUnitPool getFunctionalUnitPool() {
return functionalUnitPool;
}
@Override
public List<AbstractReorderBufferEntry> getWaitingInstructionQueue() {
return waitingInstructionQueue;
}
@Override
public List<AbstractReorderBufferEntry> getReadyInstructionQueue() {
return readyInstructionQueue;
}
@Override
public List<AbstractReorderBufferEntry> getReadyLoadQueue() {
return readyLoadQueue;
}
@Override
public List<AbstractReorderBufferEntry> getWaitingStoreQueue() {
return waitingStoreQueue;
}
@Override
public List<AbstractReorderBufferEntry> getReadyStoreQueue() {
return readyStoreQueue;
}
@Override
public List<AbstractReorderBufferEntry> getOooEventQueue() {
return oooEventQueue;
}
}