在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 |
原文地址:https://www.jb51.cc/wenti/3280715.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。