惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
M
MIT News - Artificial intelligence
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
L
LangChain Blog
D
Docker
G
Google Developers Blog
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
Vercel News
Vercel News
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
Recorded Future
Recorded Future
I
InfoQ
博客园 - 【当耐特】
The Cloudflare Blog
P
Proofpoint News Feed
GbyAI
GbyAI
博客园 - 司徒正美
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
爱范儿
爱范儿
Jina AI
Jina AI
量子位
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
有赞技术团队
有赞技术团队
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
大猫的无限游戏
大猫的无限游戏
F
Full Disclosure
雷峰网
雷峰网
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题

Пусть этот камень будет более крепким, чем человек

【琐记】烟火与尘埃 【Triton】Triton实现矩阵乘 【LLM推理加速】FlashAttention 【LLM推理加速】PagedAttention 【LLM推理加速】Online Softmax LLM基础知识【1】 Transformer模型 【AI编译】LayerGroup Tiling Tile的疑惑和思考 【AI编译】深度优先的Tile调度,万事大吉? 【AI编译】多级流水线Tile调度策略 【CUDA C++】GPU内存使用【3】 【AI编译】Cache缓存地址映射 【CUDA C++】GPU存储【2】 【CUDA C++】GPU基本介绍【1】 【00】0序章-不受欢迎的来客 【转载】我来了——持续低熵 【Halide】调度优化【2】 【感想】写作进度报告5 【Halide】调度优化【1】 【转载】北大中文男足战报2 【BYOC】TVM切分子图 【转载】北大中文男足战报1 【AI编译】张量生命周期管理 【脉动阵列】脉动阵列类型 【im2col】AScend conv accelerate 【感想】写作进度报告4 【BYOC】TVM添加自定义编译器 ccompiler 【感想】写作进度报告3 【Tengine】推理流程脑图【2】 【Tengine】推理流程脑图【1】 【NCNN】学习ncnn模型转换 【编译器】使用llvm编译自定义语言【3】编译 object 【编译器】使用llvm编译自定义语言【2】转llvm IR 【编译器】使用llvm编译自定义语言【1】构建AST 【AI编译】如何进行内存分配 【感想】写作进度报告2 【AI编译】layer-group之后如何tiling 【AI编译】如何进行layer-group 【量化】连续卷积层首尾量化的可行性 【Gemm】内存对齐 【gemm】Gemm计算加速 【TVM】通过代码学习编译流程【5】FuseOps 【TVM】通过代码学习编译流程【6】CodeGen 【TVM】通过代码学习类【3.5】Pass 【TVM】通过代码学习编译流程【4】BuildRelay 【AI编译】Tiling操作能优化什么时间 【TVM】通过代码学习编译流程【3】模型编译 【TVM】通过代码学习编译流程【2】模型转换 【TVM】通过代码学习编译流程【1】必要知识 【感想】写作进度报告1 【Winograd】卷积加速算法原理及实现 SystemC 等待异步事件解决方案 【TVM】Python脚本实现模型编译和保存 【推理引擎】常见AI推理框架 【3D建模】T110E3卡迪夫蓝调皮肤模型 【TVM】C++部署运行TVM 【推理引擎】NCNN和Tengine量化推理逻辑对比 【3D建模】IS-7攻城锤流纹岩皮肤展示 【TVM】根据例子走通代码库 博客汇总目录 【Im2Col】卷积加速算法【2】NHWC 【Im2Col】卷积加速算法【1】 NCHW openBlas库的安装与简单使用 C语言工程调用Cpp库解决方案 foo Hello World
SystemC 用寄存器同步建模方法
Post author: XianMu@Пусть этот камень будет более крепким, чем ч · 2025-08-23 · via Пусть этот камень будет более крепким, чем человек

本文为 SystemC 实现寄存器来同步的建模方法。

# 应用场景

仿真时可能有类似这样的需求:
将一系列的指令发送到三个模块 A、B、C,三个模块相互独立地执行这些指令。
为了进行同步控制,这些指令中含有 sync 类型的指令,并借助寄存器来实现模块之间的同步。
比如我创建 20 个寄存器,A 模块的 Sync 指令是往寄存器 0 号位写入 1,B 收到的 sync 指令是读寄存器 0 号位,读到 1 才能执行后续指令;然后 B 往寄存器 1 号位写入 10,C 在寄存器 1 号位读到 10,才能够执行后续指令。以此实现执行同步。

# 初步尝试

依据上述需求,我非常直接地创建了 sc_signal<int> reg[20] 来作为寄存器。

每个模块通过以下方式对 sync 指令进行读和写

mSyncRegisters->reg[reg_id].write(num); 
while (mSyncRegisters->reg[reg_id].read() != num) {
    wait(mSyncRegisters->reg[reg_id].value_changed_event());  
}

但是发现了如下错误:

Error: (E115) sc_signal<T> cannot have more than one driver

原来 sc_signal 这个变量不能被多个 module 驱动。此时,问题就变得棘手起来。

# 解决方案

报错寻找问题,以及询问 deepseek,花费大半天时间。

终究还是没能继续使用 sc_signal 。deepseek 帮我用 sc_event 手写了整个逻辑。

这里是解决方案:

#include <systemc.h>
#include <vector> 
class reg_file_if : public virtual sc_core::sc_interface {
public:
    virtual void write(int reg_index, int value) = 0;
    virtual int read(int reg_index) = 0;
    virtual void wait_until(int reg_index, int value) = 0;
};
class SyncRegFile : public sc_core::sc_module, public reg_file_if {
public:
    SC_HAS_PROCESS(SyncRegFile);
    SyncRegFile(sc_core::sc_module_name name, size_t num_regs) 
        : sc_core::sc_module(name), 
          reg_array(num_regs, 0),
          reg_events(num_regs){}
    virtual void write(int reg_index, int value) override {
        if (reg_index < 0 || static_cast<size_t>(reg_index) >= reg_array.size()) 
            return;
        
        mutex.lock();
        reg_array[reg_index] = value;
        mutex.unlock();
        reg_events[reg_index].notify(sc_core::SC_ZERO_TIME);
    }
    virtual int read(int reg_index) override {
        if (reg_index < 0 || static_cast<size_t>(reg_index) >= reg_array.size()) 
            return 0;
        
        mutex.lock();
        int value = reg_array[reg_index];
        mutex.unlock();
        return value;
    }
    virtual void wait_until(int reg_index, int value) override {
        if (reg_index < 0 || static_cast<size_t>(reg_index) >= reg_array.size()) 
            return;
        
        while (true) {
            mutex.lock();
            bool condition_met = (reg_array[reg_index] == value);
            mutex.unlock();
            
            if (condition_met) break;
            
            wait(reg_events[reg_index]);
        }
    }
private:
    std::vector<int> reg_array;
    std::vector<sc_core::sc_event> reg_events;
    sc_core::sc_mutex mutex;
};
class WorkerModule : public sc_core::sc_module {
public:
    SC_HAS_PROCESS(WorkerModule);
    sc_core::sc_port<reg_file_if> reg_file;
    
    const std::string module_name;
    
    WorkerModule(sc_core::sc_module_name name, const char* mod_name) 
        : sc_module(name), module_name(mod_name) 
    {
        SC_THREAD(main_process);
    }
    void main_process() {
        if (module_name == "A") {
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleA: Writing reg0=1" << std::endl;
            reg_file->write(0, 1);
            wait(10, sc_core::SC_NS);
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleA: Finished" << std::endl;
        } 
        else if (module_name == "B") {
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleB: Waiting for reg0==1" << std::endl;
            reg_file->wait_until(0, 1);
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleB: Writing reg1=10" << std::endl;
            reg_file->write(1, 10);
            wait(5, sc_core::SC_NS);
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleB: Finished" << std::endl;
        }
        else if (module_name == "C") {
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleC: Waiting for reg1==10" << std::endl;
            reg_file->wait_until(1, 10);
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleC: Starting execution" << std::endl;
            wait(15, sc_core::SC_NS);
            std::cout << "[" << sc_core::sc_time_stamp() << "] ModuleC: Finished" << std::endl;
        }
    }
};
class Top : public sc_core::sc_module {
public:
    SyncRegFile reg_file;
    WorkerModule mod_a, mod_b, mod_c;
    Top(sc_core::sc_module_name name) 
        : sc_module(name),
          reg_file("RegFile", 20),  
          mod_a("ModuleA", "A"),
          mod_b("ModuleB", "B"),
          mod_c("ModuleC", "C") 
    {
        mod_a.reg_file(reg_file);
        mod_b.reg_file(reg_file);
        mod_c.reg_file(reg_file);
    }
};
int sc_main(int argc, char* argv[]) {
    Top top("Top");
    
    std::cout << "Starting simulation..." << std::endl;
    sc_core::sc_start(100, sc_core::SC_NS); 
    
    std::cout << "Simulation finished at " << sc_core::sc_time_stamp() << std::endl;
    return 0;
}

预期输出:

Starting simulation...
[0 s] ModuleA: Writing reg0=1
[0 s] ModuleB: Waiting for reg0==1
[0 s] ModuleC: Waiting for reg1==10
[0 s] ModuleB: Writing reg1=10
[0 s] ModuleC: Starting execution
[10 ns] ModuleA: Finished
[5 ns] ModuleB: Finished
[15 ns] ModuleC: Finished
Simulation finished at 15 ns

# 后记

本博客目前以及可预期的将来都不会支持评论功能。各位大侠如若有指教和问题,可以在我的 github 项目 或随便一个项目下提出 issue,并指明哪一篇博客,我看到一定及时回复!