Последовательность, которая записывает в один из двух разных регистров, но с одними и теми же полями.

Я работаю в старой среде, которая не совместима с UVM, но использует vr_ad_reg. Одна из проблем с этой старой средой заключается в том, что вместо того, чтобы дважды создавать экземпляр reg-файла для одного из модулей (который в RTL действительно создается дважды), существует двойное определение для всего reg-файла и регистров в нем.

Например, у меня есть два reg-файла: «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;
};

Как видите, регистры идентичны. Я не хочу заменять все определение целиком, потому что оно основано на сценариях, которые также генерируют 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);

or:

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 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;};
};

Это не компилируется, потому что компилятор не распознает gad_seq_r вне предложения 'when'.

Я не знаю, есть ли решение для этого, помимо дублирования кода для GAD и RX_GAD, но я подумал, что могу попробовать здесь. В любом случае, в следующем проекте мы создадим более многоразовую базу данных регистров.

Если вы дожили до этого места, спасибо за внимание.


person Shay Golan    schedule 16.08.2018    source источник


Ответы (1)


Поскольку оба ваших регистра имеют одинаковую компоновку, вы можете просто сослаться на любой из типов внутри вашей последовательности, создать желаемое значение на основе ваших полей последовательности, а затем использовать 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 для записи своих регистров, которая принимает регистр для записи в качестве аргумента. Если использование write_reg невозможно (по какой-либо причине) и вам нужно использовать свою последовательность, я думаю, вы могли бы заменить вызов write_reg сверху на:

real_gad_reg.write_reg_val(dummy_gad_reg.get_cur_value());
do WR_REG seq keeping {
  .reg == real_gad_reg;
};
person Tudor Timi    schedule 16.08.2018
comment
Код не тестировался. - person Tudor Timi; 16.08.2018