package se.sics.mspsim.util;
import se.sics.mspsim.core.EmulationException;
public class ArrayFIFO {
public static final boolean STRICT = false;
private final int memory[];
private final int start;
private final int size;
private final String name;
private int readPos = 0;
private int writePos = 0;
private int len = 0;
private int markWritePos;
public ArrayFIFO(String name, int[] mem, int start, int size) {
memory = mem;
this.name = name;
this.start = start;
this.size = size;
len = 0;
}
public boolean write(int data) {
memory[start + writePos++] = data;
if (writePos >= size) {
writePos = 0;
}
len++;
return len == size;
}
public boolean isEmpty() {
return len == 0;
}
public boolean isFull() {
return len == size;
}
/* peek data as if it would be read, but leave it on the fifo */
public int peek(int index) {
int pos = readPos + index;
if (pos < 0) {
pos += size;
} else if (pos >= size) {
pos -= size;
}
int v = memory[start + pos];
return v & 0xff;
}
public int read() {
if (len <= 0) {
if (STRICT) {
throw new EmulationException("Reading from empty FIFO");
} else {
/*System.out.println("Reading from empty FIFO");*/
return 0;
}
}
int v = memory[start + readPos++];
if (readPos >= size) {
readPos = 0;
}
len--;
return v & 0xff;
}
/* get data relative the write position (typically negative input values */
public int get(int index) {
int pos = writePos + index;
if (pos < 0) {
pos += size;
} else if (pos >= size) {
pos -= size;
}
return memory[start + pos] & 0xff;
}
/* set data relative the write position (typically negative input values */
public void set(int index, int data) {
int pos = writePos + index;
if (pos < 0) {
pos += size;
} else if (pos >= size) {
pos -= size;
}
memory[start + pos] = data & 0xff;
}
public int length() {
return len;
}
public void reset() {
writePos = 0;
readPos = 0;
len = 0;
}
/* for marking a write pos - needed for supporting dropping non-matching packets */
public void mark() {
markWritePos = writePos;
}
public void restore() {
writePos = markWritePos;
len = writePos - readPos;
if (len < 0) len += size;
}
public String stateToString() {
return name + " len: " + len + " rpos: " + readPos + " wpos: " + writePos;
}
public boolean tailEquals(int[] data, int offset, int len) {
return tailEquals(data, offset, len, 0);
}
public boolean tailEquals(int[] data, int offset, int len, int ignore) {
for (int i = 0; i < len; i++) {
if ((data[offset + i] & 0xff) != get(i - len - ignore)) {
return false;
}
}
return true;
}
}