SystemC中是否存在支持阻塞读写的零容量类sc_fifo通信通道?
嗨,Michael!
针对你的需求——在SystemC中实现类似valid/ready握手、零容量sc_fifo效果的模块间通道,我来给你梳理一下可行的方案:
一、标准库中是否有现成通道?
SystemC标准库并没有直接提供这种“零容量阻塞式握手通道”,因为sc_fifo的最小容量是1(内部缓存至少需要一个存储单元),无法直接实现写操作必须等待读操作完成才能返回的逻辑。不过我们有几种易用且低出错率的替代方案,完全满足你建模的需求。
二、推荐的替代方案
1. 自定义极简握手通道(最推荐)
这种方式逻辑清晰,完全贴合你的需求,代码量小且容易维护。核心思路是用sc_event实现读写操作的双向阻塞:
#include <systemc.h> template<typename T> class HandshakeChannel : public sc_module { public: sc_event data_written; // 通知消费者有数据待读取 sc_event data_read; // 通知生产者数据已被读取 T data; // 传输的数据存储 SC_CTOR(HandshakeChannel) {} // 写操作:阻塞直到数据被读取 void write(const T& val) { data = val; data_written.notify(); // 触发数据就绪事件 wait(data_read); // 等待消费者读取完成 } // 读操作:阻塞直到有数据写入 T read() { wait(data_written); // 等待生产者写入数据 T val = data; data_read.notify(); // 触发数据已读事件 return val; } };
使用示例:
// 生产者模块 class Producer : public sc_module { public: HandshakeChannel<int>* chan; SC_CTOR(Producer) { SC_THREAD(main_thread); } void main_thread() { int count = 0; while(true) { cout << "Producer writing: " << count << endl; chan->write(count++); wait(10, SC_NS); // 模拟生产间隔 } } }; // 消费者模块 class Consumer : public sc_module { public: HandshakeChannel<int>* chan; SC_CTOR(Consumer) { SC_THREAD(main_thread); } void main_thread() { while(true) { int val = chan->read(); cout << "Consumer read: " << val << endl; wait(15, SC_NS); // 模拟处理间隔 } } }; // 顶层模块 int sc_main(int argc, char* argv[]) { HandshakeChannel<int> chan("handshake_chan"); Producer prod("producer"); Consumer cons("consumer"); prod.chan = &chan; cons.chan = &chan; sc_start(100, SC_NS); return 0; }
这个通道完全实现了你要的效果:写操作必须等读操作完成才能继续,读操作必须等写操作完成才能获取数据,完美对应valid/ready的握手逻辑。
2. 利用sc_event直接在模块间通信(轻量化方案)
如果不想自定义通道,也可以直接在生产者和消费者模块中定义成对的sc_event和共享数据变量,实现相同的握手逻辑:
- 生产者模块定义
sc_event data_ready,消费者模块定义sc_event data_consumed - 生产者写入数据后触发
data_ready,然后等待data_consumed - 消费者等待
data_ready后读取数据,触发data_consumed
这种方式省去了通道类的定义,适合简单的一对一模块通信,但扩展性不如自定义通道(比如多个生产者/消费者场景需要额外处理)。
3. TLM事务级建模(适合复杂系统)
如果你的建模场景是事务级而非RTL级,可以使用SystemC TLM中的simple_socket配合阻塞式传输。通过设置TLM_BLOCKING_TRANSPORT,可以实现类似的请求-响应式阻塞传输,不过这种方式更适合抽象度较高的系统建模,对于简单的握手场景来说有点“重”。
总结
对于你的需求,自定义极简握手通道是最优选择:逻辑清晰、代码简洁、易于维护,完全满足建模需求且不需要考虑可综合限制。
内容的提问来源于stack exchange,提问作者Michael Fivez




