[Gems-users] Contiguous Address Translation Issues


Date: Sat, 5 Nov 2011 21:13:13 -0400
From: "abhisekpan@xxxxxxxxx" <abhisekpan@xxxxxxxxx>
Subject: [Gems-users] Contiguous Address Translation Issues
Hi All!

The simics physical memory configuration I am using has a non-contiguous address space. So my question is what are the specific reasons why ruby can not handle the non-contiguous address space.

The question arises because I have a specific memory space configuration for which the non-contiguous to contiguous translation mechanism leads to creation of physical addresses greater than the memory size.
Here is my configuration:

base                             object           fn    offset             length
0x0000000000000000     dram0         0  0x0                    0x     a0,000          
0x0000000000,100,000   dram0         0  0x100,000          0xf0,000,000       
0x0000000,100,000,000  dram0         0  0xf0,000,000      0x10,000,000       

This creates an interesting problem because if you add up all the lengths, it adds up to more than 2^32(100,000,000 in hex) bytes which is what the dram size is. This happens because there is an overlap of addresses in the dram. The offset field gives the starting address in the dram for each segment. We can see the second chunk starts at 0x100,000 of dram0 and should end at 0xf0,100,000 (start + length). However the start address for the third segment starts at 0xf0,000,000 and ends at 0x100,000,000 (0xf0,000,000 + 0x10,000,000). Hence although the final address is within the limits of the dram size - 0x100,000,000 (4GB) the total size of the 3 segments is actually 0x100,0a0,000.

The translator in ruby ignores the device offset and considers only the base addresses and size, and compresses the address space into a contiguous space, which in this case means that some of the addresses exceed the dram size.

Now in  SimicsDriver::isUnhandledTransaction(): there is a filter like this:
if (IS_DEV_MEM_OP(mem_trans->s.ini_type) ||
      IS_OTH_MEM_OP(mem_trans->s.ini_type) ||
      mem_trans->s.physical_address > uinteger_t(RubyConfig::memorySizeBytes())
     ) {
  return true;
}

Hence all the address which are greater than the memory size(4GB here) are ignored silently. I set up a counter inside the 'if' condition and found out that there are a lot of addresses like that.

So I was thinking a straight-forward way to bring all addresses inside the memory size would be to subtract the difference between the base and dram start offset in the translation for each segment. That creates chunks which are inside the limit, but still not contiguous.

So my question is is this okay to do, as in are there things in ruby which will break if I use this non-contiguous arrangement?

--
Abhisek
Live Long and Prosper

PS. If you look at the translator code (TranslateSimicsToRuby()), you would find that the last segment is not considered, "since it appears to be some kind of seldom-used ROM." That will prevent these out-of-limit translated values. But it does not work in this case because I found out that most of the addresses come from the last segment, and the translator silently translates all these out-of bounds addresses to zero, as you can see below. I mention this is PS because it is kind of a separate issue, but might be important for people to know. I had changed that previously to include all the segments. Normally this would be hard to see because it won't create any error as such, but I was trying to measure the number of distinct memory addresses accessed by the program and in the process saw that most of the translated addresses are zero.

uint64 translated = 0; 
  for(int i=0;i<m_nNumMaps-1;i++) {
    if(m_startAddrs[i+1] > addr) {
      translated = addr - m_translations[i];
      break;
    }
  }
/*
   * If the loop falls through, then addr is part of an untranslated region anyway,
   * like that silly little ROM that sits at the end of memory
   */
 return translated;


[← Prev in Thread] Current Thread [Next in Thread→]