/** * **************************************************************************** * 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.common.BasicSimulationObject; import archimulator.common.CPUExperiment; import archimulator.common.Simulation; import archimulator.os.Context; import archimulator.os.ContextKilledEvent; import archimulator.os.ContextState; import archimulator.os.Kernel; import archimulator.uncore.MemoryHierarchy; import archimulator.util.event.BlockingEvent; import archimulator.util.event.BlockingEventDispatcher; import archimulator.util.event.CycleAccurateEventQueue; import java.util.*; /** * Basic processor. * * @author Min Cai */ public class BasicProcessor extends BasicSimulationObject<CPUExperiment, Simulation> implements Processor { private List<Core> cores; private Kernel kernel; private MemoryHierarchy memoryHierarchy; private Map<Context, Thread> contextToThreadMappings; /** * Create a basic processor. * * @param experiment the experiment * @param simulation the simulation * @param blockingEventDispatcher the blocking event dispatcher * @param cycleAccurateEventQueue the cycle accurate event queue * @param kernel the kernel * @param memoryHierarchy the memory hierarchy */ public BasicProcessor( CPUExperiment experiment, Simulation simulation, BlockingEventDispatcher<BlockingEvent> blockingEventDispatcher, CycleAccurateEventQueue cycleAccurateEventQueue, Kernel kernel, MemoryHierarchy memoryHierarchy ) { super(experiment, simulation, blockingEventDispatcher, cycleAccurateEventQueue); this.kernel = kernel; this.memoryHierarchy = memoryHierarchy; this.cores = new ArrayList<>(); for (int i = 0; i < getExperiment().getConfig().getNumCores(); i++) { Core core = new BasicCore(this, i); for (int j = 0; j < getExperiment().getConfig().getNumThreadsPerCore(); j++) { BasicThread thread = new BasicThread(core, j); core.getThreads().add(thread); } this.cores.add(core); } this.contextToThreadMappings = new HashMap<>(); this.updateContextToThreadAssignments(); } @Override public void updateContextToThreadAssignments() { for (Iterator<Context> it = this.kernel.getContexts().iterator(); it.hasNext(); ) { Context context = it.next(); if (context.getThreadId() != -1 && this.contextToThreadMappings.get(context) == null) { context.setState(ContextState.RUNNING); int coreNum = context.getThreadId() / getExperiment().getConfig().getNumThreadsPerCore(); int threadNum = context.getThreadId() % getExperiment().getConfig().getNumThreadsPerCore(); Thread candidateThread = this.getCores().get(coreNum).getThreads().get(threadNum); this.contextToThreadMappings.put(context, candidateThread); candidateThread.setContext(context); candidateThread.updateFetchNpcAndNnpcFromRegs(); } else if (context.getState() == ContextState.FINISHED) { Thread thread = this.contextToThreadMappings.get(context); if (thread.isLastDecodedDynamicInstructionCommitted() && thread.getReorderBuffer().isEmpty()) { this.kill(context); it.remove(); } } } } /** * Kill the specified context. * * @param context the context to be killed */ private void kill(Context context) { if (context.getState() != ContextState.FINISHED) { throw new IllegalArgumentException(); } this.kernel.getContexts().stream().filter(childContext -> childContext.getParent() == context).forEach(this::kill); if (context.getParent() == null) { context.getProcess().closeProgram(); } this.contextToThreadMappings.get(context).setContext(null); context.setThreadId(-1); this.getBlockingEventDispatcher().dispatch(new ContextKilledEvent(context)); } @Override public List<Core> getCores() { return cores; } @Override public Kernel getKernel() { return kernel; } @Override public MemoryHierarchy getMemoryHierarchy() { return memoryHierarchy; } @Override public String getName() { return "processor"; } }