跳转至

输入查询内容

    本页内容

    Sequence kill、队列清理与 phase 生命周期

    环境:VCS W-2024.09-SP2-8。1.2 使用 uvm-1.2,2.0 使用 uvm-ieee-2020-2.0

    实验检查观察值是否符合预期;成功复现问题不代表问题已修复。

    结果对比

    观察内容 UVM 1.2 UVM 2.0
    默认关闭响应溢出报告(1=是) default_response_disabled 0 1
    默认配置下响应队列溢出报错数 default_overflow_errors 1 0
    显式启用响应溢出报告后的报错数 explicit_overflow_errors 1 1
    已锁定 starting_phase 保持原值(1=是) locked_phase_preserved 1 1
    修改已锁定 starting_phase 的报错数 locked_phase_error 1 1
    kill 后其他 sequencer 上的锁仍保留(1=是) cross_sequencer_lock_after_kill 1 0
    获准 sequence 被 kill 后重试结果 retry_after_grant_kill 0 1

    运行命令

    目录与环境准备;从解包根目录执行:

    uv run tools/run_uvm_review.py --case lifecycle_probe --variants 12,20
    

    最小源码

    lifecycle_probe.sv

    lifecycle_probe.sv
    `timescale 1ns/1ps
    `include "uvm_macros.svh"
    import uvm_pkg::*;
    
    class lifecycle_catcher extends uvm_report_catcher;
      int overflow, phase_error;
      function new(); super.new("catcher"); endfunction
      function action_e catch();
        if (uvm_is_match("*Response queue overflow*", get_message())) begin
          overflow++; return CAUGHT;
        end
        if (get_id() inside {"UVM/SEQ/LOCK_DEPR", "UVM/SEQ/SP/GET", "UVM/SEQ/SP/SET", "UVM/GET_TO_LOCK_DAP/SAG"}) begin
          phase_error++; return CAUGHT;
        end
        return THROW;
      endfunction
    endclass
    
    class lifecycle_sequence extends uvm_sequence#(uvm_sequence_item);
      bit hold_after_grant, granted, route_lock, locked;
      uvm_sequencer_base other;
      function new(string name="seq"); super.new(name); endfunction
      function void overflow_now();
        uvm_sequence_item response = new("response");
        set_response_queue_depth(0);
        put_response(response);
      endfunction
      task body();
        if (route_lock) begin
          lock(other); locked = 1; wait(0);
        end else begin
          req = new("req");
          start_item(req);
          granted = 1;
          if (hold_after_grant) wait(0);
          finish_item(req);
        end
      endtask
    endclass
    
    module lifecycle_probe;
      initial begin
        lifecycle_catcher catcher = new();
        lifecycle_sequence controls = new("controls"), routing = new("routing");
        lifecycle_sequence bad = new("bad"), good = new("good");
        uvm_sequencer#(uvm_sequence_item) primary = new("primary", null);
        uvm_sequencer#(uvm_sequence_item) other = new("other", null);
        uvm_sequencer#(uvm_sequence_item) retry_sqr = new("retry", null);
        uvm_sequence_item received;
        uvm_phase phase_a = uvm_run_phase::get(), phase_b = uvm_reset_phase::get(), locked_phase;
        bit completed;
        uvm_report_cb::add(null, catcher);
        $display("REVIEW|default_response_disabled|%0d", controls.get_response_queue_error_report_disabled());
        controls.overflow_now();
        $display("REVIEW|default_overflow_errors|%0d", catcher.overflow);
        catcher.overflow = 0;
        controls.set_response_queue_error_report_disabled(0);
        controls.overflow_now();
        $display("REVIEW|explicit_overflow_errors|%0d", catcher.overflow);
        controls.set_starting_phase(phase_a);
        locked_phase = controls.get_starting_phase();
        controls.set_starting_phase(phase_b);
        locked_phase = controls.get_starting_phase();
        $display("REVIEW|locked_phase_preserved|%0d", locked_phase == phase_a);
        $display("REVIEW|locked_phase_error|%0d", catcher.phase_error > 0);
    
        routing.route_lock = 1;
        routing.other = other;
        fork routing.start(primary); join_none
        wait(routing.locked);
        routing.kill();
        #1;
        $display("REVIEW|cross_sequencer_lock_after_kill|%0d", other.is_grabbed());
    
        bad.hold_after_grant = 1;
        fork : retry_workers
          bad.start(retry_sqr, null, 200);
          good.start(retry_sqr, null, 100);
          begin
            #1;
            retry_sqr.get_next_item(received);
            retry_sqr.item_done();
            completed = 1;
          end
          begin wait(bad.granted); bad.kill(); end
        join_none
        #5;
        $display("REVIEW|retry_after_grant_kill|%0d", completed);
        good.kill();
        disable retry_workers;
        $display("REVIEW|done|1");
        $finish;
      end
      initial begin #50; $fatal(1, "lifecycle timeout"); end
    endmodule
    

    全部用例 · 证据摘要

    版本适用范围