You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求将svLogicVecVal*转换为uint8_t的API/库(DPI验证场景)

问题

在SystemVerilog中使用bit类型输入,需要转换为C语言的uint8_t类型,通过DPI验证Verilog结果时,编译C代码出现svLogicVecVal*与uint8_t*类型不兼容的警告,询问是否有可用的API或库实现该类型转换。

相关代码

SystemVerilog代码

//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);
}

编译错误

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

note: expected ‘uint8_t *’ but argument is of type ‘const struct svLogicVecVal *’
 void f2(const struct AES_ctx* ctx, uint8_t* buf);

warning: ‘main’ is normally a non-static function [-Wmain]
 int main(void)
解决方案

核心问题说明

svLogicVecVal是SystemVerilog通过DPI传递向量类型时的内部数据结构,无法直接作为uint8_t*传递给C函数,必须手动转换或使用仿真器提供的工具函数完成类型映射。


1. 单个bit类型与uint8_t的转换

如果是单个bit类型(如compute_bit函数中的参数),DPI会将其映射为C语言的svLogic类型(而非svLogicVecVal),直接转换即可:

// 假设C函数接收svLogic类型的输入
void compute_bit(svLogic i_value, svLogic* result) {
    uint8_t input_val = (i_value == SV_LOGIC_1) ? 1 : 0;
    // 处理逻辑...
    *result = (处理后的uint8_t值 != 0) ? SV_LOGIC_1 : SV_LOGIC_0;
}

2. 向量类型(如127:0 reg)转uint8_t数组

对于多bit向量,需要手动编写转换函数,将svLogicVecVal中的bit数据提取为uint8_t数组,反之亦然。

转换函数实现

#include <string.h>
#include <svdpi.h>

// 将svLogicVecVal转换为uint8_t数组
void svLogicVecToUint8(const svLogicVecVal* sv_vec, uint8_t* uint8_arr, int bit_size) {
    int byte_count = (bit_size + 7) / 8;
    memset(uint8_arr, 0, byte_count);

    for (int bit_idx = 0; bit_idx < bit_size; bit_idx++) {
        int byte_pos = bit_idx / 8;
        int bit_in_byte = bit_idx % 8;
        int sv_val_idx = bit_idx / 32; // 每个svLogicVecVal存储32位
        int sv_bit_pos = bit_idx % 32;

        // 提取对应bit的值(仅处理0/1,若需处理X/Z需检查sv_vec[sv_val_idx].bits)
        if (sv_vec[sv_val_idx].val & (1 << sv_bit_pos)) {
            uint8_arr[byte_pos] |= (1 << bit_in_byte);
        }
    }
}

// 将uint8_t数组转换回svLogicVecVal
void uint8ToSvLogicVec(const uint8_t* uint8_arr, svLogicVecVal* sv_vec, int bit_size) {
    int sv_val_count = (bit_size + 31) / 32;
    memset(sv_vec, 0, sizeof(svLogicVecVal) * sv_val_count);

    for (int bit_idx = 0; bit_idx < bit_size; bit_idx++) {
        int byte_pos = bit_idx / 8;
        int bit_in_byte = bit_idx % 8;
        int sv_val_idx = bit_idx / 32;
        int sv_bit_pos = bit_idx % 32;

        if (uint8_arr[byte_pos] & (1 << bit_in_byte)) {
            sv_vec[sv_val_idx].val |= (1 << sv_bit_pos);
        }
    }
}

修改compute_reg_vector函数

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};
    struct AES_ctx ctx;
    
    AES_init_ctx(&ctx, key);

    // 转换输入向量为uint8_t数组
    uint8_t input_buf[16] = {0};
    svLogicVecToUint8(i_value, input_buf, asize);

    // 调用AES加密函数
    f2(&ctx, input_buf);

    // 将加密结果转换回svLogicVecVal
    uint8ToSvLogicVec(input_buf, result, asize);

    for(int i=0; i<15; i++){
        printf("ECB encrypt: ");
        log_info("dpi_c.compute_reg_vector(): result %s", svLogicVecVal2String(result, asize));
    }
}

3. 仿真器原生API选项(可选)

部分商用仿真器提供了简化转换的API,例如:

  • Synopsys VCS: 使用svGetArrayPtr直接获取向量的底层指针,但需确保SV端口类型为logic而非reg,且仅在VCS环境下有效:
    const uint8_t* input_buf = (const uint8_t*)svGetArrayPtr(i_value);
    
  • Mentor Questa: 类似提供mq_get_array_ptr等函数,同样依赖仿真器环境。

这类方法兼容性较差,若需跨仿真器运行,建议使用手动转换函数。


4. 解决main函数警告

编译警告‘main’ is normally a non-static function是因为main函数被定义为static,只需去掉static修饰符,保留标准定义:

int main(void) {
    // 代码逻辑
}

内容的提问来源于stack exchange,提问作者jeff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:45:48