So, the corruption does not occur anymore (to my knowledge) because I fixed
the bug in my software that would allow replay_play() to get called in some
situations prior to replay_store().  But, I'm a bit concerned that perhaps
my code could have a bug in another place that could allow this to happen.
That is why I was hoping to be able to guarantee a reset situation upon UHD
"make" or with a specific "reset" function to the replay block. This bug
was particularly bad because there was no indication of anything wrong
(e.g., Under/Overruns, Lates, other errors) and we didn't find out about it
until we started analyzing data that we had collected over several hours
last Friday.
Rob

On Thu, Oct 15, 2020 at 12:35 PM Wade Fife <wade.f...@ettus.com> wrote:

> Hi Rob,
>
> All the blocks should get reset when you create the RFNoC graph. But the
> DRAM controller and related AXI4 interconnect are outside of RFNoC, so it
> doesn't get reset when the blocks are reset. It's possible that the DRAM
> logic is in a bad state as well. It doesn't look like there's a way
> currently to reset the DRAM logic on demand.
>
> Does the corruption still occur after fixing the bug you mentioned?
>
> Wade
>
>
>
> On Wed, Oct 14, 2020 at 6:10 PM Rob Kossler via USRP-users <
> usrp-users@lists.ettus.com> wrote:
>
>> Hi,
>> I am using the Replay block and I ran into an issue where I have gotten
>> the Replay block into a bad state which I can't seem to fix short of
>> rebooting the N310.  The way I know it is in a bad state is that the data
>> playing out is corrupted.  Although the playout is similar to what it
>> should be, there are numerous gaps & drops that indicate the corruption.
>> If I reboot the N310, the corruption disappears.  I would like to be able
>> to "reset" things without requiring an N310 reboot.
>>
>> My custom software controls the Replay block with 3 functions:
>> replay_store() and replay_play() and replay_stop(), all provided below.  I
>> don't do anything tricky like trying to store and play simultaneously.  The
>> replay_store() function is very similar to the
>> rfnoc_replay_samples_from_file() example with the exception that it doesn't
>> actually start or stop the playout. This occurs in my other 2 functions.
>>
>> The way that I get the replay block into a bad state is by failing to
>> call replay_store() prior to replay_play().  This was a bug in my software
>> that could occur in some situations (which I have since fixed). After this
>> happens, I can't produce uncorrupted playouts without rebooting the N310.
>>
>> Let me know if you have any ideas how I can "reset" the Replay block to
>> obtain uncorrupted output.
>> Rob
>>
>>
>> /*******************************************************/
>> int nd::replay_store(
>> uhd::rfnoc::replay_block_control::sptr replay_ptr,
>> size_t port,
>>     uhd::tx_streamer::sptr tx_stream,
>> std::vector<char>& samp_vec,
>> uint32_t addr
>> ){
>> const std::string ID = replay_ptr->get_block_id().to_string() + ":" +
>> std::to_string(port);
>>
>> // Constants related to the Replay block
>> const size_t bytes_per_sample = 4; // Complex signed 16-bit is 32 bits
>> per sample
>> const size_t samples_per_word = 2; // Number of sc16 samples per 64-bit
>> word
>> const size_t bytes_per_word = bytes_per_sample*samples_per_word;
>>
>> size_t num_bytes = samp_vec.size();
>>
>> // Calculate the number of 64-bit words and samples to replay
>> size_t words_to_replay = num_bytes / bytes_per_word;
>> size_t samples_to_replay = words_to_replay * samples_per_word;
>> uint32_t bytes_to_replay = words_to_replay * bytes_per_word;
>>
>> if (bytes_to_replay != num_bytes) {
>> UHD_LOGGER_WARNING(__CLASS_AND_FUNC__) << ID
>> << "Replay block requires an even number of samples. Truncating extra
>> bytes";
>> }
>>
>> // Configure a buffer in the on-board memory at address 0 that's equal in
>> // size to the file we want to play back (rounded down to a multiple of
>> // 64-bit words). Note that it is allowed to playback a different size or
>> // location from what was recorded.
>>     UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID <<
>>     ": Configuring memory at addr 0x" << std::hex << addr << std::dec <<
>> " for " << bytes_to_replay << " bytes";
>> replay_ptr->stop(port); // just in case it is presently playing
>> replay_ptr->record(addr, bytes_to_replay, port);
>>
>> // Restart record buffer repeatedly until no new data appears on the
>> Replay
>> // block's input. This will flush any data that was buffered on the input.
>> UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Restarting record
>> buffer";
>> auto start_time = std::chrono::steady_clock::now();
>> while (true)
>>     {
>> replay_ptr->record_restart(port);
>> std::this_thread::sleep_for(std::chrono::milliseconds(20));
>>
>> uint32_t fullness = replay_ptr->get_record_fullness(port);
>> if (fullness==0) break;
>>
>> std::chrono::duration<double> time_diff_s =
>> std::chrono::steady_clock::now() - start_time;
>> UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID
>> << ": Time: " << time_diff_s.count() << ": Fullness " << fullness;
>>
>> if (time_diff_s.count() > 2.0) {
>> UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Timeout waiting to flush
>> record buffer";
>> return -1;
>> }
>> }
>>
>>
>>
>> ///////////////////////////////////////////////////////////////////////////
>> // Send data to replay (record the data)
>> UHD_LOGGER_INFO(__CLASS_AND_FUNC__) << ID << ": Sending " <<
>> samples_to_replay << " samples";
>>
>> uhd::tx_metadata_t tx_md;
>> tx_md.start_of_burst = true;
>> tx_md.end_of_burst   = true;
>> size_t num_tx_samps  = tx_stream->send(&samp_vec[0], samples_to_replay,
>> tx_md);
>>
>> if (num_tx_samps != samples_to_replay) {
>> UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Error sending samples: "
>> << num_tx_samps << "/" << samples_to_replay;
>> return -1;
>> }
>>
>>
>>
>> ///////////////////////////////////////////////////////////////////////////
>> // Wait for data to be stored in on-board memory
>>
>> UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Waiting for recording to
>> complete";
>> start_time = std::chrono::steady_clock::now();
>> while (true)
>> {
>> uint32_t fullness = replay_ptr->get_record_fullness(port);
>> if (fullness>=bytes_to_replay) break;
>>
>> std::chrono::duration<double> time_diff_s =
>> std::chrono::steady_clock::now() - start_time;
>>
>> UHD_LOGGER_DEBUG(__CLASS_AND_FUNC__) << ID << ": Time: (s): " <<
>> time_diff_s.count()
>> << ": Fullness: " << fullness << " / " << bytes_to_replay;
>>
>> if (time_diff_s.count() > 2.0) {
>> UHD_LOGGER_ERROR(__CLASS_AND_FUNC__) << ID << ": Timeout waiting for
>> recording to complete";
>> return -1;
>> }
>>
>> std::this_thread::sleep_for(std::chrono::milliseconds(1));
>> }
>>
>> UHD_LOGGER_INFO(__CLASS_AND_FUNC__) << ID << ": Successfully sent " <<
>> samples_to_replay << " samples";
>>
>> return samples_to_replay;
>> }
>> /*******************************************************/
>>
>>
>>
>> /*******************************************************/
>> void nd::replay_play(
>> uhd::rfnoc::replay_block_control::sptr replay_ptr,
>> size_t port,
>> const uhd::time_spec_t start_time
>> ){
>> const std::string ID = replay_ptr->get_block_id().to_string() + ":" +
>> std::to_string(port);
>> uint64_t rec_addr = replay_ptr->get_record_offset(port);
>> uint64_t rec_size = replay_ptr->get_record_size(port);
>>
>> UHD_LOGGER_DEBUG(ID) << "Replay Started. Samples: " << (rec_size/4);
>> replay_ptr->play(rec_addr, rec_size, port, start_time, true);
>> }
>> /*******************************************************/
>>
>>
>>
>>
>> /*******************************************************/
>> void nd::replay_stop(
>> uhd::rfnoc::replay_block_control::sptr replay_ptr,
>> size_t port
>> ){
>> const std::string ID = replay_ptr->get_block_id().to_string() + ":" +
>> std::to_string(port);
>>
>> UHD_LOGGER_DEBUG(ID) << "Replay Stopped";
>> replay_ptr->stop(port);
>> }
>>
>>
>> _______________________________________________
>> USRP-users mailing list
>> USRP-users@lists.ettus.com
>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
>>
>
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com

Reply via email to