Ejemplo n.º 1
0
    def _createWriteTransactionElement(self,
                                       addrTableItem,
                                       dataList,
                                       addrOffset=0,
                                       isFifo=False):
        """Returns a Write Request transaction element (i.e. unmasked/block write)

        addrTableItem:  The relevant address table item you want to perform the write transaction on.
        dataList:  The list of 32-bit numbers you want to write (the list size defines the write depth)
        addrOffset:  The offset on the address specified within the address table item, default is 0.
        isFifo: False gives a normal write transaction; True gives a non-incrementing write transaction (i.e. same addr many times).
        """
        for value in dataList:
            if not uInt32Compatible(value):
                raise ChipsException("Write transaction creation error: cannot create a write transaction with data " \
                                     "values (" + hex(value) +") that are not valid 32-bit unsigned integers!")

        typeId = IPbusHeader.TYPE_ID_WRITE
        if isFifo: typeId = IPbusHeader.TYPE_ID_NON_INCR_WRITE
        writeHeader = IPbusHeader.makeHeader(ChipsBusBase.IPBUS_PROTOCOL_VER,
                                             self._getTransactionId(),
                                             len(dataList), typeId,
                                             IPbusHeader.INFO_CODE_REQUEST)
        writeBody = [addrTableItem.getAddress() + addrOffset] + dataList
        return TransactionElement.makeFromHeaderAndBody(writeHeader, writeBody)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
 def _createByteOrderTransactionElement(self):
     """Returns a Byte-Order Request transaction element.
     
     Note: Byte-order transactions will always and exclusively have transactionId = 0.
     """
     byteOrderHeader = IPbusHeader.makeHeader(ChipsBusBase.IPBUS_PROTOCOL_VER, 0, 0, IPbusHeader.TYPE_ID_BYTE_ORDER, 0, 0)
     return TransactionElement.makeFromHeaderAndBody(byteOrderHeader)
Ejemplo n.º 4
0
 def _handleGetReservedAddrInfoRequest(self, request):
     chipsLog.debug("Reserved Address Info transaction requested")
     # 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)
     responseHeader = IPbusHeader.updateWords(responseHeader, 2)
     # Returning zeros for the response body, as no real idea what else it should be.
     return TransactionElement.makeFromHeaderAndBody(responseHeader, [0,0])
Ejemplo n.º 5
0
 def _handleGetReservedAddrInfoRequest(self, request):
     chipsLog.debug("Reserved Address Info transaction requested")
     # 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)
     responseHeader = IPbusHeader.updateWords(responseHeader, 2)
     # Returning zeros for the response body, as no real idea what else it should be.
     return TransactionElement.makeFromHeaderAndBody(responseHeader, [0, 0])
Ejemplo n.º 6
0
 def _createReadTransactionElement(self, addrTableItem, readDepth = 1, addrOffset = 0, isFifo = False):
     """Returns a Read Request transaction element
     
     addrTableItem:  The relevant address table item you want to perform the write transaction on.
     readDepth:  The depth of the read; default is 1, which would be a single 32-bit register read. 
     addrOffset:  The offset on the address specified within the address table item, default is 0.
     isFifo: False gives a normal read transaction; True gives a non-incrementing read transaction (i.e. same addr many times).
     """
     typeId = IPbusHeader.TYPE_ID_READ
     if isFifo: typeId = IPbusHeader.TYPE_ID_NON_INCR_READ
     readHeader = IPbusHeader.makeHeader(ChipsBusBase.IPBUS_PROTOCOL_VER, self._getTransactionId(), readDepth, typeId, IPbusHeader.INFO_CODE_REQUEST)
     readBody = [addrTableItem.getAddress() + addrOffset]
     return TransactionElement.makeFromHeaderAndBody(readHeader, readBody)
Ejemplo n.º 7
0
    def _createReadTransactionElement(self, addrTableItem, readDepth = 1, addrOffset = 0, isFifo = False):
        """Returns a Read Request transaction element

        addrTableItem:  The relevant address table item you want to perform the write transaction on.
        readDepth:  The depth of the read; default is 1, which would be a single 32-bit register read.
        addrOffset:  The offset on the address specified within the address table item, default is 0.
        isFifo: False gives a normal read transaction; True gives a non-incrementing read transaction (i.e. same addr many times).
        """
        typeId = IPbusHeader.TYPE_ID_READ
        if isFifo: typeId = IPbusHeader.TYPE_ID_NON_INCR_READ
        readHeader = IPbusHeader.makeHeader(ChipsBusBase.IPBUS_PROTOCOL_VER, self._getTransactionId(), readDepth, typeId, IPbusHeader.INFO_CODE_REQUEST)
        readBody = [addrTableItem.getAddress() + addrOffset]
        return TransactionElement.makeFromHeaderAndBody(readHeader, readBody)
Ejemplo n.º 8
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)
Ejemplo n.º 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)
Ejemplo n.º 10
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
Ejemplo n.º 11
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)
Ejemplo n.º 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)
Ejemplo n.º 13
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])
Ejemplo n.º 14
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])
Ejemplo n.º 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)
Ejemplo n.º 16
0
    def _createRMWBitsTransactionElement(self, addrTableItem, dataU32, addrOffset = 0):
        """Returns a Read/Modify/Write Bits Request transaction element (i.e. masked write)

        addrTableItem:  The relevant address table item you want to perform the RMWBits transaction on.
        dataU32:  The data (32 bits max, or equal in width to the bit-mask).
        addrOffset:  The offset on the address specified within the address table item, default is 0.
        """

        if not uInt32Compatible(dataU32):
            raise ChipsException("Read-Modify-Write Bits transaction creation error: cannot create a RMW-bits " \
                            "transaction with data values (" + hex(dataU32) +") that are not valid 32-bit " \
                            "unsigned integers!")

        rmwHeader = IPbusHeader.makeHeader(ChipsBus.IPBUS_PROTOCOL_VER, self._getTransactionId(), 1, IPbusHeader.TYPE_ID_RMW_BITS, IPbusHeader.INFO_CODE_REQUEST)
        rmwBody = [addrTableItem.getAddress() + addrOffset, \
                   uInt32BitFlip(addrTableItem.getMask()), \
                   addrTableItem.shiftDataToMask(dataU32)]
        return TransactionElement.makeFromHeaderAndBody(rmwHeader, rmwBody)
Ejemplo n.º 17
0
    def _createWriteTransactionElement(self, addrTableItem, dataList, addrOffset = 0, isFifo = False):
        """Returns a Write Request transaction element (i.e. unmasked/block write)
        
        addrTableItem:  The relevant address table item you want to perform the write transaction on.
        dataList:  The list of 32-bit numbers you want to write (the list size defines the write depth) 
        addrOffset:  The offset on the address specified within the address table item, default is 0.
        isFifo: False gives a normal write transaction; True gives a non-incrementing write transaction (i.e. same addr many times).
        """
        for value in dataList:
            if not uInt32Compatible(value):
                raise ChipsException("Write transaction creation error: cannot create a write transaction with data " \
                                     "values (" + hex(value) +") that are not valid 32-bit unsigned integers!")

        typeId = IPbusHeader.TYPE_ID_WRITE
        if isFifo: typeId = IPbusHeader.TYPE_ID_NON_INCR_WRITE
        writeHeader = IPbusHeader.makeHeader(ChipsBusBase.IPBUS_PROTOCOL_VER, self._getTransactionId(), len(dataList), typeId, IPbusHeader.INFO_CODE_REQUEST)
        writeBody = [addrTableItem.getAddress() + addrOffset] + dataList
        return TransactionElement.makeFromHeaderAndBody(writeHeader, writeBody)
Ejemplo n.º 18
0
    def _createRMWBitsTransactionElement(self, addrTableItem, dataU32, addrOffset = 0):
        """Returns a Read/Modify/Write Bits Request transaction element (i.e. masked write)
        
        addrTableItem:  The relevant address table item you want to perform the RMWBits transaction on.
        dataU32:  The data (32 bits max, or equal in width to the bit-mask).
        addrOffset:  The offset on the address specified within the address table item, default is 0.
        """

        if not uInt32Compatible(dataU32):
            raise ChipsException("Read-Modify-Write Bits transaction creation error: cannot create a RMW-bits " \
                            "transaction with data values (" + hex(dataU32) +") that are not valid 32-bit " \
                            "unsigned integers!")
    
        rmwHeader = IPbusHeader.makeHeader(ChipsBus.IPBUS_PROTOCOL_VER, self._getTransactionId(), 1, IPbusHeader.TYPE_ID_RMW_BITS, IPbusHeader.INFO_CODE_REQUEST)
        rmwBody = [addrTableItem.getAddress() + addrOffset, \
                   uInt32BitFlip(addrTableItem.getMask()), \
                   addrTableItem.shiftDataToMask(dataU32)]
        return TransactionElement.makeFromHeaderAndBody(rmwHeader, rmwBody)
Ejemplo n.º 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)
Ejemplo n.º 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])
Ejemplo n.º 21
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)
Ejemplo n.º 22
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])
Ejemplo n.º 23
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)
Ejemplo n.º 24
0
 def _handleByteOrderRequest(self, request):
     chipsLog.debug("Byte-order transaction requested")
     # Response header is the request header with direction bit changed
     responseHeader = IPbusHeader.updateDirection(request.getHeader(), 1)
     return TransactionElement.makeFromHeaderAndBody(responseHeader)
Ejemplo n.º 25
0
 def _handleGetReservedAddrInfoRequest(self, request):
     # Response header is the request header with direction bit changed
     responseHeader = IPbusHeader.updateDirection(request.getHeader(), 1)
     responseHeader = IPbusHeader.updateWords(responseHeader, 2)
     # Returning zeros for the response body, as no real idea what else it should be.
     return TransactionElement.makeFromHeaderAndBody(responseHeader, [0,0])
Ejemplo n.º 26
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