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)
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