Merge pull request #979 from TheGeorge/drifting-motes

Time Drifting Motes
This commit is contained in:
Fredrik Österlind 2015-05-13 11:21:34 +02:00
commit 9261ff5d13
6 changed files with 168 additions and 36 deletions

View file

@ -44,6 +44,7 @@ import org.contikios.cooja.MoteType;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.motes.AbstractEmulatedMote;
import avrora.arch.avr.AVRProperties;
import avrora.core.LoadableProgram;
import avrora.sim.AtmelInterpreter;
@ -54,6 +55,8 @@ import avrora.sim.mcu.EEPROM;
import avrora.sim.platform.MicaZ;
import avrora.sim.platform.PlatformFactory;
import org.contikios.cooja.avrmote.interfaces.MicaClock;
/**
* @author Joakim Eriksson, Fredrik Osterlind
*/
@ -74,6 +77,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
private EEPROM eeprom = null;
private long executed = 0;
private long skipped = 0;
/* Stack monitoring variables */
private boolean stopNextInstruction = false;
@ -184,6 +191,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
private long cyclesExecuted = 0;
private long cyclesUntil = 0;
public void execute(long t) {
MicaClock clock = ((MicaClock) (myMoteInterfaceHandler.getClock()));
double deviation = clock.getDeviation();
long drift = clock.getDrift();
/* Wait until mote boots */
if (myMoteInterfaceHandler.getClock().getTime() < 0) {
scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime());
@ -196,13 +207,22 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
}
/* TODO Poll mote interfaces? */
/* skip if necessary */
if (((1-deviation) * executed) > skipped) {
skipped += 1;
scheduleNextWakeup(t + Simulation.MILLISECOND);
}
/* Execute one millisecond */
cyclesUntil += NR_CYCLES_PER_MSEC;
while (cyclesExecuted < cyclesUntil) {
cyclesExecuted += interpreter.step();
}
/* book keeping */
executed += 1;
/* TODO Poll mote interfaces? */
/* Schedule wakeup every millisecond */

View file

@ -54,10 +54,12 @@ public class MicaClock extends Clock {
private MicaZMote myMote;
private long timeDrift; /* Microseconds */
private double deviation;
public MicaClock(Mote mote) {
simulation = mote.getSimulation();
myMote = (MicaZMote) mote;
deviation = 1.0;
}
public void setTime(long newTime) {
@ -68,6 +70,15 @@ public class MicaClock extends Clock {
return simulation.getSimulationTime() + timeDrift;
}
public double getDeviation() {
return deviation;
}
public void setDeviation(double deviation) {
assert (deviation>0.0) && (deviation<=1.0);
this.deviation = deviation;
}
public void setDrift(long drift) {
timeDrift = drift;
}
@ -75,19 +86,4 @@ public class MicaClock extends Clock {
public long getDrift() {
return timeDrift;
}
public JPanel getInterfaceVisualizer() {
return null;
}
public void releaseInterfaceVisualizer(JPanel panel) {
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
}
}

View file

@ -78,6 +78,8 @@ import se.sics.mspsim.util.MapEntry;
import se.sics.mspsim.util.MapTable;
import se.sics.mspsim.profiler.SimpleProfiler;
import org.contikios.cooja.mspmote.interfaces.MspClock;
/**
* @author Fredrik Osterlind
*/
@ -288,13 +290,22 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
private long lastExecute = -1; /* Last time mote executed */
private long nextExecute;
private long executed = 0;
private long skipped = 0;
public void execute(long time) {
execute(time, EXECUTE_DURATION_US);
}
public void execute(long t, int duration) {
MspClock clock = ((MspClock) (myMoteInterfaceHandler.getClock()));
double deviation = clock.getDeviation();
long drift = clock.getDrift();
/* Wait until mote boots */
if (!booted && myMoteInterfaceHandler.getClock().getTime() < 0) {
scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime());
if (!booted && clock.getTime() < 0) {
scheduleNextWakeup(t - clock.getTime());
return;
}
booted = true;
@ -313,12 +324,17 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t);
}
if (((1-deviation) * executed) > skipped) {
lastExecute = lastExecute + duration; // (t+duration) - (t-lastExecute);
nextExecute = t+duration;
skipped += duration;
scheduleNextWakeup(nextExecute);
}
/* Execute MSPSim-based mote */
/* TODO Try-catch overhead */
try {
nextExecute =
t + duration +
myCpu.stepMicros(t - lastExecute, duration);
nextExecute = myCpu.stepMicros(Math.max(0, t-lastExecute), duration) + t + duration;
lastExecute = t;
} catch (EmulationException e) {
String trace = e.getMessage() + "\n\n" + getStackTrace();
@ -330,7 +346,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
if (nextExecute < t) {
throw new RuntimeException(t + ": MSPSim requested early wakeup: " + nextExecute);
}
/*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/
executed += duration;
scheduleNextWakeup(nextExecute);
if (stopNextInstruction) {

View file

@ -52,9 +52,11 @@ public class MspClock extends Clock {
private Simulation simulation;
private long timeDrift; /* Microseconds */
private double deviation;
public MspClock(Mote mote) {
simulation = mote.getSimulation();
deviation = 1.0;
}
public void setTime(long newTime) {
@ -72,20 +74,13 @@ public class MspClock extends Clock {
public long getDrift() {
return timeDrift;
}
public JPanel getInterfaceVisualizer() {
/* TODO Show current CPU speed */
return null;
public void setDeviation(double deviation) {
assert (deviation>0.0) && (deviation<=1.0);
this.deviation = deviation;
}
public void releaseInterfaceVisualizer(JPanel panel) {
public double getDeviation() {
return deviation;
}
public Collection<Element> getConfigXML() {
return null;
}
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
}
}

View file

@ -114,6 +114,14 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
public long getTime() {
return moteTime;
}
public void setDeviation(double deviation) {
logger.fatal("Can't change deviation");;
}
public double getDeviation() {
return 1.0;
}
public void doActionsBeforeTick() {
/* Update time */
@ -161,5 +169,4 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
}
}

View file

@ -30,7 +30,19 @@
package org.contikios.cooja.interfaces;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.contikios.cooja.*;
import org.jdom.Element;
/**
* Represents a mote's internal clock. Notice that the overall
@ -39,10 +51,10 @@ import org.contikios.cooja.*;
* This observable never notifies.
*
* @author Fredrik Osterlind
* Andreas Löscher
*/
@ClassDescription("Clock")
public abstract class Clock extends MoteInterface {
/**
* Set mote's time to given time.
*
@ -76,4 +88,88 @@ public abstract class Clock extends MoteInterface {
*/
public abstract long getDrift();
/**
* The clock deviation is a factor that represents with how much speed the
* mote progresses through the simulation in relation to the simulation speed.
*
* A value of 1.0 results in the mote being simulated with the same speed
* as the simulation. A value of 0.5 results in the mote being simulation
* at half of the simulation speed.
*
* @param deviation Deviation factor
*/
public abstract void setDeviation(double deviation);
/**
* Get deviation factor
*/
public abstract double getDeviation();
@Override
public JPanel getInterfaceVisualizer() {
JPanel panel = new JPanel();
GridLayout layout = new GridLayout(0,2);
/* elements */
final JLabel timeLabel = new JLabel("Time (ms)");
final JTextField timeField = new JTextField(String.valueOf(getTime() / 1000));
final JLabel deviationLabel = new JLabel("Deviation Factor");
final JTextField deviationField = new JTextField(String.valueOf(getDeviation()));
final JButton readButton = new JButton("Read Clock Values");
final JButton updateButton = new JButton("Write Clock Values");
/* set layout */
panel.setLayout(layout);
/* add components */
panel.add(timeLabel);
panel.add(timeField);
panel.add(deviationLabel);
panel.add(deviationField);
panel.add(readButton);
panel.add(updateButton);
readButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent ev) {
if (ev.getButton()==1) {
timeField.setText(String.valueOf(getTime() / 1000));
deviationField.setText(String.valueOf(getDeviation()));
}
}
});
updateButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent ev) {
if (ev.getButton()==1) {
setTime(Long.parseLong(timeField.getText()) * 1000);
setDeviation(Double.parseDouble(deviationField.getText()));
}
}
});
return panel;
}
@Override
public void releaseInterfaceVisualizer(JPanel panel) {
}
@Override
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element = new Element("deviation");
element.setText(String.valueOf(getDeviation()));
config.add(element);
return config;
}
@Override
public void setConfigXML(Collection<Element> configXML, boolean visAvailable) {
for (Element element : configXML) {
if (element.getName().equals("deviation")) {
setDeviation(Double.parseDouble(element.getText()));
}
}
}
}