Jump to content
PeraKojot

Custom channel based on a sc_fifo

Recommended Posts

Hi all,
I'm a SystemC newbie and I'm trying to build a channel having the same properties as a sc_fifo channel with some parameters integrated like ID (integer value). I tried to define new interfaces derived from sc_fifo_in_if and sc_fifo_out_if implementing my new functions (getters and setters to my integer values) but I'm struggling to get them work since couple of days. The idea is very simple, but I have no clue how to get out with tris problem. Any help is welcome.

Share this post


Link to post
Share on other sites

[…] but I'm struggling to get them work since couple of days. The idea is very simple, but I have no clue how to get out with tris problem. Any help is welcome.

 

In order to give you any suggestions about your "problem", please try to post some more details. 

  • What kind of "problem" do you face?
  • What are your compiler errors, if any?
  • Can you post a stripped-down code example, showing the relevant parts of the code (and preferably being self-contained and ready to compile)?

 

One good starting point to learn about defining your own (primitive) channel can be found on the Doulos website.

 

(Season's) Greetings from Oldenburg,

  Philipp

Share this post


Link to post
Share on other sites

Thank you Philipp for your quick answer. I have finally managed to get it working, but not with the way I wanted. The main problem was in calling functions through ports where I used . instead of -> notation. Here is my solution:

 

Interface:

#ifndef FIFO_IF_H_
#define FIFO_IF_H_
#include "systemc.h"

template <class T>
class fifo_if_in: virtual public sc_interface, virtual public sc_fifo_in_if<T>
{
public:
	//fifo_if_in();
	virtual void setId(int id)=0;
	virtual int getId() const=0;

};

template <class T>
class fifo_if_out: virtual public sc_interface, virtual public sc_fifo_out_if<T>
{
public:
	//fifo_if_out();
	virtual void setId(int id)=0;
	virtual int getId() const=0;

};
#endif /* FIFO_IF_H_ */

Channel:

#ifndef FIFO_ID_H_
#define FIFO_ID_H_
#include "fifo_if.h"
#include "systemc.h"

template <class T>
class fifo_id: public sc_module, public fifo_if_in<T>, public fifo_if_out<T>
{
public:
	fifo_id(sc_module_name sc_name,int id):sc_module(sc_name),id(id)
{
}
	virtual void setId(int id){this->id = id;};
	virtual int getId() const {return id;};
	virtual int num_available() const {return p_fifo.num_available();}
	virtual void read( T& t) {p_fifo.read(t);};
	virtual T read(){return p_fifo.read();};
	virtual bool nb_read( T& t){return p_fifo.nb_read(t);};
	virtual const sc_event& data_written_event() const {return p_fifo.data_written_event();};
	virtual int num_free() const {return p_fifo.num_free();};
	virtual bool nb_write( const T& t){return p_fifo.nb_write(t);};
    virtual const sc_event& data_read_event() const{return p_fifo.data_read_event();};
    virtual void write( const T& t){p_fifo.write(t);};
private:
	sc_fifo<T> p_fifo;
	int id;
};

Test module 1 (header file):

#ifndef FIFO_ID_TEST_H_
#define FIFO_ID_TEST_H_
#include "fifo_if.h"

SC_MODULE(fifo_id_test){
		sc_port<fifo_if_in<int> >  in2;
		sc_port<fifo_if_out<int> > out2;

	void fifo_id_test_func();

	SC_CTOR(fifo_id_test){
		SC_THREAD(fifo_id_test_func);
	}
};

#endif /* FIFO_ID_TEST_H_ */

Test module 1 (.cpp file)

#include "fifo_id_test.h"

void fifo_id_test::fifo_id_test_func(){
	int val;
	while(1){
		val = in2->read();
		cout << "Read from input fifo:"<<val<<endl;
		cout << "Processor id is:"<<in2->getId()<<endl;
		out2->write(val);
		cout << "Write to output fifo:"<<val<<endl;
		cout << "Processor id is:"<<out2->getId()<<endl;
	}
}

Test module 2 (.h file)

#ifndef FIFO_MUX_TEST_H_
#define FIFO_MUX_TEST_H_

#include "systemc.h"

SC_MODULE(fifo_mux_test){
	sc_fifo_out<int> out1;
	sc_fifo_out<int> out2;
	sc_fifo_in<int> in1;

	void fifo_mux_func1();
	void fifo_mux_func2();
	void fifo_mux_func3();

	SC_CTOR(fifo_mux_test){
		SC_THREAD(fifo_mux_func1);
		SC_THREAD(fifo_mux_func2);
		SC_THREAD(fifo_mux_func3);
	}

};

Test module 2 (.cpp file):

#include "fifo_mux_test.h"
void fifo_mux_test::fifo_mux_func1(){
	int val1=0;
	while(1)
	{
		wait(10,SC_NS);
		out1.write(val1);
		cout << "Write "<<val1<<" to fifo1"<<endl;
		val1++;

	}
}

void fifo_mux_test::fifo_mux_func2(){
	int val1=0;
	while(1)
	{
		wait(20,SC_NS);
		out2.write(val1);
		cout << "Write "<<val1<<" to fifo2"<<endl;
		val1++;

	}
}

void fifo_mux_test::fifo_mux_func3(){
	int val;
	while(1){
		in1.read(val);
		cout << "Read "<<val<<" from fifo out"<<endl;
	}
}

And the main function:

#include "fifo_mux_test.h"
#include "fifo_id.h"
#include "fifo_id_test.h"

int sc_main(int argc, char* argv[]){
	cout<<"Starting"<<endl;
	fifo_mux_test fmuxt("fifo_mux_test");
	fifo_id<int> scf1("scf1",1),scf3("scf3",3);
	fifo_id<int> scf2("scf2",2);
	fifo_id_test fidt("fifo_id_test");
	fidt.in2(scf1);
	fidt.out2(scf3);
	fmuxt.out1(scf1);
	fmuxt.out2(scf2);
	fmuxt.in1(scf3);
	sc_start(300,SC_NS);

	return 0;

}

This solution gives what I wanted. But I have another question and it is related to the second solution (which does not work). Here is the code.

Interface:

template <class T>
class sc_fifo_if_id:virtual public sc_interface{
public:
	virtual int getId()=0;
};

template <class T>
class sc_fifo_in_if_id: public sc_fifo_in_if<T>, public sc_fifo_if_id<T>
{};

template <class T>
class sc_fifo_out_if_id: public sc_fifo_out_if<T>, public sc_fifo_if_id<T>
{};

Channel:

#include "systemc.h"
#include "sc_fifo_if_id.h"
#include "sc_fifo_in_if_id.h"
#include "sc_fifo_out_if_id.h"

template <class T>
class sc_fifo_id:public sc_fifo<T>,public sc_fifo_if_id<T>, public sc_fifo_in_if_id<T>, public sc_fifo_out_if_id<T> {
public:
	sc_fifo_id();
	int getId(){return pr_id;}
private:
	int pr_id;
};

When I try to test this solution in main program using the same testing modules as described above, I've got the following error "The type 'sc_fifo_id' must implement the inherited pure virtual method 'sc_core::sc_fifo_nonblocking_in_if::data_written_event' and other virtual methods present in sc_fifo interfaces. My question why I need to implement all virtual methods from other interfaces of sc_fifo in the derived class sc_fifo_id? If I don't implement them, it should use already implemented methods in base class, right?

#include "fifo_mux_test.h"
#include "sc_fifo_id.h"
#include "fifo_id_test.h"

int sc_main(int argc, char* argv[]){
	cout<<"Starting"<<endl;
	fifo_mux_test fmuxt("fifo_mux_test");
	sc_fifo_id<int> scf1,scf3;
	sc_fifo_id<int> scf2;
	fifo_id_test fidt("fifo_id_test");
	fidt.in2(scf1);
	fidt.out2(scf3);
	fmuxt.out1(scf1);
	fmuxt.out2(scf2);
	fmuxt.in1(scf3);
	sc_start(300,SC_NS);

	return 0;

}

Share this post


Link to post
Share on other sites

Your second solution won't work due to the way inheritance works in C++.

 

You would need to use virtual inheritance from all of the interfaces used in sc_fifo_id and sc_fifosc_fifo does not use virtual inheritance from the sc_fifo_in/out_if interfaces, which is why you can't "extend" these interfaces and still automatically inherit the implementation from sc_fifo.

 

If you really need the separate interface definitions sc_fifo_id_in/out_if, I would suggest to wrap an sc_fifo instance (in terms of a member object) with your sc_fifo_id class and add forwarding functions to the sc_fifo member to implement the plain FIFO functions.

 

hth,
  Philipp

Share this post


Link to post
Share on other sites

Hi,

 

I reactivate this thread because I've stumbled on the same problem recently and can't seem to find any answer after having crawled the web for a while.

I understand the pb with the second solution and tried the one given by Philipp (wrapping a sc_fifo instance inside my special fifo class).

Unfortunately, it does not work if the "derived" (wrapping) class needs to access non-public members of the wrapped class.

In my case, i wand to add a method 

 

  virtual T peek(void);
 
which simply returns the data at the top of the FIFO without popping it (non destructive read).

There's no way to do this using the public interface of the sc_fifo class. The only solution would be to define peek as :
 
  virtual T peek(void) { return p_fifo.m_buf[p_fifo.m_ri]; }
 
But, as said before, this simply does not work because m_buf and m_ri are _protected_ members of the sc_fifo class.

So far, the only solution i've found is copy-pasting the code of sc_fifo and adding the requested method, which obviously is a hack.

Any idea ? 
 
Thanks in advance.
 
Jocelyn
 
 

Share this post


Link to post
Share on other sites

Thanks a lot  for the tip, Philipp. 

I haven't thought about this since i'm not familiar with the TLM layer.

Will try !

 

This said, i find it awkward that the sc_fifo class cannot be easily extended. Is it a consequence of the limitations of the C++ inheritance mechanism or a deliberate choice of the SystemC designer ?

 

Jocelyn

Share this post


Link to post
Share on other sites

Thanks a lot  for the tip, Philipp. 

I haven't thought about this since i'm not familiar with the TLM layer.

Will try !

 

This said, i find it awkward that the sc_fifo class cannot be easily extended. Is it a consequence of the limitations of the C++ inheritance mechanism or a deliberate choice of the SystemC designer ?

 

Jocelyn

Hello,

Instead of trying to force a built-in SystemC interface/class to perform a

customized operation, and thereby running into inheritance issues. why 

not simply declare/define your own interface with the appropriate semantics,

and a class to implement that interface.  That way, you are freed of trying

to figure out what exactly the designer of the built-in class had in mind.

SystemC is basically a C++ library, and whatever works in the core language

will also work here. Hope that helps.

Share this post


Link to post
Share on other sites

This is exactly what i've been doing up to now !

But since my specific fifo is very similar to the sc_fifo, this implies a lot of copying. 

 

This is that copying I was wishing to avoid by using inheritance. 
I've read a bit on multiple inheritance issues since yesterday (since i'm not basically a C++ specialist..) : not trivial ones, apparently !

 

Thanks for the feedback anyway

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

×