systemC/TLM:peq_with_cb_and_phase的简单用法

在systemC/TLM编程中,peq (payload event queue)是一个非常重要的工具,尤其是在模拟RTL中的pipeline等场景下,是必不可少的。

peq有peq_with_get 和peq_with_cb_and_phase (cb是callback的简称) 两种形式。以下主要分析peq_with_cb_and_phase,并简称peq。

peq_with_get 的用法可参考 systemC/TLM:peq_with_get的简单用法_123axj的博客-CSDN博客

peq_with_cb_and_phase是一个模板类,两个模板参数,其中第二个默认为 tlm phase;第一个参数一般为 此peq变量 所在的class name。

peq没有默认构造函数,必须使用列表初始化方式进行初始化。构造函数中的OWNER*一般设置为this,参数cb是一个callback function的指针,这个callback函数的形式为void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&); 参数有两个,默认为tlm_generic_payload&和tlm_phase&,无返回值。callback函数中不允许存在显式或隐式的wait逻辑。

Peq被notify一次后,always会调用一次这个callback函数,调用的时间根据notify 的delay时间而定。

template<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types>

class peq_with_cb_and_phase : public sc_core::sc_object

typedef typename TYPES::tlm_payload_type tlm_payload_type;

typedef typename TYPES::tlm_phase_type tlm_phase_type;

typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&);

peq_with_cb_and_phase(OWNER* , cb );

peq_with_cb_and_phase(const char* , OWNER* , cb);

struct tlm_base_protocol_types

{

  typedef tlm_generic_payload tlm_payload_type;

  typedef tlm_phase tlm_phase_type;

};

一个简单的使用示例和打印结果分别如下:

#include <iostream>

#include "systemc.h"
#include "tlm_utils/peq_with_cb_and_phase.h"

using namespace std;
using namespace sc_core;

class TestPlatform : public sc_module {
public:
  SC_HAS_PROCESS(TestPlatform);

  TestPlatform(const sc_module_name &name)
      : sc_module(name), m_period(sc_time(1000, SC_PS)),
        m_test_peq("test_peq", this, &TestPlatform::Peq_callback_func) {
    SC_THREAD(PushPeq_1);
    SC_THREAD(PushPeq_2);
  };

private:
  void Peq_callback_func(tlm::tlm_generic_payload &trans,
                         const tlm::tlm_phase &phase);
  void PushPeq_1();
  void PushPeq_2();

  ~TestPlatform() = default;

public:
  sc_time m_period;
  tlm_utils::peq_with_cb_and_phase<TestPlatform> m_test_peq;
};

void TestPlatform::PushPeq_1() {
  tlm::tlm_generic_payload *t_trans = new tlm::tlm_generic_payload();
  t_trans->set_address(0x100);
  tlm::tlm_phase t_phase = tlm::BEGIN_REQ;

  // the transaction that peq will notify can't be a temporary memory space
  m_test_peq.notify(*t_trans, t_phase, 10 * m_period);
  cout << "[" << sc_time_stamp() << "] notify trans 1 to peq, notify cycle = 10"
       << endl;
}

void TestPlatform::PushPeq_2() {
  wait(2 * m_period);
  tlm::tlm_generic_payload *t_trans = new tlm::tlm_generic_payload();
  t_trans->set_address(0x200);
  tlm::tlm_phase t_phase = tlm::END_REQ;

  m_test_peq.notify(*t_trans, t_phase, 8 * m_period);
  cout << "[" << sc_time_stamp() << "] notify trans 2 to peq, notify cycle = 8"
       << endl;
}

// this is an error using example
void TestPlatform::Peq_callback_func(tlm::tlm_generic_payload &trans,
                                     const tlm::tlm_phase &phase) {
  if (phase == tlm::BEGIN_REQ) {
    cout << "[" << sc_time_stamp() << "] BEGIN REQ , addr=0x" << std::hex
         << trans.get_address() << endl;
  } else if (phase == tlm::END_REQ) {
    cout << "[" << sc_time_stamp() << "] END REQ , addr=0x" << std::hex
         << trans.get_address() << endl;
  } else {
    assert(false);
  }
}

int sc_main(int argc, char **argv) {
  TestPlatform *m_platform;
  m_platform = new TestPlatform("TestPlatform");
  sc_start(1, SC_US);
  return 0;
}


[0 s] notify trans 1 to peq, notify cycle = 10

[2 ns] notify trans 2 to peq, notify cycle = 8

[10 ns] BEGIN REQ , addr=0x100

[10 ns] END REQ , addr=0x200

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在SystemC中,用于同步和通信的基本元素是事件和过程。事件是用于通知进程发生某些特定事件的信号,而过程则是用于响应事件的代码部分。 sc_event是SystemC中的事件类,它可以用于同步和通信。wait()是SystemC中的方法,它是用于等待事件发生的方法。wait()方法是在进程中使用的,当执行到wait()方法时,进程会阻塞,直到等待的事件被触发。 下面是一个简单的例子,演示了如何使用sc_event和wait()方法进行同步: ``` #include <systemc.h> SC_MODULE(MyModule) { public: sc_in<bool> in; // 输入端口 sc_event event; // 事件 void do_something() { while (true) { // 等待事件 wait(event); // 执行任务 cout << "任务开始执行" << endl; // ... cout << "任务执行完毕" << endl; } } SC_CTOR(MyModule) { // 绑定事件 SC_THREAD(do_something); // 在构造函数中使用SC_METHOD()定义一个方法 // 该方法会在in信号发生变化时触发事件 SC_METHOD(trigger_event); sensitive << in; } void trigger_event() { // 触发事件 event.notify(); } }; int sc_main(int argc, char *argv[]) { // 创建事件和信号 sc_signal<bool> sig; sc_event event; // 创建模块并绑定输入端口和事件 MyModule m("my_module"); m.in(sig); m.event(event); // 在主函数中改变信号状态,触发事件 sig = true; event.notify(); // 等待事件处理完成 sc_start(); return 0; } ``` 在上面的代码中,MyModule模块中定义了一个事件event和一个函数do_something(),该函数在等待事件event,当事件event被触发时,会执行一些任务。在MyModule模块的构造函数中,使用SC_METHOD()定义了一个方法trigger_event(),该方法会在输入信号in发生变化时触发事件event。 在主函数中,创建了一个信号sig和一个事件event,并将它们绑定到MyModule模块的输入端口和事件上。然后,改变信号sig的状态并触发事件event。最后,调用sc_start()方法等待事件处理完成。 注意,在SystemC中,wait()方法只能在SC_THREAD线程中使用,不能在SC_METHOD中使用。同时,wait()方法必须与敏感信号一起使用,以便在信号发生变化时触发等待。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

123axj

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

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

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

打赏作者

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

抵扣说明:

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

余额充值