Re: sc_event_and/or_list

From: Philipp A. Hartmann <philipp.hartmann@offis.de>
Date: Tue Oct 05 2010 - 04:33:34 PDT

John,

Wrt. sc_event_list::swap, this can be implemented quite
straight-forward. Of course, swapping two lists would only be allowed,
if neither of both is currently being waited on. OTOH, this may not be
too important.

I agree, that more complex event expression may be too much effort to
add for now. The most obvious use-cases for this, like user-defined
reset mechanisms e.g.

  wait( block1.finished() & block2.finished() | my_reset );

can now be built on top of the process control extensions.
More over, I think that in case of complex lists you most likely need to
determine, which (subset of) events actually fired.

Thanks,
  Philipp

On 05/10/10 12:27, john.aynsley@doulos.com wrote:
> Philipp,
>
> My opinions below...
>
> John A
>
>
>
> From:
> "Philipp A. Hartmann" <philipp.hartmann@offis.de>
> To:
> john.aynsley@doulos.com
> Cc:
> "Jeremiassen, Tor" <tor@ti.com>, systemc-p1666-technical@eda.org
> Date:
> 04/10/2010 19:17
> Subject:
> Re: sc_event_and/or_list
>
>
>
> John, Tor, All,
>
> I completely agree with your analysis. Moreover, I did some experiments
> regarding the tracking of prematurely destroyed (or modified) event
> lists, which seems to work quite well.
>
> I've added the required kernel changes (against OSCI-internal SystemC
> 2.3.16jul10_beta) to my Twiki page again (two patches [1],[2] and "new"
> sc_event.h [3] and sc_event.cpp [4]).
>
> Note, that currently an application can only default-create
> non-auto-deleted sc_event_*_lists or copy/assign from an (e1 |,& e2)
> expression. I think, the auto-delete mechanism should be hidden from an
> application. Otherwise, it's next to impossible to get the lifetimes
> correctly implemented in presence of copyable event lists which are
> required for return-by-value as in all_events().
>
> *** [JA] I agree the auto-delete mechanism should be hidden from the
> application
>
> Premature deletion and modifications while processes are still waiting
> for an event list can be detected (see source). Temporaries are
> supported, when using the const patch as proposed earlier.
>
> Some questions remain:
>
> - Should the lists have any additional public interface?
> Maybe a size() function would be useful? Maybe swap()?
>
> *** [JA] I agree with size(). I don't know whether adding swap() causes
> implementation issues.
>
> - Should empty lists trigger an error or a warning, when being passed
> to wait()/next_trigger? Or should it be silently ignored?
> wait( timeout, sc_event_*_list ) might be useful even for empty
> lists.
>
> *** [JA] I would not want to change the rules for long-standing constructs
> like this. Hence I am tending toward saying that an empty event list is an
> ERROR
>
> - What about sc_event_list (the base class) itself? Should an
> application be able to use it explicitly? I think, it could
> be left out of the standard as being an implementation artefact.
>
> *** [JA] I vote for implementation artefact.
> *** [JA] As an aside, I often hear people ask whether they can use
> combinations of and/or operators in an event list, as in
>
> wait( ((e1 & e2) | e3) & e4) );
>
> *** [JA] I kind of assume we don't want to pick that one up ;-)
>
> Thanks,
> Philipp
>
>
> [1]
> http://www.eda.org/twiki/pub/Main/PhilippHartmann/0001-make-event-handling-const.patch
>
> [2]
> http://www.eda.org/twiki/pub/Main/PhilippHartmann/0002-sc_event_list-track-in-kernel-usage.patch
>
> [3] http://www.eda.org/twiki/pub/Main/PhilippHartmann/sc_event.h
> [4] http://www.eda.org/twiki/pub/Main/PhilippHartmann/sc_event.cpp
>
> On 04/10/10 17:15, john.aynsley@doulos.com wrote:
>> Philipp, Tor, All,
>>
>> For those of you who are not up-to-speed with the issues, I will try to
>> summarize.
>>
>> Consider the following code fragment:
>>
>> sc_event e1, e2;
>> ...
>> wait( e1 | e2 );
>>
>> What happens is that sc_event::operator| creates an sc_event_or_list on
>> the heap that is marked for auto-deletion. When the process that called
>> wait resumes following the notification of e1 or e2, the
> sc_event_or_list
>> object is deleted (because it was marked for auto-deletion).
>>
>> However, the protected constructor
>>
>> sc_event_or_list( const sc_event&, bool auto_delete_ = false );
>>
>> does have an (unused) mechanism to construct an event list that is not
>> marked for auto-deletion. We could harness this mechanism to allow
>> applications to create proper event list objects. It would then be the
>> responsibility of the application to delete the event list object. As
>> Philipp points out in his example, the application has to ensure that
> the
>> event list object does not get deleted prematurely, for example by being
> a
>> stack variable in a method process.
>>
>> Now for my opinion on Philipp's questions below:
>>
>> I think it is reasonable to require an application to keep an explicitly
>
>> constructed event list object around until the process has resumed, and
>> for the implementation to have the option of detecting and reporting the
>
>> error otherwise. I would be somewhat opposed to introducing the overhead
>
>> of having wait/next_trigger copy the event list.
>>
>> In my opinion, the mutation case (c) should be outlawed. operator| was
>> originally protected, and not intended as an application-level
> side-effect
>> operator.
>>
>> I'm not sure we can disallow temporaries altogether, because the code
>> fragment
>>
>> wait( all_events() );
>>
>> should be allowed in my opinion, which I think means that we need to
> make
>> the const patch as proposed by Philipp. Does that make sense?
>>
>>
>> Thanks,
>>
>> John A
>>
>>
>>
>>
>> From:
>> "Philipp A. Hartmann" <philipp.hartmann@offis.de>
>> To:
>> john.aynsley@doulos.com
>> Cc:
>> systemc-p1666-technical@eda.org, "Jeremiassen, Tor" <tor@ti.com>
>> Date:
>> 30/09/2010 14:54
>> Subject:
>> Re: sc_event_and/or_list
>>
>>
>>
>> John,
>>
>> regarding the implementation of 'const'ness of sc_event_lists please
>> find source code and comments below.
>>
>> But actually, I'm not sure about the correct semantics anyhow. During
>> my experiments, I've realised, that we still have to define the correct
>> ownership and lifetime requirements for the event lists.
>>
>> Consider the following example:
>>
>> SC_METHOD(proc);
>> // ...
>>
>> sc_event_and_list all_events(); // return temporary
>>
>> void proc()
>> {
>> if( case_1 )
>> // (a) wait on temporary list
>> next_trigger( all_events() );
>> else {
>> // (b) wait on local list
>> sc_event_and_list el = all_events(); // copy list
>> next_trigger( el ); // would even work for sc_event_list& arg
>>
>> // (c) change list, what now?
>> el | some_event; // relation to previous next_trigger call?
>> }
>> }
>>
>> In both cases (a) and (b), the event lists are destroyed _before_ the
>> kernel had a chance to complete its processing on it.
>>
>> I see two possible solutions for this lifetime problem:
>>
>> 1) the kernel makes a copy of the list internally
>> -> copies come at some cost, but temporaries are possible now
>> 2) the kernel detects the premature deletion of the list and
>> errors out
>> -> Then we don't need to change the signatures of wait() and
>> next_trigger(), since temporaries are nearly always an user
>> error.
>>
>> For mutating event lists (case (c) in example above), only taking copies
>> seems to be viable. We could of course prohibit mutations, when the
>> kernel "uses" the event list currently.
>>
>> Opinions on that?
>>
>> Constness discussion interspersed below.
>>
>> On 30/09/10 10:45, john.aynsley@doulos.com wrote:
>> [snip]
>>> I hit the following roadblock in file sc_thread_process.h:
>>>
>>> inline
>>> void
>>> sc_thread_process::wait( const sc_event_or_list& el ) // <<<< Changed
>>> code
>>> {
>>> el.add_dynamic( this );
>>
>> The add_dynamic() member function (and friends) of sc_event itself are
>> already const. Changing these functions to be const in sc_event_list
>> does not do much harm:
>>
>> void
>> -sc_event_list::add_dynamic( sc_thread_handle thread_h )
>> +sc_event_list::add_dynamic( sc_thread_handle thread_h ) const
>> {
>> if ( m_events.size() != 0 ) {
>> - const sc_event** l_events = &m_events[0];
>> + const sc_event* const * l_events = &m_events[0];
>> for( int i = m_events.size() - 1; i >= 0; -- i ) {
>> l_events[i]->add_dynamic( thread_h );
>> }
>>
>> [snip]
>>>
>>> In other words, it seems dynamic sensitivity does change the event
>> lists.
>>> Did you get any further than this? Have you got an answer?
>>
>> Well, yes. The event lists are not really changed in the sense, that
>> the set of represented events changes. There are currently 'non-const'
>> functions called, which in their body only call const functions on the
>> events.
>>
>> This is not really pretty, but adding/removing sensitive processes
>> to/from events has to be a "const" operation, since wait() only gets
>> const event references. So we don't make anything worse here.
>>
>> I've uploaded a 'const-adding' patch against SystemC 2.2.1 (or 2.2.0) to
>> my Twiki-Space at eda.org [1].
>>
>> Thanks,
>> Philipp
>>
>> [1]
>>
> http://www.eda.org/twiki/pub/Main/PhilippHartmann/0001-make-event-handling-const.patch
>
>>
>>
>>>
>>> From:
>>> "Philipp A. Hartmann" <philipp.hartmann@offis.de>
>>> To:
>>> john.aynsley@doulos.com
>>> Cc:
>>> "Jeremiassen, Tor" <tor@ti.com>, systemc-p1666-technical@eda.org
>>> Date:
>>> 28/09/2010 22:08
>>> Subject:
>>> Re: sc_event_and/or_list
>>>
>>>
>>>
>>> Ok, I had a misconception in my last mail. Actually, dynamic
>>> sensitivity does not change the event lists (in terms of represented
>>> events) in the current OSCI implementation. This removes my main
>>> concern mentioned in the last mail. Sorry for that.
>>>
>>> So the current situation is as follows:
>>>
>>> - changing wait()/next_trigger() to take "const sc_event_*_list &"
>>> works fine (only some additional 'const' qualifiers required,
>>> no additional 'mutable' or 'const_cast').
>>> -> would enable temporary sc_event_*_lists as parameters
>>>
>>> - For efficiency reasons, the operators &,| for building
>>> event lists could keep their mutating behaviour.
>>>
>>> - Wrt to the public interface of sc_event_*_list objects, I have
>>> no strong opinion. Except that obvious things like begin(), end(),
>>> size(), swap() should probably be part of it. :-)
>>>
>>> John, if you're interested in my experimental code, please let me know.
>>>
>>> Thanks,
>>> Philipp
>>>
>>> On 28/09/10 22:18, Philipp A. Hartmann wrote:
>>>> John, Tor, All,
>>>>
>>>> from my POV, the most important issue in this regard is the definition
>>>> of value/ownership semantics of such lists in their interaction with
>> the
>>>> simulation kernel.
>>>>
>>>> As of know, the implementation is completely free to modify the
>> passed
>>>> event lists (as the interface suggests). Having these lists as proper
>>>> objects (e.g. module members) would imply, that the kernel should NOT
>>>> modify the passed objects, right?
>>>>
>>>> Changing the signatures of wait() and next_trigger to take event
>> lists
>>>> as const references would be possible and even backwards-compatible
>> (and
>>>> would solve the return-by-value issue, John mentioned).
>>>>
>>>> Example:
>>>>
>>>> sc_event_and_list el1 = e1 & e2 & e3;
>>>> sc_assert( el1.size() == 3 ); // 3 events in list
>>>>
>>>> // should el1 be unchanged ? (IMHO, yes)
>>>> sc_event_and_list el2 = el1 & e4;
>>>> sc_assert( el1.size() == 3 && el2.size() == 4 ); // (1)
>>>>
>>>> // should el1 be unchanged after wait? (IMHO, yes)
>>>> wait( el1 );
>>>> sc_assert( el1.size() == 3 ); // (2)
>>>>
>>>> With the current OSCI PoC simulator, the assertions (1) and (2) would
>>>> NOT hold.
>>>>
>>>> On the other hand, changing operators &,| and the
>>>> wait()/next_trigger() functions to make an explicit copy internally
>>>> comes with quite some runtime overhead: In a quick and dirty test
> I've
>>>> measured up to +30% for naïve enforcing (1)+(2) and +7% for enforcing
>>>> (2) only.
>>>>
>>>> Opinions?
>>>>
>>>> Greetings from Oldenburg,
>>>> Philipp
>>>>
>>>> On 28/09/10 13:41, john.aynsley@doulos.com wrote:
>>>>> Tor, All,
>>>>>
>>>>> I think we have a consensus that we want to make the change such that
>
>>>>> sc_event_and/or_list can be instantiated as proper objects and act as
>
>>>>> containers for events that can be passed to wait() and next_trigger()
>
>>> (at
>>>>> least).
>>>>>
>>>>> Would you (or someone else) please make a specific proposal for
>> classes
>>>
>>>>> sc_event_and_list and sc_event_or_list to go into the LRM. I started
>>>>> prototyping this months back and ran into some C++ issues. As I
> recall
>>
>>>>> from my experiments, the prototype wait(sc_core::sc_event_or_list&)
>>>>> currently precludes having something like wait(all_events()); where
>>>>> all_events() returns an event list by value. So we need a set of
>>>>> signatures for the constructor(s)/operators of the event list classes
>
>>> that
>>>>> work with the current signatures of wait/next_trigger.
>>>>>
>>>>> John A
>>>>
>>>
>>>
>>
>>
>
>

-- 
Philipp A. Hartmann
Hardware/Software Design Methodology Group
OFFIS Institute for Information Technology
R&D Division Transportation · FuE-Bereich Verkehr
Escherweg 2 · 26121 Oldenburg · Germany
Phone/Fax: +49-441-9722-420/282 · PGP: 0x9161A5C0 · http://www.offis.de/
-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Tue Oct 5 04:34:04 2010

This archive was generated by hypermail 2.1.8 : Tue Oct 05 2010 - 04:34:05 PDT