diff --git a/README.txt b/README.txt index 4e6ead1..015c8ba 100644 --- a/README.txt +++ b/README.txt @@ -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) diff --git a/se/sics/mspsim/chip/CC2420.java b/se/sics/mspsim/chip/CC2420.java index 3ed022d..11a4695 100644 --- a/se/sics/mspsim/chip/CC2420.java +++ b/se/sics/mspsim/chip/CC2420.java @@ -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); diff --git a/se/sics/mspsim/cli/ProfilerCommands.java b/se/sics/mspsim/cli/ProfilerCommands.java index 98fe71f..1e1296e 100644 --- a/se/sics/mspsim/cli/ProfilerCommands.java +++ b/se/sics/mspsim/cli/ProfilerCommands.java @@ -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", "") { diff --git a/se/sics/mspsim/core/Chip.java b/se/sics/mspsim/core/Chip.java index 88bee0e..0bb75b6 100644 --- a/se/sics/mspsim/core/Chip.java +++ b/se/sics/mspsim/core/Chip.java @@ -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; diff --git a/se/sics/mspsim/core/EventListener.java b/se/sics/mspsim/core/EventListener.java new file mode 100644 index 0000000..a6950a8 --- /dev/null +++ b/se/sics/mspsim/core/EventListener.java @@ -0,0 +1,5 @@ +package se.sics.mspsim.core; + +public interface EventListener { + public void event(EventSource source, String event, Object data); +} diff --git a/se/sics/mspsim/core/EventSource.java b/se/sics/mspsim/core/EventSource.java new file mode 100644 index 0000000..8b71bb8 --- /dev/null +++ b/se/sics/mspsim/core/EventSource.java @@ -0,0 +1,5 @@ +package se.sics.mspsim.core; + +public interface EventSource { + public String getName(); +} diff --git a/se/sics/mspsim/core/IOUnit.java b/se/sics/mspsim/core/IOUnit.java index e180ba4..7dd93a8 100644 --- a/se/sics/mspsim/core/IOUnit.java +++ b/se/sics/mspsim/core/IOUnit.java @@ -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 diff --git a/se/sics/mspsim/core/MSP430.java b/se/sics/mspsim/core/MSP430.java index 79d6261..0197a63 100644 --- a/se/sics/mspsim/core/MSP430.java +++ b/se/sics/mspsim/core/MSP430.java @@ -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); } } diff --git a/se/sics/mspsim/core/Multiplier.java b/se/sics/mspsim/core/Multiplier.java index e6e3700..7aed126 100644 --- a/se/sics/mspsim/core/Multiplier.java +++ b/se/sics/mspsim/core/Multiplier.java @@ -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: diff --git a/se/sics/mspsim/util/SimpleProfiler.java b/se/sics/mspsim/util/SimpleProfiler.java index 452a8ed..5a9464a 100644 --- a/se/sics/mspsim/util/SimpleProfiler.java +++ b/se/sics/mspsim/util/SimpleProfiler.java @@ -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 profileData; + private Hashtable tagProfiles; + private Hashtable startTags; + private Hashtable 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(); + tagProfiles = new Hashtable(); + startTags = new Hashtable(); + endTags = new Hashtable(); 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 { MapEntry function; long cycles; @@ -177,7 +186,88 @@ public class SimpleProfiler implements Profiler { } } + private static class TagEntry implements Comparable { + 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; + } + } + } }