/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2010, Benedikt Huber (benedikt.huber@gmail.com) * * This program 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. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.wcet; import com.jopdesign.common.AppInfo; import com.jopdesign.common.ClassInfo; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.code.CallGraph; import com.jopdesign.common.code.CallGraph.DUMPTYPE; import com.jopdesign.common.config.BooleanOption; import com.jopdesign.common.config.Config; import com.jopdesign.common.config.Config.BadConfigurationError; import com.jopdesign.common.config.EnumOption; import com.jopdesign.common.config.Option; import com.jopdesign.common.config.StringOption; import com.jopdesign.common.misc.MethodNotFoundException; import com.jopdesign.common.misc.MiscUtils; import com.jopdesign.common.type.MemberID; import java.io.File; import java.util.ArrayList; import java.util.List; public class ProjectConfig { public static final StringOption PROJECT_NAME = new StringOption("projectname","name of the 'project', used when generating reports",true); /* not used, should we use it? public static final StringOption WCET_OUT = new StringOption("wcet-out", "output base path for wcet results", "${outdir}"); */ public static final StringOption WCET_MODEL = new StringOption("wcet-model","which java processor to use (jamuth, JOP, allocObjs, allocHandles, allocHeaders, allocBlocks)","${arch}"); public static final StringOption TARGET_METHOD = new StringOption("target-method", "the name (optional: class,signature) of the method to be analyzed", "measure"); public static final StringOption TARGET_LIB_SOURCEPATH = new StringOption("splib","sourcepath of the library code, only used in '--sp' value.", Config.mergePaths(new String[]{ "java/target/src/common", "java/target/src/jdk_base", "java/target/src/jdk11", "java/target/src/rtapi" })); public static final StringOption TARGET_SOURCEPATH = new StringOption("sp","the sourcepath", Config.mergePaths(new String[]{ "${splib}", "java/target/src/app", "java/target/src/bench", "java/target/src/test" })); public static final StringOption TARGET_BINPATH = new StringOption("linkinfo-path", "directory holding linker info (.link.txt)","java/target/dist/bin"); public static final BooleanOption DO_GENERATE_REPORTS = new BooleanOption("report-generation","whether reports should be generated",true); public static final BooleanOption WCET_PREPROCESS = new BooleanOption("wcet-preprocess", "Perform bytecode preprocessing (same as running WCETPreprocess first)", false); public static final BooleanOption BLOCKING_TIME_ANALYSIS = new BooleanOption("blocking-time-analysis","perform experimental synchronized block analysis",true); public static final BooleanOption OBJECT_CACHE_ANALYSIS = new BooleanOption("object-cache-analysis","perform experimental object cache analysis",false); public static final BooleanOption USE_UPPAAL = new BooleanOption("uppaal","perform uppaal-based WCET analysis",false); public static final StringOption RESULT_FILE = new StringOption("result-file","save analysis results to the given file (CSV)",true); public static final BooleanOption RESULTS_APPEND = new BooleanOption("results-append","append analysis results to the result file",false); public static final BooleanOption RESULTS_PERFORMANCE = new BooleanOption("results-performance", "Include target-app unrelated results such as solver times in the CSV file", true); public static final EnumOption<DUMPTYPE> DUMP_TARGET_CALLGRAPH = new EnumOption<DUMPTYPE>("dump-target-callgraph", "Dump the target method callgraph (with or without callstrings)", CallGraph.DUMPTYPE.off); public static final BooleanOption LOAD_LINKINFO = new BooleanOption("load-linkinfo", "Load the link file generated by JOPizer", true); public static final BooleanOption DFA_ANALYZE_BOOT = new BooleanOption("dfa-analyze-boot", "Analyze boot method by the DFA. Enable this to reuse cached DFA results of the optimizer", false); private static final Option<?>[] standaloneOptions = { TARGET_METHOD, BLOCKING_TIME_ANALYSIS, WCET_PREPROCESS, OBJECT_CACHE_ANALYSIS, LOAD_LINKINFO, DFA_ANALYZE_BOOT }; private static final Option<?>[] projectOptions = { TARGET_LIB_SOURCEPATH, TARGET_SOURCEPATH, TARGET_BINPATH, WCET_MODEL }; private static final Option<?>[] reportOptions = { PROJECT_NAME, DO_GENERATE_REPORTS, RESULT_FILE, RESULTS_APPEND, RESULTS_PERFORMANCE }; private static final Option<?>[] debugOptions = { DUMP_TARGET_CALLGRAPH, }; private Config config; private AppInfo appInfo; public static void registerOptions(Config config, boolean standalone, boolean uppaal, boolean reports) { config.addOptions(standaloneOptions, standalone); config.addOption (USE_UPPAAL, uppaal); config.addOptions(projectOptions); config.addOptions(reportOptions, reports); config.getDebugGroup().addOptions(debugOptions, standalone); } public ProjectConfig(Config config) { this.config = config; this.appInfo = AppInfo.getSingleton(); } public Config getConfig() { return this.config; } /** * This function initializes configuration defaults, like the project name. * Must be called before any option is accessed which may refer to options whose defaults are * initialized here. * * @param mainMethodID the main method signature */ public void initConfig(MemberID mainMethodID) { String projectName = MiscUtils.sanitizeFileName(mainMethodID.getClassName() + "_" + getTargetMethodName()); config.setDefaultValue(PROJECT_NAME, projectName); } /** * @return the name of the application class defining the entry point main() */ public String getAppClassName() { return appInfo.getMainMethod().getClassName(); } /** * @see #getAppClassName * @return the name of the application class, unqualified */ public String getUnqualifiedAppClassName() { String appClassName = getAppClassName(); if(appClassName.indexOf('.') > 0) { appClassName = appClassName.substring(appClassName.lastIndexOf('.')+1); } return appClassName; } /** * @return the name of the method to be analyzed */ public String getTargetMethodName() { return config.getOption(ProjectConfig.TARGET_METHOD); } public String getTargetClass() { MemberID sig = MemberID.parse(getTargetMethodName(),true); String measureClass = sig.getClassName(); if(measureClass == null) return getAppClassName(); else return measureClass; } public String getTargetMethod() { MemberID sig = MemberID.parse(getTargetMethodName(),true); return sig.getMethodSignature(); } public MethodInfo getTargetMethodInfo() { try { return appInfo.getMethodInfo(getTargetClass(), getTargetMethod()); } catch (MethodNotFoundException e) { throw new BadConfigurationError("Cannot find target method " + getTargetMethodName(), e); } } public String getProjectName() { return config.getOption(PROJECT_NAME); } public File getLinkInfoFile() { return new File(config.getOption(TARGET_BINPATH), getUnqualifiedAppClassName() + ".jop.link.txt"); } public File getProjectDir() { return getConfig().getOutDir(); } /** * Create and return output directory {@code OUT_DIR / getProjectName() / subdir} * @param subdir subdirectory of project output directory, created if necessary * @return the path to the subdirectory for output */ public File getOutDir(String subdir) { File dir = new File(getProjectDir(), subdir); if(!dir.exists()) dir.mkdir(); return dir; } public File getOutFile(String name) { File dir = getProjectDir(); if(!dir.exists()) dir.mkdir(); return new File(dir, MiscUtils.sanitizeFileName(name)); } public File getOutFile(String subdir, String name) { return new File(getOutDir(subdir),MiscUtils.sanitizeFileName(name)); } /** * @return A list of paths used for looking up sources */ public String[] getSourcePaths() { return Config.splitPaths(config.getOption(TARGET_SOURCEPATH)); } public List<File> getSourceSearchDirs(ClassInfo ci) { String[] paths = getSourcePaths(); List<File> dirs = new ArrayList<File>(); String pkgPath = File.separator + ci.getPackageName().replace('.', File.separatorChar); for (String sourcePath : paths) { sourcePath += pkgPath; dirs.add(new File(sourcePath)); } return dirs; } public String getProcessorName() { return config.getOption(WCET_MODEL); } /** * @return Whether reports should be generated */ public boolean doGenerateReport() { return config.getOption(DO_GENERATE_REPORTS); } public boolean doObjectCacheAnalysis() { return this.config.getOption(OBJECT_CACHE_ANALYSIS); } public boolean useUppaal() { return config.getOption(USE_UPPAAL); } public boolean saveResults() { return config.hasValue(RESULT_FILE); } public boolean appendResults() { return config.getOption(RESULTS_APPEND); } public boolean addPerformanceResults() { return config.getOption(RESULTS_PERFORMANCE); } public File getResultFile() { return new File(getConfig().getOption(ProjectConfig.RESULT_FILE)); } public boolean isDebugMode() { return config.getOption(Config.DEBUG); } public boolean doPreprocess() { return config.getOption(WCET_PREPROCESS); } public boolean doLoadLinkInfo() { return config.getOption(LOAD_LINKINFO); } public boolean doAnalyzeBootMethod() { return config.getOption(DFA_ANALYZE_BOOT); } /** * @return whether to perform analysis of synchronized blocks */ public boolean doBlockingTimeAnalysis() { return config.getOption(BLOCKING_TIME_ANALYSIS); } }