ByteCode_Type instruction2ByteCode( string inst, InstructionSet& iset ) { for (ByteCode_Type i=0;i<iset.size();i++) if (inst == iset.getName(i) ) return i; throw (string)"Instruction not recognized: " + inst; }
// Runs a given ByteCode, returns true if timed-out. bool runByteCode(InstructionSet& iset, MemCore& core, ByteCode& bc, long randseed, long max_rtime, int max_loop_depth) { if (!max_rtime) max_rtime = 3600*24*7; // that's a week's worth of runtime! core.C = &bc; core.c = 0; iset.clear(); #ifndef DEBUG /* Setup the time-out handler */ timedout=false; signal(SIGALRM, alarm_handler); alarm(max_rtime); #endif iset.setMaxLoopDepth(max_loop_depth); try { do { #ifdef DEBUG cout << " [I]=" << core.I << ", [F]=" << core.F << ", D[I]=" << core.D[core.I] << endl; cout << " Next instruction: " << iset.getName((*core.C)[core.c]) << ". (hit enter)"; cin.get(); cout << endl; #endif iset.exec((*core.C)[core.c], core); core.c++; } while ( (core.c<(*core.C).size()) && (!timedout) ); } catch(int whatever) { return true; // program failed } #ifndef DEBUG alarm(0); // turns off alarm #endif if (timedout) return true; // interpreter timed-out else return false; } // runByteCode
static InstructionSet getControlDependentInstructions( const PTXInstruction* branch, const InstructionSet& instructions, analysis::ControlDependenceAnalysis* controlDependenceAnalysis) { InstructionSet controlDependentInstructions; for(auto instruction : instructions) { if(controlDependenceAnalysis->dependsOn(branch, instruction)) { controlDependentInstructions.insert(instruction); } } return controlDependentInstructions; }
static bool dependsOn(iterator next, iterator dependee, InstructionSet& visited, DependenceMap& savedDependencies) { auto dependence = InstructionPair(next->instruction, dependee->instruction); auto savedDependence = savedDependencies.find(dependence); if(savedDependence != savedDependencies.end()) { return savedDependence->second; } if(!visited.insert(next->instruction).second) return false; if(next == dependee) return true; for(auto successor : next->successors) { if(dependsOn(successor, dependee, visited, savedDependencies)) { return true; } savedDependencies.insert(std::make_pair( InstructionPair(next->instruction, successor->instruction), true)); } savedDependencies.insert(std::make_pair( InstructionPair(next->instruction, dependee->instruction), false)); return false; }
void bytecode2Source( ByteCode& bc, string& src, InstructionSet& iset ) { src.clear(); for (unsigned i=0;i<bc.size();i++) src += iset.getName(bc[i]) + "/"; src += "."; }
static InstructionSet getInstructionsThatCanObserveSideEffects(ir::IRKernel& k) { InstructionSet instructions; report(" Getting instructions that can observe side-effects"); for(auto& block : *k.cfg()) { for(auto instruction : block.instructions) { auto ptxInstruction = static_cast<ir::PTXInstruction*>(instruction); if(ptxInstruction->canObserveSideEffects()) { report(" " << ptxInstruction->toString()); instructions.insert(ptxInstruction); } } } return instructions; }
static void addPredecessors(InstructionSet& predecessors, ir::BasicBlock::const_iterator instruction) { auto end = (*instruction)->block->rend(); auto position = ir::BasicBlock::const_reverse_iterator(instruction); for(; position != end; ++position) { if(!hasDependence(**position, **instruction)) continue; report(" " << (*position)->toString() << " (" << (*position)->index() << ") -> " << (*instruction)->toString() << " (" << (*instruction)->index() << ")"); predecessors.insert(*position); } }
void ParallelismTraceAnalyzer::parallelism() const { typedef std::vector< ParallelismTraceGenerator::Event > EventVector; typedef std::set< long long unsigned int > InstructionSet; double averageSIMD = 0; double averageMIMD = 0; double averageCTAs = 0; for( KernelMap::const_iterator vector = _kernels.begin(); vector != _kernels.end(); ++vector ) { std::cout << " From program \"" << vector->first << "\".\n"; double localSIMD = 0; double localMIMD = 0; double localCTAs = 0; for( KernelVector::const_iterator kernel = vector->second.begin(); kernel != vector->second.end(); ++kernel ) { std::ifstream hstream( kernel->header.c_str() ); boost::archive::text_iarchive harchive( hstream ); ParallelismTraceGenerator::Header header; harchive >> header; assert( header.format == TraceGenerator::ParallelismTraceFormat ); hstream.close(); std::ifstream stream( kernel->path.c_str() ); if( !stream.is_open() ) { throw hydrazine::Exception( "Failed to open ParallelismTrace kernel trace file " + kernel->path ); } boost::archive::text_iarchive archive( stream ); EventVector events( header.dimensions ); for( EventVector::iterator event = events.begin(); event != events.end(); ++event ) { archive >> *event; } std::cout << " From file " << kernel->path << "\n"; std::cout << " kernel: " << kernel->name << "\n"; std::cout << " module: " << kernel->module << "\n"; std::cout << " statistics:\n"; std::cout << " ctas: " << header.dimensions << "\n"; std::cout << " threads: " << header.threads << "\n"; InstructionSet instructions; long long unsigned int totalInstructions = 0; double activity = 0; for( EventVector::iterator event = events.begin(); event != events.end(); ++event ) { totalInstructions += event->instructions; instructions.insert( event->instructions ); activity += event->activity * event->instructions; } activity /= totalInstructions + DBL_EPSILON; unsigned int previous = 0; unsigned int count = header.dimensions; double mimd = 0; for( InstructionSet::iterator instruction = instructions.begin(); instruction != instructions.end(); ++instruction ) { mimd += (*instruction - previous) * count; previous = *instruction; --count; } if( !instructions.empty() ) { mimd /= *(--instructions.end()) + DBL_EPSILON; } std::cout << " SIMD parallelism: " << activity << "\n"; std::cout << " MIMD parallelism: " << mimd << "\n"; localSIMD += activity; localMIMD += mimd; localCTAs += header.dimensions; } localSIMD /= vector->second.size() + DBL_EPSILON; localMIMD /= vector->second.size() + DBL_EPSILON; localCTAs /= vector->second.size() + DBL_EPSILON; std::cout << " Kernel " << vector->first << " statistics:\n"; std::cout << " average CTAs: " << localCTAs << "\n"; std::cout << " average SIMD parallelism: " << localSIMD << "\n"; std::cout << " average MIMD parallelism: " << localMIMD << "\n"; averageSIMD += localSIMD; averageMIMD += localMIMD; averageCTAs += localCTAs; } averageSIMD /= _kernels.size() + DBL_EPSILON; averageMIMD /= _kernels.size() + DBL_EPSILON; averageCTAs /= _kernels.size() + DBL_EPSILON; std::cout << "Aggregate statistics:\n"; std::cout << " average CTAs: " << averageCTAs << "\n"; std::cout << " average SIMD parallelism: " << averageSIMD << "\n"; std::cout << " average MIMD parallelism: " << averageMIMD << "\n"; }
void VirtualMachine::execute(std::string function) { NamespaceEntry functionEntry; if (!VM::NamespaceEntry::searchNamespace(namespace_, function, functionEntry) || functionEntry.getType() != Function) { VM_PRINTF_FATAL("%s is not a registered function\n", function.c_str()); } currentFunction = functionEntry.getFunction(); if (currentFunction->isNative()) { currentFunction->getFunction()->execute(this); return; } InstructionSet instructionSet = currentFunction->getInstructions(); currentInstruction = instructionSet.getStartLocation(); shouldReturn = false; while (!shouldReturn) { //If the current PC is above the number of instructions in this function then attempt to return. Else execute the instruction at the PC. if (currentInstruction >= instructionSet.getSizeInBytes()) { if (!returnToPreviousFunction(currentFunction, instructionSet)) { shouldReturn = true; } } else { switch (instructionSet.getByte(currentInstruction)) { /** * Loads the constant data at the specified constant index into the given register. * Capable of loading elements into the heap and assigning their reference if their initial data is already known ( Such as pushing strings ). */ case OpLoadConstant: { opLoadConstant(instructionSet); break; } /** * Copy whatever is in the target register into the destination register copying over whether it is a reference or not. */ case OpMove: { opMove(instructionSet); break; } /** * Jump to a different instruction */ case OpJump: { opJump(instructionSet); break; } /** * Add the left and right registers and place the result in the dest register. */ case OpAdd: { opAdd(instructionSet); break; } /** * Subtract the left and right registers and place the result in the dest register. */ case OpSub: { opSub(instructionSet); break; } /** * Multiply the left and right registers and place the result in the dest register. */ case OpMul: { opMul(instructionSet); break; } /** * Divide the left and right registers and place the result in the dest register. */ case OpDiv: { opDiv(instructionSet); break; } case OpInc: { opInc(instructionSet); break; } case OpDec: { opDec(instructionSet); break; } case OpNot: { opNot(instructionSet); break; } case OpAddFloat32: { opAddFloat32(instructionSet); break; } case OpSubFloat32: { opSubFloat32(instructionSet); break; } case OpMulFloat32: { opMulFloat32(instructionSet); break; } case OpDivFloat32: { opDivFloat32(instructionSet); break; } case OpCmpFloat32: { opCmpFloat32(instructionSet); break; } /** * Test if two registers are equal. If true then execute the next instruction else skip it. */ case OpEqual: { opEqual(instructionSet); break; } case OpNotEqual: { opNotEqual(instructionSet); break; } case OpEqualZero: { opEqualZero(instructionSet); break; } /** * Test if one register is less than another. If true execute next instruction otherwise skip it. */ case OpLessThan: { opLessThan(instructionSet); break; } case OpGreaterThan: { opGreaterThan(instructionSet); break; } case OpGreaterThanOrEqual: { opGreaterThanOrEqual(instructionSet); break; } /** * OpPushRegisters * Push registers, starting from the start register and pushing numregisters sequentially from it * StartRegister - Offset 1 - 1 byte * NumRegisters - Offset 2 - 1 byte */ case OpPushRegisters: { opPushRegisters(instructionSet); break; } /** * Pop n registers starting from the start+nth register and the last pop acting on the start register */ case OpPopRegisters: { opPopRegisters(instructionSet); break; } /** * Pop a long from the stack and ignore it ( Don't put it in any registers ). */ case OpPopNil: { opPopNil(instructionSet); break; } /** * Test whether the register left's value is <= than the register right. * If true execute the next instruction * Else skip the next function. */ case OpLessThanOrEqual: { opLessThanOrEqual(instructionSet); break; } case OpStructGetField: { opStructGetField(instructionSet); break; } case OpStructSetField: { opStructSetField(instructionSet); break; } /** * Set the specified element in the target array to the given data value. */ case OpArraySet: { opArraySet(instructionSet); break; } /** * Set the dataRegisters value to be the value of the array at the specified index. */ case OpArrayGet: { opArrayGet(instructionSet); break; } case OpNewStruct: { opNewStruct(instructionSet); break; } /** * Create a new array of the specified type ( Stored in constants ) and length ( The value of lengthRegister ) and set its reference to the specified register. */ case OpNewArray: { opNewArray(instructionSet); break; } /** * Set the value of dest register to be the length of the array pointed to by the value of the array length register. */ case OpArrayLength: { opArrayLength(instructionSet); break; } /** * Call the specified function. Two modes Constant or Heap. If Constant mode name of function is stored in constant instruction set zone otherwise name of function is pointed to by string in heap specified by register. */ case OpCallFn: { opCallFn(instructionSet); break; } /** * Return to the previous function that was running or exit. */ case OpReturn: { opReturn(instructionSet); break; } default: { VM_PRINTF_FATAL("Invalid instruction %li. %ii\n", currentInstruction, instructionSet.getByte(currentInstruction)); return; } } //After each instruction check the gcStat and //if it has hit the hit limit then run the garbage collector. if (gcStat_ > GarbageCollectHitLimit) { garbageCollection(); gcStat_ = 0; } } } //As the function exits run the garbage collector and reset the GC stat value garbageCollection(); gcStat_ = 0; }