Пример #1
0
    def queueWrite(self, name, dataU32, addrOffset = 0):
        """Create a register write (RMW-bits) transaction element and add it to the transaction queue.
        
        This works in the same way as a normal write(), except that many can be queued
        into a packet and dispatched all at once rather than individually.  Run the
        queued transactions with queueRun().
        
        Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        if len(self._queuedRequests) < ChipsBus.MAX_QUEUED_REQUESTS:
        
            dataU32 = dataU32 & 0xffffffff # Ignore oversize input.
            chipsLog.debug("Write queued: dataU32 = 0x" + uInt32HexStr(dataU32) + " to register '"
                           + name + "' with addrOffset = 0x" + uInt32HexStr(addrOffset))
        
            addrTableItem = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.
        
            if not addrTableItem.getWriteFlag():
                raise ChipsException("Write transaction creation error: write is not allowed on register '" +  addrTableItem.getName() + "'.")       
        
            self._queuedRequests.append(self._createRMWBitsTransactionElement(addrTableItem, dataU32, addrOffset))
            self._queuedAddrTableItems.append(addrTableItem)
            self._queuedIsARead.append(False)
            
        else:
            chipsLog.warning("Warning: transaction not added to queue as transaction queue has reached its maximum length!\n" +
                             "\tPlease either run or clear the transaction queue before continuing.\n")
Пример #2
0
    def queueWrite(self, name, dataU32, addrOffset = 0):
        """Create a register write (RMW-bits) transaction element and add it to the transaction queue.
        
        This works in the same way as a normal write(), except that many can be queued
        into a packet and dispatched all at once rather than individually.  Run the
        queued transactions with queueRun().
        
        Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        if len(self._transactionQueue) <= 50:
        
            dataU32 = dataU32 & 0xffffffff # Ignore oversize input.
            chipsLog.debug("Write queued: dataU32 = 0x" + uInt32HexStr(dataU32) + " to register '"
                           + name + "' with addrOffset = 0x" + uInt32HexStr(addrOffset))
        
            item = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.
        
            try:
                self._checkRWFlag(item, 0, 1)
            except ChipsException, err:
                raise ChipsException("Write error on register '" + name + "':\n\t" + str(err))
        
            self._transactionQueue.append(self._createRMWBitsTransactionElement(item, dataU32, addrOffset))
            self._transactionItemQueue.append(item)
            self._transactionRWFlagQueue.append(0)
Пример #3
0
    def queueWrite(self, name, dataU32, addrOffset = 0):
        """Create a register write (RMW-bits) transaction element and add it to the transaction queue.

        This works in the same way as a normal write(), except that many can be queued
        into a packet and dispatched all at once rather than individually.  Run the
        queued transactions with queueRun().

        Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        if len(self._queuedRequests) < ChipsBus.MAX_QUEUED_REQUESTS:

            dataU32 = dataU32 & 0xffffffff # Ignore oversize input.
            chipsLog.debug("Write queued: dataU32 = 0x" + uInt32HexStr(dataU32) + " to register '"
                           + name + "' with addrOffset = 0x" + uInt32HexStr(addrOffset))

            addrTableItem = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.

            if not addrTableItem.getWriteFlag():
                raise ChipsException("Write transaction creation error: write is not allowed on register '" +  addrTableItem.getName() + "'.")

            # self._queuedRequests.append(self._createRMWBitsTransactionElement(addrTableItem, dataU32, addrOffset))
            # self._queuedAddrTableItems.append(addrTableItem)
            # self._queuedIsARead.append(False)

            self._queuedRequests.append(self._createWriteTransactionElement(addrTableItem, [dataU32], addrOffset))
            self._queuedAddrTableItems.append(addrTableItem)
            self._queuedIsARead.append(False)

        else:
            chipsLog.warning("Warning: transaction not added to queue as transaction queue has reached its maximum length!\n" +
                             "\tPlease either run or clear the transaction queue before continuing.\n")
Пример #4
0
    def doTransactionChecks(self):
        """Performs a generic set of transaction checks on all transaction elements in the request/response lists"""

        if len(self.requests) != len(self.responses):
            raise ChipsException("Transaction error: incorrect number of responses returned!")

        for iElement in range(len(self.requests)):
            request = self.requests[iElement]
            response = self.responses[iElement]
            if getTransactionId(request.getHeader()) != getTransactionId(response.getHeader()):
                raise ChipsException("Transaction error: request and response transaction IDs do not match; " \
                                     "expected '" + str(getTransactionId(request.getHeader())) + "' but got '" \
                                     + str(getTransactionId(response.getHeader())) + "'!")
            if getTypeId(request.getHeader()) != getTypeId(response.getHeader()):
                raise ChipsException("Transaction error: request and response transaction types do not match; " \
                                     "expected '" + hex(getTypeId(request.getHeader())) + "' but got '" \
                                     + hex(getTypeId(response.getHeader())) + "'!")
            if getDirection(response.getHeader()) != 1:
                raise ChipsException("Transaction error: erroneous response direction bit detected for " \
                                     "transaction number " + getTransactionId(response.getHeader()) + 
                                     " (header=0x" + uInt32HexStr(response.getHeader()) + ")!")
            if not response.validBodySize():
                raise ChipsException("Transaction error: incorrect response body size for " \
                                     "transaction number " + getTransactionId(response.getHeader()) + 
                                     " (header=0x" + uInt32HexStr(response.getHeader()) + ")!")
            if getResultCode(response.getHeader()):
                raise ChipsException("Transaction error: non-zero result code returned for " \
                                     "transaction number " + getTransactionId(response.getHeader()) + 
                                     " (header=0x" + uInt32HexStr(response.getHeader()) + ")!")
Пример #5
0
    def _handleReadRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        baseAddr = request.getBody()[0]
        chipsLog.debug("Read requested on Addr=0x" + uInt32HexStr(baseAddr))

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            requestHeader, IPbusHeader.INFO_CODE_RESPONSE)

        # The (baseAddr & 0xffffffff) forces baseAddr to be in unsigned form (i.e. 0xfffffffc, say, rather than -4)
        if (
                baseAddr & 0xffffffff
        ) == 0xffffffff:  # A read on this register is a Dummy Hardware Reset Request.
            chipsLog.info(
                "** Dummy Hardware reset request received! Zeroing all registers. **"
            )
            self._registers.clear()

        responseBody = []
        appendToResponseBody = responseBody.append  # This is for a speed optimisation

        for offset in range(words):
            currentReg = baseAddr + offset
            # Create these registers if they don't already exist.
            if currentReg not in self._registers:
                self._registers[currentReg] = 0
            appendToResponseBody(self._registers[currentReg])
        return TransactionElement.makeFromHeaderAndBody(
            responseHeader, responseBody)
Пример #6
0
def getExpectedBodySize(rawHeaderU32):
    '''Calculates the expected body size of an IPbus TransactionElement from the raw 32-bit header word'''

    result = 0
    typeId = getTypeId(rawHeaderU32)

    # Test if it's a known request/response typeId (doesn't matter which bodySize map we use)
    if typeId in _minimumResponseBodySize:

        # response from target to controller
        if getInfoCode(rawHeaderU32) == INFO_CODE_RESPONSE:
            if typeId == TYPE_ID_READ or typeId == TYPE_ID_NON_INCR_READ:
                result = getWords(
                    rawHeaderU32) + _minimumResponseBodySize[typeId]
            else:
                result = _minimumResponseBodySize[typeId]

        # request from controller to target
        else:
            if typeId == TYPE_ID_WRITE or typeId == TYPE_ID_NON_INCR_WRITE:
                result = getWords(
                    rawHeaderU32) + _minimumRequestBodySize[typeId]
            else:
                result = _minimumRequestBodySize[typeId]

    # Unknown transaction typeId.
    else:
        raise ChipsException(
            "Cannot determine the expected body size from the given IPbus header '0x"
            + uInt32HexStr(rawHeaderU32) +
            "', as it is of unknown transaction type '" + hex(typeId) + "'!")

    return result
Пример #7
0
    def _blockOrFifoRead(self, name, depth, addrOffset, isFifo = False):
        """Common code for either a block read or a FIFO read."""

        if depth <= 0:
            chipsLog.warn("Ignoring read with depth = 0 from register '" + name + "'!")
            return

        if depth > ChipsBus.MAX_BLOCK_TRANSFER_DEPTH:
            return self._oversizeBlockOrFifoRead(name, depth, addrOffset, isFifo)

        addrTableItem = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.

        if addrTableItem.getMask() != 0xffffffff:
            raise ChipsException("Block/FIFO read error: cannot perform block or FIFO read on a masked register address!")

        try:
            if not addrTableItem.getReadFlag(): raise ChipsException("Read transaction creation error: read is not allowed on register '" + addrTableItem.getName() + "'.")
            # create and run the transaction and get the response
            transaction = self._makeAndRunTransaction( [self._createReadTransactionElement(addrTableItem, depth, addrOffset, isFifo)] )
        except ChipsException as err:
            raise ChipsException("Block/FIFO read error on register '" + name + "':\n\t" + str(err))

        blockReadResponse = transaction.responses[-1] # Block read response will be last in list

        chipsLog.debug("Block/FIFO read success! Register '" + name + "' (addrOffset=0x"
                       + uInt32HexStr(addrOffset) + ") was read successfully." )

        return blockReadResponse.getBody().tolist()
Пример #8
0
    def _blockOrFifoWrite(self, name, dataList, addrOffset, isFifo = False):
        """Common code for either a block write or a FIFO write."""

        depth = len(dataList)

        addrTableItem = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.

        if addrTableItem.getMask() != 0xffffffff:
            raise ChipsException("Block/FIFO write error: cannot perform block or FIFO write on a masked register address!")

        if depth == 0:
            chipsLog.warn("Ignoring block/FIFO write to register '" + name + "': dataList is empty!");
            return
        elif depth > ChipsBus.MAX_BLOCK_TRANSFER_DEPTH:
            return self._oversizeBlockOrFifoWrite(name, dataList, addrOffset, isFifo)

        try:
            if not addrTableItem.getWriteFlag(): raise ChipsException("Write transaction creation error: write is not allowed on register '" +  addrTableItem.getName() + "'.")
            # create and run the transaction and get the response
            self._makeAndRunTransaction( [self._createWriteTransactionElement(addrTableItem, dataList, addrOffset, isFifo)] )
        except ChipsException as err:
            raise ChipsException("Block/FIFO write error on register '" + name + "':\n\t" + str(err))

        chipsLog.debug("Block/FIFO write success! " + str(depth) + " 32-bit words were written to '"
                        + name + "' (addrOffset=0x" + uInt32HexStr(addrOffset) + ")")
Пример #9
0
    def _handleWriteRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        requestBody = request.getBody()
        baseAddr = requestBody[0]
        chipsLog.debug("Write requested on Addr=0x" + uInt32HexStr(baseAddr))

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(requestHeader, IPbusHeader.INFO_CODE_RESPONSE)

        for offset in range(words):
            currentReg = baseAddr + offset  
            self._registers[currentReg] = requestBody[offset + 1]
        return TransactionElement.makeFromHeaderAndBody(responseHeader)
Пример #10
0
    def _handleWriteRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        requestBody = request.getBody()
        baseAddr = requestBody[0]
        chipsLog.debug("Write requested on Addr=0x" + uInt32HexStr(baseAddr))

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(requestHeader, 1)

        for offset in range(words):
            currentReg = baseAddr + offset  
            self._registers[currentReg] = requestBody[offset + 1]
        return TransactionElement.makeFromHeaderAndBody(responseHeader)
Пример #11
0
 def deserialise(self, packetPayloadString):
     '''Deserialises a packet payload ASCII string into list of transaction elements'''
 
     # 1) Unpack the string into unsigned integers
     try:
         rawU32Array = array('I', packetPayloadString)  # Unpack string to an unsigned 32-bit array
     except Exception as err:
         raise ChipsException("Deserialisation error:\n\t" + str(err))
 
     # 2) Debug output of the raw packet
     if chipsLog.level <= logging.DEBUG:
         msg = "\nRaw received packet content is:\n"
         for u32 in rawU32Array: msg += "  0x" + uInt32HexStr(u32) + "\n"
         chipsLog.debug(msg)
 
     # 3) Detect if we need to do a byte-reorder
     firstWord = rawU32Array[0]
     firstWordMasked = firstWord & 0xf00000f0  # This selects only the bits relevant for detecting the byte ordering
     if firstWordMasked == 0x200000f0:
         chipsLog.debug("Packet header detected: no byte-reorder is required.")
     elif firstWordMasked == 0xf0000020:
         chipsLog.debug("Packet header detected: a byte-reorder will be performed.")
         self._doByteReorder = True
     else:
         chipsLog.warn("Warning: No packet header (or unknown protocol version)! First word = 0x" + uInt32HexStr(firstWord) + ". Will hope for the best!...")
     
     # 4) Do the byte-reorder if necessary
     if self._doByteReorder:  rawU32Array.byteswap()
    
     # 5) Now deserialise into a list of TransactionElements
     transactionElementList = []  # The list all the deserialised transaction elements will go into
     appendToTransactionElementList = transactionElementList.append  # This is needed for a speed optimisation
     iU32 = 1  # Index for moving through the rawU32Array          # TEMPORARY IPBUS V2.x HACK! Skip the first word which is now a packet ID
     rawU32ArraySize = len(rawU32Array)
     while iU32 < rawU32ArraySize:
         expectedBodySize = getExpectedBodySize(rawU32Array[iU32])
         if rawU32ArraySize - iU32 - 1 - expectedBodySize < 0:
             raise ChipsException("Deserialisation error: packet not correctly formatted " \
                                  "or does not contain the expected amount of data!")
         appendToTransactionElementList(TransactionElement(rawU32Array[iU32: iU32 + 1 + expectedBodySize]))
         iU32 += (1 + expectedBodySize)
     
     # 6) Debug output of deserialised packet content
     if chipsLog.level <= logging.DEBUG:
         msg = "\nDeserialised packet content is:\n" \
               + reprTransactionElementList(transactionElementList)
         chipsLog.debug(msg)
         
     return transactionElementList
Пример #12
0
    def _handleFifoWriteRequest(self, request):
        requestHeader = request.getHeader()
        requestBody = request.getBody()
        fifoAddr = requestBody[0]
        chipsLog.debug("FIFO write requested on Addr=0x" + uInt32HexStr(fifoAddr))

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(requestHeader, 1)

        # Obviously we don't really have a FIFO, we just have a single register at the address of the supposed
        # FIFO.  So, whatever the last value written into the FIFO is, this will be the value this register will
        # take.  We ignore all the previous "writes" to the FIFO.
        self._registers[fifoAddr] = requestBody[-1]

        return TransactionElement.makeFromHeaderAndBody(responseHeader)
Пример #13
0
    def _handleWriteRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        requestBody = request.getBody()
        baseAddr = requestBody[0]
        chipsLog.debug("Write requested on Addr=0x" + uInt32HexStr(baseAddr))

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            requestHeader, IPbusHeader.INFO_CODE_RESPONSE)

        for offset in range(words):
            currentReg = baseAddr + offset
            self._registers[currentReg] = requestBody[offset + 1]
        return TransactionElement.makeFromHeaderAndBody(responseHeader)
Пример #14
0
    def _handleReadModifyWriteSumRequest(self, request):
        requestBody = request.getBody()
        addr = requestBody[0]
        addend = requestBody[1]  # The value we add to the existing value
        chipsLog.debug("Read/Modify/Write-sum requested on Addr=0x" + uInt32HexStr(addr))
        
        # Create the register if it doesn't already exist.
        if addr not in self._registers: self._registers[addr] = 0
        
        updatedValue = (self._registers[addr] + addend) & 0xffffffff
        self._registers[addr] = updatedValue

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(request.getHeader(), 1)

        return TransactionElement.makeFromHeaderAndBody(responseHeader, [updatedValue])
Пример #15
0
    def _handleFifoWriteRequest(self, request):
        requestHeader = request.getHeader()
        requestBody = request.getBody()
        fifoAddr = requestBody[0]
        chipsLog.debug("FIFO write requested on Addr=0x" +
                       uInt32HexStr(fifoAddr))

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            requestHeader, IPbusHeader.INFO_CODE_RESPONSE)

        # Obviously we don't really have a FIFO, we just have a single register at the address of the supposed
        # FIFO.  So, whatever the last value written into the FIFO is, this will be the value this register will
        # take.  We ignore all the previous "writes" to the FIFO.
        self._registers[fifoAddr] = requestBody[-1]

        return TransactionElement.makeFromHeaderAndBody(responseHeader)
Пример #16
0
    def _handleReadModifyWriteBitsRequest(self, request):
        requestBody = request.getBody()
        addr = requestBody[0]
        andTerm = requestBody[1]  # The and term is the bitwise complement of the register mask (i.e. mask = ~andTerm)
        orTerm = requestBody[2]
        chipsLog.debug("Read/Modify/Write-bits requested on Addr=0x" + uInt32HexStr(addr))
        
        # Create the register if it doesn't already exist.
        if addr not in self._registers: self._registers[addr] = 0
        
        updatedValue = (self._registers[addr] & andTerm) | (orTerm)
        self._registers[addr] = updatedValue

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(request.getHeader(), 1)

        return TransactionElement.makeFromHeaderAndBody(responseHeader, [updatedValue])
Пример #17
0
    def blockRead(self, name, depth=1, addrOffset=0):
        """Block read (not for masked registers!).  Returns a list of the read results (32-bit numbers).
        
        The blockRead() transaction runs straight away - it cannot be queued.

        name: the register name of the register you want to read from.
        depth: the number of 32-bit reads deep you want to go from the start address.
            (i.e. depth=3 will return a list with three 32-bit values). 
        addrOffset: optional - provide a 32-bit word offset if you wish.
        
        Notes: Use the depth and addrOffset at your own risk!  No checking is done to
            see if these values are remotely sensible!
        """

        chipsLog.debug("Block read requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(depth))

        return self._blockOrFifoRead(name, depth, addrOffset, False)
Пример #18
0
    def blockRead(self, name, depth=1, addrOffset=0):
        """Block read (not for masked registers!).  Returns a list of the read results (32-bit numbers).

        The blockRead() transaction runs straight away - it cannot be queued.

        name: the register name of the register you want to read from.
        depth: the number of 32-bit reads deep you want to go from the start address.
            (i.e. depth=3 will return a list with three 32-bit values).
        addrOffset: optional - provide a 32-bit word offset if you wish.

        Notes: Use the depth and addrOffset at your own risk!  No checking is done to
            see if these values are remotely sensible!
        """

        chipsLog.debug("Block read requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(depth))

        return self._blockOrFifoRead(name, depth, addrOffset, False)
Пример #19
0
    def _handleFifoReadRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        fifoAddr = request.getBody()[0]
        chipsLog.debug("FIFO read requested on Addr=0x" + uInt32HexStr(fifoAddr))

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(requestHeader, 1)

        # Create the register if they don't already exist in our memory space
        if fifoAddr not in self._registers:
            self._registers[fifoAddr] = 0

        # Obviously we don't really have a FIFO, so we'll just have to return the value stored
        # at the FIFO's address many times...
        value = self._registers[fifoAddr]
        responseBody = [value for iReads in range(words)]
        return TransactionElement.makeFromHeaderAndBody(responseHeader, responseBody)
Пример #20
0
    def _handleReadModifyWriteSumRequest(self, request):
        requestBody = request.getBody()
        addr = requestBody[0]
        addend = requestBody[1]  # The value we add to the existing value
        chipsLog.debug("Read/Modify/Write-sum requested on Addr=0x" +
                       uInt32HexStr(addr))

        # Create the register if it doesn't already exist.
        if addr not in self._registers: self._registers[addr] = 0

        updatedValue = (self._registers[addr] + addend) & 0xffffffff
        self._registers[addr] = updatedValue

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            request.getHeader(), IPbusHeader.INFO_CODE_RESPONSE)

        return TransactionElement.makeFromHeaderAndBody(
            responseHeader, [updatedValue])
Пример #21
0
    def blockWrite(self, name, dataList, addrOffset=0):
        """Block write (not for masked registers!).
        
        The blockWrite() transaction runs straight away - it cannot be queued.

        name: the register name of the register you want to read from.
        dataList: the list of 32-bit values you want writing.  The size of the list
            determines how deep the block write goes.  
        addrOffset: optional - provide a 32-bit word offset if you wish.
        
        Notes:  Use this at your own risk!  No checking is currently done to see if
            you will be stomping on any other registers if the dataList or addrOffset
            is inappropriate in size!
        """

        chipsLog.debug("Block write requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(len(dataList)))

        return self._blockOrFifoWrite(name, dataList, addrOffset, False)
Пример #22
0
    def blockWrite(self, name, dataList, addrOffset=0):
        """Block write (not for masked registers!).

        The blockWrite() transaction runs straight away - it cannot be queued.

        name: the register name of the register you want to read from.
        dataList: the list of 32-bit values you want writing.  The size of the list
            determines how deep the block write goes.
        addrOffset: optional - provide a 32-bit word offset if you wish.

        Notes:  Use this at your own risk!  No checking is currently done to see if
            you will be stomping on any other registers if the dataList or addrOffset
            is inappropriate in size!
        """

        chipsLog.debug("Block write requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(len(dataList)))

        return self._blockOrFifoWrite(name, dataList, addrOffset, False)
Пример #23
0
    def fifoRead(self, name, depth=1, addrOffset=0):
        """Non-incrementing block read (not for masked registers!). Returns list of the read results.
        
        Reads from the same address the number of times specified by depth

        The fifoRead() transaction runs straight away - it cannot be queued.
        
        name: the register name of the register you want to read from.
        depth: the number of 32-bit reads you want to perform on the FIFO
            (i.e. depth=3 will return a list with three 32-bit values). 
        addrOffset: optional - provide a 32-bit word offset if you wish.
        
        Notes: Use the depth and addrOffset at your own risk!  No checking is done to
            see if these values are remotely sensible!
        """        

        chipsLog.debug("FIFO read (non-incrementing block read) requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(depth))

        return self._blockOrFifoRead(name, depth, addrOffset, True)
Пример #24
0
    def fifoRead(self, name, depth=1, addrOffset=0):
        """Non-incrementing block read (not for masked registers!). Returns list of the read results.

        Reads from the same address the number of times specified by depth

        The fifoRead() transaction runs straight away - it cannot be queued.

        name: the register name of the register you want to read from.
        depth: the number of 32-bit reads you want to perform on the FIFO
            (i.e. depth=3 will return a list with three 32-bit values).
        addrOffset: optional - provide a 32-bit word offset if you wish.

        Notes: Use the depth and addrOffset at your own risk!  No checking is done to
            see if these values are remotely sensible!
        """

        chipsLog.debug("FIFO read (non-incrementing block read) requested: register '" + name + "' with addrOffset = 0x"
                       + uInt32HexStr(addrOffset) + " and depth = " + str(depth))

        return self._blockOrFifoRead(name, depth, addrOffset, True)
Пример #25
0
    def _handleReadModifyWriteBitsRequest(self, request):
        requestBody = request.getBody()
        addr = requestBody[0]
        andTerm = requestBody[
            1]  # The and term is the bitwise complement of the register mask (i.e. mask = ~andTerm)
        orTerm = requestBody[2]
        chipsLog.debug("Read/Modify/Write-bits requested on Addr=0x" +
                       uInt32HexStr(addr))

        # Create the register if it doesn't already exist.
        if addr not in self._registers: self._registers[addr] = 0

        updatedValue = (self._registers[addr] & andTerm) | (orTerm)
        self._registers[addr] = updatedValue

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            request.getHeader(), IPbusHeader.INFO_CODE_RESPONSE)

        return TransactionElement.makeFromHeaderAndBody(
            responseHeader, [updatedValue])
Пример #26
0
    def _handleFifoReadRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        fifoAddr = request.getBody()[0]
        chipsLog.debug("FIFO read requested on Addr=0x" +
                       uInt32HexStr(fifoAddr))

        # Response header is the request header but with the Info Code field changed to INFO_CODE_RESPONSE
        responseHeader = IPbusHeader.updateInfoCode(
            requestHeader, IPbusHeader.INFO_CODE_RESPONSE)

        # Create the register if they don't already exist in our memory space
        if fifoAddr not in self._registers:
            self._registers[fifoAddr] = 0

        # Obviously we don't really have a FIFO, so we'll just have to return the value stored
        # at the FIFO's address many times...
        value = self._registers[fifoAddr]
        responseBody = [value for iReads in range(words)]
        return TransactionElement.makeFromHeaderAndBody(
            responseHeader, responseBody)
Пример #27
0
    def _handleReadRequest(self, request):
        requestHeader = request.getHeader()
        words = IPbusHeader.getWords(requestHeader)
        baseAddr = request.getBody()[0]
        chipsLog.debug("Read requested on Addr=0x" + uInt32HexStr(baseAddr))

        # Response header is the request header with direction bit changed
        responseHeader = IPbusHeader.updateDirection(requestHeader, 1)

        # The (baseAddr & 0xffffffff) forces baseAddr to be in unsigned form (i.e. 0xfffffffc, say, rather than -4)
        if (baseAddr & 0xffffffff) == 0xffffffff:  # A read on this register is a Dummy Hardware Reset Request.
            chipsLog.info("** Dummy Hardware reset request received! Zeroing all registers. **")
            self._registers.clear()
        
        responseBody = []
        appendToResponseBody = responseBody.append  # This is for a speed optimisation  
        
        for offset in range(words):
            currentReg = baseAddr + offset  
            # Create these registers if they don't already exist.
            if currentReg not in self._registers:
                self._registers[currentReg] = 0
            appendToResponseBody(self._registers[currentReg])
        return TransactionElement.makeFromHeaderAndBody(responseHeader, responseBody)
Пример #28
0
        addrTableItem = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.
       
        if addrTableItem.getMask() != 0xffffffff:
            raise ChipsException("Block/FIFO read error: cannot perform block or FIFO read on a masked register address!")

        try:
            if not addrTableItem.getReadFlag(): raise ChipsException("Read transaction creation error: read is not allowed on register '" + addrTableItem.getName() + "'.")
            # create and run the transaction and get the response
            transaction = self._makeAndRunTransaction( [self._createReadTransactionElement(addrTableItem, depth, addrOffset, isFifo)] )
        except ChipsException, err:
            raise ChipsException("Block/FIFO read error on register '" + name + "':\n\t" + str(err))

        blockReadResponse = transaction.responses[-1] # Block read response will be last in list

        chipsLog.debug("Block/FIFO read success! Register '" + name + "' (addrOffset=0x"
                       + uInt32HexStr(addrOffset) + ") was read successfully." )

        return blockReadResponse.getBody().tolist()

    
    def _oversizeBlockOrFifoRead(self, name, depth, addrOffset, isFifo):
        """Handles a block or FIFO read that's too big to be handled by a single UDP packet"""
        
        chipsLog.debug("Read depth too large for single packet... will automatically split read over many packets")
        
        remainingTransactions = depth
        result =[]
        
        offsetMultiplier = 1
        if isFifo: offsetMultiplier = 0
        
Пример #29
0
 def queueRead(self, name, addrOffset = 0):
     """Create a read transaction element and add it to the transaction queue.
     
     This works in the same way as a normal read(), except that many can be queued
     into a packet and dispatched all at once rather than individually.  Run the
     queued transactions with queueRun().
     
     Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
     be queued.
     """
     
     if len(self._transactionQueue) <= 50:
     
         chipsLog.debug("Read queued: register '" + name + "' with addrOffset = 0x" + uInt32HexStr(addrOffset))
     
         item = self.addrTable.getItem(name) # Get the details of the relevant item from the addr table.
     
         try:
             self._checkRWFlag(item)
         except ChipsException, err:
             raise ChipsException("Read error on register '" + name + "':\n\t" + str(err))
     
         self._transactionQueue.append(self._createReadTransactionElement(item, 1, addrOffset))
         self._transactionItemQueue.append(item)
         self._transactionRWFlagQueue.append(1)
Пример #30
0
                    "Read transaction creation error: read is not allowed on register '"
                    + addrTableItem.getName() + "'.")
            # create and run the transaction and get the response
            transaction = self._makeAndRunTransaction([
                self._createReadTransactionElement(addrTableItem, depth,
                                                   addrOffset, isFifo)
            ])
        except ChipsException, err:
            raise ChipsException("Block/FIFO read error on register '" + name +
                                 "':\n\t" + str(err))

        blockReadResponse = transaction.responses[
            -1]  # Block read response will be last in list

        chipsLog.debug("Block/FIFO read success! Register '" + name +
                       "' (addrOffset=0x" + uInt32HexStr(addrOffset) +
                       ") was read successfully.")

        return blockReadResponse.getBody().tolist()

    def _oversizeBlockOrFifoRead(self, name, depth, addrOffset, isFifo):
        """Handles a block or FIFO read that's too big to be handled by a single UDP packet"""

        chipsLog.debug(
            "Read depth too large for single packet... will automatically split read over many packets"
        )

        remainingTransactions = depth
        result = []

        offsetMultiplier = 1
Пример #31
0
class ChipsBusBase(object):
    """Common Hardware Interface Protocol System Bus (CHIPS-Bus) abstract base-class

    Allows you to communicate with and control devices running Jeremy Mans's, et al, IP-based
    uTCA control system firmware.  This base class represents the part of the ChipsBus code
    that is protocol-agnostic.  Protocol-specific concrete classes, using either UDP or TCP,
    derive from this.

    The bus assumes 32-bit word addressing, so in a 32-bit address space up to 2^34 bytes in
    total can be addressed.
    """

    IPBUS_PROTOCOL_VER = 2  # I.e. IPbus Protocol v1.4
    SOCKET_BUFFER_SIZE = 32768  # Max UDP/TCP socket buffer size in bytes for receiving packets.
    MAX_TRANSACTION_ID = 4095  # The maximum value the transaction ID field can go up to.

    # Max depth of a block read or write before bridging the read/write over multiple requests.
    # Note that for UDP the max IPBus packet size cannot exceed 368 32-bit words (1472 bytes), or
    # it'll fail due to reaching the max Ethernet packet payload size (without using Jumbo Frames).
    # If you are Jumbo-Frames capable, then this number should not exceed 2000. Note that the
    # jumbo-frames firmware uses a 8192-byte buffer, so we can't make use of the full 9000 byte
    # Jumbo Frame anyway.
    MAX_BLOCK_TRANSFER_DEPTH = 255  # Temporary hack to get IPbus v2.0 compatible code working

    # The max size of the request queue (note: current API excludes ability to queue block transfer requests)
    MAX_QUEUED_REQUESTS = 80

    def __init__(self, addrTable, hostIp, hostPort, localPort=None):
        """ChipsBus abstract base-class constructor

        addrTable:  An instance of AddressTable for the device you wish to communicate with.
        hostIP:  The IP address of the device you want to control, e.g. the string '192.168.1.100'.
        hostPort:  The network port number of the device you want to control.
        localPort:  If you wish to bind the socket to a particular local port, then specify the
            the local port number here.  The default (None) means that the socket will not bind
            to any specific local port - an available port be found when it comes to sending any
            packets.
        """
        object.__init__(self)
        self._transactionId = 1
        self.addrTable = addrTable
        self._hostAddr = (hostIp, hostPort)
        self._queuedRequests = []  # Request queue
        self._queuedAddrTableItems = [
        ]  # The corresponding address table item for each request in the request queue
        self._queuedIsARead = [
        ]  # This holds a True if the corresponding request in _queuedRequests is a read, or a False if it's a write.

    def queueRead(self, name, addrOffset=0):
        """Create a read transaction element and add it to the transaction queue.

        This works in the same way as a normal read(), except that many can be queued
        into a packet and dispatched all at once rather than individually.  Run the
        queued transactions with queueRun().

        Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        if len(self._queuedRequests) < ChipsBus.MAX_QUEUED_REQUESTS:

            chipsLog.debug("Read queued: register '" + name +
                           "' with addrOffset = 0x" + uInt32HexStr(addrOffset))

            addrTableItem = self.addrTable.getItem(
                name
            )  # Get the details of the relevant item from the addr table.

            if not addrTableItem.getReadFlag():
                raise ChipsException(
                    "Read transaction creation error: read is not allowed on register '"
                    + addrTableItem.getName() + "'.")

            self._queuedRequests.append(
                self._createReadTransactionElement(addrTableItem, 1,
                                                   addrOffset))
            self._queuedAddrTableItems.append(addrTableItem)
            self._queuedIsARead.append(True)

        else:
            chipsLog.warning(
                "Warning: transaction not added to queue as transaction queue has reached its maximum length!\n"
                +
                "\tPlease either run or clear the transaction queue before continuing.\n"
            )

    def queueWrite(self, name, dataU32, addrOffset=0):
        """Create a register write (RMW-bits) transaction element and add it to the transaction queue.

        This works in the same way as a normal write(), except that many can be queued
        into a packet and dispatched all at once rather than individually.  Run the
        queued transactions with queueRun().

        Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        if len(self._queuedRequests) < ChipsBus.MAX_QUEUED_REQUESTS:

            dataU32 = dataU32 & 0xffffffff  # Ignore oversize input.
            chipsLog.debug("Write queued: dataU32 = 0x" +
                           uInt32HexStr(dataU32) + " to register '" + name +
                           "' with addrOffset = 0x" + uInt32HexStr(addrOffset))

            addrTableItem = self.addrTable.getItem(
                name
            )  # Get the details of the relevant item from the addr table.

            if not addrTableItem.getWriteFlag():
                raise ChipsException(
                    "Write transaction creation error: write is not allowed on register '"
                    + addrTableItem.getName() + "'.")

            # self._queuedRequests.append(self._createRMWBitsTransactionElement(addrTableItem, dataU32, addrOffset))
            # self._queuedAddrTableItems.append(addrTableItem)
            # self._queuedIsARead.append(False)

            self._queuedRequests.append(
                self._createWriteTransactionElement(addrTableItem, [dataU32],
                                                    addrOffset))
            self._queuedAddrTableItems.append(addrTableItem)
            self._queuedIsARead.append(False)

        else:
            chipsLog.warning(
                "Warning: transaction not added to queue as transaction queue has reached its maximum length!\n"
                +
                "\tPlease either run or clear the transaction queue before continuing.\n"
            )

    def queueRun(self):
        """Runs the current queue of single register read or write transactions and returns two lists. The
        first contains the values read and the second contains the values written.

        Note: Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        chipsLog.debug("Running all queued transactions")

        requestQueueLength = len(self._queuedRequests)

        readResponse = []
        writeResponse = []

        try:
            transaction = self._makeAndRunTransaction(self._queuedRequests)
        except ChipsException, err:
            self.queueClear()
            raise ChipsException(
                "Error while running queued transactions:\n\t" + str(err))

        for i in range(requestQueueLength):
            addrTableItem = self._queuedAddrTableItems[i]

            if len(transaction.responses[0].getBody()) > 0:
                transactionResponse = transaction.responses[
                    i - requestQueueLength].getBody()[0] & 0xffffffff
                transactionResponse = addrTableItem.shiftDataFromMask(
                    transactionResponse)
            else:
                transactionResponse = 0

            if self._queuedIsARead[i]:
                readResponse.append(transactionResponse)
                chipsLog.debug("Read success! Register '" +
                               addrTableItem.getName() + "' returned: 0x" +
                               uInt32HexStr(transactionResponse))
            else:
                writeResponse.append(transactionResponse)
                chipsLog.debug("Write success! Register '" +
                               addrTableItem.getName() + "' assigned: 0x" +
                               uInt32HexStr(transactionResponse))

        self.queueClear()

        response = [readResponse, writeResponse]

        return response
Пример #32
0
    def doTransactionChecks(self):
        """Performs a generic set of client transaction checks on all transaction elements in the request/response lists"""

        if len(self.requests) != len(self.responses):
            raise ChipsException(
                "Transaction error: incorrect number of responses returned!")

        for iElement in range(len(self.requests)):

            request = self.requests[iElement]
            response = self.responses[iElement]
            requestHeader = request.getHeader()
            responseHeader = response.getHeader()

            if getTypeId(requestHeader) != getTypeId(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "request and response transaction types do not match; expected '" + hex(getTypeId(requestHeader)) +
                                     "' but got '" + hex(getTypeId(responseHeader)) + "'!")

            if getTransactionId(requestHeader) != getTransactionId(
                    responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "request and response transactions IDs do not match; expected '" + str(getTransactionId(requestHeader)) +
                                     "' but got '" + str(getTransactionId(responseHeader)) + "'!")

            if isRequestHeader(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "the received response for transaction ID " + str(getTransactionId(responseHeader)) + " has an INFO CODE " \
                                     "that declares it as a request!")

            if isResponseErrorHeader(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "the host reports the following error occurred (INFO CODE = " + hex(getInfoCode(responseHeader)) +
                                     ") whilst processing transaction ID " + str(getTransactionId(responseHeader)) + ": '" +
                                     interpretInfoCode(getInfoCode(responseHeader)) + "'!")

            if not response.validBodySize():
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "incorrect response body size for transaction number " + str(getTransactionId(responseHeader)) + "!")
Пример #33
0
 def __repr__(self):
     '''For representing the object in string form'''
     resultString = "  0x" + uInt32HexStr(self.getHeader()) + "\tHeader\n"
     for index, u32 in enumerate(self.getBody()):
         resultString += "  0x" + uInt32HexStr(u32) + "\tBody " + str(index) + "\n"
     return resultString
Пример #34
0
def getExpectedBodySize(rawHeaderU32):
    '''Calculates the expected body size of an IPbus TransactionElement from the raw 32-bit header word'''

    result = 0
    typeId = getTypeId(rawHeaderU32)

    # Test if it's a known request/response typeId (doesn't matter which bodySize map we use)
    if typeId in _minimumResponseBodySize:

        # response from target to controller
        if getInfoCode(rawHeaderU32) == INFO_CODE_RESPONSE:
            if typeId == TYPE_ID_READ or typeId == TYPE_ID_NON_INCR_READ:
                result = getWords(rawHeaderU32) + _minimumResponseBodySize[typeId]
            else: result = _minimumResponseBodySize[typeId]

        # request from controller to target
        else:
            if typeId == TYPE_ID_WRITE or typeId == TYPE_ID_NON_INCR_WRITE:
                result = getWords(rawHeaderU32) + _minimumRequestBodySize[typeId]
            else: result = _minimumRequestBodySize[typeId]

    # Unknown transaction typeId.
    else:
        raise ChipsException("Cannot determine the expected body size from the given IPbus header '0x" + uInt32HexStr(rawHeaderU32) +
                             "', as it is of unknown transaction type '" + hex(typeId) + "'!")

    return result
Пример #35
0
class SerDes(object):
    '''Class for serialising/deserialising IPbus transaction data
    
    Can serialise a list of TransactionElements into a string, or deserialise
    a string into a list of TransactionElements.  The deserialisation stage
    checks the byte-ordering by looking for a byte-order header, and deals
    with the byte-reordering as appropriate.  If a byte-reorder was required
    on the deserialisation stage, then the serialisation stage will also
    perform a reorder in order to respond correctly.
    
    Byte-reordering is off by default, as it's obviously a waste of CPU.
    '''
    def __init__(self):
        '''Constructor - no arguments'''
        object.__init__(self)
        self._doByteReorder = False

    def serialise(self, transactionElementList):
        '''Serialises a list of transaction elements into an ASCII string for transmission'''

        if chipsLog.level <= logging.DEBUG:
            msg = "\nSerialising the following packet content:\n"
            msg += reprTransactionElementList(transactionElementList)
            chipsLog.debug(msg)

        allTransactionsArray = array(
            'I', [0x200000f0]
        )  # TEMPORARY IPBUS V2.x HACK!   Add a packet header of [0x200000f0] to the beginning of each packet.
        extendFunc = allTransactionsArray.extend
        for element in transactionElementList:
            extendFunc(element.getAll())
        if self._doByteReorder: allTransactionsArray.byteswap()
        return allTransactionsArray.tostring()

    def deserialise(self, packetPayloadString):
        '''Deserialises a packet payload ASCII string into list of transaction elements'''

        # 1) Unpack the string into unsigned integers
        try:
            rawU32Array = array('I', packetPayloadString
                                )  # Unpack string to an unsigned 32-bit array
        except Exception, err:
            raise ChipsException("Deserialisation error:\n\t" + str(err))

        # 2) Debug output of the raw packet
        if chipsLog.level <= logging.DEBUG:
            msg = "\nRaw received packet content is:\n"
            for u32 in rawU32Array:
                msg += "  0x" + uInt32HexStr(u32) + "\n"
            chipsLog.debug(msg)

        # 3) Detect if we need to do a byte-reorder
        firstWord = rawU32Array[0]
        firstWordMasked = firstWord & 0xf00000f0  # This selects only the bits relevant for detecting the byte ordering
        if firstWordMasked == 0x200000f0:
            chipsLog.debug(
                "Packet header detected: no byte-reorder is required.")
        elif firstWordMasked == 0xf0000020:
            chipsLog.debug(
                "Packet header detected: a byte-reorder will be performed.")
            self._doByteReorder = True
        else:
            chipsLog.warn(
                "Warning: No packet header (or unknown protocol version)! First word = 0x"
                + uInt32HexStr(firstWord) + ". Will hope for the best!...")

        # 4) Do the byte-reorder if necessary
        if self._doByteReorder: rawU32Array.byteswap()

        # 5) Now deserialise into a list of TransactionElements
        transactionElementList = [
        ]  # The list all the deserialised transaction elements will go into
        appendToTransactionElementList = transactionElementList.append  # This is needed for a speed optimisation
        iU32 = 1  # Index for moving through the rawU32Array          # TEMPORARY IPBUS V2.x HACK! Skip the first word which is now a packet ID
        rawU32ArraySize = len(rawU32Array)
        while iU32 < rawU32ArraySize:
            expectedBodySize = getExpectedBodySize(rawU32Array[iU32])
            if rawU32ArraySize - iU32 - 1 - expectedBodySize < 0:
                raise ChipsException("Deserialisation error: packet not correctly formatted " \
                                     "or does not contain the expected amount of data!")
            appendToTransactionElementList(
                TransactionElement(rawU32Array[iU32:iU32 + 1 +
                                               expectedBodySize]))
            iU32 += (1 + expectedBodySize)

        # 6) Debug output of deserialised packet content
        if chipsLog.level <= logging.DEBUG:
            msg = "\nDeserialised packet content is:\n" \
                  + reprTransactionElementList(transactionElementList)
            chipsLog.debug(msg)

        return transactionElementList
Пример #36
0
    def queueRun(self):
        """Runs the current queue of single register read or write transactions and returns two lists. The
        first contains the values read and the second contains the values written.

        Note: Only single-register reads/writes can be queued.  Block reads/writes, etc, cannot
        be queued.
        """

        chipsLog.debug("Running all queued transactions")

        requestQueueLength = len(self._queuedRequests)

        readResponse = []
        writeResponse = []

        try:
            transaction = self._makeAndRunTransaction(self._queuedRequests)
        except ChipsException as err:
            self.queueClear()
            raise ChipsException("Error while running queued transactions:\n\t" + str(err))

        for i in range(requestQueueLength):
            addrTableItem = self._queuedAddrTableItems[i]

            if len(transaction.responses[0].getBody()) > 0:
                transactionResponse = transaction.responses[i - requestQueueLength].getBody()[0] & 0xffffffff
                transactionResponse = addrTableItem.shiftDataFromMask(transactionResponse)
            else:
                transactionResponse = 0

            if self._queuedIsARead[i]:
                readResponse.append(transactionResponse)
                chipsLog.debug("Read success! Register '" + addrTableItem.getName() + "' returned: 0x" + uInt32HexStr(transactionResponse))
            else:
                writeResponse.append(transactionResponse)
                chipsLog.debug("Write success! Register '" + addrTableItem.getName() + "' assigned: 0x" + uInt32HexStr(transactionResponse))

        self.queueClear()

        response = [readResponse, writeResponse]

        return response
Пример #37
0
    def doTransactionChecks(self):
        """Performs a generic set of client transaction checks on all transaction elements in the request/response lists"""

        if len(self.requests) != len(self.responses):
            raise ChipsException("Transaction error: incorrect number of responses returned!")

        for iElement in range(len(self.requests)):

            request = self.requests[iElement]
            response = self.responses[iElement]
            requestHeader = request.getHeader()
            responseHeader = response.getHeader()
            
            if getTypeId(requestHeader) != getTypeId(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "request and response transaction types do not match; expected '" + hex(getTypeId(requestHeader)) + 
                                     "' but got '" + hex(getTypeId(responseHeader)) + "'!")
                                     
            if getTransactionId(requestHeader) != getTransactionId(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "request and response transactions IDs do not match; expected '" + str(getTransactionId(requestHeader)) + 
                                     "' but got '" + str(getTransactionId(responseHeader)) + "'!")
                                     
            if isRequestHeader(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "the received response for transaction ID " + str(getTransactionId(responseHeader)) + " has an INFO CODE " \
                                     "that declares it as a request!")
                                                      
            if isResponseErrorHeader(responseHeader):
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "the host reports the following error occurred (INFO CODE = " + hex(getInfoCode(responseHeader)) +
                                     ") whilst processing transaction ID " + str(getTransactionId(responseHeader)) + ": '" + 
                                     interpretInfoCode(getInfoCode(responseHeader)) + "'!")
                                     
            if not response.validBodySize():
                raise ChipsException("Transaction error from '" + self.getHostAddr() + " (header=0x" + uInt32HexStr(responseHeader) + "): " \
                                     "incorrect response body size for transaction number " + str(getTransactionId(responseHeader)) + "!")
Пример #38
0
 def __repr__(self):
     """For representing the object in string form"""
     resultString = "  0x" + uInt32HexStr(self.getHeader()) + "\tHeader\n"
     for index, u32 in enumerate(self.getBody()):
         resultString += "  0x" + uInt32HexStr(u32) + "\tBody " + str(index) + "\n"
     return resultString
Пример #39
0
     writeResponse = []
     
     try:
         transaction = self._makeAndRunTransaction(self._transactionQueue)
     except ChipsException, err:
         self.queueClear()
         raise ChipsException("Error while running queued transactions:\n\t" + str(err))
     
     for i in range(transactionQueueLength):
         item = self._transactionItemQueue[i]
         transactionResponse = transaction.responses[i - transactionQueueLength].getBody()[0] & 0xffffffff
         transactionResponse = item.shiftDataFromMask(transactionResponse)
         
         if self._transactionRWFlagQueue[i]:
             readResponse.append(transactionResponse)
             chipsLog.debug("Read success! Register '" + item.getName() + "' returned: 0x" + uInt32HexStr(transactionResponse))
         else:
             writeResponse.append(transactionResponse)
             chipsLog.debug("Write success! Register '" + item.getName() + "' assigned: 0x" + uInt32HexStr(transactionResponse))
     
     self.queueClear()
     
     response = [readResponse, writeResponse]
     
     return response
     
     
 def queueClear(self):
     """Clears the current queue of transactions"""
     
     chipsLog.debug("Clearing transaction queue")