22#define NO_IMPORT_ARRAY
24#include <boost/python.hpp>
26namespace bp = boost::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);
80 bp::implicitly_convertible<rim::BlockPtr, rim::MasterPtr>();
85rim::Block::Block(uint64_t offset, uint32_t size) {
96 blockPyTrans_ =
false;
104 blockData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
105 memset(blockData_, 0, size_);
107 verifyData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
108 memset(verifyData_, 0, size_);
110 verifyMask_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
111 memset(verifyMask_, 0, size_);
113 verifyBlock_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
114 memset(verifyBlock_, 0, size_);
116 expectedData_ =
reinterpret_cast<uint8_t*
>(malloc(size_));
117 memset(expectedData_, 0, size_);
121rim::Block::~Block() {
133std::string rim::Block::path() {
138std::string rim::Block::mode() {
143bool rim::Block::bulkOpEn() {
148void rim::Block::setEnable(
bool newState) {
150 std::lock_guard<std::mutex> lock(mtx_);
155uint64_t rim::Block::offset() {
160uint64_t rim::Block::address() {
161 return (reqAddress() + offset_);
165uint32_t rim::Block::size() {
170bool rim::Block::blockPyTrans() {
171 return blockPyTrans_;
175void rim::Block::intStartTransaction(uint32_t type,
bool forceWr,
bool check,
rim::Variable* var, int32_t index) {
182 uint32_t minAccess = getSlave()->doMinAccess();
184 std::vector<rim::VariablePtr>::iterator vit;
187 if ((type ==
rim::Write && ((mode_ ==
"RO") || (!stale_ && !forceWr))) || (type ==
rim::Post && (mode_ ==
"RO")) ||
188 (type ==
rim::Read && ((mode_ ==
"WO") || stale_)) ||
189 (type ==
rim::Verify && ((mode_ ==
"WO") || (mode_ ==
"RO") || stale_ || !verifyReq_)))
193 std::lock_guard<std::mutex> lock(mtx_);
200 highByte = size_ - 1;
203 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
204 (*vit)->stale_ =
false;
226 if (lowByte % minAccess != 0) lowByte -= lowByte % minAccess;
227 if ((highByte + 1) % minAccess != 0) highByte += minAccess - ((highByte + 1) % minAccess);
229 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
230 if ((*vit)->stale_) {
231 if ((*vit)->staleLowByte_ < lowByte) lowByte = (*vit)->staleLowByte_;
232 if ((*vit)->staleHighByte_ > highByte) highByte = (*vit)->staleHighByte_;
233 (*vit)->stale_ =
false;
240 if (!enable_)
return;
246 tData = verifyData_ + verifyBase_;
253 tSize = (highByte - lowByte) + 1;
256 tData = blockData_ + tOff;
263 verifyReq_ = verifyEn_;
267 memcpy(expectedData_ + tOff, blockData_ + tOff, tSize);
270 doUpdate_ = updateEn_;
272 bLog_->debug(
"Start transaction type = %" PRIu32
", Offset=0x%" PRIx64
", lByte=%" PRIu32
", hByte=%" PRIu32
273 ", tOff=0x%" PRIx32
", tSize=%" PRIu32,
282 reqTransaction(offset_ + tOff, tSize, tData, type);
287void rim::Block::startTransaction(uint32_t type,
bool forceWr,
bool check,
rim::Variable* var, int32_t index) {
295 intStartTransaction(type, fWr, check, var, index);
298 if (check || retryCount_ > 0) checkTransaction();
304 if ((count + 1) > retryCount_) {
305 bLog_->error(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
311 bLog_->warning(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
317 }
while (count++ < retryCount_);
323void rim::Block::startTransactionPy(uint32_t type,
bool forceWr,
bool check,
rim::VariablePtr var, int32_t index) {
328 if (blockPyTrans_)
return;
335 intStartTransaction(type, fWr, check, var.get(), index);
338 if (check || retryCount_ > 0) upd = checkTransaction();
344 if ((count + 1) > retryCount_) {
345 bLog_->error(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
351 bLog_->warning(
"Error on try %" PRIu32
" out of %" PRIu32
": %s",
357 }
while (count++ < retryCount_);
359 if (upd) varUpdate();
365bool rim::Block::checkTransaction() {
372 std::lock_guard<std::mutex> lock(mtx_);
380 "Transaction error for block %s with address 0x%.8x. Error %s",
387 if (!enable_)
return false;
391 bLog_->debug(
"Verfying data. Base=0x%" PRIx32
", size=%" PRIu32, verifyBase_, verifySize_);
395 for (x = verifyBase_; x < verifyBase_ + verifySize_; x++) {
396 if ((verifyData_[x] & verifyMask_[x]) != (expectedData_[x] & verifyMask_[x])) {
398 "Verify error for block %s with address 0x%.8" PRIx64
399 ". Byte: %" PRIu32
". Got: 0x%.2" PRIx8
", Exp: 0x%.2" PRIx8
400 ", Mask: 0x%.2" PRIx8,
410 bLog_->debug(
"Transaction complete");
412 locUpdate = doUpdate_;
421void rim::Block::checkTransactionPy() {
422 if (blockPyTrans_)
return;
424 if (checkTransaction()) varUpdate();
431 startTransaction(
rim::Write,
true,
false, var, index);
432 startTransaction(
rim::Verify,
false,
false, var, index);
438 startTransaction(
rim::Read,
false,
false, var, index);
445void rim::Block::varUpdate() {
446 std::vector<rim::VariablePtr>::iterator vit;
450 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
451 if ((*vit)->updateNotify_) (*vit)->queueUpdate();
458void rim::Block::addVariables(std::vector<rim::VariablePtr> variables) {
459 std::vector<rim::VariablePtr>::iterator vit;
463 uint8_t excMask[size_];
464 uint8_t oleMask[size_];
466 memset(excMask, 0, size_);
467 memset(oleMask, 0, size_);
469 variables_ = variables;
471 for (vit = variables_.begin(); vit != variables_.end(); ++vit) {
472 (*vit)->block_ =
this;
474 if (vit == variables_.begin()) {
475 path_ = (*vit)->path_;
476 std::string logName =
"memory.block." + path_;
478 mode_ = (*vit)->mode_;
481 if ((*vit)->bulkOpEn_) bulkOpEn_ =
true;
482 if ((*vit)->updateNotify_) updateEn_ =
true;
485 if ((*vit)->retryCount_ > retryCount_) retryCount_ = (*vit)->retryCount_;
488 if (mode_ != (*vit)->mode_) mode_ =
"RW";
491 if ((*vit)->numValues_ == 0) {
492 for (x = 0; x < (*vit)->bitOffset_.size(); x++) {
494 if ((*vit)->overlapEn_) {
495 setBits(oleMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
499 if (anyBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]))
501 "Block::addVariables",
502 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
505 (*vit)->name_.c_str()));
507 setBits(excMask, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
511 if ((*vit)->mode_ ==
"RW" && (*vit)->verifyEn_) {
513 setBits(verifyMask_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
517 if ((*vit)->mode_ ==
"RO" || (*vit)->mode_ ==
"WO" || !(*vit)->verifyEn_) {
518 setBits(verifyBlock_, (*vit)->bitOffset_[x], (*vit)->bitSize_[x]);
522 "Adding variable %s to block %s at offset 0x%.8x, bitIdx=%i, bitOffset %i, bitSize %i, mode %s, "
525 (*vit)->name_.c_str(),
529 (*vit)->bitOffset_[x],
531 (*vit)->mode_.c_str(),
537 for (x = 0; x < (*vit)->numValues_; x++) {
539 if ((*vit)->overlapEn_) {
540 setBits(oleMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
544 if (anyBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_))
546 "Block::addVariables",
547 "Variable bit overlap detected for block %s with address 0x%.8x and variable %s",
550 (*vit)->name_.c_str()));
552 setBits(excMask, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
556 if ((*vit)->mode_ ==
"RW" && (*vit)->verifyEn_) {
558 setBits(verifyMask_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
562 if ((*vit)->mode_ ==
"RO" || (*vit)->mode_ ==
"WO" || !(*vit)->verifyEn_) {
563 setBits(verifyBlock_, x * (*vit)->valueStride_ + (*vit)->bitOffset_[0], (*vit)->valueBits_);
567 "Adding variable %s to block %s at offset 0x%.8x, index=%i, valueOffset=%i, valueBits %i, mode %s, "
569 (*vit)->name_.c_str(),
573 x * (*vit)->valueStride_ + (*vit)->bitOffset_[0],
575 (*vit)->mode_.c_str(),
582 for (x = 0; x < size_; x++) {
583 if (oleMask[x] & excMask[x])
585 "Variable bit mask overlap detected for block %s with address 0x%.8x",
590 verifyMask_[x] &= (verifyBlock_[x] ^ 0xFF);
597 std::stringstream ss;
598 uint32_t rem = size_;
604 ss <<
"0x" << std::setfill(
'0') << std::hex << std::setw(2) << static_cast<uint32_t>(verifyMask_[x]) <<
" ";
607 if (rem == 0 || x % 10 == 0) {
608 bLog_->debug(
"Done adding variables. Verify Mask %.3i - %.3i: %s", idx, x - 1, ss.str().c_str());
618void rim::Block::addVariablesPy(bp::object variables) {
619 std::vector<rim::VariablePtr> vars = py_list_to_std_vector<rim::VariablePtr>(variables);
626std::vector<rim::VariablePtr> rim::Block::variables() {
633bp::object rim::Block::variablesPy() {
634 return std_vector_to_py_list<rim::VariablePtr>(variables_);
640void rim::Block::reverseBytes(uint8_t* data, uint32_t byteSize) {
644 for (x = 0; x < byteSize / 2; x++) {
646 data[x] = data[byteSize - x - 1];
647 data[byteSize - x - 1] = tmp;
652void rim::Block::setBytes(
const uint8_t* data,
rim::Variable* var, uint32_t index) {
659 std::lock_guard<std::mutex> lock(mtx_);
662 if (var->
mode_ !=
"RO") stale_ =
true;
666 buff =
reinterpret_cast<uint8_t*
>(malloc(var->
valueBytes_));
670 buff =
const_cast<uint8_t*
>(
reinterpret_cast<const uint8_t*
>(data));
678 "Index %" PRIu32
" is out of range for %s",
680 var->
name_.c_str()));
689 if (var->
mode_ !=
"RO") {
702 if (var->
mode_ !=
"RO") {
716 for (x = 0; x < var->
bitOffset_.size(); x++) {
727void rim::Block::getBytes(uint8_t* data,
rim::Variable* var, uint32_t index) {
732 std::lock_guard<std::mutex> lock(mtx_);
739 "Index %" PRIu32
" is out of range for %s",
741 var->
name_.c_str()));
760 for (x = 0; x < var->
bitOffset_.size(); x++) {
780void rim::Block::setPyFunc(bp::object& value,
rim::Variable* var, int32_t index) {
785 if (index == -1) index = 0;
788 if (PyArray_Check(value.ptr())) {
790 "Passing ndarray not supported for %s",
791 var->
name_.c_str()));
794 }
else if (PyList_Check(value.ptr())) {
795 bp::list vl = bp::extract<bp::list>(value);
796 uint32_t vlen = len(vl);
800 "Overflow error for passed array with length %" PRIu32
801 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
805 var->
name_.c_str()));
807 for (x = 0; x < vlen; x++) {
811 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
813 "Failed to extract byte array for %s",
814 var->
name_.c_str()));
816 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index + x);
817 PyBuffer_Release(&valueBuf);
825 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
827 "Failed to extract byte array from pyFunc return value for %s",
828 var->
name_.c_str()));
830 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
831 PyBuffer_Release(&valueBuf);
840 if (index < 0 && var->numValues_ > 0) {
842 "Accessing unindexed value not support for %s",
843 var->
name_.c_str()));
849 getBytes(getBuffer, var, index);
850 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
854 bp::handle<> handle(val);
855 bp::object pass = bp::object(handle);
870void rim::Block::setByteArrayPy(bp::object& value,
rim::Variable* var, int32_t index) {
874 if (index < 0 && var->numValues_ > 0)
876 "Accessing unindexed value not supported for %s",
877 var->
name_.c_str()));
879 if (PyObject_GetBuffer(value.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
881 "Failed to extract byte array for %s",
882 var->
name_.c_str()));
884 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
885 PyBuffer_Release(&valueBuf);
893 if (index < 0 && var->numValues_ > 0)
895 "Accessing unindexed value not supported for %s",
896 var->
name_.c_str()));
900 getBytes(getBuffer, var, index);
901 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
905 bp::handle<> handle(val);
906 return bp::object(handle);
912void rim::Block::setByteArray(
const uint8_t* value,
rim::Variable* var, int32_t index) {
913 setBytes(value, var, index);
917void rim::Block::getByteArray(uint8_t* value,
rim::Variable* var, int32_t index) {
918 getBytes(value, var, index);
928void rim::Block::setUIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
929 if (index == -1) index = 0;
932 auto process_uint_array = [&](
auto* src, npy_intp stride, npy_intp length) {
933 for (npy_intp i = 0; i < length; ++i) {
934 setUInt(src[i * stride], var, index + i);
939 if (PyArray_Check(value.ptr())) {
941 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
942 npy_intp ndims = PyArray_NDIM(arr);
943 npy_intp* dims = PyArray_SHAPE(arr);
944 npy_intp* strides = PyArray_STRIDES(arr);
947 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
949 var->
name_.c_str()));
953 "Overflow error for passed array with length %" PRIu32
954 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
958 var->
name_.c_str()));
960 int type = PyArray_TYPE(arr);
963 uint64_t* src =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
964 npy_intp stride = strides[0] /
sizeof(uint64_t);
965 process_uint_array(src, stride, dims[0]);
969 uint32_t* src =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
970 npy_intp stride = strides[0] /
sizeof(uint32_t);
971 process_uint_array(src, stride, dims[0]);
975 uint16_t* src =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
976 npy_intp stride = strides[0] /
sizeof(uint16_t);
977 process_uint_array(src, stride, dims[0]);
981 uint8_t* src =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
982 npy_intp stride = strides[0] /
sizeof(uint8_t);
983 process_uint_array(src, stride, dims[0]);
988 "Passed nparray is not of an accepted unsigned int type (uint64, uint32, uint16, uint8) for %s",
989 var->
name_.c_str()));
993 }
else if (PyList_Check(value.ptr())) {
994 bp::list vl = bp::extract<bp::list>(value);
995 uint32_t vlen = len(vl);
998 "Overflow error for passed list with length %" PRIu32
999 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1003 var->
name_.c_str()));
1004 for (uint32_t i = 0; i < vlen; i++) {
1005 bp::extract<uint64_t> tmp(vl[i]);
1008 "Failed to extract value for %s.",
1009 var->
name_.c_str()));
1010 setUInt(tmp, var, index + i);
1014 }
else if (PyArray_CheckScalar(value.ptr())) {
1015 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1019 PyArray_ScalarAsCtype(value.ptr(), &val);
1020 setUInt(val, var, index);
1025 PyArray_ScalarAsCtype(value.ptr(), &val);
1026 setUInt(val, var, index);
1031 PyArray_ScalarAsCtype(value.ptr(), &val);
1032 setUInt(val, var, index);
1037 PyArray_ScalarAsCtype(value.ptr(), &val);
1038 setUInt(val, var, index);
1043 "Failed to extract scalar unsigned int value for %s.",
1044 var->
name_.c_str()));
1047 bp::extract<uint64_t> tmp(value);
1050 setUInt(tmp, var, index);
1059 if (index < 0 && var->numValues_ > 0) {
1067 npType = NPY_UINT16;
1069 npType = NPY_UINT32;
1071 npType = NPY_UINT64;
1074 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1075 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1079 uint8_t* dst =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
1081 dst[x] =
static_cast<uint8_t
>(getUInt(var, x));
1086 uint16_t* dst =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
1088 dst[x] =
static_cast<uint16_t
>(getUInt(var, x));
1093 uint32_t* dst =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
1095 dst[x] =
static_cast<uint32_t
>(getUInt(var, x));
1100 uint64_t* dst =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
1102 dst[x] = getUInt(var, x);
1107 boost::python::handle<> handle(obj);
1108 ret = bp::object(handle);
1110 PyObject* val = Py_BuildValue(
"K", getUInt(var, index));
1113 bp::handle<> handle(val);
1114 ret = bp::object(handle);
1122void rim::Block::setUInt(
const uint64_t& val,
rim::Variable* var, int32_t index) {
1126 "Value range error for %s. Value=%" PRIu64
", Min=%f, Max=%f",
1132 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<uint64_t*
>(&val)), var, index);
1139 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1151void rim::Block::setIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
1152 if (index == -1) index = 0;
1155 auto process_int_array = [&](
auto* src, npy_intp stride, npy_intp length) {
1156 for (npy_intp i = 0; i < length; ++i) {
1157 setInt(src[i * stride], var, index + i);
1162 if (PyArray_Check(value.ptr())) {
1164 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
1165 npy_intp ndims = PyArray_NDIM(arr);
1166 npy_intp* dims = PyArray_SHAPE(arr);
1167 npy_intp* strides = PyArray_STRIDES(arr);
1170 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1172 var->
name_.c_str()));
1176 "Overflow error for passed array with length %" PRIu32
1177 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1181 var->
name_.c_str()));
1183 int type = PyArray_TYPE(arr);
1186 int64_t* src =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1187 npy_intp stride = strides[0] /
sizeof(int64_t);
1188 process_int_array(src, stride, dims[0]);
1192 int32_t* src =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1193 npy_intp stride = strides[0] /
sizeof(int32_t);
1194 process_int_array(src, stride, dims[0]);
1198 int16_t* src =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1199 npy_intp stride = strides[0] /
sizeof(int16_t);
1200 process_int_array(src, stride, dims[0]);
1204 int8_t* src =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1205 npy_intp stride = strides[0] /
sizeof(int8_t);
1206 process_int_array(src, stride, dims[0]);
1211 "Passed nparray is not of an accepted signed int type (int64, int32, int16, int8) for %s",
1212 var->
name_.c_str()));
1216 }
else if (PyList_Check(value.ptr())) {
1217 bp::list vl = bp::extract<bp::list>(value);
1218 uint32_t vlen = len(vl);
1222 "Overflow error for passed list with length %" PRIu32
1223 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1227 var->
name_.c_str()));
1228 for (uint32_t i = 0; i < vlen; i++) {
1229 bp::extract<int64_t> tmp(vl[i]);
1232 "Failed to extract value for %s.",
1233 var->
name_.c_str()));
1234 setInt(tmp, var, index + i);
1238 }
else if (PyArray_CheckScalar(value.ptr())) {
1239 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1243 PyArray_ScalarAsCtype(value.ptr(), &val);
1244 setInt(val, var, index);
1249 PyArray_ScalarAsCtype(value.ptr(), &val);
1250 setInt(val, var, index);
1255 PyArray_ScalarAsCtype(value.ptr(), &val);
1256 setInt(val, var, index);
1261 PyArray_ScalarAsCtype(value.ptr(), &val);
1262 setInt(val, var, index);
1267 "Failed to extract scalar signed int value for %s.",
1268 var->
name_.c_str()));
1271 bp::extract<int64_t> tmp(value);
1275 setInt(tmp, var, index);
1284 if (index < 0 && var->numValues_ > 0) {
1297 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1298 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1302 int8_t* dst =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1304 dst[x] =
static_cast<int8_t
>(getInt(var, x));
1309 int16_t* dst =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1311 dst[x] =
static_cast<int16_t
>(getInt(var, x));
1316 int32_t* dst =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1318 dst[x] =
static_cast<int32_t
>(getInt(var, x));
1323 int64_t* dst =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1325 dst[x] = getInt(var, x);
1330 boost::python::handle<> handle(obj);
1331 ret = bp::object(handle);
1333 PyObject* val = Py_BuildValue(
"L", getInt(var, index));
1336 bp::handle<> handle(val);
1337 ret = bp::object(handle);
1349 "Value range error for %s. Value=%" PRId64
", Min=%f, Max=%f",
1356 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<int64_t*
>(&val)), var, index);
1363 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1366 if (tmp >=
static_cast<uint64_t
>(pow(2, var->
valueBits_ - 1))) {
1367 tmp -=
static_cast<uint64_t
>(pow(2, var->
valueBits_));
1380void rim::Block::setBoolPy(bp::object& value,
rim::Variable* var, int32_t index) {
1383 if (index == -1) index = 0;
1386 if (PyArray_Check(value.ptr())) {
1388 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1389 npy_intp ndims = PyArray_NDIM(arr);
1390 npy_intp* dims = PyArray_SHAPE(arr);
1391 npy_intp* strides = PyArray_STRIDES(arr);
1395 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1397 var->
name_.c_str()));
1401 "Overflow error for passed array with length %" PRIu32
1402 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1406 var->
name_.c_str()));
1408 if (PyArray_TYPE(arr) == NPY_BOOL) {
1409 bool* src =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1410 npy_intp stride = strides[0] /
sizeof(bool);
1411 for (x = 0; x < dims[0]; x++) {
1412 setBool(src[x * stride], var, index + x);
1416 "Passed nparray is not of type (bool) for %s",
1417 var->
name_.c_str()));
1421 }
else if (PyList_Check(value.ptr())) {
1422 bp::list vl = bp::extract<bp::list>(value);
1423 uint32_t vlen = len(vl);
1427 "Overflow error for passed array with length %" PRIu32
1428 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1432 var->
name_.c_str()));
1434 for (x = 0; x < vlen; x++) {
1435 bp::extract<bool> tmp(vl[x]);
1439 "Failed to extract value for %s.",
1440 var->
name_.c_str()));
1442 setBool(tmp, var, index + x);
1446 }
else if (PyArray_CheckScalar(value.ptr())) {
1447 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_BOOL) {
1449 PyArray_ScalarAsCtype(value.ptr(), &val);
1450 setBool(val, var, index);
1456 bp::extract<bool> tmp(value);
1462 setBool(tmp, var, index);
1472 if (index < 0 && var->numValues_ > 0) {
1475 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_BOOL);
1476 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1477 bool* dst =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1479 for (x = 0; x < var->
numValues_; x++) dst[x] = getBool(var, x);
1481 boost::python::handle<> handle(obj);
1482 ret = bp::object(handle);
1485 bp::handle<> handle(bp::borrowed(getBool(var, index) ? Py_True : Py_False));
1486 ret = bp::object(handle);
1495 uint8_t val = (uint8_t)value;
1496 setBytes(
reinterpret_cast<uint8_t*
>(&val), var, index);
1503 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1505 return tmp ? true :
false;
1515void rim::Block::setStringPy(bp::object& value,
rim::Variable* var, int32_t index) {
1520 if (index < 0 && var->numValues_ > 0)
1522 "Using nparray not supported for %s",
1523 var->
name_.c_str()));
1525 bp::extract<char*> tmp(value);
1531 setString(strVal, var, index);
1541 if (index < 0 && var->numValues_ > 0)
1545 getString(var, strVal, index);
1546 PyObject* val = Py_BuildValue(
"s", strVal.c_str());
1550 bp::handle<> handle(val);
1551 return bp::object(handle);
1557void rim::Block::setString(
const std::string& value,
rim::Variable* var, int32_t index) {
1562 strncpy(
reinterpret_cast<char*
>(getBuffer), value.c_str(), var->
valueBytes_ - 1);
1564 setBytes(getBuffer, var, index);
1570 getString(var, ret, index);
1575void rim::Block::getString(
rim::Variable* var, std::string& retString, int32_t index) {
1580 getBytes(
reinterpret_cast<uint8_t*
>(getBuffer), var, index);
1582 retString = getBuffer;
1592void rim::Block::setFloatPy(bp::object& value,
rim::Variable* var, int32_t index) {
1595 if (index == -1) index = 0;
1598 if (PyArray_Check(value.ptr())) {
1600 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1601 npy_intp ndims = PyArray_NDIM(arr);
1602 npy_intp* dims = PyArray_SHAPE(arr);
1603 npy_intp* strides = PyArray_STRIDES(arr);
1607 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1609 var->
name_.c_str()));
1613 "Overflow error for passed array with length %" PRIu32
1614 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1618 var->
name_.c_str()));
1620 if (PyArray_TYPE(arr) == NPY_FLOAT32) {
1621 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1622 npy_intp stride = strides[0] /
sizeof(float);
1623 for (x = 0; x < dims[0]; x++) {
1624 setFloat(src[x * stride], var, index + x);
1628 "Passed nparray is not of type (float32) for %s",
1629 var->
name_.c_str()));
1633 }
else if (PyList_Check(value.ptr())) {
1634 bp::list vl = bp::extract<bp::list>(value);
1635 uint32_t vlen = len(vl);
1639 "Overflow error for passed array with length %" PRIu32
1640 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1644 var->
name_.c_str()));
1646 for (x = 0; x < vlen; x++) {
1647 bp::extract<float> tmp(vl[x]);
1651 "Failed to extract value for %s.",
1652 var->
name_.c_str()));
1654 setFloat(tmp, var, index + x);
1658 }
else if (PyArray_CheckScalar(value.ptr())) {
1659 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT32) {
1661 PyArray_ScalarAsCtype(value.ptr(), &val);
1662 setFloat(val, var, index);
1665 "Failed to extract value for %s.",
1666 var->
name_.c_str()));
1669 bp::extract<float> tmp(value);
1673 "Failed to extract value for %s.",
1674 var->
name_.c_str()));
1676 setFloat(tmp, var, index);
1686 if (index < 0 && var->numValues_ > 0) {
1689 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT32);
1690 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1691 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1693 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat(var, x);
1695 boost::python::handle<> handle(obj);
1696 ret = bp::object(handle);
1699 PyObject* val = Py_BuildValue(
"f", getFloat(var, index));
1703 bp::handle<> handle(val);
1704 ret = bp::object(handle);
1716 "Value range error for %s. Value=%f, Min=%f, Max=%f",
1722 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<float*
>(&val)), var, index);
1729 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1737uint16_t floatToHalf(
float value) {
1739 std::memcpy(&f, &value,
sizeof(f));
1741 uint16_t sign = (f >> 16) & 0x8000;
1742 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 15;
1743 uint32_t mantissa = f & 0x7FFFFF;
1745 if (exponent <= 0) {
1746 if (exponent < -10)
return sign;
1747 mantissa |= 0x800000;
1748 uint32_t shift = 14 - exponent;
1749 uint32_t halfMant = mantissa >> shift;
1750 return sign |
static_cast<uint16_t
>(halfMant);
1751 }
else if (exponent == 0xFF - 127 + 15) {
1753 uint16_t halfMantissa =
static_cast<uint16_t
>(mantissa >> 13);
1754 if (halfMantissa == 0) halfMantissa = 0x0001;
1755 return sign | 0x7C00 | halfMantissa;
1757 return sign | 0x7C00;
1758 }
else if (exponent > 30) {
1759 return sign | 0x7C00;
1761 return sign | (exponent << 10) | (mantissa >> 13);
1764float halfToFloat(uint16_t h) {
1765 uint32_t sign = (h & 0x8000) << 16;
1766 uint32_t exponent = (h >> 10) & 0x1F;
1767 uint32_t mantissa = h & 0x3FF;
1770 if (exponent == 0) {
1771 if (mantissa == 0) {
1774 int32_t exponentWork = 1;
1775 while (!(mantissa & 0x400)) {
1780 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 15) << 23) | (mantissa << 13);
1782 }
else if (exponent == 31) {
1783 f = sign | 0x7F800000 | (mantissa << 13);
1785 f = sign | ((exponent + 127 - 15) << 23) | (mantissa << 13);
1789 std::memcpy(&result, &f,
sizeof(result));
1793uint8_t floatToFloat8(
float value) {
1795 std::memcpy(&f, &value,
sizeof(f));
1797 uint8_t sign = (f >> 24) & 0x80;
1798 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 7;
1799 uint32_t mantissa = f & 0x7FFFFF;
1802 if (((f >> 23) & 0xFF) == 0xFF && mantissa != 0)
return 0x7F;
1805 if (((f >> 23) & 0xFF) == 0xFF || exponent > 15)
return sign | 0x7E;
1807 if (exponent <= 0) {
1809 if (exponent < -3)
return sign;
1810 mantissa |= 0x800000;
1811 uint32_t shift = 1 - exponent;
1813 return sign | ((mantissa >> 20) & 0x07);
1815 return sign | (exponent << 3) | ((mantissa >> 20) & 0x07);
1818float float8ToFloat(uint8_t f8) {
1820 if ((f8 & 0x7F) == 0x7F) {
1821 uint32_t nan = 0x7FC00000;
1823 std::memcpy(&result, &nan,
sizeof(result));
1827 uint32_t sign = (
static_cast<uint32_t
>(f8) & 0x80) << 24;
1828 uint32_t exponent = (f8 >> 3) & 0x0F;
1829 uint32_t mantissa = f8 & 0x07;
1832 if (exponent == 0) {
1833 if (mantissa == 0) {
1838 int32_t exponentWork = 1;
1839 while (!(mantissa & 0x08)) {
1844 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 7) << 23) | (mantissa << 20);
1847 f = sign | (
static_cast<uint32_t
>(exponent + 127 - 7) << 23) | (mantissa << 20);
1851 std::memcpy(&result, &f,
sizeof(result));
1855uint16_t floatToBFloat16(
float value) {
1857 std::memcpy(&f, &value,
sizeof(f));
1860 uint16_t bf16 =
static_cast<uint16_t
>(f >> 16);
1862 uint32_t exponent = (f >> 23) & 0xFF;
1863 uint32_t mantissa = f & 0x7FFFFF;
1864 if (exponent == 0xFF && mantissa != 0 && (bf16 & 0x007F) == 0) {
1870float bfloat16ToFloat(uint16_t bf16) {
1871 uint32_t f =
static_cast<uint32_t
>(bf16) << 16;
1873 std::memcpy(&result, &f,
sizeof(result));
1880uint32_t floatToTensorFloat32(
float value) {
1882 std::memcpy(&f, &value,
sizeof(f));
1883 uint32_t tf32 = f & 0xFFFFE000U;
1885 if ((f & 0x7F800000U) == 0x7F800000U && (f & 0x007FFFFFU) != 0 &&
1886 (tf32 & 0x007FFFFFU) == 0) {
1887 tf32 |= 0x00002000U;
1892float tensorFloat32ToFloat(uint32_t tf32) {
1894 std::memcpy(&result, &tf32,
sizeof(result));
1901uint8_t floatToFloat6(
float value) {
1903 std::memcpy(&f, &value,
sizeof(f));
1905 uint8_t sign = (f >> 26) & 0x20;
1906 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 3;
1907 uint32_t mantissa = f & 0x7FFFFF;
1910 if (((f >> 23) & 0xFF) == 0xFF) {
1913 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1914 return nan_sign | 0x1F;
1918 if (exponent > 7)
return sign | 0x1F;
1920 if (exponent <= 0) {
1922 if (exponent < -2)
return sign;
1923 mantissa |= 0x800000;
1924 uint32_t shift = 1 - exponent;
1926 return sign | ((mantissa >> 21) & 0x03);
1928 return sign | (exponent << 2) | ((mantissa >> 21) & 0x03);
1931float float6ToFloat(uint8_t f6) {
1935 float sign = (f6 & 0x20) ? -1.0f : 1.0f;
1936 uint32_t exponent = (f6 >> 2) & 0x07;
1937 uint32_t mantissa = f6 & 0x03;
1939 if (exponent == 0) {
1940 if (mantissa == 0) {
1944 return sign *
static_cast<float>(mantissa) * 0.0625f;
1947 float frac = 1.0f +
static_cast<float>(mantissa) / 4.0f;
1948 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 3);
1953uint8_t floatToFloat4(
float value) {
1955 std::memcpy(&f, &value,
sizeof(f));
1957 uint8_t sign = (f >> 28) & 0x08;
1958 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 1;
1959 uint32_t mantissa = f & 0x7FFFFF;
1962 if (((f >> 23) & 0xFF) == 0xFF) {
1965 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1966 return nan_sign | 0x07;
1970 if (exponent > 3)
return sign | 0x07;
1972 if (exponent <= 0) {
1974 if (exponent < -1)
return sign;
1975 mantissa |= 0x800000;
1976 uint32_t shift = 1 - exponent;
1978 return sign | ((mantissa >> 22) & 0x01);
1980 return sign | (exponent << 1) | ((mantissa >> 22) & 0x01);
1983float float4ToFloat(uint8_t f4) {
1987 float sign = (f4 & 0x08) ? -1.0f : 1.0f;
1988 uint32_t exponent = (f4 >> 1) & 0x03;
1989 uint32_t mantissa = f4 & 0x01;
1991 if (exponent == 0) {
1992 if (mantissa == 0) {
1996 return sign *
static_cast<float>(mantissa) * 0.5f;
1999 float frac = 1.0f +
static_cast<float>(mantissa) / 2.0f;
2000 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 1);
2012void rim::Block::setFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2015 if (index == -1) index = 0;
2018 if (PyArray_Check(value.ptr())) {
2020 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2021 npy_intp ndims = PyArray_NDIM(arr);
2022 npy_intp* dims = PyArray_SHAPE(arr);
2023 npy_intp* strides = PyArray_STRIDES(arr);
2027 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2029 var->
name_.c_str()));
2033 "Overflow error for passed array with length %" PRIu32
2034 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2038 var->
name_.c_str()));
2040 if (PyArray_TYPE(arr) == NPY_HALF) {
2041 npy_half* src =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2042 npy_intp stride = strides[0] /
sizeof(npy_half);
2043 for (x = 0; x < dims[0]; x++) {
2044 float val = halfToFloat(src[x * stride]);
2045 setFloat16(val, var, index + x);
2049 "Passed nparray is not of type (float16) for %s",
2050 var->
name_.c_str()));
2054 }
else if (PyList_Check(value.ptr())) {
2055 bp::list vl = bp::extract<bp::list>(value);
2056 uint32_t vlen = len(vl);
2060 "Overflow error for passed array with length %" PRIu32
2061 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2065 var->
name_.c_str()));
2067 for (x = 0; x < vlen; x++) {
2068 bp::extract<float> tmp(vl[x]);
2072 "Failed to extract value for %s.",
2073 var->
name_.c_str()));
2075 setFloat16(tmp, var, index + x);
2079 }
else if (PyArray_CheckScalar(value.ptr())) {
2080 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_HALF) {
2082 PyArray_ScalarAsCtype(value.ptr(), &val);
2083 float fval = halfToFloat(val);
2084 setFloat16(fval, var, index);
2087 "Failed to extract value for %s.",
2088 var->
name_.c_str()));
2091 bp::extract<float> tmp(value);
2095 "Failed to extract value for %s.",
2096 var->
name_.c_str()));
2098 setFloat16(tmp, var, index);
2108 if (index < 0 && var->numValues_ > 0) {
2111 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_HALF);
2112 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2113 npy_half* dst =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2115 for (x = 0; x < var->
numValues_; x++) dst[x] = floatToHalf(getFloat16(var, x));
2117 boost::python::handle<> handle(obj);
2118 ret = bp::object(handle);
2121 PyObject* val = Py_BuildValue(
"f", getFloat16(var, index));
2125 bp::handle<> handle(val);
2126 ret = bp::object(handle);
2134void rim::Block::setFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2138 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2145 uint16_t half = floatToHalf(val);
2146 setBytes(
reinterpret_cast<uint8_t*
>(&half), var, index);
2153 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2155 return halfToFloat(tmp);
2165void rim::Block::setFloat8Py(bp::object& value,
rim::Variable* var, int32_t index) {
2168 if (index == -1) index = 0;
2171 if (PyArray_Check(value.ptr())) {
2173 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2174 npy_intp ndims = PyArray_NDIM(arr);
2175 npy_intp* dims = PyArray_SHAPE(arr);
2176 npy_intp* strides = PyArray_STRIDES(arr);
2180 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2182 var->
name_.c_str()));
2186 "Overflow error for passed array with length %" PRIu32
2187 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2191 var->
name_.c_str()));
2193 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2194 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2195 npy_intp stride = strides[0] /
sizeof(float);
2196 for (x = 0; x < dims[0]; x++) {
2197 float val = src[x * stride];
2198 setFloat8(val, var, index + x);
2202 "Passed nparray is not of type (float32) for %s",
2203 var->
name_.c_str()));
2207 }
else if (PyList_Check(value.ptr())) {
2208 bp::list vl = bp::extract<bp::list>(value);
2209 uint32_t vlen = len(vl);
2213 "Overflow error for passed array with length %" PRIu32
2214 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2218 var->
name_.c_str()));
2220 for (x = 0; x < vlen; x++) {
2221 bp::extract<float> tmp(vl[x]);
2225 "Failed to extract value for %s.",
2226 var->
name_.c_str()));
2228 setFloat8(tmp, var, index + x);
2232 bp::extract<float> tmp(value);
2236 "Failed to extract value for %s.",
2237 var->
name_.c_str()));
2239 setFloat8(tmp, var, index);
2249 if (index < 0 && var->numValues_ > 0) {
2251 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2252 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2253 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2255 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat8(var, x);
2257 boost::python::handle<> handle(obj);
2258 ret = bp::object(handle);
2261 PyObject* val = Py_BuildValue(
"f", getFloat8(var, index));
2265 bp::handle<> handle(val);
2266 ret = bp::object(handle);
2274void rim::Block::setFloat8(
const float& val,
rim::Variable* var, int32_t index) {
2278 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2285 uint8_t f8 = floatToFloat8(val);
2286 setBytes(
reinterpret_cast<uint8_t*
>(&f8), var, index);
2293 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2295 return float8ToFloat(tmp);
2305void rim::Block::setBFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2308 if (index == -1) index = 0;
2311 if (PyArray_Check(value.ptr())) {
2313 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2314 npy_intp ndims = PyArray_NDIM(arr);
2315 npy_intp* dims = PyArray_SHAPE(arr);
2316 npy_intp* strides = PyArray_STRIDES(arr);
2320 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2322 var->
name_.c_str()));
2326 "Overflow error for passed array with length %" PRIu32
2327 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2331 var->
name_.c_str()));
2333 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2334 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2335 npy_intp stride = strides[0] /
sizeof(float);
2336 for (x = 0; x < dims[0]; x++) {
2337 float val = src[x * stride];
2338 setBFloat16(val, var, index + x);
2342 "Passed nparray is not of type (float32) for %s",
2343 var->
name_.c_str()));
2347 }
else if (PyList_Check(value.ptr())) {
2348 bp::list vl = bp::extract<bp::list>(value);
2349 uint32_t vlen = len(vl);
2353 "Overflow error for passed array with length %" PRIu32
2354 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2358 var->
name_.c_str()));
2360 for (x = 0; x < vlen; x++) {
2361 bp::extract<float> tmp(vl[x]);
2365 "Failed to extract value for %s.",
2366 var->
name_.c_str()));
2368 setBFloat16(tmp, var, index + x);
2372 bp::extract<float> tmp(value);
2376 "Failed to extract value for %s.",
2377 var->
name_.c_str()));
2379 setBFloat16(tmp, var, index);
2389 if (index < 0 && var->numValues_ > 0) {
2391 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2392 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2393 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2395 for (x = 0; x < var->
numValues_; x++) dst[x] = getBFloat16(var, x);
2397 boost::python::handle<> handle(obj);
2398 ret = bp::object(handle);
2401 PyObject* val = Py_BuildValue(
"f", getBFloat16(var, index));
2405 bp::handle<> handle(val);
2406 ret = bp::object(handle);
2414void rim::Block::setBFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2418 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2425 uint16_t bf16 = floatToBFloat16(val);
2426 setBytes(
reinterpret_cast<uint8_t*
>(&bf16), var, index);
2433 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2435 return bfloat16ToFloat(tmp);
2445void rim::Block::setTensorFloat32Py(bp::object& value,
rim::Variable* var, int32_t index) {
2448 if (index == -1) index = 0;
2451 if (PyArray_Check(value.ptr())) {
2453 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2454 npy_intp ndims = PyArray_NDIM(arr);
2455 npy_intp* dims = PyArray_SHAPE(arr);
2456 npy_intp* strides = PyArray_STRIDES(arr);
2460 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2462 var->
name_.c_str()));
2466 "Overflow error for passed array with length %" PRIu32
2467 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2471 var->
name_.c_str()));
2473 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2474 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2475 npy_intp stride = strides[0] /
sizeof(float);
2476 for (x = 0; x < dims[0]; x++) {
2477 float val = src[x * stride];
2478 setTensorFloat32(val, var, index + x);
2482 "Passed nparray is not of type (float32) for %s",
2483 var->
name_.c_str()));
2487 }
else if (PyList_Check(value.ptr())) {
2488 bp::list vl = bp::extract<bp::list>(value);
2489 uint32_t vlen = len(vl);
2493 "Overflow error for passed array with length %" PRIu32
2494 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2498 var->
name_.c_str()));
2500 for (x = 0; x < vlen; x++) {
2501 bp::extract<float> tmp(vl[x]);
2505 "Failed to extract value for %s.",
2506 var->
name_.c_str()));
2508 setTensorFloat32(tmp, var, index + x);
2512 bp::extract<float> tmp(value);
2516 "Failed to extract value for %s.",
2517 var->
name_.c_str()));
2519 setTensorFloat32(tmp, var, index);
2529 if (index < 0 && var->numValues_ > 0) {
2531 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2532 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2533 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2535 for (x = 0; x < var->
numValues_; x++) dst[x] = getTensorFloat32(var, x);
2537 boost::python::handle<> handle(obj);
2538 ret = bp::object(handle);
2541 PyObject* val = Py_BuildValue(
"f", getTensorFloat32(var, index));
2545 bp::handle<> handle(val);
2546 ret = bp::object(handle);
2554void rim::Block::setTensorFloat32(
const float& val,
rim::Variable* var, int32_t index) {
2558 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2565 uint32_t tf32 = floatToTensorFloat32(val);
2566 setBytes(
reinterpret_cast<uint8_t*
>(&tf32), var, index);
2573 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2575 return tensorFloat32ToFloat(tmp);
2585void rim::Block::setFloat6Py(bp::object& value,
rim::Variable* var, int32_t index) {
2588 if (index == -1) index = 0;
2591 if (PyArray_Check(value.ptr())) {
2593 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2594 npy_intp ndims = PyArray_NDIM(arr);
2595 npy_intp* dims = PyArray_SHAPE(arr);
2596 npy_intp* strides = PyArray_STRIDES(arr);
2600 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2602 var->
name_.c_str()));
2606 "Overflow error for passed array with length %" PRIu32
2607 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2611 var->
name_.c_str()));
2613 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2614 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2615 npy_intp stride = strides[0] /
sizeof(float);
2616 for (x = 0; x < dims[0]; x++) {
2617 float val = src[x * stride];
2618 setFloat6(val, var, index + x);
2622 "Passed nparray is not of type (float32) for %s",
2623 var->
name_.c_str()));
2627 }
else if (PyList_Check(value.ptr())) {
2628 bp::list vl = bp::extract<bp::list>(value);
2629 uint32_t vlen = len(vl);
2633 "Overflow error for passed array with length %" PRIu32
2634 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2638 var->
name_.c_str()));
2640 for (x = 0; x < vlen; x++) {
2641 bp::extract<float> tmp(vl[x]);
2645 "Failed to extract value for %s.",
2646 var->
name_.c_str()));
2648 setFloat6(tmp, var, index + x);
2652 bp::extract<float> tmp(value);
2656 "Failed to extract value for %s.",
2657 var->
name_.c_str()));
2659 setFloat6(tmp, var, index);
2669 if (index < 0 && var->numValues_ > 0) {
2671 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2672 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2673 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2675 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat6(var, x);
2677 boost::python::handle<> handle(obj);
2678 ret = bp::object(handle);
2681 PyObject* val = Py_BuildValue(
"f", getFloat6(var, index));
2685 bp::handle<> handle(val);
2686 ret = bp::object(handle);
2694void rim::Block::setFloat6(
const float& val,
rim::Variable* var, int32_t index) {
2698 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2705 uint8_t f6 = floatToFloat6(val);
2706 setBytes(
reinterpret_cast<uint8_t*
>(&f6), var, index);
2713 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2715 return float6ToFloat(tmp);
2725void rim::Block::setFloat4Py(bp::object& value,
rim::Variable* var, int32_t index) {
2728 if (index == -1) index = 0;
2731 if (PyArray_Check(value.ptr())) {
2733 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2734 npy_intp ndims = PyArray_NDIM(arr);
2735 npy_intp* dims = PyArray_SHAPE(arr);
2736 npy_intp* strides = PyArray_STRIDES(arr);
2740 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2742 var->
name_.c_str()));
2746 "Overflow error for passed array with length %" PRIu32
2747 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2751 var->
name_.c_str()));
2753 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2754 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2755 npy_intp stride = strides[0] /
sizeof(float);
2756 for (x = 0; x < dims[0]; x++) {
2757 float val = src[x * stride];
2758 setFloat4(val, var, index + x);
2762 "Passed nparray is not of type (float32) for %s",
2763 var->
name_.c_str()));
2767 }
else if (PyList_Check(value.ptr())) {
2768 bp::list vl = bp::extract<bp::list>(value);
2769 uint32_t vlen = len(vl);
2773 "Overflow error for passed array with length %" PRIu32
2774 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2778 var->
name_.c_str()));
2780 for (x = 0; x < vlen; x++) {
2781 bp::extract<float> tmp(vl[x]);
2785 "Failed to extract value for %s.",
2786 var->
name_.c_str()));
2788 setFloat4(tmp, var, index + x);
2792 bp::extract<float> tmp(value);
2796 "Failed to extract value for %s.",
2797 var->
name_.c_str()));
2799 setFloat4(tmp, var, index);
2809 if (index < 0 && var->numValues_ > 0) {
2811 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2812 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2813 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2815 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat4(var, x);
2817 boost::python::handle<> handle(obj);
2818 ret = bp::object(handle);
2821 PyObject* val = Py_BuildValue(
"f", getFloat4(var, index));
2825 bp::handle<> handle(val);
2826 ret = bp::object(handle);
2834void rim::Block::setFloat4(
const float& val,
rim::Variable* var, int32_t index) {
2838 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2845 uint8_t f4 = floatToFloat4(val);
2846 setBytes(
reinterpret_cast<uint8_t*
>(&f4), var, index);
2853 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2855 return float4ToFloat(tmp);
2865void rim::Block::setDoublePy(bp::object& value,
rim::Variable* var, int32_t index) {
2868 if (index == -1) index = 0;
2871 if (PyArray_Check(value.ptr())) {
2873 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2874 npy_intp ndims = PyArray_NDIM(arr);
2875 npy_intp* dims = PyArray_SHAPE(arr);
2876 npy_intp* strides = PyArray_STRIDES(arr);
2880 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2882 var->
name_.c_str()));
2886 "Overflow error for passed array with length %" PRIu32
2887 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2891 var->
name_.c_str()));
2893 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
2894 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2895 npy_intp stride = strides[0] /
sizeof(double);
2896 for (x = 0; x < dims[0]; x++) {
2897 setDouble(src[x * stride], var, index + x);
2901 "Passed nparray is not of type (double) for %s",
2902 var->
name_.c_str()));
2906 }
else if (PyList_Check(value.ptr())) {
2907 bp::list vl = bp::extract<bp::list>(value);
2908 uint32_t vlen = len(vl);
2912 "Overflow error for passed array with length %" PRIu32
2913 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2917 var->
name_.c_str()));
2919 for (x = 0; x < vlen; x++) {
2920 bp::extract<double> tmp(vl[x]);
2924 "Failed to extract value for %s.",
2925 var->
name_.c_str()));
2927 setDouble(tmp, var, index + x);
2931 }
else if (PyArray_CheckScalar(value.ptr())) {
2932 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
2934 PyArray_ScalarAsCtype(value.ptr(), &val);
2935 setDouble(val, var, index);
2938 "Failed to extract value for %s.",
2939 var->
name_.c_str()));
2942 bp::extract<double> tmp(value);
2946 "Failed to extract value for %s.",
2947 var->
name_.c_str()));
2949 setDouble(tmp, var, index);
2959 if (index < 0 && var->numValues_ > 0) {
2962 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
2963 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2964 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2966 for (x = 0; x < var->
numValues_; x++) dst[x] = getDouble(var, x);
2968 boost::python::handle<> handle(obj);
2969 ret = bp::object(handle);
2972 PyObject* val = Py_BuildValue(
"d", getDouble(var, index));
2976 bp::handle<> handle(val);
2977 ret = bp::object(handle);
2985void rim::Block::setDouble(
const double& val,
rim::Variable* var, int32_t index) {
2989 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2995 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<double*
>(&val)), var, index);
3002 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
3014void rim::Block::setFixedPy(bp::object& value,
rim::Variable* var, int32_t index) {
3018 auto setScalar = [
this, var](
const double& v, int32_t idx) {
3020 setUFixed(v, var, idx);
3022 setFixed(v, var, idx);
3025 if (index == -1) index = 0;
3028 if (PyArray_Check(value.ptr())) {
3030 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
3031 npy_intp ndims = PyArray_NDIM(arr);
3032 npy_intp* dims = PyArray_SHAPE(arr);
3033 npy_intp* strides = PyArray_STRIDES(arr);
3037 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
3039 var->
name_.c_str()));
3043 "Overflow error for passed array with length %" PRIu32
3044 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3048 var->
name_.c_str()));
3050 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
3051 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3052 npy_intp stride = strides[0] /
sizeof(double);
3053 for (x = 0; x < dims[0]; x++) {
3054 setScalar(src[x * stride], index + x);
3058 "Passed nparray is not of type (double) for %s",
3059 var->
name_.c_str()));
3063 }
else if (PyList_Check(value.ptr())) {
3064 bp::list vl = bp::extract<bp::list>(value);
3065 uint32_t vlen = len(vl);
3069 "Overflow error for passed array with length %" PRIu32
3070 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3074 var->
name_.c_str()));
3076 for (x = 0; x < vlen; x++) {
3077 bp::extract<double> tmp(vl[x]);
3081 "Failed to extract value for %s.",
3082 var->
name_.c_str()));
3084 setScalar(tmp, index + x);
3088 }
else if (PyArray_CheckScalar(value.ptr())) {
3089 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
3091 PyArray_ScalarAsCtype(value.ptr(), &val);
3092 setScalar(val, index);
3095 "Failed to extract value for %s.",
3096 var->
name_.c_str()));
3099 bp::extract<double> tmp(value);
3103 "Failed to extract value for %s.",
3104 var->
name_.c_str()));
3106 setScalar(tmp, index);
3116 auto getScalar = [
this, var](int32_t idx) ->
double {
3121 if (index < 0 && var->numValues_ > 0) {
3124 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
3125 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
3126 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3128 for (x = 0; x < var->
numValues_; x++) dst[x] = getScalar(x);
3130 boost::python::handle<> handle(obj);
3131 ret = bp::object(handle);
3134 PyObject* val = Py_BuildValue(
"d", getScalar(index));
3138 bp::handle<> handle(val);
3139 ret = bp::object(handle);
3147void rim::Block::setFixed(
const double& val,
rim::Variable* var, int32_t index) {
3151 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3158 int64_t fPoint =
static_cast<int64_t
>(round(val * pow(2, var->
binPoint_)));
3161 int64_t maxInt =
static_cast<int64_t
>((1ULL << (var->
valueBits_ - 1)) - 1);
3162 int64_t minInt = -maxInt - 1;
3165 if (fPoint > maxInt || fPoint < minInt)
3167 "Fixed point overflow for %s. Value=%f, Min=%f, Max=%f",
3170 static_cast<double>(minInt) / pow(2, var->
binPoint_),
3171 static_cast<double>(maxInt) / pow(2, var->
binPoint_)));
3173 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3181 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3186 const int64_t signBit = 1LL << (var->
valueBits_ - 1);
3187 const int64_t modulus = 1LL << var->
valueBits_;
3188 if ((fPoint & signBit) != 0) fPoint -= modulus;
3192 tmp =
static_cast<double>(fPoint);
3198void rim::Block::setUFixed(
const double& val,
rim::Variable* var, int32_t index) {
3202 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3211 "Unsigned fixed-point underflow for %s. Value=%f",
3215 uint64_t fPoint =
static_cast<uint64_t
>(round(val * pow(2, var->
binPoint_)));
3222 if (fPoint > maxUInt)
3224 "Unsigned fixed-point overflow for %s. Value=%f, Min=0, Max=%f",
3227 static_cast<double>(maxUInt) / pow(2, var->
binPoint_)));
3229 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3234 uint64_t fPoint = 0;
3236 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3238 return static_cast<double>(fPoint) / pow(2, var->
binPoint_);
3246void rim::Block::customInit() {}
3249void rim::Block::customClean() {}
3251void rim::Block::rateTest() {
3254 struct timeval stime;
3255 struct timeval etime;
3256 struct timeval dtime;
3258 uint64_t count = 1000000;
3263 gettimeofday(&stime, NULL);
3265 for (x = 0; x < count; ++x) {
3266 reqTransaction(0, 4, &value,
rim::Read);
3269 gettimeofday(&etime, NULL);
3271 timersub(&etime, &stime, &dtime);
3272 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3273 rate = count / durr;
3275 printf(
"\nBlock c++ raw: Read %" PRIu64
" times in %f seconds. Rate = %f\n", count, durr, rate);
3277 gettimeofday(&stime, NULL);
3279 for (x = 0; x < count; ++x) {
3280 reqTransaction(0, 4,
reinterpret_cast<uint8_t*
>(&count),
rim::Write);
3283 gettimeofday(&etime, NULL);
3285 timersub(&etime, &stime, &dtime);
3286 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3287 rate = count / durr;
3289 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