Jump to content

array of sc_vector : binding and assembling help


kaushalyjain

Recommended Posts

Hi,

 

So I have a submodule having an array of boolean input ports.

 

Now in the top module, I define an sc_vector of the submodule type. Also, I define an array of sc_vector signals to be bound to. 

 

Questions:

Can I use an array of sc_vectors? Any conventions on using them? 

eg: can I write 

sc_vector < sc_signal <bool> > operand_vec[max_operands];

If no, then is there any work around for this?

 

Also, I now need to assemble and bind these ports:

The code below doesn't seem to work. 

 

Both the stack_cnt_vec and operand_vec are initialized properly.

for(int i=0;i<max_operands;i++){
operand_vec[i].init(10);
}
for(int i=0; i<10; i++) {

sc_assemble_vector( stack_cnt_vec, &StackController::operands[i]).bind( operand_vec[i] );

}

Thanks a lot for your time.

 

Link to comment
Share on other sites

Before trying to answer your question, can you provide some more information?

  • Why don't you use an sc_vector of boolean input ports instead of an array in your submodule?
  • How do you want to wire up the top-level module signals with the submodule signals (indexwise)?
  • Can you provide a stripped-down but compilable code example? (add comments for the missing parts)

In general, it is possible to have both an array of sc_vectors as well as an sc_vector of sc_vectors.  If you don't want to use a custom "creator function", you just need to take care of the proper initialisation yourself.

sc_assemble_vector might not be of much help (depending on the intended topology).
You can still do the binding manually in a nested loop over both dimensions, of course.

 

/Philipp

Link to comment
Share on other sites

Thank you Philip for the prompt answer/suggestions:

Appending my requirements through a sample code written/edited by you only (taken from OFFIS website): 

 

Desired topology: Each of the in[3] ports in the 4 submodules need to be bound with the corresponding in_vec[3] vector

Hence, binding looks something like this

module.in_vec_0[0:2] <bound to> sub_module.in[0:2]
This is also shown in the code below in for loop commented out and works fine
 

1) So, in my design: my submodule has a multi-port (currently defined here as in[3] array) 

Now, if I define input ports as sc_vector (as seen in commented portion of submodule), how do I bind the vector of vectors? Could you please show with this example? 

 

2) Also, is there a better way to bind these ports using sc_assemble_vector? 

#include "systemc.h"


SC_MODULE( sub_module )
{
    sc_in <sc_uint <16> > > in[3];
    SC_CTOR(sub_module) {}
 //possible alternative: but how do i bind this using sc_assemble_vector
 // sc_vector<sc_in<sc_uint <16> > > in;
 // SC_CTOR(sub_module):in(3) {}
};

SC_MODULE( module )
{
  // vector of sub-modules
  sc_vector< sub_module > m_sub_vec;

  // vector of ports
  sc_vector < sc_in<sc_uint<16> > > in_vec[3];

  module( sc_core::sc_module_name, unsigned n_sub )
    : m_sub_vec( "sub_modules", n_sub ) // set name prefix, and create sub-modules
    // , in_vec()                       // use default constructor
    // , in_vec( "in_vec" )             // set name prefix
  {
    // delayed initialisation of port vector
    // here with default prefix sc_core::sc_gen_unique_name("vector")
    
    // bind ports of sub-modules -- sc_assemble_vector
    for(unsigned i=0;i<3;i++){
    
    in_vec[i].init( n_sub );
	
	cout << "Size of vector " << m_sub_vec.size()<<endl;
    	
     //can I use sc_assemble_vector in this case?
     //sc_assemble_vector( m_sub_vec, &sub_module::in).bind( in_vec );	
  
    //the following element by element binding works, but is there a neater way?
    /*	for(unsigned j=0;j<m_sub_vec.size();j++){
    		m_sub_vec[j].in[i](in_vec[i][j]);
    	}
    */	
    }
  }
};

int sc_main(int , char* [])
{
  module m("dut", 4);

  std::vector<sc_object*> children = m.get_child_objects();

  for (size_t i=0; i<children.size(); ++i )
    cout << children[i]->name() << " - "
         << children[i]->kind()
         << endl;

  cout << "Program completed" << endl;
  return 0;
}
Link to comment
Share on other sites

Yes, if you use an sc_vector in your sub-module

 //possible alternative: but how do i bind this using sc_assemble_vector
 sc_vector<sc_in<sc_uint <16> > > in;
 SC_CTOR(sub_module)
   :in("in",3)  // note the required name prefix, naming objects is good style anyway
 {}
and an sc_vector of sc_vectors for the top-level ports (or a flattened sc_vector and then use the iterator-based binding API), you can use sc_assemble_vector to bind the whole hierarchy in one call (outside of the loops):

  // vector of ports
  sc_vector<sc_vector < sc_in<sc_uint<16> > > > in_vec;

  // ... and in the constructor
    sc_assemble_vector( m_sub_vec, &sub_module::in).bind( in_vec );
If you want it even more neatly, use a "custom creator" to initialize the two-dimensional port vector:

// creator function (beware of the hard-coded size 3)
static sc_vector<sc_in<sc_uint<16> > >*
  create_in_vector(const char* nm, size_t )
    { return new sc_vector<sc_in<sc_uint<16> > >(nm,3); }

// constructor - look, ma', no loops!
module( sc_core::sc_module_name, unsigned n_sub )
   : m_sub_vec( "sub_modules", n_sub ) // set name prefix, and create sub-modules
   , in_vec( "in_vec" ) // set name prefix, no init yet
{
  in_vec.init(n_sub, create_in_vector); // use custom creator 
  
  // push it even further: use a C++11 lambda as a creator
  // in_vec.init(n_sub
  //            , [](const char* nm, size_t) // lambda function
  //                  { return new sc_vector<sc_in<sc_uint<16> > >(nm,3); } );

  // do the binding
  sc_assemble_vector( m_sub_vec, &sub_module::in).bind( in_vec );  
}
Hope that helps,

  Philipp

Link to comment
Share on other sites

Thanks again Philip. That really helped. 

 

So, if we are using a sc_vector of sc_vectors, we compulsorily need to create a custom creator function/lambda function for initializing such sc_vector of sc_vectors ? 

 

A naive question, but where do we need custom creator functions in general? Also, do they have to be static (like in this case).

 

Also, in the LRM, page 405 (8.5.5) the following example uses a custom creator function and does it using Boost bind. How is it different from this case?

 

While using the custom creator function for initialization as in your answer, can we pass the arguments to the function (char* , size_t) ? I tried doing it but it threw an error.

// Case 2: creator is a member function
my_module* my_module_creator_func( const char* name, size_t i )
{
return new my_module( name, "value_of_extra_arg" );
}
Top(sc_module_name _name, int N)
{
// Initialize vector passing through constructor arguments to my_module
// Case 1: construct and pass in a function object
vector1.init(N, my_module_creator("value_of_extra_arg"));
// Case 2: pass in a member function using Boost bind
vector2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unnamed::_1, sc_unnamed::_2 ) );

Link to comment
Share on other sites

So, if we are using a sc_vector of sc_vectors, we compulsorily need to create a custom creator function/lambda function for initializing such sc_vector of sc_vectors ? 

 

No, you can also explicitly init() the sub-vectors in a loop, as you did before. 

 

A naive question, but where do we need custom creator functions in general?

 

A creator function is only strictly needed if you are forced to call a custom constructor for the vector elements, e.g. with additional parameters.  In the vector of vector case, this can be the size of the vector.

 

Also, do they have to be static (like in this case).

 

Also, in the LRM, page 405 (8.5.5) the following example uses a custom creator function and does it using Boost bind. How is it different from this case?

 

 

You can pass any C++ entity that can be called with a signature (const char*, size_t) and returns a pointer of the correct vector member type.

 

The sc_bind example is a convenient way to pass additional information to the creator.  By binding a member function, you can for example access the members of the module within the creator.

 

While using the custom creator function for initialization as in your answer, can we pass the arguments to the function (char* , size_t) ? I tried doing it but it threw an error.

// Case 2: creator is a member function
my_module* my_module_creator_func( const char* name, size_t i )
{
return new my_module( name, "value_of_extra_arg" );
}
Top(sc_module_name _name, int N)
{
// Initialize vector passing through constructor arguments to my_module
// Case 1: construct and pass in a function object
vector1.init(N, my_module_creator("value_of_extra_arg"));
// Case 2: pass in a member function using Boost bind
vector2.init(N, sc_bind( &M::my_module_creator_func, this, sc_unnamed::_1, sc_unnamed::_2 ) );

 

In both examples you have quoted after your question, you see the options to pass additional information to the creator.  In case 1, it is an explicit constructor argument passed to the my_module_creator function object, in case 2, it's the this pointer, passed to sc_bind. With a C++ lambda, you can use the various "capturing" mechanisms.

 

/Philipp

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...