diff options
Diffstat (limited to 'zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java')
-rw-r--r-- | zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java b/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java new file mode 100644 index 0000000..6ccca24 --- /dev/null +++ b/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java @@ -0,0 +1,285 @@ + +package com.zylin.zpu.simulator; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.LineNumberReader; + +import com.zylin.zpu.simulator.exceptions.CPUException; +import com.zylin.zpu.simulator.exceptions.GDBServerException; +import com.zylin.zpu.simulator.exceptions.TraceException; + +public class FileTracer implements Tracer +{ + private LineNumberReader file; + private boolean trigger; + private boolean resync; + private Simulator simulator; + private String line; + private boolean ignore; + + static class Trace + { + int pc; + int opcode; + int sp; + int stackA; + int stackB; + int intSp; + long cycle; + public boolean undefinedStackA; + public boolean undefinedStackB; + public boolean undefinedIntSp; + public void print() + { + System.err.println(Integer.toHexString(pc)+ " " + + Integer.toHexString(opcode) + " " + + Integer.toHexString(sp) + " " + + Integer.toHexString(stackA) + " " + + Integer.toHexString(stackB) + " " + + intSp + " " + + cycle); + + } + }; + private Trace[] trace= new Trace[100]; + private int current; + private String fileName; + private boolean metEnd; + + + public FileTracer(Simulator sim, String string) + { + simulator=sim; + fileName=string; + + resync=true; + + + for (int i=0; i<trace.length; i++) + { + trace[i]=new Trace(); + } + findNextTrigger(); + } + + LineNumberReader getFile() + { + if (file==null) + { + try + { + file=new LineNumberReader(new java.io.FileReader(fileName)); + } catch (FileNotFoundException e) + { + throw new RuntimeException(e); + } + } + return file; + } + + + private void findNextTrigger() throws TraceException + { + trigger=false; + try + { + for (;;) + { + line=getFile().readLine(); + if (line==null) + { + metEnd=true; + System.err.println("================== End of trace file ======================"); + break; + } + if (line.matches("^\\s*\\#.*$")) + { + /* this was a comment*/ + continue; + } + if (line.matches("^\\s*$")) + { + /* all whitespace */ + continue; + } + String[] val=line.split(" "); + + try + { + Trace t=trace[current]; + t.pc=(int) parseInt(val[0]); + t.opcode=(int) parseInt(val[1]); + t.sp=(int) parseInt(val[2]); + try + { + t.undefinedStackA=false; + t.stackA=(int) parseInt(val[3]); + } catch (NumberFormatException e) + { + t.undefinedStackA=true; + t.stackB=0; + } + + try + { + t.undefinedStackB=false; + t.stackB=(int) parseInt(val[4]); + } catch (NumberFormatException e) + { + t.undefinedStackB=true; + t.stackB=0; + } + try + { + t.undefinedIntSp=false; + t.intSp=(int) parseInt(val[5]); + } catch (NumberFormatException e) + { + t.undefinedIntSp=true; + t.intSp=0; + } + t.cycle=parseInt(val[6]); + trigger=true; + break; + } catch (NumberFormatException e) + { + /* skip this line. */ + e.printStackTrace(); + } + } + } catch (IOException e) + { + throw new TraceException(e); + } + + } + + private long parseInt(String string2) throws TraceException + { + String string = string2; + if (!string.startsWith("0x")) + { + throw new TraceException(new Exception("Trace file pasing error line " + getFile().getLineNumber())); + } + return Long.parseLong(string.substring(2), 16); + } + + public void instructionEvent() throws GDBServerException + { + if (metEnd) + { + metEnd=false; + throw new TraceException(); + } + if (resync&&trigger) + { + if (match()) + { + /* we have to wait for the first instruction in the trace to be matched */ + System.out.println("First matching instruction found!"); + resync=false; + } + } + + if (!resync&&trigger) + { + + boolean m=match(); + recordCurrent(); + current=(current+1)%trace.length; + + if (!m) + { + System.err.println("Trace file mismatch"); + dumpTraceBack(); + System.err.print("Expected by Java simulator: \n"); + simulator.printState(this); + System.err.print("Actual from ModelSim: "); + System.err.println(line); + // we now have to ignore this match. + ignore=true; + throw new TraceException(); + } + } else + { + recordCurrent(); + current=(current+1)%trace.length; + } + } + + public void dumpTraceBack() + { + System.err.println("Expected"); + System.err.println("PC SP topOfStack"); + for (int i=0; i<trace.length; i++) + { + trace[(i+current)%trace.length].print(); + } + } + + private void recordCurrent() + { + recordState(trace[current]); + } + + private void recordState(Trace trace3) + { + trace3.pc=simulator.getPc(); + trace3.sp=simulator.getSp(); + trace3.opcode=simulator.getOpcode(); + try + { + trace3.stackA=simulator.cpuReadLong(simulator.getSp()); + trace3.stackB=simulator.cpuReadLong(simulator.getSp()+4); + trace3.intSp=simulator.getIntSp(); + // trace[current].cycle=expectetdCycle(); + } catch (CPUException e1) + { + e1.printStackTrace(); + } + } + + + + boolean match() throws GDBServerException + { + if (ignore) + return true; + + return simulator.checkMatch(trace[current]); + } + + public void commit() + { + try + { + if (!resync&&trigger) + { + ignore=false; + findNextTrigger(); + } + } + catch (Throwable e) + { + e.printStackTrace(); + } + } + + public void setSp(int sp) + { + } + + public boolean onInterrupt() + { + if (trace[current].pc==0x20) + return true; + else + return false; + } + + public boolean simInterrupt() + { + return true; + } +} |