Есть ли какое-либо требование заказа для привязки multi_passthrough_initiator_sockets? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть иерархия SystemC top-> middle-> leaf, и я пытаюсь привязать multi_passthrough_initiator_socket in leaf к сокету того же типа в родительском модуле middle .Сокет в middle затем привязывается к целевому сокету в top .

Связывание выполняется в middle::before_end_of_elaboration():

leaf->i_socket.bind(i_socket)

иtop::before_end_of_elaboration():

middle->i_socket.bind(t_socket)

Это создает исключение при выполнении кода в middle - я заметил, что код в top вызывается раньше (кажется,что before_end_of_elaboration () не вызывается в глубину).

Обходной путь должен выполнить привязки в middle уже в его конструкторе, что предполагает наличие некоторого рода требования к упорядочению.Кто-нибудь знает об этом / может предложить чистое решение?

1 Ответ

0 голосов
/ 02 декабря 2018

Я предлагаю вам опубликовать это на форумах поддержки 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
}
...