Как покрыть задержку между запросом и ответом
Допустим, у нас есть протокол, где запрос req
утверждается с req_id
и соответствующий rsp
будет утверждено с rsp_id
, Они могут быть не в порядке. Я хочу покрыть количество кликов или задержку между req
с особым req_id
а также rsp
с тем же идентификатором. Я попробовал что-то подобное. Это правильный способ сделать? Есть ли другой эффективный способ?
covergroup cg with function sample(int a);
coverpoint a {
a1: bins short_latency = {[0:10]};
a2: bins med_latency = {[11:100]};
a3: bins long_latency = {[101:1000]};
}
endgroup
// Somewhere in code
cg cg_inst = new();
sequence s;
int lat;
int id;
@(posedge clk) disable iff (~rst)
(req, id = req_id, lat = 0) |-> ##[1:$] ((1'b1, lat++) and (rsp && rsp_id == id, cg_inst.sample(lat)));
endsequence
3 ответа
Вы пытаетесь использовать |->
оператор внутри последовательности, который разрешен только внутри свойства.
Если rsp
может прийти только один цикл после req
, тогда этот код должен работать:
property trans;
int lat, id;
(req, id = req_id, lat = 0) |=> (1, lat++) [*0:$] ##1 rsp && rsp_id == id
##0 (1, $display("lat = %0d", lat));
endproperty
Элемент после ##0
там для отладки. Вы можете опустить его в производственном коде.
Я бы не стал смешивать утверждения и покрытие таким образом, поскольку я видел, что операторы импликации могут вызывать проблемы с переменным потоком (т.е. lat
не будет обновляться должным образом). У вас должно быть свойство, которое просто покрывает то, что вы видели соответствующий ответ после запроса:
property cov_trans;
int lat, id;
(req, id = req_id, lat = 0) ##1 (1, lat++) [*0:$] ##1 rsp && rsp_id == id
##0 (1, $display("cov_lat = %0d", lat));
endproperty
cover property (cov_trans);
Обратите внимание, что я использовал ##1
отделить запрос от ответа.
По сути, ваша идея верна, но похоже, что правая часть последовательности будет оценена один раз, когда условие выполнено, и, следовательно, значение lat будет увеличено только один раз.
Вам понадобится петлевой механизм для подсчета времени ожидания.
Ниже приведен пример рабочего примера. Вы можете изменить [1:$], ##1 и т. Д. В зависимости от того, насколько близко генерируются сигналы.
property ps;
int lat;
int id;
@(posedge clk)
disable iff (~rst)
(req, id = req_id, lat = 0) |=> (1'b1, lat++)[*1:$] ##1 (rsp && rsp_id == id, cg_inst.sample(lat));
endproperty
assert property (ps);
С другой стороны...
свойство / последовательность, хотя они кажутся небольшим кодом, в этом случае для каждого запроса (который еще не получил rsp) отдельный процесс со своим собственным счетчиком разветвляется. Это приводит к тому, что многие счетчики выполняют очень похожую работу. Если в полете есть много требований (и / или много экземпляров свойства или последовательности), он начнет добавляться во время выполнения симуляции [хотя это всего лишь небольшой блок кода]
поэтому другой подход заключается в том, чтобы упростить триггер, и мы пытаемся сделать обработку линейной.
int counter=0; // you can use a larger variablesize to avoid the roll-over issue
int arr1[int] ; // can use array[MAX_SIZE] if you know the max request id is small
always @( posedge clk ) counter <= counter + 1 ; // simple counter
function int latency (int type_set_get , int a ) ;
if ( type_set_get == 0 ) arr1[a] = counter; // set
//DEBUG $display(" req id %d latency %d",a,counter-arr1[a]);
// for roll-over - if ( arr1[a] > counter ) return ( MAX_VAL_SIZE - arr1[a] + counter ) ;
return (counter - arr1[a]); //return the difference between captured clock and current clock .
endfunction
property ps();
@(posedge clk)
disable iff (~rst)
##[0:$]( (req,latency(0,req_id) ) or (rsp,cg_inst.sample(latency(1,rsp_id))) );
endproperty
assert property (ps);
Вышеупомянутое свойство срабатывает только тогда, когда req/rsp замечен, и только 1 поток активен, ищет его. При необходимости в функцию могут быть добавлены дополнительные проверки, но для подсчета задержки это должно быть хорошо.
Анекдот:
Ментор А.Е. - Дэн обнаружил утверждение, которое замедляло наше моделирование на целых 40 % . Плохо написанное утверждение было частью нашего блока tb, и его последствия остались незамеченными, так как в нашем тесте на уровне блоков время выполнения было ограничено. Затем он проник в наш tb верхнего уровня, что привело к неописуемым потерям во время выполнения, пока его не обнаружили год спустя:) . [думаю, мы должны были профилировать наши симуляции раньше]
Скажем, к примеру, если вышеупомянутый протокол реализовал прерывание позднее, тогда поток req-rsp продолжит обрабатывать и ждать (до завершения моделирования) прерванной транзакции, хотя это не повлияет на функциональность, он будет незаметно продолжаться тратить ресурсы процессора, ничего не делая взамен. До тех пор, пока, наконец, не выйдет продавец АЕ, чтобы спасти день:)