summaryrefslogtreecommitdiffstats
path: root/zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java
diff options
context:
space:
mode:
Diffstat (limited to 'zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java')
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/FileTracer.java285
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;
+ }
+}
OpenPOWER on IntegriCloud