NickIlieskou Posted April 4, 2014 Report Share Posted April 4, 2014 Hey to everybody, I would like to ask a very simple question just to clarify how the concurrency concept work in SystemC. Let's say that we have two modules. Both modules are sensitive to the positive edge of the simulation clock. module1 is changing the value of a signal (or of a global variable). At the same time module2 has to read the signal ( or the global variable ). So my main question is if in one cycle during which both modules are invoked at the same time module 2 will read the latest value that module1 will output. I think that SystemC has the notion of delta cycle by which before going to the next simulation step ( or clock cycle ) it will make sure that all processes read the latest values of signal/variables independently from which or how many modules have changed their value. Thank you in advance!!! Quote Link to comment Share on other sites More sharing options...
apfitch Posted April 4, 2014 Report Share Posted April 4, 2014 There's a difference between a signal and a variable. A signal does have delta cycle behaviour - so when the clock changes, module 2 will read the current (before the change) value. With a plain C++ variable the result is undefined as you don't know which process will run first (the process in module 1 or the process in module 2) regards Alan Quote Link to comment Share on other sites More sharing options...
NickIlieskou Posted April 7, 2014 Author Report Share Posted April 7, 2014 Thank you for your answer. It's nice that you specify the difference between the signal and the variable. So if I want to be sure that module2 will read the latest value of something I should make sure that this will be a signal and not a global variable. Thank you again Alan. Quote Link to comment Share on other sites More sharing options...
NickIlieskou Posted April 8, 2014 Author Report Share Posted April 8, 2014 Sorry for asking again, but I would like to know if there is any way for module 2 to read the latest value of the signal that module1 has written at the same time ( let's say at the same positive edge). Quote Link to comment Share on other sites More sharing options...
apfitch Posted April 8, 2014 Report Share Posted April 8, 2014 The danger with that approach is that you have to manually make sure you have no race hazards in your design or indeterminacy in your design. My first answer would be "don't use a signal", use a shared variable instead. Another answer would be to have a shared event between the modules. You could do something like module1 sc_event sig_written; // in a process my_sig.write(true); sig_written.notify(); // immediate notify! /////////////////////////// module2 sc_in<int> sig; // in an sc_thread sc_event * ev; module2(sc_module_name name_, sc_event * ev_) : sc_module(name_), ev(ev_) { } void thread() { while (true) { wait(sig_written); cout << my_sig << endl; } There must be a better way of doing that, but the idea is to share an event between the modules then use immediate notify to trigger the read. Of course there's no real point using an sc_signal then, as the ordering is given by the event, so you might as well just use a shared variable. A third answer is to put the code in a single module, so you then have direct access to the value you are writing to the signal. regards Alan Quote Link to comment Share on other sites More sharing options...
NickIlieskou Posted April 8, 2014 Author Report Share Posted April 8, 2014 Thank you again for your answer Alan. Your idea about using events is nice. I hope it will work in my case. I can't put the whole code in a single module. I am trying to develop a simulation framework for different software applications. So in my application I have several dlls which have to execute at the same time depending on the scheduler, which I am trying to implement with SystemC. The problem is that I might need to execute dll n.1 first and then dll n.2 etc because these dlls they will change values of variables in the SystemC framework that will be read from other dlls at the same simulation time. However the order is not fixed. Thank you again!!! regards Nick Quote Link to comment Share on other sites More sharing options...
jserot Posted November 14, 2017 Report Share Posted November 14, 2017 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 Quote Link to comment Share on other sites More sharing options...
Roman Popov Posted November 14, 2017 Report Share Posted November 14, 2017 30 minutes ago, jserot said: 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 ? Can you please elaborate what do you mean by instantaneous broadcast for those who are not familiar with named formalisms? Some small example will be the best. Quote Link to comment Share on other sites More sharing options...
jserot Posted November 14, 2017 Report Share Posted November 14, 2017 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 Quote Link to comment Share on other sites More sharing options...
Roman Popov Posted November 14, 2017 Report Share Posted November 14, 2017 Ok, understood. Yes, the only way to execute this in a single delta cycle is to enforce execution order using events with immediate notification. It is impossible to implement it in other way in C++. What you want is a “SystemC-language-aware” compiler. Such a compiler will need to understand a semantics of processes and create a static schedule: such as a producer processes are always executed before consumer processes. Static scheduling is not always possible, because some processes can have cyclic data dependencies. So as you’ve said, sometimes it will need to resolve <<undeterminacy by iterating until a fix-point is reached>> But since SystemC is just a library, it can't guess what your processes code is doing (because C++ has no code reflection capabilities). Quote Link to comment Share on other sites More sharing options...
Roman Popov Posted November 14, 2017 Report Share Posted November 14, 2017 If your issue is that you don't like to have two variables: data and event, you can create a convenient class like sc_signal, that will pack data end event together. Essentially it will be sc_fifo with immediate notification and capacity == 1. If consumer reads from empty fifo it will be blocked until producer writes into fifo. With immediate notification it will be resumed in the same delta cycle as producer writes into fifo. Quote Link to comment Share on other sites More sharing options...
jserot Posted November 15, 2017 Report Share Posted November 15, 2017 11 hours ago, Roman Popov said: Quote Ok, understood. Yes, the only way to execute this in a single delta cycle is to enforce execution order using events with immediate notification. It is impossible to implement it in other way in C++. Ok, thanks. This is indeed what i suspected. Quote What you want is a “SystemC-language-aware” compiler. Such a compiler will need to understand a semantics of processes and create a static schedule: such as a producer processes are always executed before consumer processes. 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; ... } }; Quote Static scheduling is not always possible, because some processes can have cyclic data dependencies. So as you’ve said, sometimes it will need to resolve <<undeterminacy by iterating until a fix-point is reached>> Cyclic dependencies can be detected statically (as loops in the graph) and the corresponding programs rejected i guess. Quote Link to comment Share on other sites More sharing options...
jserot Posted November 15, 2017 Report Share Posted November 15, 2017 11 hours ago, Roman Popov said: Quote Essentially it will be sc_fifo with immediate notification and capacity == 1. If consumer reads from empty fifo it will be blocked until producer writes into fifo. With immediate notification it will be resumed in the same delta cycle as producer writes into fifo. The consumer should never block in my case. Reading twice a shared variable which has only been written once should not block the reader... Quote Link to comment Share on other sites More sharing options...
ralph.goergen Posted November 15, 2017 Report Share Posted November 15, 2017 Hi. Maybe you should have a look at SystemC AMS. It offers the TDF (timed data flow) model of computation. It follows the data flow concept, i.e. you have a cluster of blocks; the solver defines an order of evaluation of each block; and in every time step, the blocks (or modules) are evaluated in that order. The output of one block is immediately visible at the input of the following block. Greetings Ralph maehne 1 Quote Link to comment Share on other sites More sharing options...
jserot Posted November 15, 2017 Report Share Posted November 15, 2017 Thanks for the suggestion, Raph. Will have a look. 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.