From 4715637b386a6e90687f76c7e6fca355884b4bd1 Mon Sep 17 00:00:00 2001 From: fros4943 Date: Tue, 27 Oct 2009 10:02:48 +0000 Subject: [PATCH] major update to mspsim-based emulated mote: * fully event based scheduling instead of previous event-tick-hybrid model -> * faster emulation of large mspsim-based networks * enables variable clock frequency (no longer fixed to 3.9 Mhz) --- .../src/se/sics/cooja/mspmote/ESBMote.java | 3 +- .../src/se/sics/cooja/mspmote/MspMote.java | 113 ++++++++++-------- .../src/se/sics/cooja/mspmote/SkyMote.java | 3 +- 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java index ff29e4c82..c3e5475e5 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/ESBMote.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ESBMote.java,v 1.10 2009/09/17 13:19:08 fros4943 Exp $ + * $Id: ESBMote.java,v 1.11 2009/10/27 10:02:48 fros4943 Exp $ */ package se.sics.cooja.mspmote; @@ -57,6 +57,7 @@ public class ESBMote extends MspMote { protected boolean initEmulator(File fileELF) { try { esbNode = new ESBNode(); + registry = esbNode.getRegistry(); prepareMote(fileELF, esbNode); } catch (Exception e) { diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index d8aa5f90a..a5735fd27 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -26,10 +26,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: MspMote.java,v 1.33 2009/09/18 09:06:15 fros4943 Exp $ + * $Id: MspMote.java,v 1.34 2009/10/27 10:02:48 fros4943 Exp $ */ package se.sics.cooja.mspmote; + import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; @@ -54,7 +55,7 @@ import se.sics.cooja.Simulation; import se.sics.cooja.Watchpoint; import se.sics.cooja.WatchpointMote; import se.sics.cooja.interfaces.IPAddress; -import se.sics.cooja.mspmote.interfaces.TR1001Radio; +import se.sics.cooja.motes.AbstractEmulatedMote; import se.sics.cooja.mspmote.plugins.MspBreakpointContainer; import se.sics.mspsim.cli.CommandHandler; import se.sics.mspsim.cli.LineListener; @@ -62,6 +63,8 @@ import se.sics.mspsim.cli.LineOutputStream; import se.sics.mspsim.core.EmulationException; import se.sics.mspsim.core.MSP430; import se.sics.mspsim.platform.GenericNode; +import se.sics.mspsim.ui.JFrameWindowManager; +import se.sics.mspsim.util.ComponentRegistry; import se.sics.mspsim.util.ConfigManager; import se.sics.mspsim.util.DebugInfo; import se.sics.mspsim.util.ELF; @@ -71,17 +74,12 @@ import se.sics.mspsim.util.MapTable; /** * @author Fredrik Osterlind */ -public abstract class MspMote implements Mote, WatchpointMote { +public abstract class MspMote extends AbstractEmulatedMote implements Mote, WatchpointMote { private static Logger logger = Logger.getLogger(MspMote.class); - /* 3.900 MHz according to Contiki's speed sync loop*/ - public static long NR_CYCLES_PER_MSEC = 3900; + private final static int EXECUTE_DURATION_US = 1; /* We always execute in 1 us steps */ - /* Cycle counter */ - public long cycleCounter = 0; - public long usDrift = 0; /* us */ - - private Simulation mySimulation = null; + private Simulation simulation; private CommandHandler commandHandler; private LineListener commandListener; private MSP430 myCpu = null; @@ -89,7 +87,8 @@ public abstract class MspMote implements Mote, WatchpointMote { private MspMoteMemory myMemory = null; private MoteInterfaceHandler myMoteInterfaceHandler = null; private ELF myELFModule = null; - + public ComponentRegistry registry = null; + /* Stack monitoring variables */ private boolean stopNextInstruction = false; private boolean monitorStackUsage = false; @@ -100,30 +99,38 @@ public abstract class MspMote implements Mote, WatchpointMote { private MspBreakpointContainer breakpointsContainer; public MspMote() { + simulation = null; myMoteType = null; - mySimulation = null; myCpu = null; myMemory = null; myMoteInterfaceHandler = null; + + /* Scheduled from setConfigXML */ } public MspMote(MspMoteType moteType, Simulation simulation) { + this.simulation = simulation; myMoteType = moteType; - mySimulation = simulation; + + /* Schedule us immediately */ + requestImmediateWakeup(); } protected void initMote() { if (myMoteType != null) { initEmulator(myMoteType.getContikiFirmwareFile()); myMoteInterfaceHandler = createMoteInterfaceHandler(); - + + /* TODO Setup COOJA-specific window manager */ + registry.registerComponent("windowManager", new JFrameWindowManager()); + /* Create watchpoint container */ breakpointsContainer = new MspBreakpointContainer(this, getFirmwareDebugInfo(this)); } } /** - * Abort current tick immediately. + * Abort execution immediately. * May for example be called by a breakpoint handler. */ public void stopNextInstruction() { @@ -175,11 +182,11 @@ public abstract class MspMote implements Mote, WatchpointMote { } public Simulation getSimulation() { - return mySimulation; + return simulation; } public void setSimulation(Simulation simulation) { - mySimulation = simulation; + this.simulation = simulation; } /* Stack monitoring variables */ @@ -295,43 +302,42 @@ public abstract class MspMote implements Mote, WatchpointMote { */ protected abstract boolean initEmulator(File ELFFile); - private int[] pcHistory = new int[5]; - - /* return false when done - e.g. true means more work to do before finished with this tick */ public boolean tick(long simTime) { + throw new RuntimeException("Obsolete method"); + } + + private long lastExecute = -1; /* Last time mote executed */ + private long nextExecute; + public void execute(long t) { + /* Wait until mote boots */ + if (myMoteInterfaceHandler.getClock().getTime() < 0) { + scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); + return; + } + if (stopNextInstruction) { stopNextInstruction = false; sendCLICommandAndPrint("trace 1000"); throw new RuntimeException("MSPSim requested simulation stop"); } - - if (simTime + usDrift < 0) { - return false; + + if (lastExecute < 0) { + /* Always execute one microsecond the first time */ + lastExecute = t; } - - long maxSimTimeCycles = (long)(NR_CYCLES_PER_MSEC * ((simTime+usDrift+Simulation.MILLISECOND)/(double)Simulation.MILLISECOND)); - if (maxSimTimeCycles <= cycleCounter) { - return false; + if (t < lastExecute) { + throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t); } - // Leave control to emulated CPU - cycleCounter += 1; - - MSP430 cpu = getCPU(); - if (cpu.cycles > cycleCounter) { - /* CPU already ticked too far - just wait it out */ - return true; - } - myMoteInterfaceHandler.doActiveActionsBeforeTick(); - - /* Log recent program counter (PC) history */ - for (int i=pcHistory.length-1; i > 0; i--) { - pcHistory[i] = pcHistory[i-1]; - } - pcHistory[0] = cpu.reg[MSP430.PC]; + /* TODO Poll mote interfaces? */ + /* Execute MSPSim-based mote */ + /* TODO Try-catch overhead */ try { - cpu.step(cycleCounter); + nextExecute = + t + EXECUTE_DURATION_US + + myCpu.stepMicros(t - lastExecute, EXECUTE_DURATION_US); + lastExecute = t; } catch (EmulationException e) { if (e.getMessage().startsWith("Bad operation")) { /* Experimental: print program counter history */ @@ -342,7 +348,18 @@ public abstract class MspMote implements Mote, WatchpointMote { new RuntimeException("Emulated exception: " + e.getMessage()).initCause(e); } - if (monitorStackUsage) { + /* TODO Poll mote interfaces? */ + + /* Schedule wakeup */ + if (nextExecute <= t) { + throw new RuntimeException(t + ": MSPSim requested early wakeup: " + nextExecute); + } + /*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/ + scheduleNextWakeup(nextExecute); + + + /* XXX TODO Reimplement stack monitoring using MSPSim internals */ + /*if (monitorStackUsage) { int newStack = cpu.reg[MSP430.SP]; if (newStack < stackPointerLow && newStack > 0) { stackPointerLow = cpu.reg[MSP430.SP]; @@ -354,11 +371,9 @@ public abstract class MspMote implements Mote, WatchpointMote { getSimulation().stopSimulation(); } } - } - - return true; + }*/ } - + private void sendCLICommandAndPrint(String comamnd) { /* Backup listener */ LineListener oldListener = commandListener; @@ -415,6 +430,8 @@ public abstract class MspMote implements Mote, WatchpointMote { } } + /* Schedule us immediately */ + requestImmediateWakeup(); return true; } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java index 838a76d8b..3a682b085 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/SkyMote.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: SkyMote.java,v 1.17 2009/10/08 14:41:20 fros4943 Exp $ + * $Id: SkyMote.java,v 1.18 2009/10/27 10:02:48 fros4943 Exp $ */ package se.sics.cooja.mspmote; @@ -58,6 +58,7 @@ public class SkyMote extends MspMote { protected boolean initEmulator(File fileELF) { try { skyNode = new SkyNode(); + registry = skyNode.getRegistry(); prepareMote(fileELF, skyNode); } catch (Exception e) { logger.fatal("Error when creating Sky mote: ", e);