added profiling of events and added event system

git-svn-id: https://mspsim.svn.sourceforge.net/svnroot/mspsim/mspsim@451 23d1a52b-0c3c-0410-b72d-8f29ab48fe35
This commit is contained in:
joxe 2009-01-20 11:37:32 +00:00
parent 0ba734ffcb
commit b5da4d2acf
10 changed files with 186 additions and 14 deletions

View File

@ -45,6 +45,7 @@ Run the default example on the Sky node emulator by typing:
- Emulates some external hardware such as TR1001 and CC2420.
- Command Line Interface, CLI, for setting up breakpoints and output
to files or windows.
- GDB remote debugging support (initial)
* What is emulated of the MSP430
- CPU (instruction level simulation)

View File

@ -628,10 +628,13 @@ public class CC2420 extends Chip implements USARTListener, RFListener {
if(txfifoFlush) {
txCursor = 0;
txfifoFlush = false;
}
}
if (DEBUG) log("Writing data: " + data + " to tx: " + txCursor);
memory[RAM_TXFIFO + txCursor++] = data & 0xff;
if (sendEvents) {
sendEvent("WRITE_TXFIFO", null);
}
break;
case RAM_ACCESS:
if (pos == 0) {
@ -707,6 +710,9 @@ public class CC2420 extends Chip implements USARTListener, RFListener {
(stateMachine == RadioState.RX_WAIT)) {
status |= STATUS_TX_ACTIVE;
setState(RadioState.TX_CALIBRATE);
if (sendEvents) {
sendEvent("STXON", null);
}
// Starting up TX subsystem - indicate that we are in TX mode!
if (DEBUG) log("Strobe STXON - transmit on! at " + cpu.cycles);
}
@ -719,6 +725,11 @@ public class CC2420 extends Chip implements USARTListener, RFListener {
(stateMachine == RadioState.RX_FRAME) ||
(stateMachine == RadioState.RX_OVERFLOW) ||
(stateMachine == RadioState.RX_WAIT)) {
if (sendEvents) {
sendEvent("STXON_CCA", null);
}
if(cca) {
status |= STATUS_TX_ACTIVE;
setState(RadioState.TX_CALIBRATE);

View File

@ -39,9 +39,13 @@
*/
package se.sics.mspsim.cli;
import se.sics.mspsim.core.Chip;
import se.sics.mspsim.core.EventListener;
import se.sics.mspsim.core.EventSource;
import se.sics.mspsim.core.MSP430;
import se.sics.mspsim.core.Profiler;
import se.sics.mspsim.util.ComponentRegistry;
import se.sics.mspsim.util.SimpleProfiler;
/**
*
@ -105,6 +109,56 @@ public class ProfilerCommands implements CommandBundle {
}
});
ch.registerCommand("logevents", new BasicAsyncCommand("log events", "") {
Chip chip;
public int executeCommand(CommandContext context) {
chip = cpu.getChip(context.getArgument(0));
if (chip == null) {
context.err.println("Can not find chip: " + context.getArgument(0));
}
chip.setEventListener(new EventListener() {
public void event(EventSource source, String event, Object data) {
System.out.println("Event:" + source.getName() + ":" + event);
}
});
return 0;
}
public void stopCommand(CommandContext context) {
chip.setEventListener(null);
}
});
ch.registerCommand("tagprof", new BasicCommand("profile between two events", "") {
public int executeCommand(CommandContext context) {
String event1 = context.getArgument(0);
String event2 = context.getArgument(1);
String chip1[] = event1.split("\\.");
String chip2[] = event2.split("\\.");
Chip chipE1 = cpu.getChip(chip1[0]);
if (chipE1 == null) {
context.err.println("Can not find chip: " + chip1[0]);
}
Chip chipE2 = cpu.getChip(chip2[0]);
if (chipE2 == null) {
context.err.println("Can not find chip: " + chip2[0]);
}
Profiler profiler = cpu.getProfiler();
SimpleProfiler sprof = (SimpleProfiler) profiler;
sprof.addProfileTag(context.getArgument(2), chipE1, chip1[1],
chipE2, chip2[1]);
return 0;
}
});
ch.registerCommand("printtags", new BasicCommand("print tags profile", "") {
public int executeCommand(CommandContext context) {
Profiler profiler = cpu.getProfiler();
SimpleProfiler sprof = (SimpleProfiler) profiler;
sprof.printTagProfile(context.out);
return 0;
}
});
ch.registerCommand("logcalls", new BasicAsyncCommand("log function calls", "") {

View File

@ -47,9 +47,11 @@ import se.sics.mspsim.util.Utils;
* @author Joakim
*
*/
public abstract class Chip implements Loggable {
public abstract class Chip implements Loggable, EventSource {
private OperatingModeListener[] omListeners;
private EventListener eventListener;
protected boolean sendEvents = false;
private String[] modeNames = null;
private int mode;
private PrintStream log;
@ -83,6 +85,18 @@ public abstract class Chip implements Loggable {
modeNames = names;
}
public void setEventListener(EventListener e) {
eventListener = e;
sendEvents = true;
}
protected void sendEvent(String event, Object data) {
if (eventListener != null) {
eventListener.event(this, event, data);
}
}
public String getModeName(int index) {
if (modeNames == null) {
return null;

View File

@ -0,0 +1,5 @@
package se.sics.mspsim.core;
public interface EventListener {
public void event(EventSource source, String event, Object data);
}

View File

@ -0,0 +1,5 @@
package se.sics.mspsim.core;
public interface EventSource {
public String getName();
}

View File

@ -53,11 +53,6 @@ public abstract class IOUnit implements InterruptHandler {
public void reset(int type) {
}
// Should return the cycle it wants the next tick...
public long ioTick(long cycles) {
return cycles + 1000000;
}
// write
// write a value to the IO unit

View File

@ -329,6 +329,7 @@ public class MSP430 extends MSP430Core {
/* When we got the map table we can also profile! */
if (profiler == null) {
this.profiler = new SimpleProfiler();
this.profiler.setCPU(this);
}
}

View File

@ -80,10 +80,6 @@ public class Multiplier extends IOUnit {
this.core = core;
}
public boolean needsTick() {
return false;
}
public int read(int address, boolean word, long cycles) {
switch (address) {
case MPY:

View File

@ -40,6 +40,9 @@
*/
package se.sics.mspsim.util;
import se.sics.mspsim.core.Chip;
import se.sics.mspsim.core.EventListener;
import se.sics.mspsim.core.EventSource;
import se.sics.mspsim.core.MSP430Core;
import se.sics.mspsim.core.Profiler;
import java.io.PrintStream;
@ -48,9 +51,12 @@ import java.util.Hashtable;
import java.util.regex.Pattern;
public class SimpleProfiler implements Profiler {
public class SimpleProfiler implements Profiler, EventListener {
private Hashtable<MapEntry,CallEntry> profileData;
private Hashtable<String, TagEntry> tagProfiles;
private Hashtable<String, TagEntry> startTags;
private Hashtable<String, TagEntry> endTags;
private CallEntry[] callStack;
private int cSP = 0;
private MSP430Core cpu;
@ -58,6 +64,9 @@ public class SimpleProfiler implements Profiler {
public SimpleProfiler() {
profileData = new Hashtable<MapEntry, CallEntry>();
tagProfiles = new Hashtable<String, TagEntry>();
startTags = new Hashtable<String, TagEntry>();
endTags = new Hashtable<String, TagEntry>();
callStack = new CallEntry[2048];
}
@ -113,7 +122,7 @@ public class SimpleProfiler implements Profiler {
}
}
}
public void printProfile(PrintStream out) {
printProfile(out, null);
}
@ -163,7 +172,7 @@ public class SimpleProfiler implements Profiler {
out.println(" " + callStack[cSP - i - 1].function.getInfo());
}
}
private static class CallEntry implements Comparable<CallEntry> {
MapEntry function;
long cycles;
@ -177,7 +186,88 @@ public class SimpleProfiler implements Profiler {
}
}
private static class TagEntry implements Comparable<TagEntry> {
String tag;
long cycles;
long lastCycles;
int calls;
public int compareTo(TagEntry o) {
long diff = o.cycles - cycles;
if (diff > 0) return 1;
if (diff < 0) return -1;
return 0;
}
}
public void setLogger(PrintStream out) {
logger = out;
}
/*
* Tag profiling.
*/
public void measureStart(String tag) {
TagEntry tagEntry = tagProfiles.get(tag);
if (tagEntry == null) {
tagEntry = new TagEntry();
tagEntry.tag = tag;
tagProfiles.put(tag, tagEntry);
}
/* only the first occurrence of event will set the lastCycles */
if (tagEntry.lastCycles == 0) {
tagEntry.lastCycles = cpu.cycles;
}
}
public void measureEnd(String tag) {
TagEntry tagEntry = tagProfiles.get(tag);
if (tagEntry != null) {
if (tagEntry.lastCycles != 0) {
tagEntry.calls++;
tagEntry.cycles += cpu.cycles - tagEntry.lastCycles;
tagEntry.lastCycles = 0;
}
}
}
public void printTagProfile(PrintStream out) {
TagEntry[] entries = tagProfiles.values().toArray(new TagEntry[tagProfiles.size()]);
Arrays.sort(entries);
for (int i = 0; i < entries.length; i++) {
TagEntry entry = entries[i];
System.out.println(entry.tag + "\t" + entry.calls + "\t" + entry.cycles);
}
}
public void addProfileTag(String tag, Chip chip, String start,
Chip chip2, String end) {
System.out.println("Add profile: " + tag +
" start: " + start + " end: " + end);
TagEntry tagEntry = new TagEntry();
tagEntry.tag = tag;
startTags.put(start, tagEntry);
endTags.put(end, tagEntry);
tagProfiles.put(tag, tagEntry);
chip.setEventListener(this);
chip2.setEventListener(this);
}
public void event(EventSource source, String event, Object data) {
TagEntry tagEntry = null;
if ((tagEntry = startTags.get(event)) != null) {
/* only the first occurrence of event will set the lastCycles */
if (tagEntry.lastCycles == 0) {
tagEntry.lastCycles = cpu.cycles;
}
} else if ((tagEntry = endTags.get(event)) != null) {
if (tagEntry.lastCycles != 0) {
tagEntry.calls++;
tagEntry.cycles += cpu.cycles - tagEntry.lastCycles;
tagEntry.lastCycles = 0;
}
}
}
}