Merge pull request #628 from ejoerns/pull-req/cooja-memory

[Cooja] Rewrote Coojas mote memory management
This commit is contained in:
Fredrik Österlind 2014-08-25 15:37:23 +02:00
commit 2a0ccf2c6b
42 changed files with 3173 additions and 1714 deletions

View file

@ -1,4 +1,5 @@
/*
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
* Copyright (c) 2009, Swedish Institute of Computer Science. All rights
* reserved.
*
@ -28,27 +29,37 @@
package org.contikios.cooja.avrmote;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.contikios.cooja.AddressMemory;
import org.contikios.cooja.MoteMemory;
import avrora.arch.avr.AVRProperties;
import avrora.core.SourceMapping;
import avrora.core.SourceMapping.Location;
import avrora.sim.AtmelInterpreter;
import avrora.sim.Simulator.Watch;
import avrora.sim.State;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
import org.contikios.cooja.mote.memory.MemoryLayout;
/**
* @author Joakim Eriksson
* @author Joakim Eriksson, Fredrik Osterlind, David Kopf, Enrico Jorns
*/
public class AvrMoteMemory implements MoteMemory, AddressMemory {
private static Logger logger = Logger.getLogger(AvrMoteMemory.class);
public class AvrMoteMemory implements MemoryInterface {
private static Logger logger = Logger.getLogger(AvrMoteMemory.class);
private static final boolean DEBUG = logger.isDebugEnabled();
private SourceMapping memoryMap;
private AtmelInterpreter interpreter;
private AVRProperties avrProperties;
private final SourceMapping memoryMap;
private final AVRProperties avrProperties;
private final AtmelInterpreter interpreter;
private final ArrayList<AvrByteMonitor> memoryMonitors = new ArrayList<>();
private final MemoryLayout memLayout = new MemoryLayout(ByteOrder.LITTLE_ENDIAN, MemoryLayout.ARCH_8BIT, 2);
private boolean coojaIsAccessingMemory;
public AvrMoteMemory(SourceMapping map, AVRProperties avrProperties, AtmelInterpreter interpreter) {
memoryMap = map;
@ -56,130 +67,158 @@ public class AvrMoteMemory implements MoteMemory, AddressMemory {
this.avrProperties = avrProperties;
}
public void insertWatch(Watch w, int address) {
interpreter.getSimulator().insertWatch(w, address);
@Override
public int getTotalSize() {
return avrProperties.sram_size;
}
@Override
public byte[] getMemory() throws MoteMemoryException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public byte[] getMemorySegment(long address, int size) throws MoteMemoryException {
/*logger.info("getMemorySegment(" + String.format("0x%04x", address) +
", " + size + ")");*/
if (!accessInRange(address, size)) {
throw new MoteMemoryException(
"Getting memory segment [0x%x,0x%x] failed: Out of range",
address, address + size - 1);
}
public void clearMemory() {
logger.fatal("not implemented");
/* XXX Unsure whether this is the appropriate method to use, as it
* triggers memoryRead monitor. Right now I'm using a flag to indicate
* that Cooja (as opposed to Contiki) read the memory, to avoid infinite
* recursion. */
coojaIsAccessingMemory = true;
byte[] data = new byte[(int) size];
for (int i = 0; i < size; i++) {
data[i] = (byte) (interpreter.getDataByte((int) address + i) & 0xff);
}
coojaIsAccessingMemory = false;
return data;
}
@Override
public void setMemorySegment(long address, byte[] data) throws MoteMemoryException {
if (!accessInRange(address, data.length)) {
throw new MoteMemoryException(
"Writing memory segment [0x%x,0x%x] failed: Out of range",
address, address + data.length - 1);
}
public byte[] getMemorySegment(int address, int size) {
logger.fatal("getMemorySegment is not implemented");
return null;
/* XXX See comment in getMemorySegment. */
coojaIsAccessingMemory = true;
for (int i = 0; i < data.length; i++) {
interpreter.writeDataByte((int) address + i, data[i]);
}
coojaIsAccessingMemory = false;
if (DEBUG) {
logger.debug(String.format(
"Wrote memory segment [0x%x,0x%x]",
address, address + data.length - 1));
}
}
@Override
public void clearMemory() {
setMemorySegment(0L, new byte[avrProperties.sram_size]);
}
private boolean accessInRange(long address, int size) {
return (address >= 0) && (address + size <= avrProperties.sram_size);
}
@Override
public long getStartAddr() {
return 0;// XXX
}
@Override
public Map<String, Symbol> getSymbolMap() {
// XXX do not fetch in function!
Map<String, Symbol> symbols = new HashMap<>();
for (Iterator<Location> iter = memoryMap.getIterator(); iter.hasNext();) {
Location loc = iter.next();
if (loc == null || (loc.section.equals(".text"))) {
continue;
}
symbols.put(loc.name, new Symbol(Symbol.Type.VARIABLE, loc.name, loc.section, loc.vma_addr & 0x7fffff, -1));
}
return symbols;
}
@Override
public MemoryLayout getLayout() {
return memLayout;
}
class AvrByteMonitor extends Watch.Empty {
/** start address to monitor */
final long address;
/** size to monitor */
final int size;
/** Segment monitor to notify */
final SegmentMonitor mm;
/** MonitorType we are listening to */
final EventType flag;
public AvrByteMonitor(long address, int size, SegmentMonitor mm, EventType flag) {
this.address = address;
this.size = size;
this.mm = mm;
this.flag = flag;
}
public int getTotalSize() {
return 0;
@Override
public void fireAfterRead(State state, int data_addr, byte value) {
if (flag == EventType.WRITE || coojaIsAccessingMemory) {
return;
}
mm.memoryChanged(AvrMoteMemory.this, EventType.READ, data_addr);
}
public void setMemorySegment(int address, byte[] data) {
logger.fatal("setMemorySegment is not implemented");
@Override
public void fireAfterWrite(State state, int data_addr, byte value) {
if (flag == EventType.READ || coojaIsAccessingMemory) {
return;
}
mm.memoryChanged(AvrMoteMemory.this, EventType.WRITE, data_addr);
}
}
public byte[] getByteArray(String varName, int length)
throws UnknownVariableException {
return null;
@Override
public boolean addSegmentMonitor(EventType flag, long address, int size, SegmentMonitor mm) {
AvrByteMonitor mon = new AvrByteMonitor(address, size, mm, flag);
memoryMonitors.add(mon);
/* logger.debug("Added AvrByteMonitor " + Integer.toString(mon.hashCode()) + " for addr " + mon.address + " size " + mon.size + " with watch" + mon.watch); */
/* Add byte monitor (watch) for every byte in range */
for (int idx = 0; idx < mon.size; idx++) {
interpreter.getSimulator().insertWatch(mon, (int) mon.address + idx);
/* logger.debug("Inserted watch " + Integer.toString(mon.watch.hashCode()) + " for " + (mon.address + idx)); */
}
return true;
}
public byte getByteValueOf(String varName) throws UnknownVariableException {
return (byte) getValueOf(varName, 1);
@Override
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor mm) {
for (AvrByteMonitor mcm : memoryMonitors) {
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
continue;
}
for (int idx = 0; idx < mcm.size; idx++) {
interpreter.getSimulator().removeWatch(mcm, (int) mcm.address + idx);
/* logger.debug("Removed watch " + Integer.toString(mcm.watch.hashCode()) + " for " + (mcm.address + idx)); */
}
memoryMonitors.remove(mcm);
return true;
}
return false;
}
private int getValueOf(String varName, int len) throws UnknownVariableException {
Location mem = memoryMap.getLocation(varName);
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName);
System.out.println("Variable:" + varName + " in section: " + mem.section);
System.out.println("LMA: " + Integer.toHexString(mem.lma_addr));
System.out.println("VMA: " + Integer.toHexString(mem.vma_addr));
System.out.println("Data: " + interpreter.getDataByte(mem.lma_addr & 0xfffff));
System.out.println("Flash: " + interpreter.getFlashByte(mem.lma_addr & 0xfffff));
int data = 0;
if (mem.vma_addr > 0xfffff) {
for (int i = 0; i < len; i++) {
data = (data << 8) + (interpreter.getDataByte((mem.vma_addr & 0xfffff) + len - i - 1) & 0xff);
System.out.println("Read byte: " + interpreter.getDataByte((mem.vma_addr & 0xfffff) + i) +
" => " + data);
}
} else {
for (int i = 0; i < len; i++) {
data = (data << 8) + interpreter.getFlashByte(mem.vma_addr + len - i - 1) & 0xff;
}
}
return data;
}
private void setValue(String varName, int val, int len) throws UnknownVariableException {
Location mem = memoryMap.getLocation(varName);
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName);
int data = val;
if (mem.vma_addr > 0xfffff) {
// write LSB first.
for (int i = 0; i < len; i++) {
interpreter.writeDataByte((mem.vma_addr & 0xfffff) + i, (byte) (data & 0xff));
System.out.println("Wrote byte: " + (data & 0xff));
data = data >> 8;
}
} else {
for (int i = 0; i < len; i++) {
interpreter.writeFlashByte(mem.vma_addr + i, (byte) (data & 0xff));
data = data >> 8;
}
}
}
public int getIntValueOf(String varName) throws UnknownVariableException {
return getValueOf(varName, 2);
}
public int getIntegerLength() {
return 2;
}
public int getVariableAddress(String varName)
throws UnknownVariableException {
return 0;
}
public String[] getVariableNames() {
ArrayList<String> symbols = new ArrayList<String>();
for (Iterator i = memoryMap.getIterator(); i.hasNext();) {
symbols.add(((Location) i.next()).name);
}
return symbols.toArray(new String[0]);
}
public void setByteArray(String varName, byte[] data)
throws UnknownVariableException {
}
public void setByteValueOf(String varName, byte newVal)
throws UnknownVariableException {
setValue(varName, newVal, 1);
}
public void setIntValueOf(String varName, int newVal)
throws UnknownVariableException {
setValue(varName, newVal, 2);
}
public boolean variableExists(String varName) {
return memoryMap.getLocation(varName) != null;
}
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
logger.warn("Not implemented");
return false;
}
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
}
public int parseInt(byte[] memorySegment) {
logger.warn("Not implemented");
return 0;
}
}

View file

@ -40,9 +40,9 @@ import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
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;
@ -264,11 +264,12 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
return config;
}
public MoteMemory getMemory() {
@Override
public MemoryInterface getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
public void setMemory(AvrMoteMemory memory) {
myMemory = (AvrMoteMemory) memory;
}

View file

@ -38,16 +38,15 @@ import javax.swing.JPanel;
import org.apache.log4j.Logger;
import org.jdom.Element;
import avrora.sim.State;
import avrora.sim.Simulator.Watch;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteTimeEvent;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.TimeEvent;
import org.contikios.cooja.avrmote.AvrMoteMemory;
import org.contikios.cooja.avrmote.MicaZMote;
import org.contikios.cooja.interfaces.MoteID;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.mote.memory.VarMemory;
public class MicaZID extends MoteID {
@ -57,7 +56,7 @@ public class MicaZID extends MoteID {
private int moteID = -1; /* TODO Implement */
private AvrMoteMemory moteMem;
private VarMemory moteMem;
boolean tosID = false;
boolean contikiID = false;
private MicaZMote mote;
@ -80,23 +79,26 @@ public class MicaZID extends MoteID {
public MicaZID(Mote mote) {
this.mote = (MicaZMote) mote;
this.moteMem = (AvrMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
if (moteMem.variableExists("node_id")) {
contikiID = true;
int addr = moteMem.getVariableAddress("node_id");
moteMem.insertWatch(new Watch() {
public void fireAfterRead(State arg0, int arg1, byte arg2) {
System.out.println("Read from node_id: " + arg2);
int addr = (int) moteMem.getVariableAddress("node_id");
moteMem.addVarMonitor(
SegmentMonitor.EventType.READWRITE,
"node_id",
new SegmentMonitor() {
@Override
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
if (type == EventType.READ) {
System.out.println("Read from node_id.");
} else {
System.out.println("Writing to node_id.");
}
}
public void fireAfterWrite(State arg0, int arg1, byte arg2) {
}
public void fireBeforeRead(State arg0, int arg1) {
}
public void fireBeforeWrite(State arg0, int arg1, byte arg2) {
System.out.println("Writing to node_id: " + arg2);
}}, addr);
});
}
if (moteMem.variableExists("TOS_NODE_ID")) {

View file

@ -45,12 +45,12 @@ import org.contikios.cooja.Cooja;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.Watchpoint;
import org.contikios.cooja.WatchpointMote;
import org.contikios.cooja.interfaces.IPAddress;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.motes.AbstractEmulatedMote;
import org.contikios.cooja.mspmote.interfaces.Msp802154Radio;
import org.contikios.cooja.mspmote.interfaces.MspSerial;
@ -185,12 +185,13 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
myCpu = cpu;
}
public MoteMemory getMemory() {
@Override
public MemoryInterface getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
myMemory = (MspMoteMemory) memory;
public void setMemory(MspMoteMemory memory) {
myMemory = memory;
}
/**

View file

@ -1,4 +1,5 @@
/*
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
* Copyright (c) 2007, Swedish Institute of Computer Science. All rights
* reserved.
*
@ -28,21 +29,27 @@
package org.contikios.cooja.mspmote;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.contikios.cooja.AddressMemory;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
import org.contikios.cooja.mote.memory.MemoryLayout;
import se.sics.mspsim.core.MSP430;
import se.sics.mspsim.core.Memory.AccessMode;
import se.sics.mspsim.core.Memory.AccessType;
import se.sics.mspsim.util.MapEntry;
public class MspMoteMemory implements MoteMemory, AddressMemory {
public class MspMoteMemory implements MemoryInterface {
private static Logger logger = Logger.getLogger(MspMoteMemory.class);
private final ArrayList<MapEntry> mapEntries;
private final MemoryLayout memLayout;
private final MSP430 cpu;
@ -56,143 +63,85 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
}
this.cpu = cpu;
memLayout = new MemoryLayout(ByteOrder.LITTLE_ENDIAN, MemoryLayout.ARCH_16BIT, 2);
}
public String[] getVariableNames() {
String[] names = new String[mapEntries.size()];
for (int i = 0; i < mapEntries.size(); i++) {
names[i] = mapEntries.get(i).getName();
}
return names;
@Override
public int getTotalSize() {
return cpu.memory.length;
}
private MapEntry getMapEntry(String varName) throws UnknownVariableException {
for (MapEntry entry: mapEntries) {
if (entry.getName().equals(varName)) {
return entry;
}
}
throw new UnknownVariableException(varName);
@Override
public byte[] getMemory() throws MoteMemoryException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public int getVariableAddress(String varName) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
return entry.getAddress();
}
public int getIntegerLength() {
return 2;
}
public void clearMemory() {
logger.fatal("clearMemory() not implemented");
}
public byte[] getMemorySegment(int address, int size) {
@Override
public byte[] getMemorySegment(long address, int size) {
int[] memInts = new int[size];
System.arraycopy(cpu.memory, address, memInts, 0, size);
System.arraycopy(cpu.memory, (int) address, memInts, 0, size);
/* Convert to byte array */
byte[] memBytes = new byte[size];
for (int i=0; i < size; i++) {
for (int i = 0; i < size; i++) {
memBytes[i] = (byte) memInts[i];
}
return memBytes;
}
public void setMemorySegment(int address, byte[] data) {
@Override
public void setMemorySegment(long address, byte[] data) {
/* Convert to int array */
int[] memInts = new int[data.length];
for (int i=0; i < data.length; i++) {
for (int i = 0; i < data.length; i++) {
memInts[i] = data[i];
}
System.arraycopy(memInts, 0, cpu.memory, address, data.length);
System.arraycopy(memInts, 0, cpu.memory, (int) address, data.length);
}
public int getTotalSize() {
return cpu.memory.length;
@Override
public void clearMemory() {
Arrays.fill(cpu.memory, 0);
}
public boolean variableExists(String varName) {
for (MapEntry entry: mapEntries) {
if (entry.getName().equals(varName)) {
return true;
@Override
public long getStartAddr() {
return 0;// XXXX
}
@Override
public Map<String, Symbol> getSymbolMap() {
Map<String, Symbol> vars = new HashMap<>();
for (MapEntry entry : mapEntries) {
if (entry.getType() != MapEntry.TYPE.variable) {
continue;
}
vars.put(entry.getName(), new Symbol(
Symbol.Type.VARIABLE,
entry.getName(),
entry.getAddress(),
entry.getSize()));
}
return false;
return vars;
}
/* TODO Check correct variable size in below methods */
public int getIntValueOf(String varName) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
byte[] varData = getMemorySegment(varAddr, 2);
return parseInt(varData);
@Override
public MemoryLayout getLayout() {
return memLayout;
}
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
private final ArrayList<MemoryCPUMonitor> cpuMonitorArray = new ArrayList<>();
int newValToSet = Integer.reverseBytes(newVal);
// Create byte array
int pos = 0;
byte[] varData = new byte[2];
varData[pos++] = (byte) ((newValToSet & 0xFF000000) >> 24);
varData[pos++] = (byte) ((newValToSet & 0xFF0000) >> 16);
setMemorySegment(varAddr, varData);
}
public byte getByteValueOf(String varName) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
byte[] varData = getMemorySegment(varAddr, 1);
return varData[0];
}
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
byte[] varData = new byte[1];
varData[0] = newVal;
setMemorySegment(varAddr, varData);
}
public byte[] getByteArray(String varName, int length) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
return getMemorySegment(varAddr, length);
}
public void setByteArray(String varName, byte[] data) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
setMemorySegment(varAddr, data);
}
private ArrayList<MemoryCPUMonitor> cpuMonitorArray = new ArrayList<MemoryCPUMonitor>();
class MemoryCPUMonitor extends se.sics.mspsim.core.MemoryMonitor.Adapter {
public final MemoryMonitor mm;
public final SegmentMonitor mm;
public final int address;
public final int size;
public MemoryCPUMonitor(MemoryMonitor mm, int address, int size) {
public MemoryCPUMonitor(SegmentMonitor mm, int address, int size) {
this.mm = mm;
this.address = address;
this.size = size;
@ -200,49 +149,39 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
@Override
public void notifyReadAfter(int address, AccessMode mode, AccessType type) {
mm.memoryChanged(MspMoteMemory.this, MemoryEventType.READ, address);
mm.memoryChanged(MspMoteMemory.this, EventType.READ, address);
}
@Override
public void notifyWriteAfter(int dstAddress, int data, AccessMode mode) {
mm.memoryChanged(MspMoteMemory.this, MemoryEventType.WRITE, dstAddress);
mm.memoryChanged(MspMoteMemory.this, EventType.WRITE, dstAddress);
}
}
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, address, size);
@Override
public boolean addSegmentMonitor(EventType type, long address, int size, SegmentMonitor mm) {
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, (int) address, size);
cpuMonitorArray.add(t);
for (int a = address; a < address+size; a++) {
for (int a = (int) address; a < address + size; a++) {
cpu.addWatchPoint(a, t);
}
return true;
}
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
for (MemoryCPUMonitor mcm: cpuMonitorArray) {
@Override
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor mm) {
for (MemoryCPUMonitor mcm : cpuMonitorArray) {
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
continue;
}
for (int a = address; a < address+size; a++) {
for (int a = (int) address; a < (int) address + size; a++) {
cpu.removeWatchPoint(a, mcm);
}
cpuMonitorArray.remove(mcm);
break;
return true;
}
}
public int parseInt(byte[] memorySegment) {
if (memorySegment.length < 2) {
return -1;
}
int retVal = 0;
int pos = 0;
retVal += ((memorySegment[pos++] & 0xFF)) << 8;
retVal += ((memorySegment[pos++] & 0xFF)) << 0;
return Integer.reverseBytes(retVal) >> 16;
return false;
}
}

View file

@ -40,8 +40,9 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote;
import org.contikios.cooja.interfaces.Log;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.VarMemory;
import org.contikios.cooja.mspmote.MspMote;
import org.contikios.cooja.mspmote.MspMoteMemory;
import se.sics.mspsim.core.Memory;
import se.sics.mspsim.core.MemoryMonitor;
@ -64,24 +65,24 @@ public class MspDebugOutput extends Log {
private final static String CONTIKI_POINTER = "cooja_debug_ptr";
private MspMote mote;
private MspMoteMemory mem;
private VarMemory mem;
private String lastLog = null;
private MemoryMonitor memoryMonitor = null;
public MspDebugOutput(Mote mote) {
this.mote = (MspMote) mote;
this.mem = (MspMoteMemory) this.mote.getMemory();
this.mem = new VarMemory(this.mote.getMemory());
if (!mem.variableExists(CONTIKI_POINTER)) {
/* Disabled */
return;
}
this.mote.getCPU().addWatchPoint(mem.getVariableAddress(CONTIKI_POINTER),
this.mote.getCPU().addWatchPoint((int) mem.getVariableAddress(CONTIKI_POINTER),
memoryMonitor = new MemoryMonitor.Adapter() {
@Override
public void notifyWriteAfter(int adr, int data, Memory.AccessMode mode) {
String msg = extractString(mem, data);
String msg = extractString(MspDebugOutput.this.mote.getMemory(), data);
if (msg != null && msg.length() > 0) {
lastLog = "DEBUG: " + msg;
setChanged();
@ -91,7 +92,7 @@ public class MspDebugOutput extends Log {
});
}
private String extractString(MspMoteMemory mem, int address) {
private String extractString(MemoryInterface mem, int address) {
StringBuilder sb = new StringBuilder();
while (true) {
byte[] data = mem.getMemorySegment(address, 8);
@ -136,7 +137,7 @@ public class MspDebugOutput extends Log {
super.removed();
if (memoryMonitor != null) {
mote.getCPU().removeWatchPoint(mem.getVariableAddress(CONTIKI_POINTER), memoryMonitor);
mote.getCPU().removeWatchPoint((int) mem.getVariableAddress(CONTIKI_POINTER), memoryMonitor);
}
}
}

View file

@ -39,8 +39,8 @@ import org.apache.log4j.Logger;
import org.contikios.cooja.Mote;
import org.contikios.cooja.interfaces.MoteID;
import org.contikios.cooja.mote.memory.VarMemory;
import org.contikios.cooja.mspmote.MspMote;
import org.contikios.cooja.mspmote.MspMoteMemory;
import se.sics.mspsim.core.Memory;
import se.sics.mspsim.core.MemoryMonitor;
@ -53,7 +53,7 @@ public class MspMoteID extends MoteID {
private static Logger logger = Logger.getLogger(MspMoteID.class);
private MspMote mote;
private MspMoteMemory moteMem = null;
private VarMemory moteMem = null;
private boolean writeFlashHeader = true;
private int moteID = -1;
@ -69,7 +69,7 @@ public class MspMoteID extends MoteID {
*/
public MspMoteID(Mote m) {
this.mote = (MspMote) m;
this.moteMem = (MspMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public int getMoteID() {
@ -144,7 +144,7 @@ public class MspMoteID extends MoteID {
byte[] id = new byte[2];
id[0] = (byte) (moteID & 0xff);
id[1] = (byte) ((moteID >> 8) & 0xff);
moteMem.setMemorySegment(dstAddress & ~1, id);
mote.getMemory().setMemorySegment(dstAddress & ~1, id);
}
};
@ -201,7 +201,7 @@ public class MspMoteID extends MoteID {
private void addMonitor(String variable, MemoryMonitor monitor) {
if (moteMem.variableExists(variable)) {
int address = moteMem.getVariableAddress(variable);
int address = (int) moteMem.getVariableAddress(variable);
if ((address & 1) != 0) {
// Variable can not be a word - must be a byte
} else {
@ -213,7 +213,7 @@ public class MspMoteID extends MoteID {
private void removeMonitor(String variable, MemoryMonitor monitor) {
if (moteMem.variableExists(variable)) {
int address = moteMem.getVariableAddress(variable);
int address = (int) moteMem.getVariableAddress(variable);
mote.getCPU().removeWatchPoint(address, monitor);
mote.getCPU().removeWatchPoint(address + 1, monitor);
}

View file

@ -25,7 +25,6 @@ PATH_JAVAC = javac
DEFAULT_PROJECTDIRS = [CONTIKI_DIR]/tools/cooja/apps/mrm;[CONTIKI_DIR]/tools/cooja/apps/mspsim;[CONTIKI_DIR]/tools/cooja/apps/avrora;[CONTIKI_DIR]/tools/cooja/apps/serial_socket;[CONTIKI_DIR]/tools/cooja/apps/collect-view;[CONTIKI_DIR]/tools/cooja/apps/powertracker
PARSE_WITH_COMMAND=false
PARSE_COMMAND=nm -a $(LIBFILE)
MAPFILE_DATA_START = ^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
MAPFILE_DATA_SIZE = ^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$
MAPFILE_BSS_START = ^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
@ -35,11 +34,19 @@ MAPFILE_VAR_ADDRESS_1 = ^[ \t]*0x([0-9A-Fa-f]*)[ \t]*
MAPFILE_VAR_ADDRESS_2 = [ \t]*$
MAPFILE_VAR_SIZE_1 = ^
MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$
COMMAND_VAR_NAME_ADDRESS = ^([0-9A-Fa-f][0-9A-Fa-f]*)[ \t][^Tt][ \t]([^ ._][^ ]*)
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]d[ \t].data$
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_edata$
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]A[ \t]__bss_start$
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_end$
PARSE_COMMAND=nm -aP $(LIBFILE)
COMMAND_VAR_NAME_ADDRESS_SIZE = ^([^.].*?) <SECTION> ([0-9a-fA-F]+) ([0-9a-fA-F])*
COMMAND_VAR_SEC_DATA = [DdGg]
COMMAND_VAR_SEC_BSS = [Bb]
COMMAND_VAR_SEC_COMMON = [C]
COMMAND_VAR_SEC_READONLY = [Rr]
COMMAND_DATA_START = ^.data[ \t]d[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_DATA_END = ^_edata[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_BSS_START = ^__bss_start[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_BSS_END = ^_end[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_READONLY_START = ^.rodata[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_READONLY_END = ^.eh_frame_hdr[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
VISUALIZER_DEFAULT_SKINS=\
org.contikios.cooja.plugins.skins.IDVisualizerSkin;\

View file

@ -6,8 +6,14 @@ COMPILER_ARGS=-D__int64\="long long" -Wall -I'$(JAVA_HOME)/include' -I'$(JAVA_HO
LINK_COMMAND_1 = mingw32-gcc -shared -Wl,-Map=$(MAPFILE) -Wl,--add-stdcall-alias -o $(LIBFILE)
LINK_COMMAND_2 = -L/usr/lib/mingw
PARSE_WITH_COMMAND = true
PARSE_COMMAND=nm -n -C $(LIBFILE)
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_start__$
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_end__$
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_start__$
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_end__$
# Hack: nm with arguments -S --size-sort does not display __data_start symbols
PARSE_COMMAND=sh -c "/bin/nm -aP --size-sort -S $(LIBFILE) && /bin/nm -aP $(LIBFILE)"
COMMAND_VAR_NAME_ADDRESS_SIZE = ^[_]([^.].*?)[ \t]<SECTION>[ \t]([0-9a-fA-F]+)[ \t]([0-9a-fA-F]+)
COMMAND_DATA_START = ^__data_start__[ \t]D[ \t]([0-9A-Fa-f]*)
COMMAND_DATA_END = ^__data_end__[ \t]D[ \t]([0-9A-Fa-f]*)
COMMAND_BSS_START = ^__bss_start__[ \t]B[ \t]([0-9A-Fa-f]*)
COMMAND_BSS_END = ^__bss_end__[ \t]B[ \t]([0-9A-Fa-f]*)
COMMAND_READONLY_START = ^.rodata[ \t]r[ \t]([0-9A-Fa-f]*)
COMMAND_READONLY_END = ^.eh_frame_hdr[ \t]r[ \t]([0-9A-Fa-f]*)

View file

@ -18,7 +18,7 @@
</appender>
<root>
<priority value="debug"/>
<priority value="info"/>
<appender-ref ref="logfile"/>
<appender-ref ref="stdout"/>
</root>

View file

@ -1,124 +0,0 @@
/*
* Copyright (c) 2006, Swedish Institute of Computer Science. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of the
* Institute nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.contikios.cooja;
public interface AddressMemory {
/**
* @return All variable names known and residing in this memory
*/
public String[] getVariableNames();
/**
* Checks if given variable exists in memory.
*
* @param varName Variable name
* @return True if variable exists, false otherwise
*/
public boolean variableExists(String varName);
/**
* Returns address of variable with given name.
*
* @param varName Variable name
* @return Variable address
* @throws UnknownVariableException Variable does not exist
*/
public int getVariableAddress(String varName) throws UnknownVariableException;
/**
* Returns a value of the byte variable with the given name.
*
* @param varName Name of byte variable
* @return Value of byte variable
* @throws UnknownVariableException Variable does not exist
*/
public byte getByteValueOf(String varName) throws UnknownVariableException;
/**
* Set byte value of variable with given name.
*
* @param varName Name of byte variable
* @param newVal New value of byte
* @throws UnknownVariableException Variable does not exist
*/
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException;
/**
* Returns byte array of given length and with the given name.
*
* @param varName Name of array
* @param length Length of array
* @return Data of array
* @throws UnknownVariableException Variable does not exist
*/
public byte[] getByteArray(String varName, int length) throws UnknownVariableException;
/**
* Set byte array of the variable with the given name.
*
* @param varName Name of array
* @param data New data of array
* @throws UnknownVariableException Variable does not exist
*/
public void setByteArray(String varName, byte[] data) throws UnknownVariableException;
/**
* @return Number of bytes in an integer
*/
public int getIntegerLength();
/**
* Returns a value of the integer variable with the given name.
*
* @param varName Name of integer variable
* @return Value of integer variable
* @throws UnknownVariableException Variable does not exist
*/
public int getIntValueOf(String varName) throws UnknownVariableException;
/**
* Set integer value of variable with given name.
*
* @param varName Name of integer variable
* @param newVal New integer value
* @throws UnknownVariableException Variable does not exist
*/
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException;
/**
* Unknown variable name exception.
*/
public class UnknownVariableException extends RuntimeException {
public UnknownVariableException(String varName) {
super("Unknown variable name: " + varName);
}
}
}

View file

@ -274,7 +274,7 @@ public class Cooja extends Observable {
"MAPFILE_VAR_SIZE_1", "MAPFILE_VAR_SIZE_2",
"PARSE_COMMAND",
"COMMAND_VAR_NAME_ADDRESS",
"COMMAND_VAR_NAME_ADDRESS_SIZE",
"COMMAND_DATA_START", "COMMAND_DATA_END",
"COMMAND_BSS_START", "COMMAND_BSS_END",
"COMMAND_COMMON_START", "COMMAND_COMMON_END",

View file

@ -28,6 +28,7 @@
package org.contikios.cooja;
import java.util.Collection;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.jdom.Element;
@ -63,7 +64,7 @@ public interface Mote {
* @see #setMemory(MoteMemory)
* @return Mote memory
*/
public MoteMemory getMemory();
public MemoryInterface getMemory();
/**
* Returns mote type.

View file

@ -1,90 +0,0 @@
/*
* Copyright (c) 2006, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package org.contikios.cooja;
/**
* This interface represents a mote memory.
*
* Mote memory is represented by byte arrays and this
* interface provides a few of basic operations.
*
* Note that this memory internally may consist of several
* different memory sections, not covering the entire range
* between the start address and the end address of this memory.
*
* @see org.contikios.cooja.SectionMoteMemory
* @author Fredrik Osterlind
*/
public interface MoteMemory extends AddressMemory {
/**
* Clears the entire memory.
*/
public void clearMemory();
/**
* Returns a memory segment.
*
* @param address Start address of memory segment
* @param size Size of memory segment
* @return Memory segment or null if segment not available
*/
public byte[] getMemorySegment(int address, int size);
/**
* Sets a memory segment.
*
* @param address Start address of memory segment
* @param data Data
*/
public void setMemorySegment(int address, byte[] data);
/**
* Returns the sum of all byte array sizes in this memory.
* This is not neccessarily the the same as the total memory range,
* since the entire memory range may not be handled by this memory.
*
* @return Total size
*/
public int getTotalSize();
public abstract int parseInt(byte[] memorySegment);
public enum MemoryEventType { READ, WRITE };
public interface MemoryMonitor {
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address);
}
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm);
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm);
}

View file

@ -1,431 +0,0 @@
/*
* Copyright (c) 2006, Swedish Institute of Computer Science. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of the
* Institute nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.contikios.cooja;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import org.apache.log4j.Logger;
/**
* Represents a mote memory consisting of non-overlapping memory sections with
* symbol addresses.
* <p>
* When an non-existing memory segment is written, a new section is automatically
* created for this segment.
* <p>
*
* @author Fredrik Osterlind
*/
public class SectionMoteMemory implements MoteMemory, AddressMemory {
private static Logger logger = Logger.getLogger(SectionMoteMemory.class);
private ArrayList<MoteMemorySection> sections = new ArrayList<MoteMemorySection>();
/* readonly memory is never written to Contiki core, and is used to provide
* access to, for instance, strings */
private ArrayList<MoteMemorySection> readonlySections = new ArrayList<MoteMemorySection>();
private final HashMap<String, Integer> addresses;
/* used to map Cooja's address space to native (Contiki's) addresses */
private final int offset;
/**
* @param addresses Symbol addresses
* @param offset Offset for internally used addresses
*/
public SectionMoteMemory(HashMap<String, Integer> addresses, int offset) {
this.addresses = addresses;
this.offset = offset;
}
public String[] getVariableNames() {
return addresses.keySet().toArray(new String[0]);
}
public int getVariableAddress(String varName) throws UnknownVariableException {
/* Cooja address space */
if (!addresses.containsKey(varName)) {
throw new UnknownVariableException(varName);
}
return addresses.get(varName).intValue() + offset;
}
public int getIntegerLength() {
return 4;
}
public void clearMemory() {
sections.clear();
}
public byte[] getMemorySegment(int address, int size) {
/* Cooja address space */
address -= offset;
for (MoteMemorySection section : sections) {
if (section.includesAddr(address)
&& section.includesAddr(address + size - 1)) {
return section.getMemorySegment(address, size);
}
}
/* Check if in readonly section */
for (MoteMemorySection section : readonlySections) {
if (section.includesAddr(address)
&& section.includesAddr(address + size - 1)) {
return section.getMemorySegment(address, size);
}
}
return null;
}
public void setMemorySegmentNative(int address, byte[] data) {
setMemorySegment(address+offset, data);
}
public void setMemorySegment(int address, byte[] data) {
/* Cooja address space */
address -= offset;
/* TODO XXX Sections may overlap */
for (MoteMemorySection section : sections) {
if (section.includesAddr(address)
&& section.includesAddr(address + data.length - 1)) {
section.setMemorySegment(address, data);
return;
}
}
sections.add(new MoteMemorySection(address, data));
}
public void setReadonlyMemorySegment(int address, byte[] data) {
/* Cooja address space */
address -= offset;
readonlySections.add(new MoteMemorySection(address, data));
}
public int getTotalSize() {
int totalSize = 0;
for (MoteMemorySection section : sections) {
totalSize += section.getSize();
}
return totalSize;
}
/**
* Returns the total number of sections in this memory.
*
* @return Number of sections
*/
public int getNumberOfSections() {
return sections.size();
}
/**
* Get start address of given section in native address space.
*
* @param sectionNr Section position
* @return Start address of section
*/
public int getSectionNativeAddress(int sectionNr) {
if (sectionNr >= sections.size()) {
return -1;
}
return sections.get(sectionNr).getStartAddr();
}
/**
* Get size of section at given position.
*
* @param sectionNr Section position
* @return Size of section
*/
public int getSizeOfSection(int sectionNr) {
if (sectionNr >= sections.size()) {
return -1;
}
return sections.get(sectionNr).getSize();
}
/**
* Get data of section at given position.
*
* @param sectionNr Section position
* @return Data at section
*/
public byte[] getDataOfSection(int sectionNr) {
if (sectionNr >= sections.size()) {
return null;
}
return sections.get(sectionNr).getData();
}
public boolean variableExists(String varName) {
return addresses.containsKey(varName);
}
public int getIntValueOf(String varName) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
byte[] varData = getMemorySegment(varAddr, 4);
if (varData == null) {
throw new UnknownVariableException(varName);
}
return parseInt(varData);
}
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
/* TODO Correct for all platforms? */
int newValToSet = Integer.reverseBytes(newVal);
int pos = 0;
byte[] varData = new byte[4];
varData[pos++] = (byte) ((newValToSet & 0xFF000000) >> 24);
varData[pos++] = (byte) ((newValToSet & 0xFF0000) >> 16);
varData[pos++] = (byte) ((newValToSet & 0xFF00) >> 8);
varData[pos++] = (byte) ((newValToSet & 0xFF) >> 0);
setMemorySegment(varAddr, varData);
}
public byte getByteValueOf(String varName) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
byte[] varData = getMemorySegment(varAddr, 1);
if (varData == null) {
throw new UnknownVariableException(varName);
}
return varData[0];
}
public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
byte[] varData = new byte[1];
varData[0] = newVal;
setMemorySegment(varAddr, varData);
}
public byte[] getByteArray(String varName, int length) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
return getMemorySegment(varAddr, length);
}
public void setByteArray(String varName, byte[] data) throws UnknownVariableException {
int varAddr = getVariableAddress(varName);
setMemorySegment(varAddr, data);
}
/**
* A memory section contains a byte array and a start address.
*
* @author Fredrik Osterlind
*/
private static class MoteMemorySection {
private byte[] data = null;
private final int startAddr;
/**
* Create a new memory section.
*
* @param startAddr
* Start address of section
* @param data
* Data of section
*/
public MoteMemorySection(int startAddr, byte[] data) {
this.startAddr = startAddr;
this.data = data;
}
/**
* Returns start address of this memory section.
*
* @return Start address
*/
public int getStartAddr() {
return startAddr;
}
/**
* Returns size of this memory section.
*
* @return Size
*/
public int getSize() {
return data.length;
}
/**
* Returns the entire byte array which defines this section.
*
* @return Byte array
*/
public byte[] getData() {
return data;
}
/**
* True if given address is part of this memory section.
*
* @param addr
* Address
* @return True if given address is part of this memory section, false
* otherwise
*/
public boolean includesAddr(int addr) {
if (data == null) {
return false;
}
return (addr >= startAddr && addr < (startAddr + data.length));
}
/**
* Returns memory segment.
*
* @param addr
* Start address of memory segment
* @param size
* Size of memory segment
* @return Memory segment
*/
public byte[] getMemorySegment(int addr, int size) {
byte[] ret = new byte[size];
System.arraycopy(data, addr - startAddr, ret, 0, size);
return ret;
}
/**
* Sets a memory segment.
*
* @param addr
* Start of memory segment
* @param data
* Data of memory segment
*/
public void setMemorySegment(int addr, byte[] data) {
System.arraycopy(data, 0, this.data, addr - startAddr, data.length);
}
public MoteMemorySection clone() {
byte[] dataClone = new byte[data.length];
System.arraycopy(data, 0, dataClone, 0, data.length);
MoteMemorySection clone = new MoteMemorySection(startAddr, dataClone);
return clone;
}
}
public SectionMoteMemory clone() {
ArrayList<MoteMemorySection> sectionsClone = new ArrayList<MoteMemorySection>();
for (MoteMemorySection section : sections) {
sectionsClone.add(section.clone());
}
SectionMoteMemory clone = new SectionMoteMemory(addresses, offset);
clone.sections = sectionsClone;
clone.readonlySections = readonlySections;
return clone;
}
private ArrayList<PolledMemorySegments> polledMemories = new ArrayList<PolledMemorySegments>();
public void pollForMemoryChanges() {
for (PolledMemorySegments mem: polledMemories.toArray(new PolledMemorySegments[0])) {
mem.notifyIfChanged();
}
}
private class PolledMemorySegments {
public final MemoryMonitor mm;
public final int address;
public final int size;
private byte[] oldMem;
public PolledMemorySegments(MemoryMonitor mm, int address, int size) {
this.mm = mm;
this.address = address;
this.size = size;
oldMem = getMemorySegment(address, size);
}
private void notifyIfChanged() {
byte[] newMem = getMemorySegment(address, size);
if (Arrays.equals(oldMem, newMem)) {
return;
}
mm.memoryChanged(SectionMoteMemory.this, MemoryEventType.WRITE, address);
oldMem = newMem;
}
}
public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) {
PolledMemorySegments t = new PolledMemorySegments(mm, address, size);
polledMemories.add(t);
return true;
}
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) {
for (PolledMemorySegments mcm: polledMemories) {
if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
continue;
}
polledMemories.remove(mcm);
break;
}
}
public int parseInt(byte[] memorySegment) {
int retVal = 0;
int pos = 0;
retVal += ((memorySegment[pos++] & 0xFF)) << 24;
retVal += ((memorySegment[pos++] & 0xFF)) << 16;
retVal += ((memorySegment[pos++] & 0xFF)) << 8;
retVal += ((memorySegment[pos++] & 0xFF)) << 0;
retVal = Integer.reverseBytes(retVal);
return retVal;
}
}

View file

@ -38,10 +38,10 @@ import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.motes.AbstractWakeupMote;
/**
@ -83,10 +83,12 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
requestImmediateWakeup();
}
@Override
public int getID() {
return myInterfaceHandler.getMoteID().getMoteID();
}
@Override
public MoteInterfaceHandler getInterfaces() {
return myInterfaceHandler;
}
@ -95,14 +97,16 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
myInterfaceHandler = newInterfaces;
}
public MoteMemory getMemory() {
@Override
public MemoryInterface getMemory() {
return myMemory;
}
public void setMemory(MoteMemory memory) {
myMemory = (SectionMoteMemory) memory;
public void setMemory(SectionMoteMemory memory) {
myMemory = memory;
}
@Override
public MoteType getType() {
return myType;
}
@ -121,6 +125,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
*
* @param simTime Current simulation time
*/
@Override
public void execute(long simTime) {
/* Poll mote interfaces */
@ -154,6 +159,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
*
* @return Current simulation config
*/
@Override
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element;
@ -173,6 +179,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
return config;
}
@Override
public boolean setConfigXML(Simulation simulation, Collection<Element> configXML, boolean visAvailable) {
setSimulation(simulation);
myMemory = myType.createInitialMemory();
@ -212,6 +219,7 @@ public class ContikiMote extends AbstractWakeupMote implements Mote {
return true;
}
@Override
public String toString() {
return "Contiki " + getID();
}

View file

@ -44,10 +44,11 @@ import org.apache.log4j.Logger;
import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.Beeper;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Beeper mote interface.
@ -70,7 +71,7 @@ import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
*/
public class ContikiBeeper extends Beeper implements ContikiMoteInterface, PolledAfterActiveTicks {
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
private static Logger logger = Logger.getLogger(ContikiBeeper.class);
/**
@ -83,7 +84,7 @@ public class ContikiBeeper extends Beeper implements ContikiMoteInterface, Polle
*/
public ContikiBeeper(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public boolean isBeeping() {

View file

@ -40,6 +40,7 @@ import org.contikios.cooja.*;
import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.Button;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Button mote interface.
@ -62,7 +63,7 @@ import org.contikios.cooja.interfaces.Button;
* @author Fredrik Osterlind
*/
public class ContikiButton extends Button implements ContikiMoteInterface {
private SectionMoteMemory moteMem;
private VarMemory moteMem;
private ContikiMote mote;
private static Logger logger = Logger.getLogger(ContikiButton.class);
@ -76,7 +77,7 @@ public class ContikiButton extends Button implements ContikiMoteInterface {
*/
public ContikiButton(Mote mote) {
this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -43,6 +43,7 @@ import org.jdom.Element;
import org.contikios.cooja.*;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Contiki FileSystem (CFS) interface (such as external flash).
@ -71,7 +72,7 @@ public class ContikiCFS extends MoteInterface implements ContikiMoteInterface, P
public int FILESYSTEM_SIZE = 4000; /* Configure CFS size here and in cfs-cooja.c */
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
private int lastRead = 0;
private int lastWritten = 0;
@ -85,7 +86,7 @@ public class ContikiCFS extends MoteInterface implements ContikiMoteInterface, P
*/
public ContikiCFS(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -37,13 +37,14 @@ import org.apache.log4j.Logger;
import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.Clock;
import org.contikios.cooja.interfaces.PolledAfterAllTicks;
import org.contikios.cooja.interfaces.PolledBeforeActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Clock mote interface. Controls Contiki time.
@ -71,7 +72,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
private Simulation simulation;
private ContikiMote mote;
private SectionMoteMemory moteMem;
private VarMemory moteMem;
private long moteTime; /* Microseconds */
private long timeDrift; /* Microseconds */
@ -85,7 +86,7 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
public ContikiClock(Mote mote) {
this.simulation = mote.getSimulation();
this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
timeDrift = 0;
moteTime = 0;
}

View file

@ -45,6 +45,7 @@ import org.jdom.Element;
import org.contikios.cooja.*;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Contiki EEPROM interface
@ -73,7 +74,7 @@ public class ContikiEEPROM extends MoteInterface implements ContikiMoteInterface
public int EEPROM_SIZE = 1024; /* Configure EEPROM size here and in eeprom.c. Should really be multiple of 16 */
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
private int lastRead = 0;
private int lastWritten = 0;
@ -87,7 +88,7 @@ public class ContikiEEPROM extends MoteInterface implements ContikiMoteInterface
*/
public ContikiEEPROM(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -40,6 +40,7 @@ import org.contikios.cooja.*;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.LED;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* LEDs mote interface.
@ -64,7 +65,7 @@ public class ContikiLED extends LED implements ContikiMoteInterface, PolledAfter
private static Logger logger = Logger.getLogger(ContikiLED.class);
private Mote mote = null;
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
private byte currentLedValue = 0;
private static final byte LEDS_GREEN = 1;
@ -91,7 +92,7 @@ public class ContikiLED extends LED implements ContikiMoteInterface, PolledAfter
*/
public ContikiLED(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -38,6 +38,7 @@ import org.jdom.Element;
import org.contikios.cooja.*;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.MoteID;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Mote ID interface: 'node_id'.
@ -60,7 +61,7 @@ import org.contikios.cooja.interfaces.MoteID;
* @author Fredrik Osterlind
*/
public class ContikiMoteID extends MoteID implements ContikiMoteInterface {
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
private static Logger logger = Logger.getLogger(ContikiMoteID.class);
private int moteID = 0;
@ -77,7 +78,7 @@ public class ContikiMoteID extends MoteID implements ContikiMoteInterface {
*/
public ContikiMoteID(Mote mote) {
this.mote = mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -37,10 +37,11 @@ import javax.swing.JButton;
import javax.swing.JPanel;
import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.PIR;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Passive IR sensor mote interface.
@ -65,7 +66,7 @@ import org.contikios.cooja.interfaces.PIR;
public class ContikiPIR extends PIR implements ContikiMoteInterface {
private ContikiMote mote;
private SectionMoteMemory moteMem;
private VarMemory moteMem;
/**
* Creates an interface to the PIR at mote.
@ -77,7 +78,7 @@ public class ContikiPIR extends PIR implements ContikiMoteInterface {
*/
public ContikiPIR(Mote mote) {
this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -38,6 +38,7 @@ import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.dialogs.SerialUI;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Contiki mote serial port and log interfaces.
@ -68,7 +69,7 @@ public class ContikiRS232 extends SerialUI implements ContikiMoteInterface, Poll
private static Logger logger = Logger.getLogger(ContikiRS232.class);
private ContikiMote mote = null;
private SectionMoteMemory moteMem = null;
private VarMemory moteMem = null;
static final int SERIAL_BUF_SIZE = 1024; /* rs232.c:40 */
@ -82,7 +83,7 @@ public class ContikiRS232 extends SerialUI implements ContikiMoteInterface, Poll
*/
public ContikiRS232(Mote mote) {
this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -39,13 +39,14 @@ import org.jdom.Element;
import org.contikios.cooja.COOJARadioPacket;
import org.contikios.cooja.Mote;
import org.contikios.cooja.RadioPacket;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.interfaces.Position;
import org.contikios.cooja.interfaces.Radio;
import org.contikios.cooja.mote.memory.VarMemory;
import org.contikios.cooja.radiomediums.UDGM;
/**
@ -89,7 +90,7 @@ import org.contikios.cooja.radiomediums.UDGM;
public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledAfterActiveTicks {
private ContikiMote mote;
private SectionMoteMemory myMoteMemory;
private VarMemory myMoteMemory;
private static Logger logger = Logger.getLogger(ContikiRadio.class);
@ -132,7 +133,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA
ContikiRadio.class, "RADIO_TRANSMISSION_RATE_kbps");
this.mote = (ContikiMote) mote;
this.myMoteMemory = (SectionMoteMemory) mote.getMemory();
this.myMoteMemory = new VarMemory(mote.getMemory());
radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1;
}

View file

@ -39,9 +39,10 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.contikimote.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Vibration sensor mote interface.
@ -67,7 +68,7 @@ import org.contikios.cooja.contikimote.ContikiMoteInterface;
public class ContikiVib extends MoteInterface implements ContikiMoteInterface {
private ContikiMote mote;
private SectionMoteMemory moteMem;
private VarMemory moteMem;
/**
* Creates an interface to the vibration sensor at mote.
@ -79,7 +80,7 @@ public class ContikiVib extends MoteInterface implements ContikiMoteInterface {
*/
public ContikiVib(Mote mote) {
this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory();
this.moteMem = new VarMemory(mote.getMemory());
}
public static String[] getCoreInterfaceDependencies() {

View file

@ -66,8 +66,11 @@ import javax.swing.JScrollPane;
import org.contikios.cooja.CoreComm;
import org.contikios.cooja.Cooja;
import org.contikios.cooja.MoteType.MoteTypeCreationException;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.contikimote.ContikiMoteType;
import org.contikios.cooja.contikimote.ContikiMoteType.SectionParser;
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
import org.contikios.cooja.mote.memory.VarMemory;
/* TODO Test common section */
/* TODO Test readonly section */
@ -141,7 +144,7 @@ public class ConfigurationWizard extends JDialog {
private static File cLibraryFile;
private static String javaLibraryName;
private static CoreComm javaLibrary;
private static HashMap<String, Integer> addresses;
private static HashMap<String, Symbol> addresses;
private static int relDataSectionAddr;
private static int dataSectionSize;
private static int relBssSectionAddr;
@ -757,18 +760,28 @@ public class ConfigurationWizard extends JDialog {
}
testOutput.addMessage("### Parsing map file data for addresses");
addresses = new HashMap<String, Integer>();
boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
if (!parseOK) {
testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
return false;
}
addresses = new HashMap<String, Symbol>();
// boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
// if (!parseOK) {
// testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
// return false;
// }
testOutput.addMessage("### Validating section addresses");
relDataSectionAddr = ContikiMoteType.parseMapDataSectionAddr(mapData);
dataSectionSize = ContikiMoteType.parseMapDataSectionSize(mapData);
relBssSectionAddr = ContikiMoteType.parseMapBssSectionAddr(mapData);
bssSectionSize = ContikiMoteType.parseMapBssSectionSize(mapData);
SectionParser dataSecParser = new ContikiMoteType.MapSectionParser(
mapData,
Cooja.getExternalToolsSetting("MAPFILE_DATA_START"),
Cooja.getExternalToolsSetting("MAPFILE_DATA_SIZE"));
SectionParser bssSecParser = new ContikiMoteType.MapSectionParser(
mapData,
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
dataSecParser.parse(0);
bssSecParser.parse(0);
relDataSectionAddr = dataSecParser.getStartAddr();
dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
@ -837,18 +850,31 @@ public class ConfigurationWizard extends JDialog {
}
testOutput.addMessage("### Parsing command output for addresses");
addresses = new HashMap<String, Integer>();
boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
if (!parseOK) {
testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
return false;
}
addresses = new HashMap<String, Symbol>();
// boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
// if (!parseOK) {
// testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
// return false;
// }
testOutput.addMessage("### Validating section addresses");
relDataSectionAddr = ContikiMoteType.parseCommandDataSectionAddr(commandData);
dataSectionSize = ContikiMoteType.parseCommandDataSectionSize(commandData);
relBssSectionAddr = ContikiMoteType.parseCommandBssSectionAddr(commandData);
bssSectionSize = ContikiMoteType.parseCommandBssSectionSize(commandData);
SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser(
commandData,
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_DATA"));
SectionParser bssSecParser = new ContikiMoteType.CommandSectionParser(
commandData,
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
dataSecParser.parse(0);
bssSecParser.parse(0);
relDataSectionAddr = dataSecParser.getStartAddr();
dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
@ -935,7 +961,7 @@ public class ConfigurationWizard extends JDialog {
testOutput.addMessage("Could not find address of referenceVar", MessageList.ERROR);
return false;
}
int relRefAddress = addresses.get("referenceVar");
int relRefAddress = (int) addresses.get("referenceVar").addr;
javaLibrary.setReferenceAddress(relRefAddress);
testOutput.addMessage("### Creating data and BSS memory sections");
@ -943,15 +969,16 @@ public class ConfigurationWizard extends JDialog {
byte[] initialBssSection = new byte[bssSectionSize];
javaLibrary.getMemory(relDataSectionAddr, dataSectionSize, initialDataSection);
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
SectionMoteMemory memory = new SectionMoteMemory(addresses, 0);
SectionMoteMemory memory = new SectionMoteMemory(addresses);
VarMemory varMem = new VarMemory(memory);
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
int contikiDataCounter, contikiBSSCounter;
testOutput.addMessage("### Checking initial variable values: 1,0");
contikiDataCounter = memory.getIntValueOf("var1");
contikiBSSCounter = memory.getIntValueOf("uvar1");
contikiDataCounter = varMem.getIntValueOf("var1");
contikiBSSCounter = varMem.getIntValueOf("uvar1");
int javaDataCounter = 1;
int javaBSSCounter = 0;
if (contikiDataCounter != javaDataCounter) {
@ -975,8 +1002,8 @@ public class ConfigurationWizard extends JDialog {
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
contikiDataCounter = memory.getIntValueOf("var1");
contikiBSSCounter = memory.getIntValueOf("uvar1");
contikiDataCounter = varMem.getIntValueOf("var1");
contikiBSSCounter = varMem.getIntValueOf("uvar1");
if (contikiDataCounter != javaDataCounter) {
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
return false;
@ -1004,8 +1031,8 @@ public class ConfigurationWizard extends JDialog {
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
contikiDataCounter = memory.getIntValueOf("var1");
contikiBSSCounter = memory.getIntValueOf("uvar1");
contikiDataCounter = varMem.getIntValueOf("var1");
contikiBSSCounter = varMem.getIntValueOf("uvar1");
if (contikiDataCounter != javaDataCounter) {
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
return false;
@ -1029,8 +1056,8 @@ public class ConfigurationWizard extends JDialog {
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
contikiDataCounter = memory.getIntValueOf("var1");
contikiBSSCounter = memory.getIntValueOf("uvar1");
contikiDataCounter = varMem.getIntValueOf("var1");
contikiBSSCounter = varMem.getIntValueOf("uvar1");
if (contikiDataCounter != javaDataCounter) {
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
return false;
@ -1049,8 +1076,8 @@ public class ConfigurationWizard extends JDialog {
javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection);
memory.setMemorySegment(relDataSectionAddr, initialDataSection);
memory.setMemorySegment(relBssSectionAddr, initialBssSection);
contikiDataCounter = memory.getIntValueOf("var1");
contikiBSSCounter = memory.getIntValueOf("uvar1");
contikiDataCounter = varMem.getIntValueOf("var1");
contikiBSSCounter = varMem.getIntValueOf("uvar1");
if (contikiDataCounter != javaDataCounter) {
testOutput.addMessage("### Data section mismatch (" + contikiDataCounter + " != " + javaDataCounter + ")", MessageList.ERROR);
return false;

View file

@ -42,9 +42,9 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteMemory.MemoryEventType;
import org.contikios.cooja.MoteMemory.MemoryMonitor;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Read-only interface to IPv4 or IPv6 address.
@ -54,21 +54,22 @@ import org.contikios.cooja.MoteMemory.MemoryMonitor;
@ClassDescription("IP Address")
public class IPAddress extends MoteInterface {
private static Logger logger = Logger.getLogger(IPAddress.class);
private final MoteMemory moteMem;
private final VarMemory moteMem;
private static final int IPv6_MAX_ADDRESSES = 4;
private boolean ipv6IsGlobal = false;
private int ipv6AddressIndex = -1;
private static final int MONITORED_SIZE = 150;
private MemoryMonitor memMonitor;
private SegmentMonitor memMonitor;
public IPAddress(final Mote mote) {
moteMem = mote.getMemory();
moteMem = new VarMemory(mote.getMemory());
memMonitor = new MemoryMonitor() {
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
if (type != MemoryEventType.WRITE) {
memMonitor = new MemoryInterface.SegmentMonitor() {
@Override
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
if (type != SegmentMonitor.EventType.WRITE) {
return;
}
setChanged();
@ -76,11 +77,11 @@ public class IPAddress extends MoteInterface {
}
};
if (isVersion4()) {
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_hostaddr"), 4, memMonitor);
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_hostaddr", memMonitor);
} else if (isVersion6()) {
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor);
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor);
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_SIZE, memMonitor);
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_netif_addr_list_offset", memMonitor);
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_addr_size", memMonitor);
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_if", memMonitor);
}
}
@ -205,11 +206,11 @@ public class IPAddress extends MoteInterface {
super.removed();
if (memMonitor != null) {
if (isVersion4()) {
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), 4, memMonitor);
moteMem.removeVarMonitor("rimeaddr_node_addr", memMonitor);
} else if (isVersion6()) {
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor);
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor);
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_SIZE, memMonitor);
moteMem.removeVarMonitor("uip_ds6_netif_addr_list_offset", memMonitor);
moteMem.removeVarMonitor("uip_ds6_addr_size", memMonitor);
moteMem.removeVarMonitor("uip_ds6_if", memMonitor);
}
}
}

View file

@ -43,9 +43,9 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteMemory.MemoryEventType;
import org.contikios.cooja.MoteMemory.MemoryMonitor;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Read-only interface to Rime address read from Contiki variable: linkaddr_node_addr.
@ -57,18 +57,19 @@ import org.contikios.cooja.MoteMemory.MemoryMonitor;
@ClassDescription("Rime address")
public class RimeAddress extends MoteInterface {
private static Logger logger = Logger.getLogger(RimeAddress.class);
private MoteMemory moteMem;
private VarMemory moteMem;
public static final int RIME_ADDR_LENGTH = 2;
private MemoryMonitor memMonitor = null;
private SegmentMonitor memMonitor = null;
public RimeAddress(final Mote mote) {
moteMem = mote.getMemory();
moteMem = new VarMemory(mote.getMemory());
if (hasRimeAddress()) {
memMonitor = new MemoryMonitor() {
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
if (type != MemoryEventType.WRITE) {
memMonitor = new SegmentMonitor() {
@Override
public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
if (type != SegmentMonitor.EventType.WRITE) {
return;
}
setChanged();
@ -76,7 +77,7 @@ public class RimeAddress extends MoteInterface {
}
};
/* TODO XXX Timeout? */
moteMem.addMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor);
moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "linkaddr_node_addr", memMonitor);
}
}
@ -131,7 +132,7 @@ public class RimeAddress extends MoteInterface {
public void removed() {
super.removed();
if (memMonitor != null) {
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("linkaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor);
moteMem.removeVarMonitor("linkaddr_node_addr", memMonitor);
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2013, Enrico Joerns
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
import java.util.Arrays;
import java.util.Map;
/**
* A memory that is backed by an array.
*
* @author Enrico Joerns
*/
public class ArrayMemory implements MemoryInterface {
private final byte memory[];
private final long startAddress;
private final MemoryLayout layout;
private final boolean readonly;
private final Map<String, Symbol> symbols;// XXX Allow to set symbols
public ArrayMemory(long address, int size, MemoryLayout layout, Map<String, Symbol> symbols) {
this(address, layout, new byte[size], symbols);
}
public ArrayMemory(long address, MemoryLayout layout, byte[] memory, Map<String, Symbol> symbols) {
this(address, layout, memory, false, symbols);
}
public ArrayMemory(long address, MemoryLayout layout, byte[] memory, boolean readonly, Map<String, Symbol> symbols) {
this.startAddress = address;
this.layout = layout;
this.memory = memory;
this.readonly = readonly;
this.symbols = symbols;
}
@Override
public byte[] getMemory() {
return memory;
}
/**
* XXX Should addr be the relative or the absolute address of this section?
* @param addr
* @param size
* @return
* @throws org.contikios.cooja.mote.memory.MemoryInterface.MoteMemoryException
*/
@Override
public byte[] getMemorySegment(long addr, int size) throws MoteMemoryException {
byte[] ret = new byte[size];
System.arraycopy(memory, (int) (addr - startAddress), ret, 0, size);
return ret;
}
@Override
public void setMemorySegment(long addr, byte[] data) throws MoteMemoryException {
if (readonly) {
throw new MoteMemoryException("Invalid write access for readonly memory");
}
System.arraycopy(data, 0, memory, (int) (addr - startAddress), data.length);
}
@Override
public void clearMemory() {
Arrays.fill(memory, (byte) 0x00);
}
@Override
public long getStartAddr() {
return startAddress;
}
@Override
public int getTotalSize() {
return memory.length;
}
@Override
public Map<String, Symbol> getSymbolMap() {
return symbols;
}
@Override
public MemoryLayout getLayout() {
return layout;
}
@Override
public boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

View file

@ -0,0 +1,256 @@
/*
* Copyright (c) 2014, TU Braunschweig.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package org.contikios.cooja.mote.memory;
import org.contikios.cooja.mote.memory.MemoryLayout.DataType;
/**
* Represents memory that can be accessed with address and size informations.
*
* @author Enrico Jorns
*/
public abstract class Memory {
private final MemoryInterface memIntf;
/**
* Creates new memory for given MemoryLayout.
*
* @param intf
*/
public Memory(MemoryInterface intf) {
memIntf = intf;
}
// -- Get fixed size types
/**
* Read 8 bit integer from address.
*
* @param addr Address to read from
* @return 8 bit value read from address
*/
public byte getInt8ValueOf(long addr) {
return memIntf.getMemorySegment(addr, DataType.INT8.getSize())[0];
}
/**
* Read 16 bit integer from address.
*
* @param addr Address to read from
* @return 16 bit value read from address
*/
public short getInt16ValueOf(long addr) {
return MemoryBuffer.wrap(
memIntf.getLayout(),
memIntf.getMemorySegment(addr, DataType.INT16.getSize())).getInt16();
}
/**
* Read 32 bit integer from address.
*
* @param addr Address to read from
* @return 32 bit value read from address
*/
public int getInt32ValueOf(long addr) {
return MemoryBuffer.wrap(
memIntf.getLayout(),
memIntf.getMemorySegment(addr, DataType.INT32.getSize())).getInt32();
}
/**
* Read 64 bit integer from address.
*
* @param addr Address to read from
* @return 64 bit value read from address
*/
public long getInt64ValueOf(long addr) {
return MemoryBuffer.wrap(
memIntf.getLayout(),
memIntf.getMemorySegment(addr, DataType.INT64.getSize())).getInt64();
}
// -- Get compiler-dependent types
/**
* Read byte from address.
*
* @param addr Address to read from
* @return byte read from address
*/
public byte getByteValueOf(long addr) {
return memIntf.getMemorySegment(addr, DataType.BYTE.getSize())[0];
}
/**
* Read short from address.
*
* @param addr Address to read from
* @return short read from address
*/
public short getShortValueOf(long addr) {
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, 2)).getShort();
}
/**
* Read integer from address.
* <p>
* Note: Size of integer depends on platform type.
*
* @param addr Address to read from
* @return integer read from address
*/
public int getIntValueOf(long addr) {
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, memIntf.getLayout().intSize)).getInt();
}
/**
* Read long from address.
*
* @param addr Address to read from
* @return long read from address
*/
public long getLongValueOf(long addr) {
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, 4)).getLong();
}
/**
* Read pointer from address.
* <p>
* Note: Size of pointer depends on platform type.
*
* @param addr Address to read from
* @return pointer read from address
*/
public long getAddrValueOf(long addr) {
return MemoryBuffer.wrap(memIntf.getLayout(), memIntf.getMemorySegment(addr, memIntf.getLayout().addrSize)).getAddr();
}
// -- Set fixed size types
/**
* Write 8 bit integer to address.
*
* @param addr Address to write to
* @param value 8 bit value to write
*/
public void setInt8ValueOf(long addr, byte value) {
memIntf.setMemorySegment(addr, new byte[]{value});
}
/**
* Write 16 bit integer to address.
*
* @param addr Address to write to
* @param value 16 bit value to write
*/
public void setInt16ValueOf(long addr, short value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
memIntf.getLayout(),
new byte[DataType.INT16.getSize()]).putShort(value).getBytes());
}
/**
* Write 32 bit integer to address.
*
* @param addr Address to write to
* @param value 32 bit value to write
*/
public void setInt32ValueOf(long addr, int value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
memIntf.getLayout(),
new byte[DataType.INT32.getSize()]).putInt(value).getBytes());
}
/**
* Write 64 bit integer to address.
*
* @param addr Address to write to
* @param value 64 bit value to write
*/
public void setInt64ValueOf(long addr, long value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(
memIntf.getLayout(),
new byte[DataType.INT64.getSize()]).putLong(value).getBytes());
}
// -- Set compiler-dependent types
/**
* Write byte to address.
*
* @param addr Address to write to
* @param value byte to write
*/
public void setByteValueOf(long addr, byte value) {
memIntf.setMemorySegment(addr, new byte[]{value});
}
/**
* Write short to address.
*
* @param addr Address to write to
* @param value short to write
*/
public void setShortValueOf(long addr, short value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[2]).putShort(value).getBytes());
}
/**
* Write integer to address.
* <p>
* Note: Size of integer depends on platform type.
*
* @param addr Address to write to
* @param value integer to write
*/
public void setIntValueOf(long addr, int value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[memIntf.getLayout().intSize]).putInt(value).getBytes());
}
/**
* Write long to address.
*
* @param addr Address to write to
* @param value long to write
*/
public void setLongValueOf(long addr, long value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[4]).putLong(value).getBytes());
}
/**
* Write pointer to address.
* <p>
* Note: Size of pointer depends on platform type.
*
* @param addr Address to write to
* @param value pointer to write
*/
public void setAddrValueOf(long addr, long value) {
memIntf.setMemorySegment(addr, MemoryBuffer.wrap(memIntf.getLayout(), new byte[memIntf.getLayout().addrSize]).putAddr(value).getBytes());
}
}

View file

@ -0,0 +1,481 @@
/*
* Copyright (c) 2014, TU Braunschweig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
import java.nio.ByteBuffer;
import org.contikios.cooja.mote.memory.MemoryLayout.DataType;
/**
* Basic routines for memory access with multi-arch support.
*
* Handles endianess, integer size and address size.
*
* Supports padding/aligning.
*
* @author Enrico Jorns
*/
public class MemoryBuffer {
private final MemoryLayout memLayout;
private final ByteBuffer bbuf;
private final DataType[] structure;
private int structIndex;
private MemoryBuffer(MemoryLayout memLayout, ByteBuffer buffer, DataType[] structure) {
this.memLayout = memLayout;
this.bbuf = buffer;
this.structure = structure;
this.structIndex = 0;
}
/**
* Wraps a byte array into an unstructered MemoryBuffer with given MemoryLayout.
*<p>
* Note that modifications to the buffer are applied to the backed array and vice versa.
*
* @param layout MemoryLayout for memory to access array from
* @param array Byte array that will back this buffer
* @return the new MemroyBuffer
*/
public static MemoryBuffer wrap(MemoryLayout layout, byte[] array) {
return wrap(layout, array, null);
}
/**
* Wraps a byte array into a structured MemoryBuffer with given MemoryLayout.
*<p>
* Note that modifications to the buffer are applied to the backed array and vice versa.
*<p>
* A structured MemoryBuffer can be used to simplify reading c struct data
* from the memory as it provides support for data aligning.
*<p>
* The structure array elements should be set to exactly the same types and order
* that the corresponding c struct has.
*
* @param layout MemoryLayout for memory to access array from
* @param structure Array of data types representing the structure to read
* @param array Byte array that will back this buffer
* @return the new MemroyBuffer
*/
public static MemoryBuffer wrap(MemoryLayout layout, byte[] array, DataType[] structure) {
ByteBuffer b = ByteBuffer.wrap(array);
b.order(layout.order); // preset endianess
return new MemoryBuffer(layout, b, structure);
}
/**
* Returns the byte array that backs this buffer
*
* @return byte array that backs this buffer
*/
public byte[] getBytes() {
if (bbuf.hasArray()) {
return bbuf.array();
}
else {
return null;
}
}
/**
* Calculates the padding bytes to be added/skipped between current and next
* element.
*
* @param type Current data type
*/
private void skipPaddingBytesFor(DataType type) {
/* Check if we have a structure and not yet reached the last element */
if (structure != null && structure[structIndex + 1] != null) {
/* get size of next element in structure */
int nextsize = structure[structIndex + 1].getSize();
/* limit padding to word size */
nextsize = nextsize > memLayout.WORD_SIZE ? memLayout.WORD_SIZE : nextsize;
/* calc padding */
int pad = nextsize - type.getSize();
/* Skip padding bytes */
if (pad > 0) {
bbuf.position(bbuf.position() + pad);
}
}
structIndex++;
}
/**
* Returns current element type.
*
* @return current element type or null if no struct is used
*/
public DataType getType() {
if (structure == null) {
return null;
}
return structure[structIndex];
}
// --- fixed size types
/**
* Reads 8 bit integer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return 8 bit integer at the buffer's current position
*/
public byte getInt8() {
byte value = bbuf.get();
skipPaddingBytesFor(DataType.INT8);
return value;
}
/**
* Reads 16 bit integer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return 16 bit integer at the buffer's current position
*/
public short getInt16() {
short value = bbuf.getShort();
skipPaddingBytesFor(DataType.INT16);
return value;
}
/**
* Reads 32 bit integer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return 32 bit integer at the buffer's current position
*/
public int getInt32() {
int value = bbuf.getInt();
skipPaddingBytesFor(DataType.INT32);
return value;
}
/**
* Reads 64 bit integer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return 64 bit integer at the buffer's current position
*/
public long getInt64() {
long value = bbuf.getLong();
skipPaddingBytesFor(DataType.INT64);
return value;
}
// --- platform-dependent types
/**
* Reads byte from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return byte at the buffer's current position
*/
public byte getByte() {
byte value = bbuf.get();
skipPaddingBytesFor(DataType.BYTE);
return value;
}
/**
* Reads short from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return short at the buffer's current position
*/
public short getShort() {
short value = bbuf.getShort();
skipPaddingBytesFor(DataType.SHORT);
return value;
}
/**
* Reads integer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return integer at the buffer's current position
*/
public int getInt() {
int value;
switch (memLayout.intSize) {
case 2:
value = bbuf.getShort();
break;
case 4:
default:
value = bbuf.getInt();
break;
}
skipPaddingBytesFor(DataType.INT);
return value;
}
/**
* Reads long from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return long at the buffer's current position
*/
public long getLong() {
long value = bbuf.getLong();
skipPaddingBytesFor(DataType.LONG);
return value;
}
/**
* Reads pointer from current buffer position,
* and then increments position.
* <p>
* Note: If structured reading is enabled,
* additional padding bytes may be skipped automatically.
*
* @return pointer at the buffer's current position
*/
public long getAddr() {
long value;
switch (memLayout.addrSize) {
case 2:
value = bbuf.getShort();
break;
case 4:
value = bbuf.getInt();
break;
case 8:
value = bbuf.getLong();
break;
default:
value = bbuf.getInt();
break;
}
skipPaddingBytesFor(DataType.POINTER);
return value;
}
// --- fixed size types
/**
* Writes 8 bit integer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value 8 bit integer to write
* @return A reference to this object
*/
public MemoryBuffer putInt8(byte value) {
bbuf.put(value);
skipPaddingBytesFor(DataType.INT8);
return this;
}
/**
* Writes 16 bit integer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value 16 bit integer to write
* @return A reference to this object
*/
public MemoryBuffer putInt16(short value) {
bbuf.putShort(value);
skipPaddingBytesFor(DataType.INT16);
return this;
}
/**
* Writes 32 bit integer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value 32 bit integer to write
* @return A reference to this object
*/
public MemoryBuffer putInt32(int value) {
bbuf.putInt(value);
skipPaddingBytesFor(DataType.INT32);
return this;
}
/**
* Writes 64 bit integer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value 64 bit integer to write
* @return A reference to this object
*/
public MemoryBuffer putInt64(long value) {
bbuf.putLong(value);
skipPaddingBytesFor(DataType.INT64);
return this;
}
// --- platform-dependent types
/**
* Writes byte to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value byte to write
* @return A reference to this object
*/
public MemoryBuffer putByte(byte value) {
bbuf.put(value);
skipPaddingBytesFor(DataType.BYTE);
return this;
}
/**
* Writes short to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value short to write
* @return A reference to this object
*/
public MemoryBuffer putShort(short value) {
bbuf.putShort(value);
skipPaddingBytesFor(DataType.SHORT);
return this;
}
/**
* Writes integer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
* <p>
* Note: Size of integer depends on platform type
*
* @param value integer to write
* @return A reference to this object
*/
public MemoryBuffer putInt(int value) {
switch (memLayout.intSize) {
case 2:
/**
* @TODO: check for size?
*/
bbuf.putShort((short) value);
break;
case 4:
default:
bbuf.putInt(value);
break;
}
skipPaddingBytesFor(DataType.INT);
return this;
}
/**
* Writes long to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
*
* @param value long to write
* @return A reference to this object
*/
public MemoryBuffer putLong(long value) {
bbuf.putLong(value);
skipPaddingBytesFor(DataType.LONG);
return this;
}
/**
* Writes pointer to current buffer position,
* and then increments position.
* <p>
* Note: If structured writing is enabled,
* additional padding bytes may be skipped automatically.
* <p>
* Note: Size of pointer depends on platform type
*
* @param value pointer to write
* @return A reference to this object
*/
public MemoryBuffer putAddr(long value) {
/**
* @TODO: check for size?
*/
switch (memLayout.addrSize) {
case 2:
bbuf.putShort((short) value);
break;
case 4:
bbuf.putInt((int) value);
break;
case 8:
bbuf.putLong(value);
break;
default:
bbuf.putInt((int) value);
break;
}
skipPaddingBytesFor(DataType.POINTER);
return this;
}
}

View file

@ -0,0 +1,192 @@
/*
* Copyright (c) 2014, TU Braunschweig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
import java.util.Map;
/**
* A minimal interface to a motes memory.
*
* Allows reading and writing memory, obtaining symbol information
* and provides some basic inforation about size, layout, etc.
*
* @author Enrico Jorns
*/
public interface MemoryInterface {
/**
* Represents a symbol in memory (variable / function)
*/
public static class Symbol {
public final Type type;
public final String name;
public final String section;
public final long addr;
public final int size;
public enum Type {
VARIABLE,
FUNCTION
}
public Symbol(Type type, String name, String section, long addr, int size) {
this.type = type;
this.name = name;
this.section = section;
this.addr = addr;
this.size = size;
}
public Symbol(Type type, String name, long addr, int size) {
this(type, name, null, addr, size);
}
@Override
public String toString() {
return new StringBuilder("Symbol(").append(type == null ? "N/A" : type.toString())
.append(") '").append(name)
.append("' in '").append(section == null ? "N/A" : section)
.append("' at 0x").append(addr == -1 ? "N/A" : Long.toHexString(addr))
.append(" size ").append(size == -1 ? "N/A" : String.valueOf(size)).toString();
}
}
/**
* Class represents memory access exceptions.
*/
public class MoteMemoryException extends RuntimeException {
public MoteMemoryException(String message, Object... args) {
super(String.format(message, args));
}
}
/**
* Returns entire mote memory
* @return Memory byte array
* @throws org.contikios.cooja.mote.memory.MemoryInterface.MoteMemoryException
*/
public byte[] getMemory() throws MoteMemoryException;
/**
* Reads a segment from memory.
*
* @param addr Start address to read from
* @param size Size to read [bytes]
* @return Byte array
*/
public byte[] getMemorySegment(long addr, int size) throws MoteMemoryException;
/**
* Sets a segment of memory.
*
* @param addr Start address to write to
* @param data Size to write [bytes]
*/
void setMemorySegment(long addr, byte[] data) throws MoteMemoryException;
/**
* Clears the memory.
*/
void clearMemory();
/**
*
* @return
*/
long getStartAddr();
/**
* Returns total size of memory.
*
* @return Size [bytes]
*/
int getTotalSize();// XXX getSize();
/**
* Returns Map of all variables in memory.
* Map must be of typ name / symbol.
*
* @return Variables
*/
Map<String, Symbol> getSymbolMap();
/**
* Returns the MemoryLayout for this memory.
*
* @return Memory layout for this memory
*/
MemoryLayout getLayout();
/**
* Monitor to listen for memory updates.
*/
interface SegmentMonitor {
public static enum EventType {
READ,
WRITE,
READWRITE
}
/**
* Invoked if the monitored segment changed
*
* @param memory Reference to the memory
* @param type XXX ???
* @param address Address in segment where modification occured
*/
void memoryChanged(MemoryInterface memory, EventType type, long address);
}
/**
* Adds a SegmentMonitor for the specified address region.
*
* @param flag Select memory operation(s) to listen for
* (read, write, read/write)
* @param address Start address of monitored data region
* @param size Size of monitored data region
* @param monitor SegmentMonitor to add
* @return true if monitor could be added, false if not
*/
boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor);
/**
* Removes SegmentMonitor assigned to the specified region.
*
* @param address Start address of Monitor data region
* @param size Size of Monitor data region
* @param monitor SegmentMonitor to remove
* @return true if monitor was removed, false if not
*/
boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor);
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2014, TU Braunschweig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
import java.nio.ByteOrder;
/**
* Holds memory layout informations such as endianess, wordsize, C int size.
*
* @author Enrico Jorns
*/
public class MemoryLayout {
/** 8 bit memory architecture */
public static final int ARCH_8BIT = 1;
/** 16 bit memory architecture */
public static final int ARCH_16BIT = 2;
/** 32 bit memory architecture */
public static final int ARCH_32BIT = 4;
/** 64 bit memory architecture */
public static final int ARCH_64BIT = 8;
/**
* Size of data types in bytes.
*/
public enum DataType {
BYTE(1),
CHAR(1),
SHORT(2),
INT(4),
LONG(8),
LONGLONG(8),
INT8(1),
INT16(2),
INT32(4),
INT64(8),
FLOAT(4),
DOUBLE(8),
POINTER(4);
private int size;
DataType(int size) {
this.size = size;
}
public void setSize(int size) {
this.size = size;
}
public int getSize() {
return this.size;
}
}
public final ByteOrder order;
public final int addrSize;
public final int intSize;
public final int WORD_SIZE;
private boolean aligned = true;
/**
* Creates new MemoryLayout instance.
*
* @param order either ByteOrder.BIG_ENDIAN, or ByteOrder.LITTLE_ENDIAN
* @param wordsize should be one of ARCH_8BIT, ARCH_16BIT, ARCH_32BIT,
* ARCH_64BIT
* @param sizeofInt
*/
public MemoryLayout(ByteOrder order, int wordsize, int sizeofInt) {
this(order, wordsize, sizeofInt, wordsize);
}
/**
* Creates new MemoryLayout instance.
*
* @param order either ByteOrder.BIG_ENDIAN, or ByteOrder.LITTLE_ENDIAN
* @param wordsize should be one of ARCH_8BIT, ARCH_16BIT, ARCH_32BIT,
* ARCH_64BIT
* @param sizeofPointer
* @param sizeofInt
*/
public MemoryLayout(ByteOrder order, int wordsize, int sizeofInt, int sizeofPointer) {
this.order = order;
this.WORD_SIZE = wordsize;
this.intSize = sizeofInt;
this.addrSize = sizeofPointer;
DataType.INT.setSize(this.intSize);
DataType.POINTER.setSize(this.addrSize);
}
/**
* Returns the MemoryLayout for the running jvm.
*
* @return MemoryLayout for the running jvm.
*/
public static MemoryLayout getNative() {
return new MemoryLayout(
ByteOrder.nativeOrder(),
Integer.parseInt(System.getProperty("sun.arch.data.model")) / 8,
Integer.SIZE / 8);
}
/**
* Enable/Disable data alignment.
*
* Determines whether data alignemnt is used for packing structs.
* Default is enabled.
*
* @param aligned true to enable data alignment, false to disable
*/
public void setAligned(boolean aligned) {
this.aligned = aligned;
}
/**
* Returns true if data is aligned.
*
* @return if aligned
*/
public boolean isAligned() {
return aligned;
}
/**
* Returns number of padding bytes between two data types.
*
* @param currType
* @param nextType
* @return
*/
public int getPaddingBytesFor(DataType currType, DataType nextType) {
/* No padding bytes for unaligned memory */
if (!isAligned()) {
return 0;
}
/* get size of next element in structure */
int nextsize = nextType.getSize();
/* limit padding to word size */
nextsize = nextsize > WORD_SIZE ? WORD_SIZE : nextsize;
System.out.println("Nextsize: " + nextsize);
/* calc padding */
int pad = nextsize - currType.getSize();
return pad;
}
/**
* Returns information string for this MemoryLayout.
*
* @return String that shows Endianess and word size.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
return sb.append("MemoryLayout: ")
.append("Endianess: ").append(order)
.append(", WORD_SIZE: ").append(WORD_SIZE)
.toString();
}
}

View file

@ -0,0 +1,330 @@
/*
* Copyright (c) 2014, TU Braunschweig. All rights reserved.
* Copyright (c) 2006, Swedish Institute of Computer Science. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of the
* Institute nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* Represents a mote memory consisting of non-overlapping memory sections with
* symbol addresses.
* <p>
* Every section must implement MemoyInterface.
* <p>
* Implements MemoryInterface by forwarding calls to available sections or returning
* an error if no section is available.
*
* @author Fredrik Osterlind
* @author Enrico Jorns
*/
public class SectionMoteMemory implements MemoryInterface {
private static Logger logger = Logger.getLogger(SectionMoteMemory.class);
private static final boolean DEBUG = logger.isDebugEnabled();
private Map<String, MemoryInterface> sections = new HashMap<>();
private final Map<String, Symbol> symbols;
private MemoryLayout memLayout;
private long startAddr = Long.MAX_VALUE;
/**
* @param symbols Symbol addresses
*/
public SectionMoteMemory(Map<String, Symbol> symbols) {
this.symbols = symbols;
}
/**
* Adds a section to this memory.
*
* A new section will be checked for address overlap with existing sections.
*
* @param name
* @param section
* @return true if adding succeeded, false otherwise
*/
public boolean addMemorySection(String name ,MemoryInterface section) {
if (section == null) {
return false;
}
/* Cooja address space */
for (MemoryInterface sec : sections.values()) {
/* check for overlap with existing region */
if ((section.getStartAddr() <= sec.getStartAddr() + sec.getTotalSize() - 1)
&& (section.getStartAddr() + section.getTotalSize() - 1 >= sec.getStartAddr())) {
logger.error(String.format(
"Failed adding section '%s' of size %d @0x%x",
name,
section.getTotalSize(),
section.getStartAddr()));
return false;
}
/* Min start address is main start address */
startAddr = sec.getStartAddr() < startAddr ? sec.getStartAddr() : startAddr;
/* Layout is last layout. XXX Check layout consistency? */
memLayout = section.getLayout();
}
sections.put(name, section);
if (section.getSymbolMap() != null) {
for (String s : section.getSymbolMap().keySet()) {
// XXX how to handle double names here?
symbols.put(s, section.getSymbolMap().get(s));
}
}
if (DEBUG) {
logger.debug(String.format(
"Added section '%s' of size %d @0x%x",
name,
section.getTotalSize(),
section.getStartAddr()));
}
return true;
}
/**
* Returns the total number of sections in this memory.
*
* @return Number of sections
*/
public int getNumberOfSections() {
return sections.size();
}
/**
* Returns memory section of this memory.
* @param name Name of section
* @return memory section
*/
public MemoryInterface getSection(String name) {
for (String memsec : sections.keySet()) {
if (memsec.equals(name)) {
return sections.get(name);
}
}
logger.warn("Section '" + name + "' not found");
return null;
}
/**
* Return all sections of this memory.
* @return All memory sections
*/
public Map<String, MemoryInterface> getSections() {
return sections;
}
/**
* True if given address is part of this memory section.
*
* @param intf
* @param addr
* Address
* @return True if given address is part of this memory section, false
* otherwise
*/
public static boolean includesAddr(MemoryInterface intf, long addr) {
return addr >= intf.getStartAddr() && addr < (intf.getStartAddr() + intf.getTotalSize());
}
/**
* True if the whole address range specified by address and size
* lies inside this memory section.
*
* @param intf
* @param addr Start address of segment to check
* @param size Size of segment to check
*
* @return True if given address range lies inside address range of this
* section
*/
public static boolean inSection(MemoryInterface intf, long addr, int size) {
return addr >= intf.getStartAddr() && addr + size <= intf.getStartAddr() + intf.getTotalSize();
}
@Override
public void clearMemory() {
sections.clear();
}
@Override
public int getTotalSize() {
int totalSize = 0;
for (MemoryInterface section : sections.values()) {
totalSize += section.getTotalSize();
}
return totalSize;
}
@Override
public byte[] getMemory() throws MoteMemoryException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
/**
* Returns memory segment from section matching segment given by address and size
* @param address start address of segment to get
* @param size size of segmetn to get
* @return Array containing data of segment
* @throws MoteMemoryException if no single section containing the given address range was found
*/
@Override
public byte[] getMemorySegment(long address, int size) throws MoteMemoryException {
for (MemoryInterface section : sections.values()) {
if (includesAddr(section, address) && includesAddr(section, address + size - 1)) {
return section.getMemorySegment(address, size);
}
}
throw new MoteMemoryException(
"Getting memory segment [0x%x,0x%x] failed: No section available",
address, address + size - 1);
}
/**
* Sets memory segment of section matching segment given by address and size.
* @param address start address of segment to set
* @param data data to set
* @throws MoteMemoryException if no single section containing the given address range was found
* or memory is readonly.
*/
@Override
public void setMemorySegment(long address, byte[] data) throws MoteMemoryException {
for (MemoryInterface section : sections.values()) {
if (inSection(section, address, data.length)) {
section.setMemorySegment(address, data);
if (DEBUG) {
logger.debug(String.format(
"Wrote memory segment [0x%x,0x%x]",
address, address + data.length - 1));
}
return;
}
}
throw new MoteMemoryException(
"Writing memory segment [0x%x,0x%x] failed: No section available",
address, address + data.length - 1);
}
@Override
public long getStartAddr() {
return startAddr;
}
@Override
public Map<String, Symbol> getSymbolMap() {
return symbols;
}
@Override
public MemoryLayout getLayout() {
return memLayout;
}
@Override
public boolean addSegmentMonitor(SegmentMonitor.EventType flag, long address, int size, SegmentMonitor monitor) {
PolledMemorySegments t = new PolledMemorySegments(monitor, address, size);
polledMemories.add(t);
return true;
}
@Override
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor monitor) {
for (PolledMemorySegments mcm: polledMemories) {
if (mcm.mm != monitor || mcm.address != address || mcm.size != size) {
continue;
}
polledMemories.remove(mcm);
return true;
}
return false;
}
/** Copies seciton memory to new (array backed) one
* @return Cloned memory
*/
@Override
public SectionMoteMemory clone() {
SectionMoteMemory clone = new SectionMoteMemory(symbols);
for (String secname : sections.keySet()) {
// Copy section memory to new ArrayMemory
MemoryInterface section = sections.get(secname);
MemoryInterface cpmem = new ArrayMemory(section.getStartAddr(), section.getLayout(), section.getMemory().clone(), section.getSymbolMap());
clone.addMemorySection(secname, cpmem);
}
return clone;
}
private ArrayList<PolledMemorySegments> polledMemories = new ArrayList<PolledMemorySegments>();
public void pollForMemoryChanges() {
for (PolledMemorySegments mem: polledMemories.toArray(new PolledMemorySegments[0])) {
mem.notifyIfChanged();
}
}
private class PolledMemorySegments {
public final SegmentMonitor mm;
public final long address;
public final int size;
private byte[] oldMem;
public PolledMemorySegments(SegmentMonitor mm, long address, int size) {
this.mm = mm;
this.address = address;
this.size = size;
oldMem = getMemorySegment(address, size);
}
private void notifyIfChanged() {
byte[] newMem = getMemorySegment(address, size);
if (Arrays.equals(oldMem, newMem)) {
return;
}
mm.memoryChanged(SectionMoteMemory.this, SegmentMonitor.EventType.WRITE, address);
oldMem = newMem;
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2013, Enrico Joerns
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.contikios.cooja.mote.memory;
/**
* Unknown variable name exception.
*/
public class UnknownVariableException extends RuntimeException {
public UnknownVariableException(String varName) {
super("Unknown variable name: " + varName);
}
}

View file

@ -0,0 +1,387 @@
/*
* Copyright (c) 2014, TU Braunschweig.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package org.contikios.cooja.mote.memory;
import java.util.Collection;
import java.util.Set;
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor.EventType;
/**
* Represents memory that can be accessed with names of variables.
*
* @author Enrico Jorns
*/
public class VarMemory extends Memory {
private MemoryInterface memIntf;
/**
* Creates new VarMemory.
*
* @param intf
*/
public VarMemory(MemoryInterface intf) {
super(intf);
memIntf = intf;
}
/**
* Allows to change the MemoryInterface associated with this access class.
*
* @param intf Interface to associate with
*/
public void associateMemory(MemoryInterface intf) {
memIntf = intf;
}
/**
* Generates and returns an array of all variables in this memory
*
* @return All variables located in this memory
*/
public Collection<Symbol> getVariables() {
return memIntf.getSymbolMap().values();
}
/**
* Generates an array of all variable names in this memory.
*
* @return All variable names located in this memory
*/
public Set<String> getVariableNames() {
return memIntf.getSymbolMap().keySet();
}
/**
* Checks if given variable exists in memory.
*
* @param varName Variable name
* @return True if variable exists, false otherwise
*/
public boolean variableExists(String varName) {
return memIntf.getSymbolMap().containsKey(varName);
}
/**
* Returns address of variable with given name.
*
* @param varName Variable name
* @return Variable address
*/
public Symbol getVariable(String varName) throws UnknownVariableException {
Symbol sym = memIntf.getSymbolMap().get(varName);
if (sym == null) {
throw new UnknownVariableException(varName);
}
return sym;
}
/**
* Returns address of variable with given name.
*
* @param varName Variable name
* @return Address of variable
* @throws UnknownVariableException If variable not found
*/
public long getVariableAddress(String varName) throws UnknownVariableException {
return getVariable(varName).addr;
}
/**
* Return size of variable with given name.
*
* @param varName Variable name
* @return Size of variable, -1 if unknown size
* @throws UnknownVariableException If variable not found
*/
public int getVariableSize(String varName) throws UnknownVariableException {
return getVariable(varName).size;
}
/**
* Read 8 bit integer from location associated with this variable name.
*
* @param varName Variable name
* @return 8 bit integer value read from location assigned to variable name
*/
public byte getInt8ValueOf(String varName)
throws UnknownVariableException {
return getInt8ValueOf(getVariable(varName).addr);
}
/**
* Read 16 bit integer from location associated with this variable name.
*
* @param varName Variable name
* @return 16 bit integer value read from location assigned to variable name
*/
public short getInt16ValueOf(String varName)
throws UnknownVariableException {
return getInt16ValueOf(getVariable(varName).addr);
}
/**
* Read 32 bit integer from location associated with this variable name.
*
* @param varName Variable name
* @return 32 bit integer value read from location assigned to variable name
*/
public int getInt32ValueOf(String varName)
throws UnknownVariableException {
return getInt32ValueOf(getVariable(varName).addr);
}
/**
* Read 64 bit integer from location associated with this variable name.
*
* @param varName Variable name
* @return 64 bit integer value read from location assigned to variable name
*/
public long getInt64ValueOf(String varName)
throws UnknownVariableException {
return getInt64ValueOf(getVariable(varName).addr);
}
/**
* Read byte from location associated with this variable name.
*
* @param varName Variable name
* @return byte value read from location assigned to variable name
*/
public byte getByteValueOf(String varName)
throws UnknownVariableException {
return getByteValueOf(getVariable(varName).addr);
}
/**
* Read short from location associated with this variable name.
*
* @param varName Variable name
* @return short value read from location assigned to variable name
*/
public short getShortValueOf(String varName)
throws UnknownVariableException {
short val = getShortValueOf(getVariable(varName).addr);
return val;
}
/**
* Read integer from location associated with this variable name.
*
* @param varName Variable name
* @return integer value read from location assigned to variable name
*/
public int getIntValueOf(String varName)
throws UnknownVariableException {
int val = getIntValueOf(getVariable(varName).addr);
return val;
}
/**
* Read long from location associated with this variable name.
*
* @param varName Variable name
* @return long value read from location assigned to variable name
*/
public long getLongValueOf(String varName)
throws UnknownVariableException {
long val = getLongValueOf(getVariable(varName).addr);
return val;
}
/**
* Read pointer from location associated with this variable name.
*
* The number of bytes actually read depends on the pointer size
* defined in memory layout.
*
* @param varName Variable name
* @return pointer value read from location assigned to variable name
*/
public long getAddrValueOf(String varName)
throws UnknownVariableException {
long val = getAddrValueOf(getVariable(varName).addr);
return val;
}
/**
* Read byte array starting at location associated with this variable name.
*
* @param varName Variable name
* @param length Numbe of bytes to read
* @return byte array read from location assigned to variable name
*/
public byte[] getByteArray(String varName, int length)
throws UnknownVariableException {
return memIntf.getMemorySegment(getVariable(varName).addr, length);
}
/**
* Write 8 bit integer value to location associated with this variable name.
*
* @param varName Variable name
* @param value 8 bit integer value to write
*/
public void setInt8ValueOf(String varName, byte value)
throws UnknownVariableException {
setInt8ValueOf(getVariable(varName).addr, value);
}
/**
* Write 16 bit integer value to location associated with this variable name.
*
* @param varName Variable name
* @param value 16 bit integer value to write
*/
public void setInt16ValueOf(String varName, byte value)
throws UnknownVariableException {
setInt16ValueOf(getVariable(varName).addr, value);
}
/**
* Write 32 bit integer value to location associated with this variable name.
*
* @param varName Variable name
* @param value 32 bit integer value to write
*/
public void setInt32ValueOf(String varName, byte value)
throws UnknownVariableException {
setInt32ValueOf(getVariable(varName).addr, value);
}
/**
* Write 64 bit integer value to location associated with this variable name.
*
* @param varName Variable name
* @param value 64 bit integer value to write
*/
public void setInt64ValueOf(String varName, byte value)
throws UnknownVariableException {
setInt64ValueOf(getVariable(varName).addr, value);
}
/**
* Write byte value to location associated with this variable name.
*
* @param varName Variable name
* @param value byte value to write
*/
public void setByteValueOf(String varName, byte value)
throws UnknownVariableException {
setByteValueOf(getVariable(varName).addr, value);
}
/**
* Write short value to location associated with this variable name.
*
* @param varName Variable name
* @param value short value to write
*/
public void setShortValueOf(String varName, short value)
throws UnknownVariableException {
setShortValueOf(getVariable(varName).addr, value);
}
/**
* Write int value to location associated with this variable name.
*
* @param varName Variable name
* @param value int value to write
*/
public void setIntValueOf(String varName, int value)
throws UnknownVariableException {
setIntValueOf(getVariable(varName).addr, value);
}
/**
* Write long value to location associated with this variable name.
*
* @param varName Variable name
* @param value long value to write
*/
public void setLongValueOf(String varName, long value)
throws UnknownVariableException {
setLongValueOf(getVariable(varName).addr, value);
}
/**
* Write pointer value to location associated with this variable name.
*
* The number of bytes actually written depends on the pointer size
* defined in memory layout.
*
* @param varName Variable name
* @param value Value to write
*/
public void setAddrValueOf(String varName, long value)
throws UnknownVariableException {
setAddrValueOf(getVariable(varName).addr, value);
}
/**
*
* @param varName
* @param data
*/
public void setByteArray(String varName, byte[] data)
throws UnknownVariableException {
memIntf.setMemorySegment(getVariable(varName).addr, data);
}
/**
* Adds a MemoryMonitor for the specified address region.
*
* @param flag Select memory operation(s) to listen for (read, write,
* read/write)
* @param varName
* @param mm
* @return
*/
public boolean addVarMonitor(EventType flag, final String varName, final SegmentMonitor mm) {
return memIntf.addSegmentMonitor(
flag,
getVariable(varName).addr,
getVariable(varName).size,
mm);
}
/**
* Removes MemoryMonitor assigned to the specified region.
*
* @param varName
* @param mm MemoryMonitor to remove
*/
public void removeVarMonitor(String varName, SegmentMonitor mm) {
memIntf.removeSegmentMonitor(getVariable(varName).addr, getVariable(varName).size, mm);
}
}

View file

@ -33,21 +33,22 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jdom.Element;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType;
import org.contikios.cooja.RadioPacket;
import org.contikios.cooja.SectionMoteMemory;
import org.contikios.cooja.mote.memory.SectionMoteMemory;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.interfaces.ApplicationRadio;
import org.contikios.cooja.interfaces.ApplicationSerialPort;
import org.contikios.cooja.interfaces.Radio;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
import org.contikios.cooja.mote.memory.MemoryLayout;
/**
* Abstract application mote.
@ -67,6 +68,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
/* Observe our own radio for incoming radio packets */
private Observer radioDataObserver = new Observer() {
@Override
public void update(Observable obs, Object obj) {
ApplicationRadio radio = (ApplicationRadio) obs;
if (radio.getLastEvent() == Radio.RadioEvent.RECEPTION_FINISHED) {
@ -89,7 +91,8 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
public AbstractApplicationMote(MoteType moteType, Simulation sim) {
setSimulation(sim);
this.moteType = moteType;
this.memory = new SectionMoteMemory(new HashMap<String, Integer>(), 0);
MemoryLayout.getNative();
this.memory = new SectionMoteMemory(new HashMap<String, Symbol>());
this.moteInterfaces = new MoteInterfaceHandler(this, moteType.getMoteInterfaceClasses());
this.moteInterfaces.getRadio().addObserver(radioDataObserver);
requestImmediateWakeup();
@ -99,6 +102,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
((ApplicationSerialPort)moteInterfaces.getLog()).triggerLog(msg);
}
@Override
public MoteInterfaceHandler getInterfaces() {
return moteInterfaces;
}
@ -107,14 +111,16 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
moteInterfaces = moteInterfaceHandler;
}
public MoteMemory getMemory() {
@Override
public MemoryInterface getMemory() {
return memory;
}
public void setMemory(MoteMemory memory) {
public void setMemory(SectionMoteMemory memory) {
this.memory = (SectionMoteMemory) memory;
}
@Override
public MoteType getType() {
return moteType;
}
@ -123,6 +129,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
moteType = type;
}
@Override
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element;
@ -141,10 +148,11 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
return config;
}
@Override
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML, boolean visAvailable) {
setSimulation(simulation);
this.memory = new SectionMoteMemory(new HashMap<String, Integer>(), 0);
this.memory = new SectionMoteMemory(new HashMap<String, Symbol>());
moteInterfaces.getRadio().addObserver(radioDataObserver);
for (Element element : configXML) {
@ -176,10 +184,12 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
return true;
}
@Override
public int getID() {
return moteInterfaces.getMoteID().getMoteID();
}
@Override
public String toString() {
return "AppMote " + getID();
}

View file

@ -89,8 +89,6 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Cooja;
import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteMemory.MemoryEventType;
import org.contikios.cooja.Plugin;
import org.contikios.cooja.PluginType;
import org.contikios.cooja.SimEventCentral.MoteCountListener;
@ -100,6 +98,10 @@ import org.contikios.cooja.VisPlugin;
import org.contikios.cooja.dialogs.TableColumnAdjuster;
import org.contikios.cooja.dialogs.UpdateAggregator;
import org.contikios.cooja.interfaces.IPAddress;
import org.contikios.cooja.mote.memory.MemoryBuffer;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.mote.memory.VarMemory;
import org.contikios.cooja.motes.AbstractEmulatedMote;
import org.contikios.cooja.util.ArrayQueue;
import org.contikios.cooja.util.StringUtils;
@ -163,6 +165,7 @@ public class BufferListener extends VisPlugin {
private Parser parser = null;
private Buffer buffer = null;
@Override
public void startPlugin() {
super.startPlugin();
if (parser == null) {
@ -214,6 +217,7 @@ public class BufferListener extends VisPlugin {
private ArrayList<SegmentMemoryMonitor> memoryMonitors = new ArrayList<SegmentMemoryMonitor>();
private TimeEvent hourTimeEvent = new TimeEvent(0) {
@Override
public void execute(long t) {
hasHours = true;
repaintTimeColumn();
@ -224,11 +228,13 @@ public class BufferListener extends VisPlugin {
private static final int UPDATE_INTERVAL = 250;
private UpdateAggregator<BufferAccess> logUpdateAggregator = new UpdateAggregator<BufferAccess>(UPDATE_INTERVAL) {
private Runnable scroll = new Runnable() {
@Override
public void run() {
logTable.scrollRectToVisible(
new Rectangle(0, logTable.getHeight() - 2, 1, logTable.getHeight()));
}
};
@Override
protected void handle(List<BufferAccess> ls) {
boolean isVisible = true;
if (logTable.getRowCount() > 0) {
@ -276,18 +282,22 @@ public class BufferListener extends VisPlugin {
model = new AbstractTableModel() {
private static final long serialVersionUID = 3065150390849332924L;
@Override
public String getColumnName(int col) {
if (col == COLUMN_TIME && formatTimeString) {
return "Time";
}
return COLUMN_NAMES[col];
}
@Override
public int getRowCount() {
return logs.size();
}
@Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
@Override
public Object getValueAt(int row, int col) {
BufferAccess log = logs.get(row);
if (col == COLUMN_TIME) {
@ -307,6 +317,7 @@ public class BufferListener extends VisPlugin {
logTable = new JTable(model) {
private static final long serialVersionUID = -930616018336483196L;
@Override
public String getToolTipText(MouseEvent e) {
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
@ -356,6 +367,7 @@ public class BufferListener extends VisPlugin {
new Color(220, 255, 220),
new Color(255, 200, 255),
};
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
@ -405,6 +417,7 @@ public class BufferListener extends VisPlugin {
logTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
logTable.setFont(new Font("Monospaced", Font.PLAIN, 12));
logTable.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
showInAllAction.actionPerformed(null);
@ -419,6 +432,7 @@ public class BufferListener extends VisPlugin {
/* Toggle time format */
logTable.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int colIndex = logTable.columnAtPoint(e.getPoint());
int columnIndex = logTable.convertColumnIndexToModel(colIndex);
@ -432,6 +446,7 @@ public class BufferListener extends VisPlugin {
});
logTable.addMouseListener(new MouseAdapter() {
private Parser lastParser = null;
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON2) {
return;
@ -444,6 +459,7 @@ public class BufferListener extends VisPlugin {
setParser(ByteArrayParser.class);
}
}
@Override
public void mouseExited(MouseEvent e) {
if (lastParser != null) {
/* Switch back to previous parser */
@ -451,6 +467,7 @@ public class BufferListener extends VisPlugin {
lastParser = null;
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (lastParser != null) {
/* Switch back to previous parser */
@ -458,6 +475,7 @@ public class BufferListener extends VisPlugin {
lastParser = null;
}
}
@Override
public void mouseClicked(MouseEvent e) {
int colIndex = logTable.columnAtPoint(e.getPoint());
int columnIndex = logTable.convertColumnIndexToModel(colIndex);
@ -482,21 +500,27 @@ public class BufferListener extends VisPlugin {
/* Popup menu */
JPopupMenu popupMenu = new JPopupMenu();
bufferMenu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(MenuEvent e) {
updateBufferMenu();
}
@Override
public void menuDeselected(MenuEvent e) {
}
@Override
public void menuCanceled(MenuEvent e) {
}
});
popupMenu.add(bufferMenu);
parserMenu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(MenuEvent e) {
updateParserMenu();
}
@Override
public void menuDeselected(MenuEvent e) {
}
@Override
public void menuCanceled(MenuEvent e) {
}
});
@ -521,6 +545,7 @@ public class BufferListener extends VisPlugin {
colorCheckbox = new JCheckBoxMenuItem("Mote-specific coloring");
popupMenu.add(colorCheckbox);
colorCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
backgroundColors = colorCheckbox.isSelected();
repaint();
@ -529,6 +554,7 @@ public class BufferListener extends VisPlugin {
inverseFilterCheckbox = new JCheckBoxMenuItem("Inverse filter");
popupMenu.add(inverseFilterCheckbox);
inverseFilterCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
inverseFilter = inverseFilterCheckbox.isSelected();
if (inverseFilter) {
@ -543,6 +569,7 @@ public class BufferListener extends VisPlugin {
hideReadsCheckbox = new JCheckBoxMenuItem("Hide READs", hideReads);
popupMenu.add(hideReadsCheckbox);
hideReadsCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hideReads = hideReadsCheckbox.isSelected();
setFilter(getFilter());
@ -553,6 +580,7 @@ public class BufferListener extends VisPlugin {
withStackTraceCheckbox = new JCheckBoxMenuItem("Capture stack traces", withStackTrace);
popupMenu.add(withStackTraceCheckbox);
withStackTraceCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
withStackTrace = withStackTraceCheckbox.isSelected();
setFilter(getFilter());
@ -564,6 +592,7 @@ public class BufferListener extends VisPlugin {
/* Column width adjustment */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
/* Make sure this happens *after* adding history */
adjuster.setDynamicAdjustment(true);
@ -573,6 +602,7 @@ public class BufferListener extends VisPlugin {
logUpdateAggregator.start();
simulation.getEventCentral().addMoteCountListener(logOutputListener = new MoteCountListener() {
@Override
public void moteWasAdded(Mote mote) {
/* Update title */
try {
@ -581,6 +611,7 @@ public class BufferListener extends VisPlugin {
logger.warn("Could not monitor buffer on: " + mote, e);
}
}
@Override
public void moteWasRemoved(Mote mote) {
/* Update title */
stopObserving(mote);
@ -596,12 +627,14 @@ public class BufferListener extends VisPlugin {
filterPanel.add(filterLabel);
filterPanel.add(filterTextField);
filterTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String str = filterTextField.getText();
setFilter(str);
/* Autoscroll */
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
int s = logTable.getSelectedRow();
if (s < 0) {
@ -664,23 +697,24 @@ public class BufferListener extends VisPlugin {
private void registerSegmentMonitor(int size, boolean notify) throws Exception {
byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize);
int segmentAddress = mote.getMemory().parseInt(pointerValue);
int segmentAddress = MemoryBuffer.wrap(mote.getMemory().getLayout(), pointerValue).getInt();
segmentMonitor = new SegmentMemoryMonitor(bl, mote, segmentAddress, size);
if (notify) {
segmentMonitor.memoryChanged(mote.getMemory(), MemoryEventType.WRITE, -1);
segmentMonitor.memoryChanged(mote.getMemory(), EventType.WRITE, -1);
}
lastSegmentAddress = segmentAddress;
}
final public void memoryChanged(MoteMemory memory,
org.contikios.cooja.MoteMemory.MemoryEventType type, int address) {
if (type == MemoryEventType.READ) {
@Override
final public void memoryChanged(MemoryInterface memory,
EventType type, long address) {
if (type == EventType.READ) {
return;
}
byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize);
int segmentAddress = mote.getMemory().parseInt(pointerValue);
int segmentAddress = MemoryBuffer.wrap(mote.getMemory().getLayout(), pointerValue).getInt();
if (segmentAddress == lastSegmentAddress) {
return;
}
@ -694,17 +728,19 @@ public class BufferListener extends VisPlugin {
}
}
@Override
public MemoryMonitorType getType() {
return MemoryMonitorType.POINTER;
}
@Override
public void dispose() {
super.dispose();
segmentMonitor.dispose();
}
}
static class SegmentMemoryMonitor implements org.contikios.cooja.MoteMemory.MemoryMonitor {
static class SegmentMemoryMonitor implements SegmentMonitor {
protected final BufferListener bl;
protected final Mote mote;
@ -721,7 +757,7 @@ public class BufferListener extends VisPlugin {
this.size = size;
if (address != 0) {
if (!mote.getMemory().addMemoryMonitor(address, size, this)) {
if (!mote.getMemory().addSegmentMonitor(SegmentMonitor.EventType.WRITE, address, size, this)) {
throw new Exception("Could not register memory monitor on: " + mote);
}
}
@ -742,17 +778,18 @@ public class BufferListener extends VisPlugin {
public void dispose() {
if (address != 0) {
mote.getMemory().removeMemoryMonitor(address, size, this);
mote.getMemory().removeSegmentMonitor(address, size, this);
}
}
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) {
@Override
public void memoryChanged(MemoryInterface memory, EventType type, long address) {
byte[] newData = getAddress()==0?null:mote.getMemory().getMemorySegment(getAddress(), getSize());
addBufferAccess(bl, mote, oldData, newData, type, this.address);
oldData = newData;
}
void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, MemoryEventType type, int address) {
void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, EventType type, int address) {
BufferAccess ba = new BufferAccess(
mote,
mote.getSimulation().getSimulationTime(),
@ -793,6 +830,7 @@ public class BufferListener extends VisPlugin {
}
}
@Override
public void closePlugin() {
if (hourTimeEvent != null) hourTimeEvent.remove();
@ -805,6 +843,7 @@ public class BufferListener extends VisPlugin {
}
}
@Override
public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element;
@ -845,12 +884,14 @@ public class BufferListener extends VisPlugin {
return config;
}
@Override
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
for (Element element : configXML) {
String name = element.getName();
if ("filter".equals(name)) {
final String str = element.getText();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
setFilter(str);
}
@ -914,10 +955,11 @@ public class BufferListener extends VisPlugin {
regexp = null;
}
RowFilter<Object, Object> wrapped = new RowFilter<Object, Object>() {
@Override
public boolean include(RowFilter.Entry<? extends Object, ? extends Object> entry) {
if (hideReads) {
int row = (Integer) entry.getIdentifier();
if (logs.get(row).type == MemoryEventType.READ) {
if (logs.get(row).type == SegmentMonitor.EventType.READ) {
return false;
}
}
@ -945,6 +987,7 @@ public class BufferListener extends VisPlugin {
public void trySelectTime(final long time) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
for (int i=0; i < logs.size(); i++) {
if (logs.get(i).time < time) {
@ -972,13 +1015,13 @@ public class BufferListener extends VisPlugin {
public final byte[] mem;
private boolean[] accessedBitpattern = null;
public final MemoryEventType type;
public final SegmentMonitor.EventType type;
public final String sourceStr;
public final String stackTrace;
public final int address;
public BufferAccess(
Mote mote, long time, int address, byte[] newData, byte[] oldData, MemoryEventType type, boolean withStackTrace) {
Mote mote, long time, int address, byte[] newData, byte[] oldData, SegmentMonitor.EventType type, boolean withStackTrace) {
this.mote = mote;
this.time = time;
this.mem = newData==null?NULL_DATA:newData;
@ -1054,6 +1097,7 @@ public class BufferListener extends VisPlugin {
private Action saveAction = new AbstractAction("Save to file") {
private static final long serialVersionUID = -4140706275748686944L;
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
File suggest = new File(Cooja.getExternalToolsSetting("BUFFER_LISTENER_SAVEFILE", "BufferAccessLogger.txt"));
@ -1116,6 +1160,7 @@ public class BufferListener extends VisPlugin {
private Action bufferListenerAction = new AbstractAction("in Buffer Listener") {
private static final long serialVersionUID = -6358463434933029699L;
@Override
public void actionPerformed(ActionEvent e) {
int view = logTable.getSelectedRow();
if (view < 0) {
@ -1139,6 +1184,7 @@ public class BufferListener extends VisPlugin {
private Action timeLineAction = new AbstractAction("in Timeline") {
private static final long serialVersionUID = -6358463434933029699L;
@Override
public void actionPerformed(ActionEvent e) {
int view = logTable.getSelectedRow();
if (view < 0) {
@ -1162,6 +1208,7 @@ public class BufferListener extends VisPlugin {
private Action radioLoggerAction = new AbstractAction("in Radio Logger") {
private static final long serialVersionUID = -3041714249257346688L;
@Override
public void actionPerformed(ActionEvent e) {
int view = logTable.getSelectedRow();
if (view < 0) {
@ -1189,6 +1236,7 @@ public class BufferListener extends VisPlugin {
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true));
}
@Override
public void actionPerformed(ActionEvent e) {
timeLineAction.actionPerformed(null);
radioLoggerAction.actionPerformed(null);
@ -1197,6 +1245,7 @@ public class BufferListener extends VisPlugin {
private Action clearAction = new AbstractAction("Clear") {
private static final long serialVersionUID = -2115620313183440224L;
@Override
public void actionPerformed(ActionEvent e) {
int size = logs.size();
if (size > 0) {
@ -1208,6 +1257,7 @@ public class BufferListener extends VisPlugin {
private Action copyAction = new AbstractAction("Selected") {
private static final long serialVersionUID = -8433490108577001803L;
@Override
public void actionPerformed(ActionEvent e) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -1240,6 +1290,7 @@ public class BufferListener extends VisPlugin {
private Action copyAllAction = new AbstractAction("All") {
private static final long serialVersionUID = -5038884975254178373L;
@Override
public void actionPerformed(ActionEvent e) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -1269,6 +1320,7 @@ public class BufferListener extends VisPlugin {
private final ActionListener parserSelectedListener = new ActionListener() {
@SuppressWarnings("unchecked")
@Override
public void actionPerformed(ActionEvent e) {
Class<? extends Parser> bpClass =
(Class<? extends Parser>)
@ -1289,6 +1341,7 @@ public class BufferListener extends VisPlugin {
private final ActionListener bufferSelectedListener = new ActionListener() {
@SuppressWarnings("unchecked")
@Override
public void actionPerformed(ActionEvent e) {
Class<? extends Buffer> btClass =
(Class<? extends Buffer>)
@ -1421,6 +1474,7 @@ public class BufferListener extends VisPlugin {
}
public static abstract class GraphicalParser implements Parser {
BufferAccess ba = null;
@Override
public Object parse(BufferAccess ba) {
this.ba = ba;
return ba;
@ -1430,6 +1484,7 @@ public class BufferListener extends VisPlugin {
}
public static abstract class StringParser implements Parser {
@Override
public Object parse(BufferAccess ba) {
return parseString(ba);
}
@ -1459,13 +1514,17 @@ public class BufferListener extends VisPlugin {
public void writeConfig(Element element);
}
public static abstract class AbstractBuffer implements Buffer {
@Override
public String getStatusString() {
return null;
}
@Override
public void writeConfig(Element element) {
}
@Override
public void applyConfig(Element element) {
}
@Override
public boolean configure(BufferListener bl) {
return true;
}
@ -1474,18 +1533,20 @@ public class BufferListener extends VisPlugin {
public static abstract class PointerBuffer extends AbstractBuffer {
public abstract int getPointerAddress(Mote mote);
@Override
public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote)
throws Exception {
return new PointerMemoryMonitor(
bl,
mote,
getPointerAddress(mote),
mote.getMemory().getIntegerLength(),
mote.getMemory().getLayout().intSize,
getSize(mote)
);
}
}
public static abstract class SegmentBuffer extends AbstractBuffer {
@Override
public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote)
throws Exception {
return new SegmentMemoryMonitor(
@ -1521,6 +1582,7 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Byte array")
public static class ByteArrayParser extends StringParser {
@Override
public String parseString(BufferAccess ba) {
boolean[] diff = ba.getAccessedBitpattern();
if (diff == null) {
@ -1562,15 +1624,18 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Integer array")
public static class IntegerParser extends StringParser {
private VarMemory varMem = new VarMemory(null);
@Override
public String parseString(BufferAccess ba) {
StringBuilder sb = new StringBuilder();
varMem.associateMemory(ba.mote.getMemory());
int intLen = ba.mote.getMemory().getIntegerLength();
int intLen = ba.mote.getMemory().getLayout().intSize;
sb.append("<html>");
for (int i=0; i < ba.mem.length/intLen; i++) {
byte[] mem = Arrays.copyOfRange(ba.mem, i*intLen,(i+1)*intLen);
boolean[] diff = Arrays.copyOfRange(ba.getAccessedBitpattern(), i*intLen,(i+1)*intLen);
int val = ba.mote.getMemory().parseInt(mem);
int val = MemoryBuffer.wrap(ba.mote.getMemory().getLayout(), mem).getInt();
boolean red = false;
for (boolean changed: diff) {
@ -1592,6 +1657,7 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Terminated string")
public static class TerminatedStringParser extends StringParser {
@Override
public String parseString(BufferAccess ba) {
/* TODO Diff? */
int i;
@ -1608,6 +1674,7 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Printable characters")
public static class PrintableCharactersParser extends StringParser {
@Override
public String parseString(BufferAccess ba) {
/* TODO Diff? */
return new String(ba.mem).replaceAll("[^\\p{Print}]", "");
@ -1616,6 +1683,7 @@ public class BufferListener extends VisPlugin {
@ClassDescription("IPv6 address")
public static class IPv6AddressParser extends StringParser {
@Override
public String parseString(BufferAccess ba) {
/* TODO Diff? */
if (ba.mem.length < 16) {
@ -1634,6 +1702,7 @@ public class BufferListener extends VisPlugin {
@ClassDescription("IPv4 address")
public static class IPv4AddressParser extends StringParser {
@Override
public String parseString(BufferAccess ba) {
/* TODO Diff? */
if (ba.mem.length < 4) {
@ -1664,6 +1733,7 @@ public class BufferListener extends VisPlugin {
parser.ba = ba;
setPreferredSize(new Dimension(parser.getUnscaledWidth() + 2*XOFFSET, HEIGHT));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.translate(XOFFSET, 0);
@ -1681,9 +1751,11 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Graphical: Height")
public static class GraphicalHeight4BitsParser extends GraphicalParser {
@Override
public int getUnscaledWidth() {
return ba.mem.length*2;
}
@Override
public void paintComponent(Graphics g, JComponent c) {
g.setColor(Color.GRAY);
boolean[] diff = ba.getAccessedBitpattern();
@ -1707,9 +1779,11 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Graphical: Grayscale")
public static class GraphicalGrayscale4BitsParser extends GraphicalParser {
@Override
public int getUnscaledWidth() {
return ba.mem.length*2;
}
@Override
public void paintComponent(Graphics g, JComponent c) {
boolean[] diff = ba.getAccessedBitpattern();
for (int x=0; x < ba.mem.length; x++) {
@ -1730,27 +1804,31 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Variable: node_id")
public static class NodeIDBuffer extends SegmentBuffer {
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists("node_id")) {
if (!mote.getMemory().getSymbolMap().containsKey("node_id")) {
return -1;
}
return mote.getMemory().getVariableAddress("node_id");
return (int) mote.getMemory().getSymbolMap().get("node_id").addr;
}
@Override
public int getSize(Mote mote) {
return mote.getMemory().getIntegerLength();
return mote.getMemory().getLayout().intSize;
}
}
@ClassDescription("Queuebuf 0 RAM")
public static class Queuebuf0Buffer extends SegmentBuffer {
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists("buframmem")) {
if (!mote.getMemory().getSymbolMap().containsKey("buframmem")) {
return -1;
}
int offset = 0;
return mote.getMemory().getVariableAddress("buframmem") + offset;
return (int) mote.getMemory().getSymbolMap().get("buframmem").addr + offset;
}
@Override
public int getSize(Mote mote) {
return 128;
}
@ -1758,12 +1836,14 @@ public class BufferListener extends VisPlugin {
@ClassDescription("packetbuf_aligned")
public static class PacketbufBuffer extends SegmentBuffer {
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists("packetbuf_aligned")) {
if (!mote.getMemory().getSymbolMap().containsKey("packetbuf_aligned")) {
return -1;
}
return mote.getMemory().getVariableAddress("packetbuf_aligned");
return (int) mote.getMemory().getSymbolMap().get("packetbuf_aligned").addr;
}
@Override
public int getSize(Mote mote) {
return 128;
}
@ -1771,18 +1851,23 @@ public class BufferListener extends VisPlugin {
@ClassDescription("*packetbufptr")
public static class PacketbufPointerBuffer extends PointerBuffer {
VarMemory varMem = new VarMemory(null);
@Override
public int getPointerAddress(Mote mote) {
if (!mote.getMemory().variableExists("packetbufptr")) {
if (!mote.getMemory().getSymbolMap().containsKey("packetbufptr")) {
return -1;
}
return mote.getMemory().getVariableAddress("packetbufptr");
return (int) mote.getMemory().getSymbolMap().get("packetbufptr").addr;
}
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists("packetbufptr")) {
if (!mote.getMemory().getSymbolMap().containsKey("packetbufptr")) {
return -1;
}
return mote.getMemory().getIntValueOf("packetbufptr");
varMem.associateMemory(mote.getMemory());
return varMem.getIntValueOf("packetbufptr");
}
@Override
public int getSize(Mote mote) {
return 128;
}
@ -1793,25 +1878,31 @@ public class BufferListener extends VisPlugin {
public String variable;
public int size;
public int offset;
VarMemory varMem = new VarMemory(null);
@Override
public int getPointerAddress(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return mote.getMemory().getVariableAddress(variable);
return (int) mote.getMemory().getSymbolMap().get(variable).addr;
}
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return mote.getMemory().getIntValueOf(variable)+offset;
varMem.associateMemory(mote.getMemory());
return varMem.getIntValueOf(variable)+offset;
}
@Override
public int getSize(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return size;
}
@Override
public String getStatusString() {
if (offset > 0) {
return "Pointer *" + variable + "[" + offset + "] (" + size + ")";
@ -1820,16 +1911,19 @@ public class BufferListener extends VisPlugin {
}
}
@Override
public void writeConfig(Element element) {
element.setAttribute("variable", variable);
element.setAttribute("size", "" + size);
element.setAttribute("offset", "" + offset);
}
@Override
public void applyConfig(Element element) {
variable = element.getAttributeValue("variable");
size = Integer.parseInt(element.getAttributeValue("size"));
offset = Integer.parseInt(element.getAttributeValue("offset"));
}
@Override
public boolean configure(BufferListener bl) {
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
String suggestSize = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2");
@ -1880,19 +1974,22 @@ public class BufferListener extends VisPlugin {
public String variable;
public int size;
public int offset;
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return mote.getMemory().getVariableAddress(variable)+offset;
return (int) mote.getMemory().getSymbolMap().get(variable).addr+offset;
}
@Override
public int getSize(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return size;
}
@Override
public String getStatusString() {
if (offset > 0) {
return "Symbol &" + variable + "[" + offset + "] (" + size + ")";
@ -1901,16 +1998,19 @@ public class BufferListener extends VisPlugin {
}
}
@Override
public void writeConfig(Element element) {
element.setAttribute("variable", variable);
element.setAttribute("size", "" + size);
element.setAttribute("offset", "" + offset);
}
@Override
public void applyConfig(Element element) {
variable = element.getAttributeValue("variable");
size = Integer.parseInt(element.getAttributeValue("size"));
offset = Integer.parseInt(element.getAttributeValue("offset"));
}
@Override
public boolean configure(BufferListener bl) {
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
String suggestSize = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2");
@ -1958,26 +2058,32 @@ public class BufferListener extends VisPlugin {
@ClassDescription("Integer...")
public static class CustomIntegerBuffer extends SegmentBuffer {
public String variable;
@Override
public int getAddress(Mote mote) {
if (!mote.getMemory().variableExists(variable)) {
if (!mote.getMemory().getSymbolMap().containsKey(variable)) {
return -1;
}
return mote.getMemory().getVariableAddress(variable);
return (int) mote.getMemory().getSymbolMap().get(variable).addr;
}
@Override
public int getSize(Mote mote) {
return mote.getMemory().getIntegerLength();
return mote.getMemory().getLayout().intSize;
}
@Override
public String getStatusString() {
return "Integer " + variable;
}
@Override
public void writeConfig(Element element) {
element.setAttribute("variable", variable);
}
@Override
public void applyConfig(Element element) {
variable = element.getAttributeValue("variable");
}
@Override
public boolean configure(BufferListener bl) {
String suggestName = Cooja.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id");
BufferInput infoComponent =

View file

@ -44,8 +44,10 @@ import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import javax.swing.BorderFactory;
@ -64,7 +66,6 @@ import javax.swing.text.PlainDocument;
import org.jdom.Element;
import org.contikios.cooja.AddressMemory;
import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Cooja;
import org.contikios.cooja.Mote;
@ -72,7 +73,8 @@ import org.contikios.cooja.MotePlugin;
import org.contikios.cooja.PluginType;
import org.contikios.cooja.Simulation;
import org.contikios.cooja.VisPlugin;
import org.contikios.cooja.AddressMemory.UnknownVariableException;
import org.contikios.cooja.mote.memory.UnknownVariableException;
import org.contikios.cooja.mote.memory.VarMemory;
/**
* Variable Watcher enables a user to watch mote variables during a simulation.
@ -87,7 +89,7 @@ import org.contikios.cooja.AddressMemory.UnknownVariableException;
public class VariableWatcher extends VisPlugin implements MotePlugin {
private static final long serialVersionUID = 1L;
private AddressMemory moteMemory;
private VarMemory moteMemory;
private final static int LABEL_WIDTH = 170;
private final static int LABEL_HEIGHT = 15;
@ -124,7 +126,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
public VariableWatcher(Mote moteToView, Simulation simulation, Cooja gui) {
super("Variable Watcher (" + moteToView + ")", gui);
this.mote = moteToView;
moteMemory = (AddressMemory) moteToView.getMemory();
moteMemory = new VarMemory(moteToView.getMemory());
JLabel label;
integerFormat = NumberFormat.getIntegerInstance();
@ -143,8 +145,8 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
varName.setEditable(true);
varName.setSelectedItem("[enter or pick name]");
String[] allPotentialVarNames = moteMemory.getVariableNames();
Arrays.sort(allPotentialVarNames);
List<String> allPotentialVarNames = new ArrayList<>(moteMemory.getVariableNames());
Collections.sort(allPotentialVarNames);
for (String aVarName: allPotentialVarNames) {
varName.addItem(aVarName);
}
@ -172,7 +174,7 @@ public class VariableWatcher extends VisPlugin implements MotePlugin {
varType = new JComboBox();
varType.addItem("Byte (1 byte)"); // BYTE_INDEX = 0
varType.addItem("Integer (" + moteMemory.getIntegerLength() + " bytes)"); // INT_INDEX = 1
varType.addItem("Integer (" + moteToView.getMemory().getLayout().intSize + " bytes)"); // INT_INDEX = 1
varType.addItem("Byte array (x bytes)"); // ARRAY_INDEX = 2
varType.addItem("Char array (x bytes)"); // CHAR_ARRAY_INDEX = 3