예제 #1
0
class RiscVFPRegisterFile(object):
    def __init__(self, num_regs=32, nbits=64):
        self.num_regs = num_regs
        self.regs = [r_uint(0)] * self.num_regs
        self.debug = Debug()
        self.nbits = nbits
        self.debug_nchars = nbits / 4

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

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

    #-----------------------------------------------------------------------
    # print_regs
    #-----------------------------------------------------------------------
    # prints all registers (register dump)
    # per_row specifies the number of registers to display per row
    def print_regs(self, per_row=6):
        for c in xrange(0, self.num_regs, per_row):
            str = ""
            for r in xrange(c, min(self.num_regs, c + per_row)):
                str += "%s:%s " % (pad("%d" % r, 2), pad_hex(self.regs[r]))
            print str
예제 #2
0
 def __init__(self, block_size=2**20, logger=None):
     self.block_size = block_size
     self.debug = Debug()
     self.logger = logger
     self.first_core = 0x808
     self.addr_mask  = block_size - 1
     self.block_mask = 0xffffffff ^ self.addr_mask
     self.block_dict = {}
     self.code_blocks = []
예제 #3
0
 def __init__(self, memory, coreid, logger):
     self.debug = Debug()
     self.logger = logger
     self.memory = memory
     self.coreid = coreid
     self.coreid_mask = coreid << 20
     self.is_first_core = False
     self.memory.write(self.coreid_mask | 0xf0704, 4, coreid & 0xfff,
                       from_core=coreid, quiet=True)
     self.num_regs = len(reg_memory_map)
     self.debug_nchars = 8
예제 #4
0
class RiscVFPRegisterFile( object ):
  def __init__( self, num_regs=32, nbits=64 ):
    self.num_regs = num_regs
    self.regs     = [ r_uint(0) ] * self.num_regs
    self.debug    = Debug()
    self.nbits    = nbits
    self.debug_nchars = nbits / 4

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

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

  #-----------------------------------------------------------------------
  # print_regs
  #-----------------------------------------------------------------------
  # prints all registers (register dump)
  # per_row specifies the number of registers to display per row
  def print_regs( self, per_row=6 ):
    for c in xrange( 0, self.num_regs, per_row ):
      str = ""
      for r in xrange( c, min( self.num_regs, c+per_row ) ):
        str += "%s:%s " % ( pad( "%d" % r, 2 ),
                            pad_hex( self.regs[r] ) )
      print str
예제 #5
0
class MemoryMappedRegisterFile(object):
    """Simulate the memory-mapped registers of a single Epiphany core.
    Note that memory objects can only read and write aligned words.
    """

    def __init__(self, memory, coreid, logger):
        self.debug = Debug()
        self.logger = logger
        self.memory = memory
        self.coreid = coreid
        self.coreid_mask = coreid << 20
        self.is_first_core = False
        self.memory.write(self.coreid_mask | 0xf0704, 4, coreid & 0xfff,
                          from_core=coreid, quiet=True)
        self.num_regs = len(reg_memory_map)
        self.debug_nchars = 8

    def __getitem__(self, index):
        address, bitsize, _ = reg_memory_map[index]
        mask = (1 << bitsize) - 1
        value = self.memory.iread(address, 4, from_core=self.coreid) & mask
        if (self.debug.enabled('rf') and self.logger and index < 64 and
              self.is_first_core):
            self.logger.log(' :: RD.RF[%s] = %s' % (pad('%d' % index, 2),
                              pad_hex(value, len=self.debug_nchars)))
        return value

    def __setitem__(self, index, value):
        if index == 0x65:  # COREID register. Read only. Other Read/Write only
            return         # registers need to be accessed by instructions.
        address, bitsize, _ = reg_memory_map[index]  # Lower 20 bits of address.
        mask = (1 << bitsize) - 1
        self.memory.write(self.coreid_mask | address, 4, value & mask,
                                 from_core=self.coreid, quiet=True)
        if (self.debug.enabled('rf') and self.logger and index < 64 and
              self.is_first_core):
            self.logger.log(' :: WR.RF[%s] = %s' % ((pad('%d' % index, 2),
                              pad_hex(value, len=self.debug_nchars))))
예제 #6
0
 def init_state(self, elf_file, filename, testbin, is_test=False):
     """Revelation has custom logging infrastructure that differs from the
     default provided by Pydgin. This matches e-sim, in that log messages are
     written to a file rather than to STDOUT. This prevents some specious
     differences in the two traces; e.g. the mode of an fstat object
     differing between Revelation and e-sim when the Revelation log is
     redirected from STDOUT to a file. This makes scripts/diff_trace.py much
     more useful.
     """
     if is_test:
         self.debug = Debug()
         Debug.global_enabled = True
     if self.debug.enabled_flags and Debug.global_enabled:
         print 'Trace will be written to: %s.' % LOG_FILENAME
         self.logger = Logger(LOG_FILENAME)
     if self.profile:
         timer = time.time()
         print 'Debugging set up took: %fs' % (timer - self.timer)
         self.timer = timer
     self.memory = new_memory(self.logger)
     if self.profile:
         timer = time.time()
         print 'Memory creation took: %fs' % (timer - self.timer)
         self.timer = timer
     f_row = (self.first_core >> 6) & 0x3f
     f_col = self.first_core & 0x3f
     elf = elf_reader(elf_file, is_64bit=False)
     coreids = []
     for row in xrange(self.rows):
         for col in xrange(self.cols):
             coreid = get_coreid_from_coords(f_row + row, f_col + col)
             coreids.append(coreid)
             print ('Loading program %s on to core %s (%s, %s)' %
                    (filename, hex(coreid), zfill(str(f_row + row), 2),
                     zfill(str(f_col + col), 2)))
             self.states[coreid] = State(self.memory, self.debug,
                                         logger=self.logger, coreid=coreid)
     code_blocks = load_program(elf, self.memory, coreids, ext_base=self.ext_base,
                                ext_size=self.ext_size)
     for section in code_blocks:
         self.memory.code_blocks.append(section)
     self.states[coreids[0]].set_first_core(True)
     if self.profile:
         timer = time.time()
         print 'ELF file loader took: %fs' % (timer - self.timer)
         self.timer = timer
예제 #7
0
 def entry_point(argv):
     self.timer = time.time()
     if self.jit_enabled:
         set_param(self.jitdriver, 'trace_limit', self.default_trace_limit)
     try:
         fname, jit, flags = cli_parser(argv, self, Debug.global_enabled)
     except DoNotInterpretError:  # CLI option such as --help or -h.
         return EXIT_SUCCESS
     except (SyntaxError, ValueError):
         return EXIT_SYNTAX_ERROR
     if jit:  # pragma: no cover
         set_user_param(self.jitdriver, jit)
     self.debug = Debug(flags, 0)
     try:
         elf_file = open(fname, 'rb')
     except IOError:
         print 'Could not open file %s' % fname
         return EXIT_FILE_ERROR
     if self.profile:
         timer = time.time()
         print 'CLI parser took: %fs' % (timer - self.timer)
         self.timer = timer
     self.init_state(elf_file, fname, False)
     for coreid in self.states:
         self.debug.set_state(self.states[coreid])
     elf_file.close()
     try:
         exit_code, tick_counter = self.run()
     except KeyboardInterrupt:
         exit_code = EXIT_CTRL_C
         tick_counter = -1
     if self.collect_times:
         self.end_time = time.time()
     if self.logger:
         self.logger.close()
     self._print_summary_statistics(tick_counter)
     return exit_code
예제 #8
0
파일: sim.py 프로젝트: cornell-brg/pydgin
class Sim( object ):

  def __init__( self, arch_name_human, arch_name="", jit_enabled=False ):

    # the human-friendly architecture name can contain large caps, special
    # characters etc.

    self.arch_name_human = arch_name_human
    if arch_name == "":
      self.arch_name = arch_name_human.lower()
    else:
      self.arch_name = arch_name

    self.jit_enabled = jit_enabled

    if jit_enabled:
      self.jitdriver = JitDriver( greens =['pc',],
                                  reds   = ['max_insts', 'state', 'sim',],
                                  virtualizables  =['state',],
                                  get_printable_location=self.get_location,
                                )

      # Set the default trace limit here. Different ISAs can override this
      # value if necessary
      self.default_trace_limit = 400000

    self.max_insts = 0

  #-----------------------------------------------------------------------
  # decode
  #-----------------------------------------------------------------------
  # This needs to be implemented in the child class

  def decode( self, bits ):
    raise NotImplementedError()

  #-----------------------------------------------------------------------
  # hooks provided for isa implementations
  #-----------------------------------------------------------------------

  def pre_execute( self ):
    pass

  def post_execute( self ):
    pass

  #-----------------------------------------------------------------------
  # init_state
  #-----------------------------------------------------------------------
  # This needs to be implemented in the child class

  def init_state( self, exe_file, exe_name, run_argv, testbin ):
    raise NotImplementedError()

  #-----------------------------------------------------------------------
  # help message
  #-----------------------------------------------------------------------
  # the help message to display on --help

  help_message = """
  Pydgin %s Instruction Set Simulator
  usage: %s <args> <sim_exe> <sim_args>

  <sim_exe>  the executable to be simulated
  <sim_args> arguments to be passed to the simulated executable
  <args>     the following optional arguments are supported:

    --help,-h       Show this message and exit
    --test          Run in testing mode (for running asm tests)
    --env,-e <NAME>=<VALUE>
                    Set an environment variable to be passed to the
                    simulated program. Can use multiple --env flags to set
                    multiple environment variables.
    --debug,-d <flags>[:<start_after>]
                    Enable debug flags in a comma-separated form (e.g.
                    "--debug syscalls,insts"). If provided, debugs starts
                    after <start_after> cycles. The following flags are
                    supported:
         insts              cycle-by-cycle instructions
         rf                 register file accesses
         mem                memory accesses
         regdump            register dump
         syscalls           syscall information
         bootstrap          initial stack and register state

    --max-insts <i> Run until the maximum number of instructions
    --jit <flags>   Set flags to tune the JIT (see
                    rpython.rlib.jit.PARAMETER_DOCS)

  """

  #-----------------------------------------------------------------------
  # get_location
  #-----------------------------------------------------------------------
  # for debug printing in PYPYLOG

  @staticmethod
  def get_location( pc ):
    # TODO: add the disassembly of the instruction here as well
    return "pc: %x" % pc

  #-----------------------------------------------------------------------
  # run
  #-----------------------------------------------------------------------
  def run( self ):
    self = hint( self, promote=True )
    s = self.state

    max_insts = self.max_insts
    jitdriver = self.jitdriver

    while s.running:

      jitdriver.jit_merge_point(
        pc        = s.fetch_pc(),
        max_insts = max_insts,
        state     = s,
        sim       = self,
      )

      # constant-fold pc and mem
      pc  = hint( s.fetch_pc(), promote=True )
      old = pc
      mem = hint( s.mem, promote=True )

      if s.debug.enabled( "insts" ):
        print pad( "%x" % pc, 8, " ", False ),

      # the print statement in memcheck conflicts with @elidable in iread.
      # So we use normal read if memcheck is enabled which includes the
      # memory checks

      if s.debug.enabled( "memcheck" ):
        inst_bits = mem.read( pc, 4 )
      else:
        # we use trace elidable iread instead of just read
        inst_bits = mem.iread( pc, 4 )

      try:
        inst, exec_fun = self.decode( inst_bits )

        if s.debug.enabled( "insts" ):
          print "%s %s %s" % (
                  pad_hex( inst_bits ),
                  pad( inst.str, 12 ),
                  pad( "%d" % s.num_insts, 8 ), ),

        self.pre_execute()

        exec_fun( s, inst )
      except NotImplementedInstError:
        # re-decode instruction to get the instruction name
        inst, _ = self.decode( inst_bits )

        print "Instruction not implemented: %s (pc: 0x%s), aborting!" \
              % ( inst.str, pad_hex( pc ) )
        break
      except FatalError as error:
        print "Exception in execution (pc: 0x%s), aborting!" % pad_hex( pc )
        print "Exception message: %s" % error.msg
        break

      s.num_insts += 1    # TODO: should this be done inside instruction definition?
      if s.stats_en: s.stat_num_insts += 1

      self.post_execute()

      if s.debug.enabled( "insts" ):
        print
      if s.debug.enabled( "regdump" ):
        s.rf.print_regs( per_row=4 )

      # check if we have reached the end of the maximum instructions and
      # exit if necessary
      if max_insts != 0 and s.num_insts >= max_insts:
        print "Reached the max_insts (%d), exiting." % max_insts
        break

      if s.fetch_pc() < old:
        jitdriver.can_enter_jit(
          pc        = s.fetch_pc(),
          max_insts = max_insts,
          state     = s,
          sim       = self,
        )

    print 'DONE! Status =', s.status
    print 'Instructions Executed =', s.num_insts

  #-----------------------------------------------------------------------
  # get_entry_point
  #-----------------------------------------------------------------------
  # generates and returns the entry_point function used to start the
  # simulator

  def get_entry_point( self ):
    def entry_point( argv ):

      # set the trace_limit parameter of the jitdriver
      if self.jit_enabled:
        set_param( self.jitdriver, "trace_limit", self.default_trace_limit )

      filename_idx       = 0
      debug_flags        = []
      debug_starts_after = 0
      testbin            = False
      max_insts          = 0
      envp               = []

      # we're using a mini state machine to parse the args

      prev_token = ""

      # list of tokens that require an additional arg

      tokens_with_args = [ "-h", "--help",
                           "-e", "--env",
                           "-d", "--debug",
                           "--max-insts",
                           "--jit",
                         ]

      # go through the args one by one and parse accordingly

      for i in xrange( 1, len( argv ) ):
        token = argv[i]

        if prev_token == "":

          if token == "--help" or token == "-h":
            print self.help_message % ( self.arch_name_human, argv[0] )
            return 0

          elif token == "--test":
            testbin = True

          elif token == "--debug" or token == "-d":
            prev_token = token
            # warn the user if debugs are not enabled for this translation
            if not Debug.global_enabled:
              print "WARNING: debugs are not enabled for this translation. " + \
                    "To allow debugs, translate with --debug option."

          elif token in tokens_with_args:
            prev_token = token

          elif token[:1] == "-":
            # unknown option
            print "Unknown argument %s" % token
            return 1

          else:
            # this marks the start of the program name
            filename_idx = i
            break

        else:
          if prev_token == "--env" or prev_token == "-e":
            envp.append( token )

          elif prev_token == "--debug" or prev_token == "-d":
            # if debug start after provided (using a colon), parse it
            debug_tokens = token.split( ":" )
            if len( debug_tokens ) > 1:
              debug_starts_after = int( debug_tokens[1] )

            debug_flags = debug_tokens[0].split( "," )

          elif prev_token == "--max-insts":
            self.max_insts = int( token )

          elif prev_token == "--jit":
            # pass the jit flags to rpython.rlib.jit
            set_user_param( self.jitdriver, token )

          prev_token = ""

      if filename_idx == 0:
        print "You must supply a filename"
        return 1

      # create a Debug object which contains the debug flags

      self.debug = Debug( debug_flags, debug_starts_after )

      filename = argv[ filename_idx ]

      # args after program are args to the simulated program

      run_argv = argv[ filename_idx : ]

      # Open the executable for reading

      try:
        exe_file = open( filename, 'rb' )

      except IOError:
        print "Could not open file %s" % filename
        return 1

      # Call ISA-dependent init_state to load program, initialize memory
      # etc.

      self.init_state( exe_file, filename, run_argv, envp, testbin )

      # pass the state to debug for cycle-triggered debugging

      self.debug.set_state( self.state )

      # Close after loading

      exe_file.close()

      # Execute the program

      self.run()

      return 0

    return entry_point

  #-----------------------------------------------------------------------
  # target
  #-----------------------------------------------------------------------
  # Enables RPython translation of our interpreter.

  def target( self, driver, args ):

    # if --debug flag is provided in translation, we enable debug printing

    if "--debug" in args:
      print "Enabling debugging"
      Debug.global_enabled = True
    else:
      print "Disabling debugging"

    # form a name
    exe_name = "pydgin-%s" % self.arch_name
    if driver.config.translation.jit:
      exe_name += "-jit"
    else:
      exe_name += "-nojit"

    if Debug.global_enabled:
      exe_name += "-debug"

    print "Translated binary name:", exe_name
    driver.exe_name = exe_name

    # NOTE: RPython has an assertion to check the type of entry_point to
    # be function (not a bound method). So we use get_entry_point which
    # generates a function type
    #return self.entry_point, None
    return self.get_entry_point(), None
예제 #9
0
파일: sim.py 프로젝트: cornell-brg/pydgin
    def entry_point( argv ):

      # set the trace_limit parameter of the jitdriver
      if self.jit_enabled:
        set_param( self.jitdriver, "trace_limit", self.default_trace_limit )

      filename_idx       = 0
      debug_flags        = []
      debug_starts_after = 0
      testbin            = False
      max_insts          = 0
      envp               = []

      # we're using a mini state machine to parse the args

      prev_token = ""

      # list of tokens that require an additional arg

      tokens_with_args = [ "-h", "--help",
                           "-e", "--env",
                           "-d", "--debug",
                           "--max-insts",
                           "--jit",
                         ]

      # go through the args one by one and parse accordingly

      for i in xrange( 1, len( argv ) ):
        token = argv[i]

        if prev_token == "":

          if token == "--help" or token == "-h":
            print self.help_message % ( self.arch_name_human, argv[0] )
            return 0

          elif token == "--test":
            testbin = True

          elif token == "--debug" or token == "-d":
            prev_token = token
            # warn the user if debugs are not enabled for this translation
            if not Debug.global_enabled:
              print "WARNING: debugs are not enabled for this translation. " + \
                    "To allow debugs, translate with --debug option."

          elif token in tokens_with_args:
            prev_token = token

          elif token[:1] == "-":
            # unknown option
            print "Unknown argument %s" % token
            return 1

          else:
            # this marks the start of the program name
            filename_idx = i
            break

        else:
          if prev_token == "--env" or prev_token == "-e":
            envp.append( token )

          elif prev_token == "--debug" or prev_token == "-d":
            # if debug start after provided (using a colon), parse it
            debug_tokens = token.split( ":" )
            if len( debug_tokens ) > 1:
              debug_starts_after = int( debug_tokens[1] )

            debug_flags = debug_tokens[0].split( "," )

          elif prev_token == "--max-insts":
            self.max_insts = int( token )

          elif prev_token == "--jit":
            # pass the jit flags to rpython.rlib.jit
            set_user_param( self.jitdriver, token )

          prev_token = ""

      if filename_idx == 0:
        print "You must supply a filename"
        return 1

      # create a Debug object which contains the debug flags

      self.debug = Debug( debug_flags, debug_starts_after )

      filename = argv[ filename_idx ]

      # args after program are args to the simulated program

      run_argv = argv[ filename_idx : ]

      # Open the executable for reading

      try:
        exe_file = open( filename, 'rb' )

      except IOError:
        print "Could not open file %s" % filename
        return 1

      # Call ISA-dependent init_state to load program, initialize memory
      # etc.

      self.init_state( exe_file, filename, run_argv, envp, testbin )

      # pass the state to debug for cycle-triggered debugging

      self.debug.set_state( self.state )

      # Close after loading

      exe_file.close()

      # Execute the program

      self.run()

      return 0
예제 #10
0
 def __init__( self, num_regs=32, nbits=64 ):
   self.num_regs = num_regs
   self.regs     = [ r_uint(0) ] * self.num_regs
   self.debug    = Debug()
   self.nbits    = nbits
   self.debug_nchars = nbits / 4
예제 #11
0
class Memory(object):
    """Sparse memory model adapted from Pydgin.
    """

    def __init__(self, block_size=2**20, logger=None):
        self.block_size = block_size
        self.debug = Debug()
        self.logger = logger
        self.first_core = 0x808
        self.addr_mask  = block_size - 1
        self.block_mask = 0xffffffff ^ self.addr_mask
        self.block_dict = {}
        self.code_blocks = []

    def add_block(self, block_addr):
        self.block_dict[block_addr] = _BlockMemory(size=self.block_size)

    def get_block_mem(self, block_addr):
        if block_addr not in self.block_dict:
            self.add_block(block_addr)
        block_mem = self.block_dict[block_addr]
        return block_mem

    def iread(self, start_addr, num_bytes, from_core=0x808):
        if is_local_address(start_addr):
            start_addr |= (from_core << 20)
        end_addr   = start_addr + num_bytes - 1
        block_addr = self.block_mask & start_addr
        block_mem = self.get_block_mem(block_addr)
        # For mixed-width ISAs, the start_addr is not necessarily
        # word-aligned, and can cross block memory boundaries. If there is
        # such a case, we have two instruction reads and then form the word
        # for it.
        block_end_addr = self.block_mask & end_addr
        if block_addr == block_end_addr:
            value = block_mem.iread(start_addr & self.addr_mask, num_bytes)
        else:
            num_bytes1 = min(self.block_size - (start_addr & self.addr_mask),
                             num_bytes)
            num_bytes2 = num_bytes - num_bytes1
            block_mem1 = block_mem
            block_mem2 = self.get_block_mem(block_end_addr)
            value1 = block_mem1.iread(start_addr & self.addr_mask, num_bytes1)
            value2 = block_mem2.iread(0, num_bytes2)
            value = value1 | (value2 << (num_bytes1 * 8))
        return value

    def read(self, start_addr, num_bytes, from_core=0x808):
        if is_local_address(start_addr):
            start_addr |= (from_core << 20)
        block_addr = self.block_mask & start_addr
        block_mem = self.get_block_mem(block_addr)
        masked_addr = 0xfffff & start_addr
        value = block_mem.read(start_addr & self.addr_mask, num_bytes)
        if (self.debug.enabled('mem') and self.logger and
              not is_register_address(masked_addr) and
              (start_addr >> 20) == self.first_core):
            if start_addr >> 20 == from_core:
                start_addr = start_addr & 0xfffff
            self.logger.log(' :: RD.MEM[%s] = %s' % \
                              (pad_hex(start_addr), pad_hex(value)))
        return value

    def write(self, start_addr, num_bytes, value, from_core=0x808, quiet=False):
        """Deal with register writes that are aliases to other locations. Better
        not to put these in the instruction semantics, as the aliased
        registers may be written to by a variety of instructions, and accessed
        as either registers or memory locations.
        """
        if is_local_address(start_addr):
            start_addr |= (from_core << 20)
        coreid_mask = start_addr & 0xfff00000
        for start, end in self.code_blocks:
            if start_addr >= start and (start_addr + num_bytes) <= end:
                print 'WARNING: self-modifying code @', pad_hex(start_addr)
        if start_addr & 0xfffff == 0xf042c:  # ILATST
            ilat = self.read(coreid_mask | 0xf0428, 4) & 0x3ff
            ilat |= (value & ((2 << 10) - 1))
            self.write(coreid_mask | 0xf0428, 4, ilat)
        elif start_addr & 0xfffff == 0xf0430:  # ILATCL
            ilat = self.read(coreid_mask | 0xf0428, 4) & 0x3ff
            ilat &= ~(value &  ((2 << 10) - 1))
            self.write(coreid_mask | 0xf0428, 4, ilat)
        elif start_addr & 0xfffff == 0xf0440:  # FSTATUS
            status = self.read(coreid_mask | 0xf0404, 4)
            status |= (value & 0xfffffffc)  # Can't write to lowest 2 bits.
            self.write(coreid_mask | 0xf0404, 4, status)
        elif start_addr & 0xfffff == 0xf0438 and value == 0:  # CTIMER0 expired.
            ilat = self.read(coreid_mask | 0xf0428, 4) & 0x3ff
            ilat |= 0x8
            self.write(coreid_mask | 0xf0428, 4, ilat)
        elif start_addr & 0xfffff == 0xf043c and value == 0:  # CTIMER1 expired.
            ilat = self.read(coreid_mask | 0xf0428, 4) & 0x3ff
            ilat |= 0x10
            self.write(coreid_mask | 0xf0428, 4, ilat)
        block_addr = self.block_mask & start_addr
        block_mem = self.get_block_mem(block_addr)
        block_mem.write(start_addr & self.addr_mask, num_bytes, value)
        masked_addr = 0xfffff & start_addr
        if (self.debug.enabled('mem') and self.logger and not quiet and
              not is_register_address(masked_addr) and
              (start_addr >> 20) == self.first_core):
            if start_addr >> 20 == from_core:
                start_addr = start_addr & 0xfffff
            self.logger.log(' :: WR.MEM[%s] = %s' % \
                              (pad_hex(start_addr), pad_hex(value)))
예제 #12
0
class Sim(object):
    def __init__(self, arch_name_human, arch_name="", jit_enabled=False):

        # the human-friendly architecture name can contain large caps, special
        # characters etc.

        self.arch_name_human = arch_name_human
        if arch_name == "":
            self.arch_name = arch_name_human.lower()
        else:
            self.arch_name = arch_name

        self.jit_enabled = jit_enabled

        if jit_enabled:
            self.jitdriver = JitDriver(
                greens=[
                    'pc',
                ],
                reds=[
                    'max_insts',
                    'state',
                    'sim',
                ],
                virtualizables=[
                    'state',
                ],
                get_printable_location=self.get_location,
            )

            # Set the default trace limit here. Different ISAs can override this
            # value if necessary
            self.default_trace_limit = 400000

        self.max_insts = 0

    #-----------------------------------------------------------------------
    # decode
    #-----------------------------------------------------------------------
    # This needs to be implemented in the child class

    def decode(self, bits):
        raise NotImplementedError()

    #-----------------------------------------------------------------------
    # hooks provided for isa implementations
    #-----------------------------------------------------------------------

    def pre_execute(self):
        pass

    def post_execute(self):
        pass

    #-----------------------------------------------------------------------
    # init_state
    #-----------------------------------------------------------------------
    # This needs to be implemented in the child class

    def init_state(self, exe_file, exe_name, run_argv, testbin):
        raise NotImplementedError()

    #-----------------------------------------------------------------------
    # help message
    #-----------------------------------------------------------------------
    # the help message to display on --help

    help_message = """
  Pydgin %s Instruction Set Simulator
  usage: %s <args> <sim_exe> <sim_args>

  <sim_exe>  the executable to be simulated
  <sim_args> arguments to be passed to the simulated executable
  <args>     the following optional arguments are supported:

    --help,-h       Show this message and exit
    --test          Run in testing mode (for running asm tests)
    --env,-e <NAME>=<VALUE>
                    Set an environment variable to be passed to the
                    simulated program. Can use multiple --env flags to set
                    multiple environment variables.
    --debug,-d <flags>[:<start_after>]
                    Enable debug flags in a comma-separated form (e.g.
                    "--debug syscalls,insts"). If provided, debugs starts
                    after <start_after> cycles. The following flags are
                    supported:
         insts              cycle-by-cycle instructions
         rf                 register file accesses
         mem                memory accesses
         regdump            register dump
         syscalls           syscall information
         bootstrap          initial stack and register state

    --max-insts <i> Run until the maximum number of instructions
    --jit <flags>   Set flags to tune the JIT (see
                    rpython.rlib.jit.PARAMETER_DOCS)

  """

    #-----------------------------------------------------------------------
    # get_location
    #-----------------------------------------------------------------------
    # for debug printing in PYPYLOG

    @staticmethod
    def get_location(pc):
        # TODO: add the disassembly of the instruction here as well
        return "pc: %x" % pc

    #-----------------------------------------------------------------------
    # run
    #-----------------------------------------------------------------------
    def run(self):
        self = hint(self, promote=True)
        s = self.state

        max_insts = self.max_insts
        jitdriver = self.jitdriver

        while s.running:

            jitdriver.jit_merge_point(
                pc=s.fetch_pc(),
                max_insts=max_insts,
                state=s,
                sim=self,
            )

            # constant-fold pc and mem
            pc = hint(s.fetch_pc(), promote=True)
            old = pc
            mem = hint(s.mem, promote=True)

            if s.debug.enabled("insts"):
                print pad("%x" % pc, 8, " ", False),

            # the print statement in memcheck conflicts with @elidable in iread.
            # So we use normal read if memcheck is enabled which includes the
            # memory checks

            if s.debug.enabled("memcheck"):
                inst_bits = mem.read(pc, 4)
            else:
                # we use trace elidable iread instead of just read
                inst_bits = mem.iread(pc, 4)

            try:
                inst, exec_fun = self.decode(inst_bits)

                if s.debug.enabled("insts"):
                    print "%s %s %s" % (
                        pad_hex(inst_bits),
                        pad(inst.str, 12),
                        pad("%d" % s.num_insts, 8),
                    ),

                self.pre_execute()

                exec_fun(s, inst)
            except NotImplementedInstError:
                # re-decode instruction to get the instruction name
                inst, _ = self.decode(inst_bits)

                print "Instruction not implemented: %s (pc: 0x%s), aborting!" \
                      % ( inst.str, pad_hex( pc ) )
                break
            except FatalError as error:
                print "Exception in execution (pc: 0x%s), aborting!" % pad_hex(
                    pc)
                print "Exception message: %s" % error.msg
                break

            s.num_insts += 1  # TODO: should this be done inside instruction definition?
            if s.stats_en: s.stat_num_insts += 1

            self.post_execute()

            if s.debug.enabled("insts"):
                print
            if s.debug.enabled("regdump"):
                s.rf.print_regs(per_row=4)

            # check if we have reached the end of the maximum instructions and
            # exit if necessary
            if max_insts != 0 and s.num_insts >= max_insts:
                print "Reached the max_insts (%d), exiting." % max_insts
                break

            if s.fetch_pc() < old:
                jitdriver.can_enter_jit(
                    pc=s.fetch_pc(),
                    max_insts=max_insts,
                    state=s,
                    sim=self,
                )

        print 'DONE! Status =', s.status
        print 'Instructions Executed =', s.num_insts

    #-----------------------------------------------------------------------
    # get_entry_point
    #-----------------------------------------------------------------------
    # generates and returns the entry_point function used to start the
    # simulator

    def get_entry_point(self):
        def entry_point(argv):

            # set the trace_limit parameter of the jitdriver
            if self.jit_enabled:
                set_param(self.jitdriver, "trace_limit",
                          self.default_trace_limit)

            filename_idx = 0
            debug_flags = []
            debug_starts_after = 0
            testbin = False
            max_insts = 0
            envp = []

            # we're using a mini state machine to parse the args

            prev_token = ""

            # list of tokens that require an additional arg

            tokens_with_args = [
                "-h",
                "--help",
                "-e",
                "--env",
                "-d",
                "--debug",
                "--max-insts",
                "--jit",
            ]

            # go through the args one by one and parse accordingly

            for i in xrange(1, len(argv)):
                token = argv[i]

                if prev_token == "":

                    if token == "--help" or token == "-h":
                        print self.help_message % (self.arch_name_human,
                                                   argv[0])
                        return 0

                    elif token == "--test":
                        testbin = True

                    elif token == "--debug" or token == "-d":
                        prev_token = token
                        # warn the user if debugs are not enabled for this translation
                        if not Debug.global_enabled:
                            print "WARNING: debugs are not enabled for this translation. " + \
                                  "To allow debugs, translate with --debug option."

                    elif token in tokens_with_args:
                        prev_token = token

                    elif token[:1] == "-":
                        # unknown option
                        print "Unknown argument %s" % token
                        return 1

                    else:
                        # this marks the start of the program name
                        filename_idx = i
                        break

                else:
                    if prev_token == "--env" or prev_token == "-e":
                        envp.append(token)

                    elif prev_token == "--debug" or prev_token == "-d":
                        # if debug start after provided (using a colon), parse it
                        debug_tokens = token.split(":")
                        if len(debug_tokens) > 1:
                            debug_starts_after = int(debug_tokens[1])

                        debug_flags = debug_tokens[0].split(",")

                    elif prev_token == "--max-insts":
                        self.max_insts = int(token)

                    elif prev_token == "--jit":
                        # pass the jit flags to rpython.rlib.jit
                        set_user_param(self.jitdriver, token)

                    prev_token = ""

            if filename_idx == 0:
                print "You must supply a filename"
                return 1

            # create a Debug object which contains the debug flags

            self.debug = Debug(debug_flags, debug_starts_after)

            filename = argv[filename_idx]

            # args after program are args to the simulated program

            run_argv = argv[filename_idx:]

            # Open the executable for reading

            try:
                exe_file = open(filename, 'rb')

            except IOError:
                print "Could not open file %s" % filename
                return 1

            # Call ISA-dependent init_state to load program, initialize memory
            # etc.

            self.init_state(exe_file, filename, run_argv, envp, testbin)

            # pass the state to debug for cycle-triggered debugging

            self.debug.set_state(self.state)

            # Close after loading

            exe_file.close()

            # Execute the program

            self.run()

            return 0

        return entry_point

    #-----------------------------------------------------------------------
    # target
    #-----------------------------------------------------------------------
    # Enables RPython translation of our interpreter.

    def target(self, driver, args):

        # if --debug flag is provided in translation, we enable debug printing

        if "--debug" in args:
            print "Enabling debugging"
            Debug.global_enabled = True
        else:
            print "Disabling debugging"

        # form a name
        exe_name = "pydgin-%s" % self.arch_name
        if driver.config.translation.jit:
            exe_name += "-jit"
        else:
            exe_name += "-nojit"

        if Debug.global_enabled:
            exe_name += "-debug"

        print "Translated binary name:", exe_name
        driver.exe_name = exe_name

        # NOTE: RPython has an assertion to check the type of entry_point to
        # be function (not a bound method). So we use get_entry_point which
        # generates a function type
        #return self.entry_point, None
        return self.get_entry_point(), None
예제 #13
0
        def entry_point(argv):

            # set the trace_limit parameter of the jitdriver
            if self.jit_enabled:
                set_param(self.jitdriver, "trace_limit",
                          self.default_trace_limit)

            filename_idx = 0
            debug_flags = []
            debug_starts_after = 0
            testbin = False
            max_insts = 0
            envp = []

            # we're using a mini state machine to parse the args

            prev_token = ""

            # list of tokens that require an additional arg

            tokens_with_args = [
                "-h",
                "--help",
                "-e",
                "--env",
                "-d",
                "--debug",
                "--max-insts",
                "--jit",
            ]

            # go through the args one by one and parse accordingly

            for i in xrange(1, len(argv)):
                token = argv[i]

                if prev_token == "":

                    if token == "--help" or token == "-h":
                        print self.help_message % (self.arch_name_human,
                                                   argv[0])
                        return 0

                    elif token == "--test":
                        testbin = True

                    elif token == "--debug" or token == "-d":
                        prev_token = token
                        # warn the user if debugs are not enabled for this translation
                        if not Debug.global_enabled:
                            print "WARNING: debugs are not enabled for this translation. " + \
                                  "To allow debugs, translate with --debug option."

                    elif token in tokens_with_args:
                        prev_token = token

                    elif token[:1] == "-":
                        # unknown option
                        print "Unknown argument %s" % token
                        return 1

                    else:
                        # this marks the start of the program name
                        filename_idx = i
                        break

                else:
                    if prev_token == "--env" or prev_token == "-e":
                        envp.append(token)

                    elif prev_token == "--debug" or prev_token == "-d":
                        # if debug start after provided (using a colon), parse it
                        debug_tokens = token.split(":")
                        if len(debug_tokens) > 1:
                            debug_starts_after = int(debug_tokens[1])

                        debug_flags = debug_tokens[0].split(",")

                    elif prev_token == "--max-insts":
                        self.max_insts = int(token)

                    elif prev_token == "--jit":
                        # pass the jit flags to rpython.rlib.jit
                        set_user_param(self.jitdriver, token)

                    prev_token = ""

            if filename_idx == 0:
                print "You must supply a filename"
                return 1

            # create a Debug object which contains the debug flags

            self.debug = Debug(debug_flags, debug_starts_after)

            filename = argv[filename_idx]

            # args after program are args to the simulated program

            run_argv = argv[filename_idx:]

            # Open the executable for reading

            try:
                exe_file = open(filename, 'rb')

            except IOError:
                print "Could not open file %s" % filename
                return 1

            # Call ISA-dependent init_state to load program, initialize memory
            # etc.

            self.init_state(exe_file, filename, run_argv, envp, testbin)

            # pass the state to debug for cycle-triggered debugging

            self.debug.set_state(self.state)

            # Close after loading

            exe_file.close()

            # Execute the program

            self.run()

            return 0
예제 #14
0
class Revelation(Sim):

    def __init__(self):
        # DO NOT call Sim.__init__() -- Revelation JIT differs from Pydgin.
        self.arch_name_human = 'Revelation'
        self.arch_name = self.arch_name_human.lower()
        self.jit_enabled = True
        if self.jit_enabled:
            self.jitdriver = JitDriver(
                greens = ['pc', ],
                reds = ['core', 'tick_counter', 'coreids', 'sim', 'state',],
                get_printable_location=get_printable_location)
        self.default_trace_limit = 400000
        self.max_insts = 0             # --max-insts.
        self.logger = None             # --debug output: self.logger.log().
        self.rows = 1                  # --rows, -r.
        self.cols = 1                  # --cols, -c.
        self.states = {}               # coreid -> revelation.machine.State.
        self.first_core = 0x808        # --first-core, -f.
        self.ext_base = 0x8e000000     # Base address of 'external' memory.
        self.ext_size = 32             # Size of 'external' memory in MB.
        self.switch_interval = 1       # --switch. TODO: currently ignored.
        self.user_environment = False  # Superuser mode. TODO: currently ignored.
        self.collect_times = False     # --time, -t option.
        self.start_time = .0           # --time, -t option.
        self.end_time = .0             # --time, -t option.
        self.profile = False  # Undocumented --profile option.
        self.timer = .0       # Undocumented --profile option.

    def get_entry_point(self):
        def entry_point(argv):
            self.timer = time.time()
            if self.jit_enabled:
                set_param(self.jitdriver, 'trace_limit', self.default_trace_limit)
            try:
                fname, jit, flags = cli_parser(argv, self, Debug.global_enabled)
            except DoNotInterpretError:  # CLI option such as --help or -h.
                return EXIT_SUCCESS
            except (SyntaxError, ValueError):
                return EXIT_SYNTAX_ERROR
            if jit:  # pragma: no cover
                set_user_param(self.jitdriver, jit)
            self.debug = Debug(flags, 0)
            try:
                elf_file = open(fname, 'rb')
            except IOError:
                print 'Could not open file %s' % fname
                return EXIT_FILE_ERROR
            if self.profile:
                timer = time.time()
                print 'CLI parser took: %fs' % (timer - self.timer)
                self.timer = timer
            self.init_state(elf_file, fname, False)
            for coreid in self.states:
                self.debug.set_state(self.states[coreid])
            elf_file.close()
            try:
                exit_code, tick_counter = self.run()
            except KeyboardInterrupt:
                exit_code = EXIT_CTRL_C
                tick_counter = -1
            if self.collect_times:
                self.end_time = time.time()
            if self.logger:
                self.logger.close()
            self._print_summary_statistics(tick_counter)
            return exit_code
        return entry_point

    def run(self):
        """Fetch, decode, execute, service interrupts loop.
        Override Sim.run to provide multicore and close the logger on exit.
        """
        coreids = self.states.keys()
        core = coreids[0]      # Key to self.states dictionary.
        state = self.states[core]  # revelation.machine.State object.
        pc = state.fetch_pc()  # Program counter.
        tick_counter = 0       # Number of instructions executed by all cores.
        old_pc = 0
        self.start_time = time.time()

        while True:
            self.jitdriver.jit_merge_point(pc=pc,
                                           core=core,
                                           tick_counter=tick_counter,
                                           coreids=coreids,
                                           sim=self,
                                           state=state,)
            # Fetch next instruction.
            opcode = state.mem.iread(pc, 4, from_core=state.coreid)
            try:
                # Decode instruction.
                mnemonic, function = decode(opcode)
                instruction = Instruction(opcode, mnemonic)
                # --debug
                if (state.is_first_core and self.logger and
                      state.debug.enabled('trace')):
                    state.logger.log('%s %s %s %s' %
                        (pad('%x' % pc, 8, ' ', False),
                         pad_hex(opcode), pad(instruction.name, 12),
                         pad('%d' % state.num_insts, 8)))
                # Check whether or not we are in a hardware loop, and set
                # registers after the next instruction, as appropriate. See
                # Section 7.9 of the Architecture Reference Rev. 14.03.11.
                if (state.GID and state.pc == state.rf[reg_map['LE']]):
                    state.rf[reg_map['LC']] -= 1
                    state.is_in_hardware_loop = True
                # Execute next instruction.
                function(state, instruction)
                # --debug
                if (state.is_first_core and state.logger and
                      state.debug.enabled('trace')):
                    state.logger.log('\n')
                # Check hardware loop registers.
                if state.is_in_hardware_loop and state.rf[reg_map['LC']] > 0:
                    state.pc = state.rf[reg_map['LS']]
                    state.is_in_hardware_loop = False
                # Service interrupts.
                if (state.rf[reg_map['ILAT']] > 0 and not (state.GID or
                       state.rf[reg_map['DEBUGSTATUS']] == 1)):
                    interrupt_level = state.get_latched_interrupt()
                    if interrupt_level > -1:  # Interrupt to process.
                        # If a pending interrupt is of a higher priority than
                        # the latched interrupt, carry on with the pending
                        # interrupt.
                        pending_interrupt = state.get_pending_interrupt()
                        if (pending_interrupt == -1 or
                              (pending_interrupt > -1 and
                              interrupt_level <= pending_interrupt)):
                            state.rf[reg_map['IRET']] = state.pc
                            state.rf[reg_map['ILAT']] &= ~(1 << interrupt_level)
                            state.rf[reg_map['IPEND']] |= 1 << interrupt_level
                            state.GID = True  # Set global interrupt disabled bit.
                            state.pc = IVT[interrupt_level]
                            state.ACTIVE = 1  # Wake up IDLE cores.
            except (FatalError, NotImplementedInstError) as error:
                mnemonic, _ = decode(opcode)
                print ('Exception in execution of %s (pc: 0x%s), aborting!' %
                       (mnemonic, pad_hex(pc)))
                print 'Exception message: %s' % error.msg
                return EXIT_GENERAL_ERROR, tick_counter  # pragma: no cover
            # Update instruction counters.
            tick_counter += 1
            state.num_insts += 1
            # Halt if we have reached the maximum instruction count.
            if self.max_insts != 0 and state.num_insts >= self.max_insts:
                print 'Reached the max_insts (%d), exiting.' % self.max_insts
                break
            # Check whether state has halted.
            if not state.running:
                if len(coreids) == 1:  # Last running core has halted.
                    break
                old_core = core
                core = coreids[(coreids.index(core) + 1) % len(coreids)]
                state = self.states[core]
                coreids.remove(old_core)
            # Switch cores after every instruction. TODO: Honour switch interval.
            elif len(coreids) > 1 and tick_counter % self.switch_interval == 0:
                while True:
                    core = coreids[(coreids.index(core) + 1) % len(coreids)]
                    if self.states[core].ACTIVE == 1:
                        break
                    # Idle cores can be made active by interrupts.
                    elif (self.states[core].ACTIVE == 0 and
                            self.states[core].rf[reg_map['ILAT']] > 0):
                        interrupt_level = self.states[core].get_latched_interrupt()
                        self.states[core].rf[reg_map['IRET']] = self.states[core].pc
                        self.states[core].rf[reg_map['ILAT']] &= ~(1 << interrupt_level)
                        self.states[core].rf[reg_map['IPEND']] |= 1 << interrupt_level
                        self.states[core].GID = True  # Set global interrupt disabled bit.
                        self.states[core].pc = IVT[interrupt_level]
                        self.states[core].ACTIVE = 1  # Wake up IDLE cores.
                        break
                state = self.states[core]
            # Move program counter to next instruction.
            old_pc = pc
            pc = state.fetch_pc()
            if pc < old_pc:
                self.jitdriver.can_enter_jit(pc=pc,
                                             core=core,
                                             tick_counter=tick_counter,
                                             coreids=coreids,
                                             sim=self,
                                             state=state,)
        return EXIT_SUCCESS, tick_counter

    def _print_summary_statistics(self, ticks):
        """Print timing information. If simulation was interrupted by the user
        pressing Ctrl+c, 'ticks' will be -1.
        """
        if ticks > -1:
            print 'Total ticks simulated = %s.' % format_thousands(ticks)
        for coreid in self.states:
            row, col = get_coords_from_coreid(coreid)
            print ('Core %s (%s, %s) STATUS: 0x%s, Instructions executed: %s' %
                   (hex(coreid), zfill(str(row), 2), zfill(str(col), 2),
                    pad_hex(self.states[coreid].rf[reg_map['STATUS']]),
                    format_thousands(self.states[coreid].num_insts)))
        if self.collect_times:
            execution_time = self.end_time - self.start_time
            print 'Total execution time: %fs.' % (execution_time)
            if ticks > -1:
                speed = format_thousands(int(ticks / execution_time))
                print 'Simulator speed:      %s instructions / second.' % speed

    def init_state(self, elf_file, filename, testbin, is_test=False):
        """Revelation has custom logging infrastructure that differs from the
        default provided by Pydgin. This matches e-sim, in that log messages are
        written to a file rather than to STDOUT. This prevents some specious
        differences in the two traces; e.g. the mode of an fstat object
        differing between Revelation and e-sim when the Revelation log is
        redirected from STDOUT to a file. This makes scripts/diff_trace.py much
        more useful.
        """
        if is_test:
            self.debug = Debug()
            Debug.global_enabled = True
        if self.debug.enabled_flags and Debug.global_enabled:
            print 'Trace will be written to: %s.' % LOG_FILENAME
            self.logger = Logger(LOG_FILENAME)
        if self.profile:
            timer = time.time()
            print 'Debugging set up took: %fs' % (timer - self.timer)
            self.timer = timer
        self.memory = new_memory(self.logger)
        if self.profile:
            timer = time.time()
            print 'Memory creation took: %fs' % (timer - self.timer)
            self.timer = timer
        f_row = (self.first_core >> 6) & 0x3f
        f_col = self.first_core & 0x3f
        elf = elf_reader(elf_file, is_64bit=False)
        coreids = []
        for row in xrange(self.rows):
            for col in xrange(self.cols):
                coreid = get_coreid_from_coords(f_row + row, f_col + col)
                coreids.append(coreid)
                print ('Loading program %s on to core %s (%s, %s)' %
                       (filename, hex(coreid), zfill(str(f_row + row), 2),
                        zfill(str(f_col + col), 2)))
                self.states[coreid] = State(self.memory, self.debug,
                                            logger=self.logger, coreid=coreid)
        code_blocks = load_program(elf, self.memory, coreids, ext_base=self.ext_base,
                                   ext_size=self.ext_size)
        for section in code_blocks:
            self.memory.code_blocks.append(section)
        self.states[coreids[0]].set_first_core(True)
        if self.profile:
            timer = time.time()
            print 'ELF file loader took: %fs' % (timer - self.timer)
            self.timer = timer
예제 #15
0
 def __init__(self, num_regs=32, nbits=64):
     self.num_regs = num_regs
     self.regs = [r_uint(0)] * self.num_regs
     self.debug = Debug()
     self.nbits = nbits
     self.debug_nchars = nbits / 4
예제 #16
0
파일: arm-sim.py 프로젝트: cfbolz/pydgin
def entry_point(argv):

    filename_idx = 0
    debug_flags = []
    testbin = False
    max_insts = 0

    # we're using a mini state machine to parse the args, and these are two
    # states we have

    ARGS = 0
    DEBUG_FLAGS = 1
    MAX_INSTS = 2
    token_type = ARGS

    # go through the args one by one and parse accordingly

    for i in xrange(1, len(argv)):
        token = argv[i]

        if token_type == ARGS:

            if token == "--help":
                print help_message % argv[0]
                return 0

            elif token == "--test":
                testbin = True

            elif token == "--debug":
                token_type = DEBUG_FLAGS
                # warn the user if debugs are not enabled for this translation
                if not Debug.global_enabled:
                    print "WARNING: debugs are not enabled for this translation. " + \
                          "To allow debugs, translate with --debug option."

            elif token == "--max-insts":
                token_type = MAX_INSTS

            elif token[:2] == "--":
                # unknown option
                print "Unknown argument %s" % token
                return 1

            else:
                # this marks the start of the program name
                filename_idx = i
                break

        elif token_type == DEBUG_FLAGS:
            debug_flags = token.split(",")
            token_type = ARGS
        elif token_type == MAX_INSTS:
            max_insts = int(token)
            token_type = ARGS

    if filename_idx == 0:
        print "You must supply a filename"
        return 1

    filename = argv[filename_idx]

    # args after program are args to the simulated program

    run_argv = argv[filename_idx:]

    # Load the program into a memory object

    mem = Memory(size=memory_size, byte_storage=False)
    entrypoint, breakpoint = load_program(
        open(filename, 'rb'),
        mem,
        # TODO: GEM5 uses this alignment, remove?
        alignment=1 << 12)

    # create a Debug object which contains the debug flags

    debug = Debug()
    debug.set_flags(debug_flags)

    # Insert bootstrapping code into memory and initialize processor state

    state = syscall_init(mem, entrypoint, breakpoint, run_argv, debug)

    # Execute the program

    run(state, max_insts)

    return 0