cverilogsystem-verilogsystem-verilog-dpi

is there any API to convert "svLogicVecVal *" to "uint_8"?


my input in systemverilog is in bits; but I need it to be in uint8_t. is API or library can do it? FYI, Im trying to verify verilog results with .C using "dpi".

system verilog:

//import "DPI-C" function int test_encrypt_ecb();

import "DPI-C" function void compute_bit(input bit i_value, output bit result);
import "DPI-C" function bit get_bit(input bit i_value);
import "DPI-C" function void compute_logic_vector(reg[127:0] i_value, reg[127:0] result, int asize);

c:


void compute_reg_vector(const svLogicVecVal* i_value, svLogicVecVal* result,
        int asize) {
    log_info("dpi_c.compute_reg_vector(): input %s",
            svLogicVecVal2String(i_value, asize));
    
    uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
    int j =0;
    struct AES_ctx ctx;
    j++;
    
    AES_init_ctx(&ctx, key);
    f2(&ctx, i_value);
    int i;
    for(i=0;i<15;i++){
    printf("ECB encrypt: ");
    memcpy(&result, i_value, 16);
    log_info("dpi_c.compute_reg_vector(): result %s",
            svLogicVecVal2String(result, asize));
}

void f2(const struct AES_ctx* ctx, uint8_t* buf)
{
 
  Cipher((state_t*)buf, ctx->Ry);
}


error of c compilation

warning: passing argument 2 of \f2\u2019 from incompatible pointer type [enabled by default]

note: expected \u2018uint8_t *\u2019 but argument is of type \u2018const struct svLogicVecVal *\u2019
 void f2(const struct AES_ctx* ctx, uint8_t* buf);

warning: \u2018main\u2019 is normally a non-static function [-Wmain]
 int main(void)

Solution

  • There are no API functions to convert from svLogicVecVal to other C types. You have to understand the C data structure representation of a 4-state (0,1,X,Z) data type which is

    typedef struct t_vpi_vecval {
      uint32_t aval; // 2-state component
      uint32_t bval; // 4-state component
    } s_vpi_vecval, *p_vpi_vecval;
    typedef s_vpi_vecval svLogicVecVal;
    

    A 128-bit packed 4-state value would be stored in an array of 8 32-bit words. The aval/bval words would be interwoven. Assuming you are only dealing with 2-state values, then picking up every other 32-bit word will work for you.

    However, if you know your DPI routines only need to deal with 2-state values, then your routines should use bit instead of reg/logic. Then your C routines only need to deal with svBitVecVal, which is defined as

    typedef uint32_t svBitVecVal;
    

    Which you can cast to uint8_t* as long as your arguments are multiples of 8 bits. Note for single bit arguments or return values, it is much more efficient to use C compatible types like byte/int that can be passed by value and require no pointers.

    Here is a small example

    SystemVerilog code:

    module top;
    import "DPI-C" function void compute_logic_vector(bit[127:0] i_value);
    
       logic [127:0] x = 128'h69c4_e0d8__6a7b_0430__d8cd_b780__70b4_c550;
    
       initial compute_logic_vector(x); // SV handles the 4- to 2-state conversion for you
    endmodule
    

    C code:

    #include "svBitVecVal.h" // compiler generated header guarantees prototypes match
    #include <stdint.h>
    #include <stdio.h>
    
    void compute_logic_vector(const svBitVecVal* i_value) {
      uint8_t* buf = (uint8_t*) i_value;
      for(int i=0;i<16;i++)
        printf("0x%x ",*buf++);
      printf("\n");
    }
    

    Command line to run Questa:

    qrun svBitVecVal.sv -dpiheader svBitVecVal.h svBitVecVal.c
    

    Output:

    # 0x50 0xc5 0xb4 0x70 0x80 0xb7 0xcd 0xd8 0x30 0x4 0x7b 0x6a 0xd8 0xe0 0xc4 0x69