Существуют ли какие-либо требования к заказу для привязки multi_passthrough_initiator_sockets?
У меня есть иерархия SystemC top->middle->leaf и пытаюсь связать multi_passthrough_initiator_socket
в листе к сокету того же типа в середине его родительского модуля. Сокет в середине затем связывается с целевым сокетом сверху.
Привязки сделаны в middle::before_end_of_elaboration()
:
leaf->i_socket.bind(i_socket)
а также top::before_end_of_elaboration()
:
middle->i_socket.bind(t_socket)
Это создает исключение при выполнении кода в середине - я заметил, что код вверху вызывается раньше (кажется, что before_end_of_elaboration() не вызывается в глубину).
Обходной путь должен сделать связывание посередине уже в его конструкторе, который предполагает, что есть какое-то требование к упорядочению. Кто-нибудь знает об этом / может предложить чистое решение?
1 ответ
Я предлагаю вам опубликовать это на форумах поддержки Accellera. http://forums.accellera.org/forum/14-systemc-tlm-transaction-level-modeling/
Это либо ошибка реализации, либо недокументированное ограничение библиотеки TLM.
Я экспериментировал с этим делом сам, и вот что я нашел:
- Там нет требований к оформлению заказа
- Но вы не можете использовать before_end_of_elaboration() для привязки сокетов tlm
Вот мой тестовый пример:
struct test : sc_module {
tlm_utils::multi_passthrough_initiator_socket<test> leaf{"leaf"};
tlm_utils::multi_passthrough_initiator_socket<test> middle{"middle"};
tlm_utils::simple_target_socket<test> target{"target"};
test(sc_module_name);
protected:
void before_end_of_elaboration();
};
Вариант 1 - Работает
test::test(sc_module_name)
{
leaf.bind(target);
middle.bind(leaf);
}
void test::before_end_of_elaboration() {}
Вариант 2 - Работает
test::test(sc_module_name)
{
middle.bind(leaf);
leaf.bind(target);
}
void test::before_end_of_elaboration() {}
Вариант 3. Сбой с ошибкой: (E126) экземпляр sc_export уже связан
test::test(sc_module_name)
{}
void test::before_end_of_elaboration() {
middle.bind(leaf);
leaf.bind(target);
}
Теперь причина такого поведения в том, что библиотека TLM использует before_end_of_elaboration
обратные вызовы для реализации поддержки иерархических привязок (проверьте исходный код multi_passthrough_initiator_socket
сам). Таким образом, код пользователя должен завершить все привязки сокетов до этого. И так как нет обратных вызовов до before_end_of_elaboration
, вы можете связывать сокеты TLM только внутри конструкторов.
Обратите внимание, что это не относится к сигнальным портам, которые можно привязать с помощью before_end_of_elaboration
, в любом порядке:
struct test : sc_module {
sc_in<int> leaf0{"leaf0"};
sc_in<int> leaf1{"leaf1"};
sc_in<int> middle0{"middle0"};
sc_in<int> middle1{"middle1"};
sc_signal<int> sig{"sig"};
test(sc_module_name);
protected:
void before_end_of_elaboration();
};
test::test(sc_module_name)
{
}
void test::before_end_of_elaboration()
{
leaf0(middle0); // OK
middle0(sig); // OK
middle1(sig); // OK
leaf1(middle1); // OK
}