You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动