//@C Copyright Notice //@C ================ //@C This file is part of CPSW. It is subject to the license terms in the LICENSE.txt //@C file found in the top-level directory of this distribution and at //@C https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. //@C //@C No part of CPSW, including this file, may be copied, modified, propagated, or //@C distributed except according to the terms contained in the LICENSE.txt file. #include #include #include #include #include #undef MEMDEV_DEBUG CMemDevImpl::CMemDevImpl(Key &k, const char *name, uint64_t size, uint8_t *ext_buf) : CDevImpl(k, name, size), buf_( ext_buf ? ext_buf : new uint8_t[size] ), isExt_ ( ext_buf ? true : false ) { } CMemDevImpl::CMemDevImpl(Key &key, YamlState &node) : CDevImpl(key, node), buf_( new uint8_t[size_] ), isExt_( false ) { if ( 0 == size_ ) { throw InvalidArgError("'size' zero or unset"); } } CMemDevImpl::CMemDevImpl(const CMemDevImpl &orig, Key &k) : CDevImpl(orig, k), buf_( new uint8_t[orig.getSize()] ), isExt_( false ) { memcpy( buf_, orig.buf_, orig.getSize() ); } CMemDevImpl::~CMemDevImpl() { if ( ! isExt_ ) delete [] buf_; } void CMemDevImpl::addAtAddress(Field child) { IAddress::AKey k = getAKey(); add( make_shared(k), child ); } void CMemDevImpl::addAtAddress(Field child, unsigned nelms) { if ( 1 != nelms ) throw ConfigurationError("CMemDevImpl::addAtAddress -- can only have exactly 1 child"); addAtAddress( child ); } CMemAddressImpl::CMemAddressImpl(AKey k) : CAddressImpl(k, 1) { } uint64_t CMemAddressImpl::read(CompositePathIterator *node, CReadArgs *args) const { MemDevImpl owner( getOwnerAs() ); unsigned toget = args->nbytes_; if ( args->off_ + toget > owner->getSize() ) { #ifdef MEMDEV_DEBUG printf("off %lu, dbytes %lu, size %lu\n", args->off_, args->nbytes_, owner->getSize()); #endif throw ConfigurationError("MemAddress: read out of range"); } memcpy(args->dst_, owner->getBufp() + args->off_, toget); #ifdef MEMDEV_DEBUG printf("MemDev read from off %lli to %p:", args->off_, args->dst_); for ( unsigned ii=0; iinbytes_; ii++) printf(" 0x%02x", args->dst_[ii]); printf("\n"); #endif if ( args->aio_ ) args->aio_->callback( 0 ); return toget; } uint64_t CMemAddressImpl::write(CompositePathIterator *node, CWriteArgs *args) const { MemDevImpl owner( getOwnerAs() ); uint8_t *buf = owner->getBufp(); unsigned put = args->nbytes_; unsigned rval = put; uint8_t msk1 = args->msk1_; uint8_t mskn = args->mskn_; uint64_t off = args->off_; uint8_t *src = args->src_; if ( off + put > owner->getSize() ) { throw ConfigurationError("MemAddress: write out of range"); } #ifdef MEMDEV_DEBUG printf("MemDev write to off %lli from %p:", args->off_, args->src_); for ( unsigned ii=0; iinbytes_; ii++) printf(" 0x%02x", args->src_[ii]); printf("\n"); #endif if ( (msk1 || mskn) && put == 1 ) { msk1 |= mskn; mskn = 0; } if ( msk1 ) { /* merge 1st byte */ buf[off] = ( (buf[off]) & msk1 ) | ( src[0] & ~msk1 ) ; off++; put--; src++; } if ( mskn ) { put--; } if ( put ) { memcpy(owner->getBufp() + off, src, put); } if ( mskn ) { /* merge last byte */ buf[off+put] = (buf[off+put] & mskn ) | ( src[put] & ~mskn ); } return rval; } MemDev IMemDev::create(const char *name, uint64_t size, uint8_t *ext_buf) { return CShObj::create(name, size, ext_buf); }