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

推荐订阅源

月光博客
月光博客
V
Visual Studio Blog
C
Check Point Blog
Google DeepMind News
Google DeepMind News
S
SegmentFault 最新的问题
博客园 - 聂微东
量子位
T
Tailwind CSS Blog
罗磊的独立博客
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
L
LangChain Blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
M
MIT News - Artificial intelligence
Know Your Adversary
Know Your Adversary
MongoDB | Blog
MongoDB | Blog
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
爱范儿
爱范儿
T
The Exploit Database - CXSecurity.com
有赞技术团队
有赞技术团队
V
Vulnerabilities – Threatpost
Martin Fowler
Martin Fowler
A
Arctic Wolf
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 司徒正美
Cyberwarzone
Cyberwarzone
阮一峰的网络日志
阮一峰的网络日志
The Hacker News
The Hacker News
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
GbyAI
GbyAI
Latest news
Latest news
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
腾讯CDC
AWS News Blog
AWS News Blog
aimingoo的专栏
aimingoo的专栏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
Lohrmann on Cybersecurity
博客园 - Franky
S
Securelist
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Threatpost
美团技术团队

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

【琐记】烟火与尘埃 【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,并指明哪一篇博客,我看到一定及时回复!