Как я собираю информацию трассировки в случае вызовов SystemVerilog+C DPI?
У меня есть ситуация, когда у меня есть 2 функции C. Эти функции C имеют много сценариев проверки ошибок, где я использую выход (1), чтобы справиться с ситуацией. Миллион мест в системном коде verilog вызывает эти 2 C-функции через вызовы DPI.
Я использовал функции execinfo.h и backtrace() в своих подпрограммах C, но информация трассировки стека отображает функцию C, но выше она просто показывает некоторый случайный vcs_exe.sim.1234_1.so в качестве основной функции вызова.
Я даже пытался найти этот vcs_exe.sim.1234.so в опубликованной области, но он не указывает ни на какой известный файл Sv.
Итак, как я могу получить функцию вызывающего не-C/SV, когда отображается трассировка стека?
3 ответа
В идеале у вашего симулятора должно быть руководство, показывающее, как это сделать. Это может потребовать изменения материала в вашем скрипте сборки, чтобы обеспечить дополнительную видимость. Отдел поддержки поставщика должен быть в состоянии помочь вам, если вы не можете найти что-либо об этом в руководстве.
Если ваш инструмент не позволяет этого, вы можете попробовать реализовать что-то самостоятельно. Если ваш метод DPI является контекстным, вы можете использовать концепцию svScope, чтобы выяснить информацию о вызывающем абоненте. Я не проверял это, но это должно быть что-то вроде:
svScope scope;
scope = svGetScope();
char *fileName, *lineNumber;
scope.svGetCallerInfo(fileName, lineNumber);
Это предполагает, что svGetCallerInfo(...)
вернул true, что, я думаю, должно быть для методов контекста DPI.
Как насчет изменения кода C, чтобы он не выходил из (1), вместо этого он просто распечатывает сообщение об ошибке и корректно возвращается в SV-домен?
Для отладки проблемы вам нужно установить точку останова на строке, которая выводит сообщение об ошибке, а затем вернуться в SV-домен в симуляторе. Вуаля! Теперь вы не только знаете, какой объект класса SV вызывает C-DPI, вы можете видеть локальные переменные объекта класса SV, чтобы помочь диагностировать проблему.
Я работал с vcs так, чтобы он вызывал экспортированную функцию, которая в свою очередь вызывала бы стек $. Это работает для меня с привязкой 'default' и 'pure' в этом примере.
import "DPI-C" context function void testStack();
export "DPI-C" function printStack;
function void printStack;
$display("====%m=====");
$stack;
endfunction
module dpis;
sub sub();
endmodule // dpis
module sub;
initial
testStack();
endmodule // sub
class Test;
function void test;
testStack();
endfunction // test
endclass // Abc
program abc;
Test a = new;
initial
a.test();
endprogram // abc
и 'c':
#include <svdpi.h>
extern void pringStack();
void testStack() {
svScope scope;
scope = svGetScopeFromName("$unit");
svSetScope(scope);
printStack();
}
и результат выглядит так:
====$unit::printStack=====
#0 in printStack at dpis.sv:9
#1 in DPI function
#2 in dpis.sub
====$unit::printStack=====
#0 in printStack at dpis.sv:9
#1 in DPI function
#2 in <protected code>
#3 in abc at dpis.sv:30
#4 in abc
Таким образом, он дает некоторую информацию о местоположении либо в виде пути к экземпляру модуля, либо в виде файла / белья.