Jump to content


  • Posts

  • Joined

  • Last visited

Recent Profile Visitors

455 profile views

jserot's Achievements


Member (1/2)



  1. Thanks for the suggestion, Raph. Will have a look. Jocelyn
  2. The consumer should never block in my case. Reading twice a shared variable which has only been written once should not block the reader...
  3. Ok, thanks. This is indeed what i suspected. Exactly. In fact, this is the kind of solution i'm investigating. I'm starting from a compiler internal representation of the application as a graph of FSMs connected via shared variables. Each FSM is implemented as a SystemC module. The idea is to extract from the graph the chain of dependencies - i.e. which module(s) read (resp. write) each variable - and to insert delta wait(s) at the right place(s). In the example above, this would involve rewriting B as void B::my_thread() { while ( 1 ) { wait(h.posedge_event()); wait(SC_ZERO_CYCLE); if ( v == 1 ) xxx; ... } }; Cyclic dependencies can be detected statically (as loops in the graph) and the corresponding programs rejected i guess.
  4. Hi Roman, thanks for your feedback. Instantaneous broadcast - also called "perfect synchrony" - means that any update performed to a shared value by a component (a module in our case) will be viewed immediately by other components (and not after n delta cycles, as for sc_signals). Here's a typical example, with two modules : - module A waits for (global) event H (a clock typically) and, when received, set shared variable v to 1 - module B also waits for H but when received only performs action xxx if v=1 (in StateChart, this is called a guarded transition) void A::my_thread() { ... while ( 1 ) { ... wait(h.posedge_event()); v = 1; ... } }; void B::my_thread() { while ( 1 ) { wait(h.posedge_event()); if ( v == 1 ) xxx; ... } }; As explained by Alan, the above implementation does not correspond to the behavior suggested above : - if v is implemented by using a sc_signal, then v only takes value 1 at time t+delta (if H occurs at time t), and hence "too late" for B - if v is implemented as a "regular" shared variable, then the behavior becomes non-deterministic (whether B "sees" v=1 depends on the order at which the scheduler runs the corresponding threads, which is un-predictable). Currently, I don't see a solution other than enforcing execution order using sc_events (as suggested by Alan). But this seriously complicates the translation from formalisms supporting the SB hypothesis to SystemC. I was just wondering if i was missing sth about SystemC semantics or whether this was simply not possible.. Jocelyn
  5. Hi, Sorry for resurrecting this post but it addresses an issue i'm currently facing. Does this mean that it is not possible to implement instantaneous broadcast (as used in StateCharts or synchronous reactive models of computation for ex.) in SystemC ? With the latters, the undeterminacy is resolved by iterating until a fix-point is reached so that the final values of shared variables do not depend on the order of (micro)-steps ? Jocelyn
  6. Ok; i should have spotted this myself ;-) Now it works correctly. Thanks _a lot_ for your help ! Best wishes Jocelyn
  7. Dear all, Thank for your answers. 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..) 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 :-( 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.. };
  8. 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; }
  9. This is exactly what i've been doing up to now ! But since my specific fifo is very similar to the sc_fifo, this implies a lot of copying. This is that copying I was wishing to avoid by using inheritance. I've read a bit on multiple inheritance issues since yesterday (since i'm not basically a C++ specialist..) : not trivial ones, apparently ! Thanks for the feedback anyway
  10. Thanks a lot for the tip, Philipp. I haven't thought about this since i'm not familiar with the TLM layer. Will try ! This said, i find it awkward that the sc_fifo class cannot be easily extended. Is it a consequence of the limitations of the C++ inheritance mechanism or a deliberate choice of the SystemC designer ? Jocelyn
  11. Hi, I reactivate this thread because I've stumbled on the same problem recently and can't seem to find any answer after having crawled the web for a while. I understand the pb with the second solution and tried the one given by Philipp (wrapping a sc_fifo instance inside my special fifo class). Unfortunately, it does not work if the "derived" (wrapping) class needs to access non-public members of the wrapped class. In my case, i wand to add a method virtual T peek(void); which simply returns the data at the top of the FIFO without popping it (non destructive read). There's no way to do this using the public interface of the sc_fifo class. The only solution would be to define peek as : virtual T peek(void) { return p_fifo.m_buf[p_fifo.m_ri]; } But, as said before, this simply does not work because m_buf and m_ri are _protected_ members of the sc_fifo class. So far, the only solution i've found is copy-pasting the code of sc_fifo and adding the requested method, which obviously is a hack. Any idea ? Thanks in advance. Jocelyn
  12. Philip, The type inference phase is carried out on a backend-independant representation. In this particular case, the tricky thing to do is to map the types computed at this level to SystemC types because, as you rightly puts it, there a significant number of corner cases (and the VHDL backend is even worst..). The solution you suggest (inserting unary + or equiv) will unfortunately not work in all cases, because _any kind_ of expression can appear as an argument of the ternary cond operator (sorry, it's difficult to be more explicit w/o showing the intermediate representation and associated transfo rules which are written ... in OCaml ) Thanks anyway for your clever comments and suggestions ! Jocelyn
  13. You guessed right, Alan The bug will be fixed in vers 1.6 (not by replacing the cond op by an "if" but by using the result of the type inference phase to insert the proper type cast when requested). Best regards Jocelyn
  14. Thanks a lot Philipp ! I was suspecting sth like this but was not aware doing arithmetic on one operand was actually changing its type (compared to the other one). In fact, i had searched the sc_int class for an (overloaded) version of the arithm operators (+, _, ...) and was a bit puzzled not to find them. Anyway, this explains the problem. ... but incidently, does not simplify my life - since the code in question is actually not written by hand but generated by a compiler (more details on this here, in case you would be interested : http://dream.univ-bpclermont.fr/index.php/en/softmenu/caph.html). So this means that i will have to detect and correct these situations on a ad-hoc, type-based, basis :-S Thanks again for your help Best wishes Jocelyn
  15. Thanks for your reply. Sorry. My code was confusing. Of course, when compiling, i comment out one of the two lines containing the return statement. To be clearer : This compiles ok : template<int n> sc_int<n> f_abs(sc_int<n> x) { if ( x <0 ) return 0-x; else return x; }; But this fails to compile : template<int n> sc_int<n> f_abs(sc_int<n> x) { return x<0 ? 0-x : x; };
  • Create New...