On 10/11/10 19:26, Andy Goodrich wrote:
> sc_unnamed seems like a good change regardless if things trickle into the LRM or not. Also, I think it should go into the LRM.
I agree, that this should probably go to the LRM.
The Boost placeholders are not yet mentioned in the LRM, though. But
maybe it's enough to refer to them similar to the current definition of
sc_bind, which more or less refers to Boost directly as well. Or simply
describe the effect as something like:
namespace sc_unamed {
/* implementation-defined */ _1;
// ...
/* implementation-defined */ _9;
}
In the namespace 'sc_unamed' -- 1 or 2 'n' here? --, the
implementation shall provide placeholders _1, ... _9, that can be
used to defer the binding of function arguments given to sc_bind.
The definition of these placeholders is implementation-defined.
Example:
struct foo {
int bar( int );
};
foo f;
sc_bind( &foo::bar, f, sc_unamed::_1 )( 42 ); // calls f.bar(42)
Greetings from Oldenburg,
Philipp
> On Nov 10, 2010, at 5:20 AM, john.aynsley@doulos.com wrote:
>
>> Philipp, Andy,
>>
>> my_vec_of_modules2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unamed::_1, sc_unamed::_2 ) );
>>
>> works.
>>
>>
>> Do we need sc_unamed added to the LRM? Do we want to change it to sc_unnamed? Or to something else? Does anything else need adding from the revised boost stuff in SystemC?
>>
>> John A
>>
>>
>>
>> From: "Philipp A. Hartmann" <philipp.hartmann@offis.de>
>> To: john.aynsley@doulos.com
>> Cc: systemc-p1666-technical@eda.org
>> Date: 09/11/2010 18:36
>> Subject: Re: sc_vector proposal
>>
>>
>>
>>
>> John,
>>
>> thanks for your comments and your nice review of the proposal.
>> Please find my answers to your questions embedded below.
>>
>> On 09/11/10 14:06, john.aynsley@doulos.com wrote:
>>
>> [snip basic feature description]
>>
>>> Then we add a few wrinkles. It is possible to bind a vector-of-ports to a
>>> vector-of-channels directly, with no explicit loop, e.g.
>>>
>>> module_inst->ports.bind( sigs ); // ports is a vector-of-ports
>>> and sigs is a vector-of-sigs
>>>
>>> Very nice. It is also possible to bind just a subset of the
>>> vector-of-ports, then come back for another pass later:
>>>
>>> typedef sc_vector<sc_inout<int> > port_type;
>>> port_type::iterator it;
>>>
>>> // Bind upper half of ports vector to hi_sigs
>>> it = module_inst->ports.bind( hi_sigs.begin(), hi_sigs.end() ); //
>>> hi_sigs.size() < ports.size()
>>>
>>> // Bind lower half of ports vector to lo_sigs
>>> it = module_inst->ports.bind( lo_sigs.begin(), lo_sigs.end(), it);
>>> // Notice binding starts from position 'it' within ports vector
>>>
>>> The above syntax - having bind return the position of the 1st unbound
>>> element - seems a little arcane to me. Are we all okay with it?
>>
>> Returning the "last" iterator follows the approach known from some of
>> the iterator-based STL algorithms, like std::copy or std::transform.
>> To me, this is the simplest way to define the interface. But I'm free
>> to any suggestions in that area.
>>
>> Note, that the user can of course ignore the return value of the bind
>> function and use an explicit iterator for the second bind offset:
>>
>> module_inst->ports.bind( lo_sigs.begin(), lo_sigs.end()
>> , module_inst.begin() + hi_sigs.size() );
>>
>> If we feel, that this iterator-based interface is too complex to
>> understand or describe, we can also drop it from the standard. Manually
>> looping over parts of the vectors is still possible and maybe easier to
>> explain:
>>
>> port_type it = module_inst.ports.begin();
>>
>> for( int i=0; i<hi_sigs.size(); ++i, ++it );
>> it->bind( hi_sigs[i] );
>>
>> for( int i=0; i<lo_sigs.size(); ++i, ++it );
>> it->bind( lo_sigs[i] );
>>
>> The returned iterator from the bind() calls can also be used to check,
>> if all elements have been bound:
>>
>> sc_assert( it == module_inst->ports.end() ); // all bound
>>
>>> But sometimes, rather than having a vector-of-ports, you might have a
>>> vector-of-modules each containing a single port. In this case it is
>>> possible to treat these ports distributed across multiple modules as one
>>> vector, using sc_view. For example:
>>>
>>> struct Initiator1: sc_module
>>> {
>>> sc_port<i_f> port;
>>> ...
>>> struct Target: public sc_module, private i_f
>>> {
>>> sc_export<i_f> xp;
>>> ...
>>>
>>> sc_vector<Initiator1> initiator_vec;
>>> sc_vector<Target> target_vec;
>>>
>>> sc_view(initiator_vec, &Initiator1::port).bind( sc_view
>>> (target_vec, &Target::xp) );
>>>
>>> In the above
>>> sc_view(initiator_vec, &Initiator1::port) creates a
>>> vector-of-ports
>>> sc_view(target_vec, &Target::xp) creates a vector-of-exports
>>> .bind() does a vector-to-vector bind
>>>
>>> The semantics are very nice, but I am not particularly happy with the name
>>> sc_view, because this is not suggestive of what is actually happening,
>>> that is, gathering together a vector from a set of elements distributed
>>> across another vector. Is there a precedent for the name sc_view, Phillip?
>>> How about something like sc_gather or sc_make_vector or sc_vectorize
>>> instead?
>>
>> I don't have a strong feeling about the name sc_view. Especially, since
>> I'm not particularly talented in given well-descriptive names.
>>
>> The chosen name sc_view originates from the database world, where a
>> view is some kind of a "stored query", which can then be manipulated
>> more easily. See e.g. http://en.wikipedia.org/wiki/Database_view
>>
>> The cause is more or less the same here: With sc_view, you pre-select
>> a given member of the vector, without actually creating a "real"
>> sc_vector object. Only accesses via this "view" are forwarded to the
>> _member object_ of the underlying vector element, instead of the element
>> itself.
>>
>> I could think of other names like
>> sc_member[_view]()
>> sc_children()
>> sc_select[ion]()
>>
>> But as I said, I'm not really good at this. ;-)
>>
>> [snip get_elements]
>>
>>> Finally, in the special case of a vector-of-modules, it is possible to
>>> pass extra arguments to the module constructor, e.g.
>>>
>>> struct my_module: sc_module
>>> {
>>> my_module(sc_module_name n, string weird_arg ) {...}
>>> ...
>>> ...
>>> sc_vector<my_module> my_vec;
>>>
>>> struct my_module_creator
>>> {
>>> my_module_creator( string arg ) : weird_arg(arg) {}
>>>
>>> my_module* operator() (const char* name, size_t)
>>> {
>>> return new my_module(name, weird_arg );
>>> }
>>> string weird_arg;
>>> };
>>> ...
>>> my_vec.init(N, my_module_creator("The Creator"));
>>>
>>> This works, but creating the function object feels like having to jump
>>> through hoops. I think regular users are going to find it confusing. Can
>>> we do any clever tricks to make it easier to use?
>>
>> The reason for the complexity is two-fold:
>>
>> - The Creator needs to receive the designated name for the element
>> (and, for convenience, the current index)
>> - The Creator may need to have a local state e.g. to store
>> or generate additional arguments.
>>
>> To use a custom Creator, the easiest/best solution depends on the
>> current situation. If you have some globally accessible way to chose
>> your additional arguments, you may get away with a plain function:
>>
>> my_module* my_module_creator_func( const char* name, size_t i )
>> {
>> return new my_module( name, WEIRD_ARG );
>> }
>> my_vec.init(N, my_module_creator_func );
>>
>> Another quite simple way is to define a local member function in the
>> surrounding module and use sc_bind for the creator. This way, you can
>> access the whole state of the owning module during creation and do all
>> kinds of nice stuff, like binding transport functions etc:
>>
>> SC_MODULE(parent)
>> {
>> sc_vector< my_module > my_vec;
>> std::string weird_arg;
>>
>> // member function as creator to use with sc_bind()
>> my_module* init_element( const char* n, unsigned i )
>> {
>> my_module * mod = new my_module( n, weird_arg );
>> mod->register_invalidate_direct_mem_ptr( this,
>> &parent::invalidate_direct_mem_ptr, i );
>> return mod;
>> }
>>
>> SC_CTOR(parent)
>> {
>> // use sc_bind, "this" + placeholders as creator
>> // note: you may need to use sc_unamed::_1 in SystemC 2.3
>>
>> my_vec.init( N, sc_bind( &parent::init_element, this, _1, _2 ) );
>> }
>> };
>>
>> To me, the above is as easy as it can get in current C++.
>> Of course, C++0x lambdas will rock here in the future:
>>
>> std::string weird_arg;
>> my_vec.init( N,
>> [&]( const char*, size_t i)
>> { return new my_module( n, weird_arg ); }
>> );
>>
>> I'm of course interested in any simpler approach to custom element
>> creation. But I've spent some time on this issue and could not come up
>> with any easier solution for supporting arbitrary constructor signatures.
>>
>> I can see that this is not really part of C++/SystemC 101, but at
>> least it's consistent with other functor APIs in C++, like Compare (in
>> std::map and std::sort) or Function in std::for_each.
>>
>> Greetings from Oldenburg,
>> Philipp
>>
>> --
>> 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/
>>
>>
>>
>
>
-- 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 Wed Nov 10 14:52:23 2010
This archive was generated by hypermail 2.1.8 : Wed Nov 10 2010 - 14:52:24 PST