Jump to content
T. Zimmermann

Initialization of nested sc_vector< sc_vector< > >

Recommended Posts

Hi,

 

I need a two dimensional array of SystemC-AMS objects. I read that it should be possible to use nested sc_vector to realize a two dimensional grid of SystemC objects. Therefore, I defined it as in the following code segement:

sc_core::sc_vector< sc_core::sc_vector< sca_module > >  element;

Now, I want to initialize each elememt, but I don't know how to call the init()-function to set the size.

Share this post


Link to post
Share on other sites

You can use a custom "creator" to initialize elements of a vector with custom constructor parameters - here the inner vector.  Something like this (assuming you have lambda support available):

  auto element_creator = [](const char* nm, size_t) // optional, depending on the "real" value type
    { return new sca_module(nm); }; 
 
  size_t inner_size = 42; // adjust for your needs, could also be a vector of sizes

  element.init( outer_size, [&](const char* nm, size_t)
    { return new sc_vector<sca_module>( nm, inner_size, element_creator ); }
  );

If you don't have lambdas in your environment, you need to put the functionality in a custom function, e.g.

static sc_vector<sca_module>* element_vector_creator(size_t size, const char* name, size_t)
  { return new sc_vector<sca_module(name, size); }

// using sc_bind to pass in the size - placeholders needed for actual call
element.init( outer_size, sc_bind(element_vector_creator, inner_size, sc_unnamed::_1, sc_unnamed::_2) ); 

Hope that helps,

  Philipp

Share this post


Link to post
Share on other sites

Philipp, thanks for the quick response.

 

I implemented the following code in the module.h file :

class module_model : public sc_core::sc_module
{
public:
  module_model( sc_core::sc_module_name name, int no_of_y_module=1, int no_of_x_module=1);
  ~module_model();
  static sc_core::sc_vector< sca_element_model >* element_vector_creator(size_t size, const char* name, size_t);
private: 
  sc_core::sc_vector< sc_core::sc_vector< sca_element_model > >  element;
}

 and in the module.cpp file:

In the module.cpp file:

sc_core::sc_vector< sca_element_model >* module_model::element_vector_creator(size_t size, const char* name, size_t) {
  return new sc_core::sc_vector< sca_element_model >( name, size);
}

Afterwards, I call the element.init() function in the constuctor of the module class:

module_model::module_model( sc_core::sc_module_name name, int no_of_y_module, int no_of_x_module){
 // Create elements
 element.init( no_of_y_module, sc_bind( element_vector_creator, no_of_x_module, sc_unnamed::_1, sc_unnamed::_2) );

 // Initialize elements

 // Interconnect elements
}

Now, the compiler throws the error that the sc_bind()-function is not defined and the 'sc_unnamed' is no class or namespace.

 

Has the sc_bind()-function implemented by the user?

Share this post


Link to post
Share on other sites

You need to add the preprocessor symbol SC_INCLUDE_DYNAMIC_PROCESSES to your build setup to enable sc_bind  in SystemC,  e.g. on the compilar command-line: -DSC_INCLUDE_DYNAMIC_PROCESSES.

hth,

  Philipp

 

Thank you Philipp,

now the project compiles without errors and I get the grid of modules e.g. the modules are named <grid1.vector_0_0_0>, <grid1.vector_0_0_1>, <grid1.vector_0_0_2>, <grid1.vector_0_1_0>, <grid1.vector_0_1_1>, <...>

Can you give me a tip, how I can call functions of the individual elements, for example in the nested loop to initialize the elements:

for (int i = 0; i < no_of_y_element; i++) {
  for (int j = 0; j < no_of_x_element; j++) {
    grid1[j][i].foo() // <-- the function call does not work
  }
}

Share this post


Link to post
Share on other sites

Hello Thomas,

 

 

Thank you Philipp,

now the project compiles without errors and I get the grid of modules e.g. the modules are named <grid1.vector_0_0_0>, <grid1.vector_0_0_1>, <grid1.vector_0_0_2>, <grid1.vector_0_1_0>, <grid1.vector_0_1_1>, <...>

Can you give me a tip, how I can call functions of the individual elements, for example in the nested loop to initialize the elements:

for (int i = 0; i < no_of_y_element; i++) {
  for (int j = 0; j < no_of_x_element; j++) {
    grid1[j][i].foo() // <-- the function call does not work
  }
}

 

 

If this snippet corresponds to your minimal example, then you are accessing the elements on the wrong object. Your variable "grid1" is of type sc_core::sc_module. It contains a private member variable "element", which is your two-dimensional vector array of type sc_core::sc_vector<sc_core::sc_vector<sca_element_model> >. If you want to access the vector from outside the grid1 module, you have to declare the member variable as public. Then, you should be able to call the functions on the individual elements using:

grid1.element[j][i].foo()

I hope this fixes your error.

 

As a side note: The SystemC AMS extensions LRM reserves all identifiers with prefix sca_ and SCA_ for itself. You should therefore avoid using the sca_ prefix for your own class, function, variable, and preprocessor macro definitions even if you put them into an own namespace. Simply, choose a different prefix instead, e.g.: sca_element_model -> my_element_model

 

Regards,

 

Torsten Maehne

Share this post


Link to post
Share on other sites

Hi,

regarding my last post.
Is it possible to call the constructor 'sca_element_model( sc_core::sc_module_name name, double r_value = 1.0)' within the function 'element_vector_creator()' and pass values to the variable 'name' and 'r_value' (second parameter of the constructor). How is this implemented? How is the construct in the C++ standard called?

Share this post


Link to post
Share on other sites

Philipp in his post from 2017-09-22 already provided you with the answer: To create your two-dimensional array of modules, you actually need two element creators:

  • One for the outer vector, which will create entire rows of modules: This is the one you have implemented with you  module_model::element_vector_creator(size_t size, const char* name, size_t) member function.
  • Another one for the inner vector, where you will allocate the individual modules. This is what Philipp demonstrated with his element_creator Lambda function. He just allocated the module and passed the module's base name as an argument. However, you can also pass any additional arguments to the constructor of the module, e.g., your argument r_value. The arguments, you pass to the constructor can be either hard-coded or calculated based on the current index for the element to initialise (i.e., the second argument passed to the element_creator, which is of type std::size_t). If you also need the current index of the outer vector, you can capture the variable representing that outer index for use within the lambda (check a book on Modern C++ discussing Lambdas for details).

You can find more information on sc_vector in clause 8.5 of IEEE Std 1666-2011. However, more accessible might be the paper "Automated SystemC Model Instantiation with modern C++ Features and sc_vector" by Ralph Goergen, Philipp Hartmann, and Wolfgang Nebel from DVCon-Europe 2015:

 DVCon_Europe_2015_TA2_4_Paper.pdf

and the "An Introduction to IEEE 1666-2011, the New SystemC Standard" video tutorial by John Ainsley, David C. Black, and Tor Jeremiassen:

http://videos.accellera.org/ieee16662011/index.html

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×