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

推荐订阅源

WordPress大学
WordPress大学
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
Webroot Blog
Webroot Blog
GbyAI
GbyAI
S
SegmentFault 最新的问题
Cyberwarzone
Cyberwarzone
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 【当耐特】
S
Secure Thoughts
酷 壳 – CoolShell
酷 壳 – CoolShell
AWS News Blog
AWS News Blog
Engineering at Meta
Engineering at Meta
S
Security Affairs
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
D
DataBreaches.Net
云风的 BLOG
云风的 BLOG
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
Spread Privacy
Spread Privacy
T
Threatpost
Forbes - Security
Forbes - Security
C
Cisco Blogs
Scott Helme
Scott Helme
Attack and Defense Labs
Attack and Defense Labs
Simon Willison's Weblog
Simon Willison's Weblog
腾讯CDC
The Last Watchdog
The Last Watchdog
Cloudbric
Cloudbric
Last Week in AI
Last Week in AI
Recorded Future
Recorded Future
小众软件
小众软件
V
Vulnerabilities – Threatpost
美团技术团队
人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
Apple Machine Learning Research
Apple Machine Learning Research
Hacker News - Newest:
Hacker News - Newest: "LLM"
I
Intezer
月光博客
月光博客
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园 - 司徒正美
C
Cybersecurity and Infrastructure Security Agency CISA
Martin Fowler
Martin Fowler
博客园 - 聂微东

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

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