0

我正在使用与 UVM 不兼容的旧环境,但使用 vr_ad_reg。这个旧环境的一个问题是,不是为其中一个模块实例化 regfile 两次(在 RTL 中确实实例化了两次),而是对整个 regfile 和其中的寄存器进行双重定义。

例如,我有两个 regfile:“GAD”和“GAD_RX”,它们都有一个这样定义的寄存器:

reg_def GAD_SEQ GAD 20'h00010 {
    reg_fld s_event : uint (bits : 7) : RW : 0x0;
    reg_fld smpl_en : bit : RW : 0x0;
    reg_fld int_en : bit : RW : 0x0;
    reg_fld dma_req : bit : RW : 0x0;
    reg_fld smpl_tag : uint (bits : 2) : RW : 0x0;
    reg_fld ch_tag : uint (bits : 4) : RW : 0x0;
    reg_fld smpl_point : uint (bits : 16) : RW : 0x0;
};

reg_def GAD_RX_SEQ GAD_RX 20'h00010 {
    reg_fld s_event : uint (bits : 7) : RW : 0x0;
    reg_fld smpl_en : bit : RW : 0x0;
    reg_fld int_en : bit : RW : 0x0;
    reg_fld dma_req : bit : RW : 0x0;
    reg_fld smpl_tag : uint (bits : 2) : RW : 0x0;
    reg_fld ch_tag : uint (bits : 4) : RW : 0x0;
    reg_fld smpl_point : uint (bits : 16) : RW : 0x0;
};

如您所见,regs 是相同的。我不希望替换整个定义,因为它基于也生成 RTL 的脚本,并且尝试重写它们太麻烦和风险。但是,我确实希望能够通过将它们约束到任一 GAD 来编写一个可以写入它们的序列。

我为写入这些寄存器的所有序列定义了一个结构成员:

type gad_type_t : [GAD,RX_GAD];

extend ocp_master_sequence_kind_t : [CONFIG_ADC_SEQ];

//This sequence writes a single line to GAD sequencer
extend CONFIG_ADC_SEQ ocp_master_sequence_q { 

smpl_point : int(bits:16);
dma_req : bit;
int_en : bit;
smpl_en : bit;
ch_tag : uint(bits:4);
smpl_tag : uint(bits:2);
samp_sig : uint(bits:4);
keep soft samp_sig==0;

//which GAD to config
gad_type : gad_type_t;
keep soft gad_type==GAD;

我尝试用宏声明寄存器变量但完全失败:

//Macro for declaring either GAD or RX_GAD register variable
define <get_gad_reg'action> "gad_reg <var_name'name> : <gad_type'exp> <reg_suffix'exp>" as computed {
   var gad_regname : string;
   var gad_type : gad_type_t = <gad_type'exp>;
   var reg_suffix_s : string = <reg_suffix'exp>;
   gad_regname = gad_type == RX_GAD ? append("GAD_RX_",reg_suffix_s) : append("GAD_",reg_suffix_s);
   return append("var ",<var_name'name>," : ",gad_regname," vr_ad_reg = driver.get_reg_by_kind(",gad_regname,").as_a(",gad_regname," vr_ad_reg)");

};

宏应该在序列主体内以这种方式使用:

gad_reg gad_seq_r : gad_type SEQ;

我希望能翻译成:

var gad_seq_r : GAD_SEQ vr_ad_reg = driver.get_reg_by_kind(GAD_SEQ).as_a(GAD_SEQ vr_ad_reg);

或者:

var gad_seq_r : GAD_RX_SEQ vr_ad_reg = driver.get_reg_by_kind(GAD_RX_SEQ).as_a(GAD_RX_SEQ vr_ad_reg);

它适用于 GAD,但不适用于 RX_GAD,经过多次调试,我推断出 gad_type 没有正确匹配,并且宏只是在条件赋值中使用 else 子句。

我决定尝试一种不同的方法而不使用宏,我尝试在序列本身中使用“when”子句:

  when GAD {
     body()@driver.clock is {
        var gad_seq_r : GAD_SEQ vr_ad_reg = driver.get_reg_by_kind(GAD_SEQ).as_a(GAD_SEQ vr_ad_reg);
    };
  };

  when RX_GAD {
     body()@driver.clock is {
        var gad_seq_r : GAD_RX_SEQ vr_ad_reg = driver.get_reg_by_kind(GAD_RX_SEQ).as_a(GAD_RX_SEQ vr_ad_reg);
     };
  };

  body()@driver.clock is also {
    gad_seq_r.smpl_point = last_line ? 0x8000 : smpl_point;
    gad_seq_r.ch_tag = ch_tag;
    gad_seq_r.smpl_tag = smpl_tag;
    gad_seq_r.dma_req = dma_req;
    gad_seq_r.int_en = int_en;
    gad_seq_r.smpl_en = smpl_en;
    gad_seq_r.s_event = s_event[6:0];
    do WR_REG seq keeping {.reg==gad_seq_r;};
};

这不会编译,因为编译器无法识别 'when' 子句之外的 gad_seq_r 。

我不知道在为 GAD 和 RX_GAD 复制代码之外是否有解决方案,但我想我可以在这里试一试。无论哪种方式,下一个项目我们将构建一个更可重用的寄存器数据库。

如果你能活到现在,谢谢你的关注。

4

1 回答 1

0

由于您的两个寄存器具有完全相同的布局,您可以只引用序列中的任何一种类型,根据您的序列字段建立所需的值,然后使用write_reg <reg> value <val>

extend CONFIG_ADC_SEQ ocp_master_sequence_q {

  gad_type : gad_type_t;

  smpl_point: int(bits:16);
  // ... all other sequence fields that model register settings

  // Used by 'write_reg'
  !gad_reg: vr_ad_reg;


  body() @driver.clock is also {
    // Dummy register variable. Could be of either GAD_SEQ or GAD_RX_SEQ type
    var dummy_gad_reg: GAD_SEQ vr_ad_reg;

    dummy_gad_reg.smpl_point = smpl_point;
    // ... set all other fields of 'gad_seq_r' based on your sequence fields

    // Get a pointer to the "real" GAD reg you're trying to access
    var real_gad_reg: vr_ad_reg;
    if gad_type == GAD {
      real_gad_reg = driver.get_reg_by_kind(GAD_SEQ);
    }
    else {
      real_gad_reg = driver.get_reg_by_kind(GAD_RX_SEQ);
    };

    // Instruct 'vr_ad' to write the value in your dummy reg to the real reg
    write_reg gad_reg { .static_item == real_gad_reg }
        val dummy_gad_reg.get_cur_value();
  };

};

我注意到您正在使用一些WR_REG序列来编写您的寄存器,它将寄存器作为参数写入。如果 usingwrite_reg不是一个选项(无论出于何种原因)并且您必须使用您的序列,我认为您可以将write_reg上面的调用替换为:

real_gad_reg.write_reg_val(dummy_gad_reg.get_cur_value());
do WR_REG seq keeping {
  .reg == real_gad_reg;
};
于 2018-08-16T14:48:06.307 回答