/* * 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.uppaal.translator; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.code.CallGraph; import com.jopdesign.common.code.CallString; import com.jopdesign.common.code.ControlFlowGraph; import com.jopdesign.common.code.ControlFlowGraph.CFGNode; import com.jopdesign.common.graphutils.ProgressMeasure.RelativeProgress; import com.jopdesign.common.misc.BadGraphException; import com.jopdesign.wcet.WCETTool; import com.jopdesign.wcet.analysis.TreeAnalysis; import com.jopdesign.wcet.uppaal.UppAalConfig; import com.jopdesign.wcet.uppaal.translator.cache.CacheSimBuilder; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Translate Java threads, either using one process per methods or * a single process */ public abstract class JavaTranslator { /* map methods to node automatons */ protected Map<MethodInfo, SubAutomaton> methodAutomata; protected List<MethodInfo> methodInfos; protected UppAalConfig config; protected WCETTool project; protected MethodInfo root; protected SystemBuilder systemBuilder; protected CacheSimBuilder cacheSim; protected HashMap<MethodInfo, Integer> methodIDs; private Map<MethodInfo, Map<ControlFlowGraph.CFGEdge, RelativeProgress<CFGNode>>> progressMap; public WCETTool getProject() { return project; } public UppAalConfig getConfig() { return config; } public List<MethodInfo> getMethodInfos() { return methodInfos; } public int getMethodID(MethodInfo m) { return methodIDs.get(m); } public CacheSimBuilder getCacheSim() { return cacheSim; } public Map<ControlFlowGraph.CFGEdge, RelativeProgress<CFGNode>> getProgress(MethodInfo mi) { return progressMap.get(mi); } public void addMethodAutomaton(MethodInfo mi, SubAutomaton auto) { this.methodAutomata.put(mi, auto); } public SubAutomaton getMethodAutomaton(MethodInfo mi) { return methodAutomata.get(mi); } public JavaTranslator(UppAalConfig c, WCETTool p, MethodInfo root) { this.config = c; this.project = p; this.root = root; /* Get callgraph */ CallGraph callGraph = project.getCallGraph(); // logger.info("Call stack depth: "+callGraph.getMaxHeight()); if (p.getCallstringLength() != 0) { throw new AssertionError("Callstrings are not support for UppAal translation"); } this.methodInfos = callGraph.getReachableImplementations(root, CallString.EMPTY); if (!methodInfos.get(0).equals(root)) { throw new AssertionError("Bad callgraph: reachable implementations needs to return root as first element"); } /* Create system builder */ systemBuilder = new SystemBuilder(config, project, callGraph.getMaxHeight() + 1, methodInfos); this.methodIDs = new HashMap<MethodInfo, Integer>(); for (int i = 0; i < methodInfos.size(); i++) { MethodInfo mi = methodInfos.get(i); methodIDs.put(mi, i); ControlFlowGraph cfg = project.getFlowGraph(mi); /* insert summary nodes if request */ if (config.collapseLeaves) { try { cfg.insertSummaryNodes(); } catch (BadGraphException e) { throw new AssertionError("Failed to insert summary nodes: " + e); } } } this.methodAutomata = new HashMap<MethodInfo, SubAutomaton>(); /* Cache sim */ this.cacheSim = systemBuilder.getCacheSim(); /* Progress measure */ TreeAnalysis ta = new TreeAnalysis(project, config.collapseLeaves); this.progressMap = ta.getRelativeProgressMap(); if (config.useProgressMeasure) { // TODO: The model checker needs some extra progress space, // if he explores loop bodies another time to often (*2 should be safe). long maxProgress = ta.getMaxProgress(project.getTargetMethod()); systemBuilder.declareVariable("int[0," + maxProgress * 2 + "]", "pm", "0"); systemBuilder.addProgressMeasure("pm"); } } protected abstract void translate(); protected void translateMethod(TemplateBuilder tb, SubAutomaton methodAutomaton, int mId, MethodInfo mi, InvokeBuilder invokeBuilder) { /* get flow graph */ ControlFlowGraph cfg = project.getFlowGraph(mi); MethodBuilder mBuilder = new MethodBuilder(this, tb, invokeBuilder, methodAutomaton, mId, cfg); mBuilder.build(); } public SystemBuilder getSystem() { translate(); return this.systemBuilder; } }