Skip to content

Commit

Permalink
Memory-mapped registers are back. This simplifies the storage model, …
Browse files Browse the repository at this point in the history
…as we no longer have registers, as such. However, to get a clean and readable trace, we have reimplemented both memory and register classes, with modified debug output.
  • Loading branch information
Sarah Mount committed Jun 26, 2016
1 parent 364956c commit 7cc2e5a
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 155 deletions.
7 changes: 7 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,17 @@ exclude_lines =
if self.debug.enabled('rf'):
if self.debug.enabled('mem'):
if self.debug.enabled('memcheck'):
if not sparse_storage:
self.memory.debug.enabled_flags
s.debug_flags()
self.bounds_check
print

# Don't complain about invalid memory accesses.
if addr > self.size:
if addr == 0:


# Don't complain about assertions in syscalls -- special code for debuggers
inst.t5 == 4
inst.t5 == 5
Expand Down
149 changes: 5 additions & 144 deletions revelation/machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
# machine.py
#=======================================================================

from pydgin.debug import Debug, pad, pad_hex
from pydgin.machine import Machine
from pydgin.storage import Memory
from pydgin.utils import r_uint, specialize

from revelation.isa import reg_map
from revelation.storage import MemoryMappedRegisterFile

try:
from rpython.rlib.rarithmetic import intmask
Expand All @@ -17,89 +15,16 @@
RESET_ADDR = 0


#-----------------------------------------------------------------------
# Memory
#-----------------------------------------------------------------------
class RevelationMemory(object):
"""Since the Epiphany has memory-mapped register files, we need to
intercept any read / write which should actually go to the registers.
FIXME: Correctly map address 0xf0408 to the program counter in State.
"""

def __init__(self, data=None, size=2**32, byte_storage=True):
self.memory = Memory(data=data, size=size, byte_storage=byte_storage)
self.rf = None # Set by Sim.init_state(). Also sets self.fetch_pc()
self.debug = None # Set after ELF file loaded.

def set_debug(self, debug):
self.debug = debug
if self.debug.enabled('mem'):
self.memory.debug.enabled_flags.append('mem')
if self.debug.enabled('memcheck'):
self.memory.debug.enabled_flags.append('memcheck')

def iread(self, address, nbytes=4):
if 0xf0718 >= address >= 0xf0000:
_, reg_num = _register_map[r_uint(address)]
return intmask(self.rf[reg_num])
else:
return self.memory.iread(address, nbytes)

def read(self, address, nbytes=4):
if 0xf0718 >= address >= 0xf0000:
_, reg_num = _register_map[r_uint(address)]
return intmask(self.rf[reg_num])
else:
return self.memory.read(address, nbytes)

def write(self, address, nbytes, value):
if 0xf0718 >= address >= 0xf0000:
_, reg_num = _register_map[r_uint(address)]
self.rf[r_uint(reg_num)] = r_uint(value)
else:
self.memory.write(address, nbytes, value)


#-----------------------------------------------------------------------
# RegisterFile
#-----------------------------------------------------------------------
class RegisterFile( object ):
def __init__(self, constant_zero=True, num_regs=32, nbits=32):
self.num_regs = num_regs
self.regs = [r_uint(0)] * self.num_regs
self.debug = Debug()
self.nbits = nbits
self.debug_nchars = nbits / 4
# Ignore constant_zero, but keep it here to maintain
# compatibility with Pydgin.

def __getitem__(self, idx):
if self.debug.enabled('rf') and idx < 64:
print (':: RD.RF[%s] = %s' %
(pad('%d' % idx, 2),
pad_hex(self.regs[idx], len=self.debug_nchars))),
return intmask(self.regs[idx])

@specialize.argtype(2)
def __setitem__(self, idx, value):
self.regs[idx] = r_uint(value)
if self.debug.enabled('rf') and idx < 64:
print (':: WR.RF[%s] = %s' %
(pad('%d' % idx, 2),
pad_hex(self.regs[idx], len=self.debug_nchars))),


#-----------------------------------------------------------------------
# State
#-----------------------------------------------------------------------
class State(Machine):
_virtualizable_ = ['pc', 'num_insts']
_virtualizable_ = ['num_insts']

def __init__(self, memory, debug, reset_addr=RESET_ADDR):
Machine.__init__(self,
memory,
RegisterFile(constant_zero=False, num_regs=107),
MemoryMappedRegisterFile(memory),
debug,
reset_addr=RESET_ADDR)
# Epiphany III exceptions.
Expand All @@ -122,7 +47,7 @@ def get_lateched_interrupt(self):
ilat_highest_bit= -1
for index in range(10):
if ((self.rf[reg_map['ILAT']] & (1 << index)) and
not (self.rf[reg_map['IMASK']] & (1 << index))):
not (self.rf[reg_map['IMASK']] & (1 << index))):
ilat_highest_bit = index
break
return ilat_highest_bit
Expand All @@ -134,7 +59,7 @@ def _set_nth_bit_of_register(self, register, n, value):
if value:
self.rf[reg_map[register]] |= (1 << n)
else:
self.rf[reg_map[register]] &= ~(1 << n)
self.rf[reg_map[register]] &= ~(1 << n)

@property
def ACTIVE(self):
Expand Down Expand Up @@ -285,67 +210,3 @@ def debug_flags(self):
print ('AN=%s AZ=%s AC=%s AV=%s AVS=%s BN=%s BZ=%s BIS=%s BUS=%s BV=%s BVS=%s ' %
(self.AN, self.AZ, self.AC, self.AV, self.AVS,
self.BN, self.BZ, self.BIS, self.BUS, self.BV, self.BVS)),


def get_address_of_register_by_name(register_name):
register_number = reg_map[register_name]
for address in _register_map:
if _register_map[address][1] == register_number:
return address


_register_map = {
# Memory location -> (size, register number)
0xf0400 : (4, reg_map['CONFIG']), # Core configuration
0xf0404 : (4, reg_map['STATUS']), # Core status
0xf0408 : (4, reg_map['pc']), # Program counter
0xf040c : (4, reg_map['DEBUGSTATUS']), # Debug status
0xf0414 : (4, reg_map['LC']), # Hardware counter loop
0xf0418 : (4, reg_map['LS']), # Hardware counter start address
0xf041c : (4, reg_map['LE']), # Hardware counter end address
0xf0420 : (4, reg_map['IRET']), # Interrupt PC return address
0xf0424 : (4, reg_map['IMASK']), # Interrupt mask
0xf0428 : (4, reg_map['ILAT']), # Interrupt latch
0xf042c : (4, reg_map['ILATST']), # Alias for setting interrupts
0xf0430 : (4, reg_map['ILATCL']), # Alias for clearing interrupts
0xf0434 : (4, reg_map['IPEND']), # Interrupt currently in progress
0xf0440 : (4, reg_map['FSTATUS']), # Alias for writing to all STATUS bits
0xf0448 : (1, reg_map['DEBUGCMD']), # Debug command register (2 bits)
0xf070c : (1, reg_map['RESETCORE']), # Per core software reset (1 bit)
# Event timer registers
0xf0438 : (4, reg_map['CTIMER0']), # Core timer 0
0xf043c : (4, reg_map['CTIMER1']), # Core timer 1
# Process control registers
0xf0604 : (2, reg_map['MEMSTATUS']), # Memory protection status
# Epiphany IV: 14 bits, III: 1 bit ([2])
0xf0608 : (2, reg_map['MEMPROTECT']), # Memory protection registration
# Epiphany IV: 16 bits, III: 8 bits.
# DMA registers
0xf0500 : (4, reg_map['DMA0CONFIG']), # DMA channel 0 configuration
0xf0504 : (4, reg_map['DMA0STRIDE']), # DMA channel 0 stride
0xf0508 : (4, reg_map['DMA0COUNT']), # DMA channel 0 count
0xf050c : (4, reg_map['DMA0SRCADDR']), # DMA channel 0 source address
0xf0510 : (4, reg_map['DMA0DSTADDR']), # DMA channel 0 destination address
0xf0514 : (4, reg_map['DMA0AUTO0']), # DMA channel 0 slave lower data
0xf0518 : (4, reg_map['DMA0AUTO1']), # DMA channel 0 slave upper data
0xf051c : (4, reg_map['DMA0STATUS']), # DMA channel 0 status
0xf0520 : (4, reg_map['DMA1CONFIG']), # DMA channel 1 configuration
0xf0524 : (4, reg_map['DMA1STRIDE']), # DMA channel 1 stride
0xf0528 : (4, reg_map['DMA1COUNT']), # DMA channel 1 count
0xf052c : (4, reg_map['DMA1SRCADDR']), # DMA channel 1 source address
0xf0530 : (4, reg_map['DMA1DSTADDR']), # DMA channel 1 destination address
0xf0534 : (4, reg_map['DMA1AUTO0']), # DMA channel 1 slave lower data
0xf0538 : (4, reg_map['DMA1AUTO1']), # DMA channel 1 slave upper data
0xf053c : (4, reg_map['DMA1STATUS']), # DMA channel 1 status
# Mesh node control registers
0xf0700 : (2, reg_map['MESHCONFIG']), # Mesh node configuration
0xf0704 : (3, reg_map['COREID']), # Processor core ID (12 bits)
0xf0708 : (4, reg_map['MULTICAST']), # Multicast configuration
0xf0710 : (3, reg_map['CMESHROUTE']), # cMesh routing configuration (12 bits)
0xf0714 : (3, reg_map['XMESHROUTE']), # xMesh routing configuration (12 bits)
0xf0718 : (3, reg_map['RMESHROUTE']), # rMesh routing configuration (12 bits)
}

# Add general purpose registers to register_map.
for index, address in enumerate(xrange(0xf0000, 0xf0100, 0x4)):
_register_map[address] = (4, reg_map['r%d' % ((address - 0xf0000) / 0x4)])
16 changes: 6 additions & 10 deletions revelation/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from pydgin.misc import load_program
from pydgin.sim import Sim, init_sim

from revelation.isa import decode, reg_map
from revelation.machine import RevelationMemory, State, RESET_ADDR
from revelation.instruction import Instruction
from revelation.isa import decode, reg_map
from revelation.machine import State, RESET_ADDR
from revelation.storage import Memory

MEMORY_SIZE = 2**32 # Global on-chip address space.

def new_memory():
return RevelationMemory(size=MEMORY_SIZE, byte_storage=True)
return Memory(size=MEMORY_SIZE)


class Revelation(Sim):
Expand Down Expand Up @@ -55,8 +56,8 @@ def post_execute(self):
self.hardware_loop = False
return
# Service interrupts. See: http://blog.alexrp.com/revelation-notes/
if (self.state.rf[reg_map['ILAT']] > 0 and not (self.state.GID or
self.state.rf[reg_map['DEBUGSTATUS']] == 1)):
if (self.state.rf[reg_map['ILAT']] > 0 and
not (self.state.GID or self.state.rf[reg_map['DEBUGSTATUS']] == 1)):
self._service_interrupts()

def _service_interrupts(self):
Expand Down Expand Up @@ -91,12 +92,7 @@ def init_state(self, exe_file, filename, run_argv,
Debug.global_enabled = True
memory = new_memory()
_, _ = load_program(exe_file, memory)
memory.set_debug(self.debug)
self.state = State(memory, self.debug, reset_addr=RESET_ADDR)
# Give the RAM model a reference to the register files. Since the
# Epiphany has memory-mapped register files, we need to intercept
# any read / write which should actually go to the registers.
memory.rf = self.state.rf
self.state.ACTIVE = True
self.state.SUPERUSER = True

Expand Down
Loading

0 comments on commit 7cc2e5a

Please sign in to comment.