/* * 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.analysis; import java.util.EnumSet; import com.jopdesign.common.MethodInfo; import com.jopdesign.common.code.CallString; import com.jopdesign.common.code.ControlFlowGraph; import com.jopdesign.common.code.Segment; import com.jopdesign.wcet.WCETProcessorModel; import com.jopdesign.wcet.WCETTool; import com.jopdesign.wcet.analysis.RecursiveAnalysis.RecursiveStrategy; import com.jopdesign.wcet.analysis.cache.CachePersistenceAnalysis; import com.jopdesign.wcet.analysis.cache.CachePersistenceAnalysis.PersistenceCheck; import com.jopdesign.wcet.analysis.cache.MethodCacheAnalysis; import com.jopdesign.wcet.ipet.IPETConfig; import com.jopdesign.wcet.ipet.IPETConfig.CacheCostCalculationMethod; import org.apache.log4j.Logger; public class LocalAnalysis implements RecursiveStrategy<AnalysisContextLocal,WcetCost> { private boolean assumeMissOnceOnInvoke; private int maxCallstringLength; private static final Logger logger = Logger.getLogger(WCETTool.LOG_WCET_ANALYSIS+".LocalAnalysis"); public LocalAnalysis(WCETTool p, IPETConfig ipetConfig) { this(ipetConfig.doAssumeMissOnceOnInvoke(), p.getCallstringLength()); } public LocalAnalysis() { this(false, 0); } public LocalAnalysis(boolean doAssumeMissOnceOnInvoke, int callstringLength) { this.assumeMissOnceOnInvoke = doAssumeMissOnceOnInvoke; this.maxCallstringLength = callstringLength; } public WcetCost recursiveCost( RecursiveAnalysis<AnalysisContextLocal,WcetCost> stagedAnalysis, ControlFlowGraph.InvokeNode n, AnalysisContextLocal ctx) { CacheCostCalculationMethod cacheMode = ctx.getCacheApproxMode(); if(cacheMode.needsInterProcIPET()) { throw new AssertionError("Error: Cache Mode "+cacheMode+" not supported using local IPET strategy - " + "it needs an interprocedural IPET analysis"); } WCETTool project = stagedAnalysis.getWCETTool(); MethodInfo invoker = n.getBasicBlock().getMethodInfo(); MethodInfo invoked = n.getImplementingMethod(); WCETProcessorModel proc = project.getWCETProcessorModel(); MethodCacheAnalysis mca = new MethodCacheAnalysis(project); long cacheCost; AnalysisContextLocal recCtx = ctx.withCallString(ctx.getCallString().push(n,maxCallstringLength)); WcetCost recCost = stagedAnalysis.computeCost(invoked, recCtx); long nonLocalExecCost = recCost.getCost() - recCost.getCacheCost(); long nonLocalCacheCost = recCost.getCacheCost(); long invokeReturnCost = mca.getInvokeReturnMissCost(n.getInvokeSite(), ctx.getCallString()); if(proc.getMethodCache().getNumBlocks() == 0 || cacheMode == CacheCostCalculationMethod.ALWAYS_HIT) { cacheCost = 0; } else if(project.getCallGraph().isLeafMethod(invoked)) { cacheCost = invokeReturnCost + nonLocalCacheCost; } else if(cacheMode == CacheCostCalculationMethod.ALL_FIT_SIMPLE && allFit(project, invoked,recCtx.getCallString())) { long returnCost = mca.getMissOnceCost(invoker, false); /* Maybe its better not to apply the all-fit heuristic ... */ long noAllFitCost = recCost.getCost() + invokeReturnCost; /* Compute cost without method cache */ AnalysisContextLocal ahCtx = recCtx.withCacheApprox(CacheCostCalculationMethod.ALWAYS_HIT); long alwaysHitCost = stagedAnalysis.computeCost(invoked, ahCtx).getCost(); /* Compute penalty for loading each method exactly once */ long allFitPenalty = mca.getMissOnceCummulativeCacheCost(invoked,assumeMissOnceOnInvoke); long allFitCacheCost = allFitPenalty + returnCost; /* Cost All-Fit: recursive + penalty for loading once + return to caller */ long allFitCost = alwaysHitCost + allFitCacheCost; // System.out.println(String.format("Method: %s, alwaysHitCost: %d, allFitCost: %d, noAllFitCost: %d(%d+%d)", // invoked.getFQMethodName(), alwaysHitCost, allFitCost, noAllFitCost,recCost.getCost(),invokeReturnCost)); /* Choose the better approximation */ if(allFitCost <= noAllFitCost) { cacheCost = allFitCacheCost; nonLocalExecCost = alwaysHitCost; } else { cacheCost = invokeReturnCost + nonLocalCacheCost; } } else { /* ALWAYS MISS or doesn't fit */ cacheCost = invokeReturnCost + nonLocalCacheCost; } WcetCost cost = new WcetCost(); cost.addNonLocalCost(nonLocalExecCost); cost.addCacheCost(cacheCost); logger.debug("Recursive WCET computation: " + invoked + ". invoke return cache cost: " + invokeReturnCost+ ". non-local cache cost: " + nonLocalCacheCost+ ". cummulative cache cost: "+cacheCost+ " non local execution cost: "+nonLocalExecCost); return cost; } protected boolean allFit(WCETTool wcetTool, MethodInfo invoked,CallString callString) { return new MethodCacheAnalysis(wcetTool). isPersistenceRegion(wcetTool, invoked, callString, EnumSet.of(PersistenceCheck.CountTotal)); } }