Jump to content

Binding sca_in ports in a vector


Recommended Posts

Hi all,

 

I have been trying to do something that I'm not sure it's possible. I have some TDF modules that are connected to each other by sca_in and sca_out ports. All of this modules will have at least one of each in/out ports. My idea was that maybe some of them will have some extra in/out ports. For example, if I want two TDFs outputs to go to one TDF input, it is not possible using just one port. Instead, those TDF modules would have a vector of sca_in's so, if I need an extra port, this will be initialized and bound to a signal.

 

All this is already done and compiling. My problem is that when I initialize and bind that new port, it is not specifically assigned to a TDF so I get this error: "Error: (E100) port specified outside of module: port 'sca_tdf_in_0' (sc_port_base)". I understand the reason of this error, but I would like to know if it is possible to assign this port to its TDF.

 

Here I will show my code, maybe it's helpful.

 

class 'gen' is a generator of doubles. It sends an increasing double through its 'out' port.

class 'pass' is just getting whatever comes from its 'in' port and sending it out through its 'out' port.

class 'waste' is where the 'magic' may be. Receives whatever which is coming from 'pass'.

 

main.cpp:

#include <systemc-ams>
#include "gen.h"
#include "waste.h"
#include "pass.h"

int sc_main(int argc, char *argv[])
{
  gen g("g");
  pass p("p");
  pass p2("p2");
  waste w("w");

  sca_tdf::sca_signal<double> sig("sig");
  sca_tdf::sca_signal<double> sig2("sig2");
  sca_tdf::sca_signal<double> sig3("sig3");

  g.out(sig);

  p.in(sig); // Both 'p' and 'p2' receive from the same signal 'sig'.
  p2.in(sig); // This works perfectly.

  p.out(sig2); // The out port of both are bound to different signals.
  p2.out(sig3); // Otherwise, I would get an error.

  w.in(sig2); // This is a normal binding (to 'p' and 'sig') that works just fine.
  w.bind(sig3); // Here's where I want to implement my idea. Look at 'waste.h'

  sc_core::sc_start(500.0, sc_core::SC_MS);
  sc_core::sc_stop();

  return 0;
};

 waste.h:

#ifndef WASTE_H
#define WASTE_H

#include <systemc-ams>
#include <vector>

SCA_TDF_MODULE(waste) {

  sca_tdf::sca_in<double> in; // Main 'in' port
  std::vector<sca_tdf::sca_in<double>*> secondary_ins; // Vector of extra 'in' ports
  std::vector<sca_tdf::sca_in<double>*>::iterator it;  // Iterator
  int ins; // Number of extra 'in' ports

  SCA_CTOR(waste)
  {
    it = secondary_ins.begin();
    ins = 0;
  }

  // This initializes the extra 'in' port and adds it to the vector
  // Here should go the 'assignation' if it is possible.
  void new_in()
  {
    sca_tdf::sca_in<double> *sec_in = new sca_tdf::sca_in<double>();
    secondary_ins.insert(it, sec_in);
    ins++;
  }

  // This method is called in 'main.cpp' and it might assign
  // the new 'in' port to the given signal
  void bind(sca_tdf::sca_signal<double> &s)
  {
    new_in();
    secondary_ins.at(secondary_ins.size()-1)->bind(s);
  }

  void processing()
  {
    double d = in.read();
    std::cout << name() << " - main_in : " << d << std::endl;
    for(int i=0; i<secondary_ins.size(); i++)
    {
      double d2 = secondary_ins.at(i)->read();
      std::cout << name() << " - sec_in(" << i << "): " << d2 << std::endl;
    }
  }

};

#endif

So basically that's it. Any ideas? Is it even possible?

 

Thanks a lot :)

Link to comment
Share on other sites

You need to create the ports while the correct instantiation context is established.  Since you can't do so during construction of the module, you need to defer it to the 'before_end_of_elaboration()' callback of SystemC.  For this matter, you need to temporarily store the signals, in e.g. a vector of pointers.  See the following (untested) sketch:

SCA_TDF_MODULE(waste) {
 
sca_tdf::sca_in<double> in; // Main 'in' port

sc_core::sc_vector< sca_tdf::sca_in<double> > secondary_ins; // prefer sc_vector over vectors of pointers
 
SCA_CTOR(waste)
  : in("in"), secondary_ins( "secondary_in" )
{
}

// temporarily store signal pointer 
void bind(sca_tdf::sca_signal<double> &s)
{
  sc_assert( sc_core::sc_get_status() == sc_core::SC_ELABORATION );
  secondary_signals.push_back( &s );
}
 
void processing()
{
//...
}
 
private:

// actually do the binding
virtual void before_end_of_elaboration()
{
  // create the secondary ports
  secondary_ins.init( secondary_signals.size() );
  // bind the ports
  for( std::size_t i = 0; i < secondary_ins.size(); ++i )
    secondary_ins[i].bind( *secondary_signals[i] );
  // cleanup temporary signals
  secondary_signals.clear();

  // be nice and call the base class callback
  sca_tdf::sca_tdf_module::before_end_of_elaboration();
}

  // temporarily hold additional inputs during elaboration
  std::vector< sca_tdf::sca_signal<double>* > secondary_signals;
};

Hope that helps,
  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...