package com.jopdesign.timing.jop;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import com.jopdesign.timing.ConsoleTable;
import com.jopdesign.timing.ConsoleTable.Alignment;
import com.jopdesign.timing.ConsoleTable.TableRow;
import com.jopdesign.tools.JopInstr;
/**
* Chip multiprocessing timing.
* Currently delegates to {link com.jopdesign.timing.WCETInstruction}
* FIXME: Create a microcode analysis based class in com.jopdesign.timing.jop.MultiCoreTiming
*/
public class JOPCmpTimingTable extends JOPTimingTable {
public static JOPCmpTimingTable getCmpTimingTable(
File asmFile, int rws, int wws, int cpus, int timeslot) throws IOException {
MicropathTable mpt = MicropathTable.getTimingTableFromAsmFile(asmFile);
return new JOPCmpTimingTable(mpt, cpus, timeslot, rws, wws);
}
private WCETInstruction instTimingInfo;
private int cpus;
private int timeslot;
protected JOPCmpTimingTable(MicropathTable mpt, int cpus, int timeslot, int rws, int wws) {
super(mpt);
instTimingInfo = new WCETInstruction(cpus, timeslot, rws, wws);
}
@Override
public void configureWaitStates(int rws, int wws) {
configure(cpus, timeslot, rws, wws);
}
/**
* @param cpus number of CPUs
* @param timeslot timeslot length
* @param rws read wait states (r)
* @param wws write wait states (w)
*/
public void configure(int cpus, int timeslot, int rws, int wws) {
super.configureWaitStates(rws, wws);
this.cpus = cpus;
this.timeslot = timeslot;
instTimingInfo.configureCMP(cpus, timeslot, rws, wws);
}
@Override
protected long getCycles(int opcode, boolean isHit, int methodLoadWords) {
long cycles = instTimingInfo.getCycles(opcode, ! isHit, methodLoadWords);
if(JopInstr.isInJava(opcode)) {
cycles = instTimingInfo.getCycles(org.apache.bcel.Constants.INVOKESTATIC, ! isHit, methodLoadWords);
}
return cycles;
}
// should be inherited, but currently we delegate to the old impl,
// so fewer bytecodes are supported
@Override
public boolean hasTimingInfo(int opcode) {
if(! super.hasTimingInfo(opcode)) return false;
return getCycles(opcode,false,32) != WCETInstruction.WCETNOTAVAILABLE;
}
/* TODO: improve WCET by taking basic blocks into account */
// @Override
// public long getCycles(List<Instruction> opcodes) {
// }
public static void main(String argv[]) {
String head = "JOP CMP Timing Table on " + new Date();
System.out.println(head);
System.out.println(ConsoleTable.getSepLine('=',head.length()));
System.out.println();
System.out.println(" Loading " + MicrocodeAnalysis.DEFAULT_ASM_FILE);
System.out.println(" Before generating the timing table do not forget to run e.g.");
System.out.println(" > make gen_mem -e ASM_SRC=jvm JVM_TYPE=USB\n");
JOPCmpTimingTable tt = null;
try {
tt = JOPCmpTimingTable.getCmpTimingTable(MicrocodeAnalysis.DEFAULT_ASM_FILE,3,5,3,15);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
// build table
ConsoleTable table = dumpCmpTimingTable(tt);
System.out.println(table.render());
}
// TODO: there is some duplication with JOPTimingTable (naturally),
// but too lazy now to extract common stuff.
private static ConsoleTable dumpCmpTimingTable(JOPCmpTimingTable tt) {
// r w cpus timeslot
int conf1[] = { 1, 2, 3, 4 };
int conf2[] = { 1, 2, 3, 5 };
int conf3[] = { 1, 2, 3, 6 };
int conf4[] = { 1, 2, 3, 7 };
int[][] cmpTestConfig = { conf1, conf2, conf3, conf4 };
ConsoleTable table = new ConsoleTable();
table.addColumn("opcode", Alignment.ALIGN_RIGHT)
.addColumn("name", Alignment.ALIGN_LEFT);
for(int[] conf : cmpTestConfig) {
table.addColumn(String.format("(%d,%d,%d,%d)",conf[0],conf[1],conf[2],conf[3]),Alignment.ALIGN_RIGHT);
}
for(int i = 0; i < 256; i++) {
int opcode = i;
if(JopInstr.isReserved(opcode)) continue;
TableRow row = table.addRow();
row.addCell(opcode)
.addCell(JopInstr.OPCODE_NAMES[i]);
if(! tt.hasTimingInfo(opcode)) {
row.addCell("... not supported ...",cmpTestConfig.length,Alignment.ALIGN_LEFT);
} else {
for(int[] conf : cmpTestConfig) {
tt.configure(conf[2], conf[3], conf[0], conf[1]);
long timingHit = tt.getCycles(opcode, true, 0);
long timingMiss1 = tt.getCycles(opcode, false, 1);
long timingMiss2 = tt.getCycles(opcode, false, 2);
long timingMiss32 = tt.getCycles(opcode, false, 32);
if(timingHit == timingMiss32) {
row.addCell(timingHit);
} else {
row.addCell(timingHit + " / " + timingMiss32);
}
}
}
}
table.addLegendTop(" (x,y,c,t) ~ (read delay, write delay, cpus, timeslot)");
table.addLegendTop(" c1 / c2 ... cycles cache hit / cycles cache miss 32 words");
table.addLegendTop(" infeasible branches: "+Arrays.toString(MicrocodeAnalysis.INFEASIBLE_BRANCHES));
// table.addLegendBottom(String.format(" hidden cycles on invoke (including JavaImplBCs) and return: %d / %d",
// tt.minCyclesHiddenOnInvoke,tt.minCyclesHiddenOnReturn));
return table;
}
}