Можно ли привязать вывод подмодуля к двум разным выходным портам? - PullRequest
0 голосов
/ 20 октября 2019

Я пытаюсь создать схему, которая вычисляет переносы для сложения.

В этом фрагменте кода я хотел бы подключить порт вывода rOut подмодуля pg к двум выходампорты (rOut и carries[0]) родительского модуля, поэтому оба получают одно и то же значение.

template<>
struct Carries<1> : ::sc_core::sc_module {
    sc_vector<sc_in<bool>> a, b;
    sc_in<bool> rIn;
    sc_out<bool> p, g, rOut;
    sc_vector<sc_out<bool>> carries;

    CarryPropGen pg {"PG"};

    SC_CTOR(Carries)
        :   a {"vectA", 1}, b {"vectB", 1},
            rIn {"rIn"},
            p {"p"}, g {"g"}, rOut {"rOut"},
            carries {"vectCarries", 1} {
        pg.a(a[0]);
        pg.b(b[0]);
        pg.r(rIn);

        pg.p(p);
        pg.g(g);
        pg.rOut(rOut);
        pg.rOut(carries[0]);
    }
};

Однако я получаю ошибку (E109) complete binding failed: 2 binds exceeds maximum of 1 allowed: port 'Carries.PG.port_5' (sc_out). Я также попробовал с сигналом, с и без политики писателя SC_MANY_WRITER, как это было предложено кем-то на форуме, но она тоже не сработала.

Я новичок в SystemC, и пока я понимаюошибка, я не очень понимаю, почему это не может работать и как сделать это по-другому. Итак, есть ли способ связать выходные данные одного подмодуля с несколькими sc_out родительского модуля и как?

1 Ответ

2 голосов
/ 20 октября 2019

Порты в SystemC - это не провода, а умные указатели. В отличие от обычных указателей C ++, порты SystemC безопасны и поддерживают иерархическое связывание. Аналогично обычным указателям, по умолчанию, нельзя подключить порт к 2 каналам одновременно.

Хотя это может быть неудобно для низкоуровневого моделирования, это позволяет использовать порты с любыми высокоуровневыми каналами, такими как FIFO или каналы TLM.

Похоже, вам нужно что-то вроде широковещательной передачи. порт: при записи в такой порт сообщение должно быть записано на все подключенные каналы.

Чтобы создать порт, который можно привязать к нескольким каналам, используйте второй параметр шаблона N из sc_port:

// ----------------------------------------------------------------------------
//  CLASS : sc_port
//
//  Generic port class and base class for other port classes.
//  N is the maximum number of channels (with interface IF) that can be bound
//  to this port. N <= 0 means no maximum.
// ----------------------------------------------------------------------------
template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND>
class sc_port

Позволяет проверить его:

#include <systemc.h>

SC_MODULE(test) {
  // Create broadcast_port that allows any number of binded channels
  sc_port<sc_signal_inout_if<int>, 0> SC_NAMED(broadcast_port);

  // create some signals
  sc_signal<int> SC_NAMED(a);
  sc_signal<int> SC_NAMED(b);
  sc_signal<int> SC_NAMED(c);

  SC_CTOR(test) {
    // bind port to signals
    broadcast_port(a);
    broadcast_port(b);
    broadcast_port(c);

    SC_THREAD(test_thread);
  }

  void test_thread() {
    // write 42 to all connected signals
    for (size_t ii = 0; ii < broadcast_port.size(); ++ii) {
      broadcast_port[ii]->write(42);
    }

    wait(SC_ZERO_TIME);
    // print results
    std::cout << a << "\n";
    std::cout << b << "\n";
    std::cout << c << "\n";
  }
};

int sc_main(int, char *[]) {
  test SC_NAMED(test_top);
  sc_start();
  return 0;
}

Это не совсем то, что мы хотели: здесь нам нужно перебирать все подключенные каналы каждый раз, когда нам нужно что-то записать в широковещательный порт.

Давайте создадим производный класс, который будет делать это автоматически:

template <typename T>
class sc_out_broadcast : public sc_port<sc_signal_inout_if<int>, 0>
{
public:
  explicit sc_out_broadcast(const char *name_) : sc_port(name_) {}

  // write the new value to all connected signals
  void write( const T& value_ )
  {
    for (size_t ii = 0; ii < this->size(); ++ii) {
      (*this)[ii]->write(value_);
    }
  }
};

Вот как мы используем его в test_thread:

  void test_thread() {

    broadcast_port.write(42);

    wait(SC_ZERO_TIME);

    std::cout << a << "\n";
    std::cout << b << "\n";
    std::cout << c << "\n";
  }
...