DPI-C error from C to SV

I’m trying to call a systemverilog function from C. I’ve called the c-function from systemverilog and the response is going to be a call back from the C to the systemverilog. But I’m having some scoping issues. I put the:

export “DPI-c” context function export_task;

and the task declaration in the top level env class…ie

export “DPI-C” function export_task();

task export_task();
$display(“SV: hello from sv”);
endtask

class my_env extends uvm_env

endclass

** Error (suppressible): (vsim-3756) The DPI exported task ‘export_task’ must be called from a context imported tf. A call from a non-context imported tf was detected. The caller’s scope is test.

The nearest DPI import tf up the call chain is at line 196 of file …/src/env/myfile.sv

Time: 178716800 ps Iteration: 1 Region: /test/iMonitor::run_phase

** Fatal: (vsim-3757) The DPI exported task ‘export_task’ must be called from a context imported task. A call from a context imported function was detected. The caller’s scope is test.

The nearest DPI import tf up the call chain is at line 196 of file …/src/env/myfile.sv

I’m not sure what this error means, I’ve tried putting this export and task in various places, but I keep getting scoping errors. Where should I put the task and the export declaration?

In reply to mhibarger:

You haven’t shown you DPI-C import statement. To call a task from C needs to be called from an imported task, not a function. Remember, in SystemVerilog, tasks can call functions or tasks, but functions can only call functions.

If your export_task is really meant to be a non-time-consuming routine, then declare it a void function. Your import statement will still need to be imported with
import “DPI-C” context function void …;

Thanks Dave! I think that fixed it. Although I think the error message was cryptic.

In reply to mike_h:

I’m currently getting this warning message:

** Warning: (vsim-3770) Failed to find user specified function ‘c_encrypt_function’ in DPI precompiled library search list "/opt/tools/mentor/questasim/10.4_1/questasim/uvm-1.1d/linux_x86_64/uvm_dpi.so ".

followed by this:

** Fatal: (vsim-160) …/src/models/sim_models/encryption.sv(26): Null foreign function pointer encountered when calling ‘c_encrypt_function’

Time: 19353600 ps Iteration: 12 Process: /uvm_pkg::uvm_task_phase::execute/#FORK#137(#ublk#215181159#137)_7fefc98aeb8 File: …/src/models/sim_models/encryption.sv

Fatal error in Module test at …/src/models/sim_models/encryption.sv line 26

I’ve compiled the C and see the .o files in the ./work/_dpi directory. I’ve got this working in another bench, but the compilation and makefiles are a little different, but I don’t see any difference in the work dirs, it seems like the .o files are not being found by the SystemVerilog files and not being linked in correctly. Any help is appreciated. Thanks.

The DPI exported function ‘encryption_inputs_1’ must be called from a context imported tf. A call from a non-context imported tf was detected. The caller’s scope is ciphertest_sv.

The nearest DPI import tf up the call chain is at line 34 of file …/code/10_7_aes_gcm/verilog/file.sv . this is my sv code: module ciphertest_sv;

import "DPI-C" function void sv_print_encryption_inputs(
    input string key, input string iv, input string p, input string a
);

import "DPI-C" function void sv_print_encryption_outputs(
    input string c, input string tag
);

import "DPI-C" function void sv_print_decryption_inputs(
    input string key, input string iv, input string c, input string tag, input string a
);

import "DPI-C" function void sv_print_decryption_output(
    input string p
);

import "DPI-C" function void sv_print_final_result(
    input string msg
);

// Import the C function for running the ciphertest
import "DPI-C" function int ciphertest(input byte key[], input byte iv[], input byte p[], input byte a[], input byte c[],
                                       input int np, input int na, input byte nt, output string r);

// Import the C function for running the test
import "DPI-C" function int run_test();


// Task to call the run_test function in C
task run_full_test;
    int result;
    result = run_test();
    if (result == 0) begin
        $display("Full test passed.");
    end else begin
        $display("Full test failed with error code: %0d", result);
    end
endtask

initial begin
    // Run the full test task
    run_full_test();
end

// Define the DPI-C functions to print the received data
export "DPI-C" function encryption_inputs_1;
export "DPI-C" function encryption_outputs_1;
export "DPI-C" function decryption_inputs_1;
export "DPI-C" function decryption_outputs_1;
export "DPI-C" function final_result_1;

function void encryption_inputs_1(
    input string key, input string iv, input string p, input string a
);
//sv_print_encryption_inputs(
  //  input string key, input string iv, input string p, input string a

// );

    $display("Encryption Inputs:");
    $display("Key: %s", key);
    $display("IV: %s", iv);
    $display("Plaintext: %s", p);
    $display("AAD: %s", a);
endfunction

function void encryption_outputs_1(
    input string c, input string tag
);
    $display("Encryption Outputs:");
    $display("Ciphertext: %s", c);
    $display("Tag: %s", tag);
endfunction

function void decryption_inputs_1(
    input string key, input string iv, input string c, input string tag, input string a
);
    $display("Decryption Inputs:");
    $display("Key: %s", key);
    $display("IV: %s", iv);
    $display("Ciphertext: %s", c);
    $display("Tag: %s", tag);
    $display("AAD: %s", a);
endfunction

function void decryption_outputs_1(
    input string p
);
    $display("Decryption Output:");
    $display("Plaintext: %s", p);
endfunction

function void final_result_1(
    input string msg
);
    $display("Final Result: %s", msg);
endfunction

endmodule
c code : include <stdio.h>
include <stdint.h>
include <string.h>
include “micro_aes.h”
include “micro_aes.c”

define TESTFILEPATH “…/code/10_7_aes_gcm/c/GCM_EncryptExtIV128.rsp”

// Function declarations for DPI-C interface
extern void encryption_inputs_1(const char* key, const char* iv, const char* p, const char* a);
extern void encryption_outputs_1(const char* c, const char* tag);
extern void decryption_inputs_1(const char* key, const char* iv, const char* c, const char* tag, const char* a);
extern void decryption_outputs_1(const char* p);
extern void final_result_1(const char* msg);

void str2bytes(const char* hex, uint8_t* bytes) {
unsigned shl = 0;
for (–bytes; *hex; ++hex) {
if (*hex < ‘0’ || ‘f’ < *hex) continue;
if ((shl ^= 4) != 0) *++bytes = 0;
*bytes |= (*hex % 16 + (*hex > ‘9’) * 9) << shl;
}
}

void bytes2str(const uint8_t* bytes, char* str, const size_t len) {
const char offset = 0x27; /* offset must be 7 for uppercase */
size_t i = len + len, shr = 0;
for (str[i] = 0; i–; shr ^= 4) {
str[i] = bytes[i / 2] >> shr & 0xF | ‘0’;
if (str[i] > ‘9’) str[i] += offset;
}
}

int ciphertest(uint8_t* key, uint8_t* iv, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, uint8_t nt, char* r) {
char sk[65], si[2*GCM_NONCE_LEN + 1], sp[0x100], sc[0x100], sa[0x100], msg[30];
uint8_t tmp[0x80], t = 0;
sprintf(msg, “%s”, “passed the test”);

// Call SV function to print encryption inputs
char sk_str[65], si_str[2*GCM_NONCE_LEN + 1], sp_str[0x100], sa_str[0x100];
bytes2str(key, sk_str, AES_KEY_SIZE);
bytes2str(iv, si_str, GCM_NONCE_LEN);
bytes2str(p, sp_str, np);
bytes2str(a, sa_str, na);

   
 encryption_inputs_1(sk_str, si_str, sp_str, sa_str);

// Perform encryption
AES_GCM_encrypt(key, iv, p, np, a, na, tmp, tmp + np);

// Call SV function to print encryption outputs
char tmp_str[0x100], tmp_tag_str[0x100];
bytes2str(tmp, tmp_str, np);
bytes2str(tmp + np, tmp_tag_str, nt);
encryption_outputs_1(tmp_str, tmp_tag_str);

if (memcmp(c, tmp, np + nt)) {
    sprintf(msg, "%s", "encrypt failure");
    t = 1;
}

// Call SV function to print decryption inputs
bytes2str(c, tmp_str, np);
bytes2str(c + np, tmp_tag_str, nt);
decryption_inputs_1(sk_str, si_str, tmp_str, tmp_tag_str, sa_str);

// Perform decryption
memset(tmp, 0xcc , sizeof tmp);
t |= AES_GCM_decrypt(key, iv, c, np, a, na, nt, tmp) ? 2 : 0;

if (t == 0) {
    // Call SV function to print decryption output
    bytes2str(tmp, tmp_str, np);
    decryption_outputs_1(tmp_str);
} else {
    sprintf(msg, "%sdecrypt failure", t & 1 ? "encrypt & " : "");
}

bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(iv, si, GCM_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
bytes2str(c, sc, np + nt);
sprintf(r, "%s\nK: %s\ni: %s\nP: %s\nA: %s\nC: %s", msg, sk, si, sp, sa, sc);

// Call SV function to print the final result
final_result_1(r);

return t;

}

int run_test(){
const char *linehdr = { "Key = ", "IV = ", "AAD = ", "PT = ", "CT = ", "Tag = " };
char buffer[0x800], *value = “”, *line = “”;
size_t pass = 0, df = 0, ef = 0, sk = 0, sn = 0, sp = 0, sa = 0, st = 0;
uint8_t key[AES_KEY_SIZE], tmp[AES_KEY_SIZE], iv[GCM_NONCE_LEN];
uint8_t i, p[96], c[112], a[96], t[16], rc = 1;
FILE *fp, *fs, *ferr;

fp = fopen(TESTFILEPATH, "r");
fs = fopen("passed.log", "w");
ferr = fopen("failed.log", "w");

if (fp == NULL) {
    printf("File not found: %s\n", TESTFILEPATH);
    return 1;
}
if (!fs || !ferr) return 1;

do {
    if ((line = fgets(buffer, sizeof buffer, fp)) != NULL) {
        buffer[strcspn(buffer, "\n")] = 0;
        if (strlen(buffer) < 4) continue;
    }
    for (i = 0; i < 6; i++) {
        if (strncmp(buffer, linehdr[i], strlen(linehdr[i])) == 0) {
            value = strrchr(buffer, ' ') + 1;
            break;
        }
    }
    switch (i) {
    case 0:
        sk = strlen(value) / 2;
        if (sk == AES_KEY_SIZE) str2bytes(value, tmp);
        break;
    case 1:
        sn = strlen(value) / 2;
        if (sn == GCM_NONCE_LEN) str2bytes(value, iv);
        break;
    case 2:
        sa = strlen(value) / 2;
        str2bytes(value, a);
        break;
    case 3:
        sp = strlen(value) / 2;
        str2bytes(value, p);
        break;
    case 4:
        str2bytes(value, c);
        break;
    case 5:
        st = strlen(value) / 2;
        str2bytes(value, t);
        break;
    }
    if (i == 0 || line == NULL) {
        if (!rc && sn == GCM_NONCE_LEN && sk == AES_KEY_SIZE) {
            memcpy(c + sp, t, st);   /* put tag at the end */
            
            rc = ciphertest(key, iv, p, a, c, sp, sa, st, buffer);

            fprintf(rc ? ferr : fs, "%s\n", buffer); /* save the log */
            if (rc == 0) ++pass;
            else {
                if (rc & 1) ++ef;
                if (rc & 2) ++df;
            }
	printf("\n");
        }
        memcpy(key, tmp, sizeof key);
        rc = 0;
    }
} while (line != NULL);
printf("test cases: %d\nsuccessful: %d\nfailed encrypt: %d, failed decrypt: %d\n",
      pass + (ef > df ? ef : df), pass, ef, df);

fclose(fp); fclose(fs); fclose(ferr);
if (ef + df == 0) {
    remove("passed.log"); remove("failed.log");
}
return 0;

}
getting a output with error… please response as soon as possible to the mail
id