2016-06-25 11 views
2

Nehmen wir an, wir haben ein Protokoll, bei dem die Anforderung req mit req_id bestätigt wird und die entsprechende rsp mit rsp_id bestätigt wird. Diese können außer Betrieb sein. Ich möchte die Anzahl der Clks oder Latenz zwischen req mit bestimmten req_id und rsp mit der gleichen ID abdecken. Ich habe so etwas versucht. Ist das richtig? Gibt es einen anderen effizienten Weg?So decken Sie die Latenz zwischen Anfrage und Antwort ab

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 
+0

** Hat nicht funktioniert ** bedeutet was? Ein Compilerfehler? keine Abdeckung? Bitte stellen Sie einen Testfall zur Verfügung. –

+0

Es tut mir leid. Ich möchte wissen, ob dies der richtige Weg war. Bedeckt dies meine Latenz? – user1978273

Antwort

1
erzeugt werden

Sie versuchen, die |-> Operator in einer Sequenz zu verwenden, die nur innerhalb einer Eigenschaft erlaubt ist.

Wenn rsp nur einen Zyklus nach req kommen kann, dann sollte dieser Code funktionieren:

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 

Das Element nach ##0 es für das Debuggen ist. Sie können es im Produktionscode weglassen.

Ich würde nicht Behauptungen und Abdeckung wie folgt mischen, aber, wie ich, dass die Implikationsoperatoren mit variabler Strömung verursachen können Probleme gesehen haben (das heißt lat wird nicht richtig erhalten aktualisiert). Sie sollten eine Eigenschaft, die gerade abdeckt, dass Sie eine passende Antwort nach einer Anfrage gesehen haben:

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

Beachten Sie, dass ich ##1 verwendet habe, die Anforderung von der Reaktion zu trennen.

0

Grundsätzlich Ihre Idee ist richtig, aber sieht aus wie die rechte Seite der Sequenz einmal ausgewertet werden, wenn die Bedingung erfüllt ist und somit die lat nur einmal erhöht werden.

Sie benötigen einen Loop-Mechanismus, um die Latenz zu zählen.

Unten finden Sie ein Beispiel für ein funktionierendes Beispiel. Sie können ändern [1: $], ## 1 usw. auf, wie nahe die Signale

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); 
+0

@RahulMnenon Ihr Code wird den Fall vermissen, in dem die Antwort unmittelbar nach der Anfrage kommt (d. H. Es gibt keine Latenz), weil Sie mindestens einen Zyklus benötigen, in dem Sie inkrementieren. –

0

Alternativ ...

Eigenschaft/Sequenzen obwohl sie erscheinen kleiner Code zu sein, in diesem Fall für jeden erf einen separaten Prozess mit einem eigenen Zähler (die noch keinen rsp erhalten) gegabelt. Dies führt dazu, dass viele Zähler sehr ähnliche Arbeiten ausführen. Wenn es viele req im Flug gibt (und/oder viele Instanzen der Eigenschaft oder Sequenz), beginnt es mit der Addition in die Simulationslaufzeit [obwohl dies nur ein kleiner Block von Code ist]

so ein anderer Ansatz ist halte den Trigger einfacher und wir versuchen, die Verarbeitung linear zu halten.

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

Die obige Eigenschaft wird nur dann ausgelöst, wenn req/rsp zu sehen ist und nur 1 Thread aktiv ist, es zu suchen. Bei Bedarf können zusätzliche Prüfungen in der Funktion hinzugefügt werden, aber für die Latenzzählung sollte dies in Ordnung sein.

Anekdote:

Mentor AE - Dan eine Behauptung entdeckt, die um mehr als 40% unserer Simulationen wurde verlangsamt. Die schlecht geschriebene Behauptung war Teil unseres Block-TB und ihre Auswirkungen blieben dort unbemerkt, da unser Block-Level-Test, die Laufzeiten, begrenzt waren.Es schlich sich dann in unsere Top-Level-TB und verursachte unzählige Laufzeitverluste, bis es ein Jahr später entdeckt wurde :). [denke, wir hätten unsere Simulationsläufe früher profilieren sollen]

Zum Beispiel wenn das obige Protokoll zu einem späteren Zeitpunkt einen Abbruch einleitete, dann wird der req-rsp-Thread weiterarbeiten und warten (bis die Simulation endet) abgebrochene Transaktion, obwohl es die Funktionalität nicht beeinträchtigt, wird es schleichend weiterhin Prozessorressourcen rauben, die nichts Nützliches im Gegenzug tun. Bis schließlich ein Verkäufer AE einsteigt, um den Tag zu retten :)