diff options
| author | Ryan Marlow <ryan.marlow@ettus.com> | 2017-12-06 09:10:45 -0500 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2017-12-20 16:56:48 -0800 | 
| commit | d6d94bf60ed75ee237e77d1a46c8ab5c752f1121 (patch) | |
| tree | 5e4c8267f51f83f1ab3ff2c4a9f5027bf5ef0807 /host | |
| parent | d1aebc9c23817dbaed580698edc11acd8763f883 (diff) | |
| download | uhd-d6d94bf60ed75ee237e77d1a46c8ab5c752f1121.tar.gz uhd-d6d94bf60ed75ee237e77d1a46c8ab5c752f1121.tar.bz2 uhd-d6d94bf60ed75ee237e77d1a46c8ab5c752f1121.zip  | |
ddc/duc: enhance ddc/duc with new parameters
- NUM_HALFBANDS and CIC_MAX are no longer hard coded and are now
  readback regs.
- both DDC and DUC use same encoding to enable halfbands
  (increment the number)
- removed hacky hack & fixed get_output_rate/get_input_rate
  to include only valid rates based on NUM_HALFBANDS and CIC_MAX.
- added compatibility number readback w/ warning/error messages
- Updated images package to include new DDC/DUC (affects X-Series only)
- Updated fpga-src submodule pointer
Diffstat (limited to 'host')
| -rw-r--r-- | host/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | host/lib/rfnoc/ddc_block_ctrl_impl.cpp | 75 | ||||
| -rw-r--r-- | host/lib/rfnoc/duc_block_ctrl_impl.cpp | 78 | 
3 files changed, 115 insertions, 42 deletions
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index a66d6bd16..720146739 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -364,8 +364,8 @@ UHD_INSTALL(FILES  #{{{IMG_SECTION  # This section is written automatically by /images/create_imgs_package.py  # Any manual changes in here will be overwritten. -SET(UHD_IMAGES_MD5SUM "0afdbe84eaa54edc6a405bce426c28ed") -SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.010.002.000-rc1.zip") +SET(UHD_IMAGES_MD5SUM "6fc29c5c141e8f3faec6189ab07e458d") +SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_3.11.0.git-227-g9277fc58.zip")  #}}}  ######################################################################## diff --git a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp index b0b510cde..ad7312fca 100644 --- a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp +++ b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp @@ -44,11 +44,12 @@ static double lambda_forward_prop(uhd::property_tree::sptr tree, uhd::fs_path pr  class ddc_block_ctrl_impl : public ddc_block_ctrl  {  public: -    static const size_t NUM_HALFBANDS = 3; -    static const size_t CIC_MAX_DECIM = 255;      UHD_RFNOC_BLOCK_CONSTRUCTOR(ddc_block_ctrl)      { +        check_compat_num(); +        _num_halfbands = (size_t) user_reg_read64(RB_REG_NUM_HALFBANDS); +        _cic_max_decim = (size_t) user_reg_read64(RB_REG_CIC_MAX_DECIM);          // Argument/prop tree hooks          for (size_t chan = 0; chan < get_input_ports().size(); chan++) {              double default_freq = get_arg<double>("freq", chan); @@ -176,6 +177,14 @@ public:  private: +    size_t _num_halfbands; +    size_t _cic_max_decim; +    static const size_t MAJOR_COMP = 1; +    static const size_t MINOR_COMP = 0; +    static const size_t RB_REG_COMPAT_NUM = 0; +    static const size_t RB_REG_NUM_HALFBANDS = 1; +    static const size_t RB_REG_CIC_MAX_DECIM = 2; +      //! Set the CORDIC frequency shift the signal to \p requested_freq      double set_freq(const double requested_freq, const size_t chan)      { @@ -198,23 +207,18 @@ private:          );      } -    // FIXME this misses a whole bunch of valid rates. Anything with CIC decim <= 255 -    // is OK.      uhd::meta_range_t get_output_rates(void)      {          uhd::meta_range_t range;          const double input_rate = get_arg<double>("input_rate"); -        for (int decim = 1024; decim > 512; decim -= 8){ -            range.push_back(uhd::range_t(input_rate/decim)); -        } -        for (int decim = 512; decim > 256; decim -= 4){ -            range.push_back(uhd::range_t(input_rate/decim)); -        } -        for (int decim = 256; decim > 128; decim -= 2){ -            range.push_back(uhd::range_t(input_rate/decim)); -        } -        for (int decim = 128; decim >= 1; decim -= 1){ -            range.push_back(uhd::range_t(input_rate/decim)); +        for (int hb = _num_halfbands; hb >= 0; hb--) { +            const size_t decim_offset = _cic_max_decim<<(hb-1); +            for(size_t decim = _cic_max_decim; decim > 0; decim--) { +                const size_t hb_cic_decim =  decim*(1<<hb);  +                if(hb == 0 || hb_cic_decim > decim_offset) { +                    range.push_back(uhd::range_t(input_rate/hb_cic_decim)); +                } +            }          }          return range;      } @@ -222,17 +226,17 @@ private:      double set_output_rate(const int requested_rate, const size_t chan)      {          const double input_rate = get_arg<double>("input_rate"); +                  const size_t decim_rate = boost::math::iround(input_rate/this->get_output_rates().clip(requested_rate, true));          size_t decim = decim_rate; -          // The FPGA knows which halfbands to enable for any given value of hb_enable.          uint32_t hb_enable = 0; -        while ((decim % 2 == 0) and hb_enable < NUM_HALFBANDS) { +        while ((decim % 2 == 0) and hb_enable < _num_halfbands) {              hb_enable++;              decim /= 2;          } -        UHD_ASSERT_THROW(hb_enable <= NUM_HALFBANDS); -        UHD_ASSERT_THROW(decim <= CIC_MAX_DECIM); +        UHD_ASSERT_THROW(hb_enable <= _num_halfbands); +        UHD_ASSERT_THROW(decim > 0 and decim <= _cic_max_decim);          // What we can't cover with halfbands, we do with the CIC          sr_write("DECIM_WORD", (hb_enable << 8) | (decim & 0xff), chan); @@ -293,6 +297,39 @@ private:          sr_write("SCALE_IQ", actual_scalar, chan);      } +   //Get cached value of _num_halfbands +   size_t get_num_halfbands() const +   { +       return (size_t) _num_halfbands; +   } + +   //Get cached value of _cic_max_decim readback +   size_t get_cic_max_decim() const +   { +       return (size_t) _cic_max_decim; +   } + +   //Check compatibility num, if not current, throw error. +   //MAJOR COMPATIBILITY, top 32 bits = 0x1 +   //MINOR COMPATIBILITY, lower 32 bits = 0x0 +   void check_compat_num() +   { +       uint64_t compat_num = user_reg_read64(RB_REG_COMPAT_NUM); +       uint32_t compat_num_major = compat_num>>32; +       uint32_t compat_num_minor = compat_num&0xFFFFFFFF; +       if ( compat_num_major > MAJOR_COMP) { +          throw uhd::runtime_error(str(boost::format( +              "DDC RFNoC block is too new for this software. Please upgrade to a driver that supports hardware revision %d.") +              % compat_num_major)); +       } else if ( compat_num_major < MAJOR_COMP) { +          throw uhd::runtime_error(str(boost::format( +              "DDC software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") +              % compat_num_major)); +       } +       if (compat_num_minor != MINOR_COMP) { +         UHD_LOGGER_WARNING("DDC") << "DDC hardware compatability does not match software, this may have adverse affects on the block's behavior."; +       } +   }  };  UHD_RFNOC_BLOCK_REGISTER(ddc_block_ctrl, "DDC"); diff --git a/host/lib/rfnoc/duc_block_ctrl_impl.cpp b/host/lib/rfnoc/duc_block_ctrl_impl.cpp index d0742a6d0..ca9e88f81 100644 --- a/host/lib/rfnoc/duc_block_ctrl_impl.cpp +++ b/host/lib/rfnoc/duc_block_ctrl_impl.cpp @@ -44,11 +44,12 @@ static double lambda_forward_prop(uhd::property_tree::sptr tree, uhd::fs_path pr  class duc_block_ctrl_impl : public duc_block_ctrl  {  public: -    static const size_t NUM_HALFBANDS = 2; -    static const size_t CIC_MAX_INTERP = 128;      UHD_RFNOC_BLOCK_CONSTRUCTOR(duc_block_ctrl)      { +        check_compat_num(); +        _num_halfbands = (size_t) user_reg_read64(RB_REG_NUM_HALFBANDS); +        _cic_max_interp = (size_t) user_reg_read64(RB_REG_CIC_MAX_INTERP);          // Argument/prop tree hooks          for (size_t chan = 0; chan < get_input_ports().size(); chan++) {              double default_freq = get_arg<double>("freq", chan); @@ -159,6 +160,14 @@ public:  private: +    size_t _num_halfbands; +    size_t _cic_max_interp; +    static const size_t MAJOR_COMP = 1; +    static const size_t MINOR_COMP = 0; +    static const size_t RB_REG_COMPAT_NUM = 0; +    static const size_t RB_REG_NUM_HALFBANDS = 1; +    static const size_t RB_REG_CIC_MAX_INTERP = 2; +      //! Set the CORDIC frequency shift the signal to \p requested_freq      double set_freq(const double requested_freq, const size_t chan)      { @@ -186,14 +195,14 @@ private:      {          uhd::meta_range_t range;          const double output_rate = get_arg<double>("output_rate"); -        for (int rate = 512; rate > 256; rate -= 4){ -            range.push_back(uhd::range_t(output_rate/rate)); -        } -        for (int rate = 256; rate > 128; rate -= 2){ -            range.push_back(uhd::range_t(output_rate/rate)); -        } -        for (int rate = 128; rate >= 1; rate -= 1){ -            range.push_back(uhd::range_t(output_rate/rate)); +        for (int hb = _num_halfbands; hb >= 0; hb--) { +            const size_t interp_offset = _cic_max_interp<<(hb-1); +            for(size_t interp = _cic_max_interp; interp > 0; interp--) { +                const size_t hb_cic_interp =  interp*(1<<hb);  +                if(hb == 0 || hb_cic_interp > interp_offset) { +                    range.push_back(uhd::range_t(output_rate/hb_cic_interp)); +                } +            }          }          return range;      } @@ -205,21 +214,14 @@ private:          size_t interp = interp_rate;          uint32_t hb_enable = 0; -        while ((interp % 2 == 0) and hb_enable < NUM_HALFBANDS) { +        while ((interp % 2 == 0) and hb_enable < _num_halfbands) {              hb_enable++;              interp /= 2;          } -        UHD_ASSERT_THROW(hb_enable <= NUM_HALFBANDS); -        UHD_ASSERT_THROW(interp > 0 and interp <= CIC_MAX_INTERP); -        // hacky hack: Unlike the DUC, the DUC actually simply has 2 -        // flags to enable either halfband. -        uint32_t hb_enable_word = hb_enable; -        if (hb_enable == 2) { -            hb_enable_word = 3; -        } -        hb_enable_word <<= 8; +        UHD_ASSERT_THROW(hb_enable <= _num_halfbands); +        UHD_ASSERT_THROW(interp > 0 and interp <= _cic_max_interp);          // What we can't cover with halfbands, we do with the CIC -        sr_write("INTERP_WORD", hb_enable_word | (interp & 0xff), chan); +        sr_write("INTERP_WORD", (hb_enable << 8) | (interp & 0xff), chan);          // Rate change = M/N          sr_write("N", 1, chan); @@ -271,6 +273,40 @@ private:          // Write DUC with scaling correction for CIC and CORDIC that maximizes dynamic range in 32/16/12/8bits.          sr_write("SCALE_IQ", actual_scalar, chan);      } + +   //Get cached value of _num_halfbands +   size_t get_num_halfbands() const +   { +       return (size_t) _num_halfbands; +   } + +   //Get cached value of _cic_max_decim readback +   size_t get_cic_max_decim() const +   { +       return (size_t) _cic_max_interp; +   } + +   //Check compatibility num, if not current, throw error. +   //MAJOR COMPATIBILITY, top 32 bits = 0x1 +   //MINOR COMPATIBILITY, lower 32 bits = 0x0 +   void check_compat_num() +   { +       uint64_t compat_num = user_reg_read64(RB_REG_COMPAT_NUM); +       uint32_t compat_num_major = compat_num>>32; +       uint32_t compat_num_minor = compat_num&0xFFFFFFFF; +       if ( compat_num_major > MAJOR_COMP) { +          throw uhd::runtime_error(str(boost::format( +              "DUC RFNoC block is too new for this software. Please upgrade to a driver that supports hardware revision %d.") +              % compat_num_major)); +       } else if ( compat_num_major < MAJOR_COMP) { +          throw uhd::runtime_error(str(boost::format( +              "DUC software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") +              % compat_num_major)); +       } +       if (compat_num_minor != MINOR_COMP) { +         UHD_LOGGER_WARNING("DDC") << "DDC hardware compatability does not match software, this may have adverse affects on the block's behavior."; +       } +   }  };  UHD_RFNOC_BLOCK_REGISTER(duc_block_ctrl, "DUC");  | 
