/** * Transform an address to a smart string, that is, * if a source line is available, transform it to "source_file:source_line", * if the CFG has a label, it gives "label + 0xoffset", else return the * address. * @param base Base address of the function containing the give address. * @param address Address to display. * @return Address transformed in string. */ string CFGProcessor::str(const Address& base, const Address& address) { Inst *first; if(base.isNull()) first = _cfg->firstInst(); else first = workspace()->findInstAt(base); String label; if(first) label = FUNCTION_LABEL(first); if(label) { int offset = address.offset() - first->address().offset(); if(offset < 0) return _ << label << " - 0x" << io::hex(-offset) << " (" << address << ")"; else return _ << label << " + 0x" << io::hex(offset) << " (" << address << ")"; } else return _ << "0x" << address; }
/** * Fill-in the BSet structure by identifying each brbanch address class. * * @param cfg CFG to analyze. * @param bs BSets structure to fill-in. */ void BPredProcessor::generateClasses(CFG *cfg, BSets& bs) { for(CFG::BBIterator bb(cfg); bb; bb++) { unsigned int nb_OE = 0; // Parcours des OutEdges for(BasicBlock::OutIterator edge(bb); edge ; edge++ ) { // on incremente que s'il s'agit d'un edge TAKEN ou NOT_TAKEN if(edge->kind() == Edge::TAKEN) nb_OE++; else if(edge->kind() == Edge::NOT_TAKEN) nb_OE++; } // Si un branchement a ete trouve ... if(nb_OE == 2 ) { Inst* inst = NULL; for(BasicBlock::InstIter i(bb); i; i++) { inst=i; } bs.add((inst->address() & (this->BHT)), bb->number()); } } }
int main(int argc, char **argv) { Manager manager; PropList props; PROCESSOR_PATH(props) = "../../data/procs/op1.xml"; CACHE_CONFIG_PATH(props) = "../../data/caches/inst-64x16x1.xml"; try { // Load program if(argc < 2) { cerr << "ERROR: no argument.\n" << "Syntax is : test_ipet <executable>\n"; return 2; } WorkSpace *fw = manager.load(argv[1], props); assert(fw); // Display information cout << "PLATFORM INFORMATION\n"; Platform *pf = fw->platform(); cout << "Platform : " << pf->identification().name() << '\n'; cout << '\n'; // Display registers cout << "REGISTERS\n"; for(int i = 0; i < pf->banks().count(); i++) { const hard::RegBank *bank = pf->banks()[i]; cout << "Bank " << bank->name() << ", " << bank->size() << "bits, " << bank->count() << " registers, " << reg_kinds[bank->kind()]; for(int j = 0; j < bank->registers().count(); j++) { if(j % 8 == 0) cout << "\n\t"; else cout << ", "; cout << bank->registers()[j]->name(); } cout << '\n'; } cout << '\n'; // Display cache cout << "CACHE CONFIGURATION\n"; const CacheConfiguration& cconf(pf->cache()); display_cache_level(1, cconf.instCache(), cconf.dataCache()); cout << '\n'; // Display some instructions fw->require(DECODED_TEXT); cout << "READ/WRITTEN REGS TEST\n"; String label("main"); Inst *inst = fw->process()->findInstAt("main"); //fw->findLabel(label)); if(!inst) throw new otawa::Exception(CString("no main in this file ?")); for(int i = 0; i < 10; i++, inst = inst->nextInst()) { cout << '\n' << inst->address() << ": " << inst << " (" << io::hex(inst->kind()) << ")\n"; const elm::genstruct::Table<hard::Register *>& reads = inst->readRegs(); cout << "\tread registers : "; for(int i = 0; i < reads.count(); i++) cout << reads[i] << ' '; cout << '\n'; const elm::genstruct::Table<hard::Register *>& writes = inst->writtenRegs(); cout << "\twritten registers : "; for(int i = 0; i < writes.count(); i++) cout << writes[i] << ' '; cout << '\n'; } cout << io::endl; // Processor load test cout << "Processor load test\n"; //pf->loadProcessor("proc.xml"); const hard::Processor *proc = pf->processor(); if(!proc) cout << "NO PROCESSOR !\n"; else { cout << "arch = " << proc->getArch() << io::endl; cout << "model = " << proc->getModel() << io::endl; cout << "builder = " << proc->getBuilder() << io::endl; cout <<"stages =\n"; const elm::genstruct::Table<hard::Stage *>& stages = proc->getStages(); for(int i = 0; i< stages.count(); i++) { cout << '\t' << stages[i]->getName() << " " << stages[i]->getType() << " " << stages[i]->getWidth() << " " << stages[i]->getLatency() << " " << io::pointer(stages[i]) << io::endl; const elm::genstruct::Table<hard::FunctionalUnit *>& fus = stages[i]->getFUs(); if(fus) { cout << "\tfus=\n"; for(int i = 0; i < fus.count(); i++) cout << "\t\t" << fus[i]->getName() << ' ' << fus[i]->getWidth() << ' ' << fus[i]->getLatency() << ' ' << fus[i]->isPipelined() << io::endl; } const elm::genstruct::Table<hard::Dispatch *>& dispatch = stages[i]->getDispatch(); if(dispatch) { cout << "\tdispatch=\n"; for(int i = 0; i < dispatch.count(); i++) cout << "\t\t" << dispatch[i]->getType() << ' ' << dispatch[i]->getFU()->getName() << io::endl; } } cout << "queues =\n"; const elm::genstruct::Table<hard::Queue *>& queues = proc->getQueues(); for(int i = 0; i< queues.count(); i++) { cout << '\t' << queues[i]->getName() << " " << queues[i]->getSize() << " " << queues[i]->getInput()->getName() << " (" << io::pointer(queues[i]->getInput()) << ") " << queues[i]->getOutput()->getName() << " (" << io::pointer(queues[i]->getOutput()) << ")" << io::endl; const elm::genstruct::Table<hard::Stage *>& intern = queues[i]->getIntern(); if(intern) { cout << "\tintern=\n"; for(int i = 0; i < intern.count(); i++) cout << "\t\t" << intern[i]->getName() << " (" << io::pointer(intern[i]) << ')' << io::endl; } } } } catch(elm::Exception& e) { cerr << "ERROR: " << e.message() << '\n'; return 1; } return 0; }
/** * Use fft_parser for editing flow facts: * <br>-to ETS::ID_LOOP_COUNT for loop. * <br>If the table contains the key put its value, * <br>else put -1. * @param ws Container framework. * @param ast AST to process. */ void FlowFactLoader::processAST(WorkSpace *ws, AST *ast){ //int val; switch(ast->kind()) { case AST_Seq: processAST(ws, ast->toSeq()->child1()); processAST(ws, ast->toSeq()->child2()); break; case AST_If: processAST(ws, ast->toIf()->condition()); processAST(ws, ast->toIf()->thenPart()); processAST(ws, ast->toIf()->elsePart()); break; case AST_While: { Inst *inst = ast->toWhile()->condition()->first(); int count = MAX_ITERATION(inst); if(count < 0) warn(_ << "loop at " << inst->address() << " has no bound"); else { FFL_OUT(cout << "|| " << ast->toWhile()->condition()->first()->get<String>(File::ID_Label, "unknown ")<< " a pour nb d'iter : "<< count << '\n'); LOOP_COUNT(ast->toWhile()) = count; } processAST(ws, ast->toWhile()->condition()); processAST(ws, ast->toWhile()->body()); } break; case AST_DoWhile: { Inst *inst = ast->toDoWhile()->condition()->first(); int count = MAX_ITERATION(inst); if(count < 0) warn(_ << "loop at " << inst->address() << " has no bound"); else { FFL_OUT(cout << "|| "<< ast->toDoWhile()->condition()->first()->get<String>(File::ID_Label, "unknown ") << " a pour nb d'iter : "<< count << '\n'); LOOP_COUNT(ast->toDoWhile()) = count; } processAST(ws, ast->toDoWhile()->condition()); processAST(ws, ast->toDoWhile()->body()); } break; case AST_For: { Inst *inst = ast->toFor()->condition()->first(); int count = MAX_ITERATION(inst); if(count < 0) warn(_ << "loop at " << inst->address() << " has no bound"); else { FFL_OUT(cout << "|| " << ast->toFor()->condition()->first()->address()<<" ~ "<<ast->toFor()->condition()->first()->get<String>(File::ID_Label, "unknown ") << " a pour nb d'iter : "<< count << '\n'); LOOP_COUNT(ast->toFor()) = count; } processAST(ws, ast->toFor()->initialization()); processAST(ws, ast->toFor()->condition()); processAST(ws, ast->toFor()->body()); processAST(ws, ast->toFor()->incrementation()); } break; case AST_Call:{ ASTInfo *ast_info = ws->getASTInfo(); Option< FunAST *> fun_res = ast_info->get(ast->toCall()->function()->name()); if(fun_res) { AST *fun_ast = (*fun_res)->ast(); processAST(ws, fun_ast); } break; } default: break; } }
virtual void work(PropList &props) throw (elm::Exception) { WorkSpace *ws = workspace(); cerr << "DEBUG: verbose = " << isVerbose() << "\n"; // put the symbols for(Process::FileIter file(workspace()->process()); file; file++) for(File::SymIter sym(file); sym; sym++) { if(sym->kind() == Symbol::FUNCTION || sym->kind() == Symbol::LABEL) { cerr << "DEBUG: code symbol: " << sym->name() << " (" << sym->address() << ")\n"; Inst *inst = workspace()->findInstAt(sym->address()); if(inst) { Symbol::ID(inst).add(*sym); switch(sym->kind()) { case Symbol::FUNCTION: FUNCTION_LABEL(inst).add(sym->name()); break; case Symbol::LABEL: LABEL(inst).add(sym->name()); break; default: break; } } } } cerr << "DEBUG: here\n"; // Look the _start Inst *start = ws->start(); if(start) { if(isVerbose()) cerr << "ENTRY: processing entry at " << start->address() << io::endl; processEntry(ws, start->address()); } else if(isVerbose()) cerr << "no entry to process\n"; // Look the function symbols for(Process::FileIter file(ws->process()); file; file++) for(File::SymIter sym(file); sym; sym++) if(sym->kind() == Symbol::FUNCTION) { if(IGNORE_ENTRY(sym)) cerr << "\n\nINFO: ignoring function symbol \"" << sym->name() << "\"\n"; else { cerr << "\n\nENTRY: processing function \"" << sym->name() << " at " << sym->address() << io::endl; Inst *inst = ws->findInstAt(sym->address()); if(inst) processEntry(ws, sym->address()); else cerr << "bad function symbol \"" << sym->name() << "\" no code segment at " << sym->address() << io::endl; } } // dump the instructions for(Process::FileIter file(workspace()->process()); file; file++) { cout << "FILE: " << file->name() << io::endl; for(File::SegIter seg(file); seg; seg++) { cout << "SEGMENT: " << seg->name() << io::endl; for(Segment::ItemIter item(seg); item; item++) { Inst *inst = item->toInst(); if(inst) { if(MARKER(inst)) cout << io::endl; for(Identifier<Symbol *>::Getter sym(inst, Symbol::ID); sym; sym++) cout << "\t" << sym->name() << ":\n"; cout << "\t\t" << inst->address() << " "; if(inst->isUnknown()) { cout << "<unknown>:"; writeBytes(cout, inst->address(), inst->size()); } else cout << inst; if(MARKER(inst)) { bool fst = true; for(Identifier<Inst *>::Getter from(inst, FROM); from; from++) { cout << (fst ? "\tfrom " : ", "); fst = false; cout << from->address(); } } cout << io::endl; } } } cout << "\n"; } }
void processEntry(WorkSpace *ws, address_t address) { ASSERT(ws); ASSERT(address); // Initialize the queue VectorQueue<Inst *> todo(1024); Inst *inst = getInst(workspace(), address); if(!inst) { cerr << "ERROR: bad function entry at " << address << io::endl; return; } todo.put(inst); // Repeat until there is no more address to explore while(!todo.isEmpty()) { // Get the next instruction Inst *first_inst = todo.get(); if(!first_inst) continue; if(isVerbose()) cerr << "starting from " << first_inst->address() << io::endl; inst = first_inst; // Follow the instruction until a branch address_t next; while(inst && !MARKER(inst)) { if(isVerbose()) { cerr << "process " << inst->address() << " : "; writeBytes(cerr, inst->address(), inst->size()); cerr << ": " << inst << io::endl; } if(inst->isControl()) break; next = inst->topAddress(); inst = getInst(ws, next, inst); } // mark the block if(isVerbose()) cerr << "end found\n"; if(!inst) { cerr << "WARNING: unknown instruction at " << next << io::endl; continue; } bool marker_found = MARKER(inst); MARKER(first_inst) = true; if(marker_found) continue; // Record target and next if(inst->isConditional()) { if(isVerbose()) cerr << "put(" << inst->topAddress() << ")" << io::endl; Inst *ti = getInst(ws, inst->topAddress(), inst); if(!ti) cerr << "ERROR: broken sequence from " << inst->address() << " to " << inst->topAddress() << io::endl; else { FROM(ti).add(first_inst); todo.put(ti); } } if(!inst->isReturn() && !IS_RETURN(inst)) { Inst *target = 0; try { target = inst->target(); if(!target) continue; } catch(ProcessException& e) { cerr << "WARNING: " << e.message() << ": the branched code will not be decoded\n"; } if(target && !NO_CALL(target)) { if(isVerbose()) cerr << "put(" << target->address() << ")\n"; FROM(target).add(first_inst); todo.put(target); } else if(!target) { bool one = false; for(Identifier<Address>::Getter target(inst, BRANCH_TARGET); target; target++) { one = true; Inst *ti = getInst(ws, target, inst); if(!ti) { cerr << "ERROR: broken target from " << inst->address() << " to " << *target << io::endl; continue; } FROM(ti).add(first_inst); todo.put(ti); if(isVerbose()) cerr << "put(" << target << ")\n"; } if(!one) cerr << "WARNING: no target for branch at " << inst->address() << io::endl; } if(inst->isCall() && (!target || !NO_RETURN(target))) { if(isVerbose()) cerr << "put(" << inst->topAddress() << ")\n"; Inst *ti = getInst(ws, inst->topAddress(), inst); if(!ti) { cerr << "ERROR: broken target from " << inst->address() << " to " << *target << io::endl; continue; } FROM(ti).add(first_inst); todo.put(ti); } } } }