总结
允许的绑定关系:
sc_port.bind(sc_port)
sc_port.bind(sc_interface)
sc_export.bind(sc_interface)
sc_port.bind(sc_export)
sc_export.bind(sc_export)
需要注意的是,前三者在 sc_port 和sc_export 代码中提供了对应的bind函数;而后两者sc_port.bind(sc_export) 和 sc_export.bind(sc_export) 需要先调用 sc_export的隐式类型转换函数,将sc_export 转换为 sc_interface,然后再调用sc_port.bind(sc_interface) 和sc_export.bind(sc_interface) |
不允许的绑定关系:
sc_export.bind(sc_port)
sc_interface.bind(sc_interface)
sc_interface.bind(sc_port)
sc_interface.bind(sc_export)
需要注意,系统中所有的sc_port 和sc_export 实例 都必须进行绑定,且只能绑定一次;一个绑定链上有且只能有一个sc_interface。(1个sc_port与多个sc_interface 相连,我们认为是多条 绑定链)
sc_interface 实例 是可以单独存在和使用的。
如果报E107 的error,说明重复绑定了。
Error: (E107) bind interface to port failed: interface already bound to port: port 'top_2.mst_top.port_0' (sc_port) In file: ../../../src/sysc/communication/sc_port.cpp:235
如果报E109 的error,说明有port或export没有绑定。
Error: (E109) complete binding failed: port not bound: port 'top_2.mst_top.port_0' (sc_port)
In file: ../../../src/sysc/communication/sc_port.cpp:235
以下为一个sc_port/sc_export/sc_interface的绑定和使用示例,其中class MyTop_1是一个sc_port绑定多个sc_interface的示例,class MyTop_2是用到sc_port/sc_export的层次化绑定的示例。
// 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 "tlm"
#include <map>
#include <systemc>
using namespace std;
using namespace sc_core;
class MyInterface : public sc_core::sc_interface, public sc_core::sc_module {
public:
explicit MyInterface(sc_core::sc_module_name name)
: sc_core::sc_module(name) {}
virtual void slave_write(int addr, int data) {
std::cout << this->name() << " write addr " << std::hex << addr << " = "
<< data << std::endl;
m_addr_data[addr] = data;
}
virtual void slave_read(int addr, int &data) {
if (m_addr_data.find(addr) != m_addr_data.end()) {
std::cout << this->name() << " read addr " << std::hex << addr << " = "
<< m_addr_data[addr] << std::endl;
data = m_addr_data[addr];
} else {
data = 0;
}
}
std::map<int, int> m_addr_data;
};
// MyMaster
class MyMaster : public sc_core::sc_module {
public:
SC_HAS_PROCESS(MyMaster);
explicit MyMaster(sc_core::sc_module_name name) : sc_core::sc_module(name) {
SC_THREAD(HandleThread);
}
~MyMaster() override = default;
void HandleThread() {
for (int i = 0; i < m_port.size(); ++i) {
cout << this->name() << " HandleThread write " << std::hex << (0x100 + i)
<< " = " << (0x5000 + i) << endl;
// here equal to (m_port.get_interface(i))->slave_write
m_port[i]->slave_write(0x100 + i, 0x5000 + i);
wait(1, SC_NS);
}
// here is call operator->
m_port->slave_write(0x5ffff, 0x1000);
wait(1, SC_NS);
for (int i = 0; i < m_port.size(); ++i) {
int t_data = 0;
cout << this->name() << " HandleThread read " << std::hex << (0x100 + i)
<< " = " << t_data << endl;
(m_port.get_interface(i))->slave_read(0x100 + i, t_data);
wait(1, SC_NS);
}
}
sc_core::sc_port<MyInterface, 0> m_port;
};
class MyTop_1 : public sc_core::sc_module {
public:
MyTop_1(sc_core::sc_module_name name)
: sc_core::sc_module(name), m_mst("mst"), m_interface("interface") {
m_interface.init(3);
for (int i = 0; i < 3; ++i) {
m_mst.m_port.bind(m_interface[i]);
}
}
MyMaster m_mst;
sc_vector<MyInterface> m_interface;
};
/
// MyMasterTop
class MyMasterTop : public sc_core::sc_module {
public:
SC_HAS_PROCESS(MyMasterTop);
explicit MyMasterTop(sc_core::sc_module_name name)
: sc_core::sc_module(name), m_mst("mst") {
/*****************************************************************************
// all port and export must to be bind, and must bind only once.
// if you write below line twice, will lead to simulation error
Error: (E107) bind interface to port failed: interface already bound to port x
In file: ../../../src/sysc/communication/sc_port.cpp:235
// if you forget to write below line, will lead to simulation error
Error: (E109) complete binding failed: port not bound: port xxx
In file: ../../../src/sysc/communication/sc_port.cpp:235
******************************************************************************/
m_mst.m_port.bind(m_mst_top_port);
}
~MyMasterTop() override = default;
sc_core::sc_port<MyInterface, 0> m_mst_top_port;
MyMaster m_mst;
};
// MySlave
class MySlave : public sc_core::sc_module {
public:
SC_HAS_PROCESS(MySlave);
explicit MySlave(sc_core::sc_module_name name)
: sc_core::sc_module(name), m_interface("interface") {
m_export.bind(m_interface);
}
~MySlave() override = default;
sc_core::sc_export<MyInterface> m_export;
MyInterface m_interface;
};
// MySlaveTop
class MySlaveTop : public sc_core::sc_module {
public:
SC_HAS_PROCESS(MySlaveTop);
explicit MySlaveTop(sc_core::sc_module_name name)
: sc_core::sc_module(name), m_slv("slv") {
/*****************************************************************************
// here can't change the export bind export direction,
// if you write m_slv.m_export.bind(m_slv_top_export);
// will build pass, but lead to below error in simulation
Error: (E120) sc_export instance has no interface: top_2.slv_top.export_0
In file: /usr/local/systemc-2.3.3/include/sysc/communication/sc_export.h:174
******************************************************************************/
m_slv_top_export.bind(m_slv.m_export);
}
~MySlaveTop() override = default;
sc_core::sc_export<MyInterface> m_slv_top_export;
MySlave m_slv;
};
class MyTop_2 : public sc_core::sc_module {
public:
MyTop_2(sc_core::sc_module_name name)
: sc_core::sc_module(name), m_mst_top("mst_top"), m_slv_top("slv_top") {
// here must sc_port.bind(sc_export)
// sc_export.bind(sc_port) will lead to build error
m_mst_top.m_mst_top_port.bind(m_slv_top.m_slv_top_export);
}
MyMasterTop m_mst_top;
MySlaveTop m_slv_top;
};
int sc_main(int argc, char **argv) {
/*****************************************************************************
// ports shall only be instantiated during elaboration and only from within a
// module, so can't use port in sc_main
// below code is error, which will lead to the below error in simulation
Error: (E100) port specified outside of module: port 'port_0' (sc_port_base)
In file: ../../../src/sysc/communication/sc_port.cpp:235
******************************************************************************/
// sc_core::sc_port<MyInterface, 0> error_port;
// MyInterface error_interface("error_interface") ;
// error_port.bind(error_interface);
MyTop_1 m_top("top_1");
MyTop_2 m_top_2("top_2");
sc_core::sc_start();
return 0;
}