port
通信的三大概念:
-
接口 (Interface):
- 从
sc_interface派生的抽象类,但不是从sc_object派生的。 - 包含一组纯虚函数,将在从该接口派生的一个或多个通道中定义。
- 它定义了通道应该提供的服务,但没有实现这些服务。
- 从
-
端口 (Port):
- 模块与外部通信的媒介,使其独立于实例化上下文。
- 将接口方法调用转发到端口绑定的通道。
- 定义端口所在模块所需的一组服务(由端口类型标识)。
- 提供一种将模块与实现服务(通道)连接的方式。
-
通道 (Channel):
sc_prim_channel是所有原始通道的基类。- 通道可能提供一些公共成员函数,可以使用接口方法调用范例进行调用。
- 一个原始通道必须实现一个或多个接口。
- 它具体实现了接口定义的服务。
简而言之:
- 端口需要服务,接口定义服务,通道实现服务。
- 端口可以连接(绑定)到通道,前提是通道实现了端口所需的接口。
- 端口基本上是指向通道的指针。
什么时候使用端口:
- 如果模块需要调用属于模块外部通道的成员函数,则应通过模块的端口进行接口方法调用。否则,被视为糟糕的编码风格。
- 但是,可以直接调用当前模块内实例化的通道的成员函数。这称为无端口通道访问。
- 如果模块需要调用子模块内通道实例的成员函数,则应通过子模块的导出进行调用。
补充:
- 端口和接口有助于代码的可重用性和可测试性。
- 理解这三个概念对于 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