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:
parent
ae9aaea5f3
commit
4715637b38
3 changed files with 69 additions and 50 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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,6 +87,7 @@ 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;
|
||||||
|
@ -100,16 +99,21 @@ 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() {
|
||||||
|
@ -117,13 +121,16 @@ public abstract class MspMote implements Mote, WatchpointMote {
|
||||||
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) {
|
||||||
|
throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t);
|
||||||
}
|
}
|
||||||
|
|
||||||
long maxSimTimeCycles = (long)(NR_CYCLES_PER_MSEC * ((simTime+usDrift+Simulation.MILLISECOND)/(double)Simulation.MILLISECOND));
|
/* TODO Poll mote interfaces? */
|
||||||
if (maxSimTimeCycles <= cycleCounter) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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];
|
|
||||||
|
|
||||||
|
/* 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,9 +371,7 @@ public abstract class MspMote implements Mote, WatchpointMote {
|
||||||
getSimulation().stopSimulation();
|
getSimulation().stopSimulation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendCLICommandAndPrint(String comamnd) {
|
private void sendCLICommandAndPrint(String comamnd) {
|
||||||
|
@ -415,6 +430,8 @@ public abstract class MspMote implements Mote, WatchpointMote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Schedule us immediately */
|
||||||
|
requestImmediateWakeup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue