Существуют ли какие-либо требования к заказу для привязки 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
}
Другие вопросы по тегам