致SystemC初学者:第一个程序

本文提供了一个SystemC初学者的安装教程,并展示了一个简单的SystemC程序示例,该程序创建了一个带有reset信号的模块,展示了SC_METHOD和SC_THREAD的使用,以及敏感事件和初始化过程的管理。程序中还包括了SystemC的主要运行阶段和调度机制的说明。
摘要由CSDN通过智能技术生成

SystemC安装教程,可参考 虚拟机安装systemc 

// execute:    
//     g++ -g -Wall -lsystemc -m64 -pthread main.cpp  
//         -L/$(your systemc path)/lib-linux64 
//         -I/$(your systemc path)/include  -I/$(your systemc path)/src/tlm_utils -o sim

#include <systemc>

class MySCModule : public sc_core::sc_module {
 public:
  SC_HAS_PROCESS(MySCModule); // must have this line
  explicit MySCModule(sc_core::sc_module_name name)
  :sc_core::sc_module(name) {
    std::cout<<"top module construct "<<std::endl;

    SC_METHOD(TestMethod_have_Initialization);
    sensitive<<m_update_evt;
    SC_METHOD(TestMethod_no_Initialization);
    sensitive<<m_update_evt;
    dont_initialize();//this SC_METHOD func don't called at Initialization phase

    SC_THREAD(WriteThread);
    SC_THREAD(ReadThread);
  }
  ~MySCModule() override {
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"]"<<" top module destruct "<<std::endl;
  };
  void before_end_of_elaboration() override{
    std::cout<<"before_end_of_elaboration. "<<std::endl;
  }
  void end_of_elaboration() override{
    std::cout<<"end_of_elaboration. "<<std::endl;
  }
  void start_of_simulation() override{
    std::cout<<"start_of_simulation. "<<std::endl;
  }
  void end_of_simulation() override{
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"] end_of_simulation. "<<std::endl;
  }

  void TestMethod_have_Initialization(){
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"]"<< 
      " TestMethod_have_Initialization " <<std::endl;
  }

  void TestMethod_no_Initialization(){
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"]"<< 
      " TestMethod_no_Initialization " <<std::endl;
  }

  void WriteThread(){
    m_reset.write(false);
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"] m_reset write 0 " <<std::endl;
    sc_core::wait(2,sc_core::SC_NS);
    m_reset.write(true);
    std::cout<<" ["<<sc_core::sc_time_stamp()<<"] m_reset write 1 " <<std::endl;
  }

  void ReadThread(){
    while(1){
      bool t_sig = m_reset.read();
      if (t_sig == true){
        std::cout<<" ["<<sc_core::sc_time_stamp() <<
          "] m_reset read is 1, notify event " <<std::endl;
        m_update_evt.notify(sc_core::SC_ZERO_TIME); 
        return; 
      }
      sc_core::wait(1,sc_core::SC_NS);
    }
  }

  sc_core::sc_signal<bool>  m_reset ; 
  sc_core::sc_event         m_update_evt;
};

int sc_main(int argc, char ** argv)
{
  MySCModule m_top_module ("my_top_module");
  std::cout<<"top module construct finish "<<std::endl;
  sc_core::sc_start(10,sc_core::SC_NS);
  // sc_core::sc_start();
  std::cout<<"start finish, beign call sc_stop"<<std::endl;
  sc_core::sc_stop();// only have sc_stop, end_of_simulation can be called.
  std::cout<<"stop finish "<<std::endl;
  return 0;
}

此程序可作为SystemC初学者的第一个测试程序,其实现的功能比较简单:一个reset 信号,初始值为false,2ns的时候赋值为true,触发两个method函数打印。

此程序中包含了SystemC程序代码的常见组件,以下分别进行介绍。

类似与C/C++ 的main函数,sc_main为SystemC/TLM程序的入口函数。

Class MySCModule继承于sc_module (模块),我们的SystemC程序一般都只有一个top module,然后在sc_main中进行例化,其他的子模块都在这个top module的构造函数中进行例化,这就是SystemC spec (以下简称spec)中提到的module hierarchy。一般情况下,我们会给每个module都起一个名字,也就是调用sc_module的含参构造函数,sc_core::sc_module(name);如果某一个类被例化多份,可以使用SystemC自带的函数sc_gen_unique_name("my_module_name")来产生不同的name (name后面加_instance_num),代码中可以使用this->name() 可以得到当前模块的name,如果模块是一个子模块,那么得到的name将是一个包含所有层次关系的name,比如 top_name.sub_module_name.xxx

SC_HAS_PROCESS(MySCModule);是声明本module中有SC_THREAD / SC_METHOD关联函数,必须要在类中进行声明,否则会导致关联函数在Simulation阶段不能被SystemC kernel调用。

SC_THREAD / SC_METHOD是进程宏,进程宏的目的是将关联的函数注册到SystemC kernel,以便调度程序可以在模拟期间回调该成员函数。Spec中有如下解释:

The purpose of the process macros is to register the associated function with the kernel such that the scheduler can call back that member function during simulation. It is also possible to use spawned processes for this same purpose. The process macros are provided for backward compatibility with earlier versions of SystemC and to provide clocked threads for hardware synthesis.

Sensitive用于添加敏感事件列表,dont_initialize用于disable initialization phase调用。Sensitive 和dont_initialize都只对离它最近的上一条SC_THREAD / SC_METHOD关联函数有效。比如实例中 TestMethod_have_Initialization和TestMethod_no_Initialization都有敏感事件 m_update_evt,但必须分别写在两句SC_METHOD的后面。实例中的dont_initialize只对TestMethod_no_Initialization有效。如果我们希望多个事件都能触发关联函数,则可以使用sensitive<< event1 <<event 2 << xxx 来添加多个敏感事件。

sc_start和sc_stop从字面意思我们就知道前者是启动SystemC运行,后者是停止。其中,sc_start是一个SystemC代码中必须有的;但sc_stop可以没有。因为SystemC Kernel在调度过程中,如果发现没有processes需要被update,则自动停止Simulation阶段;sc_start函数如果不加任何参数,则必须依赖这种停止方式。本实例中,sc_start函数中有一个10ns的时间参数,表明我只希望此程序的SystemC 仿真时间推进到10ns,即使还有任务未完成(需要在下一个SystemC仿真时间,比如11ns才会执行),到10ns时程序依然立即停止Simulation阶段。

以下是示例程序的执行打印结果,可以看到最终的stop 打印时间(SystemC仿真时间)为10ns。

top module construct 
top module construct finish 
before_end_of_elaboration. 
end_of_elaboration. 
start_of_simulation. 
 [0 s] TestMethod_have_Initialization 
 [0 s] m_reset write 0 
 [2 ns] m_reset write 1 
 [3 ns] m_reset read is 1, notify event 
 [3 ns] TestMethod_no_Initialization 
 [3 ns] TestMethod_have_Initialization 
start finish, beign call sc_stop

Info: /OSCI/SystemC: Simulation stopped by user.
 [10 ns] end_of_simulation. 
stop finish 
 [10 ns] top module destruct 

如果将sc_core::sc_start(10,sc_core::SC_NS);改为sc_core::sc_start();则会发现最终的stop 打印时间(SystemC仿真时间)为3ns。这是因为3ns之后所有的SC_THREAD / SC_METHOD关联函数都没有更新了,SystemC 自动停止Simulation阶段。

top module construct 
top module construct finish 
before_end_of_elaboration. 
end_of_elaboration. 
start_of_simulation. 
 [0 s] TestMethod_have_Initialization 
 [0 s] m_reset write 0 
 [2 ns] m_reset write 1 
 [3 ns] m_reset read is 1, notify event 
 [3 ns] TestMethod_no_Initialization 
 [3 ns] TestMethod_have_Initialization 
start finish, beign call sc_stop

Info: /OSCI/SystemC: Simulation stopped by user.
 [3 ns] end_of_simulation. 
stop finish 
 [3 ns] top module destruct 

代码中涉及的其他问题,可参考以下相关内容。

 SystemC的运行阶段

SystemC Simulation调度机制

SystemC time

SystemC:SC_THREAD和SC_METHOD

SystemC中的Wait 函数

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要从初学到精通SystemC,需要有以下几个步骤: 1. 学习基础知识:要了解SystemC的基本概念和语法规则,可以通过阅读相关的书籍、网上教程或者参加培训课程入门,掌握SystemC的数据类型、进程模型、事件驱动机制等基础知识。 2. 练习实践:在学习的同时,通过实践来巩固所学知识。可以选择一些简单的SystemC项目进行实践,例如设计一个简单的加法器或者乘法器。通过实际操作,能够更好地理解SystemC的使用方法和特性。 3. 参与项目开发:找一个开源的SystemC项目参与其中,这样可以学习到更多的实践经验和与其他开发者的交流。通过与更有经验的人一起工作,可以学习到更高级的技巧和最佳实践,逐步提高自己的技术水平。 4. 深入研究和学习:在掌握基础知识后,可以深入研究SystemC的高级特性和扩展功能,如TLM(事务级建模)和自定义通信接口等。阅读SystemC的相关文档和论文,参与相关的学术研究或工业项目,持续提升自己的技术能力。 5. 实践应用:在掌握了SystemC的基础和高级特性后,可以将所学应用于实际项目开发中。可以选择一个自己感兴趣或者有挑战的项目,例如设计一个处理器核或者嵌入式系统。通过实践应用,不断优化和提升自己的SystemC技能。 综上所述,要从初学到精通SystemC,需要系统地学习和实践,并不断拓展自己的知识和技能。通过学以致用,与其他开发者的交流和合作,不断提高自己的专业水平,可以成为一名精通SystemC的工程师。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

123axj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值