use of com.jopdesign.wcet.analysis.cache.ObjectCacheEvaluationResult.OCacheMode in project jop by jop-devel.
the class ObjectCacheEvaluation method evaluateObjectCache.
private void evaluateObjectCache(MethodInfo targetMethod) throws InvalidFlowFactException, LpSolveException {
long start, stop;
// Method Cache
//testExactAllFit();
// Object Cache (debugging)
ObjectCache objectCache = project.getWCETProcessorModel().getObjectCache();
if (objectCache == null) {
throw new AssertionError("Cannot evaluate object cache on a processor without object cache");
}
ObjectCacheAnalysis ocAnalysis = new ObjectCacheAnalysis(project, objectCache);
// ocAnalysis.false, 1, 65536, ObjectCacheAnalysisDemo.DEFAULT_SET_SIZE);
TopologicalOrderIterator<ExecutionContext, ContextEdge> cgIter = this.project.getCallGraph().topDownIterator();
while (cgIter.hasNext()) {
ExecutionContext scope = cgIter.next();
Set<SymbolicAddress> addresses = ocAnalysis.getAddressSet(scope);
String entryString = String.format("%-50s ==> |%d|%s ; Saturated Types: (%s)", scope, addresses.size(), ocAnalysis.getAddressSet(scope), ocAnalysis.getSaturatedTypes(scope));
System.out.println(" " + entryString);
}
// Object cache, evaluation
PrintStream pStream;
ExecHelper.TeePrintStream oStream;
try {
pStream = new PrintStream(project.getProjectConfig().getOutFile("ocache", "eval.txt"));
oStream = new ExecHelper.TeePrintStream(System.out, pStream);
} catch (FileNotFoundException e) {
oStream = new ExecHelper.TeePrintStream(System.out, null);
}
ObjectCacheAnalysisDemo oca;
ObjectCacheTiming[] configs = { // sram,uni: 2 cycles field cost, 2*w cycles line cost
new OCTimingUni(0, 0, 2), // sdram,uni: 10+2*w cycles for each w-word access
new OCTimingUni(0, 10, 2), // SRAM, cmp, 2 cycles word load cost, s=2
new OCTimingCmp(8, 1, 0, 0, 2), // SDRAM, cmp, 18 cycles quadword load cost, s=18
new OCTimingCmp(8, 4, 0, 10, 2) };
OCacheMode[] modes = { OCacheMode.BLOCK_FILL, OCacheMode.SINGLE_FIELD };
List<OCacheAnalysisResult> samples = new ArrayList<OCacheAnalysisResult>();
// need to be in ascending order
int[] cacheWays = { 0, 2, 4, 8, 16, 32, 64, 512 };
int[] lineSizesObjCache = { 4, 8, 16, 32 };
int[] lineSizesFieldCache = { 1 };
int[] blockSizesObjCache = { 1, 2, 4, 8, 16 };
int[] lineSizes;
for (int configId = 0; configId < configs.length; configId++) {
ObjectCacheTiming ocConfig = configs[configId];
oStream.println("---------------------------------------------------------");
oStream.println("Object Cache Configuration: " + ocConfig);
oStream.println("---------------------------------------------------------");
for (OCacheMode mode : modes) {
long maxCost = 0;
// long cacheMisses = Long.MAX_VALUE;
String modeString;
lineSizes = lineSizesObjCache;
if (mode == OCacheMode.BLOCK_FILL)
modeString = "fill-block";
else {
modeString = "field-as-tag";
lineSizes = lineSizesFieldCache;
}
boolean first = true;
for (int lineSize : lineSizes) {
for (int blockSize : blockSizesObjCache) {
if (blockSize > lineSize)
continue;
if (mode == OCacheMode.BLOCK_FILL) {
} else {
if (blockSize > 1)
continue;
}
/* Configure object cache timing */
/* We have to take field access count of cache size = 0; our analysis otherwise does not assign
* sensible field access counts (thats the fault of the IPET method)
*/
long totalFieldAccesses = -1, cachedFieldAccesses = -1;
double bestCyclesPerAccessForConfig = Double.POSITIVE_INFINITY;
double bestHitRate = 0.0;
long bestCostPerConfig = Long.MAX_VALUE;
// assume cacheSizes are in ascending order
for (int ways : cacheWays) {
ocConfig.setObjectCacheTiming(objectCache, blockSize);
if (mode == OCacheMode.SINGLE_FIELD) {
objectCache = ObjectCache.createFieldCache(project, ways, 0, 0, 0);
} else {
objectCache = new ObjectCache(project, ways, blockSize, lineSize, 0, 0, 0);
}
ocConfig.setObjectCacheTiming(objectCache, blockSize);
oca = new ObjectCacheAnalysisDemo(project, objectCache);
double cyclesPerAccess, hitRate;
ObjectCache.ObjectCacheCost ocCost = oca.computeCost();
long cost = ocCost.getCost();
if (cost < bestCostPerConfig)
bestCostPerConfig = cost;
double bestRatio, ratio;
if (ways == 0) {
maxCost = cost;
totalFieldAccesses = ocCost.getTotalFieldAccesses();
cachedFieldAccesses = ocCost.getFieldAccessesWithoutBypass();
bestRatio = 1.0;
ratio = 1.0;
} else {
bestRatio = (double) bestCostPerConfig / (double) maxCost;
ratio = (double) cost / (double) maxCost;
}
cyclesPerAccess = (double) cost / (double) totalFieldAccesses;
if (cyclesPerAccess < bestCyclesPerAccessForConfig || ways <= 1) {
bestCyclesPerAccessForConfig = cyclesPerAccess;
}
/* hit rate is defined as: 1 - ((cache misses+accesses to bypassed fields) / total field accesses (with n=0) */
long missAccesses = ocCost.getCacheMissCount() + ocCost.getBypassCount();
hitRate = (1 - ((double) missAccesses / (double) totalFieldAccesses));
if (hitRate > bestHitRate || ways <= 1) {
bestHitRate = hitRate;
}
if (first) {
oStream.println(String.format("***** ***** MODE = %s ***** *****\n", modeString));
oStream.println(String.format(" - max tags accessed (upper bound) = %d, max fields accesses = %d", oca.getMaxAccessedTags(targetMethod, CallString.EMPTY), totalFieldAccesses));
first = false;
}
String report = //, %.2f %% 'hitrate')",
String.format(//, %.2f %% 'hitrate')",
" + Cycles Per Access [N=%3d,l=%2d,b=%2d]: %.2f (%d total cost, %.2f %% cost of no cache, %d bypass cost)", ways, lineSize, blockSize, bestCyclesPerAccessForConfig, cost, bestRatio * 100, ocCost.getBypassCost());
if (bestCostPerConfig > cost) {
report += String.format(" # (analysis cost increased by %.2f %% for this associativity)", ratio * 100);
}
oStream.println(report);
if (mode != OCacheMode.SINGLE_FIELD) {
OCacheAnalysisResult sample = new ObjectCacheEvaluationResult.OCacheAnalysisResult(ways, lineSize, blockSize, configId, bestHitRate, bestCyclesPerAccessForConfig, ocCost);
samples.add(sample);
}
}
}
}
}
}
OCacheAnalysisResult.dumpBarPlot(samples, oStream);
OCacheAnalysisResult.dumpPlot(samples, oStream);
OCacheAnalysisResult.dumpLatex(samples, oStream);
}
Aggregations