Philipp, Everybody,
I have worked through Philipp's sc_vector proposal. I will share some
examples with you, starting with the most basic features, then showing the
clever cases. I have a few comments/questions, highlighted below.
Firstly, you can construct vectors of modules, ports, exports, and
channels, e.g.
sc_vector<my_module> my_vec; // vector-of-modules
sc_vector<sc_inout<int> > ports; // vector-of-ports
sc_vector<sc_port<i_f> > ports; // vector-of-user-defined
ports
sc_vector<sc_signal<int> > sigs; // vector-of primitive channels
Secondly, you can set the size of the port either at construction time or
deferred until later:
Either
: ports("ports", N) // "ports" used as the prefix for the
string name,
or
: ports("ports")
{
ports.init(N); // N is the size of the vector - cannot
be modified once it has been set
Thirdly, you can access the vector elements using the size(), operator[],
and at() methods, e.g.
for (unsigned int i = 0; i < ports.size(); i++)
ports[i]->method();
m1->ports[i].bind( sigs[i] ); // ports and sigs are both
sc_vectors
We are constraining the elements to be sc_objects. In each case, the
elements of the sc_vector are all children of the containing module or
process instance, so are picked up by
std::vector<sc_object*> children = obj->get_child_objects();
This is all very natural and as-expected.
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?
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?
It is possible to extract a std::vector of elements from any sc_vector,
e.g.
std::vector<sc_object*> elements;
elements = ports.get_elements();
elements = sc_view(initiator_vec,
&Initiator1::port).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?
Thanks,
John A
-- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Tue Nov 9 05:06:40 2010
This archive was generated by hypermail 2.1.8 : Tue Nov 09 2010 - 05:06:43 PST