Beispiel #1
0
    def _rawWrite(self,
                  offset,
                  data,
                  base=pr.UInt,
                  stride=4,
                  wordBitSize=32,
                  tryCount=1,
                  posted=False):

        if not isinstance(base, pr.Model):
            base = base(wordBitSize)

        with self._memLock:

            if posted:
                txn = rim.Post
            else:
                txn = rim.Write

            for _ in range(tryCount):
                self._clearError()
                self._rawTxnChunker(offset, data, base, stride, wordBitSize,
                                    txn)
                self._waitTransaction(0)

                if self._getError() == "":
                    return
                elif posted:
                    break
                self._log.warning("Retrying raw write transaction")

            # If we get here an error has occurred
            raise pr.MemoryError(name=self.name,
                                 address=offset | self.address,
                                 msg=self._getError())
Beispiel #2
0
    def _rawTxnChunker(self,
                       offset,
                       data,
                       base=pr.UInt,
                       stride=4,
                       wordBitSize=32,
                       txnType=rim.Write,
                       numWords=1):

        if not isinstance(base, pr.Model):
            base = base(wordBitSize)

        if offset + (numWords * stride) > self._size:
            raise pr.MemoryError(name=self.name,
                                 address=offset | self.address,
                                 msg='Raw transaction outside of device size')

        if base.bitSize > stride * 8:
            raise pr.MemoryError(
                name=self.name,
                address=offset | self.address,
                msg='Called raw memory access with wordBitSize > stride')

        if txnType == rim.Write or txnType == rim.Post:
            if isinstance(data, bytearray):
                ldata = data
            elif isinstance(data, collections.abc.Iterable):
                ldata = b''.join(
                    base.toBytes(word).ljust(stride, b'\0') for word in data)
            else:
                ldata = base.toBytes(data)

        else:
            if data is not None:
                ldata = data
            else:
                ldata = bytearray(numWords * stride)

        with self._memLock:
            for i in range(offset, offset + len(ldata), self._reqMaxAccess()):
                sliceOffset = i | self.offset
                txnSize = min(self._reqMaxAccess(), len(ldata) - (i - offset))
                #print(f'sliceOffset: {sliceOffset:#x}, ldata: {ldata}, txnSize: {txnSize}, buffOffset: {i-offset}')
                self._reqTransaction(sliceOffset, ldata, txnSize, i - offset,
                                     txnType)

            return ldata
Beispiel #3
0
    def _rawRead(self,
                 offset,
                 numWords=1,
                 base=pr.UInt,
                 stride=4,
                 wordBitSize=32,
                 data=None,
                 tryCount=1):

        if not isinstance(base, pr.Model):
            base = base(wordBitSize)

        with self._memLock:
            for _ in range(tryCount):
                self._clearError()
                ldata = self._rawTxnChunker(offset,
                                            data,
                                            base,
                                            stride,
                                            wordBitSize,
                                            txnType=rim.Read,
                                            numWords=numWords)
                self._waitTransaction(0)

                if self._getError() == "":
                    if numWords == 1:
                        return base.fromBytes(ldata)
                    else:
                        return [
                            base.fromBytes(ldata[i:i + stride])
                            for i in range(0, len(ldata), stride)
                        ]
                self._log.warning("Retrying raw read transaction")

            # If we get here an error has occurred
            raise pr.MemoryError(name=self.name,
                                 address=offset | self.address,
                                 msg=self._getError())
Beispiel #4
0
    def _buildBlocks(self):
        remVars = []

        # Use min block size, larger blocks can be pre-created
        blkSize = self._blkMinAccess()

        # Process all of the variables
        for k, n in self.nodes.items():

            # Local variables have a 1:1 block association
            if isinstance(n, pr.LocalVariable):
                self._blocks.append(n._block)

            # Align to min access, create list of remote variables
            elif isinstance(n, pr.RemoteVariable) and n.offset is not None:
                n._updatePath(n.path)
                n._shiftOffsetDown(n.offset % blkSize, blkSize)
                remVars += [n]

        # Sort var list by offset, size
        remVars.sort(key=lambda x: (x.offset, x.varBytes))
        blocks = []
        blk = None

        # Go through sorted variable list, look for overlaps, group into blocks
        for n in remVars:

            if blk is not None and ((blk['offset'] + blk['size']) > n.offset):
                self._log.info(
                    "Overlap detected var offset={} block offset={} block bytes={}"
                    .format(n.offset, blk['offset'], blk['size']))
                n._shiftOffsetDown(n.offset - blk['offset'], blkSize)
                blk['vars'].append(n)

                if n.varBytes > blk['size']:
                    blk['size'] = n.varBytes

            # We need a new block for this variable
            else:
                blk = None

                # Look for pre-made block which overlaps
                for b in self._custBlocks:
                    if ((n.offset >= b.offset)
                            and ((b.offset + b.size) > n.offset)):

                        # Just in case a variable extends past the end of pre-made block, user mistake
                        if n.varBytes > b.size:
                            msg = 'Failed to add variable {n.name} to pre-made block with offset {b.offset} and size {b.size}'
                            raise pr.MemoryError(name=self.path,
                                                 address=self.address,
                                                 msg=msg)

                        blk = {
                            'offset': b.offset,
                            'size': b.size,
                            'vars': [n],
                            'block': b
                        }
                        break

                # Block not found
                if blk is None:
                    blk = {
                        'offset': n.offset,
                        'size': n.varBytes,
                        'vars': [n],
                        'block': None
                    }
                    blocks.append(blk)

        # Clear pre-made list
        self._custBlocks = []

        # Create new blocks and add new and pre-made blocks to device
        # Add variables to the block
        for b in blocks:

            # Create new block
            if b['block'] is None:
                newBlock = rim.Block(b['offset'], b['size'])
                self._log.debug(
                    "Adding new block at offset {:#02x}, size {}".format(
                        b['offset'], b['size']))
            else:
                newBlock = b['block']

            # Set memory slave
            newBlock._setSlave(self)

            # Verify the block is not too small or large for the memory interface
            if newBlock.size > self._reqMaxAccess(
            ) or newBlock.size < self._reqMinAccess():
                msg = f'Block size {newBlock.size} is not in the range: {self._reqMinAccess()} - {self._reqMaxAccess()}'
                raise pr.MemoryError(name=self.path,
                                     address=self.address,
                                     msg=msg)

            # Add variables to the block
            newBlock.addVariables(b['vars'])

            # Set varible block links
            for v in b['vars']:
                v._block = newBlock

            # Add to device
            self._blocks.append(newBlock)
            newBlock.setEnable(self.enable.value() is True)
Beispiel #5
0
 def TestMemoryException(arg):
     raise pr.MemoryError(name='blah', address=0)