diff --git a/.github/workflows/rogue_ci.yml b/.github/workflows/rogue_ci.yml index be54ad1b6..81487af53 100644 --- a/.github/workflows/rogue_ci.yml +++ b/.github/workflows/rogue_ci.yml @@ -140,7 +140,7 @@ jobs: - name: Get Image Information id: get_image_info run: | - echo ::set-output name=tag::`git describe --tags` + echo tag=`git describe --tags` >> ${GITHUB_OUTPUT} - name: Get Ruckus run: | @@ -192,8 +192,7 @@ jobs: env: CONDA_UPLOAD_TOKEN_TAG: ${{ secrets.CONDA_UPLOAD_TOKEN_TAG }} run: | - echo ::set-output name=token::$CONDA_UPLOAD_TOKEN_TAG - echo ::set-output name=os::linux-64 + echo token=${CONDA_UPLOAD_TOKEN_TAG} >> ${GITHUB_OUTPUT} - name: Build run: | @@ -222,8 +221,8 @@ jobs: - name: Get Image Information id: get_image_info run: | - echo ::set-output name=tag::`git describe --tags` - echo ::set-output name=branch::`echo ${GITHUB_REF} | awk 'BEGIN { FS = "/" } ; { print $3 }'` + echo tag=`git describe --tags` >> ${GITHUB_OUTPUT} + echo branch=`echo ${GITHUB_REF} | awk 'BEGIN { FS = "/" } ; { print $3 }'` >> ${GITHUB_OUTPUT} # Setup docker build environment - name: Set up Docker Buildx diff --git a/pip_requirements.txt b/pip_requirements.txt index 1179b662b..e3f5afab4 100644 --- a/pip_requirements.txt +++ b/pip_requirements.txt @@ -19,3 +19,4 @@ gitpython pygithub pydm matplotlib +hwcounter diff --git a/python/pyrogue/_Block.py b/python/pyrogue/_Block.py index 57720f163..cb167c233 100644 --- a/python/pyrogue/_Block.py +++ b/python/pyrogue/_Block.py @@ -12,10 +12,12 @@ # contained in the LICENSE.txt file. #----------------------------------------------------------------------------- import threading +import numpy as np import pyrogue as pr import rogue.interfaces.memory as rim + def startTransaction(block, *, type, forceWr=False, checkEach=False, variable=None, index=-1, **kwargs): """ Helper function for calling the startTransaction function in a block. This helper @@ -228,10 +230,12 @@ def set(self, var, value, index=-1): """ with self._lock: - if index < 0 and (isinstance(value, list) or isinstance(value,dict)): + if index < 0 and (isinstance(value, list) or isinstance(value, dict)): changed = True elif index >= 0: changed = self._value[index] != value + elif isinstance(value, np.ndarray): + changed = np.array_equal(self._value, value) else: changed = self._value != value diff --git a/python/pyrogue/_DataReceiver.py b/python/pyrogue/_DataReceiver.py index a671d7202..39e284e2b 100644 --- a/python/pyrogue/_DataReceiver.py +++ b/python/pyrogue/_DataReceiver.py @@ -55,6 +55,7 @@ def __init__(self, self.add(pr.LocalVariable(name='Data', typeStr=typeStr, disp='', + groups=['NoState','NoStream'], value=value, hidden=hideData, description='Data Frame Container')) diff --git a/python/pyrogue/_Variable.py b/python/pyrogue/_Variable.py index 26983dde4..06ea016c9 100644 --- a/python/pyrogue/_Variable.py +++ b/python/pyrogue/_Variable.py @@ -814,10 +814,14 @@ def _setDict(self,d,writeEach,modes,incGroups,excGroups,keys): for val,i in zip(s,idxSlice): self.setDisp(val.strip(), write=writeEach, index=i) + else: + self._log.warning(f"Skipping set for Entry {self.name} with mode {self._mode}. Enabled Modes={modes}.") # Standard set elif self._mode in modes: self.setDisp(d,writeEach) + else: + self._log.warning(f"Skipping set for Entry {self.name} with mode {self._mode}. Enabled Modes={modes}.") def _getDict(self, modes=['RW', 'RO', 'WO'], incGroups=None, excGroups=None, properties=False): """ @@ -1042,9 +1046,22 @@ def __init__(self, *, listData = VariableListData(numValues,valueBits,valueStride) # Setup C++ Base class - rim.Variable.__init__(self,self._name,self._mode,self._minimum,self._maximum, - offset, bitOffset, bitSize, overlapEn, verify, - self._bulkOpEn, self._updateNotify, self._base, listData, retryCount) + rim.Variable.__init__( + self, + self._name, + self._mode, + self._minimum, + self._maximum, + offset, + bitOffset, + bitSize, + overlapEn, + verify, + self._bulkOpEn, + self._updateNotify, + self._base, + listData, + retryCount) ############################## diff --git a/src/rogue/interfaces/memory/Block.cpp b/src/rogue/interfaces/memory/Block.cpp index 9e12443ae..5e3a106e5 100644 --- a/src/rogue/interfaces/memory/Block.cpp +++ b/src/rogue/interfaces/memory/Block.cpp @@ -1824,7 +1824,8 @@ double rim::Block::getFixed(rim::Variable* var, int32_t index) { if ((fPoint & (1 << (var->valueBits_ - 1))) != 0) { fPoint = fPoint - (1 << var->valueBits_); } // Convert to float - tmp = (double)fPoint / pow(2, var->binPoint_); + tmp = (double)fPoint; + tmp = tmp / pow(2, var->binPoint_); return tmp; } diff --git a/src/rogue/interfaces/memory/Variable.cpp b/src/rogue/interfaces/memory/Variable.cpp index cfb92dc56..01934be9b 100644 --- a/src/rogue/interfaces/memory/Variable.cpp +++ b/src/rogue/interfaces/memory/Variable.cpp @@ -43,65 +43,68 @@ namespace bp = boost::python; #endif //! Class factory which returns a pointer to a Variable (VariablePtr) -rim::VariablePtr rim::Variable::create(std::string name, - std::string mode, - double minimum, - double maximum, - uint64_t offset, - std::vector bitOffset, - std::vector bitSize, - bool overlapEn, - bool verify, - bool bulkOpEn, - bool updateNotify, - uint32_t modelId, - bool byteReverse, - bool bitReverse, - uint32_t binPoint, - uint32_t numValues, - uint32_t valueBits, - uint32_t valueStride, - uint32_t retryCount) { - rim::VariablePtr v = std::make_shared(name, - mode, - minimum, - maximum, - offset, - bitOffset, - bitSize, - overlapEn, - verify, - bulkOpEn, - updateNotify, - modelId, - byteReverse, - bitReverse, - binPoint, - numValues, - valueBits, - valueStride, - retryCount); +rim::VariablePtr rim::Variable::create( + std::string name, + std::string mode, + double minimum, + double maximum, + uint64_t offset, + std::vector bitOffset, + std::vector bitSize, + bool overlapEn, + bool verify, + bool bulkOpEn, + bool updateNotify, + uint32_t modelId, + bool byteReverse, + bool bitReverse, + uint32_t binPoint, + uint32_t numValues, + uint32_t valueBits, + uint32_t valueStride, + uint32_t retryCount) { + rim::VariablePtr v = std::make_shared( + name, + mode, + minimum, + maximum, + offset, + bitOffset, + bitSize, + overlapEn, + verify, + bulkOpEn, + updateNotify, + modelId, + byteReverse, + bitReverse, + binPoint, + numValues, + valueBits, + valueStride, + retryCount); return (v); } // Setup class for use in python void rim::Variable::setup_python() { #ifndef NO_PYTHON - bp::class_("Variable", - bp::init()) + bp::class_( + "Variable", + bp::init()) .def("_varBytes", &rim::Variable::varBytes) .def("_offset", &rim::Variable::offset) .def("_shiftOffsetDown", &rim::Variable::shiftOffsetDown) diff --git a/src/rogue/protocols/packetizer/ControllerV2.cpp b/src/rogue/protocols/packetizer/ControllerV2.cpp index ee680e2aa..84b4019af 100644 --- a/src/rogue/protocols/packetizer/ControllerV2.cpp +++ b/src/rogue/protocols/packetizer/ControllerV2.cpp @@ -235,7 +235,8 @@ void rpp::ControllerV2::transportRx(ris::FramePtr frame) { tranFrame_[tmpDest]->setLastUser(tmpLuser); transSof_[tmpDest] = true; tranCount_[tmpDest] = 0; - if (app_[tmpDest]) { app_[tmpDest]->pushFrame(tranFrame_[tmpDest]); } + if (app_[tmpDest]) { + app_[tmpDest]->pushFrame(tranFrame_[tmpDest]); } tranFrame_[tmpDest].reset(); // Detect SSI error @@ -358,7 +359,7 @@ void rpp::ControllerV2::applicationRx(ris::FramePtr frame, uint8_t tDest) { fUser, tDest, segment, - data[7], + data[7]>>7, lUser, data[size - 7], last); diff --git a/tests/test_rate.py b/tests/test_rate.py index f761c2e6b..ffbb00a97 100644 --- a/tests/test_rate.py +++ b/tests/test_rate.py @@ -14,12 +14,21 @@ import pyrogue.interfaces.simulation import rogue.interfaces.memory import time +import hwcounter #rogue.Logging.setLevel(rogue.Logging.Debug) #import logging #logger = logging.getLogger('pyrogue') #logger.setLevel(logging.DEBUG) +MaxCycles = { 'remoteSetRate' : 8.0e9, + 'remoteSetNvRate' : 7.0e9, + 'remoteGetRate' : 6.0e9, + 'localSetRate' : 8.0e9, + 'localGetRate' : 6.0e9, + 'linkedSetRate' : 9.0e9, + 'linkedGetRate' : 8.0e9 } + class TestDev(pr.Device): def __init__(self,**kwargs): @@ -98,57 +107,76 @@ def test_rate(): with DummyTree() as root: count = 100000 + resultRate = {} + resultCycles = {} stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestRemote.set(i) - remoteSetRate = 1/((time.time()-stime) / count) + resultCycles['remoteSetRate'] = float(hwcounter.count_end() - scount) + resultRate['remoteSetRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestRemoteNoVerify.set(i) - remoteSetNvRate = 1/((time.time()-stime) / count) + resultCycles['remoteSetNvRate'] = float(hwcounter.count_end() - scount) + resultRate['remoteSetNvRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestRemote.get() - remoteGetRate = 1/((time.time()-stime) / count) + resultCycles['remoteGetRate'] = float(hwcounter.count_end() - scount) + resultRate['remoteGetRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestLocal.set(i) - localSetRate = 1/((time.time()-stime) / count) + resultCycles['localSetRate'] = float(hwcounter.count_end() - scount) + resultRate['localSetRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestLocal.get() - localGetRate = 1/((time.time()-stime) / count) + resultCycles['localGetRate'] = float(hwcounter.count_end() - scount) + resultRate['localGetRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestLink.set(i) - linkedSetRate = 1/((time.time()-stime) / count) + resultCycles['linkedSetRate'] = float(hwcounter.count_end() - scount) + resultRate['linkedSetRate'] = int(1/((time.time()-stime) / count)) stime = time.time() + scount = hwcounter.count() with root.updateGroup(): for i in range(count): root.TestDev.TestLink.get(i) - linkedGetRate = 1/((time.time()-stime) / count) + resultCycles['linkedGetRate'] = float(hwcounter.count_end() - scount) + resultRate['linkedGetRate'] = int(1/((time.time()-stime) / count)) + + passed = True + + for k,v in MaxCycles.items(): + + print(f"{k} cyles {resultCycles[k]:.2e}, maximum {v:.2e}, rate {resultRate[k]}") - print(f"Remote Set Rate = {remoteSetRate:.0f}") - print(f"Remote Set Nv Rate = {remoteSetNvRate:.0f}") - print(f"Remote Get Rate = {remoteGetRate:.0f}") - print(f"Local Set Rate = {localSetRate:.0f}") - print(f"Local Get Rate = {localGetRate:.0f}") - print(f"Linked Set Rate = {linkedSetRate:.0f}") - print(f"Linked Get Rate = {linkedGetRate:.0f}") + if resultCycles[k] > v: + passed = False + if passed is False: + raise AssertionError('Rate check failed') if __name__ == "__main__": test_rate()