I got this error on SystemC, and I don't understand why. The error is:
'write': is not a member of
'sc_core::sc_in' ConsoleApplication1
'write': is not a member of 'sc_core::sc_in'
class "sc_core::sc_in" has no member "write"
class "sc_core::sc_in" has no member "write"
Here I put together the code.
#include<systemc.h>
SC_MODULE(prin) {
sc_in<bool> a;
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
If the error seems confusing, here I put together the picture of my error:
The port "a" is an input port so cannot be written to. If you make it an output port then you can write to it. Also, the port is not bound so you will also get an error for that so I have bound a signal to it just so it compiles.
#include <systemc.h>
SC_MODULE(prin) {
sc_out<bool> a; //output port
sc_signal<bool> sig; //something to bind port a to
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
a(sig); //bind port a to s signal
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
Then
g++ -file.cpp -lsystemc
./a.out
Gives me the output
SystemC 2.3.2-Accellera --- Apr 16 2018 00:15:03
Copyright (c) 1996-2017 by all Contributors,
ALL RIGHTS RESERVED
Hello World
Related
I am trying to implement a producer (master) speaking to a memory element (slave) through the memory controller (which implements the interface simple_mem_interface).
Note: Some functions details and include statements are not fully mentioned in the code attached.
Searching for bugs in the code.
Adding debugging tools to find the fault in Write Enable Port.
binding.cpp
int sc_main(int argc, char* argv[])
{
sc_signal<unsigned int> d_out,d_in,address_d;
sc_signal<bool> wen, ren, ack;
sc_clock ClkFast("ClkFast", 100, SC_NS);
sc_clock ClkSlow("ClkSlow", 50, SC_NS);
Memory_Controller Controller1 ("Controller");
d_out = Controller1.data_mem_read;
ren.write(Controller1.REN);
ack.write(Controller1.ack);
d_in.write(Controller1.data_write);
address_d.write(Controller1.address);
wen.write(Controller1.WEN);
producer P1("Producer");
P1.out(Controller1);
P1.Clk(ClkFast);
Memory_module MEM("Memory");
MEM.Wen(wen);
MEM.Ren(ren);
MEM.ack(ack);
MEM.Clock(ClkSlow);
MEM.data_in(d_in);
MEM.data_out(d_out);
MEM.address(address_d);
sc_start(5000, SC_NS);
return 0;
Memory_controller.h
#define MEM_SIZE 100
#include <interface_func.h>
class Memory_Controller : public sc_module, public simple_mem_if
{
public:
// Ports
sc_in <unsigned int> data_mem_read{ "Data_Read_from_Memory" };
sc_out<bool> REN { "Read_Enable" };
sc_out<bool> WEN { "Write_Enable" };
sc_out <bool> ack{ "ACK_Bool" };
sc_out<unsigned int> address{ "Memory_Address" }, data_write{
"Data_Written_to_Memory" };
// constructor
Memory_Controller(sc_module_name nm) : sc_module(nm)
{ // Creating a 2 dimentional array holding adresses and data
WEN.write(false);
REN.write(false);
ack.write(false);
}
~Memory_Controller() //destructor
{
}
bool Write(unsigned int address_i, unsigned int datum) // blocking write
{
WEN.write(true);
REN.write(false);
data_write.write(datum);
address.write(address_i);
if (ack == true)
return true;
else
return false;
}
bool Read(unsigned int address_i, unsigned int& datum_i) // blocking read
{
WEN.write(false);
REN.write(true);
datum_i=data_mem_read;
address.write(address_i);
if (ack == true)
return true;
else
return false;
}
void register_port(sc_port_base& port, const char* if_typename)
{
cout << "binding " << port.name() << " to "
<< "interface: " << if_typename << endl;
}
};
Memory.h
#define MEM_SIZE 100
#include "interface_func.h"
class Memory_module : public sc_module
{
public:
sc_in<bool> Wen,Ren;
sc_in <unsigned int> address, data_in ;
sc_in<bool> Clock;
sc_out <unsigned int> data_out;
sc_out <bool> ack;
bool fileinput = false;
ifstream myfile;
unsigned int item [MEM_SIZE];
Memory_module()
{
}
void Write() // blocking write
{
while (true)
{
wait();
if (Wen==true)
{
if (address >= MEM_SIZE || address < 0)
{
ack=false;
}
else
{
item[address]=data_in;
ack=true;
}
}
}
}
void Read() // blocking read
{
while (true)
{
wait();
if (Ren)
{
if (address >= MEM_SIZE || address < 0)
ack=false;
else
{
data_out.write(item[address]);
ack=true;
}
}
}
}
SC_CTOR(Memory_module)
{
SC_THREAD(Read);
sensitive << Clock.pos();
SC_THREAD(Write);
sensitive << Clock.pos();
}
};
interface_func.h
class simple_mem_if : virtual public sc_interface
{
public:
virtual bool Write(unsigned int addr, unsigned int data) = 0;
virtual bool Read(unsigned int addr, unsigned int& data) = 0;
};
After debugging the SystemC binder.cpp code, the following error arises:
(E112) get interface failed: port is not bound : port 'Controller.Write_Enable' (sc_out)
You cannot drive your unconnected ports in the Memory_Controller constructor. If you want to explicitly drive these ports during startup, move these calls to a start_of_simulation callback:
Memory_Controller(sc_module_name nm) : sc_module(nm)
{}
void start_of_simulation()
{
WEN.write(false);
REN.write(false);
ack.write(false);
}
I get a SIGSEGV in following class on the second time I call the start_receive(). It works correctly in my open() function, but seems to fail when input is received and I try restarting listen for more input:
#0 0x0000555555584154 in boost::asio::basic_io_object<boost::asio::datagram_socket_service<boost::asio::ip::udp>, true>::get_service (this=0x100007f00000000)
at /usr/include/boost/asio/basic_io_object.hpp:225
#1 0x000055555558398b in boost::asio::basic_datagram_socket<boost::asio::ip::udp, boost::asio::datagram_socket_service<boost::asio::ip::udp> >::async_receive_from<boost::asio::mutable_buffers_1, boost::_bi::bind_t<int, boost::_mfi::mf2<int, Vast::net_udpNC_MChandler, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<Vast::net_udpNC_MChandler*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (this=0x100007f00000000, buffers=...,
sender_endpoint=..., handler=...)
at /usr/include/boost/asio/basic_datagram_socket.hpp:895
#2 0x000055555557a889 in Vast::net_udpNC_MChandler::start_receive (
this=0x7fffffff5c70) at net_udpnc_mchandler.cpp:58
#3 0x000055555557aa77 in Vast::net_udpNC_MChandler::handle_input (
this=0x7fffffff5c70, error=..., bytes_transferred=24)
at net_udpnc_mchandler.cpp:100
#4 0x000055555557abb3 in Vast::net_udpNC_MChandler::handle_buffer (
this=0x7fffffff5c70, buf=0x7fffffffdad0 "\035\300", bytes_transferred=24)
at net_udpnc_mchandler.cpp:114
#5 0x000055555556397f in test_process_encoded ()
at unittest_net_udpnc_mchandler.cpp:43
#6 0x000055555556400e in main () at unittest_net_udpnc_mchandler.cpp:101
Header:
class net_udpNC_MChandler
{
public:
net_udpNC_MChandler(ip::udp::endpoint local_endpoint);
//MChandler will run its own io_service
int open (AbstractRLNCMsgReceiver *msghandler);
int handle_buffer (char *buf, std::size_t bytes_transferred);
protected:
//Start the receiving loop
void start_receive ();
// handling incoming message
int handle_input (const boost::system::error_code& error,
std::size_t bytes_transferred);
private:
ip::udp::socket *_udp;
ip::udp::endpoint _remote_endpoint_;
ip::udp::endpoint _local_endpoint;
ip::udp::endpoint MC_address;
char _buf[VAST_BUFSIZ];
AbstractRLNCMsgReceiver *_msghandler = NULL;
io_service *_io_service;
boost::thread *_iosthread;
};
Source file:
net_udpNC_MChandler::net_udpNC_MChandler(ip::udp::endpoint local_endpoint) :
MC_address(ip::address::from_string("239.255.0.1"), 1037)
{
_io_service = new io_service();
_local_endpoint = local_endpoint;
}
int net_udpNC_MChandler::open(AbstractRLNCMsgReceiver *msghandler) {
_msghandler = msghandler;
if (_udp == NULL) {
_udp = new ip::udp::socket(*_io_service);
_udp->open(ip::udp::v4());
_udp->set_option(ip::udp::socket::reuse_address(true));
_udp->set_option(ip::multicast::join_group(MC_address.address ()));
boost::system::error_code ec;
_udp->bind(MC_address, ec);
std::cout << "net_udpnc_mchandler::open " + ec.message() << std::endl;
if (ec)
{
std::cout << "net_udpnc_mchandler:: open MC address failed" << ec.message() << std::endl;
}
//Add async receive to io_service queue
start_receive();
std::cout << "net_udpnc_mchandler::open _udp->_local_endpoint: " << _udp->local_endpoint() << " _local_endpoint" << _local_endpoint << std::endl;
//Start the thread handling async receives
_iosthread = new boost::thread(boost::bind(&boost::asio::io_service::run, _io_service));
}
return 0;
}
void net_udpNC_MChandler::start_receive()
{
_udp->async_receive_from(
boost::asio::buffer(_buf, VAST_BUFSIZ), _remote_endpoint_,
boost::bind(&net_udpNC_MChandler::handle_input, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
// handling incoming message
int net_udpNC_MChandler::handle_input (const boost::system::error_code& error,
std::size_t bytes_transferred)
{
RLNCHeader header;
if (!error)
{
//Store UDP messages
char *p = _buf;
memcpy(&header, p, sizeof(RLNCHeader));
if (RLNCHeader_factory::isRLNCHeader (header) && header.enc_packet_count > 1)
{
CPPDEBUG("net_udpnc_mchandler::handle_input: Encoded packet received" << std::endl);
process_encoded (bytes_transferred);
}
//Restart waiting for new packets
start_receive();
}
else {
CPPDEBUG("Error on UDP socket receive: " << error.message() << std::endl;);
}
return -1;
}
The strangest thing is that everything works if I use a default constructor without arguments (i.e. no local_endpoint), this SIGSEGV does not appear. But as soon as I change the constructor to the current one, I get the SIGSEGV.
The _io_service is a class object and it does not get destructed anywhere but the destructor, so I do not know how I can get a SIGSEGV for it...
Is there some requirement on the handler class that it has a no arguments constructor?
I'd like to print out the name of sc_module to which sc_signal connected.
How can I get the module name, "module_a" in the following code, from "sig_out"?
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm)
{
}
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
// std::cout << sig_out.get_parent() << std::endl;
sc_start();
return 0;
}
You could override sc_interface::register_port() in the my_sig class to save a reference to the bound port. The parent of the bound port is the module that contains the port.
#include <iostream>
#include <cassert>
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm), bound_port(NULL)
{
}
void register_port(sc_port_base& port, const char*) {
bound_port = &port;
}
sc_object* get_bound_module() const {
assert(bound_port);
return bound_port->get_parent_object();
};
sc_port_base* bound_port;
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
sc_start(0, SC_NS);
std::cout << sig_out.get_bound_module()->name() << std::endl;
return 0;
}
The above code prints the name of module_a. Note that sig::get_bound_module() can only be called after elaboration, that is, after sc_start() has been called, because sc_interface::register_port() is only called during elaboration.
I struggled with the following code. My signal handler on_button_press_event() is never called but I have no idea why. Could someone have a look on it? Maybe someone is able to run through the gtkmm lib with debug infos. I only have the pre-installed gtkmm packages which could not be used for debugging into the library itself.
#include <iostream>
using namespace std;
#include <gtkmm.h>
#include <goocanvasmm.h>
bool MyExternalHandler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "External Handler" << endl;
return false;
}
class MyRect : public Goocanvas::Rect
{
public:
MyRect( double x, double y, double w, double h)
//: Goocanvas::Rect( x,y,w,h)
{
property_x()=x;
property_y()=y;
property_width()=w;
property_height()=h;
}
public:
virtual void nonsens() {}
bool on_button_press_event(const Glib::RefPtr<Item>& target, GdkEventButton* event) override
{
cout << "override handler" << endl;
return false;
}
bool Handler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "via mem_fun" << endl;
return false;
}
bool on_enter_notify_event(const Glib::RefPtr<Item>& target, GdkEventCrossing* event) override
{
cout << "override enter notify" << endl;
return false;
}
};
int main(int argc, char* argv[])
{
Gtk::Main app(&argc, &argv);
Goocanvas::init("example", "0.1", argc, argv);
Gtk::Window win;
Goocanvas::Canvas m_canvas;
m_canvas.set_size_request(640, 480);
m_canvas.set_bounds(0, 0, 1000, 1000);
MyRect* ptr;
Glib::RefPtr<MyRect> m_rect_own(ptr=new MyRect(225, 225, 150, 150));
m_rect_own->property_line_width() = 1.0;
m_rect_own->property_stroke_color() = "black";
m_rect_own->property_fill_color_rgba() = 0x555555ff;
Glib::RefPtr<Goocanvas::Item> root = m_canvas.get_root_item();
root->add_child( m_rect_own);
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::ptr_fun(&MyExternalHandler));
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::mem_fun(*ptr, &MyRect::Handler));
win.add(m_canvas);
win.show_all_children();
Gtk::Main::run(win);
return 0;
}
Your on_button_press_event() method is not an override, because it has the wrong parameters:
https://developer.gnome.org/gtkmm/unstable/classGtk_1_1Widget.html#aba72b7f8655d1a0eb1273a26894584e3
When I create a D-Bus server (via g_bus_own_name()) and the client to it (using g_dbus_proxy_new()) in the same process and then call g_dbus_proxy_call_sync(), it never returns. However, if server and client are in separate processes, everything is ok.
The following code illustrates my problem (I am using giomm C++ bindings here):
file main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
std::thread thr_server([](){ server_main(); });
sleep(1); // give some time to server to register
std::thread thr_client([](){ client_main(); });
sleep(10); // wait for the client to finish
}
file server.cc:
#include <giomm.h>
#include <iostream>
namespace {
static Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
static Glib::ustring introspection_xml =
"<node name='/org/glibmm/DBusExample'>"
" <interface name='org.glibmm.DBusExample'>"
" <method name='Method'>"
" </method>"
" </interface>"
"</node>";
guint registered_id = 0;
}
static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */,
const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
const Glib::VariantContainerBase& parameters,
const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
{
if(method_name == "Method") {
std::cout << "Method was called\n";
}
}
const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call));
void on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */)
{
std::cout << "on_bus_acquired\n";
try {
registered_id = connection->register_object("/org/glibmm/DBusExample",
introspection_data->lookup_interface(),
interface_vtable);
}
catch(const Glib::Error& ex) {
std::cerr << "Registration of object failed." << std::endl;
}
return;
}
void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */, const Glib::ustring& /* name */)
{}
void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */) {
connection->unregister_object(registered_id);
}
int server_main()
{
try {
introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml);
}
catch(const Glib::Error& ex) {
std::cerr << "Unable to create introspection data: " << ex.what() <<
"." << std::endl;
return 1;
}
const guint id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION,
"org.glibmm.DBusExample",
sigc::ptr_fun(&on_bus_acquired),
sigc::ptr_fun(&on_name_acquired),
sigc::ptr_fun(&on_name_lost));
//Keep the service running
auto loop = Glib::MainLoop::create();
loop->run();
Gio::DBus::unown_name(id);
return EXIT_SUCCESS;
}
file client.cc:
#include <giomm.h>
#include <iostream>
Glib::RefPtr<Glib::MainLoop> loop;
// A main loop idle callback to quit when the main loop is idle.
bool on_main_loop_idle() {
std::cout << "loop_idle\n";
loop->quit();
return false;
}
void on_dbus_proxy_available(Glib::RefPtr<Gio::AsyncResult>& result)
{
auto proxy = Gio::DBus::Proxy::create_finish(result);
if(!proxy) {
std::cerr << "The proxy to the user's session bus was not successfully "
"created." << std::endl;
loop->quit();
return;
}
try {
std::cout << "Calling...\n";
proxy->call_sync("Method");
std::cout << "It works!\n";
}
catch(const Glib::Error& error) {
std::cerr << "Got an error: '" << error.what() << "'." << std::endl;
}
// Connect an idle callback to the main loop to quit when the main loop is
// idle now that the method call is finished.
Glib::signal_idle().connect(sigc::ptr_fun(&on_main_loop_idle));
}
int client_main() {
loop = Glib::MainLoop::create();
auto connection =
Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SESSION);
if(!connection) {
std::cerr << "The user's session bus is not available." << std::endl;
return 1;
}
// Create the proxy to the bus asynchronously.
Gio::DBus::Proxy::create(connection, "org.glibmm.DBusExample",
"/org/glibmm/DBusExample", "org.glibmm.DBusExample",
sigc::ptr_fun(&on_dbus_proxy_available));
loop->run();
return EXIT_SUCCESS;
}
I compile the test with g++ -O2 -std=c++0x main.cc server.cc client.cc -o test $(pkg-config --cflags --libs giomm-2.4) and run:
./test
on_bus_acquired
Calling...
<it hangs>
However, when I change main.cc:
#include <giomm.h>
int server_main();
int client_main();
int main() {
Gio::init();
auto childid = fork();
if (childid == 0) {
server_main();
} else {
sleep(1);
client_main();
}
}
I get:
./test
on_bus_acquired
Calling...
Method was called
It works!
So call_sync() returns successfully.
I tried to exclude loops from server and client, and use a single-threaded main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
server_main();
client_main();
auto loop = Glib::MainLoop::create();
loop->run();
}
Nothing helps. The question is, what am I doing wrong? I want to use my d-bus server and client in one process.
I figured it out, the trick is to execute
Glib::VariantContainerBase result;
invocation->return_value(result);
in the end of on_method_call.