Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

vmm_vxc_managerクラスの実装(その10)

Verification Engineerの戯言

vmm_vxc_managerクラスINTERRUPTコマンドを解釈するtry_interrupt関数を見てみましょう!
基本的には、try_action関数と同じです。
    function bit vmm_xvc_manager::try_interrupt();

        // 途中、略

        //parse cmd and extract information.
        //syntax is of the form:
        //  I[NTERRUPT] [ONESHOT] <instance> <action> \
        //    [W[AIT] wait_for] \ 
        //    [E[VENT] event [event]]
        arg_no = 1;
        if (this.argv[arg_no].tolower() == "oneshot") begin
            is_oneshot = 1;
            arg_no++;
        end else begin
            is_oneshot = 0;
        end
        inst       = this.argv[arg_no++];
        action_str = this.argv[arg_no++]; 
        while (1) begin
            string tmpstr;
            //if there are args still left over..
            if (arg_no >= this.argv.size()) 
                break;
            tmpstr = this.argv[arg_no].tolower;
            if(`vmm_str_match(tmpstr, "^(w|wait)")) begin
                arg_no++;
            //ToDo: error if no wait argument
            wait_for_ev = this.argv[arg_no++];
            continue;
        end
        tmpstr = this.argv[arg_no].tolower;
        if (`vmm_str_match(tmpstr, "^(e|event)")) begin
            arg_no++;
            //ToDo: error if dont have atleast 1 arg
            while (`vmm_str_match(this.argv[arg_no], "^[0-9.]*$")) begin
                emit_ev_list.push_back(this.argv[arg_no]);
                arg_no++;
                if (arg_no >= this.argv.size()) 
                    break;
            end
        end   
    end
前半は構文の解釈部です。オプションのW[AIT]とE[MIT]は、この順番でないといけません。
また、この部分は、`vmm_str_matchマクロを使って解釈しています。
        //Iterate over xactor instances
        begin
            xvc_xactor xvc;
            xvc_action action;

            this.for_reset(inst);
            xvc = this.for_each();
            if (xvc == null) begin
                `vmm_error(this.log, 
                           $psprintf("%s, line %0d: No such XVC %s",
                                     this.testfile, 
                                     this.linec,
                                     inst)
                          );
                return 1;
            end
こでは、インスタンス(vxc)が存在するかどうかをチェックします。
            // Actions can only apply to one XVC
            if (this.for_each() != null) begin
                `vmm_error(this.log, 
                           $psprintf("%s, line %0d: Action matches multiple XVCs %s",
                                     this.testfile, 
                                     this.linec,
                                     inst)
                           );
                return 1;
            end
ここでは、アクションが特定のインスタンス(xvc)にだけのモノかをチェックします。
            //There must be a current scenario for an action/interrupt
            if (this.current_sc == null) begin
                `vmm_error(this.log, 
                           $psprintf("%s, line %0d: Action not preceded by scenario",
                                     this.testfile, 
                                     this.linec)
                           );
                return 1;
            end
ここでは、アクションがシナリオコマンドの後になっているかどうかをチェックします。
            //Split up string , remove extra white spaces
            // and pass it as a argv array to the xvc.parse()
            begin
                string action_str_args[];
                this.split(action_str, action_str_args);
                action = xvc.parse(action_str_args);
                if (action == null) return 1;
            end
アクション部の文字列を分割、解析し、アクション部を取り出します。
            //create the action and put it in the Q. 
            begin
                vmm_xvc_action_block act_b = new;
                act_b.xvc_mgr = this;
                act_b.descr = action_str;
                act_b.action = action; 
                act_b.xvc = xvc;
                act_b.sc  = this.current_sc;
                act_b.is_interrupt = 1;
                act_b.is_interrupt_oneshot = is_oneshot; 
                act_b.set_wait(wait_for_ev);
                act_b.set_emit(emit_ev_list);
                this.current_sc.actionQ.push_back(act_b);
            end
この部分でやっとアクションをactionQに登録します。
    `ifdef VMM_DETAILED_MSGS
            if (this.log.start_msg(vmm_log::INTERNAL_TYP , vmm_log::DEBUG_SEV )) begin
                void'(this.log.text(
                      $psprintf("%s, 
                                line %0d: Adding interrupt action %s to scenario %s...",
                                this.testfile, 
                                this.linec, 
                                action_str,
                                this.current_sc.name)));
                      this.log.end_msg();
            end
    `endif  
        end
    endfunction: try_interrupt

検証、Verification、SystemVerilog、VMM、Verifica