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 * Copyright (c) 2009, Swedish Institute of Computer Science. All rights
* reserved. * reserved.
* *
@ -28,27 +29,37 @@
package org.contikios.cooja.avrmote; package org.contikios.cooja.avrmote;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.contikios.cooja.AddressMemory;
import org.contikios.cooja.MoteMemory;
import avrora.arch.avr.AVRProperties; import avrora.arch.avr.AVRProperties;
import avrora.core.SourceMapping; import avrora.core.SourceMapping;
import avrora.core.SourceMapping.Location; import avrora.core.SourceMapping.Location;
import avrora.sim.AtmelInterpreter; import avrora.sim.AtmelInterpreter;
import avrora.sim.Simulator.Watch; 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 { public class AvrMoteMemory implements MemoryInterface {
private static Logger logger = Logger.getLogger(AvrMoteMemory.class); private static Logger logger = Logger.getLogger(AvrMoteMemory.class);
private static final boolean DEBUG = logger.isDebugEnabled();
private SourceMapping memoryMap; private final SourceMapping memoryMap;
private AtmelInterpreter interpreter; private final AVRProperties avrProperties;
private 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) { public AvrMoteMemory(SourceMapping map, AVRProperties avrProperties, AtmelInterpreter interpreter) {
memoryMap = map; memoryMap = map;
@ -56,130 +67,158 @@ public class AvrMoteMemory implements MoteMemory, AddressMemory {
this.avrProperties = avrProperties; this.avrProperties = avrProperties;
} }
public void insertWatch(Watch w, int address) { @Override
interpreter.getSimulator().insertWatch(w, address);
}
public void clearMemory() {
logger.fatal("not implemented");
}
public byte[] getMemorySegment(int address, int size) {
logger.fatal("getMemorySegment is not implemented");
return null;
}
public int getTotalSize() { public int getTotalSize() {
return 0; return avrProperties.sram_size;
} }
public void setMemorySegment(int address, byte[] data) { @Override
logger.fatal("setMemorySegment is not implemented"); public byte[] getMemory() throws MoteMemoryException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
} }
public byte[] getByteArray(String varName, int length) @Override
throws UnknownVariableException { public byte[] getMemorySegment(long address, int size) throws MoteMemoryException {
return null; /*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 byte getByteValueOf(String varName) throws UnknownVariableException { /* XXX Unsure whether this is the appropriate method to use, as it
return (byte) getValueOf(varName, 1); * 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. */
private int getValueOf(String varName, int len) throws UnknownVariableException { coojaIsAccessingMemory = true;
Location mem = memoryMap.getLocation(varName); byte[] data = new byte[(int) size];
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName); for (int i = 0; i < size; i++) {
data[i] = (byte) (interpreter.getDataByte((int) address + i) & 0xff);
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;
}
} }
coojaIsAccessingMemory = false;
return data; return data;
} }
private void setValue(String varName, int val, int len) throws UnknownVariableException { @Override
Location mem = memoryMap.getLocation(varName); public void setMemorySegment(long address, byte[] data) throws MoteMemoryException {
if (mem == null) throw new UnknownVariableException("Variable does not exist: " + varName); if (!accessInRange(address, data.length)) {
throw new MoteMemoryException(
"Writing memory segment [0x%x,0x%x] failed: Out of range",
address, address + data.length - 1);
}
int data = val; /* XXX See comment in getMemorySegment. */
if (mem.vma_addr > 0xfffff) { coojaIsAccessingMemory = true;
// write LSB first. for (int i = 0; i < data.length; i++) {
for (int i = 0; i < len; i++) { interpreter.writeDataByte((int) address + i, data[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;
} }
coojaIsAccessingMemory = false;
if (DEBUG) {
logger.debug(String.format(
"Wrote memory segment [0x%x,0x%x]",
address, address + data.length - 1));
} }
} }
public int getIntValueOf(String varName) throws UnknownVariableException { @Override
return getValueOf(varName, 2); public void clearMemory() {
setMemorySegment(0L, new byte[avrProperties.sram_size]);
} }
public int getIntegerLength() { private boolean accessInRange(long address, int size) {
return 2; return (address >= 0) && (address + size <= avrProperties.sram_size);
} }
public int getVariableAddress(String varName) @Override
throws UnknownVariableException { public long getStartAddr() {
return 0; return 0;// XXX
} }
public String[] getVariableNames() { @Override
ArrayList<String> symbols = new ArrayList<String>(); public Map<String, Symbol> getSymbolMap() {
for (Iterator i = memoryMap.getIterator(); i.hasNext();) { // XXX do not fetch in function!
symbols.add(((Location) i.next()).name); 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;
} }
return symbols.toArray(new String[0]); symbols.put(loc.name, new Symbol(Symbol.Type.VARIABLE, loc.name, loc.section, loc.vma_addr & 0x7fffff, -1));
}
return symbols;
} }
public void setByteArray(String varName, byte[] data)
throws UnknownVariableException { @Override
public MemoryLayout getLayout() {
return memLayout;
} }
public void setByteValueOf(String varName, byte newVal) class AvrByteMonitor extends Watch.Empty {
throws UnknownVariableException {
setValue(varName, newVal, 1); /** 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 void setIntValueOf(String varName, int newVal) @Override
throws UnknownVariableException { public void fireAfterRead(State state, int data_addr, byte value) {
setValue(varName, newVal, 2); if (flag == EventType.WRITE || coojaIsAccessingMemory) {
return;
}
mm.memoryChanged(AvrMoteMemory.this, EventType.READ, data_addr);
} }
public boolean variableExists(String varName) { @Override
return memoryMap.getLocation(varName) != null; 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 boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) { @Override
logger.warn("Not implemented"); 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;
}
@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; 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.Mote;
import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler; import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType; import org.contikios.cooja.MoteType;
import org.contikios.cooja.Simulation; import org.contikios.cooja.Simulation;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.motes.AbstractEmulatedMote; import org.contikios.cooja.motes.AbstractEmulatedMote;
import avrora.arch.avr.AVRProperties; import avrora.arch.avr.AVRProperties;
import avrora.core.LoadableProgram; import avrora.core.LoadableProgram;
@ -264,11 +264,12 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote {
return config; return config;
} }
public MoteMemory getMemory() { @Override
public MemoryInterface getMemory() {
return myMemory; return myMemory;
} }
public void setMemory(MoteMemory memory) { public void setMemory(AvrMoteMemory memory) {
myMemory = (AvrMoteMemory) memory; myMemory = (AvrMoteMemory) memory;
} }

View file

@ -38,16 +38,15 @@ import javax.swing.JPanel;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import avrora.sim.State;
import avrora.sim.Simulator.Watch;
import org.contikios.cooja.Mote; import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteTimeEvent; import org.contikios.cooja.MoteTimeEvent;
import org.contikios.cooja.Simulation; import org.contikios.cooja.Simulation;
import org.contikios.cooja.TimeEvent; import org.contikios.cooja.TimeEvent;
import org.contikios.cooja.avrmote.AvrMoteMemory;
import org.contikios.cooja.avrmote.MicaZMote; import org.contikios.cooja.avrmote.MicaZMote;
import org.contikios.cooja.interfaces.MoteID; 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 { public class MicaZID extends MoteID {
@ -57,7 +56,7 @@ public class MicaZID extends MoteID {
private int moteID = -1; /* TODO Implement */ private int moteID = -1; /* TODO Implement */
private AvrMoteMemory moteMem; private VarMemory moteMem;
boolean tosID = false; boolean tosID = false;
boolean contikiID = false; boolean contikiID = false;
private MicaZMote mote; private MicaZMote mote;
@ -80,23 +79,26 @@ public class MicaZID extends MoteID {
public MicaZID(Mote mote) { public MicaZID(Mote mote) {
this.mote = (MicaZMote) mote; this.mote = (MicaZMote) mote;
this.moteMem = (AvrMoteMemory) mote.getMemory(); this.moteMem = new VarMemory(mote.getMemory());
if (moteMem.variableExists("node_id")) { if (moteMem.variableExists("node_id")) {
contikiID = true; contikiID = true;
int addr = moteMem.getVariableAddress("node_id"); int addr = (int) moteMem.getVariableAddress("node_id");
moteMem.insertWatch(new Watch() { moteMem.addVarMonitor(
public void fireAfterRead(State arg0, int arg1, byte arg2) { SegmentMonitor.EventType.READWRITE,
System.out.println("Read from node_id: " + arg2); "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")) { 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.Mote;
import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler; import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType; import org.contikios.cooja.MoteType;
import org.contikios.cooja.Simulation; import org.contikios.cooja.Simulation;
import org.contikios.cooja.Watchpoint; import org.contikios.cooja.Watchpoint;
import org.contikios.cooja.WatchpointMote; import org.contikios.cooja.WatchpointMote;
import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.IPAddress;
import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.motes.AbstractEmulatedMote; import org.contikios.cooja.motes.AbstractEmulatedMote;
import org.contikios.cooja.mspmote.interfaces.Msp802154Radio; import org.contikios.cooja.mspmote.interfaces.Msp802154Radio;
import org.contikios.cooja.mspmote.interfaces.MspSerial; import org.contikios.cooja.mspmote.interfaces.MspSerial;
@ -185,12 +185,13 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
myCpu = cpu; myCpu = cpu;
} }
public MoteMemory getMemory() { @Override
public MemoryInterface getMemory() {
return myMemory; return myMemory;
} }
public void setMemory(MoteMemory memory) { public void setMemory(MspMoteMemory memory) {
myMemory = (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 * Copyright (c) 2007, Swedish Institute of Computer Science. All rights
* reserved. * reserved.
* *
@ -28,21 +29,27 @@
package org.contikios.cooja.mspmote; package org.contikios.cooja.mspmote;
import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.contikios.cooja.AddressMemory;
import org.contikios.cooja.Mote; 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.MSP430;
import se.sics.mspsim.core.Memory.AccessMode; import se.sics.mspsim.core.Memory.AccessMode;
import se.sics.mspsim.core.Memory.AccessType; import se.sics.mspsim.core.Memory.AccessType;
import se.sics.mspsim.util.MapEntry; 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 static Logger logger = Logger.getLogger(MspMoteMemory.class);
private final ArrayList<MapEntry> mapEntries; private final ArrayList<MapEntry> mapEntries;
private final MemoryLayout memLayout;
private final MSP430 cpu; private final MSP430 cpu;
@ -56,42 +63,24 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
} }
this.cpu = cpu; this.cpu = cpu;
memLayout = new MemoryLayout(ByteOrder.LITTLE_ENDIAN, MemoryLayout.ARCH_16BIT, 2);
} }
public String[] getVariableNames() { @Override
String[] names = new String[mapEntries.size()]; public int getTotalSize() {
for (int i = 0; i < mapEntries.size(); i++) { return cpu.memory.length;
names[i] = mapEntries.get(i).getName();
}
return names;
} }
private MapEntry getMapEntry(String varName) throws UnknownVariableException { @Override
for (MapEntry entry: mapEntries) { public byte[] getMemory() throws MoteMemoryException {
if (entry.getName().equals(varName)) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
return entry;
}
}
throw new UnknownVariableException(varName);
} }
public int getVariableAddress(String varName) throws UnknownVariableException { @Override
MapEntry entry = getMapEntry(varName); public byte[] getMemorySegment(long address, int size) {
return entry.getAddress();
}
public int getIntegerLength() {
return 2;
}
public void clearMemory() {
logger.fatal("clearMemory() not implemented");
}
public byte[] getMemorySegment(int address, int size) {
int[] memInts = new 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 */ /* Convert to byte array */
byte[] memBytes = new byte[size]; byte[] memBytes = new byte[size];
@ -102,97 +91,57 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
return memBytes; return memBytes;
} }
public void setMemorySegment(int address, byte[] data) { @Override
public void setMemorySegment(long address, byte[] data) {
/* Convert to int array */ /* Convert to int array */
int[] memInts = new int[data.length]; 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]; 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() { @Override
return cpu.memory.length; public void clearMemory() {
Arrays.fill(cpu.memory, 0);
} }
public boolean variableExists(String varName) { @Override
public long getStartAddr() {
return 0;// XXXX
}
@Override
public Map<String, Symbol> getSymbolMap() {
Map<String, Symbol> vars = new HashMap<>();
for (MapEntry entry : mapEntries) { for (MapEntry entry : mapEntries) {
if (entry.getName().equals(varName)) { if (entry.getType() != MapEntry.TYPE.variable) {
return true; continue;
} }
vars.put(entry.getName(), new Symbol(
Symbol.Type.VARIABLE,
entry.getName(),
entry.getAddress(),
entry.getSize()));
}
return vars;
} }
return false; @Override
public MemoryLayout getLayout() {
return memLayout;
} }
/* TODO Check correct variable size in below methods */ private final ArrayList<MemoryCPUMonitor> cpuMonitorArray = new ArrayList<>();
public int getIntValueOf(String varName) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
byte[] varData = getMemorySegment(varAddr, 2);
return parseInt(varData);
}
public void setIntValueOf(String varName, int newVal) throws UnknownVariableException {
MapEntry entry = getMapEntry(varName);
int varAddr = entry.getAddress();
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 { class MemoryCPUMonitor extends se.sics.mspsim.core.MemoryMonitor.Adapter {
public final MemoryMonitor mm;
public final SegmentMonitor mm;
public final int address; public final int address;
public final int size; public final int size;
public MemoryCPUMonitor(MemoryMonitor mm, int address, int size) { public MemoryCPUMonitor(SegmentMonitor mm, int address, int size) {
this.mm = mm; this.mm = mm;
this.address = address; this.address = address;
this.size = size; this.size = size;
@ -200,49 +149,39 @@ public class MspMoteMemory implements MoteMemory, AddressMemory {
@Override @Override
public void notifyReadAfter(int address, AccessMode mode, AccessType type) { public void notifyReadAfter(int address, AccessMode mode, AccessType type) {
mm.memoryChanged(MspMoteMemory.this, MemoryEventType.READ, address); mm.memoryChanged(MspMoteMemory.this, EventType.READ, address);
} }
@Override @Override
public void notifyWriteAfter(int dstAddress, int data, AccessMode mode) { 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) { @Override
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, address, size); public boolean addSegmentMonitor(EventType type, long address, int size, SegmentMonitor mm) {
MemoryCPUMonitor t = new MemoryCPUMonitor(mm, (int) address, size);
cpuMonitorArray.add(t); cpuMonitorArray.add(t);
for (int a = address; a < address+size; a++) { for (int a = (int) address; a < address + size; a++) {
cpu.addWatchPoint(a, t); cpu.addWatchPoint(a, t);
} }
return true; return true;
} }
public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) { @Override
public boolean removeSegmentMonitor(long address, int size, SegmentMonitor mm) {
for (MemoryCPUMonitor mcm : cpuMonitorArray) { for (MemoryCPUMonitor mcm : cpuMonitorArray) {
if (mcm.mm != mm || mcm.address != address || mcm.size != size) { if (mcm.mm != mm || mcm.address != address || mcm.size != size) {
continue; continue;
} }
for (int a = address; a < address+size; a++) { for (int a = (int) address; a < (int) address + size; a++) {
cpu.removeWatchPoint(a, mcm); cpu.removeWatchPoint(a, mcm);
} }
cpuMonitorArray.remove(mcm); cpuMonitorArray.remove(mcm);
break; return true;
} }
} return false;
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;
} }
} }

View file

@ -40,8 +40,9 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription; import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote; import org.contikios.cooja.Mote;
import org.contikios.cooja.interfaces.Log; 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.MspMote;
import org.contikios.cooja.mspmote.MspMoteMemory;
import se.sics.mspsim.core.Memory; import se.sics.mspsim.core.Memory;
import se.sics.mspsim.core.MemoryMonitor; 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 final static String CONTIKI_POINTER = "cooja_debug_ptr";
private MspMote mote; private MspMote mote;
private MspMoteMemory mem; private VarMemory mem;
private String lastLog = null; private String lastLog = null;
private MemoryMonitor memoryMonitor = null; private MemoryMonitor memoryMonitor = null;
public MspDebugOutput(Mote mote) { public MspDebugOutput(Mote mote) {
this.mote = (MspMote) mote; this.mote = (MspMote) mote;
this.mem = (MspMoteMemory) this.mote.getMemory(); this.mem = new VarMemory(this.mote.getMemory());
if (!mem.variableExists(CONTIKI_POINTER)) { if (!mem.variableExists(CONTIKI_POINTER)) {
/* Disabled */ /* Disabled */
return; return;
} }
this.mote.getCPU().addWatchPoint(mem.getVariableAddress(CONTIKI_POINTER), this.mote.getCPU().addWatchPoint((int) mem.getVariableAddress(CONTIKI_POINTER),
memoryMonitor = new MemoryMonitor.Adapter() { memoryMonitor = new MemoryMonitor.Adapter() {
@Override @Override
public void notifyWriteAfter(int adr, int data, Memory.AccessMode mode) { 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) { if (msg != null && msg.length() > 0) {
lastLog = "DEBUG: " + msg; lastLog = "DEBUG: " + msg;
setChanged(); 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(); StringBuilder sb = new StringBuilder();
while (true) { while (true) {
byte[] data = mem.getMemorySegment(address, 8); byte[] data = mem.getMemorySegment(address, 8);
@ -136,7 +137,7 @@ public class MspDebugOutput extends Log {
super.removed(); super.removed();
if (memoryMonitor != null) { 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.Mote;
import org.contikios.cooja.interfaces.MoteID; import org.contikios.cooja.interfaces.MoteID;
import org.contikios.cooja.mote.memory.VarMemory;
import org.contikios.cooja.mspmote.MspMote; import org.contikios.cooja.mspmote.MspMote;
import org.contikios.cooja.mspmote.MspMoteMemory;
import se.sics.mspsim.core.Memory; import se.sics.mspsim.core.Memory;
import se.sics.mspsim.core.MemoryMonitor; import se.sics.mspsim.core.MemoryMonitor;
@ -53,7 +53,7 @@ public class MspMoteID extends MoteID {
private static Logger logger = Logger.getLogger(MspMoteID.class); private static Logger logger = Logger.getLogger(MspMoteID.class);
private MspMote mote; private MspMote mote;
private MspMoteMemory moteMem = null; private VarMemory moteMem = null;
private boolean writeFlashHeader = true; private boolean writeFlashHeader = true;
private int moteID = -1; private int moteID = -1;
@ -69,7 +69,7 @@ public class MspMoteID extends MoteID {
*/ */
public MspMoteID(Mote m) { public MspMoteID(Mote m) {
this.mote = (MspMote) m; this.mote = (MspMote) m;
this.moteMem = (MspMoteMemory) mote.getMemory(); this.moteMem = new VarMemory(mote.getMemory());
} }
public int getMoteID() { public int getMoteID() {
@ -144,7 +144,7 @@ public class MspMoteID extends MoteID {
byte[] id = new byte[2]; byte[] id = new byte[2];
id[0] = (byte) (moteID & 0xff); id[0] = (byte) (moteID & 0xff);
id[1] = (byte) ((moteID >> 8) & 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) { private void addMonitor(String variable, MemoryMonitor monitor) {
if (moteMem.variableExists(variable)) { if (moteMem.variableExists(variable)) {
int address = moteMem.getVariableAddress(variable); int address = (int) moteMem.getVariableAddress(variable);
if ((address & 1) != 0) { if ((address & 1) != 0) {
// Variable can not be a word - must be a byte // Variable can not be a word - must be a byte
} else { } else {
@ -213,7 +213,7 @@ public class MspMoteID extends MoteID {
private void removeMonitor(String variable, MemoryMonitor monitor) { private void removeMonitor(String variable, MemoryMonitor monitor) {
if (moteMem.variableExists(variable)) { if (moteMem.variableExists(variable)) {
int address = moteMem.getVariableAddress(variable); int address = (int) moteMem.getVariableAddress(variable);
mote.getCPU().removeWatchPoint(address, monitor); mote.getCPU().removeWatchPoint(address, monitor);
mote.getCPU().removeWatchPoint(address + 1, 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 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_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_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_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]*$ 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_ADDRESS_2 = [ \t]*$
MAPFILE_VAR_SIZE_1 = ^ MAPFILE_VAR_SIZE_1 = ^
MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$ 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$ PARSE_COMMAND=nm -aP $(LIBFILE)
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_edata$ COMMAND_VAR_NAME_ADDRESS_SIZE = ^([^.].*?) <SECTION> ([0-9a-fA-F]+) ([0-9a-fA-F])*
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]A[ \t]__bss_start$ COMMAND_VAR_SEC_DATA = [DdGg]
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_end$ 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=\ VISUALIZER_DEFAULT_SKINS=\
org.contikios.cooja.plugins.skins.IDVisualizerSkin;\ 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_1 = mingw32-gcc -shared -Wl,-Map=$(MAPFILE) -Wl,--add-stdcall-alias -o $(LIBFILE)
LINK_COMMAND_2 = -L/usr/lib/mingw LINK_COMMAND_2 = -L/usr/lib/mingw
PARSE_WITH_COMMAND = true PARSE_WITH_COMMAND = true
PARSE_COMMAND=nm -n -C $(LIBFILE)
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_start__$ # Hack: nm with arguments -S --size-sort does not display __data_start symbols
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_end__$ PARSE_COMMAND=sh -c "/bin/nm -aP --size-sort -S $(LIBFILE) && /bin/nm -aP $(LIBFILE)"
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_start__$
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_end__$ 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> </appender>
<root> <root>
<priority value="debug"/> <priority value="info"/>
<appender-ref ref="logfile"/> <appender-ref ref="logfile"/>
<appender-ref ref="stdout"/> <appender-ref ref="stdout"/>
</root> </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", "MAPFILE_VAR_SIZE_1", "MAPFILE_VAR_SIZE_2",
"PARSE_COMMAND", "PARSE_COMMAND",
"COMMAND_VAR_NAME_ADDRESS", "COMMAND_VAR_NAME_ADDRESS_SIZE",
"COMMAND_DATA_START", "COMMAND_DATA_END", "COMMAND_DATA_START", "COMMAND_DATA_END",
"COMMAND_BSS_START", "COMMAND_BSS_END", "COMMAND_BSS_START", "COMMAND_BSS_END",
"COMMAND_COMMON_START", "COMMAND_COMMON_END", "COMMAND_COMMON_START", "COMMAND_COMMON_END",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -37,10 +37,11 @@ import javax.swing.JButton;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.jdom.Element; import org.jdom.Element;
import org.contikios.cooja.Mote; 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.ContikiMote;
import org.contikios.cooja.contikimote.ContikiMoteInterface; import org.contikios.cooja.contikimote.ContikiMoteInterface;
import org.contikios.cooja.interfaces.PIR; import org.contikios.cooja.interfaces.PIR;
import org.contikios.cooja.mote.memory.VarMemory;
/** /**
* Passive IR sensor mote interface. * Passive IR sensor mote interface.
@ -65,7 +66,7 @@ import org.contikios.cooja.interfaces.PIR;
public class ContikiPIR extends PIR implements ContikiMoteInterface { public class ContikiPIR extends PIR implements ContikiMoteInterface {
private ContikiMote mote; private ContikiMote mote;
private SectionMoteMemory moteMem; private VarMemory moteMem;
/** /**
* Creates an interface to the PIR at mote. * Creates an interface to the PIR at mote.
@ -77,7 +78,7 @@ public class ContikiPIR extends PIR implements ContikiMoteInterface {
*/ */
public ContikiPIR(Mote mote) { public ContikiPIR(Mote mote) {
this.mote = (ContikiMote) mote; this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory(); this.moteMem = new VarMemory(mote.getMemory());
} }
public static String[] getCoreInterfaceDependencies() { 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.contikimote.ContikiMoteInterface;
import org.contikios.cooja.dialogs.SerialUI; import org.contikios.cooja.dialogs.SerialUI;
import org.contikios.cooja.interfaces.PolledAfterActiveTicks; import org.contikios.cooja.interfaces.PolledAfterActiveTicks;
import org.contikios.cooja.mote.memory.VarMemory;
/** /**
* Contiki mote serial port and log interfaces. * 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 static Logger logger = Logger.getLogger(ContikiRS232.class);
private ContikiMote mote = null; private ContikiMote mote = null;
private SectionMoteMemory moteMem = null; private VarMemory moteMem = null;
static final int SERIAL_BUF_SIZE = 1024; /* rs232.c:40 */ 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) { public ContikiRS232(Mote mote) {
this.mote = (ContikiMote) mote; this.mote = (ContikiMote) mote;
this.moteMem = (SectionMoteMemory) mote.getMemory(); this.moteMem = new VarMemory(mote.getMemory());
} }
public static String[] getCoreInterfaceDependencies() { public static String[] getCoreInterfaceDependencies() {

View file

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

View file

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

View file

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

View file

@ -42,9 +42,9 @@ import org.jdom.Element;
import org.contikios.cooja.ClassDescription; import org.contikios.cooja.ClassDescription;
import org.contikios.cooja.Mote; import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteMemory; import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.MoteMemory.MemoryEventType; import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.MoteMemory.MemoryMonitor; import org.contikios.cooja.mote.memory.VarMemory;
/** /**
* Read-only interface to IPv4 or IPv6 address. * Read-only interface to IPv4 or IPv6 address.
@ -54,21 +54,22 @@ import org.contikios.cooja.MoteMemory.MemoryMonitor;
@ClassDescription("IP Address") @ClassDescription("IP Address")
public class IPAddress extends MoteInterface { public class IPAddress extends MoteInterface {
private static Logger logger = Logger.getLogger(IPAddress.class); 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 static final int IPv6_MAX_ADDRESSES = 4;
private boolean ipv6IsGlobal = false; private boolean ipv6IsGlobal = false;
private int ipv6AddressIndex = -1; private int ipv6AddressIndex = -1;
private static final int MONITORED_SIZE = 150; private static final int MONITORED_SIZE = 150;
private MemoryMonitor memMonitor; private SegmentMonitor memMonitor;
public IPAddress(final Mote mote) { public IPAddress(final Mote mote) {
moteMem = mote.getMemory(); moteMem = new VarMemory(mote.getMemory());
memMonitor = new MemoryMonitor() { memMonitor = new MemoryInterface.SegmentMonitor() {
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) { @Override
if (type != MemoryEventType.WRITE) { public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
if (type != SegmentMonitor.EventType.WRITE) {
return; return;
} }
setChanged(); setChanged();
@ -76,11 +77,11 @@ public class IPAddress extends MoteInterface {
} }
}; };
if (isVersion4()) { if (isVersion4()) {
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_hostaddr"), 4, memMonitor); moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_hostaddr", memMonitor);
} else if (isVersion6()) { } else if (isVersion6()) {
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor); moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_netif_addr_list_offset", memMonitor);
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor); moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_addr_size", memMonitor);
moteMem.addMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_SIZE, memMonitor); moteMem.addVarMonitor(SegmentMonitor.EventType.WRITE, "uip_ds6_if", memMonitor);
} }
} }
@ -205,11 +206,11 @@ public class IPAddress extends MoteInterface {
super.removed(); super.removed();
if (memMonitor != null) { if (memMonitor != null) {
if (isVersion4()) { if (isVersion4()) {
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), 4, memMonitor); moteMem.removeVarMonitor("rimeaddr_node_addr", memMonitor);
} else if (isVersion6()) { } else if (isVersion6()) {
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_netif_addr_list_offset"), 1, memMonitor); moteMem.removeVarMonitor("uip_ds6_netif_addr_list_offset", memMonitor);
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_addr_size"), 1, memMonitor); moteMem.removeVarMonitor("uip_ds6_addr_size", memMonitor);
moteMem.removeMemoryMonitor(moteMem.getVariableAddress("uip_ds6_if"), MONITORED_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.ClassDescription;
import org.contikios.cooja.Mote; import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteMemory; import org.contikios.cooja.mote.memory.MemoryInterface;
import org.contikios.cooja.MoteMemory.MemoryEventType; import org.contikios.cooja.mote.memory.MemoryInterface.SegmentMonitor;
import org.contikios.cooja.MoteMemory.MemoryMonitor; import org.contikios.cooja.mote.memory.VarMemory;
/** /**
* Read-only interface to Rime address read from Contiki variable: linkaddr_node_addr. * 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") @ClassDescription("Rime address")
public class RimeAddress extends MoteInterface { public class RimeAddress extends MoteInterface {
private static Logger logger = Logger.getLogger(RimeAddress.class); private static Logger logger = Logger.getLogger(RimeAddress.class);
private MoteMemory moteMem; private VarMemory moteMem;
public static final int RIME_ADDR_LENGTH = 2; public static final int RIME_ADDR_LENGTH = 2;
private MemoryMonitor memMonitor = null; private SegmentMonitor memMonitor = null;
public RimeAddress(final Mote mote) { public RimeAddress(final Mote mote) {
moteMem = mote.getMemory(); moteMem = new VarMemory(mote.getMemory());
if (hasRimeAddress()) { if (hasRimeAddress()) {
memMonitor = new MemoryMonitor() { memMonitor = new SegmentMonitor() {
public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) { @Override
if (type != MemoryEventType.WRITE) { public void memoryChanged(MemoryInterface memory, SegmentMonitor.EventType type, long address) {
if (type != SegmentMonitor.EventType.WRITE) {
return; return;
} }
setChanged(); setChanged();
@ -76,7 +77,7 @@ public class RimeAddress extends MoteInterface {
} }
}; };
/* TODO XXX Timeout? */ /* 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() { public void removed() {
super.removed(); super.removed();
if (memMonitor != null) { 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.HashMap;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import java.util.Properties;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import org.contikios.cooja.Mote; import org.contikios.cooja.Mote;
import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteInterface;
import org.contikios.cooja.MoteInterfaceHandler; import org.contikios.cooja.MoteInterfaceHandler;
import org.contikios.cooja.MoteMemory;
import org.contikios.cooja.MoteType; import org.contikios.cooja.MoteType;
import org.contikios.cooja.RadioPacket; 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.Simulation;
import org.contikios.cooja.interfaces.ApplicationRadio; import org.contikios.cooja.interfaces.ApplicationRadio;
import org.contikios.cooja.interfaces.ApplicationSerialPort; import org.contikios.cooja.interfaces.ApplicationSerialPort;
import org.contikios.cooja.interfaces.Radio; 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. * Abstract application mote.
@ -67,6 +68,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
/* Observe our own radio for incoming radio packets */ /* Observe our own radio for incoming radio packets */
private Observer radioDataObserver = new Observer() { private Observer radioDataObserver = new Observer() {
@Override
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
ApplicationRadio radio = (ApplicationRadio) obs; ApplicationRadio radio = (ApplicationRadio) obs;
if (radio.getLastEvent() == Radio.RadioEvent.RECEPTION_FINISHED) { if (radio.getLastEvent() == Radio.RadioEvent.RECEPTION_FINISHED) {
@ -89,7 +91,8 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
public AbstractApplicationMote(MoteType moteType, Simulation sim) { public AbstractApplicationMote(MoteType moteType, Simulation sim) {
setSimulation(sim); setSimulation(sim);
this.moteType = moteType; 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 = new MoteInterfaceHandler(this, moteType.getMoteInterfaceClasses());
this.moteInterfaces.getRadio().addObserver(radioDataObserver); this.moteInterfaces.getRadio().addObserver(radioDataObserver);
requestImmediateWakeup(); requestImmediateWakeup();
@ -99,6 +102,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
((ApplicationSerialPort)moteInterfaces.getLog()).triggerLog(msg); ((ApplicationSerialPort)moteInterfaces.getLog()).triggerLog(msg);
} }
@Override
public MoteInterfaceHandler getInterfaces() { public MoteInterfaceHandler getInterfaces() {
return moteInterfaces; return moteInterfaces;
} }
@ -107,14 +111,16 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
moteInterfaces = moteInterfaceHandler; moteInterfaces = moteInterfaceHandler;
} }
public MoteMemory getMemory() { @Override
public MemoryInterface getMemory() {
return memory; return memory;
} }
public void setMemory(MoteMemory memory) { public void setMemory(SectionMoteMemory memory) {
this.memory = (SectionMoteMemory) memory; this.memory = (SectionMoteMemory) memory;
} }
@Override
public MoteType getType() { public MoteType getType() {
return moteType; return moteType;
} }
@ -123,6 +129,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
moteType = type; moteType = type;
} }
@Override
public Collection<Element> getConfigXML() { public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>(); ArrayList<Element> config = new ArrayList<Element>();
Element element; Element element;
@ -141,10 +148,11 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
return config; return config;
} }
@Override
public boolean setConfigXML(Simulation simulation, public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML, boolean visAvailable) { Collection<Element> configXML, boolean visAvailable) {
setSimulation(simulation); setSimulation(simulation);
this.memory = new SectionMoteMemory(new HashMap<String, Integer>(), 0); this.memory = new SectionMoteMemory(new HashMap<String, Symbol>());
moteInterfaces.getRadio().addObserver(radioDataObserver); moteInterfaces.getRadio().addObserver(radioDataObserver);
for (Element element : configXML) { for (Element element : configXML) {
@ -176,10 +184,12 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme
return true; return true;
} }
@Override
public int getID() { public int getID() {
return moteInterfaces.getMoteID().getMoteID(); return moteInterfaces.getMoteID().getMoteID();
} }
@Override
public String toString() { public String toString() {
return "AppMote " + getID(); return "AppMote " + getID();
} }

View file

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

View file

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