blob: 1ddcef9da4a118875246def8696136951f96b5b7 [file] [log] [blame]
package xdc.rov;
import xdc.rov.IMemoryImage;
import xdc.rov.Sections;
import xdc.rov.TargetEncoder;
/*!
* ======== MemoryImage ========
* This class wraps an IMemoryImage implementation to provide support for
* features needed across all memory readers.
* This includes:
* - Common error messages
* - Checking of abort flag
* - Checking memory read address against section map
*/
public class MemoryImage {
/* The IMemoryImage implementation used to perform the memory reads. */
private IMemoryImage memReader;
/*
* Sections object defining all of the valid data sections for the
* current application.
*/
private Sections sections;
/* The number of bits in a MAU */
private int bitsPerChar;
/* Target encoder used for encoding MAUs to bytes */
private TargetEncoder enc = null;
/* Flag to indicate that memory reads should not be performed. */
private Boolean abortFlag = false;
/* Message to throw if the memory read failed at a VALID address. */
private static final String validFail =
"This read is at a VALID address according to the " +
"application's section map, but the IMemoryImage memory " +
"read failed.";
/* Message to throw if the memory read failed at an INVALID address. */
private static final String invalidFail =
"This read is at an INVALID address according to the " +
"application's section map. The application is likely " +
"either uninitialized or corrupt.";
/*!
* ======== AbortedException ========
*/
public class AbortedException extends Exception {
private static final long serialVersionUID = 1L;
public AbortedException(String msg) {
super(msg);
}
}
/*
* ======== Constructor ========
*/
public MemoryImage(IMemoryImage memReader, TargetType.Endianess endian,
int bitsPerChar)
{
this.memReader = memReader;
this.bitsPerChar = bitsPerChar;
/* Retrieve the section map from the IMemoryImage implementation. */
sections = memReader.getSections();
/* Create the TargetEncoder, used for encoding MAUs to bytes. */
enc = new TargetEncoder(endian, bitsPerChar);
}
/*!
* ======== readMaus ========
* Read an array of data from target memory. The size of each element in
* the array is a target MAU (minimal addressable unit). This is a byte on
* byte addressable targets and 2 bytes on 16-bit targets such as 28x and
* 55x.
*
* @param(addr) Address of the data to fetch.
* @param(numMaus) Number of bytes to read.
* @param(addrCheck) Indicates whether the memory image should validate
* the read by comparing the address to section
* information, if available
*
*/
public int[] readMaus(long addr, int numMaus, boolean addrCheck)
throws Exception
{
/* Check for abort command at beginning and end of read */
if (getAbortFlag()) {
throw (new AbortedException("abort"));
}
/* Verify that memory request falls within valid section */
if (addrCheck) {
/* If the read doesn't fit within a section, throw an error */
if (!sections.isValidDataRead(addr, numMaus)) {
throw (new Exception(getReadFailMsg(addr, numMaus) + "\n" +
invalidFail));
}
}
/* Create the buffer */
int[] buffer = new int[numMaus];
boolean res;
if (!traceEnable) {
/* Call down to the device to perform the read. */
res = memReader.readMaus(buffer, addr, numMaus);
}
else {
/* Time the memory read */
long start = System.currentTimeMillis();
/* Call down to the device to perform the read. */
res = memReader.readMaus(buffer, addr, numMaus);
/* End time. */
long end = System.currentTimeMillis();
debugPrint("Memory read took " + (end - start) + "ms");
}
/* Check the return code, non-zero indicates a problem. */
if (!res) {
/*
* If an address check was performed, then this read is failing at
* a valid address. This is a serious error and indicates a
* problem with the IMemoryImage reader.
*/
if (addrCheck) {
throw (new Exception(getReadFailMsg(addr, numMaus) + "\n" +
validFail));
}
/*
* If no address check was performed, we can't say whether the
* address was valid or invalid.
*/
else {
throw (new Exception(getReadFailMsg(addr, numMaus)));
}
}
/* Check for abort command at beginning and end of read */
if (getAbortFlag()) {
throw (new AbortedException("abort"));
}
return (buffer);
}
/*!
* ======== readBytes ========
* Read an array of bytes from target memory.
*
* @param(addr) Address of the data to fetch.
* @param(numBytes) Number of bytes to read.
* @param(addrCheck) Indicates whether the memory image should validate
* the read by comparing the address to section
* information, if available
*/
public byte[] readBytes(long addr, int numBytes, boolean addrCheck)
throws Exception
{
/* We can only read MAUs, so calculate the number of MAUs to read. */
int bytesPerMau = (bitsPerChar / 8);
int numMaus = numBytes / bytesPerMau;
/* Read the data. */
int[] lBuf = readMaus(addr, numMaus, addrCheck);
/* Return the values in a byte array. */
byte[] bBuf = new byte[numBytes];
/* If the MAU is a byte, just copy the values. */
if (bitsPerChar == 8) {
for (int i = 0; i < lBuf.length; i++) {
bBuf[i] = (byte) lBuf[i];
}
}
/* Otherwise, encode the MAUs into bytes */
else {
int offset = 0;
for (int i = 0; i < lBuf.length; i++) {
enc.encodeBytes(bBuf, offset, lBuf[i], bytesPerMau);
offset += bytesPerMau;
}
}
return (bBuf);
}
/*
* ======== getReadFailMsg ========
* Returns a string stating that the given memory read failed.
*/
String getReadFailMsg(long addr, int length)
{
return ("Target memory read failed at address: 0x" +
Long.toHexString(addr) + ", length: " + length);
}
/*
* ======== getAbortFlag ========
* Synchronized method for checking the abort flag.
*/
public boolean getAbortFlag()
{
synchronized (abortFlag) {
return(abortFlag);
}
}
/*
* ======== setAbortFlag ========
*/
public void setAbortFlag(boolean val)
{
synchronized (abortFlag) {
abortFlag = val;
}
}
/*!
* ======== setSections ========
*/
public void setSections(Sections sections)
{
this.sections = sections;
}
/*
* ======== getSections ========
*/
public Sections getSections()
{
return (sections);
}
/*
* Initialize 'traceEnable' based on the xdc.rov.traceEnable environment
* variable.
*/
private static boolean traceEnable;
static {
String traceEnableStr = System.getProperty("xdc.rov.traceEnable");
traceEnable = (traceEnableStr != null) && traceEnableStr.equals("true");
}
public static void debugPrint(String str) {
if (traceEnable) {
System.out.println("[MemoryReader] " + str);
}
}
}