package elw.dp.mips;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntByteHashMap;
import gnu.trove.TIntIntHashMap;
import java.util.Arrays;
public class Memory {
private TIntByteHashMap contentMap = new TIntByteHashMap();
private TIntArrayList readAdresses = new TIntArrayList();
private TIntArrayList writeAdresses = new TIntArrayList();
public int getWord(int address) {
readAdresses.add(address);
return getWordInternal(address);
}
public int getWordInternal(final int address) {
final byte byte0 = getByteInternal(address);
final byte byte1 = getByteInternal(address + 1);
final byte byte2 = getByteInternal(address + 2);
final byte byte3 = getByteInternal(address + 3);
return (byte0 << 24) | ((byte1 << 16) & 0xFF0000) | ((byte2 << 8) & 0xFF00) | ((int) byte3 & 0xFF);
}
public int setWord(int address, int newWord) {
writeAdresses.add(address);
writeAdresses.add(address + 1);
writeAdresses.add(address + 2);
writeAdresses.add(address + 3);
return setWordInternal(address, newWord);
}
private int setWordInternal(int address, int newWord) {
final int oldWord = getWordInternal(address);
setByteInternal(address, (byte) (newWord >> 24));
setByteInternal(address + 1, (byte) (newWord >> 16 & 0xFF));
setByteInternal(address + 2, (byte) (newWord >> 8 & 0xFF));
setByteInternal(address + 3, (byte) (newWord & 0xFF));
return oldWord;
}
public byte getByteInternal(final int address) {
return contentMap.get(address);
}
private byte setByteInternal(int address, byte value) {
return contentMap.put(address, value);
}
public byte getByte(int address) {
readAdresses.add(address);
return getByteInternal(address);
}
public byte setByte(int address, byte newByte) {
writeAdresses.add(address);
return setByteInternal(address, newByte);
}
public TIntArrayList getReadAdresses() {
return readAdresses;
}
public TIntArrayList getWriteAdresses() {
return writeAdresses;
}
public void resetAccess() {
readAdresses.clear();
writeAdresses.clear();
}
public int getSize() {
return contentMap.size();
}
public int getAddressAt(int index) {
// LATER optimize this
final int[] keys = contentMap.keys();
Arrays.sort(keys);
return keys[index];
}
public void setData(final TIntIntHashMap newData) {
resetAccess();
contentMap.clear();
final int[] addresses = newData.keys();
for (final int addr : addresses) {
setWord(addr, newData.get(addr));
}
}
public boolean hasWord(final int address) {
return hasByte(address) && hasByte(address + 1) && hasByte(address + 2) && hasByte(address + 3);
}
private boolean hasByte(final int address) {
return contentMap.containsKey(address);
}
}