rogue
Loading...
Searching...
No Matches
Block.cpp
Go to the documentation of this file.
1
18#include "rogue/Directives.h"
19
20#ifndef NO_PYTHON
21
22#define NO_IMPORT_ARRAY
23#include "rogue/numpy.h"
24#include <boost/python.hpp>
25
26namespace bp = boost::python;
27
28#endif
29
31
32#include <inttypes.h>
33#include <sys/time.h>
34
35#include <cmath>
36#include <cstdio>
37#include <cstring>
38#include <exception>
39#include <iomanip>
40#include <memory>
41#include <sstream>
42#include <string>
43#include <vector>
44
45#include "rogue/GeneralError.h"
46#include "rogue/GilRelease.h"
47#include "rogue/ScopedGil.h"
52
54
55
56// Class factory which returns a pointer to a Block (BlockPtr)
57rim::BlockPtr rim::Block::create(uint64_t offset, uint32_t size) {
58 rim::BlockPtr b = std::make_shared<rim::Block>(offset, size);
59 return (b);
60}
61
62#ifndef NO_PYTHON
63// Setup class for use in python
64void rim::Block::setup_python() {
65 bp::class_<rim::Block, rim::BlockPtr, bp::bases<rim::Master>, boost::noncopyable>("Block",
66 bp::init<uint64_t, uint32_t>())
67 .add_property("path", &rim::Block::path)
68 .add_property("mode", &rim::Block::mode)
69 .add_property("bulkOpEn", &rim::Block::bulkOpEn)
70 .add_property("offset", &rim::Block::offset)
71 .add_property("address", &rim::Block::address)
72 .add_property("size", &rim::Block::size)
73 .def("setEnable", &rim::Block::setEnable)
74 .def("_startTransaction", &rim::Block::startTransactionPy)
75 .def("_checkTransaction", &rim::Block::checkTransactionPy)
76 .def("addVariables", &rim::Block::addVariablesPy)
77 .def("_rateTest", &rim::Block::rateTest)
78 .add_property("variables", &rim::Block::variablesPy);
79
80 bp::implicitly_convertible<rim::BlockPtr, rim::MasterPtr>();
81}
82#endif
83
84// Create a Hub device with a given offset
85rim::Block::Block(uint64_t offset, uint32_t size) {
86 path_ = "Undefined";
87 mode_ = "RW";
88 bulkOpEn_ = false;
89 updateEn_ = false;
90 offset_ = offset;
91 size_ = size;
92 verifyEn_ = false;
93 verifyReq_ = false;
94 verifyInp_ = false;
95 doUpdate_ = false;
96 blockPyTrans_ = false;
97 enable_ = false;
98 stale_ = false;
99 retryCount_ = 0;
100
101 verifyBase_ = 0; // Verify Range
102 verifySize_ = 0; // Verify Range
103
104 blockData_ = reinterpret_cast<uint8_t*>(malloc(size_));
105 memset(blockData_, 0, size_);
106
107 verifyData_ = reinterpret_cast<uint8_t*>(malloc(size_));
108 memset(verifyData_, 0, size_);
109
110 verifyMask_ = reinterpret_cast<uint8_t*>(malloc(size_));
111 memset(verifyMask_, 0, size_);
112
113 verifyBlock_ = reinterpret_cast<uint8_t*>(malloc(size_));
114 memset(verifyBlock_, 0, size_);
115}
116
117// Destroy the Hub
118rim::Block::~Block() {
119 // Custom clean
120 customClean();
121
122 free(blockData_);
123 free(verifyData_);
124 free(verifyMask_);
125 free(verifyBlock_);
126}
127
128// Return the path of the block
129std::string rim::Block::path() {
130 return path_;
131}
132
133// Return the mode of the block
134std::string rim::Block::mode() {
135 return mode_;
136}
137
138// Return bulk enable flag
139bool rim::Block::bulkOpEn() {
140 return bulkOpEn_;
141}
142
143// Set enable state
144void rim::Block::setEnable(bool newState) {
145 rogue::GilRelease noGil;
146 std::lock_guard<std::mutex> lock(mtx_);
147 enable_ = newState;
148}
149
150// Get offset of this Block
151uint64_t rim::Block::offset() {
152 return offset_;
153}
154
155// Get full address of this Block
156uint64_t rim::Block::address() {
157 return (reqAddress() + offset_);
158}
159
160// Get size of this block in bytes.
161uint32_t rim::Block::size() {
162 return size_;
163}
164
165// Block transactions
166bool rim::Block::blockPyTrans() {
167 return blockPyTrans_;
168}
169
170// Start a transaction for this block
171void rim::Block::intStartTransaction(uint32_t type, bool forceWr, bool check, rim::Variable* var, int32_t index) {
172 uint32_t x;
173 uint32_t tOff;
174 uint32_t tSize;
175 uint8_t* tData;
176 uint32_t highByte;
177 uint32_t lowByte;
178 uint32_t minAccess = getSlave()->doMinAccess();
179
180 std::vector<rim::VariablePtr>::iterator vit;
181
182 // Check for valid combinations
183 if ((type == rim::Write && ((mode_ == "RO") || (!stale_ && !forceWr))) || (type == rim::Post && (mode_ == "RO")) ||
184 (type == rim::Read && ((mode_ == "WO") || stale_)) ||
185 (type == rim::Verify && ((mode_ == "WO") || (mode_ == "RO") || stale_ || !verifyReq_)))
186 return;
187 {
188 rogue::GilRelease noGil;
189 std::lock_guard<std::mutex> lock(mtx_);
190 waitTransaction(0);
191 clearError();
192
193 // Determine transaction range
194 if (var == NULL) {
195 lowByte = 0;
196 highByte = size_ - 1;
197 if (type == rim::Write || type == rim::Post) {
198 stale_ = false;
199 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
200 (*vit)->stale_ = false;
201 }
202 }
203 } else {
204 if (type == rim::Read || type == rim::Verify) {
205 if (index < 0 || index >= var->numValues_) {
206 lowByte = var->lowTranByte_[0];
207
208 if (var->numValues_ == 0) {
209 highByte = var->highTranByte_[0];
210 } else {
211 highByte = var->highTranByte_[var->numValues_ - 1];
212 }
213 } else {
214 lowByte = var->lowTranByte_[index];
215 highByte = var->highTranByte_[index];
216 }
217 } else {
218 lowByte = var->staleLowByte_;
219 highByte = var->staleHighByte_;
220
221 // Catch case where fewer stale bytes than min access or non-aligned
222 if (lowByte % minAccess != 0) lowByte -= lowByte % minAccess;
223 if ((highByte + 1) % minAccess != 0) highByte += minAccess - ((highByte + 1) % minAccess);
224 stale_ = false;
225 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
226 if ((*vit)->stale_) {
227 if ((*vit)->staleLowByte_ < lowByte) lowByte = (*vit)->staleLowByte_;
228 if ((*vit)->staleHighByte_ > highByte) highByte = (*vit)->staleHighByte_;
229 (*vit)->stale_ = false;
230 }
231 }
232 }
233 }
234
235 // Device is disabled, check after clearing stale states
236 if (!enable_) return;
237
238 // Setup verify data, clear verify write flag if verify transaction
239 if (type == rim::Verify) {
240 tOff = verifyBase_;
241 tSize = verifySize_;
242 tData = verifyData_ + verifyBase_;
243 verifyInp_ = true;
244
245 // Not a verify transaction
246 } else {
247 // Derive offset and size based upon min transaction size
248 tOff = lowByte;
249 tSize = (highByte - lowByte) + 1;
250
251 // Set transaction pointer
252 tData = blockData_ + tOff;
253
254 // Track verify after writes.
255 // Only verify blocks that have been written since last verify
256 if (type == rim::Write) {
257 verifyBase_ = tOff;
258 verifySize_ = tSize;
259 verifyReq_ = verifyEn_;
260 }
261 }
262 doUpdate_ = updateEn_;
263
264 bLog_->debug("Start transaction type = %" PRIu32 ", Offset=0x%" PRIx64 ", lByte=%" PRIu32 ", hByte=%" PRIu32
265 ", tOff=0x%" PRIx32 ", tSize=%" PRIu32,
266 type,
267 offset_,
268 lowByte,
269 highByte,
270 tOff,
271 tSize);
272
273 // Start transaction
274 reqTransaction(offset_ + tOff, tSize, tData, type);
275 }
276}
277
278// Start a transaction for this block, cpp version
279void rim::Block::startTransaction(uint32_t type, bool forceWr, bool check, rim::Variable* var, int32_t index) {
280 uint32_t count;
281 bool fWr;
282
283 count = 0;
284 fWr = forceWr;
285
286 do {
287 intStartTransaction(type, fWr, check, var, index);
288
289 try {
290 if (check || retryCount_ > 0) checkTransaction();
291 count = retryCount_; // Success
292 } catch (rogue::GeneralError err) {
293 fWr = true; // Stale state is now lost
294
295 // Rethrow the error if this is the final retry, else log warning
296 if ((count + 1) > retryCount_) {
297 bLog_->error("Error on try %" PRIu32 " out of %" PRIu32 ": %s",
298 (count + 1),
299 (retryCount_ + 1),
300 err.what());
301 throw err;
302 } else {
303 bLog_->warning("Error on try %" PRIu32 " out of %" PRIu32 ": %s",
304 (count + 1),
305 (retryCount_ + 1),
306 err.what());
307 }
308 }
309 } while (count++ < retryCount_);
310}
311
312#ifndef NO_PYTHON
313
314// Start a transaction for this block, python version
315void rim::Block::startTransactionPy(uint32_t type, bool forceWr, bool check, rim::VariablePtr var, int32_t index) {
316 uint32_t count;
317 bool upd;
318 bool fWr;
319
320 if (blockPyTrans_) return;
321
322 count = 0;
323 upd = false;
324 fWr = forceWr;
325
326 do {
327 intStartTransaction(type, fWr, check, var.get(), index);
328
329 try {
330 if (check || retryCount_ > 0) upd = checkTransaction();
331 count = retryCount_; // Success
332 } catch (rogue::GeneralError err) {
333 fWr = true; // Stale state is now lost
334
335 // Rethrow the error if this is the final retry, else log warning
336 if ((count + 1) > retryCount_) {
337 bLog_->error("Error on try %" PRIu32 " out of %" PRIu32 ": %s",
338 (count + 1),
339 (retryCount_ + 1),
340 err.what());
341 throw err;
342 } else {
343 bLog_->warning("Error on try %" PRIu32 " out of %" PRIu32 ": %s",
344 (count + 1),
345 (retryCount_ + 1),
346 err.what());
347 }
348 }
349 } while (count++ < retryCount_);
350
351 if (upd) varUpdate();
352}
353
354#endif
355
356// Check transaction result
357bool rim::Block::checkTransaction() {
358 std::string err;
359 bool locUpdate;
360 uint32_t x;
361
362 {
363 rogue::GilRelease noGil;
364 std::lock_guard<std::mutex> lock(mtx_);
365 waitTransaction(0);
366
367 err = getError();
368 clearError();
369
370 if (err != "") {
371 throw(rogue::GeneralError::create("Block::checkTransaction",
372 "Transaction error for block %s with address 0x%.8x. Error %s",
373 path_.c_str(),
374 address(),
375 err.c_str()));
376 }
377
378 // Device is disabled
379 if (!enable_) return false;
380
381 // Check verify data if verifyInp is set
382 if (verifyInp_) {
383 bLog_->debug("Verfying data. Base=0x%" PRIx32 ", size=%" PRIu32, verifyBase_, verifySize_);
384 verifyReq_ = false;
385 verifyInp_ = false;
386
387 for (x = verifyBase_; x < verifyBase_ + verifySize_; x++) {
388 if ((verifyData_[x] & verifyMask_[x]) != (blockData_[x] & verifyMask_[x])) {
389 throw(rogue::GeneralError::create("Block::checkTransaction",
390 "Verify error for block %s with address 0x%.8" PRIx64
391 ". Byte: %" PRIu32 ". Got: 0x%.2" PRIx8 ", Exp: 0x%.2" PRIx8
392 ", Mask: 0x%.2" PRIx8,
393 path_.c_str(),
394 address(),
395 x,
396 verifyData_[x],
397 blockData_[x],
398 verifyMask_[x]));
399 }
400 }
401 }
402 bLog_->debug("Transaction complete");
403
404 locUpdate = doUpdate_;
405 doUpdate_ = false;
406 }
407 return locUpdate;
408}
409
410#ifndef NO_PYTHON
411
412// Check transaction result
413void rim::Block::checkTransactionPy() {
414 if (blockPyTrans_) return;
415
416 if (checkTransaction()) varUpdate();
417}
418
419#endif
420
421// Write sequence
422void rim::Block::write(rim::Variable* var, int32_t index) {
423 startTransaction(rim::Write, true, false, var, index);
424 startTransaction(rim::Verify, false, false, var, index);
425 checkTransaction();
426}
427
428// Read sequence
429void rim::Block::read(rim::Variable* var, int32_t index) {
430 startTransaction(rim::Read, false, false, var, index);
431 checkTransaction();
432}
433
434#ifndef NO_PYTHON
435
436// Call variable update for all variables
437void rim::Block::varUpdate() {
438 std::vector<rim::VariablePtr>::iterator vit;
439
441
442 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
443 if ((*vit)->updateNotify_) (*vit)->queueUpdate();
444 }
445}
446
447#endif
448
449// Add variables to block
450void rim::Block::addVariables(std::vector<rim::VariablePtr> variables) {
451 std::vector<rim::VariablePtr>::iterator vit;
452
453 uint32_t x;
454
455 uint8_t excMask[size_];
456 uint8_t oleMask[size_];
457
458 memset(excMask, 0, size_);
459 memset(oleMask, 0, size_);
460
461 variables_ = variables;
462
463 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
464 (*vit)->block_ = this;
465
466 if (vit == variables_.begin()) {
467 path_ = (*vit)->path_;
468 std::string logName = "memory.block." + path_;
469 bLog_ = rogue::Logging::create(logName.c_str());
470 mode_ = (*vit)->mode_;
471 }
472
473 if ((*vit)->bulkOpEn_) bulkOpEn_ = true;
474 if ((*vit)->updateNotify_) updateEn_ = true;
475
476 // Retry count
477 if ((*vit)->retryCount_ > retryCount_) retryCount_ = (*vit)->retryCount_;
478
479 // If variable modes mismatch, set block to read/write
480 if (mode_ != (*vit)->mode_) mode_ = "RW";
481
482 // Update variable masks for standard variable
483 if ((*vit)->numValues_ == 0) {
484 for (x = 0; x < (*vit)->bitOffset_.size(); x++) {
485 // Variable allows overlaps, add to overlap enable mask
486 if ((*vit)->overlapEn_) {
487 setBits(oleMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
488
489 // Otherwise add to exclusive mask and check for existing mapping
490 } else {
491 if (anyBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]))
493 "Block::addVariables",
494 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
495 path_.c_str(),
496 address(),
497 (*vit)->name_.c_str()));
498
499 setBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
500 }
501
502 // update verify mask
503 if ((*vit)->mode_ == "RW" && (*vit)->verifyEn_) {
504 verifyEn_ = true;
505 setBits(verifyMask_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
506 }
507
508 // update verify block
509 if ((*vit)->mode_ == "RO" || (*vit)->mode_ == "WO" || !(*vit)->verifyEn_) {
510 setBits(verifyBlock_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
511 }
512
513 bLog_->debug(
514 "Adding variable %s to block %s at offset 0x%.8x, bitIdx=%i, bitOffset %i, bitSize %i, mode %s, "
515 "verifyEn "
516 "%d " PRIx64,
517 (*vit)->name_.c_str(),
518 path_.c_str(),
519 offset_,
520 x,
521 (*vit)->bitOffset_[x],
522 (*vit)->bitSize_[x],
523 (*vit)->mode_.c_str(),
524 (*vit)->verifyEn_);
525 }
526
527 // List variables
528 } else {
529 for (x = 0; x < (*vit)->numValues_; x++) {
530 // Variable allows overlaps, add to overlap enable mask
531 if ((*vit)->overlapEn_) {
532 setBits(oleMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
533
534 // Otherwise add to exclusive mask and check for existing mapping
535 } else {
536 if (anyBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_))
538 "Block::addVariables",
539 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
540 path_.c_str(),
541 address(),
542 (*vit)->name_.c_str()));
543
544 setBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
545 }
546
547 // update verify mask
548 if ((*vit)->mode_ == "RW" && (*vit)->verifyEn_) {
549 verifyEn_ = true;
550 setBits(verifyMask_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
551 }
552
553 // update verify block
554 if ((*vit)->mode_ == "RO" || (*vit)->mode_ == "WO" || !(*vit)->verifyEn_) {
555 setBits(verifyBlock_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
556 }
557
558 bLog_->debug(
559 "Adding variable %s to block %s at offset 0x%.8x, index=%i, valueOffset=%i, valueBits %i, mode %s, "
560 "verifyEn %d",
561 (*vit)->name_.c_str(),
562 path_.c_str(),
563 offset_,
564 x,
565 x * (*vit)->valueStride_ + (*vit)->bitOffset_[0],
566 (*vit)->valueBits_,
567 (*vit)->mode_.c_str(),
568 (*vit)->verifyEn_);
569 }
570 }
571 }
572
573 // Check for overlaps by anding exclusive and overlap bit vectors
574 for (x = 0; x < size_; x++) {
575 if (oleMask[x] & excMask[x])
576 throw(rogue::GeneralError::create("Block::addVariables",
577 "Variable bit mask overlap detected for block %s with address 0x%.8x",
578 path_.c_str(),
579 address()));
580
581 // Update very mask using verify block
582 verifyMask_[x] &= (verifyBlock_[x] ^ 0xFF);
583 }
584
585 // Execute custom init
586 customInit();
587
588 // Debug the results of the build
589 std::stringstream ss;
590 uint32_t rem = size_;
591 uint32_t idx;
592 idx = 0;
593 x = 0;
594
595 while (rem > 0) {
596 ss << "0x" << std::setfill('0') << std::hex << std::setw(2) << static_cast<uint32_t>(verifyMask_[x]) << " ";
597 x++;
598 rem--;
599 if (rem == 0 || x % 10 == 0) {
600 bLog_->debug("Done adding variables. Verify Mask %.3i - %.3i: %s", idx, x - 1, ss.str().c_str());
601 ss.str("");
602 idx = x;
603 }
604 }
605}
606
607#ifndef NO_PYTHON
608
609// Add variables to block
610void rim::Block::addVariablesPy(bp::object variables) {
611 std::vector<rim::VariablePtr> vars = py_list_to_std_vector<rim::VariablePtr>(variables);
612 addVariables(vars);
613}
614
615#endif
616
618std::vector<rim::VariablePtr> rim::Block::variables() {
619 return variables_;
620}
621
622#ifndef NO_PYTHON
623
625bp::object rim::Block::variablesPy() {
626 return std_vector_to_py_list<rim::VariablePtr>(variables_);
627}
628
629#endif
630
631// byte reverse
632void rim::Block::reverseBytes(uint8_t* data, uint32_t byteSize) {
633 uint32_t x;
634 uint8_t tmp;
635
636 for (x = 0; x < byteSize / 2; x++) {
637 tmp = data[x];
638 data[x] = data[byteSize - x - 1];
639 data[byteSize - x - 1] = tmp;
640 }
641}
642
643// Set data from pointer to internal staged memory
644void rim::Block::setBytes(const uint8_t* data, rim::Variable* var, uint32_t index) {
645 uint32_t srcBit;
646 uint32_t x;
647 uint8_t tmp;
648 uint8_t* buff;
649
650 rogue::GilRelease noGil;
651 std::lock_guard<std::mutex> lock(mtx_);
652
653 // Set stale flag
654 if (var->mode_ != "RO") stale_ = true;
655
656 // Change byte order, need to make a copy
657 if (var->byteReverse_) {
658 buff = reinterpret_cast<uint8_t*>(malloc(var->valueBytes_));
659 memcpy(buff, data, var->valueBytes_);
660 reverseBytes(buff, var->valueBytes_);
661 } else {
662 buff = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(data));
663 }
664
665 // List variable
666 if (var->numValues_ != 0) {
667 // Verify range
668 if (index < 0 || index >= var->numValues_)
669 throw(rogue::GeneralError::create("Block::setBytes",
670 "Index %" PRIu32 " is out of range for %s",
671 index,
672 var->name_.c_str()));
673
674 // Fast copy
675 if (var->fastByte_ != NULL)
676 memcpy(blockData_ + var->fastByte_[index], buff, var->valueBytes_);
677
678 else
679 copyBits(blockData_, var->bitOffset_[0] + (index * var->valueStride_), buff, 0, var->valueBits_);
680
681 if (var->mode_ != "RO") {
682 if (var->stale_) {
683 if (var->lowTranByte_[index] < var->staleLowByte_) var->staleLowByte_ = var->lowTranByte_[index];
684
685 if (var->highTranByte_[index] > var->staleHighByte_) var->staleHighByte_ = var->highTranByte_[index];
686 } else {
687 var->staleLowByte_ = var->lowTranByte_[index];
688 var->staleHighByte_ = var->highTranByte_[index];
689 }
690 }
691
692 // Standard variable
693 } else {
694 if (var->mode_ != "RO") {
695 var->staleLowByte_ = var->lowTranByte_[0];
696 var->staleHighByte_ = var->highTranByte_[0];
697 }
698
699 // Fast copy
700 if (var->fastByte_ != NULL) {
701 memcpy(blockData_ + var->fastByte_[0], buff, var->valueBytes_);
702
703 } else if (var->bitOffset_.size() == 1) {
704 copyBits(blockData_, var->bitOffset_[0], buff, 0, var->bitSize_[0]);
705
706 } else {
707 srcBit = 0;
708 for (x = 0; x < var->bitOffset_.size(); x++) {
709 copyBits(blockData_, var->bitOffset_[x], buff, srcBit, var->bitSize_[x]);
710 srcBit += var->bitSize_[x];
711 }
712 }
713 }
714 if ( var->mode_ != "RO" ) var->stale_ = true;
715 if (var->byteReverse_) free(buff);
716}
717
718// Get data to pointer from internal block or staged memory
719void rim::Block::getBytes(uint8_t* data, rim::Variable* var, uint32_t index) {
720 uint32_t dstBit;
721 uint32_t x;
722
723 rogue::GilRelease noGil;
724 std::lock_guard<std::mutex> lock(mtx_);
725
726 // List variable
727 if (var->numValues_ != 0) {
728 // Verify range
729 if (index < 0 || index >= var->numValues_)
730 throw(rogue::GeneralError::create("Block::getBytes",
731 "Index %" PRIu32 " is out of range for %s",
732 index,
733 var->name_.c_str()));
734
735 // Fast copy
736 if (var->fastByte_ != NULL)
737 memcpy(data, blockData_ + var->fastByte_[index], var->valueBytes_);
738
739 else
740 copyBits(data, 0, blockData_, var->bitOffset_[0] + (index * var->valueStride_), var->valueBits_);
741
742 } else {
743 // Fast copy
744 if (var->fastByte_ != NULL) {
745 memcpy(data, blockData_ + var->fastByte_[0], var->valueBytes_);
746
747 } else if (var->bitOffset_.size() == 1) {
748 copyBits(data, 0, blockData_, var->bitOffset_[0], var->bitSize_[0]);
749
750 } else {
751 dstBit = 0;
752 for (x = 0; x < var->bitOffset_.size(); x++) {
753 copyBits(data, dstBit, blockData_, var->bitOffset_[x], var->bitSize_[x]);
754 dstBit += var->bitSize_[x];
755 }
756 }
757 }
758
759 // Change byte order
760 if (var->byteReverse_) {
761 reverseBytes(data, var->valueBytes_);
762 }
763}
764
766// Python functions
768
769#ifndef NO_PYTHON
770
771// Set data using python function
772void rim::Block::setPyFunc(bp::object& value, rim::Variable* var, int32_t index) {
773 uint32_t x;
774 Py_buffer valueBuf;
775 bp::object tmp;
776
777 if (index == -1) index = 0;
778
779 // Passed value is a numpy value
780 if (PyArray_Check(value.ptr())) {
781 throw(rogue::GeneralError::create("Block::setPyFunc",
782 "Passing ndarray not supported for %s",
783 var->name_.c_str()));
784
785 // Is passed value a list
786 } else if (PyList_Check(value.ptr())) {
787 bp::list vl = bp::extract<bp::list>(value);
788 uint32_t vlen = len(vl);
789
790 if ((index + vlen) > var->numValues_)
791 throw(rogue::GeneralError::create("Block::setPyFunc",
792 "Overflow error for passed array with length %" PRIu32
793 " at index %" PRIu32 ". Variable length = %" PRIu32 " for %s",
794 vlen,
795 index,
796 var->numValues_,
797 var->name_.c_str()));
798
799 for (x = 0; x < vlen; x++) {
800 tmp = vl[x];
801 bp::object ret = ((rim::VariableWrap*)var)->toBytes(tmp);
802
803 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
804 throw(rogue::GeneralError::create("Block::setPyFunc",
805 "Failed to extract byte array for %s",
806 var->name_.c_str()));
807
808 setBytes(reinterpret_cast<uint8_t*>(valueBuf.buf), var, index + x);
809 PyBuffer_Release(&valueBuf);
810 }
811
812 // Single value
813 } else {
814 // Call python function
815 bp::object ret = ((rim::VariableWrap*)var)->toBytes(value);
816
817 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
818 throw(rogue::GeneralError::create("Block::setPyFunc",
819 "Failed to extract byte array from pyFunc return value for %s",
820 var->name_.c_str()));
821
822 setBytes(reinterpret_cast<uint8_t*>(valueBuf.buf), var, index);
823 PyBuffer_Release(&valueBuf);
824 }
825}
826
827// Get data using python function
828bp::object rim::Block::getPyFunc(rim::Variable* var, int32_t index) {
829 uint8_t getBuffer[var->valueBytes_];
830
831 // Unindexed with a list variable not supported
832 if (index < 0 && var->numValues_ > 0) {
833 throw(rogue::GeneralError::create("Block::getPyFunc",
834 "Accessing unindexed value not support for %s",
835 var->name_.c_str()));
836
837 // Single value
838 } else {
839 memset(getBuffer, 0, var->valueBytes_);
840
841 getBytes(getBuffer, var, index);
842 PyObject* val = Py_BuildValue("y#", getBuffer, var->valueBytes_);
843
844 if (val == NULL) throw(rogue::GeneralError::create("Block::getPyFunc", "Failed to generate bytearray"));
845
846 bp::handle<> handle(val);
847 bp::object pass = bp::object(handle);
848
849 return ((rim::VariableWrap*)var)->fromBytes(pass);
850 }
851}
852
853#endif
854
856// Byte Array
858
859#ifndef NO_PYTHON
860
861// Set data using byte array
862void rim::Block::setByteArrayPy(bp::object& value, rim::Variable* var, int32_t index) {
863 Py_buffer valueBuf;
864
865 // Unindexed with a list variable
866 if (index < 0 && var->numValues_ > 0)
867 throw(rogue::GeneralError::create("Block::setByteArrayPy",
868 "Accessing unindexed value not supported for %s",
869 var->name_.c_str()));
870
871 if (PyObject_GetBuffer(value.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
872 throw(rogue::GeneralError::create("Block::setByteArray",
873 "Failed to extract byte array for %s",
874 var->name_.c_str()));
875
876 setBytes(reinterpret_cast<uint8_t*>(valueBuf.buf), var, index);
877 PyBuffer_Release(&valueBuf);
878}
879
880// Get data using byte array
881bp::object rim::Block::getByteArrayPy(rim::Variable* var, int32_t index) {
882 uint8_t getBuffer[var->valueBytes_];
883
884 // Unindexed with a list variable
885 if (index < 0 && var->numValues_ > 0)
886 throw(rogue::GeneralError::create("Block::setByteArrayPy",
887 "Accessing unindexed value not supported for %s",
888 var->name_.c_str()));
889
890 memset(getBuffer, 0, var->valueBytes_);
891
892 getBytes(getBuffer, var, index);
893 PyObject* val = Py_BuildValue("y#", getBuffer, var->valueBytes_);
894
895 if (val == NULL) throw(rogue::GeneralError::create("Block::setByteArrayPy", "Failed to generate bytearray"));
896
897 bp::handle<> handle(val);
898 return bp::object(handle);
899}
900
901#endif
902
903// Set data using byte array
904void rim::Block::setByteArray(const uint8_t* value, rim::Variable* var, int32_t index) {
905 setBytes(value, var, index);
906}
907
908// Get data using byte array
909void rim::Block::getByteArray(uint8_t* value, rim::Variable* var, int32_t index) {
910 getBytes(value, var, index);
911}
912
914// Unsigned Int
916
917#ifndef NO_PYTHON
918
919// Set data using unsigned int
920void rim::Block::setUIntPy(bp::object& value, rim::Variable* var, int32_t index) {
921 if (index == -1) index = 0;
922
923 // Lambda to process an array of unsigned values.
924 auto process_uint_array = [&](auto* src, npy_intp stride, npy_intp length) {
925 for (npy_intp i = 0; i < length; ++i) {
926 setUInt(src[i * stride], var, index + i);
927 }
928 };
929
930 // Passed value is a numpy value
931 if (PyArray_Check(value.ptr())) {
932 // Cast to an array object and check that the numpy array
933 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(value.ptr());
934 npy_intp ndims = PyArray_NDIM(arr);
935 npy_intp* dims = PyArray_SHAPE(arr);
936 npy_intp* strides = PyArray_STRIDES(arr);
937 if (ndims != 1)
938 throw(rogue::GeneralError::create("Block::setUIntPy",
939 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
940 ndims,
941 var->name_.c_str()));
942
943 if ((index + dims[0]) > var->numValues_)
944 throw(rogue::GeneralError::create("Block::setUIntPy",
945 "Overflow error for passed array with length %" PRIu32
946 " at index %" PRIu32 ". Variable length = %" PRIu32 " for %s",
947 dims[0],
948 index,
949 var->numValues_,
950 var->name_.c_str()));
951
952 int type = PyArray_TYPE(arr);
953 switch (type) {
954 case NPY_UINT64: {
955 uint64_t* src = reinterpret_cast<uint64_t*>(PyArray_DATA(arr));
956 npy_intp stride = strides[0] / sizeof(uint64_t);
957 process_uint_array(src, stride, dims[0]);
958 break;
959 }
960 case NPY_UINT32: {
961 uint32_t* src = reinterpret_cast<uint32_t*>(PyArray_DATA(arr));
962 npy_intp stride = strides[0] / sizeof(uint32_t);
963 process_uint_array(src, stride, dims[0]);
964 break;
965 }
966 case NPY_UINT16: {
967 uint16_t* src = reinterpret_cast<uint16_t*>(PyArray_DATA(arr));
968 npy_intp stride = strides[0] / sizeof(uint16_t);
969 process_uint_array(src, stride, dims[0]);
970 break;
971 }
972 case NPY_UINT8: {
973 uint8_t* src = reinterpret_cast<uint8_t*>(PyArray_DATA(arr));
974 npy_intp stride = strides[0] / sizeof(uint8_t);
975 process_uint_array(src, stride, dims[0]);
976 break;
977 }
978 default:
979 throw(rogue::GeneralError::create("Block::setUIntPy",
980 "Passed nparray is not of an accepted unsigned int type (uint64, uint32, uint16, uint8) for %s",
981 var->name_.c_str()));
982 }
983
984 // Is passed value a list
985 } else if (PyList_Check(value.ptr())) {
986 bp::list vl = bp::extract<bp::list>(value);
987 uint32_t vlen = len(vl);
988 if ((index + vlen) > var->numValues_)
989 throw(rogue::GeneralError::create("Block::setUIntPy",
990 "Overflow error for passed list with length %" PRIu32
991 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
992 vlen,
993 index,
994 var->numValues_,
995 var->name_.c_str()));
996 for (uint32_t i = 0; i < vlen; i++) {
997 bp::extract<uint64_t> tmp(vl[i]);
998 if (!tmp.check())
999 throw(rogue::GeneralError::create("Block::setUIntPy",
1000 "Failed to extract value for %s.",
1001 var->name_.c_str()));
1002 setUInt(tmp, var, index + i);
1003 }
1004
1005 // Passed scalar numpy value
1006 } else if (PyArray_CheckScalar(value.ptr())) {
1007 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1008 switch (type_num) {
1009 case NPY_UINT64: {
1010 uint64_t val;
1011 PyArray_ScalarAsCtype(value.ptr(), &val);
1012 setUInt(val, var, index);
1013 break;
1014 }
1015 case NPY_UINT32: {
1016 uint32_t val;
1017 PyArray_ScalarAsCtype(value.ptr(), &val);
1018 setUInt(val, var, index);
1019 break;
1020 }
1021 case NPY_UINT16: {
1022 uint16_t val;
1023 PyArray_ScalarAsCtype(value.ptr(), &val);
1024 setUInt(val, var, index);
1025 break;
1026 }
1027 case NPY_UINT8: {
1028 uint8_t val;
1029 PyArray_ScalarAsCtype(value.ptr(), &val);
1030 setUInt(val, var, index);
1031 break;
1032 }
1033 default:
1034 throw(rogue::GeneralError::create("Block::setUIntPy",
1035 "Failed to extract scalar unsigned int value for %s.",
1036 var->name_.c_str()));
1037 }
1038 } else {
1039 bp::extract<uint64_t> tmp(value);
1040 if (!tmp.check())
1041 throw(rogue::GeneralError::create("Block::setUIntPy", "Failed to extract value for %s.", var->name_.c_str()));
1042 setUInt(tmp, var, index);
1043 }
1044}
1045
1046// Get data using unsigned int
1047bp::object rim::Block::getUIntPy(rim::Variable* var, int32_t index) {
1048 bp::object ret;
1049
1050 // Unindexed with a list variable
1051 if (index < 0 && var->numValues_ > 0) {
1052 // Create a numpy array to receive it and locate the destination data buffer
1053 npy_intp dims[1] = {var->numValues_};
1054 int npType;
1055 // Choose numpy type based on the variable's valueBits.
1056 if (var->valueBits_ <= 8) {
1057 npType = NPY_UINT8;
1058 } else if (var->valueBits_ <= 16) {
1059 npType = NPY_UINT16;
1060 } else if (var->valueBits_ <= 32) {
1061 npType = NPY_UINT32;
1062 } else {
1063 npType = NPY_UINT64;
1064 }
1065
1066 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1067 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1068 uint32_t x;
1069 switch (npType) {
1070 case NPY_UINT8: {
1071 uint8_t* dst = reinterpret_cast<uint8_t*>(PyArray_DATA(arr));
1072 for (x = 0; x < var->numValues_; x++) {
1073 dst[x] = static_cast<uint8_t>(getUInt(var, x));
1074 }
1075 break;
1076 }
1077 case NPY_UINT16: {
1078 uint16_t* dst = reinterpret_cast<uint16_t*>(PyArray_DATA(arr));
1079 for (x = 0; x < var->numValues_; x++) {
1080 dst[x] = static_cast<uint16_t>(getUInt(var, x));
1081 }
1082 break;
1083 }
1084 case NPY_UINT32: {
1085 uint32_t* dst = reinterpret_cast<uint32_t*>(PyArray_DATA(arr));
1086 for (x = 0; x < var->numValues_; x++) {
1087 dst[x] = static_cast<uint32_t>(getUInt(var, x));
1088 }
1089 break;
1090 }
1091 case NPY_UINT64: {
1092 uint64_t* dst = reinterpret_cast<uint64_t*>(PyArray_DATA(arr));
1093 for (x = 0; x < var->numValues_; x++) {
1094 dst[x] = getUInt(var, x);
1095 }
1096 break;
1097 }
1098 }
1099 boost::python::handle<> handle(obj);
1100 ret = bp::object(handle);
1101 } else {
1102 PyObject* val = Py_BuildValue("K", getUInt(var, index));
1103 if (val == NULL)
1104 throw(rogue::GeneralError::create("Block::getUIntPy", "Failed to generate UInt"));
1105 bp::handle<> handle(val);
1106 ret = bp::object(handle);
1107 }
1108 return ret;
1109}
1110
1111#endif
1112
1113// Set data using unsigned int
1114void rim::Block::setUInt(const uint64_t& val, rim::Variable* var, int32_t index) {
1115 // Check range
1116 if ((var->minValue_ != 0 || var->maxValue_ != 0) && (val > var->maxValue_ || val < var->minValue_))
1117 throw(rogue::GeneralError::create("Block::setUInt",
1118 "Value range error for %s. Value=%" PRIu64 ", Min=%f, Max=%f",
1119 var->name_.c_str(),
1120 val,
1121 var->minValue_,
1122 var->maxValue_));
1123
1124 setBytes(reinterpret_cast<uint8_t*>(const_cast<uint64_t*>(&val)), var, index);
1125}
1126
1127// Get data using unsigned int
1128uint64_t rim::Block::getUInt(rim::Variable* var, int32_t index) {
1129 uint64_t tmp = 0;
1130
1131 getBytes(reinterpret_cast<uint8_t*>(&tmp), var, index);
1132
1133 return tmp;
1134}
1135
1137// Signed Int
1139
1140#ifndef NO_PYTHON
1141
1142// Set data using int
1143void rim::Block::setIntPy(bp::object& value, rim::Variable* var, int32_t index) {
1144 if (index == -1) index = 0;
1145
1146 // Lambda to process an array of signed values.
1147 auto process_int_array = [&](auto* src, npy_intp stride, npy_intp length) {
1148 for (npy_intp i = 0; i < length; ++i) {
1149 setInt(src[i * stride], var, index + i);
1150 }
1151 };
1152
1153 // Passed value is a numpy value
1154 if (PyArray_Check(value.ptr())) {
1155 // Cast to an array object and check that the numpy array
1156 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(value.ptr());
1157 npy_intp ndims = PyArray_NDIM(arr);
1158 npy_intp* dims = PyArray_SHAPE(arr);
1159 npy_intp* strides = PyArray_STRIDES(arr);
1160 if (ndims != 1)
1161 throw(rogue::GeneralError::create("Block::setIntPy",
1162 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
1163 ndims,
1164 var->name_.c_str()));
1165
1166 if ((index + dims[0]) > var->numValues_)
1167 throw(rogue::GeneralError::create("Block::setIntPy",
1168 "Overflow error for passed array with length %" PRIu32
1169 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1170 dims[0],
1171 index,
1172 var->numValues_,
1173 var->name_.c_str()));
1174
1175 int type = PyArray_TYPE(arr);
1176 switch (type) {
1177 case NPY_INT64: {
1178 int64_t* src = reinterpret_cast<int64_t*>(PyArray_DATA(arr));
1179 npy_intp stride = strides[0] / sizeof(int64_t);
1180 process_int_array(src, stride, dims[0]);
1181 break;
1182 }
1183 case NPY_INT32: {
1184 int32_t* src = reinterpret_cast<int32_t*>(PyArray_DATA(arr));
1185 npy_intp stride = strides[0] / sizeof(int32_t);
1186 process_int_array(src, stride, dims[0]);
1187 break;
1188 }
1189 case NPY_INT16: {
1190 int16_t* src = reinterpret_cast<int16_t*>(PyArray_DATA(arr));
1191 npy_intp stride = strides[0] / sizeof(int16_t);
1192 process_int_array(src, stride, dims[0]);
1193 break;
1194 }
1195 case NPY_INT8: {
1196 int8_t* src = reinterpret_cast<int8_t*>(PyArray_DATA(arr));
1197 npy_intp stride = strides[0] / sizeof(int8_t);
1198 process_int_array(src, stride, dims[0]);
1199 break;
1200 }
1201 default:
1202 throw(rogue::GeneralError::create("Block::setIntPy",
1203 "Passed nparray is not of an accepted signed int type (int64, int32, int16, int8) for %s",
1204 var->name_.c_str()));
1205 }
1206
1207 // Is passed value a list
1208 } else if (PyList_Check(value.ptr())) {
1209 bp::list vl = bp::extract<bp::list>(value);
1210 uint32_t vlen = len(vl);
1211
1212 if ((index + vlen) > var->numValues_)
1213 throw(rogue::GeneralError::create("Block::setIntPy",
1214 "Overflow error for passed list with length %" PRIu32
1215 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1216 vlen,
1217 index,
1218 var->numValues_,
1219 var->name_.c_str()));
1220 for (uint32_t i = 0; i < vlen; i++) {
1221 bp::extract<int64_t> tmp(vl[i]);
1222 if (!tmp.check())
1223 throw(rogue::GeneralError::create("Block::setIntPy",
1224 "Failed to extract value for %s.",
1225 var->name_.c_str()));
1226 setInt(tmp, var, index + i);
1227 }
1228
1229 // Passed scalar numpy value
1230 } else if (PyArray_CheckScalar(value.ptr())) {
1231 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1232 switch (type_num) {
1233 case NPY_INT64: {
1234 int64_t val;
1235 PyArray_ScalarAsCtype(value.ptr(), &val);
1236 setInt(val, var, index);
1237 break;
1238 }
1239 case NPY_INT32: {
1240 int32_t val;
1241 PyArray_ScalarAsCtype(value.ptr(), &val);
1242 setInt(val, var, index);
1243 break;
1244 }
1245 case NPY_INT16: {
1246 int16_t val;
1247 PyArray_ScalarAsCtype(value.ptr(), &val);
1248 setInt(val, var, index);
1249 break;
1250 }
1251 case NPY_INT8: {
1252 int8_t val;
1253 PyArray_ScalarAsCtype(value.ptr(), &val);
1254 setInt(val, var, index);
1255 break;
1256 }
1257 default:
1258 throw(rogue::GeneralError::create("Block::setIntPy",
1259 "Failed to extract scalar signed int value for %s.",
1260 var->name_.c_str()));
1261 }
1262 } else {
1263 bp::extract<int64_t> tmp(value);
1264
1265 if (!tmp.check())
1266 throw(rogue::GeneralError::create("Block::setIntPy", "Failed to extract value for %s.", var->name_.c_str()));
1267 setInt(tmp, var, index);
1268 }
1269}
1270
1271// Get data using int
1272bp::object rim::Block::getIntPy(rim::Variable* var, int32_t index) {
1273 bp::object ret;
1274
1275 // Unindexed with a list variable
1276 if (index < 0 && var->numValues_ > 0) {
1277 // Create a numpy array to receive it and locate the destination data buffer
1278 npy_intp dims[1] = {var->numValues_};
1279 int npType;
1280 if (var->valueBits_ <= 8) {
1281 npType = NPY_INT8;
1282 } else if (var->valueBits_ <= 16) {
1283 npType = NPY_INT16;
1284 } else if (var->valueBits_ <= 32) {
1285 npType = NPY_INT32;
1286 } else {
1287 npType = NPY_INT64;
1288 }
1289 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1290 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1291 uint32_t x;
1292 switch (npType) {
1293 case NPY_INT8: {
1294 int8_t* dst = reinterpret_cast<int8_t*>(PyArray_DATA(arr));
1295 for (x = 0; x < var->numValues_; x++) {
1296 dst[x] = static_cast<int8_t>(getInt(var, x));
1297 }
1298 break;
1299 }
1300 case NPY_INT16: {
1301 int16_t* dst = reinterpret_cast<int16_t*>(PyArray_DATA(arr));
1302 for (x = 0; x < var->numValues_; x++) {
1303 dst[x] = static_cast<int16_t>(getInt(var, x));
1304 }
1305 break;
1306 }
1307 case NPY_INT32: {
1308 int32_t* dst = reinterpret_cast<int32_t*>(PyArray_DATA(arr));
1309 for (x = 0; x < var->numValues_; x++) {
1310 dst[x] = static_cast<int32_t>(getInt(var, x));
1311 }
1312 break;
1313 }
1314 case NPY_INT64: {
1315 int64_t* dst = reinterpret_cast<int64_t*>(PyArray_DATA(arr));
1316 for (x = 0; x < var->numValues_; x++) {
1317 dst[x] = getInt(var, x);
1318 }
1319 break;
1320 }
1321 }
1322 boost::python::handle<> handle(obj);
1323 ret = bp::object(handle);
1324 } else {
1325 PyObject* val = Py_BuildValue("L", getInt(var, index));
1326 if (val == NULL)
1327 throw(rogue::GeneralError::create("Block::getIntPy", "Failed to generate Int"));
1328 bp::handle<> handle(val);
1329 ret = bp::object(handle);
1330 }
1331 return ret;
1332}
1333
1334#endif
1335
1336// Set data using int
1337void rim::Block::setInt(const int64_t& val, rim::Variable* var, int32_t index) {
1338 // Check range
1339 if ((var->minValue_ != 0 || var->maxValue_ != 0) && (val > var->maxValue_ || val < var->minValue_))
1340 throw(rogue::GeneralError::create("Block::setInt",
1341 "Value range error for %s. Value=%" PRId64 ", Min=%f, Max=%f",
1342 var->name_.c_str(),
1343 val,
1344 var->minValue_,
1345 var->maxValue_));
1346
1347 // This works because all bits between the msb and bit 64 are set to '1' for a negative value
1348 setBytes(reinterpret_cast<uint8_t*>(const_cast<int64_t*>(&val)), var, index);
1349}
1350
1351// Get data using int
1352int64_t rim::Block::getInt(rim::Variable* var, int32_t index) {
1353 int64_t tmp = 0;
1354
1355 getBytes(reinterpret_cast<uint8_t*>(&tmp), var, index);
1356
1357 if (var->valueBits_ != 64) {
1358 if (tmp >= static_cast<uint64_t>(pow(2, var->valueBits_ - 1))) {
1359 tmp -= static_cast<uint64_t>(pow(2, var->valueBits_));
1360 }
1361 }
1362 return tmp;
1363}
1364
1366// Bool
1368
1369#ifndef NO_PYTHON
1370
1371// Set data using bool
1372void rim::Block::setBoolPy(bp::object& value, rim::Variable* var, int32_t index) {
1373 uint32_t x;
1374
1375 if (index == -1) index = 0;
1376
1377 // Passed value is a numpy value
1378 if (PyArray_Check(value.ptr())) {
1379 // Cast to an array object and check that the numpy array
1380 PyArrayObject* arr = reinterpret_cast<decltype(arr)>(value.ptr());
1381 npy_intp ndims = PyArray_NDIM(arr);
1382 npy_intp* dims = PyArray_SHAPE(arr);
1383 npy_intp* strides = PyArray_STRIDES(arr);
1384
1385 if (ndims != 1)
1386 throw(rogue::GeneralError::create("Block::setBoolPy",
1387 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
1388 ndims,
1389 var->name_.c_str()));
1390
1391 if ((index + dims[0]) > var->numValues_)
1392 throw(rogue::GeneralError::create("Block::setBoolPy",
1393 "Overflow error for passed array with length %" PRIu32
1394 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1395 dims[0],
1396 index,
1397 var->numValues_,
1398 var->name_.c_str()));
1399
1400 if (PyArray_TYPE(arr) == NPY_BOOL) {
1401 bool* src = reinterpret_cast<bool*>(PyArray_DATA(arr));
1402 npy_intp stride = strides[0] / sizeof(bool);
1403 for (x = 0; x < dims[0]; x++) {
1404 setBool(src[x * stride], var, index + x);
1405 }
1406 } else {
1407 throw(rogue::GeneralError::create("Block::setBoolPy",
1408 "Passed nparray is not of type (bool) for %s",
1409 var->name_.c_str()));
1410 }
1411
1412 // Is passed value a list
1413 } else if (PyList_Check(value.ptr())) {
1414 bp::list vl = bp::extract<bp::list>(value);
1415 uint32_t vlen = len(vl);
1416
1417 if ((index + vlen) > var->numValues_)
1418 throw(rogue::GeneralError::create("Block::setBoolPy",
1419 "Overflow error for passed array with length %" PRIu32
1420 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1421 vlen,
1422 index,
1423 var->numValues_,
1424 var->name_.c_str()));
1425
1426 for (x = 0; x < vlen; x++) {
1427 bp::extract<bool> tmp(vl[x]);
1428
1429 if (!tmp.check())
1430 throw(rogue::GeneralError::create("Block::setBoolPy",
1431 "Failed to extract value for %s.",
1432 var->name_.c_str()));
1433
1434 setBool(tmp, var, index + x);
1435 }
1436
1437 // Passed scalar numpy value
1438 } else if (PyArray_CheckScalar(value.ptr())) {
1439 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_BOOL) {
1440 bool val;
1441 PyArray_ScalarAsCtype(value.ptr(), &val);
1442 setBool(val, var, index);
1443 } else {
1444 throw(
1445 rogue::GeneralError::create("Block::setBoolPy", "Failed to extract value for %s.", var->name_.c_str()));
1446 }
1447 } else {
1448 bp::extract<bool> tmp(value);
1449
1450 if (!tmp.check())
1451 throw(
1452 rogue::GeneralError::create("Block::setBoolPy", "Failed to extract value for %s.", var->name_.c_str()));
1453
1454 setBool(tmp, var, index);
1455 }
1456}
1457
1458// Get data using bool
1459bp::object rim::Block::getBoolPy(rim::Variable* var, int32_t index) {
1460 bp::object ret;
1461 uint32_t x;
1462
1463 // Unindexed with a list variable
1464 if (index < 0 && var->numValues_ > 0) {
1465 // Create a numpy array to receive it and locate the destination data buffer
1466 npy_intp dims[1] = {var->numValues_};
1467 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_BOOL);
1468 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1469 bool* dst = reinterpret_cast<bool*>(PyArray_DATA(arr));
1470
1471 for (x = 0; x < var->numValues_; x++) dst[x] = getBool(var, x);
1472
1473 boost::python::handle<> handle(obj);
1474 ret = bp::object(handle);
1475
1476 } else {
1477 bp::handle<> handle(bp::borrowed(getBool(var, index) ? Py_True : Py_False));
1478 ret = bp::object(handle);
1479 }
1480 return ret;
1481}
1482
1483#endif
1484
1485// Set data using bool
1486void rim::Block::setBool(const bool& value, rim::Variable* var, int32_t index) {
1487 uint8_t val = (uint8_t)value;
1488 setBytes(reinterpret_cast<uint8_t*>(&val), var, index);
1489}
1490
1491// Get data using bool
1492bool rim::Block::getBool(rim::Variable* var, int32_t index) {
1493 uint8_t tmp = 0;
1494
1495 getBytes(reinterpret_cast<uint8_t*>(&tmp), var, index);
1496
1497 return tmp ? true : false;
1498}
1499
1501// String
1503
1504#ifndef NO_PYTHON
1505
1506// Set data using string
1507void rim::Block::setStringPy(bp::object& value, rim::Variable* var, int32_t index) {
1508 uint32_t x;
1509 std::string strVal;
1510
1511 // Unindexed with a list variable
1512 if (index < 0 && var->numValues_ > 0)
1513 throw(rogue::GeneralError::create("Block::setStringPy",
1514 "Using nparray not supported for %s",
1515 var->name_.c_str()));
1516
1517 bp::extract<char*> tmp(value);
1518
1519 if (!tmp.check())
1520 throw(rogue::GeneralError::create("Block::setStringPy", "Failed to extract value for %s.", var->name_.c_str()));
1521
1522 strVal = tmp;
1523 setString(strVal, var, index);
1524}
1525
1526// Get data using string
1527bp::object rim::Block::getStringPy(rim::Variable* var, int32_t index) {
1528 bp::object ret;
1529 std::string strVal;
1530 uint32_t x;
1531
1532 // Unindexed with a list variable
1533 if (index < 0 && var->numValues_ > 0)
1534 throw(
1535 rogue::GeneralError::create("Block::getStringPy", "Using ndarry not supported for %s", var->name_.c_str()));
1536
1537 getString(var, strVal, index);
1538 PyObject* val = Py_BuildValue("s", strVal.c_str());
1539
1540 if (val == NULL) throw(rogue::GeneralError::create("Block::getStringPy", "Failed to generate String"));
1541
1542 bp::handle<> handle(val);
1543 return bp::object(handle);
1544}
1545
1546#endif
1547
1548// Set data using string
1549void rim::Block::setString(const std::string& value, rim::Variable* var, int32_t index) {
1550 uint8_t getBuffer[var->valueBytes_];
1551
1552 memset(getBuffer, 0, var->valueBytes_);
1553
1554 strncpy(reinterpret_cast<char*>(getBuffer), value.c_str(), var->valueBytes_ - 1);
1555
1556 setBytes(getBuffer, var, index);
1557}
1558
1559// Get data using string
1560std::string rim::Block::getString(rim::Variable* var, int32_t index) {
1561 std::string ret;
1562 getString(var, ret, index);
1563 return ret;
1564}
1565
1566// Get data into string
1567void rim::Block::getString(rim::Variable* var, std::string& retString, int32_t index) {
1568 char getBuffer[var->valueBytes_ + 1];
1569
1570 memset(getBuffer, 0, var->valueBytes_ + 1);
1571
1572 getBytes(reinterpret_cast<uint8_t*>(getBuffer), var, index);
1573
1574 retString = getBuffer;
1575}
1576
1578// Float
1580
1581#ifndef NO_PYTHON
1582
1583// Set data using float
1584void rim::Block::setFloatPy(bp::object& value, rim::Variable* var, int32_t index) {
1585 uint32_t x;
1586
1587 if (index == -1) index = 0;
1588
1589 // Passed value is a numpy value
1590 if (PyArray_Check(value.ptr())) {
1591 // Cast to an array object and check that the numpy array
1592 PyArrayObject* arr = reinterpret_cast<decltype(arr)>(value.ptr());
1593 npy_intp ndims = PyArray_NDIM(arr);
1594 npy_intp* dims = PyArray_SHAPE(arr);
1595 npy_intp* strides = PyArray_STRIDES(arr);
1596
1597 if (ndims != 1)
1598 throw(rogue::GeneralError::create("Block::setFloatPy",
1599 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
1600 ndims,
1601 var->name_.c_str()));
1602
1603 if ((index + dims[0]) > var->numValues_)
1604 throw(rogue::GeneralError::create("Block::setFloatPy",
1605 "Overflow error for passed array with length %" PRIu32
1606 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1607 dims[0],
1608 index,
1609 var->numValues_,
1610 var->name_.c_str()));
1611
1612 if (PyArray_TYPE(arr) == NPY_FLOAT32) {
1613 float* src = reinterpret_cast<float*>(PyArray_DATA(arr));
1614 npy_intp stride = strides[0] / sizeof(float);
1615 for (x = 0; x < dims[0]; x++) {
1616 setFloat(src[x * stride], var, index + x);
1617 }
1618 } else {
1619 throw(rogue::GeneralError::create("Block::setFLoatPy",
1620 "Passed nparray is not of type (float32) for %s",
1621 var->name_.c_str()));
1622 }
1623
1624 // Is passed value a list
1625 } else if (PyList_Check(value.ptr())) {
1626 bp::list vl = bp::extract<bp::list>(value);
1627 uint32_t vlen = len(vl);
1628
1629 if ((index + vlen) > var->numValues_)
1630 throw(rogue::GeneralError::create("Block::setFloatPy",
1631 "Overflow error for passed array with length %" PRIu32
1632 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1633 vlen,
1634 index,
1635 var->numValues_,
1636 var->name_.c_str()));
1637
1638 for (x = 0; x < vlen; x++) {
1639 bp::extract<float> tmp(vl[x]);
1640
1641 if (!tmp.check())
1642 throw(rogue::GeneralError::create("Block::setFloatPy",
1643 "Failed to extract value for %s.",
1644 var->name_.c_str()));
1645
1646 setFloat(tmp, var, index + x);
1647 }
1648
1649 // Passed scalar numpy value
1650 } else if (PyArray_CheckScalar(value.ptr())) {
1651 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT32) {
1652 float val;
1653 PyArray_ScalarAsCtype(value.ptr(), &val);
1654 setFloat(val, var, index);
1655 } else {
1656 throw(rogue::GeneralError::create("Block::setFloatPy",
1657 "Failed to extract value for %s.",
1658 var->name_.c_str()));
1659 }
1660 } else {
1661 bp::extract<float> tmp(value);
1662
1663 if (!tmp.check())
1664 throw(rogue::GeneralError::create("Block::setFloatPy",
1665 "Failed to extract value for %s.",
1666 var->name_.c_str()));
1667
1668 setFloat(tmp, var, index);
1669 }
1670}
1671
1672// Get data using float
1673bp::object rim::Block::getFloatPy(rim::Variable* var, int32_t index) {
1674 bp::object ret;
1675 uint32_t x;
1676
1677 // Unindexed with a list variable
1678 if (index < 0 && var->numValues_ > 0) {
1679 // Create a numpy array to receive it and locate the destination data buffer
1680 npy_intp dims[1] = {var->numValues_};
1681 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT32);
1682 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1683 float* dst = reinterpret_cast<float*>(PyArray_DATA(arr));
1684
1685 for (x = 0; x < var->numValues_; x++) dst[x] = getFloat(var, x);
1686
1687 boost::python::handle<> handle(obj);
1688 ret = bp::object(handle);
1689
1690 } else {
1691 PyObject* val = Py_BuildValue("f", getFloat(var, index));
1692
1693 if (val == NULL) throw(rogue::GeneralError::create("Block::getFloatPy", "Failed to generate Float"));
1694
1695 bp::handle<> handle(val);
1696 ret = bp::object(handle);
1697 }
1698 return ret;
1699}
1700
1701#endif
1702
1703// Set data using float
1704void rim::Block::setFloat(const float& val, rim::Variable* var, int32_t index) {
1705 // Check range
1706 if ((var->minValue_ != 0 || var->maxValue_ != 0) && (val > var->maxValue_ || val < var->minValue_))
1707 throw(rogue::GeneralError::create("Block::setFloat",
1708 "Value range error for %s. Value=%f, Min=%f, Max=%f",
1709 var->name_.c_str(),
1710 val,
1711 var->minValue_,
1712 var->maxValue_));
1713
1714 setBytes(reinterpret_cast<uint8_t*>(const_cast<float*>(&val)), var, index);
1715}
1716
1717// Get data using float
1718float rim::Block::getFloat(rim::Variable* var, int32_t index) {
1719 float tmp = 0;
1720
1721 getBytes(reinterpret_cast<uint8_t*>(&tmp), var, index);
1722
1723 return tmp;
1724}
1725
1727// Double
1729
1730#ifndef NO_PYTHON
1731
1732// Set data using double
1733void rim::Block::setDoublePy(bp::object& value, rim::Variable* var, int32_t index) {
1734 uint32_t x;
1735
1736 if (index == -1) index = 0;
1737
1738 // Passed value is a numpy value
1739 if (PyArray_Check(value.ptr())) {
1740 // Cast to an array object and check that the numpy array
1741 PyArrayObject* arr = reinterpret_cast<decltype(arr)>(value.ptr());
1742 npy_intp ndims = PyArray_NDIM(arr);
1743 npy_intp* dims = PyArray_SHAPE(arr);
1744 npy_intp* strides = PyArray_STRIDES(arr);
1745
1746 if (ndims != 1)
1747 throw(rogue::GeneralError::create("Block::setDoublePy",
1748 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
1749 ndims,
1750 var->name_.c_str()));
1751
1752 if ((index + dims[0]) > var->numValues_)
1753 throw(rogue::GeneralError::create("Block::setDoublePy",
1754 "Overflow error for passed array with length %" PRIu32
1755 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1756 dims[0],
1757 index,
1758 var->numValues_,
1759 var->name_.c_str()));
1760
1761 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
1762 double* src = reinterpret_cast<double*>(PyArray_DATA(arr));
1763 npy_intp stride = strides[0] / sizeof(double);
1764 for (x = 0; x < dims[0]; x++) {
1765 setDouble(src[x * stride], var, index + x);
1766 }
1767 } else {
1768 throw(rogue::GeneralError::create("Block::setFLoatPy",
1769 "Passed nparray is not of type (double) for %s",
1770 var->name_.c_str()));
1771 }
1772
1773 // Is passed value a list
1774 } else if (PyList_Check(value.ptr())) {
1775 bp::list vl = bp::extract<bp::list>(value);
1776 uint32_t vlen = len(vl);
1777
1778 if ((index + vlen) > var->numValues_)
1779 throw(rogue::GeneralError::create("Block::setDoublePy",
1780 "Overflow error for passed array with length %" PRIu32
1781 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1782 vlen,
1783 index,
1784 var->numValues_,
1785 var->name_.c_str()));
1786
1787 for (x = 0; x < vlen; x++) {
1788 bp::extract<double> tmp(vl[x]);
1789
1790 if (!tmp.check())
1791 throw(rogue::GeneralError::create("Block::setDoublePy",
1792 "Failed to extract value for %s.",
1793 var->name_.c_str()));
1794
1795 setDouble(tmp, var, index + x);
1796 }
1797
1798 // Passed scalar numpy value
1799 } else if (PyArray_CheckScalar(value.ptr())) {
1800 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
1801 double val;
1802 PyArray_ScalarAsCtype(value.ptr(), &val);
1803 setDouble(val, var, index);
1804 } else {
1805 throw(rogue::GeneralError::create("Block::setDoublePy",
1806 "Failed to extract value for %s.",
1807 var->name_.c_str()));
1808 }
1809 } else {
1810 bp::extract<double> tmp(value);
1811
1812 if (!tmp.check())
1813 throw(rogue::GeneralError::create("Block::setDoublePy",
1814 "Failed to extract value for %s.",
1815 var->name_.c_str()));
1816
1817 setDouble(tmp, var, index);
1818 }
1819}
1820
1821// Get data using double
1822bp::object rim::Block::getDoublePy(rim::Variable* var, int32_t index) {
1823 bp::object ret;
1824 uint32_t x;
1825
1826 // Unindexed with a list variable
1827 if (index < 0 && var->numValues_ > 0) {
1828 // Create a numpy array to receive it and locate the destination data buffer
1829 npy_intp dims[1] = {var->numValues_};
1830 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
1831 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1832 double* dst = reinterpret_cast<double*>(PyArray_DATA(arr));
1833
1834 for (x = 0; x < var->numValues_; x++) dst[x] = getDouble(var, x);
1835
1836 boost::python::handle<> handle(obj);
1837 ret = bp::object(handle);
1838
1839 } else {
1840 PyObject* val = Py_BuildValue("d", getDouble(var, index));
1841
1842 if (val == NULL) throw(rogue::GeneralError::create("Block::getDoublePy", "Failed to generate Double"));
1843
1844 bp::handle<> handle(val);
1845 ret = bp::object(handle);
1846 }
1847 return ret;
1848}
1849
1850#endif
1851
1852// Set data using double
1853void rim::Block::setDouble(const double& val, rim::Variable* var, int32_t index) {
1854 // Check range
1855 if ((var->minValue_ != 0 || var->maxValue_ != 0) && (val > var->maxValue_ || val < var->minValue_))
1856 throw(rogue::GeneralError::create("Block::setDouble",
1857 "Value range error for %s. Value=%f, Min=%f, Max=%f",
1858 var->name_.c_str(),
1859 val,
1860 var->minValue_,
1861 var->maxValue_));
1862
1863 setBytes(reinterpret_cast<uint8_t*>(const_cast<double*>(&val)), var, index);
1864}
1865
1866// Get data using double
1867double rim::Block::getDouble(rim::Variable* var, int32_t index) {
1868 double tmp = 0;
1869
1870 getBytes(reinterpret_cast<uint8_t*>(&tmp), var, index);
1871
1872 return tmp;
1873}
1874
1876// Fixed Point
1878
1879#ifndef NO_PYTHON
1880
1881// Set data using fixed point
1882void rim::Block::setFixedPy(bp::object& value, rim::Variable* var, int32_t index) {
1883 uint32_t x;
1884
1885 if (index == -1) index = 0;
1886
1887 // Passed value is a numpy value
1888 if (PyArray_Check(value.ptr())) {
1889 // Cast to an array object and check that the numpy array
1890 PyArrayObject* arr = reinterpret_cast<decltype(arr)>(value.ptr());
1891 npy_intp ndims = PyArray_NDIM(arr);
1892 npy_intp* dims = PyArray_SHAPE(arr);
1893 npy_intp* strides = PyArray_STRIDES(arr);
1894
1895 if (ndims != 1)
1896 throw(rogue::GeneralError::create("Block::setFixedPy",
1897 "Invalid number of dimensions (%" PRIu32 ") for passed ndarray for %s",
1898 ndims,
1899 var->name_.c_str()));
1900
1901 if ((index + dims[0]) > var->numValues_)
1902 throw(rogue::GeneralError::create("Block::setFixedPy",
1903 "Overflow error for passed array with length %" PRIu32
1904 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1905 dims[0],
1906 index,
1907 var->numValues_,
1908 var->name_.c_str()));
1909
1910 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
1911 double* src = reinterpret_cast<double*>(PyArray_DATA(arr));
1912 npy_intp stride = strides[0] / sizeof(double);
1913 for (x = 0; x < dims[0]; x++) {
1914 setFixed(src[x * stride], var, index + x);
1915 }
1916 } else {
1917 throw(rogue::GeneralError::create("Block::setFixedPy",
1918 "Passed nparray is not of type (double) for %s",
1919 var->name_.c_str()));
1920 }
1921
1922 // Is passed value a list
1923 } else if (PyList_Check(value.ptr())) {
1924 bp::list vl = bp::extract<bp::list>(value);
1925 uint32_t vlen = len(vl);
1926
1927 if ((index + vlen) > var->numValues_)
1928 throw(rogue::GeneralError::create("Block::setFixedPy",
1929 "Overflow error for passed array with length %" PRIu32
1930 " at index %" PRIi32 ". Variable length = %" PRIu32 " for %s",
1931 vlen,
1932 index,
1933 var->numValues_,
1934 var->name_.c_str()));
1935
1936 for (x = 0; x < vlen; x++) {
1937 bp::extract<double> tmp(vl[x]);
1938
1939 if (!tmp.check())
1940 throw(rogue::GeneralError::create("Block::setFixedPy",
1941 "Failed to extract value for %s.",
1942 var->name_.c_str()));
1943
1944 setFixed(tmp, var, index + x);
1945 }
1946
1947 // Passed scalar numpy value
1948 } else if (PyArray_CheckScalar(value.ptr())) {
1949 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
1950 double val;
1951 PyArray_ScalarAsCtype(value.ptr(), &val);
1952 setFixed(val, var, index);
1953 } else {
1954 throw(rogue::GeneralError::create("Block::setFixedPy",
1955 "Failed to extract value for %s.",
1956 var->name_.c_str()));
1957 }
1958 } else {
1959 bp::extract<double> tmp(value);
1960
1961 if (!tmp.check())
1962 throw(rogue::GeneralError::create("Block::setFixedPy",
1963 "Failed to extract value for %s.",
1964 var->name_.c_str()));
1965
1966 setFixed(tmp, var, index);
1967 }
1968}
1969
1970// Get data using fixed point
1971bp::object rim::Block::getFixedPy(rim::Variable* var, int32_t index) {
1972 bp::object ret;
1973 uint32_t x;
1974
1975 // Unindexed with a list variable
1976 if (index < 0 && var->numValues_ > 0) {
1977 // Create a numpy array to receive it and locate the destination data buffer
1978 npy_intp dims[1] = {var->numValues_};
1979 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
1980 PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(obj);
1981 double* dst = reinterpret_cast<double*>(PyArray_DATA(arr));
1982
1983 for (x = 0; x < var->numValues_; x++) dst[x] = getFixed(var, x);
1984
1985 boost::python::handle<> handle(obj);
1986 ret = bp::object(handle);
1987
1988 } else {
1989 PyObject* val = Py_BuildValue("d", getFixed(var, index));
1990
1991 if (val == NULL) throw(rogue::GeneralError::create("Block::getFixedPy", "Failed to generate Fixed"));
1992
1993 bp::handle<> handle(val);
1994 ret = bp::object(handle);
1995 }
1996 return ret;
1997}
1998
1999#endif
2000
2001// Set data using fixed point
2002void rim::Block::setFixed(const double& val, rim::Variable* var, int32_t index) {
2003 // Check range
2004 if ((var->minValue_ != 0 || var->maxValue_ != 0) && (val > var->maxValue_ || val < var->minValue_))
2005 throw(rogue::GeneralError::create("Block::setFixed",
2006 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2007 var->name_.c_str(),
2008 val,
2009 var->minValue_,
2010 var->maxValue_));
2011
2012 // Convert
2013 int64_t fPoint = static_cast<int64_t>(round(val * pow(2, var->binPoint_)));
2014 // Check for positive edge case
2015 uint64_t mask = 1 << (var->valueBits_ - 1);
2016 if (val > 0 && ((fPoint & mask) != 0)) {
2017 fPoint -= 1;
2018 }
2019 setBytes(reinterpret_cast<uint8_t*>(&fPoint), var, index);
2020}
2021
2022// Get data using fixed point
2023double rim::Block::getFixed(rim::Variable* var, int32_t index) {
2024 int64_t fPoint = 0;
2025 double tmp;
2026
2027 getBytes(reinterpret_cast<uint8_t*>(&fPoint), var, index);
2028 // Do two-complement if negative
2029 if ((fPoint & (1 << (var->valueBits_ - 1))) != 0) {
2030 fPoint = fPoint - (1 << var->valueBits_);
2031 }
2032
2033 // Convert to float
2034 tmp = static_cast<double>(fPoint);
2035 tmp = tmp / pow(2, var->binPoint_);
2036 return tmp;
2037}
2038
2040// Custom
2042
2043// Custom Init function called after addVariables
2044void rim::Block::customInit() {}
2045
2046// Custom Clean function called before delete
2047void rim::Block::customClean() {}
2048
2049void rim::Block::rateTest() {
2050 uint32_t x;
2051
2052 struct timeval stime;
2053 struct timeval etime;
2054 struct timeval dtime;
2055
2056 uint64_t count = 1000000;
2057 double durr;
2058 double rate;
2059 uint32_t value;
2060
2061 gettimeofday(&stime, NULL);
2062 waitTransaction(0);
2063 for (x = 0; x < count; ++x) {
2064 reqTransaction(0, 4, &value, rim::Read);
2065 waitTransaction(0);
2066 }
2067 gettimeofday(&etime, NULL);
2068
2069 timersub(&etime, &stime, &dtime);
2070 durr = dtime.tv_sec + static_cast<float>(dtime.tv_usec) / 1.0e6;
2071 rate = count / durr;
2072
2073 printf("\nBlock c++ raw: Read %" PRIu64 " times in %f seconds. Rate = %f\n", count, durr, rate);
2074
2075 gettimeofday(&stime, NULL);
2076 waitTransaction(0);
2077 for (x = 0; x < count; ++x) {
2078 reqTransaction(0, 4, reinterpret_cast<uint8_t*>(&count), rim::Write);
2079 waitTransaction(0);
2080 }
2081 gettimeofday(&etime, NULL);
2082
2083 timersub(&etime, &stime, &dtime);
2084 durr = dtime.tv_sec + static_cast<float>(dtime.tv_usec) / 1.0e6;
2085 rate = count / durr;
2086
2087 printf("\nBlock c++ raw: Wrote %" PRIu64 " times in %f seconds. Rate = %f\n", count, durr, rate);
2088}
Generic Rogue exception type.
char const * what() const
Returns exception text for standard exception handling.
static GeneralError create(std::string src, const char *fmt,...)
Creates a formatted error instance.
RAII helper that releases the Python GIL for a scope.
Definition GilRelease.h:36
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
Definition Logging.cpp:60
RAII helper that acquires the Python GIL for a scope.
Definition ScopedGil.h:35
uint32_t size()
Returns block size in bytes.
Definition Block.cpp:161
uint64_t offset()
Returns the local offset of this block.
Definition Block.cpp:151
Internal Boost.Python wrapper for rogue::interfaces::memory::Variable. Enables Python subclasses to o...
Definition Variable.h:874
Memory variable descriptor and typed accessor facade.
Definition Variable.h:62
std::vector< uint32_t > bitSize_
Definition Variable.h:103
std::vector< uint32_t > bitOffset_
Definition Variable.h:100
std::shared_ptr< rogue::interfaces::memory::Block > BlockPtr
Shared pointer alias for Block.
Definition Block.h:902
static const uint32_t Read
Memory read transaction type.
Definition Constants.h:36
static const uint32_t Write
Memory write transaction type.
Definition Constants.h:43
static const uint32_t Verify
Memory verify readback transaction type.
Definition Constants.h:57
static const uint32_t Post
Memory posted write transaction type.
Definition Constants.h:50
std::shared_ptr< rogue::interfaces::memory::Variable > VariablePtr
Definition Variable.h:43