/* * This represents a reader thread in the simulator which keeps on reading from EMUTHREADS. */ package emulatorinterface; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; import java.util.TreeMap; import java.util.Vector; import java.util.zip.GZIPInputStream; import main.ArchitecturalComponent; import main.CustomObjectPool; import main.Main; import memorysystem.Cache; import memorysystem.MemorySystem; import pipeline.PipelineInterface; import pipeline.outoforder.OutOrderExecutionEngine; import config.CommunicationType; import config.EmulatorConfig; import config.EmulatorType; import config.MainMemoryConfig; import config.SimulationConfig; import config.SystemConfig; import emulatorinterface.ThreadBlockState.blockState; import emulatorinterface.communication.Encoding; import emulatorinterface.communication.IpcBase; import emulatorinterface.communication.Packet; import emulatorinterface.communication.filePacket.FileWrite; import emulatorinterface.communication.shm.SharedMem; import emulatorinterface.translator.InvalidInstructionException; import emulatorinterface.translator.x86.objparser.ObjParser; import generic.BarrierTable; import generic.CircularPacketQueue; import generic.Core; import generic.CustomInstructionPool; import generic.GenericCircularQueue; import generic.GlobalClock; import generic.Instruction; import generic.Operand; import generic.OperandType; import generic.OperationType; import generic.Statistics; /* MaxNumThreads threads are created from this class. Each thread * continuously keeps reading from the shared memory segment according * to its index(taken care in the jni C file). */ public class RunnableThread implements Encoding, Runnable { public static final int INSTRUCTION_THRESHOLD = 2000; boolean oNotProcess = false; int javaTid; long sum = 0; // checksum int EMUTHREADS; int currentEMUTHREADS = 0; //total number of livethreads int maxCoreAssign = 0; //the maximum core id assigned static EmulatorThreadState[] emulatorThreadState;// = new EmulatorThreadState[EMUTHREADS]; static ThreadBlockState[] threadBlockState;//=new ThreadBlockState[EMUTHREADS]; GenericCircularQueue[] inputToPipeline; //FileWrite obj=new FileWrite(1,EmulatorConfig.basenameForTraceFiles); // static long ignoredInstructions = 0; // QQQ re-arrange packets for use by translate instruction. // DynamicInstructionBuffer[] dynamicInstructionBuffer; static long[] noOfMicroOps; //long[] numInstructions; //FIXME PipelineInterface should be in IpcBase and not here as pipelines from other RunnableThreads // will need to interact. PipelineInterface[] pipelineInterfaces; long prevTotalInstructions, currentTotalInstructions; long[] prevCycles; public IpcBase ipcBase; private static int liveJavaThreads; static boolean printIPTrace = false; static long numShmWrites[]; //aded by harveenk kushagra //to synch RAM and core clock long counter1=0; long counter2=0; //changed by kush, only declare here, initialize later long RAMclock; long CoreClock; BufferedReader[] traceReaders; boolean[] tracesDoneReading; /* * This keeps on reading from the appropriate index in the shared memory * till it gets a -1 after which it stops. NOTE this depends on each thread * calling threadFini() which might not be the case. This function will * break if the threads which started do not call threadfini in the PIN (in * case of unclean termination). Although the problem is easily fixable. */ Operand retOp(String str1, String str2){ //System.out.println(str1.substring(1, str1.length()-1)+" "+str2); Operand op= new Operand(OperandType.valueOf(str1.substring(1, str1.length()-1)),Long.parseLong(str2)); return op; } public void run() { if (EmulatorConfig.emulatorType == EmulatorType.none && EmulatorConfig.communicationType == CommunicationType.file) { //trace-file based simulation for(int core = 0; core < maxCoreAssign; core++) { ArchitecturalComponent.getCore(core).getExecEngine().setExecutionBegun(true); } long microOpsReadFromFile = 0; long microOpsSentToPipelines = 0; while(true) { for(int core = 0; core < maxCoreAssign; core++) { if(tracesDoneReading[core] == false) { for(int insCount = 0; insCount < 1000; insCount++) { if(inputToPipeline[core].spaceLeft()==0) break; Instruction iNew = null; String line = null; try { line = traceReaders[core].readLine(); } catch (Exception e) { e.printStackTrace(); misc.Error.showErrorAndExit(e.getMessage()); } if(line==null) iNew =Instruction.getInvalidInstruction(); else { microOpsReadFromFile++; if(microOpsReadFromFile < SimulationConfig.NumInsToIgnore) { continue; } if(SimulationConfig.subsetSimulation == true && microOpsReadFromFile > (SimulationConfig.NumInsToIgnore + SimulationConfig.subsetSimSize)) { iNew =Instruction.getInvalidInstruction(); line = null; } else { String[] splited = line.split(" "); iNew = CustomObjectPool.getInstructionPool().borrowObject(); iNew.setCISCProgramCounter(Long.parseLong(splited[0])); iNew.setOperationType(OperationType.valueOf(splited[1])); Operand ops[] = new Operand[9]; int i=2; for(int k=0; k<9;k++){ if(!splited[i].equals("null")){ ops[k] = retOp(splited[i], splited[i+1]); if(k!=8) i+=2; } else{ ops[k]=null; if(k!=8) i+=1; } } i+=1; if(ops[0]!=null){ ops[0].setMemoryLocationFirstOperand(ops[1]); ops[0].setMemoryLocationSecondOperand(ops[2]); } if(ops[3]!=null){ ops[3].setMemoryLocationFirstOperand(ops[4]); ops[3].setMemoryLocationSecondOperand(ops[5]); } if(ops[6]!=null){ ops[6].setMemoryLocationFirstOperand(ops[7]); ops[6].setMemoryLocationSecondOperand(ops[8]); } iNew.setSourceOperand1(ops[0]); iNew.setSourceOperand2(ops[3]); iNew.setDestinationOperand(ops[6]); iNew.setSourceOperand1MemValue(Long.parseLong(splited[i])); iNew.setSourceOperand2MemValue(Long.parseLong(splited[i+1])); iNew.setDestinationOperandMemValue(Long.parseLong(splited[i+2])); iNew.setBranchTargetAddress(Long.parseLong(splited[i+3])); iNew.setBranchTaken(Boolean.parseBoolean(splited[i+4])); //iNew.setSerialNo(Long.parseLong(splited[i+6])); } } inputToPipeline[core].enqueue(iNew); microOpsSentToPipelines++; if(line==null) { tracesDoneReading[core] = true; try { traceReaders[core].close(); } catch(Exception e) { e.printStackTrace(); misc.Error.showErrorAndExit(e.getMessage()); } break; } } } } runPipelines(); boolean allTracesDoneReading = true; for(int core = 0; core < maxCoreAssign; core++) { if(tracesDoneReading[core] == false) { allTracesDoneReading = false; break; } } if(allTracesDoneReading == true) { finishAllPipelines(); break; } } } else { //PIN-based simulation // create pool for emulator packets ArrayList fromEmulatorAll = new ArrayList(EMUTHREADS); for(int i=0; i1) {//System.out.println("live threads :"+liveJavaThreads); if(inputToPipeline[tidEmulator].size()<=0 || liveJavaThreads>1 && statusOfOtherThreads()) { //System.out.println("******************************continued2*******************"); continue; } } } runPipelines(); // System.out.println("after execution n= "+n+" Thread finished ? "+threadParams[1].finished); // this runnable thread can be stopped in two ways. Either the // emulator threads from which it was supposed to read never // started(none of them) so it has to be signalled by the main // thread. When this happens 'all over' becomes 'true' and it // breaks out from the loop. The second situation is that all the // emulator threads which started have now finished, so probably // this thread should now terminate. // The second condition handles this situation. // NOTE this ugly state management cannot be avoided unless we use // some kind of a signalling mechanism between the emulator and // simulator(TODO). // Although this should handle most of the cases. if (allover || (ipcBase.javaThreadStarted[javaTid]==true && emuThreadsFinished())) { ipcBase.javaThreadTermination[javaTid] = true; break; } } finishAllPipelines(); if(unHandledCount!=null) { sorted_map.putAll(unHandledCount); System.out.println(sorted_map); } if(EmulatorConfig.storeExecutionTraceInAFile == true) { for(int rob = 0; rob < ArchitecturalComponent.getCores().length; rob++) { try { ((OutOrderExecutionEngine)ArchitecturalComponent.getCore(rob).getExecEngine()).getReorderBuffer().bw.close(); } catch(Exception e) { e.printStackTrace(); misc.Error.showErrorAndExit(e.getMessage()); } } } } } // void errorCheck(int tidApp, int emuid, int queue_size, // long numReads, long v) { // // // some error checking // // threadParams[emuid].totalRead += numReads; // long totalRead = threadParams[emuid].totalRead; // long totalProduced = ipcBase.totalProduced(tidApp); // // if (totalRead > totalProduced) { // System.out.println("numReads=" + numReads + " > totalProduced=" // + totalProduced + " !!"); // // System.out.println("queue_size=" + queue_size); // System.exit(1); // } // // if (queue_size < 0) { // System.out.println("queue less than 0"); // System.exit(1); // } // } private boolean statusOfOtherThreads() { // returns true if any other live threads have empty inputtopipeline for(int i=0;i []) Array.newInstance(GenericCircularQueue.class, EMUTHREADS); noOfMicroOps = new long[EMUTHREADS]; //numInstructions = new long[EMUTHREADS]; pipelineInterfaces = new PipelineInterface[EMUTHREADS]; for(int i = 0; i < EMUTHREADS; i++) { int id = javaTid*EMUTHREADS+i; IpcBase.glTable.getStateTable().put(id, new ThreadState(id)); emulatorThreadState[i] = new EmulatorThreadState(); threadBlockState[i]=new ThreadBlockState(); //TODO pipelineinterfaces & inputToPipeline should also be in the IpcBase pipelineInterfaces[i] = cores[i].getPipelineInterface(); inputToPipeline[i] = new GenericCircularQueue( Instruction.class, INSTRUCTION_THRESHOLD); // dynamicInstructionBuffer[i] = new DynamicInstructionBuffer(); GenericCircularQueue[] toBeSet = (GenericCircularQueue[]) Array.newInstance(GenericCircularQueue.class, 1); toBeSet[0] = inputToPipeline[i]; pipelineInterfaces[i].setInputToPipeline(toBeSet); } this.javaTid = javaTid; System.out.println("-- starting java thread"+this.javaTid); prevTotalInstructions=-1; currentTotalInstructions=0; // threadCoreMaping = new Hashtable(); prevCycles=new long[EMUTHREADS]; //added by harveenk kushagra CoreClock = cores[0].getFrequency() * 1000000; //added later by kush if(SystemConfig.memControllerToUse==true) RAMclock = (long) (1 / (SystemConfig.mainMemoryConfig.tCK) * 1000000000); if (EmulatorConfig.emulatorType == EmulatorType.none && EmulatorConfig.communicationType == CommunicationType.file) { //trace-file based simulation int numTotalThreads = 0; for (int benchmark=0; benchmark < Main.getTraceFileBasename().length; benchmark++) { for (int tid=0; ;tid++) { String inputFileName = Main.getTraceFileBasename()[benchmark] + "_" + tid + ".gz"; try { File f = new File(inputFileName); if(f.exists() && !f.isDirectory()) { numTotalThreads++; } else { break; } } catch (Exception e) { break; } } } maxCoreAssign = numTotalThreads; traceReaders = new BufferedReader[maxCoreAssign]; tracesDoneReading = new boolean[maxCoreAssign]; int index = 0; for (int benchmark=0; benchmark < Main.getTraceFileBasename().length; benchmark++) { for (int tid=0; ;tid++) { String inputFileName = Main.getTraceFileBasename()[benchmark] + "_" + tid + ".gz"; try { FileInputStream f = new FileInputStream(inputFileName); GZIPInputStream g = new GZIPInputStream(f); InputStreamReader i = new InputStreamReader(g); traceReaders[index++] = new BufferedReader(i); } catch (Exception e) { if(tid==0) { // not able to find first file is surely an error. misc.Error.showErrorAndExit("Error in reading input packet file " + inputFileName); } else { System.out.println("Number of threads for benchmark " + Main.getTraceFileBasename()[benchmark] + " : " + tid); break; } } } } } } protected void runPipelines() { int minN = Integer.MAX_VALUE; boolean RAMcyclerun = false; for (int tidEmu = 0; tidEmu < maxCoreAssign; tidEmu++) { EmulatorThreadState th = emulatorThreadState[tidEmu]; if ( th.halted && !(this.inputToPipeline[tidEmu].size() > INSTRUCTION_THRESHOLD)) { th.halted = false; } int n = (int)(inputToPipeline[tidEmu].size() / pipelineInterfaces[tidEmu].getCore().getDecodeWidth() * pipelineInterfaces[tidEmu].getCoreStepSize()); if (n < minN && n != 0) minN = n; } minN = (minN == Integer.MAX_VALUE) ? 0 : minN; for (int i1 = 0; i1 < minN; i1++) { /* Note: DRAM simulation Order of execution must be maintained for cycle accurate simulation. Order is: MainMemoryController.oneCycleOperation() processEvents() [called from within oneCycleOperation of pipelines] MainMemoryController.enqueueToCommandQ(); */ //added later by kush //run one cycle operation only when DRAM simulation enabled if(SystemConfig.memControllerToUse==true){ counter1 += RAMclock; //added by harveenk if (counter2 < counter1) { counter2 += CoreClock; for(int k=0;kSYNCHSTART && pnew.value(); bvc = new UnhandledInsnCountComparator(unHandledCount); sorted_map = new TreeMap(bvc); } if(unHandledCount.get(ip)==null) { unHandledCount.put(ip, 1l); } else { unHandledCount.put(ip,unHandledCount.get(ip)+1); } } protected boolean poolExhausted(int tidEmulator) { return false; //we have a growable pool now //return (CustomObjectPool.getInstructionPool().getNumPoolAllowed() < 2000); } private void resumeSleep(ResumeSleep update) { for (int i=0; i>>1; // System.out.println(tidApp+" pin thread got -1"); // FIXME threadParams should be on tidApp. Currently it is on tidEmu emulatorThreadState[tidApp].finished = true; } public static void setThreadState(int tid,boolean cond) { // System.out.println("set thread state halted" + tid + " to " + cond); emulatorThreadState[tid].halted = cond; } }