Как вы определяете бэкдор доступ для полей, которые охватывают два регистра?
У меня есть карта регистров, которая имеет 16-битные регистры. У меня есть поле с шириной более 16 бит, поэтому оно должно охватывать два адреса. Как мне определить бэкдор доступ к этому полю?
Это то, что я пытался для моей области test_pattern[23:0]
:
register_a.add_hdl_path_slice("path.to.regmap.test_pattern[15:0]", 0, 16);
register_b.add_hdl_path_slice("path.to.regmap.test_pattern[23:16]", 0, 8);
Это терпит неудачу с этой ошибкой:
ОШИБКА: VPI TYPERR vpi_handle_by_name() не может получить дескриптор выбора детали.
Не ясно, является ли это ограничением моего инструмента или того, как код UVM использует VPI. После осмотра внутри кода UVM я вижу код, который должен обрабатывать выборки части, но он внутри #ifdef QUESTA
директивы, так что я думаю, что это ограничение инструмента.
Есть ли хорошая работа для этого?
3 ответа
Очень жаль, что тот, кто внес этот код (предположительно, Mentor?), Счел необходимым добавить полезную функцию в библиотеку Universal, обернутую в ifdefs
, На самом деле это еще хуже на UVM_1_2
ветвь, где весь файл интерфейса DPI/PLI разделен на специфические реализации симулятора!
Смотря на distrib/src/dpi/uvm_hdl.c
в основной ветке git://git.code.sf.net/p/uvm/code похоже, что единственным конкретным кодом для QUESTA является эта функция:
static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
Который использует следующие значения, определенные DPI:
svLogic logic_bit;
svGetBitselLogic(&bit_value,0);
svLogicVecVal bit_value;
svGetPartselLogic(&bit_value,value,i,1);
svPutPartselLogic(value,bit_value,i,1);
Теоретически, если ваш симулятор и код Mentor соответствуют стандарту, вы можете удалить ifdefs
и это все еще должно работать.
Вы также можете сделать это, обнаружив деталь, выбранную в пути и использовать vpi_handle_by_index
читать отдельные биты, которые также должны поддерживаться в любом симуляторе.
Обратите внимание, что мой первоначальный ответ был неверным по поводу того, что код был специфичен для Mentor - спасибо @dave_59 за то, что он прямо сказал мне, и извиняюсь перед Mentor.
Согласно справке класса UVM:
функция void add_hdl_path_slice(имя строки, смещение int, размер int, бит первый = 0, string kind = "RTL")
Я предполагаю, что решение должно использовать offset
выбрать начальный индекс.
register_a.add_hdl_path_slice("path.to.regmap.test_pattern", 0, 16);
register_b.add_hdl_path_slice("path.to.regmap.test_pattern", 16, 8);
Возможная альтернатива, бит выбора в цикле for:
for (int i=0; i<16; i++) begin
string tmp_path_s;
tmp_path_s = $sformatf("path.to.regmap.test_pattern[%0d]", i);
register_a.add_hdl_path_slice(tmp_path_s, i, 1);
end
for (int i=0; i<8; i++) begin
string tmp_path_s;
tmp_path_s = $sformatf("path.to.regmap.test_pattern[%0d]", i+16);
register_a.add_hdl_path_slice(tmp_path_s, i, 1);
end
Есть ли какая-то причина, по которой вы не делите это на 2 регистра? Поскольку размер вашего регистра равен 16 битам, нет смысла объявлять регистр, который больше этого.
То, как я видел большие поля, как это определено, состоит в том, чтобы объявить 2 регистра с отдельным полем в каждом. Например, если вам нужен 32-битный указатель, вы получите:
addr_high с 16-битным полем addr_low с 16-битным полем
Для удобства вы можете добавить задачу, которая будет обращаться к обоим по порядку.