diff options
m--------- | fpga-src | 0 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/block_ctrl_base.hpp | 3 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/constants.hpp | 2 | ||||
-rw-r--r-- | host/lib/rfnoc/block_ctrl_base.cpp | 86 | ||||
-rw-r--r-- | host/lib/usrp/device3/device3_io_impl.cpp | 6 | ||||
-rw-r--r-- | images/manifest.txt | 10 |
6 files changed, 97 insertions, 10 deletions
diff --git a/fpga-src b/fpga-src -Subproject 2e310fae0a6a7354c250fca36060daaeaac1535 +Subproject f27926410328883a315d5230146936d2d782bd0 diff --git a/host/include/uhd/rfnoc/block_ctrl_base.hpp b/host/include/uhd/rfnoc/block_ctrl_base.hpp index 63939a114..0405ed8b7 100644 --- a/host/include/uhd/rfnoc/block_ctrl_base.hpp +++ b/host/include/uhd/rfnoc/block_ctrl_base.hpp @@ -401,6 +401,9 @@ private: //! Helper to create a lambda to read tick rate double get_command_tick_rate(const size_t port); + //! Helper to flush any in-flight packets for this block + bool _flush(const size_t port = 0); + /*********************************************************************** * Private members **********************************************************************/ diff --git a/host/include/uhd/rfnoc/constants.hpp b/host/include/uhd/rfnoc/constants.hpp index 94cca3e7a..6df4c535f 100644 --- a/host/include/uhd/rfnoc/constants.hpp +++ b/host/include/uhd/rfnoc/constants.hpp @@ -25,7 +25,7 @@ static const std::string XML_PATH_ENV = "UHD_RFNOC_DIR"; //! If the block name can't be automatically detected, this name is used static const std::string DEFAULT_BLOCK_NAME = "Block"; static const uint64_t DEFAULT_NOC_ID = 0xFFFFFFFFFFFFFFFF; -static const size_t NOC_SHELL_COMPAT_MAJOR = 2; +static const size_t NOC_SHELL_COMPAT_MAJOR = 3; static const size_t NOC_SHELL_COMPAT_MINOR = 0; static const size_t MAX_PACKET_SIZE = 8000; // bytes diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp index 0b9f6d281..c7884f291 100644 --- a/host/lib/rfnoc/block_ctrl_base.cpp +++ b/host/lib/rfnoc/block_ctrl_base.cpp @@ -19,6 +19,8 @@ #include <uhdlib/rfnoc/wb_iface_adapter.hpp> #include <boost/format.hpp> #include <boost/bind.hpp> +#include <chrono> +#include <thread> using namespace uhd; using namespace uhd::rfnoc; @@ -72,6 +74,20 @@ block_ctrl_base::block_ctrl_base( _tree->create<uint64_t>(_root_path / "noc_id").set(_noc_id); /*** Reset block state *******************************************/ + // We don't know the state of the data-path of this block before + // we initialize. If everything tore down properly, the data-path + // should be disconnected and thus idle. Reconfiguration of parameters + // like SIDs is safe to do in that scenario. + // However, if data is still streaming, block configuration + // can potentially lock up noc_shell. So we flush the data-path here. + + // Flush is a block-level operation that can be triggered + // from any block port. + // Do it once before clearing... + if (get_ctrl_ports().size() > 0) { + _flush(get_ctrl_ports().front()); + } + // Clear flow control and misc state clear(); /*** Configure ports ****************************************************/ @@ -129,6 +145,17 @@ block_ctrl_base::block_ctrl_base( block_ctrl_base::~block_ctrl_base() { + if (get_ctrl_ports().size() > 0) { + // Notify the data-path gatekeeper in noc_shell that we are done + // with this block. This operation disconnects the noc_block + // data-path from noc_shell which dumps all input and output + // packets that are in flight, for now and until the setting is + // disabled. This prevents long-running blocks without a tear-down + // mechanism to gracefully flush. + const size_t port = get_ctrl_ports().front(); + sr_write(SR_CLEAR_TX_FC, 0x2, port); // Disconnect TX data-path + sr_write(SR_CLEAR_RX_FC, 0x2, port); // Disconnect RX data-path + } _tree->remove(_root_path); } @@ -558,6 +585,59 @@ stream_sig_t block_ctrl_base::_resolve_port_def(const blockdef::port_t &port_def return stream_sig; } +bool block_ctrl_base::_flush(const size_t port) +{ + UHD_LOG_DEBUG(unique_id(), "block_ctrl_base::_flush()"); + + auto is_data_streaming = [this](int time_ms) -> bool { + // noc_shell has 2 16-bit counters (one for TX and one for RX) in the top + // 32 bits of the SR_READBACK_REG_GLOBAL_PARAMS. For all the checks below + // we want to make sure that the counts are not changing i.e. no data is + // streaming. So we just look at the two counters together as a single + // 32-bit quantity. + auto old_cnts = static_cast<uint32_t>(this->sr_read64(SR_READBACK_REG_GLOBAL_PARAMS) >> 32); + std::this_thread::sleep_for(std::chrono::milliseconds(time_ms)); + auto new_cnts = static_cast<uint32_t>(this->sr_read64(SR_READBACK_REG_GLOBAL_PARAMS) >> 32); + return (new_cnts != old_cnts); + }; + + // Initial check for activity + // We use a 10ms window to check for activity which detects a stream with approx + // 100 packets per second + constexpr int INITIAL_CHK_WINDOW_MS = 10; + if (not is_data_streaming(INITIAL_CHK_WINDOW_MS)) return true; + + UHD_LOG_DEBUG(unique_id(), "block_ctrl_base::_flush(recovery mode)"); + // We noticed streaming data. This is most likely because the last + // session terminated abnormally or if logic in a noc_block is + // misbehaving. This is a situation that we may not be able to + // recover from because we are in a partially initialized state. + // We will try to at least not lock up the FPGA. + + // Disconnect the RX and TX data paths and let them flush. + // A timeout of 2s is chosen to be conservative. It needs to account for: + // - Upstream blocks that weren't terminated to run out of FC credits + // - This block which might be finishing up with its data output + constexpr int FLUSH_TIMEOUT_MS = 2000; // This is approximate + bool success = false; + sr_write(SR_CLEAR_TX_FC, 0x2, port); // Disconnect TX data-path + sr_write(SR_CLEAR_RX_FC, 0x2, port); // Disconnect RX data-path + for (int i = 0; i < FLUSH_TIMEOUT_MS/10; i++) { + if (not is_data_streaming(10)) { + success = true; + break; + } + } + sr_write(SR_CLEAR_TX_FC, 0x0, port); // Enable TX data-path + sr_write(SR_CLEAR_RX_FC, 0x0, port); // Enable RX data-path + + UHD_LOGGER_WARNING(unique_id()) << + "This block seems to be busy most likely due to the abnormal termination of a previous session. " << + "Attempted recovery but it may not have worked depending on the behavior of other blocks in the design. " << + "Please restart the application."; + return success; +} + /*********************************************************************** * Hooks & Derivables @@ -565,8 +645,10 @@ stream_sig_t block_ctrl_base::_resolve_port_def(const blockdef::port_t &port_def void block_ctrl_base::_clear(const size_t port) { UHD_LOG_TRACE(unique_id(), "block_ctrl_base::_clear()"); - sr_write(SR_CLEAR_TX_FC, 0x00C1EA12, port); // 'CLEAR', but we can write anything, really - sr_write(SR_CLEAR_RX_FC, 0x00C1EA12, port); // 'CLEAR', but we can write anything, really + sr_write(SR_CLEAR_TX_FC, 0x1, port); // Write 1 to trigger a single cycle clear event + sr_write(SR_CLEAR_TX_FC, 0x0, port); // Write 0 to reset the clear flag + sr_write(SR_CLEAR_RX_FC, 0x1, port); // Write 1 to trigger a single cycle clear event + sr_write(SR_CLEAR_RX_FC, 0x0, port); // Write 0 to reset the clear flag } void block_ctrl_base::_set_command_time(const time_spec_t & /*time_spec*/, const size_t /*port*/) diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index 236269ceb..8882552af 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -556,7 +556,8 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) // See noc_shell.v, in the section called Stream Source for details. // Setting SR_CLEAR_TX_FC will actually also clear the destination and // other settings. - blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_TX_FC, 0xc1ea12, block_port); + blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_TX_FC, 0x1, block_port); + blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_TX_FC, 0x0, block_port); blk_ctrl->set_destination(xport.send_sid.get_src(), block_port); blk_ctrl->sr_write(uhd::rfnoc::SR_RESP_OUT_DST_SID, xport.send_sid.get_src(), block_port); @@ -845,7 +846,8 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) "tx_async_msgs_task" ); - blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0xc1ea12, block_port); + blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x1, block_port); + blk_ctrl->sr_write(uhd::rfnoc::SR_CLEAR_RX_FC, 0x0, block_port); blk_ctrl->sr_write(uhd::rfnoc::SR_RESP_IN_DST_SID, my_streamer->_async_xport.recv_sid.get_dst(), block_port); UHD_TX_STREAMER_LOG() << "resp_in_dst_sid == " << boost::format("0x%04X") % xport.recv_sid.get_dst() ; diff --git a/images/manifest.txt b/images/manifest.txt index 3fcf88342..266f564ab 100644 --- a/images/manifest.txt +++ b/images/manifest.txt @@ -1,18 +1,18 @@ # UHD Image Manifest File # Target hash url SHA256 # X300-Series -x3xx_x310_fpga_default fpga-1107862 x3xx/fpga-1107862/x3xx_x310_fpga_default-g1107862.zip e1f59031b7c7f5fa166a46636c7b12df6ede5470138cfb71e3860e2945f180e8 -x3xx_x300_fpga_default fpga-1107862 x3xx/fpga-1107862/x3xx_x300_fpga_default-g1107862.zip f90a760837bea61d144cf9940ac24db72959ad075444de0d94c2724a78beb402 +x3xx_x310_fpga_default fpga-f279264 x3xx/fpga-f279264/x3xx_x310_fpga_default-gf279264.zip a9d0f4b9f75bca4724333f3320989b2f9a56cf75e3a7bc569b4e868af3feb095 +x3xx_x300_fpga_default fpga-f279264 x3xx/fpga-f279264/x3xx_x300_fpga_default-gf279264.zip 872c3833dc03ed8ff5a6dea2053d7ccb353a63ba760b82c4a48c3c3b839a725c # Example daughterboard targets (none currently exist) #x3xx_twinrx_cpld_default example_target #dboard_ubx_cpld_default example_target # E-Series -e3xx_e310_fpga_default fpga-1107862 e3xx/fpga-1107862/e3xx_e310_fpga_default-g1107862.zip 52f8451fd459b2a3113903284adea11474a9efb8eaef45b986233c0693f10549 +e3xx_e310_fpga_default fpga-f279264 e3xx/fpga-f279264/e3xx_e310_fpga_default-gf279264.zip 707428e8703b29ad9df60725f25fed78223deab5f4a7becf4ed1886b43f18f92 e3xx_e310_fpga_rfnoc fpga-d6a878b e3xx/fpga-d6a878b/e3xx_e310_fpga_rfnoc-gd6a878b.zip 5c9b89fb6293423644868c22e914de386a9af39ff031da6800a1cf39a90ea73b # N300-Series -n3xx_n310_fpga_default fpga-1107862 n3xx/fpga-1107862/n3xx_n310_fpga_default-g1107862.zip fc80462f2e144d9745b0b480aa513f426e48df46ad18dc85cbb8fdb3cb162355 -n3xx_n300_fpga_default fpga-1107862 n3xx/fpga-1107862/n3xx_n300_fpga_default-g1107862.zip 1e7ae1429825811531149f87f82dfcbc06cf63e1fc3752517edf104950406c36 +n3xx_n310_fpga_default fpga-f279264 n3xx/fpga-f279264/n3xx_n310_fpga_default-gf279264.zip e31c2a71014e7fdb140e00ef3f6e9814b720e0f8de4544d2bad8a50cf1c61ce1 +n3xx_n300_fpga_default fpga-f279264 n3xx/fpga-f279264/n3xx_n300_fpga_default-gf279264.zip 83f880d2b79f666a8fe660aa949cd1c1eaf5256d31036696fd270ae59491acc6 #n3xx_n310_fpga_aurora fpga-1107862 n3xx/fpga-1107862/n3xx_n310_fpga_aurora-g1107862.zip 3926d6b247a8f931809460d3957cec51f8407cd3f7aea6f4f3b91d1bbb427c7d #n3xx_n300_fpga_aurora fpga-1107862 n3xx/fpga-1107862/n3xx_n300_fpga_aurora-g1107862.zip e34e9343572adfba905433a1570cb394fe45207d442268d0fa400c3406253530 #n3xx_n310_cpld_default fpga-6bea23d n3xx/fpga-6bea23d/n3xx_n310_cpld_default-g6bea23d.zip 0 |