22#define NO_IMPORT_ARRAY
24#include <boost/python.hpp>
26namespace bp = boost::python;
65void rim::Block::setup_python() {
66 bp::class_<rim::Block, rim::BlockPtr, bp::bases<rim::Master>, boost::noncopyable>(
"Block",
67 bp::init<uint64_t, uint32_t>())
68 .add_property(
"path", &rim::Block::path)
69 .add_property(
"mode", &rim::Block::mode)
70 .add_property(
"bulkOpEn", &rim::Block::bulkOpEn)
71 .add_property(
"offset", &rim::Block::offset)
72 .add_property(
"address", &rim::Block::address)
73 .add_property(
"size", &rim::Block::size)
74 .def(
"setEnable", &rim::Block::setEnable)
75 .def(
"_startTransaction", &rim::Block::startTransactionPy)
76 .def(
"_checkTransaction", &rim::Block::checkTransactionPy)
77 .def(
"addVariables", &rim::Block::addVariablesPy)
78 .def(
"_rateTest", &rim::Block::rateTest)
79 .add_property(
"variables", &rim::Block::variablesPy);
81 bp::implicitly_convertible<rim::BlockPtr, rim::MasterPtr>();
86rim::Block::Block(uint64_t offset, uint32_t size) {
97 blockPyTrans_ =
false;
105 blockData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
106 memset(blockData_, 0, size_);
108 verifyData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
109 memset(verifyData_, 0, size_);
111 verifyMask_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
112 memset(verifyMask_, 0, size_);
114 verifyBlock_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
115 memset(verifyBlock_, 0, size_);
117 expectedData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
118 memset(expectedData_, 0, size_);
122rim::Block::~Block() {
134std::string rim::Block::path() {
139std::string rim::Block::mode() {
144bool rim::Block::bulkOpEn() {
149void rim::Block::setEnable(
bool newState) {
151 std::lock_guard<std::mutex> lock(mtx_);
156uint64_t rim::Block::offset() {
161uint64_t rim::Block::address() {
162 return (reqAddress() + offset_);
166uint32_t rim::Block::size() {
171bool rim::Block::blockPyTrans() {
172 return blockPyTrans_;
176void rim::Block::intStartTransaction(uint32_t type,
bool forceWr,
rim::Variable* var, int32_t index) {
183 uint32_t minAccess = getSlave()->doMinAccess();
185 std::vector<rim::VariablePtr>::iterator vit;
188 if ((type ==
rim::Write && ((mode_ ==
"RO") || (!stale_ && !forceWr))) || (type ==
rim::Post && (mode_ ==
"RO")) ||
189 (type ==
rim::Read && ((mode_ ==
"WO") || stale_)) ||
190 (type ==
rim::Verify && ((mode_ ==
"WO") || (mode_ ==
"RO") || stale_ || !verifyReq_)))
194 std::lock_guard<std::mutex> lock(mtx_);
201 highByte = size_ - 1;
204 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
205 (*vit)->stale_ =
false;
227 if (lowByte % minAccess != 0) lowByte -= lowByte % minAccess;
228 if ((highByte + 1) % minAccess != 0) highByte += minAccess - ((highByte + 1) % minAccess);
230 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
231 if ((*vit)->stale_) {
232 if ((*vit)->staleLowByte_ < lowByte) lowByte = (*vit)->staleLowByte_;
233 if ((*vit)->staleHighByte_ > highByte) highByte = (*vit)->staleHighByte_;
234 (*vit)->stale_ =
false;
241 if (!enable_)
return;
247 tData = verifyData_ + verifyBase_;
254 tSize = (highByte - lowByte) + 1;
257 tData = blockData_ + tOff;
264 verifyReq_ = verifyEn_;
268 memcpy(expectedData_ + tOff, blockData_ + tOff, tSize);
271 doUpdate_ = updateEn_;
273 bLog_->debug(
"Start transaction type = %" PRIu32
", Offset=0x%" PRIx64
", lByte=%" PRIu32
", hByte=%" PRIu32
274 ", tOff=0x%" PRIx32
", tSize=%" PRIu32,
283 reqTransaction(offset_ + tOff, tSize, tData, type);
288void rim::Block::startTransaction(uint32_t type,
bool forceWr,
bool check,
rim::Variable* var, int32_t index) {
296 intStartTransaction(type, fWr, var, index);
299 if (check || retryCount_ > 0) checkTransaction();
305 if ((count + 1) > retryCount_) {
306 bLog_->error(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
312 bLog_->warning(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
318 }
while (count++ < retryCount_);
324void rim::Block::startTransactionPy(uint32_t type,
bool forceWr,
bool check,
rim::VariablePtr var, int32_t index) {
329 if (blockPyTrans_)
return;
336 intStartTransaction(type, fWr, var.get(), index);
339 if (check || retryCount_ > 0) upd = checkTransaction();
345 if ((count + 1) > retryCount_) {
346 bLog_->error(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
352 bLog_->warning(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
358 }
while (count++ < retryCount_);
360 if (upd) varUpdate();
366bool rim::Block::checkTransaction() {
373 std::lock_guard<std::mutex> lock(mtx_);
381 "Transaction error for block %s with address 0x%.8x. Error %s",
388 if (!enable_)
return false;
392 bLog_->debug(
"Verfying data. Base=0x%" PRIx32
", size=%" PRIu32, verifyBase_, verifySize_);
396 for (x = verifyBase_; x < verifyBase_ + verifySize_; x++) {
397 if ((verifyData_[x] & verifyMask_[x]) != (expectedData_[x] & verifyMask_[x])) {
399 "Verify error for block %s with address 0x%.8" PRIx64
400 ". Byte: %" PRIu32
". Got: 0x%.2" PRIx8
", Exp: 0x%.2" PRIx8
401 ", Mask: 0x%.2" PRIx8,
411 bLog_->debug(
"Transaction complete");
413 locUpdate = doUpdate_;
422void rim::Block::checkTransactionPy() {
423 if (blockPyTrans_)
return;
425 if (checkTransaction()) varUpdate();
432 startTransaction(
rim::Write,
true,
false, var, index);
433 startTransaction(
rim::Verify,
false,
false, var, index);
439 startTransaction(
rim::Read,
false,
false, var, index);
446void rim::Block::varUpdate() {
447 std::vector<rim::VariablePtr>::iterator vit;
451 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
452 if ((*vit)->updateNotify_) (*vit)->queueUpdate();
459void rim::Block::addVariables(std::vector<rim::VariablePtr> variables) {
460 std::vector<rim::VariablePtr>::iterator vit;
464 uint8_t excMask[size_];
465 uint8_t oleMask[size_];
467 memset(excMask, 0, size_);
468 memset(oleMask, 0, size_);
470 variables_ = variables;
472 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
473 (*vit)->block_ =
this;
475 if (vit == variables_.begin()) {
476 path_ = (*vit)->path_;
477 std::string logName =
"memory.block." + path_;
479 mode_ = (*vit)->mode_;
482 if ((*vit)->bulkOpEn_) bulkOpEn_ =
true;
483 if ((*vit)->updateNotify_) updateEn_ =
true;
486 if ((*vit)->retryCount_ > retryCount_) retryCount_ = (*vit)->retryCount_;
489 if (mode_ != (*vit)->mode_) mode_ =
"RW";
492 if ((*vit)->numValues_ == 0) {
493 for (x = 0; x < (*vit)->bitOffset_.size(); x++) {
495 if ((*vit)->overlapEn_) {
496 setBits(oleMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
500 if (anyBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]))
502 "Block::addVariables",
503 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
506 (*vit)->name_.c_str()));
508 setBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
512 if ((*vit)->mode_ ==
"RW" && (*vit)->verifyEn_) {
514 setBits(verifyMask_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
518 if ((*vit)->mode_ ==
"RO" || (*vit)->mode_ ==
"WO" || !(*vit)->verifyEn_) {
519 setBits(verifyBlock_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
523 "Adding variable %s to block %s at offset 0x%.8x, bitIdx=%i, bitOffset %i, bitSize %i, mode %s, "
526 (*vit)->name_.c_str(),
530 (*vit)->bitOffset_[x],
532 (*vit)->mode_.c_str(),
538 for (x = 0; x < (*vit)->numValues_; x++) {
540 if ((*vit)->overlapEn_) {
541 setBits(oleMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
545 if (anyBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_))
547 "Block::addVariables",
548 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
551 (*vit)->name_.c_str()));
553 setBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
557 if ((*vit)->mode_ ==
"RW" && (*vit)->verifyEn_) {
559 setBits(verifyMask_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
563 if ((*vit)->mode_ ==
"RO" || (*vit)->mode_ ==
"WO" || !(*vit)->verifyEn_) {
564 setBits(verifyBlock_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
568 "Adding variable %s to block %s at offset 0x%.8x, index=%i, valueOffset=%i, valueBits %i, mode %s, "
570 (*vit)->name_.c_str(),
574 x * (*vit)->valueStride_ + (*vit)->bitOffset_[0],
576 (*vit)->mode_.c_str(),
583 for (x = 0; x < size_; x++) {
584 if (oleMask[x] & excMask[x])
586 "Variable bit mask overlap detected for block %s with address 0x%.8x",
591 verifyMask_[x] &= (verifyBlock_[x] ^ 0xFF);
598 std::stringstream ss;
599 uint32_t rem = size_;
605 ss <<
"0x" << std::setfill(
'0') << std::hex << std::setw(2) << static_cast<uint32_t>(verifyMask_[x]) <<
" ";
608 if (rem == 0 || x % 10 == 0) {
609 bLog_->debug(
"Done adding variables. Verify Mask %.3i - %.3i: %s", idx, x - 1, ss.str().c_str());
619void rim::Block::addVariablesPy(bp::object variables) {
620 std::vector<rim::VariablePtr> vars = py_list_to_std_vector<rim::VariablePtr>(variables);
627std::vector<rim::VariablePtr> rim::Block::variables() {
634bp::object rim::Block::variablesPy() {
635 return std_vector_to_py_list<rim::VariablePtr>(variables_);
641void rim::Block::reverseBytes(uint8_t* data, uint32_t byteSize) {
645 for (x = 0; x < byteSize / 2; x++) {
647 data[x] = data[byteSize - x - 1];
648 data[byteSize - x - 1] = tmp;
653void rim::Block::setBytes(
const uint8_t* data,
rim::Variable* var, uint32_t index) {
666 std::unique_lock<std::mutex> lock(mtx_, std::try_to_lock);
667 if (!lock.owns_lock()) {
673 if (var->
mode_ !=
"RO") stale_ =
true;
677 buff =
reinterpret_cast<uint8_t*
>(malloc(var->
valueBytes_));
680 "Failed to allocate %" PRIu32
" bytes for byte-reversed copy of %s",
682 var->
name_.c_str()));
686 buff =
const_cast<uint8_t*
>(
reinterpret_cast<const uint8_t*
>(data));
694 "Index %" PRIu32
" is out of range for %s",
696 var->
name_.c_str()));
711 if (var->
mode_ !=
"RO") {
724 if (var->
mode_ !=
"RO") {
738 for (x = 0; x < var->
bitOffset_.size(); x++) {
749void rim::Block::getBytes(uint8_t* data,
rim::Variable* var, uint32_t index) {
757 std::unique_lock<std::mutex> lock(mtx_, std::try_to_lock);
758 if (!lock.owns_lock()) {
767 "Index %" PRIu32
" is out of range for %s",
769 var->
name_.c_str()));
790 for (x = 0; x < var->
bitOffset_.size(); x++) {
810void rim::Block::setPyFunc(bp::object& value,
rim::Variable* var, int32_t index) {
815 if (index == -1) index = 0;
818 if (PyArray_Check(value.ptr())) {
820 "Passing ndarray not supported for %s",
821 var->
name_.c_str()));
824 }
else if (PyList_Check(value.ptr())) {
825 bp::list vl = bp::extract<bp::list>(value);
826 uint32_t vlen = len(vl);
830 "Overflow error for passed array with length %" PRIu32
831 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
835 var->
name_.c_str()));
837 for (x = 0; x < vlen; x++) {
841 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
843 "Failed to extract byte array for %s",
844 var->
name_.c_str()));
846 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index + x);
847 PyBuffer_Release(&valueBuf);
855 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
857 "Failed to extract byte array from pyFunc return value for %s",
858 var->
name_.c_str()));
860 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
861 PyBuffer_Release(&valueBuf);
870 if (index < 0 && var->numValues_ > 0) {
872 "Accessing unindexed value not support for %s",
873 var->
name_.c_str()));
879 getBytes(getBuffer, var, index);
880 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
884 bp::handle<> handle(val);
885 bp::object pass = bp::object(handle);
900void rim::Block::setByteArrayPy(bp::object& value,
rim::Variable* var, int32_t index) {
904 if (index < 0 && var->numValues_ > 0)
906 "Accessing unindexed value not supported for %s",
907 var->
name_.c_str()));
909 if (PyObject_GetBuffer(value.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
911 "Failed to extract byte array for %s",
912 var->
name_.c_str()));
914 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
915 PyBuffer_Release(&valueBuf);
923 if (index < 0 && var->numValues_ > 0)
925 "Accessing unindexed value not supported for %s",
926 var->
name_.c_str()));
930 getBytes(getBuffer, var, index);
931 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
935 bp::handle<> handle(val);
936 return bp::object(handle);
942void rim::Block::setByteArray(
const uint8_t* value,
rim::Variable* var, int32_t index) {
943 setBytes(value, var, index);
947void rim::Block::getByteArray(uint8_t* value,
rim::Variable* var, int32_t index) {
948 getBytes(value, var, index);
958void rim::Block::setUIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
959 if (index == -1) index = 0;
962 auto process_uint_array = [&](
auto* src, npy_intp stride, npy_intp length) {
963 for (npy_intp i = 0; i < length; ++i) {
964 setUInt(src[i * stride], var, index + i);
969 if (PyArray_Check(value.ptr())) {
971 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
972 npy_intp ndims = PyArray_NDIM(arr);
973 npy_intp* dims = PyArray_SHAPE(arr);
974 npy_intp* strides = PyArray_STRIDES(arr);
977 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
979 var->
name_.c_str()));
983 "Overflow error for passed array with length %" PRIu32
984 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
988 var->
name_.c_str()));
990 int type = PyArray_TYPE(arr);
993 uint64_t* src =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
994 npy_intp stride = strides[0] /
sizeof(uint64_t);
995 process_uint_array(src, stride, dims[0]);
999 uint32_t* src =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
1000 npy_intp stride = strides[0] /
sizeof(uint32_t);
1001 process_uint_array(src, stride, dims[0]);
1005 uint16_t* src =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
1006 npy_intp stride = strides[0] /
sizeof(uint16_t);
1007 process_uint_array(src, stride, dims[0]);
1011 uint8_t* src =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
1012 npy_intp stride = strides[0] /
sizeof(uint8_t);
1013 process_uint_array(src, stride, dims[0]);
1018 "Passed nparray is not of an accepted unsigned int type (uint64, uint32, uint16, uint8) for %s",
1019 var->
name_.c_str()));
1023 }
else if (PyList_Check(value.ptr())) {
1024 bp::list vl = bp::extract<bp::list>(value);
1025 uint32_t vlen = len(vl);
1028 "Overflow error for passed list with length %" PRIu32
1029 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1033 var->
name_.c_str()));
1034 for (uint32_t i = 0; i < vlen; i++) {
1035 bp::extract<uint64_t> tmp(vl[i]);
1038 "Failed to extract value for %s.",
1039 var->
name_.c_str()));
1040 setUInt(tmp, var, index + i);
1044 }
else if (PyArray_CheckScalar(value.ptr())) {
1045 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1049 PyArray_ScalarAsCtype(value.ptr(), &val);
1050 setUInt(val, var, index);
1055 PyArray_ScalarAsCtype(value.ptr(), &val);
1056 setUInt(val, var, index);
1061 PyArray_ScalarAsCtype(value.ptr(), &val);
1062 setUInt(val, var, index);
1067 PyArray_ScalarAsCtype(value.ptr(), &val);
1068 setUInt(val, var, index);
1073 "Failed to extract scalar unsigned int value for %s.",
1074 var->
name_.c_str()));
1077 bp::extract<uint64_t> tmp(value);
1080 setUInt(tmp, var, index);
1089 if (index < 0 && var->numValues_ > 0) {
1097 npType = NPY_UINT16;
1099 npType = NPY_UINT32;
1101 npType = NPY_UINT64;
1104 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1105 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1109 uint8_t* dst =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
1111 dst[x] =
static_cast<uint8_t
>(getUInt(var, x));
1116 uint16_t* dst =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
1118 dst[x] =
static_cast<uint16_t
>(getUInt(var, x));
1123 uint32_t* dst =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
1125 dst[x] =
static_cast<uint32_t
>(getUInt(var, x));
1130 uint64_t* dst =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
1132 dst[x] = getUInt(var, x);
1137 boost::python::handle<> handle(obj);
1138 ret = bp::object(handle);
1140 PyObject* val = Py_BuildValue(
"K", getUInt(var, index));
1143 bp::handle<> handle(val);
1144 ret = bp::object(handle);
1152void rim::Block::setUInt(
const uint64_t& val,
rim::Variable* var, int32_t index) {
1156 "Value range error for %s. Value=%" PRIu64
", Min=%f, Max=%f",
1162 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<uint64_t*
>(&val)), var, index);
1169 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1181void rim::Block::setIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
1182 if (index == -1) index = 0;
1185 auto process_int_array = [&](
auto* src, npy_intp stride, npy_intp length) {
1186 for (npy_intp i = 0; i < length; ++i) {
1187 setInt(src[i * stride], var, index + i);
1192 if (PyArray_Check(value.ptr())) {
1194 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
1195 npy_intp ndims = PyArray_NDIM(arr);
1196 npy_intp* dims = PyArray_SHAPE(arr);
1197 npy_intp* strides = PyArray_STRIDES(arr);
1200 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1202 var->
name_.c_str()));
1206 "Overflow error for passed array with length %" PRIu32
1207 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1211 var->
name_.c_str()));
1213 int type = PyArray_TYPE(arr);
1216 int64_t* src =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1217 npy_intp stride = strides[0] /
sizeof(int64_t);
1218 process_int_array(src, stride, dims[0]);
1222 int32_t* src =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1223 npy_intp stride = strides[0] /
sizeof(int32_t);
1224 process_int_array(src, stride, dims[0]);
1228 int16_t* src =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1229 npy_intp stride = strides[0] /
sizeof(int16_t);
1230 process_int_array(src, stride, dims[0]);
1234 int8_t* src =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1235 npy_intp stride = strides[0] /
sizeof(int8_t);
1236 process_int_array(src, stride, dims[0]);
1241 "Passed nparray is not of an accepted signed int type (int64, int32, int16, int8) for %s",
1242 var->
name_.c_str()));
1246 }
else if (PyList_Check(value.ptr())) {
1247 bp::list vl = bp::extract<bp::list>(value);
1248 uint32_t vlen = len(vl);
1252 "Overflow error for passed list with length %" PRIu32
1253 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1257 var->
name_.c_str()));
1258 for (uint32_t i = 0; i < vlen; i++) {
1259 bp::extract<int64_t> tmp(vl[i]);
1262 "Failed to extract value for %s.",
1263 var->
name_.c_str()));
1264 setInt(tmp, var, index + i);
1268 }
else if (PyArray_CheckScalar(value.ptr())) {
1269 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1273 PyArray_ScalarAsCtype(value.ptr(), &val);
1274 setInt(val, var, index);
1279 PyArray_ScalarAsCtype(value.ptr(), &val);
1280 setInt(val, var, index);
1285 PyArray_ScalarAsCtype(value.ptr(), &val);
1286 setInt(val, var, index);
1291 PyArray_ScalarAsCtype(value.ptr(), &val);
1292 setInt(val, var, index);
1297 "Failed to extract scalar signed int value for %s.",
1298 var->
name_.c_str()));
1301 bp::extract<int64_t> tmp(value);
1305 setInt(tmp, var, index);
1314 if (index < 0 && var->numValues_ > 0) {
1327 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1328 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1332 int8_t* dst =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1334 dst[x] =
static_cast<int8_t
>(getInt(var, x));
1339 int16_t* dst =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1341 dst[x] =
static_cast<int16_t
>(getInt(var, x));
1346 int32_t* dst =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1348 dst[x] =
static_cast<int32_t
>(getInt(var, x));
1353 int64_t* dst =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1355 dst[x] = getInt(var, x);
1360 boost::python::handle<> handle(obj);
1361 ret = bp::object(handle);
1363 PyObject* val = Py_BuildValue(
"L", getInt(var, index));
1366 bp::handle<> handle(val);
1367 ret = bp::object(handle);
1379 "Value range error for %s. Value=%" PRId64
", Min=%f, Max=%f",
1386 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<int64_t*
>(&val)), var, index);
1393 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1396 if (tmp >=
static_cast<uint64_t
>(pow(2, var->
valueBits_ - 1))) {
1397 tmp -=
static_cast<uint64_t
>(pow(2, var->
valueBits_));
1410void rim::Block::setBoolPy(bp::object& value,
rim::Variable* var, int32_t index) {
1413 if (index == -1) index = 0;
1416 if (PyArray_Check(value.ptr())) {
1418 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1419 npy_intp ndims = PyArray_NDIM(arr);
1420 npy_intp* dims = PyArray_SHAPE(arr);
1421 npy_intp* strides = PyArray_STRIDES(arr);
1425 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1427 var->
name_.c_str()));
1431 "Overflow error for passed array with length %" PRIu32
1432 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1436 var->
name_.c_str()));
1438 if (PyArray_TYPE(arr) == NPY_BOOL) {
1439 bool* src =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1440 npy_intp stride = strides[0] /
sizeof(bool);
1441 for (x = 0; x < dims[0]; x++) {
1442 setBool(src[x * stride], var, index + x);
1446 "Passed nparray is not of type (bool) for %s",
1447 var->
name_.c_str()));
1451 }
else if (PyList_Check(value.ptr())) {
1452 bp::list vl = bp::extract<bp::list>(value);
1453 uint32_t vlen = len(vl);
1457 "Overflow error for passed array with length %" PRIu32
1458 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1462 var->
name_.c_str()));
1464 for (x = 0; x < vlen; x++) {
1465 bp::extract<bool> tmp(vl[x]);
1469 "Failed to extract value for %s.",
1470 var->
name_.c_str()));
1472 setBool(tmp, var, index + x);
1476 }
else if (PyArray_CheckScalar(value.ptr())) {
1477 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_BOOL) {
1479 PyArray_ScalarAsCtype(value.ptr(), &val);
1480 setBool(val, var, index);
1486 bp::extract<bool> tmp(value);
1492 setBool(tmp, var, index);
1502 if (index < 0 && var->numValues_ > 0) {
1505 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_BOOL);
1506 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1507 bool* dst =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1509 for (x = 0; x < var->
numValues_; x++) dst[x] = getBool(var, x);
1511 boost::python::handle<> handle(obj);
1512 ret = bp::object(handle);
1515 bp::handle<> handle(bp::borrowed(getBool(var, index) ? Py_True : Py_False));
1516 ret = bp::object(handle);
1525 uint8_t val = (uint8_t)value;
1526 setBytes(
reinterpret_cast<uint8_t*
>(&val), var, index);
1533 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1535 return tmp ? true :
false;
1545void rim::Block::setStringPy(bp::object& value,
rim::Variable* var, int32_t index) {
1550 if (index < 0 && var->numValues_ > 0)
1552 "Using nparray not supported for %s",
1553 var->
name_.c_str()));
1555 bp::extract<char*> tmp(value);
1561 setString(strVal, var, index);
1571 if (index < 0 && var->numValues_ > 0)
1575 getString(var, strVal, index);
1576 PyObject* val = Py_BuildValue(
"s", strVal.c_str());
1580 bp::handle<> handle(val);
1581 return bp::object(handle);
1587void rim::Block::setString(
const std::string& value,
rim::Variable* var, int32_t index) {
1592 strncpy(
reinterpret_cast<char*
>(getBuffer), value.c_str(), var->
valueBytes_ - 1);
1594 setBytes(getBuffer, var, index);
1600 getString(var, ret, index);
1605void rim::Block::getString(
rim::Variable* var, std::string& retString, int32_t index) {
1610 getBytes(
reinterpret_cast<uint8_t*
>(getBuffer), var, index);
1612 retString = getBuffer;
1622void rim::Block::setFloatPy(bp::object& value,
rim::Variable* var, int32_t index) {
1625 if (index == -1) index = 0;
1628 if (PyArray_Check(value.ptr())) {
1630 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1631 npy_intp ndims = PyArray_NDIM(arr);
1632 npy_intp* dims = PyArray_SHAPE(arr);
1633 npy_intp* strides = PyArray_STRIDES(arr);
1637 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1639 var->
name_.c_str()));
1643 "Overflow error for passed array with length %" PRIu32
1644 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1648 var->
name_.c_str()));
1650 if (PyArray_TYPE(arr) == NPY_FLOAT32) {
1651 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1652 npy_intp stride = strides[0] /
sizeof(float);
1653 for (x = 0; x < dims[0]; x++) {
1654 setFloat(src[x * stride], var, index + x);
1658 "Passed nparray is not of type (float32) for %s",
1659 var->
name_.c_str()));
1663 }
else if (PyList_Check(value.ptr())) {
1664 bp::list vl = bp::extract<bp::list>(value);
1665 uint32_t vlen = len(vl);
1669 "Overflow error for passed array with length %" PRIu32
1670 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1674 var->
name_.c_str()));
1676 for (x = 0; x < vlen; x++) {
1677 bp::extract<float> tmp(vl[x]);
1681 "Failed to extract value for %s.",
1682 var->
name_.c_str()));
1684 setFloat(tmp, var, index + x);
1688 }
else if (PyArray_CheckScalar(value.ptr())) {
1689 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT32) {
1691 PyArray_ScalarAsCtype(value.ptr(), &val);
1692 setFloat(val, var, index);
1695 "Failed to extract value for %s.",
1696 var->
name_.c_str()));
1699 bp::extract<float> tmp(value);
1703 "Failed to extract value for %s.",
1704 var->
name_.c_str()));
1706 setFloat(tmp, var, index);
1716 if (index < 0 && var->numValues_ > 0) {
1719 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT32);
1720 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1721 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1723 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat(var, x);
1725 boost::python::handle<> handle(obj);
1726 ret = bp::object(handle);
1729 PyObject* val = Py_BuildValue(
"f", getFloat(var, index));
1733 bp::handle<> handle(val);
1734 ret = bp::object(handle);
1746 "Value range error for %s. Value=%f, Min=%f, Max=%f",
1752 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<float*
>(&val)), var, index);
1759 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1767uint16_t floatToHalf(
float value) {
1769 std::memcpy(&f, &value,
sizeof(f));
1771 uint16_t sign = (f >> 16) & 0x8000;
1772 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 15;
1773 uint32_t mantissa = f & 0x7FFFFF;
1775 if (exponent <= 0) {
1776 if (exponent < -10)
return sign;
1777 mantissa |= 0x800000;
1778 uint32_t shift = 14 - exponent;
1779 uint32_t halfMant = mantissa >> shift;
1780 return sign |
static_cast<uint16_t
>(halfMant);
1781 }
else if (exponent == 0xFF - 127 + 15) {
1783 uint16_t halfMantissa =
static_cast<uint16_t
>(mantissa >> 13);
1784 if (halfMantissa == 0) halfMantissa = 0x0001;
1785 return sign | 0x7C00 | halfMantissa;
1787 return sign | 0x7C00;
1788 }
else if (exponent > 30) {
1789 return sign | 0x7C00;
1791 return sign | (exponent << 10) | (mantissa >> 13);
1794float halfToFloat(uint16_t h) {
1795 uint32_t sign = (h & 0x8000) << 16;
1796 uint32_t exponent = (h >> 10) & 0x1F;
1797 uint32_t mantissa = h & 0x3FF;
1800 if (exponent == 0) {
1801 if (mantissa == 0) {
1804 int32_t exponentWork = 1;
1805 while (!(mantissa & 0x400)) {
1810 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 15) << 23) | (mantissa << 13);
1812 }
else if (exponent == 31) {
1813 f = sign | 0x7F800000 | (mantissa << 13);
1815 f = sign | ((exponent + 127 - 15) << 23) | (mantissa << 13);
1819 std::memcpy(&result, &f,
sizeof(result));
1823uint8_t floatToFloat8(
float value) {
1825 std::memcpy(&f, &value,
sizeof(f));
1827 uint8_t sign = (f >> 24) & 0x80;
1828 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 7;
1829 uint32_t mantissa = f & 0x7FFFFF;
1832 if (((f >> 23) & 0xFF) == 0xFF && mantissa != 0)
return 0x7F;
1835 if (((f >> 23) & 0xFF) == 0xFF || exponent > 15)
return sign | 0x7E;
1837 if (exponent <= 0) {
1839 if (exponent < -3)
return sign;
1840 mantissa |= 0x800000;
1841 uint32_t shift = 1 - exponent;
1843 return sign | ((mantissa >> 20) & 0x07);
1845 return sign | (exponent << 3) | ((mantissa >> 20) & 0x07);
1848float float8ToFloat(uint8_t f8) {
1850 if ((f8 & 0x7F) == 0x7F) {
1851 uint32_t nan = 0x7FC00000;
1853 std::memcpy(&result, &nan,
sizeof(result));
1857 uint32_t sign = (
static_cast<uint32_t
>(f8) & 0x80) << 24;
1858 uint32_t exponent = (f8 >> 3) & 0x0F;
1859 uint32_t mantissa = f8 & 0x07;
1862 if (exponent == 0) {
1863 if (mantissa == 0) {
1868 int32_t exponentWork = 1;
1869 while (!(mantissa & 0x08)) {
1874 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 7) << 23) | (mantissa << 20);
1877 f = sign | (
static_cast<uint32_t
>(exponent + 127 - 7) << 23) | (mantissa << 20);
1881 std::memcpy(&result, &f,
sizeof(result));
1885uint16_t floatToBFloat16(
float value) {
1887 std::memcpy(&f, &value,
sizeof(f));
1890 uint16_t bf16 =
static_cast<uint16_t
>(f >> 16);
1892 uint32_t exponent = (f >> 23) & 0xFF;
1893 uint32_t mantissa = f & 0x7FFFFF;
1894 if (exponent == 0xFF && mantissa != 0 && (bf16 & 0x007F) == 0) {
1900float bfloat16ToFloat(uint16_t bf16) {
1901 uint32_t f =
static_cast<uint32_t
>(bf16) << 16;
1903 std::memcpy(&result, &f,
sizeof(result));
1910uint32_t floatToTensorFloat32(
float value) {
1912 std::memcpy(&f, &value,
sizeof(f));
1913 uint32_t tf32 = f & 0xFFFFE000U;
1915 if ((f & 0x7F800000U) == 0x7F800000U && (f & 0x007FFFFFU) != 0 &&
1916 (tf32 & 0x007FFFFFU) == 0) {
1917 tf32 |= 0x00002000U;
1922float tensorFloat32ToFloat(uint32_t tf32) {
1924 std::memcpy(&result, &tf32,
sizeof(result));
1931uint8_t floatToFloat6(
float value) {
1933 std::memcpy(&f, &value,
sizeof(f));
1935 uint8_t sign = (f >> 26) & 0x20;
1936 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 3;
1937 uint32_t mantissa = f & 0x7FFFFF;
1940 if (((f >> 23) & 0xFF) == 0xFF) {
1943 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1944 return nan_sign | 0x1F;
1948 if (exponent > 7)
return sign | 0x1F;
1950 if (exponent <= 0) {
1952 if (exponent < -2)
return sign;
1953 mantissa |= 0x800000;
1954 uint32_t shift = 1 - exponent;
1956 return sign | ((mantissa >> 21) & 0x03);
1958 return sign | (exponent << 2) | ((mantissa >> 21) & 0x03);
1961float float6ToFloat(uint8_t f6) {
1965 float sign = (f6 & 0x20) ? -1.0f : 1.0f;
1966 uint32_t exponent = (f6 >> 2) & 0x07;
1967 uint32_t mantissa = f6 & 0x03;
1969 if (exponent == 0) {
1970 if (mantissa == 0) {
1974 return sign *
static_cast<float>(mantissa) * 0.0625f;
1977 float frac = 1.0f +
static_cast<float>(mantissa) / 4.0f;
1978 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 3);
1983uint8_t floatToFloat4(
float value) {
1985 std::memcpy(&f, &value,
sizeof(f));
1987 uint8_t sign = (f >> 28) & 0x08;
1988 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 1;
1989 uint32_t mantissa = f & 0x7FFFFF;
1992 if (((f >> 23) & 0xFF) == 0xFF) {
1995 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1996 return nan_sign | 0x07;
2000 if (exponent > 3)
return sign | 0x07;
2002 if (exponent <= 0) {
2004 if (exponent < -1)
return sign;
2005 mantissa |= 0x800000;
2006 uint32_t shift = 1 - exponent;
2008 return sign | ((mantissa >> 22) & 0x01);
2010 return sign | (exponent << 1) | ((mantissa >> 22) & 0x01);
2013float float4ToFloat(uint8_t f4) {
2017 float sign = (f4 & 0x08) ? -1.0f : 1.0f;
2018 uint32_t exponent = (f4 >> 1) & 0x03;
2019 uint32_t mantissa = f4 & 0x01;
2021 if (exponent == 0) {
2022 if (mantissa == 0) {
2026 return sign *
static_cast<float>(mantissa) * 0.5f;
2029 float frac = 1.0f +
static_cast<float>(mantissa) / 2.0f;
2030 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 1);
2042void rim::Block::setFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2045 if (index == -1) index = 0;
2048 if (PyArray_Check(value.ptr())) {
2050 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2051 npy_intp ndims = PyArray_NDIM(arr);
2052 npy_intp* dims = PyArray_SHAPE(arr);
2053 npy_intp* strides = PyArray_STRIDES(arr);
2057 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2059 var->
name_.c_str()));
2063 "Overflow error for passed array with length %" PRIu32
2064 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2068 var->
name_.c_str()));
2070 if (PyArray_TYPE(arr) == NPY_HALF) {
2071 npy_half* src =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2072 npy_intp stride = strides[0] /
sizeof(npy_half);
2073 for (x = 0; x < dims[0]; x++) {
2074 float val = halfToFloat(src[x * stride]);
2075 setFloat16(val, var, index + x);
2079 "Passed nparray is not of type (float16) for %s",
2080 var->
name_.c_str()));
2084 }
else if (PyList_Check(value.ptr())) {
2085 bp::list vl = bp::extract<bp::list>(value);
2086 uint32_t vlen = len(vl);
2090 "Overflow error for passed array with length %" PRIu32
2091 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2095 var->
name_.c_str()));
2097 for (x = 0; x < vlen; x++) {
2098 bp::extract<float> tmp(vl[x]);
2102 "Failed to extract value for %s.",
2103 var->
name_.c_str()));
2105 setFloat16(tmp, var, index + x);
2109 }
else if (PyArray_CheckScalar(value.ptr())) {
2110 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_HALF) {
2112 PyArray_ScalarAsCtype(value.ptr(), &val);
2113 float fval = halfToFloat(val);
2114 setFloat16(fval, var, index);
2117 "Failed to extract value for %s.",
2118 var->
name_.c_str()));
2121 bp::extract<float> tmp(value);
2125 "Failed to extract value for %s.",
2126 var->
name_.c_str()));
2128 setFloat16(tmp, var, index);
2138 if (index < 0 && var->numValues_ > 0) {
2141 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_HALF);
2142 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2143 npy_half* dst =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2145 for (x = 0; x < var->
numValues_; x++) dst[x] = floatToHalf(getFloat16(var, x));
2147 boost::python::handle<> handle(obj);
2148 ret = bp::object(handle);
2151 PyObject* val = Py_BuildValue(
"f", getFloat16(var, index));
2155 bp::handle<> handle(val);
2156 ret = bp::object(handle);
2164void rim::Block::setFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2168 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2175 uint16_t half = floatToHalf(val);
2176 setBytes(
reinterpret_cast<uint8_t*
>(&half), var, index);
2183 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2185 return halfToFloat(tmp);
2195void rim::Block::setFloat8Py(bp::object& value,
rim::Variable* var, int32_t index) {
2198 if (index == -1) index = 0;
2201 if (PyArray_Check(value.ptr())) {
2203 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2204 npy_intp ndims = PyArray_NDIM(arr);
2205 npy_intp* dims = PyArray_SHAPE(arr);
2206 npy_intp* strides = PyArray_STRIDES(arr);
2210 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2212 var->
name_.c_str()));
2216 "Overflow error for passed array with length %" PRIu32
2217 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2221 var->
name_.c_str()));
2223 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2224 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2225 npy_intp stride = strides[0] /
sizeof(float);
2226 for (x = 0; x < dims[0]; x++) {
2227 float val = src[x * stride];
2228 setFloat8(val, var, index + x);
2232 "Passed nparray is not of type (float32) for %s",
2233 var->
name_.c_str()));
2237 }
else if (PyList_Check(value.ptr())) {
2238 bp::list vl = bp::extract<bp::list>(value);
2239 uint32_t vlen = len(vl);
2243 "Overflow error for passed array with length %" PRIu32
2244 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2248 var->
name_.c_str()));
2250 for (x = 0; x < vlen; x++) {
2251 bp::extract<float> tmp(vl[x]);
2255 "Failed to extract value for %s.",
2256 var->
name_.c_str()));
2258 setFloat8(tmp, var, index + x);
2262 bp::extract<float> tmp(value);
2266 "Failed to extract value for %s.",
2267 var->
name_.c_str()));
2269 setFloat8(tmp, var, index);
2279 if (index < 0 && var->numValues_ > 0) {
2281 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2282 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2283 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2285 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat8(var, x);
2287 boost::python::handle<> handle(obj);
2288 ret = bp::object(handle);
2291 PyObject* val = Py_BuildValue(
"f", getFloat8(var, index));
2295 bp::handle<> handle(val);
2296 ret = bp::object(handle);
2304void rim::Block::setFloat8(
const float& val,
rim::Variable* var, int32_t index) {
2308 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2315 uint8_t f8 = floatToFloat8(val);
2316 setBytes(
reinterpret_cast<uint8_t*
>(&f8), var, index);
2323 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2325 return float8ToFloat(tmp);
2335void rim::Block::setBFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2338 if (index == -1) index = 0;
2341 if (PyArray_Check(value.ptr())) {
2343 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2344 npy_intp ndims = PyArray_NDIM(arr);
2345 npy_intp* dims = PyArray_SHAPE(arr);
2346 npy_intp* strides = PyArray_STRIDES(arr);
2350 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2352 var->
name_.c_str()));
2356 "Overflow error for passed array with length %" PRIu32
2357 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2361 var->
name_.c_str()));
2363 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2364 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2365 npy_intp stride = strides[0] /
sizeof(float);
2366 for (x = 0; x < dims[0]; x++) {
2367 float val = src[x * stride];
2368 setBFloat16(val, var, index + x);
2372 "Passed nparray is not of type (float32) for %s",
2373 var->
name_.c_str()));
2377 }
else if (PyList_Check(value.ptr())) {
2378 bp::list vl = bp::extract<bp::list>(value);
2379 uint32_t vlen = len(vl);
2383 "Overflow error for passed array with length %" PRIu32
2384 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2388 var->
name_.c_str()));
2390 for (x = 0; x < vlen; x++) {
2391 bp::extract<float> tmp(vl[x]);
2395 "Failed to extract value for %s.",
2396 var->
name_.c_str()));
2398 setBFloat16(tmp, var, index + x);
2402 bp::extract<float> tmp(value);
2406 "Failed to extract value for %s.",
2407 var->
name_.c_str()));
2409 setBFloat16(tmp, var, index);
2419 if (index < 0 && var->numValues_ > 0) {
2421 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2422 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2423 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2425 for (x = 0; x < var->
numValues_; x++) dst[x] = getBFloat16(var, x);
2427 boost::python::handle<> handle(obj);
2428 ret = bp::object(handle);
2431 PyObject* val = Py_BuildValue(
"f", getBFloat16(var, index));
2435 bp::handle<> handle(val);
2436 ret = bp::object(handle);
2444void rim::Block::setBFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2448 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2455 uint16_t bf16 = floatToBFloat16(val);
2456 setBytes(
reinterpret_cast<uint8_t*
>(&bf16), var, index);
2463 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2465 return bfloat16ToFloat(tmp);
2475void rim::Block::setTensorFloat32Py(bp::object& value,
rim::Variable* var, int32_t index) {
2478 if (index == -1) index = 0;
2481 if (PyArray_Check(value.ptr())) {
2483 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2484 npy_intp ndims = PyArray_NDIM(arr);
2485 npy_intp* dims = PyArray_SHAPE(arr);
2486 npy_intp* strides = PyArray_STRIDES(arr);
2490 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2492 var->
name_.c_str()));
2496 "Overflow error for passed array with length %" PRIu32
2497 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2501 var->
name_.c_str()));
2503 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2504 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2505 npy_intp stride = strides[0] /
sizeof(float);
2506 for (x = 0; x < dims[0]; x++) {
2507 float val = src[x * stride];
2508 setTensorFloat32(val, var, index + x);
2512 "Passed nparray is not of type (float32) for %s",
2513 var->
name_.c_str()));
2517 }
else if (PyList_Check(value.ptr())) {
2518 bp::list vl = bp::extract<bp::list>(value);
2519 uint32_t vlen = len(vl);
2523 "Overflow error for passed array with length %" PRIu32
2524 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2528 var->
name_.c_str()));
2530 for (x = 0; x < vlen; x++) {
2531 bp::extract<float> tmp(vl[x]);
2535 "Failed to extract value for %s.",
2536 var->
name_.c_str()));
2538 setTensorFloat32(tmp, var, index + x);
2542 bp::extract<float> tmp(value);
2546 "Failed to extract value for %s.",
2547 var->
name_.c_str()));
2549 setTensorFloat32(tmp, var, index);
2559 if (index < 0 && var->numValues_ > 0) {
2561 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2562 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2563 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2565 for (x = 0; x < var->
numValues_; x++) dst[x] = getTensorFloat32(var, x);
2567 boost::python::handle<> handle(obj);
2568 ret = bp::object(handle);
2571 PyObject* val = Py_BuildValue(
"f", getTensorFloat32(var, index));
2575 bp::handle<> handle(val);
2576 ret = bp::object(handle);
2584void rim::Block::setTensorFloat32(
const float& val,
rim::Variable* var, int32_t index) {
2588 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2595 uint32_t tf32 = floatToTensorFloat32(val);
2596 setBytes(
reinterpret_cast<uint8_t*
>(&tf32), var, index);
2603 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2605 return tensorFloat32ToFloat(tmp);
2615void rim::Block::setFloat6Py(bp::object& value,
rim::Variable* var, int32_t index) {
2618 if (index == -1) index = 0;
2621 if (PyArray_Check(value.ptr())) {
2623 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2624 npy_intp ndims = PyArray_NDIM(arr);
2625 npy_intp* dims = PyArray_SHAPE(arr);
2626 npy_intp* strides = PyArray_STRIDES(arr);
2630 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2632 var->
name_.c_str()));
2636 "Overflow error for passed array with length %" PRIu32
2637 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2641 var->
name_.c_str()));
2643 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2644 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2645 npy_intp stride = strides[0] /
sizeof(float);
2646 for (x = 0; x < dims[0]; x++) {
2647 float val = src[x * stride];
2648 setFloat6(val, var, index + x);
2652 "Passed nparray is not of type (float32) for %s",
2653 var->
name_.c_str()));
2657 }
else if (PyList_Check(value.ptr())) {
2658 bp::list vl = bp::extract<bp::list>(value);
2659 uint32_t vlen = len(vl);
2663 "Overflow error for passed array with length %" PRIu32
2664 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2668 var->
name_.c_str()));
2670 for (x = 0; x < vlen; x++) {
2671 bp::extract<float> tmp(vl[x]);
2675 "Failed to extract value for %s.",
2676 var->
name_.c_str()));
2678 setFloat6(tmp, var, index + x);
2682 bp::extract<float> tmp(value);
2686 "Failed to extract value for %s.",
2687 var->
name_.c_str()));
2689 setFloat6(tmp, var, index);
2699 if (index < 0 && var->numValues_ > 0) {
2701 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2702 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2703 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2705 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat6(var, x);
2707 boost::python::handle<> handle(obj);
2708 ret = bp::object(handle);
2711 PyObject* val = Py_BuildValue(
"f", getFloat6(var, index));
2715 bp::handle<> handle(val);
2716 ret = bp::object(handle);
2724void rim::Block::setFloat6(
const float& val,
rim::Variable* var, int32_t index) {
2728 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2735 uint8_t f6 = floatToFloat6(val);
2736 setBytes(
reinterpret_cast<uint8_t*
>(&f6), var, index);
2743 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2745 return float6ToFloat(tmp);
2755void rim::Block::setFloat4Py(bp::object& value,
rim::Variable* var, int32_t index) {
2758 if (index == -1) index = 0;
2761 if (PyArray_Check(value.ptr())) {
2763 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2764 npy_intp ndims = PyArray_NDIM(arr);
2765 npy_intp* dims = PyArray_SHAPE(arr);
2766 npy_intp* strides = PyArray_STRIDES(arr);
2770 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2772 var->
name_.c_str()));
2776 "Overflow error for passed array with length %" PRIu32
2777 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2781 var->
name_.c_str()));
2783 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2784 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2785 npy_intp stride = strides[0] /
sizeof(float);
2786 for (x = 0; x < dims[0]; x++) {
2787 float val = src[x * stride];
2788 setFloat4(val, var, index + x);
2792 "Passed nparray is not of type (float32) for %s",
2793 var->
name_.c_str()));
2797 }
else if (PyList_Check(value.ptr())) {
2798 bp::list vl = bp::extract<bp::list>(value);
2799 uint32_t vlen = len(vl);
2803 "Overflow error for passed array with length %" PRIu32
2804 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2808 var->
name_.c_str()));
2810 for (x = 0; x < vlen; x++) {
2811 bp::extract<float> tmp(vl[x]);
2815 "Failed to extract value for %s.",
2816 var->
name_.c_str()));
2818 setFloat4(tmp, var, index + x);
2822 bp::extract<float> tmp(value);
2826 "Failed to extract value for %s.",
2827 var->
name_.c_str()));
2829 setFloat4(tmp, var, index);
2839 if (index < 0 && var->numValues_ > 0) {
2841 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2842 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2843 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2845 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat4(var, x);
2847 boost::python::handle<> handle(obj);
2848 ret = bp::object(handle);
2851 PyObject* val = Py_BuildValue(
"f", getFloat4(var, index));
2855 bp::handle<> handle(val);
2856 ret = bp::object(handle);
2864void rim::Block::setFloat4(
const float& val,
rim::Variable* var, int32_t index) {
2868 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2875 uint8_t f4 = floatToFloat4(val);
2876 setBytes(
reinterpret_cast<uint8_t*
>(&f4), var, index);
2883 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2885 return float4ToFloat(tmp);
2895void rim::Block::setDoublePy(bp::object& value,
rim::Variable* var, int32_t index) {
2898 if (index == -1) index = 0;
2901 if (PyArray_Check(value.ptr())) {
2903 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2904 npy_intp ndims = PyArray_NDIM(arr);
2905 npy_intp* dims = PyArray_SHAPE(arr);
2906 npy_intp* strides = PyArray_STRIDES(arr);
2910 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2912 var->
name_.c_str()));
2916 "Overflow error for passed array with length %" PRIu32
2917 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2921 var->
name_.c_str()));
2923 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
2924 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2925 npy_intp stride = strides[0] /
sizeof(double);
2926 for (x = 0; x < dims[0]; x++) {
2927 setDouble(src[x * stride], var, index + x);
2931 "Passed nparray is not of type (double) for %s",
2932 var->
name_.c_str()));
2936 }
else if (PyList_Check(value.ptr())) {
2937 bp::list vl = bp::extract<bp::list>(value);
2938 uint32_t vlen = len(vl);
2942 "Overflow error for passed array with length %" PRIu32
2943 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2947 var->
name_.c_str()));
2949 for (x = 0; x < vlen; x++) {
2950 bp::extract<double> tmp(vl[x]);
2954 "Failed to extract value for %s.",
2955 var->
name_.c_str()));
2957 setDouble(tmp, var, index + x);
2961 }
else if (PyArray_CheckScalar(value.ptr())) {
2962 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
2964 PyArray_ScalarAsCtype(value.ptr(), &val);
2965 setDouble(val, var, index);
2968 "Failed to extract value for %s.",
2969 var->
name_.c_str()));
2972 bp::extract<double> tmp(value);
2976 "Failed to extract value for %s.",
2977 var->
name_.c_str()));
2979 setDouble(tmp, var, index);
2989 if (index < 0 && var->numValues_ > 0) {
2992 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
2993 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2994 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2996 for (x = 0; x < var->
numValues_; x++) dst[x] = getDouble(var, x);
2998 boost::python::handle<> handle(obj);
2999 ret = bp::object(handle);
3002 PyObject* val = Py_BuildValue(
"d", getDouble(var, index));
3006 bp::handle<> handle(val);
3007 ret = bp::object(handle);
3015void rim::Block::setDouble(
const double& val,
rim::Variable* var, int32_t index) {
3019 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3025 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<double*
>(&val)), var, index);
3032 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
3044void rim::Block::setFixedPy(bp::object& value,
rim::Variable* var, int32_t index) {
3048 auto setScalar = [
this, var](
const double& v, int32_t idx) {
3050 setUFixed(v, var, idx);
3052 setFixed(v, var, idx);
3055 if (index == -1) index = 0;
3058 if (PyArray_Check(value.ptr())) {
3060 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
3061 npy_intp ndims = PyArray_NDIM(arr);
3062 npy_intp* dims = PyArray_SHAPE(arr);
3063 npy_intp* strides = PyArray_STRIDES(arr);
3067 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
3069 var->
name_.c_str()));
3073 "Overflow error for passed array with length %" PRIu32
3074 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3078 var->
name_.c_str()));
3080 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
3081 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3082 npy_intp stride = strides[0] /
sizeof(double);
3083 for (x = 0; x < dims[0]; x++) {
3084 setScalar(src[x * stride], index + x);
3088 "Passed nparray is not of type (double) for %s",
3089 var->
name_.c_str()));
3093 }
else if (PyList_Check(value.ptr())) {
3094 bp::list vl = bp::extract<bp::list>(value);
3095 uint32_t vlen = len(vl);
3099 "Overflow error for passed array with length %" PRIu32
3100 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3104 var->
name_.c_str()));
3106 for (x = 0; x < vlen; x++) {
3107 bp::extract<double> tmp(vl[x]);
3111 "Failed to extract value for %s.",
3112 var->
name_.c_str()));
3114 setScalar(tmp, index + x);
3118 }
else if (PyArray_CheckScalar(value.ptr())) {
3119 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
3121 PyArray_ScalarAsCtype(value.ptr(), &val);
3122 setScalar(val, index);
3125 "Failed to extract value for %s.",
3126 var->
name_.c_str()));
3129 bp::extract<double> tmp(value);
3133 "Failed to extract value for %s.",
3134 var->
name_.c_str()));
3136 setScalar(tmp, index);
3146 auto getScalar = [
this, var](int32_t idx) ->
double {
3151 if (index < 0 && var->numValues_ > 0) {
3154 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
3155 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
3156 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3158 for (x = 0; x < var->
numValues_; x++) dst[x] = getScalar(x);
3160 boost::python::handle<> handle(obj);
3161 ret = bp::object(handle);
3164 PyObject* val = Py_BuildValue(
"d", getScalar(index));
3168 bp::handle<> handle(val);
3169 ret = bp::object(handle);
3177void rim::Block::setFixed(
const double& val,
rim::Variable* var, int32_t index) {
3181 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3188 int64_t fPoint =
static_cast<int64_t
>(round(val * pow(2, var->
binPoint_)));
3191 int64_t maxInt =
static_cast<int64_t
>((1ULL << (var->
valueBits_ - 1)) - 1);
3192 int64_t minInt = -maxInt - 1;
3195 if (fPoint > maxInt || fPoint < minInt)
3197 "Fixed point overflow for %s. Value=%f, Min=%f, Max=%f",
3200 static_cast<double>(minInt) / pow(2, var->
binPoint_),
3201 static_cast<double>(maxInt) / pow(2, var->
binPoint_)));
3203 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3211 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3216 const int64_t signBit = 1LL << (var->
valueBits_ - 1);
3217 const int64_t modulus = 1LL << var->
valueBits_;
3218 if ((fPoint & signBit) != 0) fPoint -= modulus;
3222 tmp =
static_cast<double>(fPoint);
3228void rim::Block::setUFixed(
const double& val,
rim::Variable* var, int32_t index) {
3232 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3241 "Unsigned fixed-point underflow for %s. Value=%f",
3245 uint64_t fPoint =
static_cast<uint64_t
>(round(val * pow(2, var->
binPoint_)));
3252 if (fPoint > maxUInt)
3254 "Unsigned fixed-point overflow for %s. Value=%f, Min=0, Max=%f",
3257 static_cast<double>(maxUInt) / pow(2, var->
binPoint_)));
3259 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3264 uint64_t fPoint = 0;
3266 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3268 return static_cast<double>(fPoint) / pow(2, var->
binPoint_);
3276void rim::Block::customInit() {}
3279void rim::Block::customClean() {}
3281void rim::Block::rateTest() {
3284 struct timeval stime;
3285 struct timeval etime;
3286 struct timeval dtime;
3288 uint64_t count = 1000000;
3293 gettimeofday(&stime, NULL);
3295 for (x = 0; x < count; ++x) {
3296 reqTransaction(0, 4, &value,
rim::Read);
3299 gettimeofday(&etime, NULL);
3301 timersub(&etime, &stime, &dtime);
3302 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3303 rate = count / durr;
3305 printf(
"\nBlock c++ raw: Read %" PRIu64
" times in %f seconds. Rate = %f\n", count, durr, rate);
3307 gettimeofday(&stime, NULL);
3309 for (x = 0; x < count; ++x) {
3310 reqTransaction(0, 4,
reinterpret_cast<uint8_t*
>(&count),
rim::Write);
3313 gettimeofday(&etime, NULL);
3315 timersub(&etime, &stime, &dtime);
3316 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3317 rate = count / durr;
3319 printf(
"\nBlock c++ raw: Wrote %" PRIu64
" times in %f seconds. Rate = %f\n", count, durr, rate);
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.
static std::shared_ptr< rogue::Logging > create(const std::string &name, bool quiet=false)
Creates a logger instance.
RAII helper that acquires the Python GIL for a scope.
uint32_t size()
Returns block size in bytes.
uint64_t offset()
Returns the local offset of this block.
Internal Boost.Python wrapper for rogue::interfaces::memory::Variable. Enables Python subclasses to o...
Memory variable descriptor and typed accessor facade.
std::vector< uint32_t > bitSize_
std::vector< uint32_t > bitOffset_
std::shared_ptr< rogue::interfaces::memory::Block > BlockPtr
Shared pointer alias for Block.
static const uint32_t Read
Memory read transaction type.
static const uint32_t Write
Memory write transaction type.
static const uint32_t Verify
Memory verify readback transaction type.
static const uint8_t UFixed
Block access type for unsigned fixed-point numeric data.
static const uint32_t Post
Memory posted write transaction type.
std::shared_ptr< rogue::interfaces::memory::Variable > VariablePtr