# Path: src/uio/ti/icss/program.py
# class Program:
#     def __init__( self ):
#         self.path = None
#         self.entrypoint = None
#         self.memories = [ Memory( *meminfo ) for meminfo in memories ]
#         self.labels = {}
#         self.dbginfo = None
#         self.sourcefiles = None
# 
#     @property
#     def code( self ):
#         return self.memories[ 0 ]
# 
#     def add_segment( self, data, address, is_code=False ):
#         for mem in reversed( self.memories ):
#             if address >= mem.address and is_code == mem.is_code:
#                 return mem.add( data, address - mem.address )
#         raise RuntimeError( "Invalid segment load address" )
# 
#     @staticmethod
#     def load( path, filetype=None, *, entrypoint=None ):
#         path = Path( path )
# 
#         with path.open( 'rb' ) as f:
#             exe = f.read()
# 
#         if filetype is None: # auto detect filetype
#             # ELF magic is not a valid pru instruction (in little endian)
#             if exe[:4] == b'\x7fELF':
#                 filetype = 'elf'
#             elif path.suffix == '.dbg':
#                 filetype = 'dbg'
#             else:
#                 filetype = 'bin'
# 
#         program = Program()
#         program.path = path
#         program.entrypoint = entrypoint
# 
#         if filetype == 'elf':
#             program._load_elf( exe )
#         elif filetype == 'bin':
#             program._load_bin( exe )
#         elif filetype == 'dbg':
#             program._load_dbg( exe )
#         else:
#             raise ValueError( "Unknown filetype: %r" % filetype )
# 
#         return program
# 
#     def _load_bin( self, exe ):
#         if self.entrypoint is None:
#             self.entrypoint = 0
# 
#         self.code.add( exe, 0 )
# 
#     def _load_dbg( self, dbg ):
#         ( magic, n_label, label_off, n_file, file_off, n_instr, instr_off,
#                 self.entrypoint, flags ) = unpack( '9I', dbg, 0 )
#         if magic != 0x10150003:
#             raise RuntimeError( "Invalid debug info" )
# 
#         for i in range( n_label ):
#             ( addr, name ) = unpack( 'I 64s', dbg, label_off )
#             label_off += 4 + 64
#             name = name.decode( 'ascii' ).rstrip( "\x00" )
#             self.labels[ name ] = addr
# 
#         files = []
#         for i in range( n_file ):
#             name = dbg[ file_off : file_off + 64 ]
#             file_off += 64
#             name = name.decode( 'ascii' ).rstrip( "\x00" )
#             files.append( SourceFile( self.path.parent / name ) )
#         self.sourcefiles = files
# 
#         dbginfo = []
#         for i in range( n_instr ):
#             ( flags, fileindex, line, addr, opcode ) = unpack( 'HHIII', dbg, instr_off )
#             instr_off += 16
#             if addr != i:
#                 raise RuntimeError( "Unexpected code address" )
#             instr = Instruction( i, opcode, files[ fileindex ], line )
#             dbginfo.append( instr )
#         self.dbginfo = dbginfo
# 
#         exe = array( 'I', ( instr.opcode for instr in dbginfo ) )
#         self.code.add( exe, 0 )
# 
# 
#     def _load_elf( self, exe ):
#         # parse file header
#         if exe[:7] != b'\x7fELF\x01\x01\x01':
#             raise RuntimeError( "Invalid ELF32 header" )
#         if unpack( 'HH', exe, 0x10 ) != ( 2, 144 ):
#             raise RuntimeError( "Not a TI-PRU executable" )
#         ( entry, phoff, phsz, nph ) = unpack( 'II10xHH', exe, 0x18 )
# 
#         if self.entrypoint is None:
#             if entry & 3:
#                 raise RuntimeError( "Entrypoint not word-aligned: 0x%x" % entry )
#             self.entrypoint = entry >> 2
#         elif entry != self.entrypoint << 2:
#             warn( "Overriding entrypoint of ELF executable" )
# 
#         for i in range( nph ):
#             ( pt, *args ) = unpack( '8I', exe, phoff )
#             phoff += phsz
# 
#             if pt == 1:
#                 self._load_elf_segment( exe, *args )
#             elif pt == 0x70000000:
#                 pass  # segment attributes
#             else:
#                 warn( "Unknown program header type: 0x%x" % pt )
# 
#     def _load_elf_segment( self, exe, offset, va, pa, fsz, msz, flags, align ):
#         if fsz > msz or offset + fsz > len( exe ):
#             raise RuntimeError( "Invalid segment" )
# 
#         if not ( flags & 1 ):
#             # data segment
#             self.add_segment( exe[ offset : offset + fsz ], va )
#             self.add_segment( bytearray( msz - fsz ), va + fsz )
#         else:
#             # code segment
#             if va & 3 or fsz & 3 or msz & 3:
#                 raise RuntimeError( "Misaligned code segment" )
#             if fsz < msz:
#                 raise RuntimeError( "Uninitialized code segment" )
#             self.add_segment( exe[ offset : offset + fsz ], va, is_code=True )


from uio.utils import cached_getter
from ctypes import ( c_uint8 as ubyte, c_uint16 as ushort, c_uint32 as uint )
from struct import unpack_from as unpack
from .program import Program
import ctypes
    def halted( self ):
        return not ( self.control & ( RUN | BUSY ) )

    @property
    def state( self ):
        return State( self.control )

    @property
    def profiling( self ):
        return bool( self.control & PROFILE )

    @profiling.setter
    def profiling( self, value ):
        control = self.control | SLEEP
        if control & SINGLE:
            control &= ~RUN
        if value:
            control |= PROFILE
        else:
            control &= ~PROFILE
        self.control = control

    @property
    def profiling_running( self ):
        return not ( ~self.control & ( BUSY | PROFILE ) )

    @cached_getter
    def _profiling_sample( self ):
        return ctypes.c_uint64.from_buffer( self, 0x0c )


# Path: src/uio/ti/icss/program.py
# class Program:
#     def __init__( self ):
#         self.path = None
#         self.entrypoint = None
#         self.memories = [ Memory( *meminfo ) for meminfo in memories ]
#         self.labels = {}
#         self.dbginfo = None
#         self.sourcefiles = None
# 
#     @property
#     def code( self ):
#         return self.memories[ 0 ]
# 
#     def add_segment( self, data, address, is_code=False ):
#         for mem in reversed( self.memories ):
#             if address >= mem.address and is_code == mem.is_code:
#                 return mem.add( data, address - mem.address )
#         raise RuntimeError( "Invalid segment load address" )
# 
#     @staticmethod
#     def load( path, filetype=None, *, entrypoint=None ):
#         path = Path( path )
# 
#         with path.open( 'rb' ) as f:
#             exe = f.read()
# 
#         if filetype is None: # auto detect filetype
#             # ELF magic is not a valid pru instruction (in little endian)
#             if exe[:4] == b'\x7fELF':
#                 filetype = 'elf'
#             elif path.suffix == '.dbg':
#                 filetype = 'dbg'
#             else:
#                 filetype = 'bin'
# 
#         program = Program()
#         program.path = path
#         program.entrypoint = entrypoint
# 
#         if filetype == 'elf':
#             program._load_elf( exe )
#         elif filetype == 'bin':
#             program._load_bin( exe )
#         elif filetype == 'dbg':
#             program._load_dbg( exe )
#         else:
#             raise ValueError( "Unknown filetype: %r" % filetype )
# 
#         return program
# 
#     def _load_bin( self, exe ):
#         if self.entrypoint is None:
#             self.entrypoint = 0
# 
#         self.code.add( exe, 0 )
# 
#     def _load_dbg( self, dbg ):
#         ( magic, n_label, label_off, n_file, file_off, n_instr, instr_off,
#                 self.entrypoint, flags ) = unpack( '9I', dbg, 0 )
#         if magic != 0x10150003:
#             raise RuntimeError( "Invalid debug info" )
# 
#         for i in range( n_label ):
#             ( addr, name ) = unpack( 'I 64s', dbg, label_off )
#             label_off += 4 + 64
#             name = name.decode( 'ascii' ).rstrip( "\x00" )
#             self.labels[ name ] = addr
# 
#         files = []
#         for i in range( n_file ):
#             name = dbg[ file_off : file_off + 64 ]
#             file_off += 64
#             name = name.decode( 'ascii' ).rstrip( "\x00" )
#             files.append( SourceFile( self.path.parent / name ) )
#         self.sourcefiles = files
# 
#         dbginfo = []
#         for i in range( n_instr ):
#             ( flags, fileindex, line, addr, opcode ) = unpack( 'HHIII', dbg, instr_off )
#             instr_off += 16
#             if addr != i:
#                 raise RuntimeError( "Unexpected code address" )
#             instr = Instruction( i, opcode, files[ fileindex ], line )
#             dbginfo.append( instr )
#         self.dbginfo = dbginfo
# 
#         exe = array( 'I', ( instr.opcode for instr in dbginfo ) )
#         self.code.add( exe, 0 )
# 
# 
#     def _load_elf( self, exe ):
#         # parse file header
#         if exe[:7] != b'\x7fELF\x01\x01\x01':
#             raise RuntimeError( "Invalid ELF32 header" )
#         if unpack( 'HH', exe, 0x10 ) != ( 2, 144 ):
#             raise RuntimeError( "Not a TI-PRU executable" )
#         ( entry, phoff, phsz, nph ) = unpack( 'II10xHH', exe, 0x18 )
# 
#         if self.entrypoint is None:
#             if entry & 3:
#                 raise RuntimeError( "Entrypoint not word-aligned: 0x%x" % entry )
#             self.entrypoint = entry >> 2
#         elif entry != self.entrypoint << 2:
#             warn( "Overriding entrypoint of ELF executable" )
# 
#         for i in range( nph ):
#             ( pt, *args ) = unpack( '8I', exe, phoff )
#             phoff += phsz
# 
#             if pt == 1:
#                 self._load_elf_segment( exe, *args )
#             elif pt == 0x70000000:
#                 pass  # segment attributes
#             else:
#                 warn( "Unknown program header type: 0x%x" % pt )
# 
#     def _load_elf_segment( self, exe, offset, va, pa, fsz, msz, flags, align ):
#         if fsz > msz or offset + fsz > len( exe ):
#             raise RuntimeError( "Invalid segment" )
# 
#         if not ( flags & 1 ):
#             # data segment
#             self.add_segment( exe[ offset : offset + fsz ], va )
#             self.add_segment( bytearray( msz - fsz ), va + fsz )
#         else:
#             # code segment
#             if va & 3 or fsz & 3 or msz & 3:
#                 raise RuntimeError( "Misaligned code segment" )
#             if fsz < msz:
#                 raise RuntimeError( "Uninitialized code segment" )
#             self.add_segment( exe[ offset : offset + fsz ], va, is_code=True )


# Path: src/uio/ti/icss/core.py
from uio.utils import cached_getter
from ctypes import ( c_uint8 as ubyte, c_uint16 as ushort, c_uint32 as uint )
from struct import unpack_from as unpack
from .program import Program
import ctypes

    def halted( self ):
        return not ( self.control & ( RUN | BUSY ) )

    @property
    def state( self ):
        return State( self.control )

    @property
    def profiling( self ):
        return bool( self.control & PROFILE )

    @profiling.setter
    def profiling( self, value ):
        control = self.control | SLEEP
        if control & SINGLE:
            control &= ~RUN
        if value:
            control |= PROFILE
        else:
            control &= ~PROFILE
        self.control = control

    @property
    def profiling_running( self ):
        return not ( ~self.control & ( BUSY | PROFILE ) )

    @cached_getter
    def _profiling_sample( self ):
        return ctypes.c_uint64.from_buffer( self, 0x0c )


    def profiling_sample( self, running=None ):