jserot Posted November 18, 2014 Report Share Posted November 18, 2014 Dear all, I'm implementing a custom channel which is basically an hybrid object, offering a fifo-lile interface on the reader side and a signal-like interface on the writer side. The code is given below (listing 1). Basically, it just wraps up a sc_signal so that it can be viewed as a never-empty FIFO on the reader side. It works well except that the value changes -- that are correctly witnessed by issuing print msg in the write() method() -- are not dumped in the trace file (see listing 2). My intuition is that the write actions are not viewed by the trace mechanism and that i should explicitly call a method for this in the write() method. But i can just figure out which one. I've browsed the ref man but cannot find the answer to this question : what events are exactly dumped in the trace file when a channel is registered as traced by calling sc_trace ? Any clue ? Jocelyn template<class T> class buffer_in : public sc_signal_write_if<T>, public fifo_in_if<T>, public sc_prim_channel { protected: sc_signal<T> m_sig; sc_event m_data_written_event; public: explicit buffer_in( const char* name_ ) : m_sig(name_), m_data_written_event((std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) { } virtual ~buffer_in() { } // (read-only) fifo-conformant interface virtual int num_available() const { return 1; } virtual void read( T& t) { t = m_sig.read(); } virtual T read() { return m_sig.read(); } virtual bool nb_read( T& t) { t = m_sig.read(); return true; } virtual const sc_event& data_written_event() const { return m_data_written_event; } virtual T peek() const { return m_sig.read(); } virtual bool rd_rdy() const { return 1; } // (write-only) signal-conformant interface virtual void write( const T& t) { cout << "*** *** buffer " << m_sig.name() << " : write: " << t << endl; cout.flush(); m_data_written_event.notify(SC_ZERO_TIME); m_sig.write(t); }; // other methods virtual const char* kind() const { return "buffer_in"; } operator T () { return read(); } void trace( sc_trace_file* tf ) const { m_sig.trace(tf); } // sc_trace( tf, m_sig.read(), name()); } }; int sc_main(int argc, char* argv[]) { sc_clock clk("clk", 10, SC_NS, 1); sc_trace_file *trace_file; trace_file = sc_create_vcd_trace_file ("test_buffer"); ... buffer_in<sc_uint<8> > w("b1"); ... sc_trace(trace_file, clk, "clk"); sc_trace(trace_file, w, "b1"); sc_start(100, SC_NS); sc_close_vcd_trace_file (trace_file); cout << "Wrote file test_buffer.vcd" << endl; return EXIT_SUCCESS; } Quote Link to comment Share on other sites More sharing options...
sumit_tuwien Posted November 18, 2014 Report Share Posted November 18, 2014 protected: sc_signal<T> m_sig; sc_event m_data_written_event; public: explicit buffer_in( const char* name_ ) : m_sig(name_), m_data_written_event((std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) { } Your problem is possibly you are trying to trace event. sc_event(s) are not tracable. By the way std::string(SC_KERNEL_EVENT_PREFIX) will add some horrible $$$$ ..... Quote Link to comment Share on other sites More sharing options...
apfitch Posted November 19, 2014 Report Share Posted November 19, 2014 If you want to trace a user defined data type, you have to write an overloaded sc_trace function for that type. So if you wanted to trace your type you'd have to write a non-member function template<T> sc_trace(sc_trace_file *, const sc_buffer_in<T>, const std::string& ); and then in that function call sc_trace for the member m_sig. The standard says (in 8.2.1) "All changes to the value of the second argument that occur between the time the function is called andthe time the trace file is closed shall be recorded in the trace file." regards Alan maehne and David Black 2 Quote Link to comment Share on other sites More sharing options...
dakupoto Posted November 19, 2014 Report Share Posted November 19, 2014 Dear all, I'm implementing a custom channel which is basically an hybrid object, offering a fifo-lile interface on the reader side and a signal-like interface on the writer side. The code is given below (listing 1). Basically, it just wraps up a sc_signal so that it can be viewed as a never-empty FIFO on the reader side. It works well except that the value changes -- that are correctly witnessed by issuing print msg in the write() method() -- are not dumped in the trace file (see listing 2). My intuition is that the write actions are not viewed by the trace mechanism and that i should explicitly call a method for this in the write() method. But i can just figure out which one. I've browsed the ref man but cannot find the answer to this question : what events are exactly dumped in the trace file when a channel is registered as traced by calling sc_trace ? Any clue ? Jocelyn template<class T> class buffer_in : public sc_signal_write_if<T>, public fifo_in_if<T>, public sc_prim_channel { protected: sc_signal<T> m_sig; sc_event m_data_written_event; public: explicit buffer_in( const char* name_ ) : m_sig(name_), m_data_written_event((std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) { } virtual ~buffer_in() { } // (read-only) fifo-conformant interface virtual int num_available() const { return 1; } virtual void read( T& t) { t = m_sig.read(); } virtual T read() { return m_sig.read(); } virtual bool nb_read( T& t) { t = m_sig.read(); return true; } virtual const sc_event& data_written_event() const { return m_data_written_event; } virtual T peek() const { return m_sig.read(); } virtual bool rd_rdy() const { return 1; } // (write-only) signal-conformant interface virtual void write( const T& t) { cout << "*** *** buffer " << m_sig.name() << " : write: " << t << endl; cout.flush(); m_data_written_event.notify(SC_ZERO_TIME); m_sig.write(t); }; // other methods virtual const char* kind() const { return "buffer_in"; } operator T () { return read(); } void trace( sc_trace_file* tf ) const { m_sig.trace(tf); } // sc_trace( tf, m_sig.read(), name()); } }; int sc_main(int argc, char* argv[]) { sc_clock clk("clk", 10, SC_NS, 1); sc_trace_file *trace_file; trace_file = sc_create_vcd_trace_file ("test_buffer"); ... buffer_in<sc_uint<8> > w("b1"); ... sc_trace(trace_file, clk, "clk"); sc_trace(trace_file, w, "b1"); sc_start(100, SC_NS); sc_close_vcd_trace_file (trace_file); cout << "Wrote file test_buffer.vcd" << endl; return EXIT_SUCCESS; } Hello, After reading through your code, here are a few questions: As your custom channel is is going to transfer some generic type 'T', it will depend very much on whether what the actual type of 'T' is, in order for 'cout' to print out something meaningful. To be specific, if for example T is a bit vector or even a string, there would be no issues. But if T is itself another object, say a struct with different types of data inside it, then these need to be printed out separately. This is subtle problem with C++ templates in general - although they represent "generic" data types, often times manipulating these generic data types involve using plain good old C style techniques and tricks. Hope that helps. Quote Link to comment Share on other sites More sharing options...
jserot Posted November 19, 2014 Author Report Share Posted November 19, 2014 Dear all, Thank for your answers. Your problem is possibly you are trying to trace event. sc_event(s) are not tracable. By the way std::string(SC_KERNEL_EVENT_PREFIX) will add some horrible $$$$ ..... Sorry, i dont understand. What i'm trying to do is to trace value change on a signal - there surely must be a way to do this since tracing a sc_signal is obviously possible.. For the SC_KERNEL_EVENT_PREFIX, you're right, i can probably get rid of this (i just copied this line from the sc_fifo.h..) If you want to trace a user defined data type, you have to write an overloaded sc_trace function for that type. So if you wanted to trace your type you'd have to write a non-member function template<T> sc_trace(sc_trace_file *, const sc_buffer_in<T>, const std::string& ); and then in that function call sc_trace for the member m_sig. The standard says (in 8.2.1) "All changes to the value of the second argument that occur between the time the function is called andthe time the trace file is closed shall be recorded in the trace file." regards Alan Thanks for the suggestion, Alan.I tried this, adding this definition after the buffer_in class definition in my .h file (incidentally, i had to make the m_sig member public for this) : template<class T> void sc_trace(sc_trace_file *tf, const buffer_in<T> b, const std::string& s) { sc_trace( tf, b.m_sig, s); } but i get this error msg from the C++ compiler : In file included from test_buffer_port_in.cpp:5: ../buffer_in.h:14:7: error: inherited virtual base class 'sc_core::sc_interface' has private copy constructor class buffer_in ^ /usr/local/systemc-2.3.0/include/sysc/communication/sc_interface.h:65:5: note: declared private here sc_interface( const sc_interface& ); Seems i'm bumping again against a complex inheritance pb :-( Hello, After reading through your code, here are a few questions: As your custom channel is is going to transfer some generic type 'T', it will depend very much on whether what the actual type of 'T' is, in order for 'cout' to print out something meaningful. To be specific, if for example T is a bit vector or even a string, there would be no issues. But if T is itself another object, say a struct with different types of data inside it, then these need to be printed out separately. This is subtle problem with C++ templates in general - although they represent "generic" data types, often times manipulating these generic data types involve using plain good old C style techniques and tricks. Hope that helps. I understand this and all the types T that will be used to parameterize my buffer_in class are indeed equiped with the necessary functions to be traced.. In fact, i'm really puzzled by the fact that a similar class, buffer_out (see listing below) works perfectly well as regards tracing. I'm wondering what makes the difference with the above-mentionned buffer_in class.. template<class T> class buffer_out : public fifo_out_if<T>, public sc_signal_in_if<T>, public sc_prim_channel { protected: const char *name; sc_signal<T> m_sig; sc_event m_data_read_event; public: explicit buffer_out(const char* name_) : name(name_), m_sig(name_), m_data_read_event((std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()) {} virtual ~buffer_out() { } // fifo-like interface virtual int num_free() const { return 1; } virtual void write( const T& v) { m_sig.write(v); } virtual bool nb_write(const T& t) { m_sig.write(t); return true; }; virtual bool wr_rdy() const { return true; } virtual const sc_event& data_read_event() const { return m_data_read_event; } // signal-conformant interface virtual const sc_event& value_changed_event() const { return m_sig.value_changed_event(); } virtual const T& read() const { /*m_data_read_event.notify(SC_ZERO_TIME);*/ return m_sig.read(); } virtual const T& get_data_ref() const { return m_sig.get_data_ref(); } virtual bool event() const { return m_sig.event(); } // other methods virtual const char* kind() const { return "buffer_out"; } buffer_out<T>& operator = ( const T& a ) { write(a); return *this; } void trace( sc_trace_file* tf ) const { sc_trace(tf, m_sig.read(), m_sig.name()); }; // THIS WORKS. All write events get actually logged in the trace file.. }; Quote Link to comment Share on other sites More sharing options...
apfitch Posted November 19, 2014 Report Share Posted November 19, 2014 (edited) Hi Jocelyn, I think the reason the buffer_out works is that the trace function you are calling is declared in sc_signal_in_if, but isn't part of sc_signal_write_if. However using that trace is "cheating" because it's not part of the public API defined in the standard. Of course it does work with the Accellera Proof of Concept simulator. Regarding the copy constructor error, that's my fault - you need to declare the sc_trace function to take a const ref to the buffer_in, not a const object - because it's an object not a ref, it's invoking the copy constructor when the sc_trace is called, and as you've found some of the base class copy constructors are intentionally disabled. So change the function declaration to sc_trace(sc_trace_file *, const buffer_in<T> &, const std::string &); regards Alan Edited November 19, 2014 by apfitch Quote Link to comment Share on other sites More sharing options...
jserot Posted November 20, 2014 Author Report Share Posted November 20, 2014 So change the function declaration to sc_trace(sc_trace_file *, const buffer_in<T> &, const std::string &); regards Alan Ok; i should have spotted this myself ;-) Now it works correctly. Thanks _a lot_ for your help ! Best wishes Jocelyn Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.