예제 #1
0
    def read_memory(self,
                    address,
                    memory_space=None,
                    size=1,
                    count=1,
                    do_side_effects=False):
        """
        :param address:
            Address to begin reading from.

        :param memory_space:
            Name of the memory space to read or None which will read the core's current memory space.

        :param size:
            Size of memory access unit in bytes. Must be one of 1, 2, 4 or 8.
            Note that not all values are supported by all models.
            Note that the data is always returned as bytes, so calling with
            size=4, count=1 will return a byte array of length 4.

        :param count:
            Number of units to read.

        :param do_side_effects:
            If True, the target must perform any side-effects normally triggered
            by the read, for example clear-on-read.

        Returns an integer if count is 1, otherwise returns a bytearray of length size*count

        """

        space = self._get_address_space(memory_space)

        if address < space.minAddress:
            raise ValueError(
                "Address is below minimum address of memory space '%s'" %
                space.memSpaceName)

        if address > space.maxAddress:
            raise ValueError(
                "Address is above maximum address of memory space '%s'" %
                space.memSpaceName)

        if size not in [1, 2, 4, 8]:
            raise ValueError("'size' must be 1, 2, 4 or 8")

        if count is None:
            count = len(data) / size
            if len(data) % size != 0:
                raise ValueError("len(data) must be a multiple of size")

        cadi_address = CADI.CADIAddrComplete(
            CADI.CADI_NO_OVERLAY, CADI.CADIAddr(space.memSpaceId, address))

        data = self.__cadi.CADIMemRead(cadi_address, count, size,
                                       do_side_effects)

        return data
예제 #2
0
 def appliOutput(self, streamId, count, actualCountp, buf):
     """Semihosting output callback"""
     if streamId == CADI.CADI_STREAMID_STDOUT:
         stream = self.stdout
     elif streamId == CADI.CADI_STREAMID_STDERR:
         stream = self.stderr
     else:
         warn("attempted to write to stream: %s" % streamId)
     stream.write(buf)
     CADI.uint32p_assign(actualCountp, count)
예제 #3
0
    def add_bpt_mem(self,
                    address,
                    memory_space=None,
                    on_read=True,
                    on_write=True,
                    on_modify=True):
        """
        Set a new breakpoint, which will be hit when a memory location is accessed

        :param address:
            The address to set the breakpoint on

        :param memory_space:
            The name of the memory space that ``address`` is in.
            If None, the current memory space of the core is used

        :param on_read:
            If True, the breakpoint will be triggered when the memory location
            is read from.

        :param on_write:
            If True, the breakpoint will be triggered when the memory location
            is written to.

        :param on_modify:
            If True, the breakpoint will be triggered when the memory location
            is modified.
        """

        space = self._get_address_space(memory_space)

        cadi_address = CADI.CADIAddrComplete(
            CADI.CADI_NO_OVERLAY, CADI.CADIAddr(space.memSpaceId, address))

        trigger_type = 0
        if on_read:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_READ
        if on_write:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_WRITE
        if on_modify:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_MODIFY

        if trigger_type == 0:
            raise ValueError(
                "At least one of on_read, on_write and on_modify must be True")

        request = CADI.CADIBptRequest(enabled_par=1,
                                      type_par=CADI.CADI_BPT_MEMORY,
                                      address_par=cadi_address,
                                      triggerType_par=trigger_type)
        bpt = Breakpoint(self, self.__cadi, request)
        self.breakpoints[bpt.number] = bpt
        return self.breakpoints[bpt.number]
예제 #4
0
    def _get_cadi_value(self):
        # info.(min|max|default)Value is stored as int64_t, but sometimes contains 2**64-1
        # The workaround is to add/subtract 2**64 if values seem wrong (max < min)

        # This does not fix the problem in all possible cases
        # This currently gets triggered by the AEM and v8 models
        # Is *seems* to fix the bug for all current cores using the default property values
        # Many properties use the range [-2**63, 2**63-1] so I don't think this can be solved properly

        # This is based on CadiRunner::CheckParameter in MaxCore/CadiRunner/CadiRunner.cpp
        if self.__info.maxValue >= self.__info.minValue:
            if self >= self.__info.minValue and self <= self.__info.maxValue:
                intValue = self
            else:
                raise ValueError("int parameter %s must satisfy: %i <= value <= %i (actual %i)"
                                 % (self.__info.name, self.__info.minValue, self.__info.maxValue, self))
        else: # min and max wrong way round, must be unsigned range

            def unsigned_to_signed(n):
                if n < 0:
                    return n + (2 ** 64)
                else:
                    return n

            if (    unsigned_to_signed(self) >= unsigned_to_signed(self.__info.minValue)
                and unsigned_to_signed(self) <= unsigned_to_signed(self.__info.maxValue) ):
                intValue = self
            else:
                raise ValueError("int parameter %s must satisfy: %i <= value <= %i (actual %i)"
                                 % (self.__info.name, self.__info.minValue, self.__info.maxValue, self))
        return CADI.CADIParameterValue(self.__info.id,
                                       CADI.CADI_PARAM_INT,
                                       intValue,
                                       "")
예제 #5
0
    def write(self, value, sideEffects=False):
        """
        Write a new value to the register. The value may be a bytearray or
        a value appropriate to the register type.
        """

        reg = [
            CADI.CADIReg(self._info.regNumber, 0, i, False,
                         self._info.attribute)
            for i in xrange(self.__reg_count)
        ]
        full_array = bytearray(self.__reg_count * 16)
        if isinstance(value, bytearray):
            full_array[0:len(value)] = value
        elif self.__conversion_str != None:
            if self.__conversion_str != "":
                pack_into(self.__conversion_str, full_array, 0, value)
        elif self._info.display == CADI.CADI_REGTYPE_SYMBOL:
            if value not in self.__symbols:
                raise ValueError(
                    "\"%s\" is not a valid symbol for register %s" %
                    self._info.name)
            pack_into("<I", full_array, 0, self.__symbols.index(value))
        elif self._info.display == CADI.CADI_REGTYPE_STRING:
            full_array[0:len(value)] = value
        else:
            raise TypeError("Expecting a bytearray or %s" % self.__type_str)
        offset = 0
        for r in reg:
            r.bytes = full_array[offset:(offset + 16)]
            offset += 16
        self.__cadi.CADIRegWrite(reg, sideEffects)
예제 #6
0
    def read(self, sideEffects=False):
        """
        Read the contents of the register and attempt to convert it to an
        appropriate format according to CADIRegInfo.display.
        If the value cannot be converted to an appropriate format the
        register contents will be returned as a bytearray.
        """

        reg = [
            CADI.CADIReg(self._info.regNumber, 0, i, False,
                         self._info.attribute)
            for i in xrange(self.__reg_count)
        ]
        reg = self.__cadi.CADIRegRead(reg, sideEffects)
        bytes_to_read = self.__width_in_bytes
        if self._info.display == CADI.CADI_REGTYPE_SYMBOL:
            bytes_to_read = 4
        full_array = b"".join([str(r.bytes) for r in reg])[0:bytes_to_read]
        if self.__conversion_str != None:
            if self.__conversion_str == "":
                # this happens with the vector-breakpoint fake registers on v8A
                return 0
            else:
                return unpack(self.__conversion_str, full_array)[0]
        elif self._info.display == CADI.CADI_REGTYPE_SYMBOL:
            index = unpack("<I", full_array)[0]
            return self.__symbols[index]
        elif self._info.display == CADI.CADI_REGTYPE_STRING:
            return full_array
        else:
            return bytearray(full_array)
예제 #7
0
    def __init__(self, filename, parameters={}, verbose=False):
        """
        Loads a model from a DLL, and initialises it

        :param filename:
            The path of the file to load the model from

        :param parameters:
            Dictionary containing parameters of the model to set. The keys of
            this dictionary should be strings containing the names of the
            parameters, and the values should be strings, bools or ints containing
            the values of the parameters

        :param verbose:
            If True, extra debugging information is printed
        """

        self.__filename = filename
        self._loader = CADI.CADIDll()
        self._loader.openDll(filename)
        self._broker = self._loader.CreateCADIBroker()
        factories = self._broker.GetSimulationFactories()
        factory = factories[0]

        callbacks_enable = '\001' * CADI.CADI_SIM_CB_Count
        errors = []

        @CADIcallback
        def Error(severity, errorCode, erroneousParameterId, message):
            """
            Error(severity, errorCode, erroneousParameterId, message)
            Recieves error information during instantiation
            """
            errors.append("CADIErrorCallback::Error(severity=%s, error=%s, paramId=%d, message=%s)"
                          % (CADIFACT_SEVERITY2str(severity),
                             CADIFACT_ERROR2str(errorCode),
                             erroneousParameterId,
                             repr(message)))

        parameter_dict = ParameterDict(factory.GetParameterInfos())
        for (key, value) in parameters.iteritems():
            # This will raise an exception for unknown parameters
            parameter_dict[key] = value
        
        # This will raise an exception for parameters set to a value of
        # the wrong type or out of range
        parameter_array = parameter_dict._get_parameter_array()
        
        self._sim_callback = Model.SimulationCallback(self, verbose)
        self._sim_error_callback = PyCADIErrorCallback(Error)
        
        simulation = factory.Instantiate(parameter_array,
                                         self._sim_error_callback,
                                         self._sim_callback,
                                         callbacks_enable)
        if simulation is None:
            raise TargetError("Instantiation failed: " + ", ".join(errors))
        factory.Release()

        Model.__init__(self, simulation, verbose)
예제 #8
0
    def get_target(self, target):
        """
        Obtain an interface to a target
        
        :param target: The instance name corresponding to the desired target
        """

        interface_name = "eslapi.CADI2"
        target_id = next((t.id for t in self.__simulation.GetTargetInfos()
                         if t.instanceName == target), None)
        if target_id == None:
            raise ValueError("Model has no target named \"%s\"" % target)
        if target_id not in self.__targets:
            target = self.__simulation.GetTarget(target_id)
            result = target.ObtainInterface(interface_name)
            if type(result) == int:
                raise Model.ObtainInterfaceFailed(interface_name)
            (interface, rev) = result
            cadi = CADI.CAInterface_CADI(interface)
            target_name = cadi.CADIGetTargetInfo().targetName
            try:
                # if this fails, this target object hangs around, breaking the
                # modechange callbacks
                target_object = _target_classes[target_name](cadi, self)
            except Exception as ex:
                target_object = Target(cadi, self)
                if self.__verbose:
                    warn("Failed to load specialised target, falling back to general implementation.\n(Error: %s)" % ex)
            self.__targets[target_id] = target_object
        return self.__targets[target_id]
예제 #9
0
    def get_model_parameters(cls, filename):
        """Get a dictionary containing the default parameters for the model

        :param filename:
            The path of the file to load the model parameters from
        """
        loader = CADI.CADIDll()
        loader.openDll(filename)
        broker = loader.CreateCADIBroker()
        factory = broker.GetSimulationFactories()[0]
        return ParameterDict(factory.GetParameterInfos())
예제 #10
0
    def add_bpt_prog(self, address, memory_space=None):
        """
        Set a new breakpoint, which will be hit when program execution reaches a memory address

        :param address:
            The address to set the breakpoint on

        :param memory_space:
            The name of the memory space that ``address`` is in.
            If None, the current memory space of the core is used
        """

        space = self._get_address_space(memory_space)

        cadi_address = CADI.CADIAddrComplete(
            CADI.CADI_NO_OVERLAY, CADI.CADIAddr(space.memSpaceId, address))
        request = CADI.CADIBptRequest(enabled_par=1,
                                      type_par=CADI.CADI_BPT_PROGRAM,
                                      address_par=cadi_address)
        bpt = Breakpoint(self, self.__cadi, request)
        self.breakpoints[bpt.number] = bpt
        return self.breakpoints[bpt.number]
예제 #11
0
    def add_bpt_reg(self,
                    reg_name,
                    on_read=True,
                    on_write=True,
                    on_modify=True):
        """
        Set a new breakpoint, which will be hit when a register is accessed

        :param reg_name:
            The name of the register to set the breakpoint on.
            The name can be in one of the following formats:
                * ``<group>.<register>``
                * ``<group>.<register>.<field>``
                * ``<register>``
                * ``<register>.<field>``
            
            The last two forms can only be used if the register name is unambiguous

        :param on_read:
            If True, the breakpoint will be triggered when the register is read from.

        :param on_write:
            If True, the breakpoint will be triggered when the register is written to.

        :param on_modify:
            If True, the breakpoint will be triggered when the register is modified.
        """

        # No ARM models support register breakpoints (as of Apr 2013), so this is untested
        register = self._get_register_by_name(reg_name)

        trigger_type = 0
        if on_read:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_READ
        if on_write:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_WRITE
        if on_modify:
            trigger_type |= CADI.CADI_BPT_TRIGGER_ON_MODIFY

        if trigger_type == 0:
            raise ValueError(
                "At least one of on_read, on_write and on_modify must be True")

        request = CADI.CADIBptRequest(enabled_par=1,
                                      type_par=CADI.CADI_BPT_REGISTER,
                                      regNumber_par=register._info.regNumber,
                                      triggerType_par=trigger_type)

        bpt = Breakpoint(self, self.__cadi, request)
        self.breakpoints[bpt.number] = bpt
        return self.breakpoints[bpt.number]
예제 #12
0
    def __init__(self, host, port, verbose=False):
        """
        Connects to an already initalised model using CADIIPC

        :param host:
            Hostname or IP address of the computer running the model.

        :param port:
            Port number that the model is listening on.

        :param verbose:
            If True, extra debugging information is printed
        """

        self.__host = host
        self.__port = port
        self._loader = CADI.CADIClient()
        self._broker = self._loader.CreateCADIBroker("cadiclient://" + host)

        callbacks_enable = '\001' * CADI.CADI_SIM_CB_Count
        errors = []

        @CADIcallback
        def Error(severity, errorCode, erroneousParameterId, message):
            """
            Error(severity, errorCode, erroneousParameterId, message)
            Recieves error information during instantiation
            """
            errors.append("CADIErrorCallback::Error(severity=%s, error=%s, paramId=%d, message=%s)"
                          % (CADIFACT_SEVERITY2str(severity),
                             CADIFACT_ERROR2str(errorCode),
                             erroneousParameterId,
                             repr(message)))
        
        self._sim_callback = Model.SimulationCallback(self, verbose)
        self._sim_error_callback = PyCADIErrorCallback(Error)
        
        simulation = self._broker.SelectSimulation(port,
                                                   self._sim_error_callback,
                                                   self._sim_callback,
                                                   callbacks_enable)

        if simulation is None:
            raise TargetError("Instantiation failed: " + ", ".join(errors))

        Model.__init__(self, simulation, verbose)
예제 #13
0
 def _get_cadi_value(self):
     return CADI.CADIParameterValue(self.__info.id,
                                    CADI.CADI_PARAM_STRING,
                                    0,
                                    self)
예제 #14
0
 def _get_cadi_value(self):
     intValue = 1 if self.__value == True else 0
     return CADI.CADIParameterValue(self.__info.id,
                                    CADI.CADI_PARAM_BOOL,
                                    intValue,
                                    "")
예제 #15
0
    def write_memory(self,
                     address,
                     data,
                     memory_space=None,
                     size=1,
                     count=None,
                     do_side_effects=False):
        """
        :param address:
            Address to begin reading from

        :param data:
            The data to write.
            If count is 1, this must be an integer
            Otherwise it must be a bytearray with length >= size*count

        :param memory_space:
            memory space to read.
            Default is None which will read the core's current memory space.

        :param size:
            Size of memory access unit in bytes. Must be one of 1, 2, 4 or 8.
            Note that not all values are supported by all models.

        :param count:
            Number of units to write. If None, count is automatically calculated
            such that all data from the array is written to the target

        :param do_side_effects:
            If True, the target must perform any side-effects normally triggered
            by the write, for example triggering an interrupt.
        """

        space = self._get_address_space(memory_space)

        if address < space.minAddress:
            raise ValueError(
                "Address is below minimum address of memory space '%s'" %
                space.memSpaceName)

        if address > space.maxAddress:
            raise ValueError(
                "Address is above maximum address of memory space '%s'" %
                space.memSpaceName)

        if size not in [1, 2, 4, 8]:
            raise ValueError("'size' must be 1, 2, 4 or 8")

        if isinstance(data, Integral):
            data = bytearray([data])

        if count is None:
            count = len(data) / size
            if len(data) % size != 0:
                raise ValueError("len(data) must be a multiple of size")

        if isinstance(data, bytearray) and len(data) < size * count:
            raise ValueError(
                "'data' must be either an integer, or a bytearray with length >= size*count"
            )

        cadi_address = CADI.CADIAddrComplete(
            CADI.CADI_NO_OVERLAY, CADI.CADIAddr(space.memSpaceId, address))

        self.__cadi.CADIMemWrite(cadi_address, count, size, data,
                                 do_side_effects)
예제 #16
0
 def appliInput(self, streamId, count, actualCountp, buf):
     """Semihosting input callback"""
     result = self.stdin.read(count)
     length = len(result)
     buf[0:length] = result
     CADI.uint32p_assign(actualCountp, length)