/*******************************************************************************
* openDLX - A DLX/MIPS processor simulator.
* Copyright (C) 2013 The openDLX project, University of Augsburg, Germany
* Project URL: <https://sourceforge.net/projects/opendlx>
* Development branch: <https://github.com/smetzlaff/openDLX>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program, see <LICENSE>. If not, see
* <http://www.gnu.org/licenses/>.
******************************************************************************/
package openDLX.memory;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.log4j.Logger;
import openDLX.datatypes.*;
import openDLX.exception.MemoryException;
import openDLX.util.PagedMemory;
public class MainMemory implements MemoryInterface
{
private static Logger logger = Logger.getLogger("MainMemory");
private PagedMemory memory;
private short memory_latency;
public MainMemory(String raw_file, int raw_file_code_start_address, short memory_latency) throws MemoryException
{
this.memory_latency = memory_latency;
memory = new PagedMemory();
try
{
FileInputStream fileinputstream = new FileInputStream(raw_file);
int raw_file_size = fileinputstream.available();
byte bytearray[] = new byte[raw_file_size];
fileinputstream.read(bytearray);
int i;
// write memory code dump into memory, with base address and start
// offset
for (i = 0; i < raw_file_size; i++)
{
memory.writeByte(raw_file_code_start_address + i, bytearray[i]);
}
fileinputstream.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
System.exit(1);
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
}
public uint8 read_u8(uint32 address, boolean log_output) throws MemoryException
{
if (log_output)
{
dumpMemory(new uint32(address.getValue() - 4), new uint32(address.getValue() + 4));
}
return new uint8(memory.readByte(address));
}
public uint8 read_u8(uint32 address) throws MemoryException
{
return read_u8(address, false);
}
public uint32 read_u32(uint32 address, boolean log_output) throws MemoryException
{
if((address.getValue()&0x3) != 0)
{
logger.error("Read u32 from unaligned addr: " + address.getValueAsHexString());
throw new MemoryException("Read u32 from unaligned addr: " + address.getValueAsHexString());
}
uint32 value = new uint32((memory.readByte(address.getValue()) & 0xFF) + ((memory.readByte(address.getValue() + 1) & 0xFF) << 8) + ((memory.readByte(address.getValue() + 2) & 0xFF) << 16) + ((memory.readByte(address.getValue() + 3) & 0xFF) << 24));
if (log_output)
{
//logger.trace("Read u32 from addr: " + address.getHex());
//logger.trace("Read: " + Integer.toHexString(memory.readByte(address.getValue())) + " " + Integer.toHexString(memory.readByte(address.getValue() + 1)) + " "
// + Integer.toHexString(memory.readByte(address.getValue() + 2)) + " " + Integer.toHexString(memory.readByte(address.getValue() + 3)) + " -> " + value.getHex());
dumpMemory(new uint32(address.getValue() - 4), new uint32(address.getValue() + 4));
}
return value;
}
public uint32 read_u32(uint32 address) throws MemoryException
{
return read_u32(address, false);
}
/**
* TODO ...
* @throws MemoryException
*/
private uint32 read_u32_dump(uint32 address) throws MemoryException
{
return new uint32((memory.readByteDump(address.getValue()) & 0xFF) + ((memory.readByteDump(address.getValue() + 1) & 0xFF) << 8) + ((memory.readByteDump(address.getValue() + 2) & 0xFF) << 16) + ((memory.readByteDump(address.getValue() + 3) & 0xFF) << 24));
}
public uint16 read_u16(uint32 address, boolean log_output) throws MemoryException
{
if((address.getValue()&0x1 ) != 0)
{
logger.error("Read u16 from unaligned addr: " + address.getValueAsHexString());
throw new MemoryException("Read u16 from unaligned addr: " + address.getValueAsHexString());
}
uint16 value = new uint16((memory.readByte(address.getValue()) & 0xFF) + ((memory.readByte(address.getValue() + 1) & 0xFF) << 8));
if(log_output)
{
dumpMemory(new uint32(address.getValue() - 4), new uint32(address.getValue() + 4));
}
return value;
}
public uint16 read_u16(uint32 address) throws MemoryException
{
return read_u16(address, false);
}
public void write_u32(uint32 address, uint32 value) throws MemoryException
{
if((address.getValue()&0x3 ) != 0)
{
logger.error("Write u32 to unaligned addr: " + address.getValueAsHexString());
throw new MemoryException("Write u32 to unaligned addr: " + address.getValueAsHexString());
}
logger.debug("Write u32 to addr: " + address.getValueAsHexString() + " value: " + value.getValueAsHexString());
memory.writeByte(address.getValue(), (byte) (value.getValue() & 0xFF));
memory.writeByte(address.getValue() + 1, (byte) ((value.getValue() >> 8) & 0xFF));
memory.writeByte(address.getValue() + 2, (byte) ((value.getValue() >> 16) & 0xFF));
memory.writeByte(address.getValue() + 3, (byte) ((value.getValue() >> 24) & 0xFF));
logger.debug("Written: " + value.getValueAsHexString() + " -> " + memory.readByteAsString(address.getValue() + 3) + " " + memory.readByteAsString(address.getValue() + 2) + " "
+ memory.readByteAsString(address.getValue() + 1) + " " + memory.readByteAsString(address.getValue() + 0));
dumpMemory(new uint32(address.getValue() - 4), new uint32(address.getValue() + 4));
}
public void write_u8(uint32 address, uint32 value) throws MemoryException
{
write_u8(address, new uint8(value.getValue()));
}
public void write_u8(uint32 address, uint8 value) throws MemoryException
{
logger.debug("Write u8 to addr: " + address.getValueAsHexString() + " value: " + value.getValueAsHexString());
memory.writeByte(address.getValue(), value.getValue());
logger.debug("Written: " + value.getValueAsHexString() + " -> " + memory.readByteAsString(address.getValue()));
dumpMemory(new uint32(address.getValue() - 4), new uint32(address.getValue() + 4));
}
public void dumpMemory(uint32 start, uint32 end) throws MemoryException
{
uint32 start_aligned = new uint32(start.getValue() & 0xFFFFFFE0);
logger.debug(" | 0 4 8 c 10 14 18 1c |");
logger.debug("-------------+-----------------------------------------------------------------------------------------+");
for (uint32 addr = start_aligned; addr.getValue() <= end.getValue(); addr.setValue(addr.getValue() + 32))
{
String s = " " + addr.getValueAsHexString() + " | ";
for (int i = 0; i <= 28; i += 4)
{
s = s + read_u32_dump(new uint32(addr.getValue() + i)).getValueAsHexString() + " ";
}
s = s + "|";
logger.debug(s);
}
logger.debug("-------------+-----------------------------------------------------------------------------------------+");
}
public uint32 getEndOfMemory()
{
return new uint32(-1);
}
public short getRequestDelay(RequestType type, uint32 address) throws MemoryException
{
switch (type)
{
case INSTR_RD:
case DATA_RD:
case DATA_WR:
break;
default:
throw new MemoryException("Unknown memory request type.");
}
return getLatency();
}
public short getLatency()
{
return memory_latency;
}
}