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_));
669 "Failed to allocate %" PRIu32
" bytes for byte-reversed copy of %s",
671 var->
name_.c_str()));
675 buff =
const_cast<uint8_t*
>(
reinterpret_cast<const uint8_t*
>(data));
683 "Index %" PRIu32
" is out of range for %s",
685 var->
name_.c_str()));
700 if (var->
mode_ !=
"RO") {
713 if (var->
mode_ !=
"RO") {
727 for (x = 0; x < var->
bitOffset_.size(); x++) {
738void rim::Block::getBytes(uint8_t* data,
rim::Variable* var, uint32_t index) {
743 std::lock_guard<std::mutex> lock(mtx_);
749 "Index %" PRIu32
" is out of range for %s",
751 var->
name_.c_str()));
772 for (x = 0; x < var->
bitOffset_.size(); x++) {
792void rim::Block::setPyFunc(bp::object& value,
rim::Variable* var, int32_t index) {
797 if (index == -1) index = 0;
800 if (PyArray_Check(value.ptr())) {
802 "Passing ndarray not supported for %s",
803 var->
name_.c_str()));
806 }
else if (PyList_Check(value.ptr())) {
807 bp::list vl = bp::extract<bp::list>(value);
808 uint32_t vlen = len(vl);
812 "Overflow error for passed array with length %" PRIu32
813 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
817 var->
name_.c_str()));
819 for (x = 0; x < vlen; x++) {
823 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
825 "Failed to extract byte array for %s",
826 var->
name_.c_str()));
828 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index + x);
829 PyBuffer_Release(&valueBuf);
837 if (PyObject_GetBuffer(ret.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
839 "Failed to extract byte array from pyFunc return value for %s",
840 var->
name_.c_str()));
842 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
843 PyBuffer_Release(&valueBuf);
852 if (index < 0 && var->numValues_ > 0) {
854 "Accessing unindexed value not support for %s",
855 var->
name_.c_str()));
861 getBytes(getBuffer, var, index);
862 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
866 bp::handle<> handle(val);
867 bp::object pass = bp::object(handle);
882void rim::Block::setByteArrayPy(bp::object& value,
rim::Variable* var, int32_t index) {
886 if (index < 0 && var->numValues_ > 0)
888 "Accessing unindexed value not supported for %s",
889 var->
name_.c_str()));
891 if (PyObject_GetBuffer(value.ptr(), &(valueBuf), PyBUF_SIMPLE) < 0)
893 "Failed to extract byte array for %s",
894 var->
name_.c_str()));
896 setBytes(
reinterpret_cast<uint8_t*
>(valueBuf.buf), var, index);
897 PyBuffer_Release(&valueBuf);
905 if (index < 0 && var->numValues_ > 0)
907 "Accessing unindexed value not supported for %s",
908 var->
name_.c_str()));
912 getBytes(getBuffer, var, index);
913 PyObject* val = Py_BuildValue(
"y#", getBuffer, var->
valueBytes_);
917 bp::handle<> handle(val);
918 return bp::object(handle);
924void rim::Block::setByteArray(
const uint8_t* value,
rim::Variable* var, int32_t index) {
925 setBytes(value, var, index);
929void rim::Block::getByteArray(uint8_t* value,
rim::Variable* var, int32_t index) {
930 getBytes(value, var, index);
940void rim::Block::setUIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
941 if (index == -1) index = 0;
944 auto process_uint_array = [&](
auto* src, npy_intp stride, npy_intp length) {
945 for (npy_intp i = 0; i < length; ++i) {
946 setUInt(src[i * stride], var, index + i);
951 if (PyArray_Check(value.ptr())) {
953 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
954 npy_intp ndims = PyArray_NDIM(arr);
955 npy_intp* dims = PyArray_SHAPE(arr);
956 npy_intp* strides = PyArray_STRIDES(arr);
959 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
961 var->
name_.c_str()));
965 "Overflow error for passed array with length %" PRIu32
966 " at index %" PRIu32
". Variable length = %" PRIu32
" for %s",
970 var->
name_.c_str()));
972 int type = PyArray_TYPE(arr);
975 uint64_t* src =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
976 npy_intp stride = strides[0] /
sizeof(uint64_t);
977 process_uint_array(src, stride, dims[0]);
981 uint32_t* src =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
982 npy_intp stride = strides[0] /
sizeof(uint32_t);
983 process_uint_array(src, stride, dims[0]);
987 uint16_t* src =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
988 npy_intp stride = strides[0] /
sizeof(uint16_t);
989 process_uint_array(src, stride, dims[0]);
993 uint8_t* src =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
994 npy_intp stride = strides[0] /
sizeof(uint8_t);
995 process_uint_array(src, stride, dims[0]);
1000 "Passed nparray is not of an accepted unsigned int type (uint64, uint32, uint16, uint8) for %s",
1001 var->
name_.c_str()));
1005 }
else if (PyList_Check(value.ptr())) {
1006 bp::list vl = bp::extract<bp::list>(value);
1007 uint32_t vlen = len(vl);
1010 "Overflow error for passed list with length %" PRIu32
1011 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1015 var->
name_.c_str()));
1016 for (uint32_t i = 0; i < vlen; i++) {
1017 bp::extract<uint64_t> tmp(vl[i]);
1020 "Failed to extract value for %s.",
1021 var->
name_.c_str()));
1022 setUInt(tmp, var, index + i);
1026 }
else if (PyArray_CheckScalar(value.ptr())) {
1027 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1031 PyArray_ScalarAsCtype(value.ptr(), &val);
1032 setUInt(val, var, index);
1037 PyArray_ScalarAsCtype(value.ptr(), &val);
1038 setUInt(val, var, index);
1043 PyArray_ScalarAsCtype(value.ptr(), &val);
1044 setUInt(val, var, index);
1049 PyArray_ScalarAsCtype(value.ptr(), &val);
1050 setUInt(val, var, index);
1055 "Failed to extract scalar unsigned int value for %s.",
1056 var->
name_.c_str()));
1059 bp::extract<uint64_t> tmp(value);
1062 setUInt(tmp, var, index);
1071 if (index < 0 && var->numValues_ > 0) {
1079 npType = NPY_UINT16;
1081 npType = NPY_UINT32;
1083 npType = NPY_UINT64;
1086 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1087 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1091 uint8_t* dst =
reinterpret_cast<uint8_t*
>(PyArray_DATA(arr));
1093 dst[x] =
static_cast<uint8_t
>(getUInt(var, x));
1098 uint16_t* dst =
reinterpret_cast<uint16_t*
>(PyArray_DATA(arr));
1100 dst[x] =
static_cast<uint16_t
>(getUInt(var, x));
1105 uint32_t* dst =
reinterpret_cast<uint32_t*
>(PyArray_DATA(arr));
1107 dst[x] =
static_cast<uint32_t
>(getUInt(var, x));
1112 uint64_t* dst =
reinterpret_cast<uint64_t*
>(PyArray_DATA(arr));
1114 dst[x] = getUInt(var, x);
1119 boost::python::handle<> handle(obj);
1120 ret = bp::object(handle);
1122 PyObject* val = Py_BuildValue(
"K", getUInt(var, index));
1125 bp::handle<> handle(val);
1126 ret = bp::object(handle);
1134void rim::Block::setUInt(
const uint64_t& val,
rim::Variable* var, int32_t index) {
1138 "Value range error for %s. Value=%" PRIu64
", Min=%f, Max=%f",
1144 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<uint64_t*
>(&val)), var, index);
1151 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1163void rim::Block::setIntPy(bp::object& value,
rim::Variable* var, int32_t index) {
1164 if (index == -1) index = 0;
1167 auto process_int_array = [&](
auto* src, npy_intp stride, npy_intp length) {
1168 for (npy_intp i = 0; i < length; ++i) {
1169 setInt(src[i * stride], var, index + i);
1174 if (PyArray_Check(value.ptr())) {
1176 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(value.ptr());
1177 npy_intp ndims = PyArray_NDIM(arr);
1178 npy_intp* dims = PyArray_SHAPE(arr);
1179 npy_intp* strides = PyArray_STRIDES(arr);
1182 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1184 var->
name_.c_str()));
1188 "Overflow error for passed array with length %" PRIu32
1189 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1193 var->
name_.c_str()));
1195 int type = PyArray_TYPE(arr);
1198 int64_t* src =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1199 npy_intp stride = strides[0] /
sizeof(int64_t);
1200 process_int_array(src, stride, dims[0]);
1204 int32_t* src =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1205 npy_intp stride = strides[0] /
sizeof(int32_t);
1206 process_int_array(src, stride, dims[0]);
1210 int16_t* src =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1211 npy_intp stride = strides[0] /
sizeof(int16_t);
1212 process_int_array(src, stride, dims[0]);
1216 int8_t* src =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1217 npy_intp stride = strides[0] /
sizeof(int8_t);
1218 process_int_array(src, stride, dims[0]);
1223 "Passed nparray is not of an accepted signed int type (int64, int32, int16, int8) for %s",
1224 var->
name_.c_str()));
1228 }
else if (PyList_Check(value.ptr())) {
1229 bp::list vl = bp::extract<bp::list>(value);
1230 uint32_t vlen = len(vl);
1234 "Overflow error for passed list with length %" PRIu32
1235 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1239 var->
name_.c_str()));
1240 for (uint32_t i = 0; i < vlen; i++) {
1241 bp::extract<int64_t> tmp(vl[i]);
1244 "Failed to extract value for %s.",
1245 var->
name_.c_str()));
1246 setInt(tmp, var, index + i);
1250 }
else if (PyArray_CheckScalar(value.ptr())) {
1251 int type_num = PyArray_DescrFromScalar(value.ptr())->type_num;
1255 PyArray_ScalarAsCtype(value.ptr(), &val);
1256 setInt(val, var, index);
1261 PyArray_ScalarAsCtype(value.ptr(), &val);
1262 setInt(val, var, index);
1267 PyArray_ScalarAsCtype(value.ptr(), &val);
1268 setInt(val, var, index);
1273 PyArray_ScalarAsCtype(value.ptr(), &val);
1274 setInt(val, var, index);
1279 "Failed to extract scalar signed int value for %s.",
1280 var->
name_.c_str()));
1283 bp::extract<int64_t> tmp(value);
1287 setInt(tmp, var, index);
1296 if (index < 0 && var->numValues_ > 0) {
1309 PyObject* obj = PyArray_SimpleNew(1, dims, npType);
1310 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1314 int8_t* dst =
reinterpret_cast<int8_t*
>(PyArray_DATA(arr));
1316 dst[x] =
static_cast<int8_t
>(getInt(var, x));
1321 int16_t* dst =
reinterpret_cast<int16_t*
>(PyArray_DATA(arr));
1323 dst[x] =
static_cast<int16_t
>(getInt(var, x));
1328 int32_t* dst =
reinterpret_cast<int32_t*
>(PyArray_DATA(arr));
1330 dst[x] =
static_cast<int32_t
>(getInt(var, x));
1335 int64_t* dst =
reinterpret_cast<int64_t*
>(PyArray_DATA(arr));
1337 dst[x] = getInt(var, x);
1342 boost::python::handle<> handle(obj);
1343 ret = bp::object(handle);
1345 PyObject* val = Py_BuildValue(
"L", getInt(var, index));
1348 bp::handle<> handle(val);
1349 ret = bp::object(handle);
1361 "Value range error for %s. Value=%" PRId64
", Min=%f, Max=%f",
1368 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<int64_t*
>(&val)), var, index);
1375 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1378 if (tmp >=
static_cast<uint64_t
>(pow(2, var->
valueBits_ - 1))) {
1379 tmp -=
static_cast<uint64_t
>(pow(2, var->
valueBits_));
1392void rim::Block::setBoolPy(bp::object& value,
rim::Variable* var, int32_t index) {
1395 if (index == -1) index = 0;
1398 if (PyArray_Check(value.ptr())) {
1400 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1401 npy_intp ndims = PyArray_NDIM(arr);
1402 npy_intp* dims = PyArray_SHAPE(arr);
1403 npy_intp* strides = PyArray_STRIDES(arr);
1407 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1409 var->
name_.c_str()));
1413 "Overflow error for passed array with length %" PRIu32
1414 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1418 var->
name_.c_str()));
1420 if (PyArray_TYPE(arr) == NPY_BOOL) {
1421 bool* src =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1422 npy_intp stride = strides[0] /
sizeof(bool);
1423 for (x = 0; x < dims[0]; x++) {
1424 setBool(src[x * stride], var, index + x);
1428 "Passed nparray is not of type (bool) for %s",
1429 var->
name_.c_str()));
1433 }
else if (PyList_Check(value.ptr())) {
1434 bp::list vl = bp::extract<bp::list>(value);
1435 uint32_t vlen = len(vl);
1439 "Overflow error for passed array with length %" PRIu32
1440 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1444 var->
name_.c_str()));
1446 for (x = 0; x < vlen; x++) {
1447 bp::extract<bool> tmp(vl[x]);
1451 "Failed to extract value for %s.",
1452 var->
name_.c_str()));
1454 setBool(tmp, var, index + x);
1458 }
else if (PyArray_CheckScalar(value.ptr())) {
1459 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_BOOL) {
1461 PyArray_ScalarAsCtype(value.ptr(), &val);
1462 setBool(val, var, index);
1468 bp::extract<bool> tmp(value);
1474 setBool(tmp, var, index);
1484 if (index < 0 && var->numValues_ > 0) {
1487 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_BOOL);
1488 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1489 bool* dst =
reinterpret_cast<bool*
>(PyArray_DATA(arr));
1491 for (x = 0; x < var->
numValues_; x++) dst[x] = getBool(var, x);
1493 boost::python::handle<> handle(obj);
1494 ret = bp::object(handle);
1497 bp::handle<> handle(bp::borrowed(getBool(var, index) ? Py_True : Py_False));
1498 ret = bp::object(handle);
1507 uint8_t val = (uint8_t)value;
1508 setBytes(
reinterpret_cast<uint8_t*
>(&val), var, index);
1515 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1517 return tmp ? true :
false;
1527void rim::Block::setStringPy(bp::object& value,
rim::Variable* var, int32_t index) {
1532 if (index < 0 && var->numValues_ > 0)
1534 "Using nparray not supported for %s",
1535 var->
name_.c_str()));
1537 bp::extract<char*> tmp(value);
1543 setString(strVal, var, index);
1553 if (index < 0 && var->numValues_ > 0)
1557 getString(var, strVal, index);
1558 PyObject* val = Py_BuildValue(
"s", strVal.c_str());
1562 bp::handle<> handle(val);
1563 return bp::object(handle);
1569void rim::Block::setString(
const std::string& value,
rim::Variable* var, int32_t index) {
1574 strncpy(
reinterpret_cast<char*
>(getBuffer), value.c_str(), var->
valueBytes_ - 1);
1576 setBytes(getBuffer, var, index);
1582 getString(var, ret, index);
1587void rim::Block::getString(
rim::Variable* var, std::string& retString, int32_t index) {
1592 getBytes(
reinterpret_cast<uint8_t*
>(getBuffer), var, index);
1594 retString = getBuffer;
1604void rim::Block::setFloatPy(bp::object& value,
rim::Variable* var, int32_t index) {
1607 if (index == -1) index = 0;
1610 if (PyArray_Check(value.ptr())) {
1612 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
1613 npy_intp ndims = PyArray_NDIM(arr);
1614 npy_intp* dims = PyArray_SHAPE(arr);
1615 npy_intp* strides = PyArray_STRIDES(arr);
1619 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
1621 var->
name_.c_str()));
1625 "Overflow error for passed array with length %" PRIu32
1626 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1630 var->
name_.c_str()));
1632 if (PyArray_TYPE(arr) == NPY_FLOAT32) {
1633 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1634 npy_intp stride = strides[0] /
sizeof(float);
1635 for (x = 0; x < dims[0]; x++) {
1636 setFloat(src[x * stride], var, index + x);
1640 "Passed nparray is not of type (float32) for %s",
1641 var->
name_.c_str()));
1645 }
else if (PyList_Check(value.ptr())) {
1646 bp::list vl = bp::extract<bp::list>(value);
1647 uint32_t vlen = len(vl);
1651 "Overflow error for passed array with length %" PRIu32
1652 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
1656 var->
name_.c_str()));
1658 for (x = 0; x < vlen; x++) {
1659 bp::extract<float> tmp(vl[x]);
1663 "Failed to extract value for %s.",
1664 var->
name_.c_str()));
1666 setFloat(tmp, var, index + x);
1670 }
else if (PyArray_CheckScalar(value.ptr())) {
1671 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT32) {
1673 PyArray_ScalarAsCtype(value.ptr(), &val);
1674 setFloat(val, var, index);
1677 "Failed to extract value for %s.",
1678 var->
name_.c_str()));
1681 bp::extract<float> tmp(value);
1685 "Failed to extract value for %s.",
1686 var->
name_.c_str()));
1688 setFloat(tmp, var, index);
1698 if (index < 0 && var->numValues_ > 0) {
1701 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT32);
1702 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
1703 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
1705 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat(var, x);
1707 boost::python::handle<> handle(obj);
1708 ret = bp::object(handle);
1711 PyObject* val = Py_BuildValue(
"f", getFloat(var, index));
1715 bp::handle<> handle(val);
1716 ret = bp::object(handle);
1728 "Value range error for %s. Value=%f, Min=%f, Max=%f",
1734 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<float*
>(&val)), var, index);
1741 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
1749uint16_t floatToHalf(
float value) {
1751 std::memcpy(&f, &value,
sizeof(f));
1753 uint16_t sign = (f >> 16) & 0x8000;
1754 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 15;
1755 uint32_t mantissa = f & 0x7FFFFF;
1757 if (exponent <= 0) {
1758 if (exponent < -10)
return sign;
1759 mantissa |= 0x800000;
1760 uint32_t shift = 14 - exponent;
1761 uint32_t halfMant = mantissa >> shift;
1762 return sign |
static_cast<uint16_t
>(halfMant);
1763 }
else if (exponent == 0xFF - 127 + 15) {
1765 uint16_t halfMantissa =
static_cast<uint16_t
>(mantissa >> 13);
1766 if (halfMantissa == 0) halfMantissa = 0x0001;
1767 return sign | 0x7C00 | halfMantissa;
1769 return sign | 0x7C00;
1770 }
else if (exponent > 30) {
1771 return sign | 0x7C00;
1773 return sign | (exponent << 10) | (mantissa >> 13);
1776float halfToFloat(uint16_t h) {
1777 uint32_t sign = (h & 0x8000) << 16;
1778 uint32_t exponent = (h >> 10) & 0x1F;
1779 uint32_t mantissa = h & 0x3FF;
1782 if (exponent == 0) {
1783 if (mantissa == 0) {
1786 int32_t exponentWork = 1;
1787 while (!(mantissa & 0x400)) {
1792 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 15) << 23) | (mantissa << 13);
1794 }
else if (exponent == 31) {
1795 f = sign | 0x7F800000 | (mantissa << 13);
1797 f = sign | ((exponent + 127 - 15) << 23) | (mantissa << 13);
1801 std::memcpy(&result, &f,
sizeof(result));
1805uint8_t floatToFloat8(
float value) {
1807 std::memcpy(&f, &value,
sizeof(f));
1809 uint8_t sign = (f >> 24) & 0x80;
1810 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 7;
1811 uint32_t mantissa = f & 0x7FFFFF;
1814 if (((f >> 23) & 0xFF) == 0xFF && mantissa != 0)
return 0x7F;
1817 if (((f >> 23) & 0xFF) == 0xFF || exponent > 15)
return sign | 0x7E;
1819 if (exponent <= 0) {
1821 if (exponent < -3)
return sign;
1822 mantissa |= 0x800000;
1823 uint32_t shift = 1 - exponent;
1825 return sign | ((mantissa >> 20) & 0x07);
1827 return sign | (exponent << 3) | ((mantissa >> 20) & 0x07);
1830float float8ToFloat(uint8_t f8) {
1832 if ((f8 & 0x7F) == 0x7F) {
1833 uint32_t nan = 0x7FC00000;
1835 std::memcpy(&result, &nan,
sizeof(result));
1839 uint32_t sign = (
static_cast<uint32_t
>(f8) & 0x80) << 24;
1840 uint32_t exponent = (f8 >> 3) & 0x0F;
1841 uint32_t mantissa = f8 & 0x07;
1844 if (exponent == 0) {
1845 if (mantissa == 0) {
1850 int32_t exponentWork = 1;
1851 while (!(mantissa & 0x08)) {
1856 f = sign | (
static_cast<uint32_t
>(exponentWork + 127 - 7) << 23) | (mantissa << 20);
1859 f = sign | (
static_cast<uint32_t
>(exponent + 127 - 7) << 23) | (mantissa << 20);
1863 std::memcpy(&result, &f,
sizeof(result));
1867uint16_t floatToBFloat16(
float value) {
1869 std::memcpy(&f, &value,
sizeof(f));
1872 uint16_t bf16 =
static_cast<uint16_t
>(f >> 16);
1874 uint32_t exponent = (f >> 23) & 0xFF;
1875 uint32_t mantissa = f & 0x7FFFFF;
1876 if (exponent == 0xFF && mantissa != 0 && (bf16 & 0x007F) == 0) {
1882float bfloat16ToFloat(uint16_t bf16) {
1883 uint32_t f =
static_cast<uint32_t
>(bf16) << 16;
1885 std::memcpy(&result, &f,
sizeof(result));
1892uint32_t floatToTensorFloat32(
float value) {
1894 std::memcpy(&f, &value,
sizeof(f));
1895 uint32_t tf32 = f & 0xFFFFE000U;
1897 if ((f & 0x7F800000U) == 0x7F800000U && (f & 0x007FFFFFU) != 0 &&
1898 (tf32 & 0x007FFFFFU) == 0) {
1899 tf32 |= 0x00002000U;
1904float tensorFloat32ToFloat(uint32_t tf32) {
1906 std::memcpy(&result, &tf32,
sizeof(result));
1913uint8_t floatToFloat6(
float value) {
1915 std::memcpy(&f, &value,
sizeof(f));
1917 uint8_t sign = (f >> 26) & 0x20;
1918 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 3;
1919 uint32_t mantissa = f & 0x7FFFFF;
1922 if (((f >> 23) & 0xFF) == 0xFF) {
1925 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1926 return nan_sign | 0x1F;
1930 if (exponent > 7)
return sign | 0x1F;
1932 if (exponent <= 0) {
1934 if (exponent < -2)
return sign;
1935 mantissa |= 0x800000;
1936 uint32_t shift = 1 - exponent;
1938 return sign | ((mantissa >> 21) & 0x03);
1940 return sign | (exponent << 2) | ((mantissa >> 21) & 0x03);
1943float float6ToFloat(uint8_t f6) {
1947 float sign = (f6 & 0x20) ? -1.0f : 1.0f;
1948 uint32_t exponent = (f6 >> 2) & 0x07;
1949 uint32_t mantissa = f6 & 0x03;
1951 if (exponent == 0) {
1952 if (mantissa == 0) {
1956 return sign *
static_cast<float>(mantissa) * 0.0625f;
1959 float frac = 1.0f +
static_cast<float>(mantissa) / 4.0f;
1960 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 3);
1965uint8_t floatToFloat4(
float value) {
1967 std::memcpy(&f, &value,
sizeof(f));
1969 uint8_t sign = (f >> 28) & 0x08;
1970 int32_t exponent = ((f >> 23) & 0xFF) - 127 + 1;
1971 uint32_t mantissa = f & 0x7FFFFF;
1974 if (((f >> 23) & 0xFF) == 0xFF) {
1977 uint8_t nan_sign = (f & 0x7FFFFF) ? 0x00 : static_cast<uint8_t>(sign);
1978 return nan_sign | 0x07;
1982 if (exponent > 3)
return sign | 0x07;
1984 if (exponent <= 0) {
1986 if (exponent < -1)
return sign;
1987 mantissa |= 0x800000;
1988 uint32_t shift = 1 - exponent;
1990 return sign | ((mantissa >> 22) & 0x01);
1992 return sign | (exponent << 1) | ((mantissa >> 22) & 0x01);
1995float float4ToFloat(uint8_t f4) {
1999 float sign = (f4 & 0x08) ? -1.0f : 1.0f;
2000 uint32_t exponent = (f4 >> 1) & 0x03;
2001 uint32_t mantissa = f4 & 0x01;
2003 if (exponent == 0) {
2004 if (mantissa == 0) {
2008 return sign *
static_cast<float>(mantissa) * 0.5f;
2011 float frac = 1.0f +
static_cast<float>(mantissa) / 2.0f;
2012 return sign * std::ldexp(frac,
static_cast<int>(exponent) - 1);
2024void rim::Block::setFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2027 if (index == -1) index = 0;
2030 if (PyArray_Check(value.ptr())) {
2032 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2033 npy_intp ndims = PyArray_NDIM(arr);
2034 npy_intp* dims = PyArray_SHAPE(arr);
2035 npy_intp* strides = PyArray_STRIDES(arr);
2039 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2041 var->
name_.c_str()));
2045 "Overflow error for passed array with length %" PRIu32
2046 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2050 var->
name_.c_str()));
2052 if (PyArray_TYPE(arr) == NPY_HALF) {
2053 npy_half* src =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2054 npy_intp stride = strides[0] /
sizeof(npy_half);
2055 for (x = 0; x < dims[0]; x++) {
2056 float val = halfToFloat(src[x * stride]);
2057 setFloat16(val, var, index + x);
2061 "Passed nparray is not of type (float16) for %s",
2062 var->
name_.c_str()));
2066 }
else if (PyList_Check(value.ptr())) {
2067 bp::list vl = bp::extract<bp::list>(value);
2068 uint32_t vlen = len(vl);
2072 "Overflow error for passed array with length %" PRIu32
2073 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2077 var->
name_.c_str()));
2079 for (x = 0; x < vlen; x++) {
2080 bp::extract<float> tmp(vl[x]);
2084 "Failed to extract value for %s.",
2085 var->
name_.c_str()));
2087 setFloat16(tmp, var, index + x);
2091 }
else if (PyArray_CheckScalar(value.ptr())) {
2092 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_HALF) {
2094 PyArray_ScalarAsCtype(value.ptr(), &val);
2095 float fval = halfToFloat(val);
2096 setFloat16(fval, var, index);
2099 "Failed to extract value for %s.",
2100 var->
name_.c_str()));
2103 bp::extract<float> tmp(value);
2107 "Failed to extract value for %s.",
2108 var->
name_.c_str()));
2110 setFloat16(tmp, var, index);
2120 if (index < 0 && var->numValues_ > 0) {
2123 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_HALF);
2124 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2125 npy_half* dst =
reinterpret_cast<npy_half*
>(PyArray_DATA(arr));
2127 for (x = 0; x < var->
numValues_; x++) dst[x] = floatToHalf(getFloat16(var, x));
2129 boost::python::handle<> handle(obj);
2130 ret = bp::object(handle);
2133 PyObject* val = Py_BuildValue(
"f", getFloat16(var, index));
2137 bp::handle<> handle(val);
2138 ret = bp::object(handle);
2146void rim::Block::setFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2150 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2157 uint16_t half = floatToHalf(val);
2158 setBytes(
reinterpret_cast<uint8_t*
>(&half), var, index);
2165 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2167 return halfToFloat(tmp);
2177void rim::Block::setFloat8Py(bp::object& value,
rim::Variable* var, int32_t index) {
2180 if (index == -1) index = 0;
2183 if (PyArray_Check(value.ptr())) {
2185 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2186 npy_intp ndims = PyArray_NDIM(arr);
2187 npy_intp* dims = PyArray_SHAPE(arr);
2188 npy_intp* strides = PyArray_STRIDES(arr);
2192 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2194 var->
name_.c_str()));
2198 "Overflow error for passed array with length %" PRIu32
2199 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2203 var->
name_.c_str()));
2205 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2206 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2207 npy_intp stride = strides[0] /
sizeof(float);
2208 for (x = 0; x < dims[0]; x++) {
2209 float val = src[x * stride];
2210 setFloat8(val, var, index + x);
2214 "Passed nparray is not of type (float32) for %s",
2215 var->
name_.c_str()));
2219 }
else if (PyList_Check(value.ptr())) {
2220 bp::list vl = bp::extract<bp::list>(value);
2221 uint32_t vlen = len(vl);
2225 "Overflow error for passed array with length %" PRIu32
2226 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2230 var->
name_.c_str()));
2232 for (x = 0; x < vlen; x++) {
2233 bp::extract<float> tmp(vl[x]);
2237 "Failed to extract value for %s.",
2238 var->
name_.c_str()));
2240 setFloat8(tmp, var, index + x);
2244 bp::extract<float> tmp(value);
2248 "Failed to extract value for %s.",
2249 var->
name_.c_str()));
2251 setFloat8(tmp, var, index);
2261 if (index < 0 && var->numValues_ > 0) {
2263 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2264 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2265 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2267 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat8(var, x);
2269 boost::python::handle<> handle(obj);
2270 ret = bp::object(handle);
2273 PyObject* val = Py_BuildValue(
"f", getFloat8(var, index));
2277 bp::handle<> handle(val);
2278 ret = bp::object(handle);
2286void rim::Block::setFloat8(
const float& val,
rim::Variable* var, int32_t index) {
2290 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2297 uint8_t f8 = floatToFloat8(val);
2298 setBytes(
reinterpret_cast<uint8_t*
>(&f8), var, index);
2305 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2307 return float8ToFloat(tmp);
2317void rim::Block::setBFloat16Py(bp::object& value,
rim::Variable* var, int32_t index) {
2320 if (index == -1) index = 0;
2323 if (PyArray_Check(value.ptr())) {
2325 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2326 npy_intp ndims = PyArray_NDIM(arr);
2327 npy_intp* dims = PyArray_SHAPE(arr);
2328 npy_intp* strides = PyArray_STRIDES(arr);
2332 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2334 var->
name_.c_str()));
2338 "Overflow error for passed array with length %" PRIu32
2339 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2343 var->
name_.c_str()));
2345 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2346 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2347 npy_intp stride = strides[0] /
sizeof(float);
2348 for (x = 0; x < dims[0]; x++) {
2349 float val = src[x * stride];
2350 setBFloat16(val, var, index + x);
2354 "Passed nparray is not of type (float32) for %s",
2355 var->
name_.c_str()));
2359 }
else if (PyList_Check(value.ptr())) {
2360 bp::list vl = bp::extract<bp::list>(value);
2361 uint32_t vlen = len(vl);
2365 "Overflow error for passed array with length %" PRIu32
2366 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2370 var->
name_.c_str()));
2372 for (x = 0; x < vlen; x++) {
2373 bp::extract<float> tmp(vl[x]);
2377 "Failed to extract value for %s.",
2378 var->
name_.c_str()));
2380 setBFloat16(tmp, var, index + x);
2384 bp::extract<float> tmp(value);
2388 "Failed to extract value for %s.",
2389 var->
name_.c_str()));
2391 setBFloat16(tmp, var, index);
2401 if (index < 0 && var->numValues_ > 0) {
2403 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2404 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2405 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2407 for (x = 0; x < var->
numValues_; x++) dst[x] = getBFloat16(var, x);
2409 boost::python::handle<> handle(obj);
2410 ret = bp::object(handle);
2413 PyObject* val = Py_BuildValue(
"f", getBFloat16(var, index));
2417 bp::handle<> handle(val);
2418 ret = bp::object(handle);
2426void rim::Block::setBFloat16(
const float& val,
rim::Variable* var, int32_t index) {
2430 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2437 uint16_t bf16 = floatToBFloat16(val);
2438 setBytes(
reinterpret_cast<uint8_t*
>(&bf16), var, index);
2445 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2447 return bfloat16ToFloat(tmp);
2457void rim::Block::setTensorFloat32Py(bp::object& value,
rim::Variable* var, int32_t index) {
2460 if (index == -1) index = 0;
2463 if (PyArray_Check(value.ptr())) {
2465 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2466 npy_intp ndims = PyArray_NDIM(arr);
2467 npy_intp* dims = PyArray_SHAPE(arr);
2468 npy_intp* strides = PyArray_STRIDES(arr);
2472 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2474 var->
name_.c_str()));
2478 "Overflow error for passed array with length %" PRIu32
2479 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2483 var->
name_.c_str()));
2485 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2486 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2487 npy_intp stride = strides[0] /
sizeof(float);
2488 for (x = 0; x < dims[0]; x++) {
2489 float val = src[x * stride];
2490 setTensorFloat32(val, var, index + x);
2494 "Passed nparray is not of type (float32) for %s",
2495 var->
name_.c_str()));
2499 }
else if (PyList_Check(value.ptr())) {
2500 bp::list vl = bp::extract<bp::list>(value);
2501 uint32_t vlen = len(vl);
2505 "Overflow error for passed array with length %" PRIu32
2506 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2510 var->
name_.c_str()));
2512 for (x = 0; x < vlen; x++) {
2513 bp::extract<float> tmp(vl[x]);
2517 "Failed to extract value for %s.",
2518 var->
name_.c_str()));
2520 setTensorFloat32(tmp, var, index + x);
2524 bp::extract<float> tmp(value);
2528 "Failed to extract value for %s.",
2529 var->
name_.c_str()));
2531 setTensorFloat32(tmp, var, index);
2541 if (index < 0 && var->numValues_ > 0) {
2543 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2544 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2545 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2547 for (x = 0; x < var->
numValues_; x++) dst[x] = getTensorFloat32(var, x);
2549 boost::python::handle<> handle(obj);
2550 ret = bp::object(handle);
2553 PyObject* val = Py_BuildValue(
"f", getTensorFloat32(var, index));
2557 bp::handle<> handle(val);
2558 ret = bp::object(handle);
2566void rim::Block::setTensorFloat32(
const float& val,
rim::Variable* var, int32_t index) {
2570 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2577 uint32_t tf32 = floatToTensorFloat32(val);
2578 setBytes(
reinterpret_cast<uint8_t*
>(&tf32), var, index);
2585 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2587 return tensorFloat32ToFloat(tmp);
2597void rim::Block::setFloat6Py(bp::object& value,
rim::Variable* var, int32_t index) {
2600 if (index == -1) index = 0;
2603 if (PyArray_Check(value.ptr())) {
2605 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2606 npy_intp ndims = PyArray_NDIM(arr);
2607 npy_intp* dims = PyArray_SHAPE(arr);
2608 npy_intp* strides = PyArray_STRIDES(arr);
2612 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2614 var->
name_.c_str()));
2618 "Overflow error for passed array with length %" PRIu32
2619 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2623 var->
name_.c_str()));
2625 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2626 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2627 npy_intp stride = strides[0] /
sizeof(float);
2628 for (x = 0; x < dims[0]; x++) {
2629 float val = src[x * stride];
2630 setFloat6(val, var, index + x);
2634 "Passed nparray is not of type (float32) for %s",
2635 var->
name_.c_str()));
2639 }
else if (PyList_Check(value.ptr())) {
2640 bp::list vl = bp::extract<bp::list>(value);
2641 uint32_t vlen = len(vl);
2645 "Overflow error for passed array with length %" PRIu32
2646 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2650 var->
name_.c_str()));
2652 for (x = 0; x < vlen; x++) {
2653 bp::extract<float> tmp(vl[x]);
2657 "Failed to extract value for %s.",
2658 var->
name_.c_str()));
2660 setFloat6(tmp, var, index + x);
2664 bp::extract<float> tmp(value);
2668 "Failed to extract value for %s.",
2669 var->
name_.c_str()));
2671 setFloat6(tmp, var, index);
2681 if (index < 0 && var->numValues_ > 0) {
2683 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2684 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2685 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2687 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat6(var, x);
2689 boost::python::handle<> handle(obj);
2690 ret = bp::object(handle);
2693 PyObject* val = Py_BuildValue(
"f", getFloat6(var, index));
2697 bp::handle<> handle(val);
2698 ret = bp::object(handle);
2706void rim::Block::setFloat6(
const float& val,
rim::Variable* var, int32_t index) {
2710 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2717 uint8_t f6 = floatToFloat6(val);
2718 setBytes(
reinterpret_cast<uint8_t*
>(&f6), var, index);
2725 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2727 return float6ToFloat(tmp);
2737void rim::Block::setFloat4Py(bp::object& value,
rim::Variable* var, int32_t index) {
2740 if (index == -1) index = 0;
2743 if (PyArray_Check(value.ptr())) {
2745 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2746 npy_intp ndims = PyArray_NDIM(arr);
2747 npy_intp* dims = PyArray_SHAPE(arr);
2748 npy_intp* strides = PyArray_STRIDES(arr);
2752 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2754 var->
name_.c_str()));
2758 "Overflow error for passed array with length %" PRIu32
2759 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2763 var->
name_.c_str()));
2765 if (PyArray_TYPE(arr) == NPY_FLOAT) {
2766 float* src =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2767 npy_intp stride = strides[0] /
sizeof(float);
2768 for (x = 0; x < dims[0]; x++) {
2769 float val = src[x * stride];
2770 setFloat4(val, var, index + x);
2774 "Passed nparray is not of type (float32) for %s",
2775 var->
name_.c_str()));
2779 }
else if (PyList_Check(value.ptr())) {
2780 bp::list vl = bp::extract<bp::list>(value);
2781 uint32_t vlen = len(vl);
2785 "Overflow error for passed array with length %" PRIu32
2786 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2790 var->
name_.c_str()));
2792 for (x = 0; x < vlen; x++) {
2793 bp::extract<float> tmp(vl[x]);
2797 "Failed to extract value for %s.",
2798 var->
name_.c_str()));
2800 setFloat4(tmp, var, index + x);
2804 bp::extract<float> tmp(value);
2808 "Failed to extract value for %s.",
2809 var->
name_.c_str()));
2811 setFloat4(tmp, var, index);
2821 if (index < 0 && var->numValues_ > 0) {
2823 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT);
2824 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2825 float* dst =
reinterpret_cast<float*
>(PyArray_DATA(arr));
2827 for (x = 0; x < var->
numValues_; x++) dst[x] = getFloat4(var, x);
2829 boost::python::handle<> handle(obj);
2830 ret = bp::object(handle);
2833 PyObject* val = Py_BuildValue(
"f", getFloat4(var, index));
2837 bp::handle<> handle(val);
2838 ret = bp::object(handle);
2846void rim::Block::setFloat4(
const float& val,
rim::Variable* var, int32_t index) {
2850 "Value range error for %s. Value=%f, Min=%f, Max=%f",
2857 uint8_t f4 = floatToFloat4(val);
2858 setBytes(
reinterpret_cast<uint8_t*
>(&f4), var, index);
2865 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
2867 return float4ToFloat(tmp);
2877void rim::Block::setDoublePy(bp::object& value,
rim::Variable* var, int32_t index) {
2880 if (index == -1) index = 0;
2883 if (PyArray_Check(value.ptr())) {
2885 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
2886 npy_intp ndims = PyArray_NDIM(arr);
2887 npy_intp* dims = PyArray_SHAPE(arr);
2888 npy_intp* strides = PyArray_STRIDES(arr);
2892 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
2894 var->
name_.c_str()));
2898 "Overflow error for passed array with length %" PRIu32
2899 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2903 var->
name_.c_str()));
2905 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
2906 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2907 npy_intp stride = strides[0] /
sizeof(double);
2908 for (x = 0; x < dims[0]; x++) {
2909 setDouble(src[x * stride], var, index + x);
2913 "Passed nparray is not of type (double) for %s",
2914 var->
name_.c_str()));
2918 }
else if (PyList_Check(value.ptr())) {
2919 bp::list vl = bp::extract<bp::list>(value);
2920 uint32_t vlen = len(vl);
2924 "Overflow error for passed array with length %" PRIu32
2925 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
2929 var->
name_.c_str()));
2931 for (x = 0; x < vlen; x++) {
2932 bp::extract<double> tmp(vl[x]);
2936 "Failed to extract value for %s.",
2937 var->
name_.c_str()));
2939 setDouble(tmp, var, index + x);
2943 }
else if (PyArray_CheckScalar(value.ptr())) {
2944 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
2946 PyArray_ScalarAsCtype(value.ptr(), &val);
2947 setDouble(val, var, index);
2950 "Failed to extract value for %s.",
2951 var->
name_.c_str()));
2954 bp::extract<double> tmp(value);
2958 "Failed to extract value for %s.",
2959 var->
name_.c_str()));
2961 setDouble(tmp, var, index);
2971 if (index < 0 && var->numValues_ > 0) {
2974 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
2975 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
2976 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
2978 for (x = 0; x < var->
numValues_; x++) dst[x] = getDouble(var, x);
2980 boost::python::handle<> handle(obj);
2981 ret = bp::object(handle);
2984 PyObject* val = Py_BuildValue(
"d", getDouble(var, index));
2988 bp::handle<> handle(val);
2989 ret = bp::object(handle);
2997void rim::Block::setDouble(
const double& val,
rim::Variable* var, int32_t index) {
3001 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3007 setBytes(
reinterpret_cast<uint8_t*
>(
const_cast<double*
>(&val)), var, index);
3014 getBytes(
reinterpret_cast<uint8_t*
>(&tmp), var, index);
3026void rim::Block::setFixedPy(bp::object& value,
rim::Variable* var, int32_t index) {
3030 auto setScalar = [
this, var](
const double& v, int32_t idx) {
3032 setUFixed(v, var, idx);
3034 setFixed(v, var, idx);
3037 if (index == -1) index = 0;
3040 if (PyArray_Check(value.ptr())) {
3042 PyArrayObject* arr =
reinterpret_cast<decltype(arr)
>(value.ptr());
3043 npy_intp ndims = PyArray_NDIM(arr);
3044 npy_intp* dims = PyArray_SHAPE(arr);
3045 npy_intp* strides = PyArray_STRIDES(arr);
3049 "Invalid number of dimensions (%" PRIu32
") for passed ndarray for %s",
3051 var->
name_.c_str()));
3055 "Overflow error for passed array with length %" PRIu32
3056 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3060 var->
name_.c_str()));
3062 if (PyArray_TYPE(arr) == NPY_FLOAT64) {
3063 double* src =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3064 npy_intp stride = strides[0] /
sizeof(double);
3065 for (x = 0; x < dims[0]; x++) {
3066 setScalar(src[x * stride], index + x);
3070 "Passed nparray is not of type (double) for %s",
3071 var->
name_.c_str()));
3075 }
else if (PyList_Check(value.ptr())) {
3076 bp::list vl = bp::extract<bp::list>(value);
3077 uint32_t vlen = len(vl);
3081 "Overflow error for passed array with length %" PRIu32
3082 " at index %" PRIi32
". Variable length = %" PRIu32
" for %s",
3086 var->
name_.c_str()));
3088 for (x = 0; x < vlen; x++) {
3089 bp::extract<double> tmp(vl[x]);
3093 "Failed to extract value for %s.",
3094 var->
name_.c_str()));
3096 setScalar(tmp, index + x);
3100 }
else if (PyArray_CheckScalar(value.ptr())) {
3101 if (PyArray_DescrFromScalar(value.ptr())->type_num == NPY_FLOAT64) {
3103 PyArray_ScalarAsCtype(value.ptr(), &val);
3104 setScalar(val, index);
3107 "Failed to extract value for %s.",
3108 var->
name_.c_str()));
3111 bp::extract<double> tmp(value);
3115 "Failed to extract value for %s.",
3116 var->
name_.c_str()));
3118 setScalar(tmp, index);
3128 auto getScalar = [
this, var](int32_t idx) ->
double {
3133 if (index < 0 && var->numValues_ > 0) {
3136 PyObject* obj = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
3137 PyArrayObject* arr =
reinterpret_cast<PyArrayObject*
>(obj);
3138 double* dst =
reinterpret_cast<double*
>(PyArray_DATA(arr));
3140 for (x = 0; x < var->
numValues_; x++) dst[x] = getScalar(x);
3142 boost::python::handle<> handle(obj);
3143 ret = bp::object(handle);
3146 PyObject* val = Py_BuildValue(
"d", getScalar(index));
3150 bp::handle<> handle(val);
3151 ret = bp::object(handle);
3159void rim::Block::setFixed(
const double& val,
rim::Variable* var, int32_t index) {
3163 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3170 int64_t fPoint =
static_cast<int64_t
>(round(val * pow(2, var->
binPoint_)));
3173 int64_t maxInt =
static_cast<int64_t
>((1ULL << (var->
valueBits_ - 1)) - 1);
3174 int64_t minInt = -maxInt - 1;
3177 if (fPoint > maxInt || fPoint < minInt)
3179 "Fixed point overflow for %s. Value=%f, Min=%f, Max=%f",
3182 static_cast<double>(minInt) / pow(2, var->
binPoint_),
3183 static_cast<double>(maxInt) / pow(2, var->
binPoint_)));
3185 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3193 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3198 const int64_t signBit = 1LL << (var->
valueBits_ - 1);
3199 const int64_t modulus = 1LL << var->
valueBits_;
3200 if ((fPoint & signBit) != 0) fPoint -= modulus;
3204 tmp =
static_cast<double>(fPoint);
3210void rim::Block::setUFixed(
const double& val,
rim::Variable* var, int32_t index) {
3214 "Value range error for %s. Value=%f, Min=%f, Max=%f",
3223 "Unsigned fixed-point underflow for %s. Value=%f",
3227 uint64_t fPoint =
static_cast<uint64_t
>(round(val * pow(2, var->
binPoint_)));
3234 if (fPoint > maxUInt)
3236 "Unsigned fixed-point overflow for %s. Value=%f, Min=0, Max=%f",
3239 static_cast<double>(maxUInt) / pow(2, var->
binPoint_)));
3241 setBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3246 uint64_t fPoint = 0;
3248 getBytes(
reinterpret_cast<uint8_t*
>(&fPoint), var, index);
3250 return static_cast<double>(fPoint) / pow(2, var->
binPoint_);
3258void rim::Block::customInit() {}
3261void rim::Block::customClean() {}
3263void rim::Block::rateTest() {
3266 struct timeval stime;
3267 struct timeval etime;
3268 struct timeval dtime;
3270 uint64_t count = 1000000;
3275 gettimeofday(&stime, NULL);
3277 for (x = 0; x < count; ++x) {
3278 reqTransaction(0, 4, &value,
rim::Read);
3281 gettimeofday(&etime, NULL);
3283 timersub(&etime, &stime, &dtime);
3284 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3285 rate = count / durr;
3287 printf(
"\nBlock c++ raw: Read %" PRIu64
" times in %f seconds. Rate = %f\n", count, durr, rate);
3289 gettimeofday(&stime, NULL);
3291 for (x = 0; x < count; ++x) {
3292 reqTransaction(0, 4,
reinterpret_cast<uint8_t*
>(&count),
rim::Write);
3295 gettimeofday(&etime, NULL);
3297 timersub(&etime, &stime, &dtime);
3298 durr = dtime.tv_sec +
static_cast<float>(dtime.tv_usec) / 1.0e6;
3299 rate = count / durr;
3301 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