使用运行时参数绕过控制 - 2022.1 简体中文

Versal ACAP AI 引擎编程环境 用户指南 (UG1076)

Document ID
UG1076
Release Date
2022-05-25
Version
2022.1 简体中文

下图显示了支持两条信号数据通道的应用,其中一条通道拆分为两条低带宽通道,另一条则必须持续运行,不受任何干扰。此类动态重配置在无线应用中很常见。

图 1. 将 2 条 LTE20 通道动态重配置为 1 条 LTE20 和 2 条 LTE10 通道

在此图中,第一条通道负责处理 LTE20 数据(无更改),而中间通道则动态拆分为 2 条 LTE10 通道。标记为 carrier configuration RTP 的控制参数用于在块边界处拆分数据处理。在中间通道作为 LTE20 通道来工作的同时,绕过 11 抽头半带内核。但当中间通道的带宽在其本身与第三条通道之间进行拆分,形成 2 条 LTE10 通道时,这 2 条通道都需要 3 阶滤波器链才能将数据加以混合。具体达成方法是将 11 抽头半带滤波器切换回控制流程并重新配置混频器以处理 3 条(而不是 2 条)数据串流。

提示: 混用 LTE20 和 LTE10 信号时以及在控制流程中,由于需要在两者之间进行动态切换,因此都需要延迟对齐内核来平衡采样延迟。

以下代码中显示了以上应用的顶层输入 graph 规范。

class lte_reconfig : public graph {
  private:
    kernel demux;
    kernel cf[3];
    kernel interp0[3];
    kernel interp1[2];
    bypass bphb11;
    kernel delay ;
    kernel delay_byp ;
    bypass bpdelay ;
    kernel mixer ;
  public:
    input_port in;
    input_port  fromPS;
    output_port out ;

    lte_reconfig() {
      // demux also handles the control
      demux = kernel::create(demultiplexor);
      connect< window<1536> >(in, demux.in[0]);
      connect< parameter >(fromPS, demux.in[1]);

      runtime<ratio>(demux) = 0.1;
      source(demux) = "kernels/demux.cc";

      // instantiate all channel kernels
      for (int i=0;i<3;i++) {
        cf[i] = kernel::create(fir_89t_sym);
        source(cf[i]) = "kernels/fir_89t_sym.cc";
        runtime<ratio>(cf[i]) = 0.12;
      }
      for (int i=0;i<3;i++) {
        interp0[i] = kernel::create(fir_23t_sym_hb_2i);
        source(interp0[i]) = "kernels/hb23_2i.cc";
        runtime<ratio>(interp0[i]) = 0.1;
      }
      for (int i=0;i<2;i++) {
        interp1[i] = kernel::create(fir_11t_sym_hb_2i);
        source(interp1[i]) = "kernels/hb11_2i.cc";
        runtime<ratio>(interp1[i]) = 0.1;
      }
      bphb11 = bypass::create(interp1[0]);
      mixer =  kernel::create(mixer_dynamic);
      source(mixer) = "kernels/mixer_dynamic.cc";
      runtime<ratio>(mixer) = 0.4;
      delay =  kernel::create(sample_delay);
      source(delay) = "kernels/delay.cc";
      runtime<ratio>(delay) = 0.1;
      delay_byp =  kernel::create(sample_delay);
      source(delay_byp) = "kernels/delay.cc";
      runtime<ratio>(delay_byp) = 0.1;
      bpdelay = bypass::create(delay_byp) ;

      // Graph connections
      for (int i=0; i<3; i++) {
        connect< window<512, 352> >(demux.out[i], cf[i].in[0]);
        connect< parameter >(demux.inout[i], cf[i].in[1]);
      }
      connect< parameter >(demux.inout[3], bphb11.bp);
      connect< parameter >(demux.inout[3], negate(bpdelay.bp)) ;
      for (int i=0;i<3;i++) {
        connect< window<512, 64> >(cf[i].out[0], interp0[i].in[0]);
        connect< parameter >(cf[i].inout[0], interp0[i].in[1]);
      }
       // chan0 is LTE20 and is output right away
      connect< window<1024, 416> >(interp0[0].out[0], delay.in[0]);
      connect< window<1024> >(delay.out[0], mixer.in[0]);
      // chan1 is LTE20/10 and uses bypass
      connect< window<1024, 32> >(interp0[1].out[0], bphb11.in[0]);
      connect< parameter >(interp0[1].inout[0], bphb11.in[1]);
      connect< window<1024, 416> >(bphb11.out[0], bpdelay.in[0]);
      connect< window<1024> >(bpdelay.out[0], mixer.in[1]);
      // chan2 is LTE10 always
      connect< window<512, 32> >(interp0[2].out[0], interp1[1].in[0]);
      connect< parameter >(interp0[2].inout[0], interp1[1].in[1]);
      connect< window<1024> >(interp1[1].out[0], mixer.in[2]);
      //Mixer
      connect< parameter >(demux.inout[3], mixer.in[3]);
      connect< window<1024> >(mixer.out[0], out);
    };
};

基于要绕过的内核,旁路规范编码为特殊的封装器。旁路的端口签名与其封装的内核的端口签名相匹配。它还会接收运行时参数以控制旁路:0 对应无旁路,1 对应旁路。通过使用所示取反函数还可反转控制。

此 graph 的旁路参数端口是普通的标量运行时参数,可由另一个内核驱动或者由 Arm® 处理器使用交互机制或脚本生成机制来驱动,如 运行时参数更新/读取机制 中所述。将其嵌入外包围的 graph 中还可按分层方式对其进行连接。