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)
This commit is contained in:
fros4943 2009-10-27 10:02:48 +00:00
parent ae9aaea5f3
commit 4715637b38
3 changed files with 69 additions and 50 deletions

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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; package se.sics.cooja.mspmote;
@ -57,6 +57,7 @@ public class ESBMote extends MspMote {
protected boolean initEmulator(File fileELF) { protected boolean initEmulator(File fileELF) {
try { try {
esbNode = new ESBNode(); esbNode = new ESBNode();
registry = esbNode.getRegistry();
prepareMote(fileELF, esbNode); prepareMote(fileELF, esbNode);
} catch (Exception e) { } catch (Exception e) {

View File

@ -26,10 +26,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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; package se.sics.cooja.mspmote;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -54,7 +55,7 @@ import se.sics.cooja.Simulation;
import se.sics.cooja.Watchpoint; import se.sics.cooja.Watchpoint;
import se.sics.cooja.WatchpointMote; import se.sics.cooja.WatchpointMote;
import se.sics.cooja.interfaces.IPAddress; 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.cooja.mspmote.plugins.MspBreakpointContainer;
import se.sics.mspsim.cli.CommandHandler; import se.sics.mspsim.cli.CommandHandler;
import se.sics.mspsim.cli.LineListener; 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.EmulationException;
import se.sics.mspsim.core.MSP430; import se.sics.mspsim.core.MSP430;
import se.sics.mspsim.platform.GenericNode; 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.ConfigManager;
import se.sics.mspsim.util.DebugInfo; import se.sics.mspsim.util.DebugInfo;
import se.sics.mspsim.util.ELF; import se.sics.mspsim.util.ELF;
@ -71,17 +74,12 @@ import se.sics.mspsim.util.MapTable;
/** /**
* @author Fredrik Osterlind * @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); private static Logger logger = Logger.getLogger(MspMote.class);
/* 3.900 MHz according to Contiki's speed sync loop*/ private final static int EXECUTE_DURATION_US = 1; /* We always execute in 1 us steps */
public static long NR_CYCLES_PER_MSEC = 3900;
/* Cycle counter */ private Simulation simulation;
public long cycleCounter = 0;
public long usDrift = 0; /* us */
private Simulation mySimulation = null;
private CommandHandler commandHandler; private CommandHandler commandHandler;
private LineListener commandListener; private LineListener commandListener;
private MSP430 myCpu = null; private MSP430 myCpu = null;
@ -89,7 +87,8 @@ public abstract class MspMote implements Mote, WatchpointMote {
private MspMoteMemory myMemory = null; private MspMoteMemory myMemory = null;
private MoteInterfaceHandler myMoteInterfaceHandler = null; private MoteInterfaceHandler myMoteInterfaceHandler = null;
private ELF myELFModule = null; private ELF myELFModule = null;
public ComponentRegistry registry = null;
/* Stack monitoring variables */ /* Stack monitoring variables */
private boolean stopNextInstruction = false; private boolean stopNextInstruction = false;
private boolean monitorStackUsage = false; private boolean monitorStackUsage = false;
@ -100,30 +99,38 @@ public abstract class MspMote implements Mote, WatchpointMote {
private MspBreakpointContainer breakpointsContainer; private MspBreakpointContainer breakpointsContainer;
public MspMote() { public MspMote() {
simulation = null;
myMoteType = null; myMoteType = null;
mySimulation = null;
myCpu = null; myCpu = null;
myMemory = null; myMemory = null;
myMoteInterfaceHandler = null; myMoteInterfaceHandler = null;
/* Scheduled from setConfigXML */
} }
public MspMote(MspMoteType moteType, Simulation simulation) { public MspMote(MspMoteType moteType, Simulation simulation) {
this.simulation = simulation;
myMoteType = moteType; myMoteType = moteType;
mySimulation = simulation;
/* Schedule us immediately */
requestImmediateWakeup();
} }
protected void initMote() { protected void initMote() {
if (myMoteType != null) { if (myMoteType != null) {
initEmulator(myMoteType.getContikiFirmwareFile()); initEmulator(myMoteType.getContikiFirmwareFile());
myMoteInterfaceHandler = createMoteInterfaceHandler(); myMoteInterfaceHandler = createMoteInterfaceHandler();
/* TODO Setup COOJA-specific window manager */
registry.registerComponent("windowManager", new JFrameWindowManager());
/* Create watchpoint container */ /* Create watchpoint container */
breakpointsContainer = new MspBreakpointContainer(this, getFirmwareDebugInfo(this)); breakpointsContainer = new MspBreakpointContainer(this, getFirmwareDebugInfo(this));
} }
} }
/** /**
* Abort current tick immediately. * Abort execution immediately.
* May for example be called by a breakpoint handler. * May for example be called by a breakpoint handler.
*/ */
public void stopNextInstruction() { public void stopNextInstruction() {
@ -175,11 +182,11 @@ public abstract class MspMote implements Mote, WatchpointMote {
} }
public Simulation getSimulation() { public Simulation getSimulation() {
return mySimulation; return simulation;
} }
public void setSimulation(Simulation simulation) { public void setSimulation(Simulation simulation) {
mySimulation = simulation; this.simulation = simulation;
} }
/* Stack monitoring variables */ /* Stack monitoring variables */
@ -295,43 +302,42 @@ public abstract class MspMote implements Mote, WatchpointMote {
*/ */
protected abstract boolean initEmulator(File ELFFile); 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) { 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) { if (stopNextInstruction) {
stopNextInstruction = false; stopNextInstruction = false;
sendCLICommandAndPrint("trace 1000"); sendCLICommandAndPrint("trace 1000");
throw new RuntimeException("MSPSim requested simulation stop"); throw new RuntimeException("MSPSim requested simulation stop");
} }
if (simTime + usDrift < 0) { if (lastExecute < 0) {
return false; /* Always execute one microsecond the first time */
lastExecute = t;
} }
if (t < lastExecute) {
long maxSimTimeCycles = (long)(NR_CYCLES_PER_MSEC * ((simTime+usDrift+Simulation.MILLISECOND)/(double)Simulation.MILLISECOND)); throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t);
if (maxSimTimeCycles <= cycleCounter) {
return false;
} }
// Leave control to emulated CPU /* TODO Poll mote interfaces? */
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];
/* Execute MSPSim-based mote */
/* TODO Try-catch overhead */
try { try {
cpu.step(cycleCounter); nextExecute =
t + EXECUTE_DURATION_US +
myCpu.stepMicros(t - lastExecute, EXECUTE_DURATION_US);
lastExecute = t;
} catch (EmulationException e) { } catch (EmulationException e) {
if (e.getMessage().startsWith("Bad operation")) { if (e.getMessage().startsWith("Bad operation")) {
/* Experimental: print program counter history */ /* Experimental: print program counter history */
@ -342,7 +348,18 @@ public abstract class MspMote implements Mote, WatchpointMote {
new RuntimeException("Emulated exception: " + e.getMessage()).initCause(e); 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]; int newStack = cpu.reg[MSP430.SP];
if (newStack < stackPointerLow && newStack > 0) { if (newStack < stackPointerLow && newStack > 0) {
stackPointerLow = cpu.reg[MSP430.SP]; stackPointerLow = cpu.reg[MSP430.SP];
@ -354,11 +371,9 @@ public abstract class MspMote implements Mote, WatchpointMote {
getSimulation().stopSimulation(); getSimulation().stopSimulation();
} }
} }
} }*/
return true;
} }
private void sendCLICommandAndPrint(String comamnd) { private void sendCLICommandAndPrint(String comamnd) {
/* Backup listener */ /* Backup listener */
LineListener oldListener = commandListener; LineListener oldListener = commandListener;
@ -415,6 +430,8 @@ public abstract class MspMote implements Mote, WatchpointMote {
} }
} }
/* Schedule us immediately */
requestImmediateWakeup();
return true; return true;
} }

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * 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; package se.sics.cooja.mspmote;
@ -58,6 +58,7 @@ public class SkyMote extends MspMote {
protected boolean initEmulator(File fileELF) { protected boolean initEmulator(File fileELF) {
try { try {
skyNode = new SkyNode(); skyNode = new SkyNode();
registry = skyNode.getRegistry();
prepareMote(fileELF, skyNode); prepareMote(fileELF, skyNode);
} catch (Exception e) { } catch (Exception e) {
logger.fatal("Error when creating Sky mote: ", e); logger.fatal("Error when creating Sky mote: ", e);