/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2011, Benedikt Huber (benedikt@vmars.tuwien.ac.at) 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.jop; import com.jopdesign.common.config.OptionGroup; import com.jopdesign.common.processormodel.JOPConfig; import com.jopdesign.timing.jop.JOPTimingTable; import com.jopdesign.wcet.WCETTool; import com.jopdesign.wcet.analysis.cache.ObjectCacheAnalysis.ObjectCacheCostModel; /** * Purpose: * */ public class ObjectCache implements CacheModel { public static class ObjectCacheCost { private long missCost; private long bypassCost; private long fieldAccesses; private long bypassCount; private long missCount; /** * @param missCost * @param bypassCost * @param fieldAccesses */ public ObjectCacheCost(long missCount, long missCost, long bypassAccesses, long bypassCost, long fieldAccesses) { this.missCost = missCost; this.bypassCost = bypassCost; this.fieldAccesses = fieldAccesses; this.missCount = missCount; this.bypassCount = bypassAccesses; } public ObjectCacheCost() { this(0,0,0,0,0); } public long getCost() { return missCost + bypassCost; } public long getBypassCost() { return bypassCost; } public long getBypassCount() { return this.bypassCount; } public void addBypassCost(long bypassCost, int accesses) { this.bypassCost += bypassCost; this.bypassCount += accesses; } public ObjectCacheCost addMissCost(long missCost, int missCount) { this.missCost += missCost; this.missCount += missCount; return this; } /* addition field accesses either hit or miss (but not bypass) */ public void addAccessToCachedField(long additionalFAs) { fieldAccesses += additionalFAs; } public long getTotalFieldAccesses() { return bypassCount + fieldAccesses; } public long getFieldAccessesWithoutBypass() { return fieldAccesses; } /* cache miss count */ public long getCacheMissCount() { return missCount; } public void addCost(ObjectCacheCost occ) { this.missCount += occ.missCount; this.missCost += occ.missCost; this.bypassCount += occ.bypassCount; this.bypassCost += occ.bypassCost; addAccessToCachedField(occ.fieldAccesses); } @Override public String toString() { return String.format("missCycles = %d [miss-cost=%d, bypass-cost = %d, relevant-accesses=%d]",getCost(),this.missCost,this.bypassCost,this.fieldAccesses); } public ObjectCacheCost times(Long value) { return new ObjectCacheCost(missCount * value, missCost * value, bypassCount * value, bypassCost * value, fieldAccesses * value); } } private int associativity; private int blockSize; private boolean fieldAsTag; private int lineSize; private long hitCycles; private long loadFieldCycles; private long loadBlockCycles; /** * @param p * @param timing */ public ObjectCache(WCETTool p, JOPTimingTable timing) { OptionGroup options = JOPConfig.getOptions(p.getConfig()); this.associativity = options.getOption(JOPConfig.OBJECT_CACHE_ASSOCIATIVITY).intValue(); this.blockSize = options.getOption(JOPConfig.OBJECT_CACHE_BLOCK_SIZE).intValue(); this.fieldAsTag = false; this.lineSize = options.getOption(JOPConfig.OBJECT_CACHE_WORDS_PER_LINE).intValue(); this.hitCycles = options.getOption(JOPConfig.OBJECT_CACHE_HIT_CYCLES); this.loadFieldCycles = options.getOption(JOPConfig.OBJECT_CACHE_LOAD_FIELD_CYCLES); this.loadBlockCycles = options.getOption(JOPConfig.OBJECT_CACHE_LOAD_BLOCK_CYCLES); } public ObjectCache(WCETTool p, int associativity, int blockSize, int lineSize, long hitCycles, long loadFieldCycles, long loadBlockCycles) { this.associativity = associativity; this.blockSize = blockSize; this.fieldAsTag = false; this.lineSize = lineSize; this.hitCycles = hitCycles; this.loadFieldCycles = loadFieldCycles; this.loadBlockCycles = loadFieldCycles; } public static ObjectCache createFieldCache(WCETTool p, int ways, long hitCycles, long loadFieldCycles, long loadBlockCycles) { ObjectCache oc = new ObjectCache(p, ways, 1, 1, hitCycles, loadFieldCycles, loadBlockCycles); oc.fieldAsTag = true; return oc; } /* (non-Javadoc) * @see com.jopdesign.wcet.jop.CacheModel#getSizeInWords() */ @Override public long getSizeInWords() { /* TODO: take metadata into account */ if(fieldAsTag) return associativity; return lineSize * associativity; } /** * @return */ public int getMaxCachedFieldIndex() { if(fieldAsTag) return Integer.MAX_VALUE; return lineSize - 1; } public boolean isFieldCache() { return fieldAsTag; } public int getAssociativity() { return this.associativity; } public int getLineSize() { return lineSize; } public int getBlockSize() { return blockSize; } public int getBlocksPerLine() { return lineSize / blockSize; } public long getHitCycles() { return hitCycles; } public long getLoadBlockCycles() { return this.loadBlockCycles; } public long getBypassTime() { return this.loadFieldCycles; } /* preliminary cost model */ public ObjectCacheCostModel getCostModel() { return new ObjectCacheCostModel( Math.max(0, getLoadBlockCycles() - getHitCycles()), 0, Math.max(0, getBypassTime() - getHitCycles())); } /* for evaluation purposes only */ public void setHitCycles(long hitCycles) { this.hitCycles = hitCycles; } public void setLoadFieldCycles(long loadFieldCycles) { this.loadFieldCycles = loadFieldCycles; } public void setLoadBlockCycles(long loadBlockCycles) { this.loadBlockCycles = loadBlockCycles; } @Override public String toString() { if(this.isFieldCache()) { return "f$-N"+getAssociativity(); } else { return "o$-N"+getAssociativity()+"-"+getBlocksPerLine()+"x"+getBlockSize(); } } /* Removed for now, as is not flexible enough */ // public long getAccessTime(int words) { // int burstLength = this.MaxBurst; // long delay = this.AccessDelay; // long cyclesPerWord = this.CyclesPerWord; // int fullBursts = words / burstLength; // int lastBurst = words % burstLength; // long accessTime = delay + cyclesPerWord * lastBurst; // for(int i = 0; i < fullBursts; i++) { // accessTime += delay + cyclesPerWord * burstLength; // } // return accessTime; // } }