use of com.jopdesign.dfa.analyses.SymbolicAddress in project jop by jop-devel.
the class ObjectCacheAnalysis method getSaturatedTypes.
/** Traverse vertex set. Collect those types where we could not resolve
* the symbolic object names. (Not too useful in the analysis, but useful
* for debugging)
*/
public HashSet<String> getSaturatedTypes(Segment segment, LocalPointsToResult usedRefs) {
HashSet<String> topTypes = new HashSet<String>();
for (SuperGraphNode n : segment.getNodes()) {
BasicBlock bb = n.getCFGNode().getBasicBlock();
if (bb == null)
continue;
CallString cs = n.getContextCFG().getCallString();
for (InstructionHandle ih : bb.getInstructions()) {
BoundedSet<SymbolicAddress> refs;
if (usedRefs.containsKey(ih)) {
refs = usedRefs.get(ih, cs);
String handleType = getHandleType(project, n.getCfg(), ih);
if (handleType == null)
continue;
if (refs.isSaturated()) {
topTypes.add(handleType);
}
}
}
}
return topTypes;
}
use of com.jopdesign.dfa.analyses.SymbolicAddress in project jop by jop-devel.
the class ObjectCacheAnalysis method getMaxCacheCost.
/**
* Get maximum cost due to the object cache in the given scope.
* Using special cost models such as COUNT_FIELD_TAGS and COUNT_REF_TAGS, this
* method can be used to calculate different metrics as well.
* <p> XXX: Use segment instead of scope </p>
* @param scope
* @param costModel The object cache cost model
* @return
* @throws InvalidFlowFactException
* @throws LpSolveException
*/
public ObjectCacheCost getMaxCacheCost(ExecutionContext scope, ObjectCacheCostModel costModel) throws InvalidFlowFactException, LpSolveException {
LocalPointsToResult usedRefs = getUsedRefs(scope);
Segment segment = Segment.methodSegment(scope.getMethodInfo(), scope.getCallString(), project, project.getCallstringLength(), project);
/* Compute worst-case cost */
HashSet<SymbolicAddress> usedObjectsSet = new HashSet<SymbolicAddress>();
return computeCacheCost(segment, usedRefs, costModel, usedObjectsSet);
}
use of com.jopdesign.dfa.analyses.SymbolicAddress 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);
}
use of com.jopdesign.dfa.analyses.SymbolicAddress in project jop by jop-devel.
the class ObjectCacheAnalysis method addMissOnceCost.
/**
* Add miss once cost: for each method cache persistence segment, add maximum miss cost to the segment entries
* @param segment
* @param ipetSolver
* @param checks
* @throws LpSolveException
* @throws InvalidFlowFactException
*/
@Override
public Set<SuperGraphEdge> addMissOnceCost(Segment segment, IPETSolver<SuperGraphEdge> ipetSolver, EnumSet<PersistenceCheck> checks) throws InvalidFlowFactException, LpSolveException {
Set<SuperGraphEdge> missCostEdges = new HashSet<SuperGraphEdge>();
Set<SuperGraphNode> alwaysMissNodes = new HashSet<SuperGraphNode>();
Collection<Segment> cover = findPersistenceSegmentCover(segment, EnumSet.allOf(PersistenceCheck.class), false, alwaysMissNodes);
int tag = 0;
for (Segment persistenceSegment : cover) {
tag++;
/* Compute cost for persistence segment */
HashSet<SymbolicAddress> usedSetOut = new HashSet<SymbolicAddress>();
ObjectCacheCost cost = computeCacheCost(persistenceSegment, getUsedRefs(persistenceSegment), objectCache.getCostModel(), usedSetOut);
WCETTool.logger.info("O$-addMissOnceCost: " + cost.toString());
F1<SuperGraphEdge, Long> costModel = MiscUtils.const1(cost.getCost());
Set<SuperGraphEdge> costEdges = addFixedCostEdges(persistenceSegment.getEntryEdges(), ipetSolver, costModel, KEY + "_miss_once", tag);
missCostEdges.addAll(costEdges);
}
AccessCostInfo alwaysMissAccessInfo = extractAccessesAndCosts(alwaysMissNodes, null, objectCache.getCostModel());
missCostEdges.addAll(addStaticCost(segment, alwaysMissAccessInfo, ipetSolver));
return missCostEdges;
}
use of com.jopdesign.dfa.analyses.SymbolicAddress in project jop by jop-devel.
the class ObjectCacheAnalysis method extractAccessesAndCosts.
/** Traverse vertex set.
* <p>Add vertex to access set of referenced addresses
* For references whose type cannot be fully resolved, add a
* cost of 1.</p>
* <p>FIXME: We should deal with subtyping (or better use storage based alias-analysis)</p>
*
* @param nodes
* @param usedRefs the results of the local points-to analysis, or {@code null} for always miss costs
* @param costModel
*/
private AccessCostInfo extractAccessesAndCosts(Iterable<SuperGraphNode> nodes, LocalPointsToResult usedRefs, ObjectCacheCostModel costModel) {
AccessCostInfo aci = new AccessCostInfo();
for (SuperGraphNode node : nodes) {
/* Compute cost for basic block */
BasicBlock bb = node.getCFGNode().getBasicBlock();
if (bb == null)
continue;
long bypassCost = 0;
long alwaysMissCost = 0;
CallString cs = node.getContextCFG().getCallString();
for (InstructionHandle ih : bb.getInstructions()) {
String handleType = getHandleType(project, node.getCfg(), ih);
if (handleType == null)
continue;
/* No getfield/handle access */
int fieldIndex = getFieldIndex(project, node.getCfg(), ih);
int blockIndex = getBlockIndex(fieldIndex);
if (fieldIndex > this.maxCachedFieldIndex) {
bypassCost += costModel.getFieldAccessCostBypass();
continue;
}
BoundedSet<SymbolicAddress> refs = null;
if (usedRefs != null) {
if (!usedRefs.containsKey(ih)) {
usedRefs = null;
WCETTool.logger.error("No DFA results for: " + ih.getInstruction() + " with field " + ((FieldInstruction) ih.getInstruction()).getFieldName(bb.cpg()));
} else {
refs = usedRefs.get(ih, cs);
if (refs.isSaturated())
refs = null;
}
}
if (refs == null) {
alwaysMissCost += costModel.getReplaceLineCost() + costModel.getLoadCacheBlockCost();
} else {
for (SymbolicAddress ref : refs.getSet()) {
aci.addRefAccess(ref, node);
aci.addBlockAccess(ref.accessArray(blockIndex), node);
// Handle getfield_long / getfield_double
if (getCachedType(project, node.getCfg(), ih) == Type.LONG || getCachedType(project, node.getCfg(), ih) == Type.DOUBLE) {
if (blockIndex + 1 > this.maxCachedFieldIndex) {
bypassCost += costModel.getFieldAccessCostBypass();
} else {
aci.addBlockAccess(ref.accessArray(blockIndex + 1), node);
}
}
}
}
}
aci.putBypassCost(node, bypassCost);
aci.putStaticCost(node, bypassCost + alwaysMissCost);
}
return aci;
}
Aggregations