📄 wcetanalyser.java
字号:
package com.jopdesign.wcet;import java.util.*;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import org.apache.bcel.classfile.*;import org.apache.bcel.classfile.Visitor;import org.apache.bcel.generic.*;import org.apache.bcel.generic.FieldOrMethod;import org.apache.bcel.verifier.structurals.*;import com.jopdesign.build.TransitiveHull;import com.jopdesign.tools.JopInstr;import lpsolve.*;/** * The class is for wcet analysis. The class hierarchy is such * that WCETAnalyzer creates one WCETMethodBlock for each * method. The WCETMethodBlock assists WCETAnalyzer in creating the * WCETBasicBlock objects for each basic block. Then WCETBasicBlock can be used * together with WCETInstruction to calculate the WCET/BCET value for that particular * basic block. * * Options in the Makefile for the wcet target: You can set "latex" to true, * and WCA will generate "&" characters between columns and "\\" as row terminator. * In Latex do this post-processing: replace ">" with "$>$ and "_" with "\_". * A directed graph of the basic blocks can be generated in dot * format by setting the "dot" property to true. * * It can generate LPSolve compliant code which can be used to calculate * WCET of each method. Enable the "ls" switch in the Makefile. * * @author rup, ms * @see Section 7.4 and Appendix D in MS thesis * @see http://www.graphviz.org * @see http://lpsolve.sourceforge.net/5.5/ */// History:// 2006-04-01 rup: Initial version aimed at directed graph of basic blocks// 2006-04-07 rup: Moved to become a non-Jopizer dependent piece of code// 2006-04-20 rup: Show both cachehit and cachemiss entries// 2006-04-27 rup: Show latex tables and load/store info for locals// 2006-05-04 ms: Split cache miss column // 2006-05-07 rup: Output dot graphs // 2006-05-25 rup: "Annotations" and lp_solvable wcet output// 2006-05-30 rup: Exact call graph permutation to allow cache simulation//TODO: abstract method resolution (try all implementations and select worst)./** * The thing that controls the WCETClassBlock etc. */public class WCETAnalyser{ WCETMethodBlock wcmbapp = null; boolean global = true; // controls names of blocks B1 or B1_M1 if true String dotf = null; // dot property: it will generate dot graphs if true public static boolean jline; public static boolean instr; // true if you want instriction cycles printed // The app method or main if not provided public static String appmethod; public static int idtmp = 0; // counter to make unique ids public final static String nativeClass = "com.jopdesign.sys.Native"; JavaClass[] jca; PrintWriter out; PrintWriter dotout; /** * Loaded classes, type is JavaClass */ List clazzes = new LinkedList(); org.apache.bcel.util.ClassPath classpath; // = ClassPath.SYSTEM_CLASS_PATH; /** * The class that contains the main method. */ static String mainClass; public StringBuffer wcasb = new StringBuffer(); //signaure -> methodbcel HashMap mmap; // methodbcel -> WCETMethodBlock HashMap mtowcmb = new HashMap(); //method name to id HashMap midmap; //id to wcmb HashMap idmmap; // methodsignature -> wcmb HashMap msigtowcmb; HashMap javaFilePathMap; ArrayList javaFiles; public ArrayList wcmbs; // all the wcmbs static String outFile; public boolean init = true; public boolean analyze = false; public WCETAnalyser() { wcmbs = new ArrayList(); msigtowcmb = new HashMap(); classpath = new org.apache.bcel.util.ClassPath("."); mmap = new HashMap(); midmap = new HashMap(); javaFiles = new ArrayList(); javaFilePathMap = new HashMap(); } public static void main(String[] args) { WCETAnalyser wca = new WCETAnalyser(); HashSet clsArgs = new HashSet(); outFile = null; // wcet/P3+Wcet.txt //the tables can be easier to use in latex using this property jline = System.getProperty("jline", "false").equals("true"); instr = System.getProperty("instr", "true").equals("true"); // appmethod = System.getProperty("appmethod");// if(appmethod==null){// System.out.println("appmethod property not set");// System.exit(-1);// } String srcPath = "nodir"; try { if (args.length == 0) { System.err .println("WCETAnalyser arguments: [-cp classpath] [-o file] class [class]*"); } else { for (int i = 0; i < args.length; i++) { if (args[i].equals("-cp")) { i++; wca.classpath = new org.apache.bcel.util.ClassPath(args[i]); continue; } if (args[i].equals("-o")) { i++; outFile = args[i]; continue; } if (args[i].equals("-sp")) { i++; srcPath = args[i]; continue; } clsArgs.add(args[i]); mainClass = args[i].replace('/', '.'); appmethod = mainClass+".main"; } StringTokenizer st = new StringTokenizer(srcPath,";"); while(st.hasMoreTokens()){ String srcDir = st.nextToken();//"java/target/src/common"; File sDir = new File(srcDir); if(sDir.isDirectory()){//System.out.println("srcDir="+srcDir); wca.visitAllFiles(sDir); } }// Iterator ito = wca.javaFilePathMap.values().iterator();// while(ito.hasNext()){//System.out.println(ito.next()); // }//System.out.println("CLASSPATH=" + wca.classpath + "\tmain class="// + mainClass); wca.out = new PrintWriter(new FileOutputStream(outFile)); String ds = new File(WCETAnalyser.outFile).getParentFile().getAbsolutePath()+"\\Makefile"; wca.dotout = new PrintWriter(new FileOutputStream(ds)); wca.dotout.print("doteps:\n"); wca.load(clsArgs); wca.global = false; wca.iterate(new SetWCETAnalysis(wca)); wca.init = false; wca.analyze = true; wca.iterate(new SetWCETAnalysis(wca)); //wca.out.println("*************APPLICATION WCET="+wca.wcmbapp.wcet+"********************"); StringBuffer wcasbtemp = new StringBuffer(); if(wca.analyze){ wca.global = true; wcasbtemp.append(wca.wcmbapp.toLS(true,true, null)); //wca.out.println(wca.wcmbapp.toLS(true,true, null)); wcasbtemp.append(wca.toDot()); if(wca.wcmbapp.wcetlp>=0) wcasbtemp.insert(0, "*************APPLICATION WCET="+wca.wcmbapp.wcetlp+"********************\n"); else wcasbtemp.insert(0, "*************APPLICATION WCET=UNBOUNDED (CHECK LOOP BOUNDS I.E.: @WCA loop=XYZ)********************\n"); wca.out.println(wcasbtemp.toString()); wca.dotout.print("\tdot -Tps "+wca.dotf+" > "+wca.dotf.substring(0,wca.dotf.length()-4)+".eps\n"); } wca.out.println("*************END APPLICATION WCET*******************"); wca.out.println(wca.wcasb.toString()); //instruction info wca.out.println("*****************************************************"); if(instr) wca.out.println(WCETInstruction.toWCAString()); wca.out.println("Note: Remember to keep WCETAnalyzer updated"); wca.out.println("each time a bytecode implementation is changed."); wca.out.close(); wca.dotout.close(); } } catch (Exception e) { e.printStackTrace(); } } //Java Dev. Almanac public void visitAllFiles(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; i<children.length; i++) { visitAllFiles(new File(dir, children[i])); } } else { String filePath = dir.getAbsolutePath(); String fileName = dir.getName(); if(fileName.endsWith(".java")){//System.out.println(fileName);//System.out.println(filePath);// String prevPath = (String)javaFilePathMap.get(fileName);// if(prevPath != null && !prevPath.equals(filePath)){// System.out.println(fileName +" is referring to "+prevPath+" and to "+filePath+". Exiting.");// System.exit(1); // }// else{// javaFilePathMap.put(fileName,filePath);// } javaFiles.add(filePath); } }} /** * Load all classes and the super classes from the argument list. * * @throws IOException */ private void load(Set clsArgs) throws IOException { JavaClass[] jcl = new JavaClass[clsArgs.size()]; Iterator i = clsArgs.iterator(); for (int nr = 0; i.hasNext(); ++nr) { String clname = (String) i.next(); InputStream is = classpath.getInputStream(clname); jcl[nr] = new ClassParser(is, clname).parse(); } TransitiveHull hull = new TransitiveHull(classpath, jcl); hull.start(); System.out.println(Arrays.asList(hull.getClassNames())); jca = hull.getClasses(); // clazzes contains now the closure of the application int mid = 0; for (int j = 0; j < jca.length; ++j) { // The class Native is NOT used in a JOP application if (!jca[j].getClassName().equals(nativeClass)) { // ClassInfo cli = new ClassInfo(jc[j]);//System.out.println("added classname:"+jc[j].getClassName()+" filename:"+jc[j].getFileName()+ " sourcefilename:"+jc[j].getSourceFileName()+" packagename:"+jc[j].getPackageName()); clazzes.add(jca[j]); } //package name and associated sourcefile String pacSrc = jca[j].getPackageName()+"."+jca[j].getSourceFileName(); boolean fileMatch = false; for(int k=0;k<javaFiles.size();k++){ String orig = (String)javaFiles.get(k); String pn = orig; pn = pn.replace('/','.'); pn = pn.replace('\\','.');//System.out.println("Trying to match:"+pn+ " with: "+pacSrc); int match = pn.lastIndexOf(pacSrc); if(match != -1){ String key = jca[j].getClassName();//System.out.println("Match! Key :"+key); javaFilePathMap.put(key, orig); fileMatch = true; break; } } if(!fileMatch){ System.out.println("No filematch for "+jca[j].getClassName() + " and pacSrc="+pacSrc); System.exit(-1); } Method[] m = jca[j].getMethods(); for(int ii=0;ii<m.length;ii++){ String msig = jca[j].getClassName() + "." + m[ii].getName()+m[ii].getSignature();//System.out.println("m to be put:"+msig);//TODO mig everywhere //System.out.println("r: "+m[ii].getReturnType().getSignature());//TODO mig everywhere mmap.put(msig,m[ii]); midmap.put(new Integer(mid),msig); mid++; } } } private void iterate(Visitor v) { Iterator it = clazzes.iterator(); while (it.hasNext()) { JavaClass clz = (JavaClass) it.next(); new DescendingVisitor(clz, v).visit(); } } /** * Get a method object from the String id. It is used to find * the length of a method when it is invoked from some method. * The methodid is created like this: c.getClassName() + "." + m.getName()+m.getSignature(); * @param methodid * @return the method object */ public Method getMethod(String methodid){ Method m = (Method)mmap.get(methodid); return m; } public WCETMethodBlock getWCMB(Method method){ WCETMethodBlock wcmb = (WCETMethodBlock)mtowcmb.get(method);//System.out.println("getWCMB:"+wcmb); return wcmb; } /** * Return the opcode for the methodId (applicable to Native methods). * @param methodid * @return opcode which can be used to call WCETIstruction.getcycles */ public int getNativeOpcode(String methodid){ int opcode = JopInstr.getNative(methodid); if(opcode==-1){ System.out.println("Did not find native"); System.exit(-1); } return opcode; } public String toDot(){ StringBuffer sb = new StringBuffer(); sb.append("\n/* App Dot Graph */\n"); sb.append("digraph G {\n"); //8.27 x 11.69 inches sb.append("size = \"7.27,9.69\"\n"); //boolean mem = global; //global = false; ArrayList appWCMB = new ArrayList(); appWCMB.add(wcmbapp); while(appWCMB.size() > 0){ WCETMethodBlock wcmb = (WCETMethodBlock)appWCMB.get(0); wcmb.link(); sb.append("subgraph cluster"+wcmb.mid+" {\n"); sb.append("color = black;\n"); sb.append(wcmb.toDot(true)+"\n"); sb.append("label = \""+wcmb.cname+"."+wcmb.name+" : M"+wcmb.mid+"\";\n"); sb.append("}\n"); WCETBasicBlock[] wcbba = wcmb.getBBSArray(); for(int j=0;j<wcbba.length;j++){ if(wcbba[j].invowcmb != null){ sb.append(wcbba[j].toDotFlowEdge(wcbba[j].invowcmb.S)); sb.append(" [label=\""+wcbba[j].toDotFlowLabel(wcbba[j].invowcmb.S)+"\"];\n"); sb.append(wcbba[j].invowcmb.T.toDotFlowEdge(wcbba[j])); sb.append(" [label=\""+wcbba[j].invowcmb.T.toDotFlowLabel(wcbba[j])+"\"];\n"); appWCMB.add(wcbba[j].invowcmb); } } appWCMB.remove(0); } sb.append("}\n"); try { dotf = new File(WCETAnalyser.outFile).getParentFile().getAbsolutePath()+"\\App.dot"; dotf = dotf.replace('<','_'); dotf = dotf.replace('>','_'); dotf = dotf.replace('\\','/'); PrintWriter dotout = new PrintWriter(new FileOutputStream(dotf));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -