/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2009, 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.timing.jop;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
import com.jopdesign.timing.InstructionInfo;
import com.jopdesign.timing.MethodCacheTiming;
import com.jopdesign.timing.TimingTable;
import com.jopdesign.timing.jop.MicrocodeAnalysis.MicrocodeVerificationException;
/** Microcode Timing Table
* Before generating the timing table do not forget to run e.g.
* {@code make gen_mem -e ASM_SRC=jvm JVM_TYPE=USB @}
*/
public abstract class JOPTimingTable extends TimingTable<JOPInstructionInfo> implements MethodCacheTiming {
protected MicropathTable micropathTable;
protected HashSet<Short> bytecodeAccessInstructions = new HashSet<Short>();
protected int readWaitStates;
protected int writeWaitStates;
protected TreeMap<Integer, MicrocodeVerificationException> analysisErrors;
// custom timings for experiments
public Map<Integer,Long> customTiming = new HashMap<Integer,Long>();
protected JOPTimingTable(MicropathTable mpt) {
this.micropathTable = mpt;
analysisErrors = new TreeMap<Integer,MicrocodeVerificationException>(mpt.getAnalysisErrors());
this.readWaitStates = this.writeWaitStates = -1; // not configured
for(short i = 0; i < 256; i++) {
if(mpt.hasTiming(i) && mpt.hasBytecodeLoad(i)) {
this.bytecodeAccessInstructions.add(i);
}
}
}
/** Override timing for certain instructions (for experiments) */
public void setCustomTiming(int opcode, long l) {
this.customTiming.put(opcode, l);
}
@Override
public long getCycles(JOPInstructionInfo instrInfo) {
// see whether a custom timing is configured for this opcode
if(customTiming.containsKey(instrInfo.getOpcode())) {
return customTiming.get(instrInfo.getOpcode());
}
return getCycles(instrInfo.getOpcode(), instrInfo.hit, instrInfo.wordsLoaded);
}
public long getLocalCycles(int opcode) {
// see whether a custom timing is configured for this opcode
if(customTiming.containsKey(opcode)) {
return customTiming.get(opcode);
}
return getCycles(opcode, false, 0);
}
protected abstract long getCycles(int opcode, boolean isHit, int words);
public MicrocodeVerificationException getAnalysisError(int opcode) {
return analysisErrors.get(opcode);
}
public boolean isImplemented(int opcode) {
return micropathTable.hasMicrocodeImpl(opcode);
}
@Override
public boolean hasTimingInfo(int opcode) {
if(customTiming.containsKey(opcode)) return true;
return micropathTable.hasTiming(opcode);
}
public void configureWaitStates(int r, int w) {
this.readWaitStates = r;
this.writeWaitStates = w;
}
public boolean hasBytecodeLoad(short opcode) {
for(MicrocodePath path: micropathTable.getMicroPaths(opcode)) {
if(path.hasBytecodeLoad()) return true;
}
return false;
}
protected static boolean hasBytecodeLoad(Vector<MicropathTiming> timings) {
for(MicropathTiming ptime : timings) {
if(ptime.hasBytecodeLoad()) return true;
}
return false;
}
/*
* (non-Javadoc)
* @see com.jopdesign.timing.MethodCacheTiming#getMethodCacheMissPenalty(int, boolean)
*/
@Override
public long getMethodCacheMissPenalty(int words, boolean loadOnInvoke) {
long maxDiff = Long.MIN_VALUE;
for(short opcode : bytecodeAccessInstructions) {
if(loadOnInvoke && InstructionInfo.isReturnOpcode(opcode)) continue;
long diff = getMethodCacheMissPenalty(words, opcode);
maxDiff = Math.max(diff, maxDiff);
}
return maxDiff;
}
/* (non-Javadoc)
* @see com.jopdesign.timing.MethodCacheTiming#getMethodCacheMissPenalty(int, short)
*/
@Override
public long getMethodCacheMissPenalty(int words, short opcode) {
long onHit = getCycles(opcode,true,words);
long onMiss = getCycles(opcode,false,words);
long diff = onMiss - onHit;
if(diff < 0) throw new AssertionError("Miss is cheaper than hit ? - Not on JOP !");
return diff;
}
}