SystemC - Port

329 阅读3分钟

port

通信的三大概念:

  1. 接口 (Interface):

    • sc_interface 派生的抽象类,但不是从 sc_object 派生的。
    • 包含一组纯虚函数,将在从该接口派生的一个或多个通道中定义。
    • 它定义了通道应该提供的服务,但没有实现这些服务。
  2. 端口 (Port):

    • 模块与外部通信的媒介,使其独立于实例化上下文。
    • 将接口方法调用转发到端口绑定的通道。
    • 定义端口所在模块所需的一组服务(由端口类型标识)。
    • 提供一种将模块与实现服务(通道)连接的方式。
  3. 通道 (Channel):

    • sc_prim_channel 是所有原始通道的基类。
    • 通道可能提供一些公共成员函数,可以使用接口方法调用范例进行调用。
    • 一个原始通道必须实现一个或多个接口。
    • 它具体实现了接口定义的服务。

简而言之:

  • 端口需要服务,接口定义服务,通道实现服务。
  • 端口可以连接(绑定)到通道,前提是通道实现了端口所需的接口。
  • 端口基本上是指向通道的指针。

什么时候使用端口:

  1. 如果模块需要调用属于模块外部通道的成员函数,则应通过模块的端口进行接口方法调用。否则,被视为糟糕的编码风格。
  2. 但是,可以直接调用当前模块内实例化的通道的成员函数。这称为无端口通道访问。
  3. 如果模块需要调用子模块内通道实例的成员函数,则应通过子模块的导出进行调用。

补充:

  • 端口和接口有助于代码的可重用性和可测试性。
  • 理解这三个概念对于 SystemC 中的模块交互和通信至关重要。

示例

// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;

SC_MODULE(MODULE1) { // defines one module
  sc_signal<int> s; // a signal (channel) inside the module
  sc_port<sc_signal_out_if<int> > p; // a port used to write to an outside channel
  SC_CTOR(MODULE1) {
    SC_THREAD(selfWrite); // a process to write to own channel
    SC_THREAD(selfRead); // a process to read from own channel
    sensitive << s; // triggered by value change on the channel
    dont_initialize();
    SC_THREAD(outsideWrite); // a process to write to an outside channel
  }
  void selfWrite() {
    int val = 1; // init value
    while (true) {
      s.write(val++); // write to own channel
      wait(1, SC_SEC); // repeat after 1 s
    }
  }
  void selfRead() {
    while (true) {
      std::cout << sc_time_stamp() << ": reads from own channel, val=" << s.read() << std::endl; // read from own channel
      wait(); // receives from signal
    }
  }
  void outsideWrite() {
    int val = 100; // init value
    while (true) {
      p->write(val++); // write to an outside channel, calls the write method of the outside channel. p is a pointer.
      wait(1, SC_SEC);
    }
  }
};
SC_MODULE(MODULE2) { // a module that reads from an outside channel
  sc_port<sc_signal_in_if<int> > p; // a port used to read from an outside channel
  SC_CTOR(MODULE2) {
    SC_THREAD(outsideRead); // a process to read from an outside channel
    sensitive << p; // triggered by value change on the channel
    dont_initialize();
  }
  void outsideRead() {
    while (true) {
      std::cout << sc_time_stamp() << ": reads from outside channel, val=" << p->read() << std::endl; // use port to read from the channel, like a pointer.
      wait(); // receives from port
    }
  }
};

int sc_main(int, char*[]) {
  MODULE1 module1("module1"); // instantiate module1
  MODULE2 module2("module2"); // instantiate module2
  sc_signal<int> s; // declares a signal (channel) outside module1 and moudle2
  module1.p(s); // binds (connects) port p of module1 to channel (signal) s
  module2.p(s); // binds port p of module2 to channel s
  sc_start(2, SC_SEC);
  return 0;
}

上面的例子中, 使用sc_signal<int>作为channel, sc_signal实现了write()read()

输出:

0 s: reads from own channel, val=1
0 s: reads from outside channel, val=100
1 s: reads from own channel, val=2
1 s: reads from outside channel, val=101

Reference

www.learnsystemc.com/basic/port