Verification Engineerの戯言
今回は、scenarioAクラスとmy_driverクラスについてです。
scenarioAクラスは、次のようにbodyタスクとpre_applyタスクを定義しています。
bodyタスクはnum_loops回(実際には10回のBUS_WRITE->BUS_READをシナリオコントローラに送っています。
ここで定義したbodyタスクは、ovm_scenario_base::startタスクで説明したようにstartタスク内で呼び出されます。
`define num_loops 10 class scenarioA #(type REQ = ovm_sequence_item, type RSP = ovm_sequence_item) extends ovm_scenario #(REQ, RSP); function new(string name); super.new(name); endfunction task body(); string prstring; int ret_data; REQ req; RSP rsp; ovm_report_message("scenarioA", "Starting scenario"); $display(" scenario %0d", get_id()); for(int unsigned i = 0; i < `num_loops; i++) begin req = new(); req.addr = (get_id() * `num_loops) + i; req.data = get_id() + i + 55; req.op = BUS_WRITE; $display("scen issue op: %s", req.convert2string()); apply(req,rsp); req = new(); req.addr = (get_id() * `num_loops) + i; req.data = 0; req.op = BUS_READ; $display("scen issue op: %s", req.convert2string()); apply(req,rsp); if (rsp.data != (get_id() + i + 55)) begin $sformat(prstring, "Error, addr: %0d, expected data: %0d, actual data: %0d", req.addr, req.data, rsp.data); ovm_report_error("ScenarioA", prstring); end end ovm_report_message("scenarioA", "Finishing scenario"); endtask // body task pre_apply(); $display("In Pre-apply of scenario %0d", get_id()); endtask endclasspre_applyタスクは、メッセージを表示しているだけですが、
bodyタスクはnum_loops回(実際には10回のBUS_WRITE->BUS_READをシナリオコントローラに送っています。
ここで定義したbodyタスクは、ovm_scenario_base::startタスクで説明したようにstartタスク内で呼び出されます。
my_driverクラスは、次のようにrunタスクを定義しています。
req.opの値でBUS_READ/BUS_WRITEの処理を行い、put_rsp.put(rsp)でシナリオコントローラに応答しています。
class my_driver #(type REQ = ovm_sequence_item, type RSP = ovm_sequence_item) extends ovm_scenario_driver #(REQ, RSP); int data_array[511:0]; function new(string name, ovm_component parent); super.new(name, parent); endfunction task run(); REQ req; RSP rsp; forever begin get_next_item(req); #1; rsp = new(); rsp.copy_req(req); // Actually do the read or write here if (req.op == BUS_READ) begin rsp.data = data_array[req.addr[8:0]]; $display("Driver Read, addr: %0d, rdata: %0d", req.addr, rsp.data); end else begin data_array[req.addr[8:0]] = req.data; $display("Driver Write, addr: %0d, data: %0d", req.addr, req.data); end $display("Driver about to call put rsp"); put_rsp.put(rsp); $display("Driver called put rsp"); end endtask endclassrunタスクでは、get_next_itemタスクでシナリオコントローラからREQ(req)を受け取り、
req.opの値でBUS_READ/BUS_WRITEの処理を行い、put_rsp.put(rsp)でシナリオコントローラに応答しています。
検証、Verification、SystemVerilog、OVM、Open Verification Methodology