1

Я хочу написать параллельное утверждение, которое начинается после того, как запись регистра выполняется на тестируемом устройстве из UVM testbench.Concurrent Assertion - зависимость от UVM-теста

class test extends uvm_test; 
bit flag; 
task run_phase(uvm_phase phase); 
//call register write task , data is chosen in a random fashion 
write(addr,data); 
flag = 1; // flag gives the time when the register is written. 
// after this task the assertions must start depending on data. 
endtask 
endclass 

module top(); 
//instantiate dut, interface and other stuff 

property p1(logic a,logic [4:0] b,logic flag,logic c); 
disable iff(!reset || b[i] == 1 || !flag) 
/* 
default register value is 0, enable assertion only if 0 is written into it. 
(0 is for enabling certain feature in DUT and by-default it is enabled. 
1 is for disabling that feature. Assertion must never be enabled if b[i] contains 1) 
*/ 
@(posedge clk) 
a == 0 |-> $stable(c); 
endproperty 

assert property p1(dut_top.path_to_dut_signal,uvm_test_top.data,uvm_test_top.flag,dut_top.path_to_dut_other_signal); // gives compile error 
// basically I need here dut's signal and the data written to register 

// call run_test and set config_db for interface here 
initial 
begin 
// ... run_test 
end 

Это дает перекрестной ссылке модуля ошибку компиляции, так как uvm_test_top создаются во время выполнения, и я предполагаю, что входы Утверждающих устанавливается во время компиляции.

Итак, я нашел несколько обходных решений для этого.

Объявление некоторых временных и флаг переменных в глобальном пространстве следующим образом:

bit flag; // in global space 
logic [4:0] temp; 
class test extends uvm_test; 
task run_phase(uvm_phase phase); 
//call register write task 
write(addr,data); 
temp=data, flag=1; 
// after this task the assertions must start depending on temp. 
endtask 
endclass 

/** In top, **/ 

property p1(logic a,logic [4:0] b,logic flag,logic c); 
disable iff(!reset || b[i] == 0 || flag ==0) 
@(posedge clk) 
a == 0 |-> $stable(c); 
endproperty 

assert property p1(dut_top.path_to_dut_signal,temp,flag,dut_top.path_to_dut_other_signal); 
// solves the error 

Здесь используются два глобальных пространственных переменных; чего лучше избегать.

В любом случае, я могу взять эти переменные в верхней части и получить к ним доступ с помощью $ root в тесте. Но я бы не предпочел использовать $ root для повторного использования и проблем с пакетами (в случае изменения имени моего имени или написания модуля для утверждения, тест получит ошибку).

Мне интересно, есть ли еще какой-нибудь другой способ сделать это? Такое, что я могу отложить выполнение утверждения. Даже если я задержу его на 1 timestamp, я бы оценил uvm_test_top (звучит безумно .. !!).

Кроме того, я не хочу использовать интерфейсные сигналы, так как DUT является агностиком протокола, он может поддерживать разные интерфейсы на основе `ifdefs. (На самом деле это еще один способ обхода !!)

Любая помощь очень ценится.

ответ

4

Самая портативная вещь, которую я могу думать, это объявить событие внутри СВА интерфейса/модуля/проверки, который сигнализирует, когда происходит интересный регистр записи:

interface sva_checker(...); 
    event register_written; 

    property my_prop; 
    register_written |-> ... 
    endproperty 
endinterface 

Таким образом, вы только вызвать ваше имущество после того, как регистр запись бывает. Вам также не нужно выяснять, когда запись в регистре произошла на основе сигналов протокола, потому что вы будете полагаться на информацию из тестового стенда.

Теперь интересная часть запускает это событие с вашего испытательного стенда UVM. Сначала вам необходимо передать этот интерфейс на ваш испытательный стенд UVM. Если это единственный интерфейс, который у вас есть, то это довольно легко. Вы просто делаете набор конфигурации DB и соответствующие ПОЛУЧАЕТ:

// in top or wherever you instantiate your SVA checker 
uvm_config_db #(virtual sva_checker)::set(...); 

// in your UVM TB 
uvm_config_db #(virtual sva_checker)::get(..., sva_checker); 

Теперь в вашем коде, вы можете просто вызвать событие после того, как вы знаете, что вы написали в реестр:

task run_phase(uvm_phase phase); 
    //call register write task , data is chosen in a random fashion 
    write(addr,data); 
    -> sva_checker.register_written; 
    // after this task the assertions must start depending on data. 
endtask 

Таким образом, вы дон используйте любые иерархические пути, и вы не получите проблем с повторным использованием.

P.S. Я бы рассмотрел использование пакета регистров UVM для регистров. Таким образом, вы можете сделать так, чтобы это событие запускалось автоматически после записи регистра, без необходимости называть его вручную.

+0

Спасибо @Tudor. Я никогда не думал конвертировать SVA в _interface _ .. !! Несколько моментов, которые нужно уточнить. ** Во-первых, я понял о передаче интерфейса SVA в логику запуска теста и события.Но «событие» будет запускаться только ** один раз ** во время всего моделирования, и впредь запускать это утверждение только один раз (а не на каждый тактовый импульс после записи регистра). Кроме того, вопросы компиляции; так как ** ** ** ** ** ** ** ** * ** ** * * * * * Поэтому я предпочел бы использовать переменную 'bit register_written' вместо' event register_written'. – sharvil111

+0

** Во-вторых **, это не метод записи UVM-RAL, а только задание _testbench-defined_ write; Думаю, эта информация не имеет значения. Я сделал псевдокод для этого, используя бит вместо события (событие генерирует ошибку компиляции, как ожидалось). Ссылка доступна на [EDAPlayground] (http://www.edaplayground.com/x/AQ5). – sharvil111