// // Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #pragma once #include #include #include #include namespace py = pybind11; using namespace uhd::utils::chdr; namespace chdr_rfnoc = uhd::rfnoc::chdr; template void export_utils_with_payload( pybind11::class_& packet_class, std::string packet_name) { std::string get_payload_name("get_payload_"); get_payload_name.append(packet_name); std::string to_string_with_payload_name("to_string_with_payload_"); to_string_with_payload_name.append(packet_name); packet_class .def(py::init([](uhd::rfnoc::chdr_w_t chdr_w, chdr_rfnoc::chdr_header header, payload_t payload, boost::optional timestamp, std::vector metadata) { return chdr_packet(chdr_w, header, payload, timestamp, metadata); }), py::arg("chdr_w"), py::arg("header"), py::arg("payload"), py::arg("timestamp") = boost::optional(), py::arg("metadata") = std::vector()) .def(get_payload_name.c_str(), &chdr_packet::get_payload, py::arg("endianness") = uhd::ENDIANNESS_LITTLE) .def("set_payload", &chdr_packet::set_payload, py::arg("payload"), py::arg("endianness") = uhd::ENDIANNESS_LITTLE) .def(to_string_with_payload_name.c_str(), &chdr_packet::to_string_with_payload, py::arg("endianness") = uhd::ENDIANNESS_LITTLE); } void export_utils(py::module& m) { py::enum_(m, "Endianness") .value("LITTLE", uhd::ENDIANNESS_LITTLE) .value("BIG", uhd::ENDIANNESS_BIG); py::enum_(m, "ChdrWidth") .value("W64", uhd::rfnoc::CHDR_W_64) .value("W128", uhd::rfnoc::CHDR_W_128) .value("W256", uhd::rfnoc::CHDR_W_256) .value("W512", uhd::rfnoc::CHDR_W_512); pybind11::class_ packet_class = py::class_(m, "ChdrPacket") .def(py::init([](uhd::rfnoc::chdr_w_t chdr_w, chdr_rfnoc::chdr_header header, py::bytes& payload, boost::optional timestamp, py::bytes& metadata) { return chdr_packet(chdr_w, header, pybytes_to_vector(payload), timestamp, pybytes_to_u64_vector(metadata)); }), py::arg("chdr_w"), py::arg("header"), py::arg("payload"), py::arg("timestamp") = boost::optional(), py::arg("metadata") = py::bytes()) // Methods .def("__str__", &chdr_packet::to_string) .def("__repr__", &chdr_packet::to_string) .def("get_header", &chdr_packet::get_header) .def("set_header", &chdr_packet::set_header) .def("get_timestamp", &chdr_packet::get_timestamp) .def("set_timestamp", &chdr_packet::set_timestamp) .def("get_metadata", &chdr_packet::get_metadata) .def("serialize", &chdr_packet::serialize_to_byte_vector, py::arg("endianness") = uhd::ENDIANNESS_LITTLE) .def_static( "deserialize", [](uhd::rfnoc::chdr_w_t chdr_w, std::vector bytes, uhd::endianness_t endianness) { return chdr_packet::deserialize( chdr_w, bytes.begin(), bytes.end(), endianness); }, py::arg("chdr_w"), py::arg("bytes"), py::arg("endianness") = uhd::ENDIANNESS_LITTLE) .def_static( "deserialize", [](uhd::rfnoc::chdr_w_t chdr_w, py::bytes bytes, uhd::endianness_t endianness) { std::vector vector = pybytes_to_vector(bytes); return chdr_packet::deserialize( chdr_w, vector.begin(), vector.end(), endianness); }, py::arg("chdr_w"), py::arg("bytes"), py::arg("endianness") = uhd::ENDIANNESS_LITTLE) .def("get_packet_len", &chdr_packet::get_packet_len) .def("get_payload_bytes", &chdr_packet::get_payload_bytes) .def("set_payload_bytes", &chdr_packet::set_payload_bytes) .def("set_payload_bytes", [](chdr_packet& self, py::bytes bytes) { auto bytes_vector = pybytes_to_vector(bytes); self.set_payload_bytes(bytes_vector); }); export_utils_with_payload(packet_class, "ctrl"); export_utils_with_payload(packet_class, "mgmt"); export_utils_with_payload(packet_class, "strs"); export_utils_with_payload(packet_class, "strc"); py::class_(m, "ChdrHeader") // Constructor .def(py::init<>()) // Methods .def("__str__", &chdr_rfnoc::chdr_header::to_string) .def("__repr__", &chdr_rfnoc::chdr_header::to_string) // Properties .def_property( "vc", &chdr_rfnoc::chdr_header::get_vc, &chdr_rfnoc::chdr_header::set_vc) .def_property( "eob", &chdr_rfnoc::chdr_header::get_eob, &chdr_rfnoc::chdr_header::set_eob) .def_property( "eov", &chdr_rfnoc::chdr_header::get_eov, &chdr_rfnoc::chdr_header::set_eov) .def_property("pkt_type", &chdr_rfnoc::chdr_header::get_pkt_type, &chdr_rfnoc::chdr_header::set_pkt_type) .def_property("seq_num", &chdr_rfnoc::chdr_header::get_seq_num, &chdr_rfnoc::chdr_header::set_seq_num) .def_property("length", &chdr_rfnoc::chdr_header::get_length, &chdr_rfnoc::chdr_header::set_length) .def_property("dst_epid", &chdr_rfnoc::chdr_header::get_dst_epid, &chdr_rfnoc::chdr_header::set_dst_epid) .def_property("num_mdata", &chdr_rfnoc::chdr_header::get_num_mdata, &chdr_rfnoc::chdr_header::set_num_mdata) .def("pack", &chdr_rfnoc::chdr_header::pack); py::enum_(m, "PacketType") .value("MGMT", chdr_rfnoc::PKT_TYPE_MGMT) .value("STRS", chdr_rfnoc::PKT_TYPE_STRS) .value("STRC", chdr_rfnoc::PKT_TYPE_STRC) .value("CTRL", chdr_rfnoc::PKT_TYPE_CTRL) .value("DATA_NO_TS", chdr_rfnoc::PKT_TYPE_DATA_NO_TS) .value("DATA_WITH_TS", chdr_rfnoc::PKT_TYPE_DATA_WITH_TS); py::class_(m, "CtrlPayload") // Constructor .def(py::init<>()) // Methods .def("has_timestamp", &chdr_rfnoc::ctrl_payload::has_timestamp) .def_readwrite("dst_port", &chdr_rfnoc::ctrl_payload::dst_port) .def_readwrite("src_port", &chdr_rfnoc::ctrl_payload::src_port) .def_readwrite("seq_num", &chdr_rfnoc::ctrl_payload::seq_num) .def_readwrite("timestamp", &chdr_rfnoc::ctrl_payload::timestamp) .def_readwrite("is_ack", &chdr_rfnoc::ctrl_payload::is_ack) .def_readwrite("src_epid", &chdr_rfnoc::ctrl_payload::src_epid) .def_readwrite("address", &chdr_rfnoc::ctrl_payload::address) .def_readwrite("byte_enable", &chdr_rfnoc::ctrl_payload::byte_enable) .def_readwrite("op_code", &chdr_rfnoc::ctrl_payload::op_code) .def_readwrite("status", &chdr_rfnoc::ctrl_payload::status) .def("get_data", [](chdr_rfnoc::ctrl_payload& self) -> std::vector { return self.data_vtr; }) .def("set_data", [](chdr_rfnoc::ctrl_payload& self, std::vector data) { self.data_vtr = data; }) .def("__str__", &chdr_rfnoc::ctrl_payload::to_string) .def("__repr__", &chdr_rfnoc::ctrl_payload::to_string); py::enum_(m, "CtrlStatus") .value("OKAY", chdr_rfnoc::CMD_OKAY) .value("CMDERR", chdr_rfnoc::CMD_CMDERR) .value("TSERR", chdr_rfnoc::CMD_TSERR) .value("WARNING", chdr_rfnoc::CMD_WARNING); py::enum_(m, "CtrlOpCode") .value("SLEEP", chdr_rfnoc::OP_SLEEP) .value("WRITE", chdr_rfnoc::OP_WRITE) .value("READ", chdr_rfnoc::OP_READ) .value("READ_WRITE", chdr_rfnoc::OP_READ_WRITE) .value("BLOCK_WRITE", chdr_rfnoc::OP_BLOCK_WRITE) .value("BLOCK_READ", chdr_rfnoc::OP_BLOCK_READ) .value("POLL", chdr_rfnoc::OP_POLL) .value("USER1", chdr_rfnoc::OP_USER1) .value("USER2", chdr_rfnoc::OP_USER2) .value("USER3", chdr_rfnoc::OP_USER3) .value("USER4", chdr_rfnoc::OP_USER4) .value("USER5", chdr_rfnoc::OP_USER5) .value("USER6", chdr_rfnoc::OP_USER6); py::class_(m, "MgmtPayload") // Constructor .def(py::init<>()) // Methods .def("set_header", &chdr_rfnoc::mgmt_payload::set_header, py::arg("src_epid"), py::arg("proto_ver"), py::arg("chdr_w")) .def("add_hop", &chdr_rfnoc::mgmt_payload::add_hop) .def("get_num_hops", &chdr_rfnoc::mgmt_payload::get_num_hops) .def("get_hop", &chdr_rfnoc::mgmt_payload::get_hop, py::return_value_policy::reference_internal) .def("pop_hop", &chdr_rfnoc::mgmt_payload::pop_hop) .def_property("src_epid", &chdr_rfnoc::mgmt_payload::get_src_epid, &chdr_rfnoc::mgmt_payload::set_src_epid) .def_property("chdr_w", &chdr_rfnoc::mgmt_payload::get_chdr_w, &chdr_rfnoc::mgmt_payload::set_chdr_w) .def_property("proto_ver", &chdr_rfnoc::mgmt_payload::get_proto_ver, &chdr_rfnoc::mgmt_payload::set_proto_ver) .def("__str__", &chdr_rfnoc::mgmt_payload::to_string) .def("__repr__", &chdr_rfnoc::mgmt_payload::to_string) .def("hops_to_string", &chdr_rfnoc::mgmt_payload::hops_to_string); py::class_(m, "MgmtHop") // Constructor .def(py::init<>()) // Methods .def("add_op", &chdr_rfnoc::mgmt_hop_t::add_op) .def("get_num_ops", &chdr_rfnoc::mgmt_hop_t::get_num_ops) .def("get_op", &chdr_rfnoc::mgmt_hop_t::get_op, py::return_value_policy::reference_internal) .def("__str__", &chdr_rfnoc::mgmt_hop_t::to_string) .def("__repr__", &chdr_rfnoc::mgmt_hop_t::to_string); py::class_(m, "MgmtOp") // Constructor .def(py::init(), py::arg("op_code"), py::arg("op_payload") = 0) .def(py::init(), py::arg("op_code"), py::arg("op_payload")) .def(py::init(), py::arg("op_code"), py::arg("op_payload")) .def(py::init(), py::arg("op_code"), py::arg("op_payload")) // Methods .def_property_readonly("op_code", &chdr_rfnoc::mgmt_op_t::get_op_code) .def("get_op_payload", &chdr_rfnoc::mgmt_op_t::get_op_payload) .def("__str__", &chdr_rfnoc::mgmt_op_t::to_string) .def("__repr__", &chdr_rfnoc::mgmt_op_t::to_string); py::enum_(m, "MgmtOpCode") .value("NOP", chdr_rfnoc::mgmt_op_t::MGMT_OP_NOP) .value("ADVERTISE", chdr_rfnoc::mgmt_op_t::MGMT_OP_ADVERTISE) .value("SEL_DEST", chdr_rfnoc::mgmt_op_t::MGMT_OP_SEL_DEST) .value("RETURN", chdr_rfnoc::mgmt_op_t::MGMT_OP_RETURN) .value("INFO_REQ", chdr_rfnoc::mgmt_op_t::MGMT_OP_INFO_REQ) .value("INFO_RESP", chdr_rfnoc::mgmt_op_t::MGMT_OP_INFO_RESP) .value("CFG_WR_REQ", chdr_rfnoc::mgmt_op_t::MGMT_OP_CFG_WR_REQ) .value("CFG_RD_REQ", chdr_rfnoc::mgmt_op_t::MGMT_OP_CFG_RD_REQ) .value("CFG_RD_RESP", chdr_rfnoc::mgmt_op_t::MGMT_OP_CFG_RD_RESP); py::class_(m, "MgmtOpSelDest") .def(py::init()) .def_readonly("dest", &chdr_rfnoc::mgmt_op_t::sel_dest_payload::dest) .def_static( "parse", [](uint64_t value) -> chdr_rfnoc::mgmt_op_t::sel_dest_payload { return value; }); py::class_(m, "MgmtOpCfg") .def(py::init(), py::arg("addr"), py::arg("data")) .def_readonly("addr", &chdr_rfnoc::mgmt_op_t::cfg_payload::addr) .def_readonly("data", &chdr_rfnoc::mgmt_op_t::cfg_payload::data) .def_static("parse", [](uint64_t value) -> chdr_rfnoc::mgmt_op_t::cfg_payload { return value; }); py::class_(m, "MgmtOpNodeInfo") .def(py::init(), py::arg("device_id"), py::arg("node_type"), py::arg("node_inst"), py::arg("ext_info")) .def_readonly("device_id", &chdr_rfnoc::mgmt_op_t::node_info_payload::device_id) .def_readonly("node_type", &chdr_rfnoc::mgmt_op_t::node_info_payload::node_type) .def_readonly("node_inst", &chdr_rfnoc::mgmt_op_t::node_info_payload::node_inst) .def_readonly("ext_info", &chdr_rfnoc::mgmt_op_t::node_info_payload::ext_info) .def_static( "parse", [](uint64_t value) -> chdr_rfnoc::mgmt_op_t::node_info_payload { return value; }); py::class_(m, "StrsPayload") // Constructor .def(py::init<>()) // Methods .def_readwrite("src_epid", &chdr_rfnoc::strs_payload::src_epid) .def_readwrite("status", &chdr_rfnoc::strs_payload::status) .def_readwrite("capacity_bytes", &chdr_rfnoc::strs_payload::capacity_bytes) .def_readwrite("capacity_pkts", &chdr_rfnoc::strs_payload::capacity_pkts) .def_readwrite("xfer_count_bytes", &chdr_rfnoc::strs_payload::xfer_count_bytes) .def_readwrite("xfer_count_pkts", &chdr_rfnoc::strs_payload::xfer_count_pkts) .def_readwrite("buff_info", &chdr_rfnoc::strs_payload::buff_info) .def_readwrite("status_info", &chdr_rfnoc::strs_payload::status_info) .def("__str__", &chdr_rfnoc::strs_payload::to_string) .def("__repr__", &chdr_rfnoc::strs_payload::to_string); py::enum_(m, "StrsStatus") .value("OKAY", chdr_rfnoc::STRS_OKAY) .value("CMDERR", chdr_rfnoc::STRS_CMDERR) .value("SEQERR", chdr_rfnoc::STRS_SEQERR) .value("DATAERR", chdr_rfnoc::STRS_DATAERR) .value("RTERR", chdr_rfnoc::STRS_RTERR); py::class_(m, "StrcPayload") // Constructor .def(py::init<>()) // Methods .def_readwrite("src_epid", &chdr_rfnoc::strc_payload::src_epid) .def_readwrite("op_code", &chdr_rfnoc::strc_payload::op_code) .def_readwrite("op_data", &chdr_rfnoc::strc_payload::op_data) .def_readwrite("num_pkts", &chdr_rfnoc::strc_payload::num_pkts) .def_readwrite("num_bytes", &chdr_rfnoc::strc_payload::num_bytes) .def("__str__", &chdr_rfnoc::strc_payload::to_string) .def("__repr__", &chdr_rfnoc::strc_payload::to_string); py::enum_(m, "StrcOpCode") .value("INIT", chdr_rfnoc::STRC_INIT) .value("PING", chdr_rfnoc::STRC_PING) .value("RESYNC", chdr_rfnoc::STRC_RESYNC); }