Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python and RFNOC: Atomic item size with FFT blocks #634

Open
LorenzoMinutolo opened this issue Oct 4, 2022 · 2 comments
Open

Python and RFNOC: Atomic item size with FFT blocks #634

LorenzoMinutolo opened this issue Oct 4, 2022 · 2 comments

Comments

@LorenzoMinutolo
Copy link

LorenzoMinutolo commented Oct 4, 2022

Issue Description

After adding the FFT block to a RFNOC design and successfully compiling the firmware, I cannot commit the graph due to an error generated on graph.commit() in my Python script. Specifically the error is:
RuntimeError: ValueError: samples per package must not be smaller than atomic item size
Which should stem from a mismatch in the samples per packet setup. I do take care of this aspect by setting the spp at the beginning and configuring each block with the same value.

Setup Details

[INFO] [UHD] linux; GNU C++ version 11.2.0; Boost_107400; UHD_4.2.0.1-0-g321295fb, Python 3.10
The USRP I am using is a x300 with a WBX daughterboard connected via a single 10Gbe. The NIC is an Intel X710.

Expected Behavior

The script should commit the graph without issues. Or at least tell me which block is causing the problem.

Actual Behaviour

RuntimeError: ValueError: samples per package must not be smaller than atomic item size

Steps to reproduce the problem

Compile a firmware with the FFT block. The usrp_probe returns:

|   |   * 0/SEP#6:0==>0/FFT#0:0
|   |   * 0/FFT#0:0==>0/SEP#6:0
|   |   * 0/SEP#0:0==>0/DUC#0:0
|   |   * 0/DUC#0:0==>0/Radio#0:0
|   |   * 0/Radio#0:0==>0/DDC#0:0
|   |   * 0/DDC#0:0==>0/SEP#0:0
|   |   * 0/Radio#0:1==>0/DDC#0:1
|   |   * 0/DDC#0:1==>0/SEP#1:0
|   |   * 0/SEP#2:0==>0/DUC#1:0
|   |   * 0/DUC#1:0==>0/Radio#1:0
|   |   * 0/Radio#1:0==>0/DDC#1:0
|   |   * 0/DDC#1:0==>0/SEP#2:0
|   |   * 0/Radio#1:1==>0/DDC#1:1
|   |   * 0/DDC#1:1==>0/SEP#3:0
|   |   * 0/SEP#4:0==>0/Replay#0:0
|   |   * 0/Replay#0:0==>0/SEP#4:0
|   |   * 0/SEP#5:0==>0/Replay#0:1
|   |   * 0/Replay#0:1==>0/SEP#5:0

Run the following code:

import numpy as np
import uhd
args = "addr=<address of the USRP>"
graph = uhd.rfnoc.RfnocGraph(args)

radio_ID_A = uhd.rfnoc.BlockID(0, "Radio", 0);
radio_block_A = graph.get_block(radio_ID_A);
radio_ctrl_A = uhd.rfnoc.RadioControl(radio_block_A)

set_freq = int(300e6)
spp = 512
radio_ctrl_A.set_tx_frequency(set_freq, 0)
tx_freq = radio_ctrl_A.get_tx_frequency(0)
radio_ctrl_A.set_rx_frequency(set_freq, 0)
rx_freq = radio_ctrl_A.get_rx_frequency(0)

radio_ctrl_A.set_properties(f'spp={spp}', 0)
radio_ctrl_A.set_rx_antenna('RX2',0)
radio_ctrl_A.set_rate(int(200e6))

DDC_ID = graph.find_blocks("DDC")[0]
DDC_block = graph.get_block(DDC_ID)
DDC_control = uhd.rfnoc.DdcBlockControl(DDC_block)
DDC_control.set_input_rate(int(200e6), 0)
DDC_control.set_output_rate(int(5e6), 0)

FFT_ID = graph.find_blocks("FFT")[0]
FFT_block = graph.get_block(FFT_ID)
FFT_control = uhd.rfnoc.FftBlockControl(FFT_block)
FFT_control.set_magnitude(uhd.libpyuhd.rfnoc.fft_magnitude.COMPLEX)
FFT_control.set_direction(uhd.libpyuhd.rfnoc.fft_direction.FORWARD)
FFT_control.set_shift_config(uhd.libpyuhd.rfnoc.fft_shift.NORMAL)
FFT_control.set_length(int(spp))

stream_args = uhd.usrp.StreamArgs('fc32','sc16')
stream_args.args = uhd.types.DeviceAddr(f'spp={spp}')
rx_stream = graph.create_rx_streamer(1, stream_args)

graph.connect(
    radio_ID_A,0,
    DDC_ID,0,
    False
)
graph.connect(
    DDC_ID,0,
    FFT_ID,0,
    False
)
graph.connect(
    FFT_ID,0,
    rx_stream,0
)
graph.commit()
@LorenzoMinutolo
Copy link
Author

LorenzoMinutolo commented Oct 4, 2022

Interestingly this version of the code commits the graph successfully.

args = "addr=<address of the USRP>"
spp = 128
graph = uhd.rfnoc.RfnocGraph(args)
radio_ID_A = uhd.rfnoc.BlockID(0, "Radio", 0)
FFT_ID = graph.find_blocks("FFT")[0]

DDC_ID = graph.find_blocks("DDC")[0]
DDC_block = graph.get_block(DDC_ID)
DDC_control = uhd.rfnoc.DdcBlockControl(DDC_block)
DDC_control.set_input_rate(int(200e6), 0)
DDC_control.set_output_rate(int(5e6), 0)

stream_args = uhd.usrp.StreamArgs('fc32','sc16')
rx_stream = graph.create_rx_streamer(1, stream_args)

uhd.rfnoc.connect_through_blocks(graph,radio_ID_A,0,DDC_ID,0)

FFT_block = graph.get_block(FFT_ID)
FFT_control = uhd.rfnoc.FftBlockControl(FFT_block)
FFT_control.set_magnitude(uhd.libpyuhd.rfnoc.fft_magnitude.COMPLEX)
FFT_control.set_direction(uhd.libpyuhd.rfnoc.fft_direction.FORWARD)
FFT_control.set_shift_config(uhd.libpyuhd.rfnoc.fft_shift.NORMAL)
FFT_control.set_length(int(spp))

radio_block_A = graph.get_block(radio_ID_A)
radio_ctrl_A = uhd.rfnoc.RadioControl(radio_block_A)
radio_ctrl_A.set_properties(f'spp={spp}', 0)
radio_ctrl_A.set_rx_antenna('RX2',0)

graph.connect(DDC_ID, 0, FFT_ID, 0,False)
graph.connect(FFT_ID, 0, rx_stream, 0,False)

graph.commit()

The main differences are:

  1. the use of the function connect_through_blocks instead of just connect for connecting the radio block. What is the difference between these functions?
  2. I am not setting the spp for the streamer. Whenever I do that, the original error is thrown.

Also: does the order in which I declare/connect blocks matter?

I just noticed that changing the spp above 256 makes the script throw the original error. Does this rings a bell to anyone?

Thanks,
Lorenzo

@mbr0wn
Copy link
Contributor

mbr0wn commented Nov 8, 2022

Hey @LorenzoMinutolo, we are aware of this issue. In fact, we had already fixed it in f163af4, but we had to revert it in 036f7a3 because it broke some streaming tests. It's on our backlog to put the fix in again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants