2016-09-21 3 views
1

Ich muss den Status eines Registers überwachen. Ich habe eine UVM-Sequenz erstellt, um das Register zu lesen und lokal zu speichern. Jetzt in meinem Testcode, muss ich auf diese Register zugreifen. Hier ist ein sudo Code:Verweis auf UVM Sequenz

typedef struct { 
    int a; 
} my_regs; 

class my_seq extends uvm_sequence; 
    // register to uvm db 
    reg_map  map; 
    my_regs  regs; 
    uvm_status_e status; 

    task build_phase(uvm_phase phase); 
    endtask 

    task run_phase(uvm_phase phase); 
     map.CORE.reg_a.read(status, regs.a, UVM_BACKDOOR) 
    endtask 
endclass 

class test_reg extends uvm_test; 
    // register to uvm db 
    my_seq seq; 
    my_regs regs; 

    task build_phase(uvm_phase phase); 
     seq = my_seq::type_id::create("reg_seq", this); 
     regs = seq.regs; 
    endtask 

    task run_phase(uvm_phase phase); 
     reg_seq.start(null); 
     // read reg values from seq?????? 
     if(rqgs.a>1) 
      //do some thing 

    endtask 
endclass 

Wie Sie sehen, ich bin ständig Startsequenz so, dass ich keine Updates nicht verpassen. Ich glaube, die Start Aufgabe in Folge erstellt kein neues Objekt , so dass die Werte innerhalb des Objekts zwischen den Startaufrufen konstant bleiben sollte.

Angenommen, dass ich Regs-Werte nicht jedes Mal von Seq lesen, erhalten die Regs der Testklasse keine Updates von Seq. Das bedeutet, dass die regs = seq.regs; erstellt keinen tatsächlichen Verweis auf die seq.regs. Ich möchte wissen, warum das so ist und wie kann ich eine absolute Referenz auf dieses Objekt erstellen? (Damit verschwende ich keine Simulationszyklen beim Lesen und Aktualisieren der Regs-Werte in der Testklasse). Bitte teilen Sie mir auch mit, ob es einen besseren Weg gibt, dies zu tun.

Antwort

2

Zunächst eine kleine Korrektur. Eine Sequenz hat keine Build- oder Ausführungsphasen. Sie werden im Gegensatz zu anderen uvm_components nicht automatisch gestartet [unter Verwendung des Phasensystems]. Eine Sequenz hat eine Körperaufgabe, die außer Kraft gesetzt wird, um die Funktionalität zu implementieren (in diesem Fall liest das Register). Daher muss der Code aus der run_phase in eine body-Funktion verschoben werden.

class my_seq extends uvm_sequence; 
    // register to uvm db 
    reg_map  map; 
    my_regs  regs; 
    uvm_status_e status; 
function new(string name="my_seq"); 
    super.new(name); 
    endfunction 

    task body(); 
     map.CORE.reg_a.read(status, regs.a, UVM_BACKDOOR); 
    endtask 
endclass 

Sobald die Sequenz aufgerufen wird, wird der Wert aus dem RTL registrieren und aktualisieren Sie das „a“ Feld in regs in der Klasse my_seq lesen.

regs = seq.regs; // 

regs (im Test) wird eine permanente Verbindung zum regs-Feld innerhalb der Sequenz bereitstellen. Jedes Mal, wenn die Sequenz das Register liest und das regs-Feld aktualisiert, wird die Variable regs in test_reg die Änderung sehen, aber es bedeutet, dass das Register von der RTL gelesen werden muss. Der Test_reg müsste eine Schleife implementieren, um das Register periodisch zu lesen (indem die Sequenz my_seq aufgerufen wird). Dies liegt daran, dass die Variable regs oder das Registerfeld map.CORE.reg_a keine direkte Verbindung zum Register in der RTL ist.

Sie müssen Simulationszyklen beim Lesen des RTL-Registers verwenden, da das uvm_register nur eine Spiegelung/Kopie ist, die nur aktualisiert wird, wenn ein Lesevorgang ausgeführt wird.

Die Frage ist, wie auf das Register von der Firmware zugegriffen wird? Wenn auf das Register über einen Polungsmechanismus zugegriffen wird, ist es besser, dasselbe im Testfall nachzuahmen.

task run_phase(uvm_phase phase); 
    task_done = 0; 
    while (!task_done) 
     begin 
     // wait for some delay as backdoor access takes 0 simulation time 
     reg_seq.start(null); // regs is updates 
     // read reg values from seq - done 
     if(regs.a>1) // check for bit to be set 
     begin 
      task_done = 1; 
      //do some thing 
     end 
     // else continue to poll register 
     end 
end task 

Alternativ könnten wir für das RTL-Signal warten zu ändern und dann die Auslese- (dieses Verfahren nicht wünschenswert ist, da wir RTL Signale von dem Prüfstand zugreifen.)

task run_phase(uvm_phase phase); 
      wait (RTL.module.reg.CORE.reg_a == 1) ; 
      reg_seq.start(null); // regs file is updates 
      // read reg values from seq - done 
      if(regs.a>1) // check for bit to be set 
       //do some thing 
    endtask 
+0

Oh, du habe recht Wie gesagt, es war ein Sudo-Code und im Originalcode habe ich den Körper so implementiert, wie du es beschrieben hast. Danke noch einmal! – maskarih

+0

:) Verstanden. Nur dafür sorgen, dass das alles ist. Bitte schön . –