zoukankan      html  css  js  c++  java
  • uvm_hdl——DPI在UVM中的实现(四)

      我们可以在uvm中实现HDL的后门访问,具体包括的function有uvm_hdl_check_path,uvm_hdl_deposit, uvm_hdl_force,uvm_hdl_release,uvm_hdl_read, task 有uvm_hdl_force_time。 这么做与直接用SV中force, release 有什么区别,有什么好处?这么做的话函数的输入是字符串而不是HDL(hardware description language, 硬件描述语言 )的层次结构。有了字符串就可以模块化了(函数),首先来看uvm_hdl.svh的源代码,当定义了UVM_HDL_NO_DPI,而用户由调用了HDL DPI相关的函数,这时会报错。

    // TITLE: UVM HDL Backdoor Access support routines.
    //
    // These routines provide an interface to the DPI/PLI
    // implementation of backdoor access used by registers.
    //
    // If you DON'T want to use the DPI HDL API, then compile your
    // SystemVerilog code with the vlog switch
    //:   vlog ... +define+UVM_HDL_NO_DPI ...
    //
    
    
    `ifndef UVM_HDL__SVH
    `define UVM_HDL__SVH
    
    
    `ifndef UVM_HDL_MAX_WIDTH
    `define UVM_HDL_MAX_WIDTH 1024
    `endif
    
    /* 
     * VARIABLE: UVM_HDL_MAX_WIDTH
     * Sets the maximum size bit vector for backdoor access. 
     * This parameter will be looked up by the 
     * DPI-C code using:
     *   vpi_handle_by_name(
     *     "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
     */
    parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;
    
    
    typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t;
    
                                
    `ifndef UVM_HDL_NO_DPI
    
      // Function: uvm_hdl_check_path
      //
      // Checks that the given HDL ~path~ exists. Returns 0 if NOT found, 1 otherwise.
      //
      import "DPI-C" context function int uvm_hdl_check_path(string path);
    
    
      // Function: uvm_hdl_deposit
      //
      // Sets the given HDL ~path~ to the specified ~value~.
      // Returns 1 if the call succeeded, 0 otherwise.
      //
      import "DPI-C" context function int uvm_hdl_deposit(string path, uvm_hdl_data_t value);
    
    
      // Function: uvm_hdl_force
      //
      // Forces the ~value~ on the given ~path~. Returns 1 if the call succeeded, 0 otherwise.
      //
      import "DPI-C" context function int uvm_hdl_force(string path, uvm_hdl_data_t value);
    
    
      // Function: uvm_hdl_force_time
      //
      // Forces the ~value~ on the given ~path~ for the specified amount of ~force_time~.
      // If ~force_time~ is 0, <uvm_hdl_deposit> is called.
      // Returns 1 if the call succeeded, 0 otherwise.
      //
      task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time = 0);
        if (force_time == 0) begin
          void'(uvm_hdl_deposit(path, value));
          return;
        end
        if (!uvm_hdl_force(path, value))
          return;
        #force_time;
        void'(uvm_hdl_release_and_read(path, value));
      endtask
    
    
      // Function: uvm_hdl_release_and_read
      //
      // Releases a value previously set with <uvm_hdl_force>.
      // Returns 1 if the call succeeded, 0 otherwise. ~value~ is set to
      // the HDL value after the release. For 'reg', the value will still be
      // the forced value until it has been procedurally reassigned. For 'wire',
      // the value will change immediately to the resolved value of its
      // continuous drivers, if any. If none, its value remains as forced until
      // the next direct assignment.
      //
      import "DPI-C" context function int uvm_hdl_release_and_read(string path, inout uvm_hdl_data_t value);
    
    
      // Function: uvm_hdl_release
      //
      // Releases a value previously set with <uvm_hdl_force>.
      // Returns 1 if the call succeeded, 0 otherwise.
      //
      import "DPI-C" context function int uvm_hdl_release(string path);
    
    
      // Function: uvm_hdl_read()
      //
      // Gets the value at the given ~path~.
      // Returns 1 if the call succeeded, 0 otherwise.
      //
      import "DPI-C" context function int uvm_hdl_read(string path, output uvm_hdl_data_t value);
    
    `else
    
      function int uvm_hdl_check_path(string path);
        uvm_report_fatal("UVM_HDL_CHECK_PATH", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
        return 0;
      endfunction
    
      function int uvm_hdl_deposit(string path, uvm_hdl_data_t value);
        uvm_report_fatal("UVM_HDL_DEPOSIT", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
        return 0;
      endfunction
    
      function int uvm_hdl_force(string path, uvm_hdl_data_t value);
        uvm_report_fatal("UVM_HDL_FORCE", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
        return 0;
      endfunction
    
      task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time=0);
        uvm_report_fatal("UVM_HDL_FORCE_TIME", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
      endtask
    
      function int uvm_hdl_release(string path, output uvm_hdl_data_t value);
        uvm_report_fatal("UVM_HDL_RELEASE", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
        return 0;
      endfunction
    
      function int uvm_hdl_read(string path, output uvm_hdl_data_t value);
        uvm_report_fatal("UVM_HDL_READ", 
          $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI"));
        return 0;
      endfunction
    
    `endif
    
    
    `endif

    与之对应的uvm_hdl.c实现如下,由于每个EDA vendor 具体实现方式不同,所有分别包含在不同的文件中了。

    // hdl vendor backends are defined for VCS,QUESTA,INCA
    #if defined(VCS) || defined(VCSMX)
    #include "uvm_hdl_vcs.c"
    #else
    #ifdef QUESTA
    #include "uvm_hdl_questa.c"
    #else
    #if defined(INCA) || defined(NCSC)
    #include "uvm_hdl_inca.c"
    #else
    #error "hdl vendor backend is missing"
    #endif
    #endif
    #endif

    首先来看Synopsy家的uvm_hdl_vcs.c:

    #include "uvm_dpi.h"
    #include <math.h>
    
    #include "svdpi.h"
    #include "vcsuser.h"
    
    #ifdef VCSMX
    #include "mhpi_user.h"
    #include "vhpi_user.h"
    #endif
    
    
    /* 
     * UVM HDL access C code.
     *
     */
    
    /*
     * This C code checks to see if there is PLI handle
     * with a value set to define the maximum bit width.
     *
     * If no such variable is found, then the default 
     * width of 1024 is used.
     *
     * This function should only get called once or twice,
     * its return value is cached in the caller.
     *
     */
    static int uvm_hdl_max_width()
    {
      vpiHandle ms;
      s_vpi_value value_s = { vpiIntVal, { 0 } };
      ms = vpi_handle_by_name((PLI_BYTE8*) "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
      if(ms == 0) 
        return 1024;  /* If nothing else is defined, 
                         this is the DEFAULT */
      vpi_get_value(ms, &value_s);
      return value_s.value.integer;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI,
     * and set it to 'value'.
     */
    static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      vpiHandle r;
      s_vpi_value value_s = { vpiIntVal, { 0 } };
      s_vpi_time  time_s = { vpiSimTime, 0, 0, 0.0 };
    
      //vpi_printf("uvm_hdl_set_vlog(%s,%0x)
    ",path,value[0].aval);
    
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
      {
          const char * err_str = "set: unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name";
          char buffer[strlen(err_str) + strlen(path)];
          sprintf(buffer, err_str, path);
          m_uvm_report_dpi(M_UVM_ERROR,
                           (char*) "UVM/DPI/HDL_SET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
        return 0;
      }
      else
      {
        if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
        if (flag == vpiReleaseFlag) {
          //size = vpi_get(vpiSize, r);
          //value_p = (p_vpi_vecval)(malloc(((size-1)/32+1)*8*sizeof(s_vpi_vecval)));
          //value = &value_p;
        }
        value_s.format = vpiVectorVal;
        value_s.value.vector = value;
        vpi_put_value(r, &value_s, &time_s, flag);  
        //if (value_p != NULL)
        //  free(value_p);
        if (value == NULL) {
          value = value_s.value.vector;
        }
      }
      return 1;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * and return its 'value'.
     */
    static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      int i, size, chunks;
      vpiHandle r;
      s_vpi_value value_s;
    
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
      {
          const char * err_str = "get: unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name";
          char buffer[strlen(err_str) + strlen(path)];
          sprintf(buffer, err_str, path);
          m_uvm_report_dpi(M_UVM_ERROR,
                  (char*)"UVM/DPI/HDL_GET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
        // Exiting is too harsh. Just return instead.
        // tf_dofinish();
        return 0;
      }
      else
      {
        if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
        size = vpi_get(vpiSize, r);
        if(size > maxsize)
        {
          const char * err_str = "uvm_reg : hdl path '%s' is %0d bits, but the maximum size is %0d.  You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>";
          char buffer[strlen(err_str) + strlen(path) + (2*int_str_max(10))];
          sprintf(buffer, err_str, path, size, maxsize);
          m_uvm_report_dpi(M_UVM_ERROR,
                  (char*)"UVM/DPI/HDL_SET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
          return 0;
        }
        chunks = (size-1)/32 + 1;
    
        value_s.format = vpiVectorVal;
        vpi_get_value(r, &value_s);
        /*dpi and vpi are reversed*/
        for(i=0;i<chunks; ++i)
        {
          value[i].aval = value_s.value.vector[i].aval;
          value[i].bval = value_s.value.vector[i].bval;
        }
      }
      //vpi_printf("uvm_hdl_get_vlog(%s,%0x)
    ",path,value[0].aval);
      return 1;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI,
     * but don't set or get. Just check.
     *
     * Return 0 if NOT found.
     * Return 1 if found.
     */
    int uvm_hdl_check_path(char *path)
    {
      vpiHandle r;
    
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
          return 0;
      else 
        return 1;
    }
    
    /*
     * convert binary to integer
     */
    long int uvm_hdl_btoi(char *binVal) {
      long int remainder, dec=0, j = 0;
      unsigned long long int bin;
      int i;
      char tmp[2];
      tmp[1] = '';
    
      for(i= strlen(binVal) -1 ; i >= 0 ; i--) {
        tmp[0] = binVal[i];
        bin = atoi(tmp);
        dec = dec+(bin*(pow(2,j)));
        j++;
      }
      return(dec);
    }
    
    
    /*
     *decimal to hex conversion
     */
    char *uvm_hdl_dtob(long int decimalNumber) {
       int remainder, quotient;
      int  i=0,j, length;
      int binN[65];
      static char binaryNumber[65];
      char *str = (char*) malloc(sizeof(char));
    
      quotient = decimalNumber;
    
      do {
        binN[i++] = quotient%2;
        quotient = quotient/2;
      } while (quotient!=0);
      length = i;
    
      for (i=length-1, j = 0; i>=0; i--) {
        binaryNumber[j++] = binN[i]?'1':'0';
      }
      binaryNumber[j] = '';
      return(binaryNumber);
    }
    
    
    /*
     * Mixed lanaguage API Get calls
     */
    #ifdef VCSMX
    int uvm_hdl_get_mhdl(char *path, p_vpi_vecval value) {
    
      long int value_int;
    
      char *binVal;
      int i = 0;
      vhpiValueT value1;
      p_vpi_vecval vecval;
      mhpi_initialize('/');
      mhpiHandleT mhpiH = mhpi_handle_by_name(path, 0);
      vhpiHandleT vhpiH = (long unsigned int *)mhpi_get_vhpi_handle(mhpiH);
      value1.format=vhpiStrVal;
      value1.bufSize = vhpi_get(vhpiSizeP, vhpiH);
      value1.value.str = (char*)malloc(value1.bufSize*sizeof(char)+1);
    
    
      if (vhpi_get_value(vhpiH, &value1) == 0) {
        binVal = value1.value.str;
        
        value_int = uvm_hdl_btoi(binVal);
        value->aval = (PLI_UINT32) value_int;
        value->bval = 0;
        mhpi_release_parent_handle(mhpiH);
        free(value1.value.str);
        return(1);
        
    
      } else {
        mhpi_release_parent_handle(mhpiH);
        free(value1.value.str);
        return (0);
      }
    
    }
    #endif
    
    /*
     * Given a path, look the path name up using the PLI
     * or the VHPI, and return its 'value'.
     */
    int uvm_hdl_read(char *path, p_vpi_vecval value)
    {
    #ifndef VCSMX
         return uvm_hdl_get_vlog(path, value, vpiNoDelay);
    #else
        mhpi_initialize('/');
        mhpiHandleT h = mhpi_handle_by_name(path, 0);
        if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) {
        mhpi_release_parent_handle(h);
          return uvm_hdl_get_vlog(path, value, vpiNoDelay);
        }
        else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) {
    
        mhpi_release_parent_handle(h);
          return uvm_hdl_get_mhdl(path,value);
        }
    #endif
    }
    
    
    /*
     * Mixed Language API Set calls
     */
    #ifdef VCSMX
    int uvm_hdl_set_mhdl(char *path, p_vpi_vecval value, mhpiPutValueFlagsT flags) 
    {
        mhpi_initialize('/');
        mhpiRealT forceDelay = 0;
        mhpiRealT cancelDelay = -1;
        mhpiReturnT ret;
        mhpiHandleT h = mhpi_handle_by_name(path, 0);
        mhpiHandleT mhpi_mhRegion = mhpi_handle(mhpiScope, h);
        int val = value->aval;
        char *force_value = uvm_hdl_dtob(val);
    
        ret = mhpi_force_value(path, mhpi_mhRegion, force_value, flags, forceDelay, cancelDelay); 
        mhpi_release_parent_handle(h);
        if (ret == mhpiRetOk) {
          return(1);
        }
        else 
          return(0);
    }
    #endif
    
    /*
     * Given a path, look the path name up using the PLI
     * or the VHPI, and set it to 'value'.
     */
    int uvm_hdl_deposit(char *path, p_vpi_vecval value)
    {
    #ifndef VCSMX
         return uvm_hdl_set_vlog(path, value, vpiNoDelay);
    #else
        mhpi_initialize('/');
        mhpiHandleT h = mhpi_handle_by_name(path, 0);
    
        if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) {
        mhpi_release_parent_handle(h);
          return uvm_hdl_set_vlog(path, value, vpiNoDelay);
        }
        else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) {
          mhpi_release_parent_handle(h);
          return uvm_hdl_set_mhdl(path, value, mhpiNoDelay);
         }
        else
          return (0);
    #endif
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the VHPI, and set it to 'value'.
     */
    int uvm_hdl_force(char *path, p_vpi_vecval value)
    {
    #ifndef VCSMX
          return uvm_hdl_set_vlog(path, value, vpiForceFlag);
    #else
        mhpi_initialize('/');
        mhpiHandleT h = mhpi_handle_by_name(path, 0);
    
        if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) {
        mhpi_release_parent_handle(h);
          return uvm_hdl_set_vlog(path, value, vpiForceFlag);
        }
        else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) {
    
        mhpi_release_parent_handle(h);
          return uvm_hdl_set_mhdl(path, value, mhpiForce);
    
          }
        else
          return (0);
    #endif
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the VHPI, and release it.
     */
    int uvm_hdl_release_and_read(char *path, p_vpi_vecval value)
    {
        return uvm_hdl_set_vlog(path, value, vpiReleaseFlag);
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * or the VHPI, and release it.
     */
    int uvm_hdl_release(char *path)
    {
        s_vpi_vecval value;
        p_vpi_vecval valuep = &value;
    #ifndef VCSMX
         return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag);
    #else
        mhpi_initialize('/');
        mhpiHandleT h = mhpi_handle_by_name(path, 0);
        mhpiReturnT ret;
    
        if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) {
          return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag);
        }
        else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) {
          mhpiHandleT mhpi_mhRegion = mhpi_handle(mhpiScope, h);
          ret = mhpi_release_force(path, mhpi_mhRegion);
          if (ret == mhpiRetOk) {
            return(1);
          }
          else 
            return(0);
    
          }
        else
          return (0);
    #endif
    }
    View Code

    再看Cadence家的uvm_hdl_inca.c:

    // use -DINCA_EXTENDED_PARTSEL_SUPPORT to use extended support for vpi_handle_by_name
    
    #include "vhpi_user.h"
    #include "vpi_user.h"
    #include "veriuser.h"
    #include "svdpi.h"
    #include <malloc.h>
    #include <string.h>
    #include <stdio.h>
    
    static void m_uvm_error(const char *ID, const char *msg, ...);
    static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
    static void m_uvm_get_object_handle(const char* path, vhpiHandleT *handle,int *language);
    static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
    static int uvm_hdl_max_width();
    
    // static print buffer
    static char m_uvm_temp_print_buffer[1024];
    
    /* 
     * UVM HDL access C code.
     *
     */
    static void m_uvm_get_object_handle(const char* path, vhpiHandleT *handle,int *language)
    {
      *handle = vhpi_handle_by_name(path, 0);
    
      if(*handle)
          *language = vhpi_get(vhpiLanguageP, *handle);
    }
    
    // returns 0 if the name is NOT a slice
    // returns 1 if the name is a slice
    static int is_valid_path_slice(const char* path) {
          char *path_ptr = (char *) path;
          int path_len;
    
    #ifdef INCA_EXTENDED_PARTSEL_SUPPORT
          return 0;
    #endif
    
          path_len = strlen(path);
          path_ptr = (char*)(path+path_len-1);
    
          if (*path_ptr != ']')
            return 0;
    
          while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
            path_ptr--;
    
          if (path_ptr == path || *path_ptr != ':')
            return 0;
    
          while(path_ptr != path && *path_ptr != '[')
            path_ptr--;
    
          if (path_ptr == path || *path_ptr != '[')
            return 0;
    
          return 1;
    }
    
    static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      char *path_ptr = path;
      int path_len;
      svLogicVecVal bit_value;
    
      if(!is_valid_path_slice(path)) return 0;
      path_len = strlen(path);
      path_ptr = (char*)(path+path_len-1);
    
      if (*path_ptr != ']')
        return 0;
    
      while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != ':')
        return 0;
    
      while(path_ptr != path && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != '[')
        return 0;
    
      int lhs, rhs, width, incr;
    
      // extract range from path
      if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) {
        char index_str[20];
        int i;
        path_ptr++;
        path_len = (path_len - (path_ptr - path));
        incr = (lhs>rhs) ? 1 : -1;
        width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1;
    
        // perform set for each individual bit
        for (i=0; i < width; i++) {
          sprintf(index_str,"%u]",rhs);
          strncpy(path_ptr,index_str,path_len);
          svGetPartselLogic(&bit_value,value,i,1);
          rhs += incr;
          if (uvm_hdl_set_vlog_partsel(path,&bit_value,flag)==0) {
              if(uvm_hdl_set_vlog(path,&bit_value,flag)==0) { return 0; };
          }
        }
        return 1;
      }
      return 0;
    }
    
    
    /*
     * Given a path with part-select, break into individual bit accesses
     * path = pointer to user string
     * value = pointer to logic vector
     * flag = deposit vs force/release options, etc
     */
    static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      char *path_ptr = path;
      int path_len;
      svLogicVecVal bit_value;
    
      path_len = strlen(path);
      path_ptr = (char*)(path+path_len-1);
    
      if (*path_ptr != ']')
        return 0;
    
      while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != ':')
        return 0;
    
      while(path_ptr != path && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != '[')
        return 0;
    
      int lhs, rhs, width, incr;
    
      // extract range from path
      if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) {
        char index_str[20];
        int i;
        path_ptr++;
        path_len = (path_len - (path_ptr - path));
        incr = (lhs>rhs) ? 1 : -1;
        width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1;
        bit_value.aval = 0;
        bit_value.bval = 0;
        for (i=0; i < width; i++) {
          svLogic logic_bit;
          sprintf(index_str,"%u]",rhs);
          strncpy(path_ptr,index_str,path_len);
    
          if(uvm_hdl_get_vlog_partsel(path,&bit_value,flag) == 0) {
              if(uvm_hdl_get_vlog(path,&bit_value,flag)==0) { return 0; }
          }
    
          logic_bit = svGetBitselLogic(&bit_value,0);
          svPutPartselLogic(value,bit_value,i,1);
          rhs += incr;
        }
        return 1;
      } else {
          return 0;
      }
    }
    
    static void clear_value(p_vpi_vecval value) {
        int chunks;
        int maxsize = uvm_hdl_max_width();
        chunks = (maxsize-1)/32 + 1;
        for(int i=0;i<chunks-1; ++i) {
          value[i].aval = 0;
          value[i].bval = 0;
        }
    }
    
    /*
     * This C code checks to see if there is PLI handle
     * with a value set to define the maximum bit width.
     *
     * This function should only get called once or twice,
     * its return value is cached in the caller.
     *
     */
    static int UVM_HDL_MAX_WIDTH = 0;
    static int uvm_hdl_max_width()
    {
      if(!UVM_HDL_MAX_WIDTH) {
        vpiHandle ms;
        s_vpi_value value_s = { vpiIntVal, { 0 } };
        ms = vpi_handle_by_name((PLI_BYTE8*) "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
        vpi_get_value(ms, &value_s);
        UVM_HDL_MAX_WIDTH= value_s.value.integer;
      } 
      return UVM_HDL_MAX_WIDTH;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI,
     * and set it to 'value'.
     */
    static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      vpiHandle r;
      s_vpi_value value_s = { vpiIntVal, { 0 } };
      s_vpi_time  time_s = { vpiSimTime, 0, 0, 0.0 };
    
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
        {
          m_uvm_error("UVM/DPI/HDL_SET","set: unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name",
              path);
          return 0;
        }
      else
        {
          if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
          if (flag == vpiReleaseFlag) {
        // FIXME
        //size = vpi_get(vpiSize, r);
        //value_p = (p_vpi_vecval)(malloc(((size-1)/32+1)*8*sizeof(s_vpi_vecval)));
        //value = &value_p;
          }
          value_s.format = vpiVectorVal;
          value_s.value.vector = value;
          vpi_put_value(r, &value_s, &time_s, flag);  
          //if (value_p != NULL)
          //  free(value_p);
          if (value == NULL) {
        value = value_s.value.vector;
          }
        }
    
      vpi_release_handle(r);
    
      return 1;
    }
    
    static vhpiEnumT vhpiEnumTLookup[4] = {vhpi0,vhpi1,vhpiZ,vhpiX}; // idx={b[0],a[0]}
    static vhpiEnumT vhpi2val(int aval,int bval) {
      int idx=(((bval<<1) || (aval&1)) && 3);
      return vhpiEnumTLookup[idx];
    }
    
    static int uvm_hdl_set_vhdl(char* path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      int size, chunks, bit, i, j, aval, bval;
      vhpiValueT value_s;
      vhpiHandleT r = vhpi_handle_by_name(path, 0);
    
      if(maxsize == -1) maxsize = uvm_hdl_max_width();
      if(maxsize == -1) maxsize = 1024;
    
      size = vhpi_get(vhpiSizeP, r);
      if(size > maxsize)
        {
          m_uvm_error("UVM/DPI/VHDL_SET","hdl path %s is %0d bits, but the current maximum size is %0d. You may redefine it using the compile-time flag: -define UVM_HDL_MAX_WIDTH=<value>", path, size,maxsize);
    
          tf_dofinish();
        }
      chunks = (size-1)/32 + 1;
    
      value_s.format = vhpiObjTypeVal;
      value_s.bufSize = 0;
      value_s.value.str = NULL;
    
      vhpi_get_value(r, &value_s);
    
      switch(value_s.format)
        {
        case vhpiEnumVal:
          {
        value_s.value.enumv = vhpi2val(value[0].aval,value[0].bval);
        break;
          }
        case vhpiEnumVecVal:
          {
        value_s.bufSize = size*sizeof(int); 
        value_s.value.enumvs = (vhpiEnumT *)malloc(size*sizeof(int));
    
        vhpi_get_value(r, &value_s);
        chunks = (size-1)/32 + 1;
    
        bit = 0;
        for(i=0;i<chunks && bit<size; ++i)
          {
            aval = value[i].aval;
            bval = value[i].bval;
    
            for(j=0;j<32 && bit<size; ++j)
              {
            value_s.value.enumvs[size-bit-1]= vhpi2val(aval,bval);
            aval>>=1; bval>>=1;
            bit++;
              }
          }
        break;
          }
        default:
          {
        m_uvm_error("UVM/DPI/VHDL_SET","Failed to set value to hdl path %s (unexpected type: %0d)", path, value_s.format);
        tf_dofinish();
        return 0;
          }
        }
    
      vhpi_put_value(r, &value_s, flag);  
    
      if(value_s.format == vhpiEnumVecVal)
        {
          free(value_s.value.enumvs);
        }
      return 1;
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * and return its 'value'.
     */
    static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      int i, size, chunks;
      vpiHandle r;
      s_vpi_value value_s;
    
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
        {
          m_uvm_error("UVM/DPI/VLOG_GET","unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name",path);
          // Exiting is too harsh. Just return instead.
          // tf_dofinish();
          return 0;
        }
      else
        {
          if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
          size = vpi_get(vpiSize, r);
          if(size > maxsize)
        {
          m_uvm_error("UVM/DPI/VLOG_GET","hdl path '%s' is %0d bits, but the maximum size is %0d.  You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>",
              path,size,maxsize);
          //tf_dofinish();
    
          vpi_release_handle(r);
    
          return 0;
        }
          chunks = (size-1)/32 + 1;
    
          value_s.format = vpiVectorVal;
          vpi_get_value(r, &value_s);
          /*dpi and vpi are reversed*/
          for(i=0;i<chunks; ++i)
        {
          value[i].aval = value_s.value.vector[i].aval;
          value[i].bval = value_s.value.vector[i].bval;
        }
        }
      //vpi_printf("uvm_hdl_get_vlog(%s,%0x)
    ",path,value[0].aval);
    
      vpi_release_handle(r);
    
      return 1;
    }
    
    static int uvm_hdl_get_vhdl(char* path, p_vpi_vecval value)
    {
      static int maxsize = -1;
      int i, j, size, chunks, bit, aval, bval, rtn;
      vhpiValueT value_s;
      vhpiHandleT r = vhpi_handle_by_name(path, 0);
    
      if(maxsize == -1) maxsize = uvm_hdl_max_width();
      if(maxsize == -1) maxsize = 1024;
    
      size = vhpi_get(vhpiSizeP, r);
      if(size > maxsize)
        {
          m_uvm_error("UVM/DPI/HDL_SET","hdl path %s is %0d bits, but the maximum size is %0d, redefine using -define UVM_HDL_MAX_WIDTH=<value>", path, size,maxsize);
          tf_dofinish();
        }
      chunks = (size-1)/32 + 1;
      value_s.format = vhpiObjTypeVal;
      value_s.bufSize = 0;
      value_s.value.str = NULL;
    
      rtn = vhpi_get_value(r, &value_s);
    
      if(vhpi_check_error(0) != 0) 
        {
          m_uvm_error("UVM/DPI/VHDL_GET","Failed to get value from hdl path %s",path);
          tf_dofinish();
          return 0;
        }
    
      switch (value_s.format)
        {
        case vhpiIntVal:
          {
        value[0].aval = value_s.value.intg;
        value[0].bval = 0;
        break;
          }
        case vhpiEnumVal:
          {
        switch(value_s.value.enumv)
          {
          case vhpiU: 
          case vhpiW: 
          case vhpiX: 
            {
              value[0].aval = 1; value[0].bval = 1; break;
            }
          case vhpiZ: 
            {
              value[0].aval = 0; value[0].bval = 1; break;
            }
          case vhpi0: 
          case vhpiL: 
          case vhpiDontCare: 
            {
              value[0].aval = 0; value[0].bval = 0; break;
            }
          case vhpi1: 
          case vhpiH: 
            {
              value[0].aval = 1; value[0].bval = 0; break;
            }
          }
        break;
          }
        case vhpiEnumVecVal:
          {
        value_s.bufSize = size;
        value_s.value.str = (char*)malloc(size);
        rtn = vhpi_get_value(r, &value_s);
        if (rtn > 0) {
          value_s.value.str = (char*)realloc(value_s.value.str, rtn);
          value_s.bufSize = rtn;
          vhpi_get_value(r, &value_s);
        }
        for(i=0; i<((maxsize-1)/32+1); ++i)
          {
            value[i].aval = 0;
            value[i].bval = 0;
          }
        bit = 0;
        for(i=0;i<chunks && bit<size; ++i)
          {
            aval = 0;
            bval = 0;
            for(j=0;(j<32) && (bit<size); ++j)
              {
            aval<<=1; bval<<=1;
            switch(value_s.value.enumvs[bit])
              {
              case vhpiU: 
              case vhpiW: 
              case vhpiX: 
                {
                  aval |= 1;
                  bval |= 1;
                  break;
                }
              case vhpiZ: 
                {
                  bval |= 1;
                  break;
                }
              case vhpi0: 
              case vhpiL: 
              case vhpiDontCare: 
                {
                  break;
                }
              case vhpi1: 
              case vhpiH: 
                {
                  aval |= 1;
                  break;
                }
              }
            bit++;
              }
            value[i].aval = aval;
            value[i].bval = bval;
            free (value_s.value.str);
          }
        break;
          }
        default:
          {
              m_uvm_error("UVM/DPI/VHDL_GET","Failed to get value from hdl path %s (unexpected type: %0d)", path, value_s.format);
    
        tf_dofinish();
        return 0;
          }
        }
      return 1;
    }
    
    /*
     * Given a path, look the path name up using the PLI,
     * but don't set or get. Just check.
     *
     * Return 0 if NOT found.
     * Return 1 if found.
     */
    int uvm_hdl_check_path(char *path)
    {
      vhpiHandleT handle;
      int language;
    
      m_uvm_get_object_handle(path,&handle,&language);
    
      return (handle!=0);
    }
    
    static void m_uvm_error(const char *id, const char *msg, ...) {
            va_list argptr;
            va_start(argptr,msg);
            vsprintf(m_uvm_temp_print_buffer,msg, argptr);
            va_end(argptr);
            m_uvm_report_dpi(M_UVM_ERROR,
                 (char *) id,
                 &m_uvm_temp_print_buffer[0],
                 M_UVM_NONE,
                 (char*) __FILE__,
                 __LINE__);
    }
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and return its 'value'.
     */
    int uvm_hdl_read(char *path, p_vpi_vecval value)
    {
            vhpiHandleT handle;
            int language;
    
            if(is_valid_path_slice(path)) {
                clear_value(value);
                return uvm_hdl_get_vlog_partsel(path, value, vpiNoDelay);
            }
    
            m_uvm_get_object_handle(path,&handle,&language);
            switch(language) {
                case vhpiVerilog:  return uvm_hdl_get_vlog(path, value, vpiNoDelay);
                case vhpiVHDL: return uvm_hdl_get_vhdl(path, value);
                default:m_uvm_error("UVM/DPI/NOBJ1","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0;
            }
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and set it to 'value'.
     */
    int uvm_hdl_deposit(char *path, p_vpi_vecval value)
    {
        vhpiHandleT handle;
        int language;
    
        if(is_valid_path_slice(path))
            return uvm_hdl_set_vlog_partsel(path, value, vpiNoDelay);
    
        m_uvm_get_object_handle(path,&handle,&language);
        switch(language) {
            case vhpiVerilog:  return uvm_hdl_set_vlog(path, value, vpiNoDelay);
            case vhpiVHDL: return uvm_hdl_set_vhdl(path, value, vhpiDepositPropagate);
            default:m_uvm_error("UVM/DPI/NOBJ2","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0;
        }
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and set it to 'value'.
     */
    int uvm_hdl_force(char *path, p_vpi_vecval value)
    {
        vhpiHandleT handle;
        int language;
    
        if(is_valid_path_slice(path))
            return uvm_hdl_set_vlog_partsel(path, value, vpiForceFlag);
    
        m_uvm_get_object_handle(path,&handle,&language);
        switch(language) {
            case vhpiVerilog:  return uvm_hdl_set_vlog(path, value, vpiForceFlag);
            case vhpiVHDL: return uvm_hdl_set_vhdl(path, value, vhpiForcePropagate);
            default:m_uvm_error("UVM/DPI/NOBJ3","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0;
        }
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and release it.
     */
    int uvm_hdl_release_and_read(char *path, p_vpi_vecval value)
    {
        vhpiHandleT handle;
        int language;
    
        if(is_valid_path_slice(path)) {
            uvm_hdl_set_vlog_partsel(path, value, vpiReleaseFlag);
            clear_value(value);
            return uvm_hdl_get_vlog_partsel(path, value, vpiNoDelay);
        }
    
        m_uvm_get_object_handle(path,&handle,&language);
        switch(language) {
            case vhpiVerilog:      uvm_hdl_set_vlog(path, value, vpiReleaseFlag); return uvm_hdl_get_vlog(path, value, vpiNoDelay);
            case vhpiVHDL:    uvm_hdl_set_vhdl(path, value, vhpiReleaseKV); return uvm_hdl_get_vhdl(path, value);
            default:m_uvm_error("UVM/DPI/NOBJ4","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0;
        }
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and release it.
     */
    int uvm_hdl_release(char *path)
    {
        s_vpi_vecval value;
        vhpiHandleT handle;
        int language;
    
        if(is_valid_path_slice(path))
            return uvm_hdl_set_vlog_partsel(path, &value, vpiReleaseFlag);
    
        m_uvm_get_object_handle(path,&handle,&language);
        switch(language) {
            case vhpiVerilog:  return uvm_hdl_set_vlog(path, &value, vpiReleaseFlag);
            case vhpiVHDL: return uvm_hdl_set_vhdl(path, &value, vhpiReleaseKV);
            default:m_uvm_error("UVM/DPI/NOBJ5","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0;
        }
    }
    View Code

    最后,Mentor Graphic的uvm_hdl_questa.c:

    #include "uvm_dpi.h"
    
    
    /* 
     * UVM HDL access C code.
     *
     */
    
    /*
     * This C code checks to see if there is PLI handle
     * with a value set to define the maximum bit width.
     *
     * If no such variable is found, then the default 
     * width of 1024 is used.
     *
     * This function should only get called once or twice,
     * its return value is cached in the caller.
     *
     */
    static int uvm_hdl_max_width()
    {
      vpiHandle ms;
      s_vpi_value value_s = { vpiIntVal, { 0 } };
      ms = vpi_handle_by_name((PLI_BYTE8*) "uvm_pkg::UVM_HDL_MAX_WIDTH", 0);
      if(ms == 0) 
        return 1024;  /* If nothing else is defined, 
                         this is the DEFAULT */
      vpi_get_value(ms, &value_s);
      return value_s.value.integer;
    }
    
    
    #ifdef QUESTA
    static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
    static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);
    static int partsel = 0;
    
    /*
     * Given a path with part-select, break into individual bit accesses 
     * path = pointer to user string
     * value = pointer to logic vector
     * flag = deposit vs force/release options, etc
     */
    static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      char *path_ptr = path;
      int path_len, idx;
      svLogicVecVal bit_value;
    
      path_len = strlen(path);
      path_ptr = (char*)(path+path_len-1);
    
      if (*path_ptr != ']') 
        return 0;
    
      while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != ':') 
        return 0;
    
      while(path_ptr != path && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != '[') 
        return 0;
    
      int lhs, rhs, width, incr;
    
      // extract range from path
      if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) {
        char index_str[20];
        int i;
        path_ptr++;
        path_len = (path_len - (path_ptr - path));
        incr = (lhs>rhs) ? 1 : -1;
        width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1;
    
        // perform set for each individual bit
        for (i=0; i < width; i++) {
          sprintf(index_str,"%u]",rhs);
          strncpy(path_ptr,index_str,path_len);
          svGetPartselLogic(&bit_value,value,i,1);
          rhs += incr;
          if (!uvm_hdl_set_vlog(path,&bit_value,flag))
            return 0;
        }
        return 1;
      }
    }
    
    
    /*
     * Given a path with part-select, break into individual bit accesses 
     * path = pointer to user string
     * value = pointer to logic vector
     * flag = deposit vs force/release options, etc
     */
    static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      char *path_ptr = path;
      int path_len, idx;
      svLogicVecVal bit_value;
    
      path_len = strlen(path);
      path_ptr = (char*)(path+path_len-1);
    
      if (*path_ptr != ']') 
        return 0;
    
      while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != ':') 
        return 0;
    
      while(path_ptr != path && *path_ptr != '[')
        path_ptr--;
    
      if (path_ptr == path || *path_ptr != '[') 
        return 0;
    
      int lhs, rhs, width, incr;
    
      // extract range from path
      if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) {
        char index_str[20];
        int i;
        path_ptr++;
        path_len = (path_len - (path_ptr - path));
        incr = (lhs>rhs) ? 1 : -1;
        width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1;
        bit_value.aval = 0;
        bit_value.bval = 0;
        partsel = 1;
        for (i=0; i < width; i++) {
          int result;
          svLogic logic_bit;
          sprintf(index_str,"%u]",rhs);
          strncpy(path_ptr,index_str,path_len);
          result = uvm_hdl_get_vlog(path,&bit_value,flag);
          logic_bit = svGetBitselLogic(&bit_value,0);
          svPutPartselLogic(value,bit_value,i,1);
          rhs += incr;
          if (!result)
            return 0;
        }
        partsel = 0;
        return 1;
      }
    }
    #endif
    
    
    /*
     * Given a path, look the path name up using the PLI,
     * and set it to 'value'.
     */
    static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      vpiHandle r;
      s_vpi_value value_s = { vpiIntVal, { 0 } };
      s_vpi_time  time_s = { vpiSimTime, 0, 0, 0.0 };
    
      //vpi_printf("uvm_hdl_set_vlog(%s,%0x)
    ",path,value[0].aval);
    
      #ifdef QUESTA
      int result = 0;
      result = uvm_hdl_set_vlog_partsel(path,value,flag);
      if (result < 0)
        return 0;
      if (result == 1)
        return 1;
    
      if (!strncmp(path,"$root.",6))
        r = vpi_handle_by_name(path+6, 0);
      else
      #endif
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
      {
          const char * err_str = "set: unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name";
          char buffer[strlen(err_str) + strlen(path)];
          sprintf(buffer, err_str, path);
          m_uvm_report_dpi(M_UVM_ERROR,
                           (char*) "UVM/DPI/HDL_SET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
        return 0;
      }
      else
      {
        if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
        if (flag == vpiReleaseFlag) {
          //size = vpi_get(vpiSize, r);
          //value_p = (p_vpi_vecval)(malloc(((size-1)/32+1)*8*sizeof(s_vpi_vecval)));
          //value = &value_p;
        }
        value_s.format = vpiVectorVal;
        value_s.value.vector = value;
        vpi_put_value(r, &value_s, &time_s, flag);  
        //if (value_p != NULL)
        //  free(value_p);
        if (value == NULL) {
          value = value_s.value.vector;
        }
      }
    #ifndef VCS
      vpi_release_handle(r);
    #endif
      return 1;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * and return its 'value'.
     */
    static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag)
    {
      static int maxsize = -1;
      int i, size, chunks;
      vpiHandle r;
      s_vpi_value value_s;
    
      #ifdef QUESTA
      if (!partsel) {
        maxsize = uvm_hdl_max_width();
        chunks = (maxsize-1)/32 + 1;
        for(i=0;i<chunks-1; ++i) {
          value[i].aval = 0;
          value[i].bval = 0;
        }
      }
      int result = 0;
      result = uvm_hdl_get_vlog_partsel(path,value,flag);
      if (result < 0)
        return 0;
      if (result == 1)
        return 1;
    
      if (!strncmp(path,"$root.",6))
        r = vpi_handle_by_name(path+6, 0);
      else
      #endif
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
      {
          const char * err_str = "get: unable to locate hdl path (%s)
     Either the name is incorrect, or you may not have PLI/ACC visibility to that name";
          char buffer[strlen(err_str) + strlen(path)];
          sprintf(buffer, err_str, path);
          m_uvm_report_dpi(M_UVM_ERROR,
                  (char*)"UVM/DPI/HDL_GET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
        // Exiting is too harsh. Just return instead.
        // tf_dofinish();
        return 0;
      }
      else
      {
        if(maxsize == -1) 
            maxsize = uvm_hdl_max_width();
    
        size = vpi_get(vpiSize, r);
        if(size > maxsize)
        {
          const char * err_str = "uvm_reg : hdl path '%s' is %0d bits, but the maximum size is %0d.  You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>";
          char buffer[strlen(err_str) + strlen(path) + (2*int_str_max(10))];
          sprintf(buffer, err_str, path, size, maxsize);
          m_uvm_report_dpi(M_UVM_ERROR,
                  (char*)"UVM/DPI/HDL_SET",
                           &buffer[0],
                           M_UVM_NONE,
                           (char*)__FILE__,
                           __LINE__);
          //tf_dofinish();
    #ifndef VCS
          vpi_release_handle(r);
    #endif
          return 0;
        }
        chunks = (size-1)/32 + 1;
    
        value_s.format = vpiVectorVal;
        vpi_get_value(r, &value_s);
        /*dpi and vpi are reversed*/
        for(i=0;i<chunks; ++i)
        {
          value[i].aval = value_s.value.vector[i].aval;
          value[i].bval = value_s.value.vector[i].bval;
        }
      }
      //vpi_printf("uvm_hdl_get_vlog(%s,%0x)
    ",path,value[0].aval);
    #ifndef VCS
      vpi_release_handle(r);
    #endif
      return 1;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI,
     * but don't set or get. Just check.
     *
     * Return 0 if NOT found.
     * Return 1 if found.
     */
    int uvm_hdl_check_path(char *path)
    {
      vpiHandle r;
    
      #ifdef QUESTA
      if (!strncmp(path,"$root.",6)) {
        r = vpi_handle_by_name(path+6, 0);
      }
      else
      #endif
      r = vpi_handle_by_name(path, 0);
    
      if(r == 0)
          return 0;
      else 
        return 1;
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and return its 'value'.
     */
    int uvm_hdl_read(char *path, p_vpi_vecval value)
    {
        return uvm_hdl_get_vlog(path, value, vpiNoDelay);
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and set it to 'value'.
     */
    int uvm_hdl_deposit(char *path, p_vpi_vecval value)
    {
        return uvm_hdl_set_vlog(path, value, vpiNoDelay);
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and set it to 'value'.
     */
    int uvm_hdl_force(char *path, p_vpi_vecval value)
    {
        return uvm_hdl_set_vlog(path, value, vpiForceFlag);
    }
    
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and release it.
     */
    int uvm_hdl_release_and_read(char *path, p_vpi_vecval value)
    {
        return uvm_hdl_set_vlog(path, value, vpiReleaseFlag);
    }
    
    /*
     * Given a path, look the path name up using the PLI
     * or the FLI, and release it.
     */
    int uvm_hdl_release(char *path)
    {
      s_vpi_vecval value;
      p_vpi_vecval valuep = &value;
      return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag);
    }
    View Code
  • 相关阅读:
    第一章 数据集散地:数据库
    第六章 使用ADO.NET查询和操作数据
    第五章 使用ADO.NET访问数据库
    第四章 深入C#的String类
    IOS框架和服务
    一步步调试解决iOS内存泄漏
    app跳转
    iOS 视频直播
    学习心得
    iOS中FMDB的使用
  • 原文地址:https://www.cnblogs.com/dpc525/p/8066518.html
Copyright © 2011-2022 走看看