blob: d40a7aa1424aeb490ed44b54e6b195a5aeaa95ec [file] [log] [blame]
#include <systemc.h>
// Tests for 2.0.1 extended coding styles, illustrating that SystemC is a class library, not a syntax
static int global_count = 0;
SC_MODULE(Mod)
{
SC_CTOR(Mod)
{
sc_assert(std::string(this->kind()) == "sc_module");
}
};
SC_MODULE(Mod0)
{
SC_CTOR(Mod0)
{
sc_assert(std::string(basename()) == "mod0");
SC_METHOD(method);
dont_initialize();
method(); //// Calling an SC_METHOD member function directly DOULOS009
for (int i = 0; i < 3; i++)
{
SC_THREAD(thread); //// Registering the same function multiple times DOULOS046
//// Get warnings re-defining sc_object names, multiple threads created
}
SC_THREAD(thread);
SC_THREAD(thread); //// Compile-time error - 'threadhandle' redefinition
f();
}
void method(void) {
sc_assert(sc_get_current_process_handle().proc_kind() == SC_METHOD_PROC_);
++ global_count;
}
void thread(void) {
sc_assert(sc_get_current_process_handle().proc_kind() == SC_THREAD_PROC_);
++ global_count;
}
void f() { SC_THREAD(g); } //// Process registered in member function called from constructor DOULOS007
void g()
{
sc_assert(std::string(sc_get_current_process_handle().name()) == "top.mod0.g");
++ global_count;
}
};
struct Chan //// Pseudo-channel used for port-less interprocess communication
//// but not derived from sc_module, sc_prim_channel or sc_interface DOULOS048
{
void write(int i) { wait(10, SC_NS); data = i; e.notify(); }
void read(int& i) { wait(e); i = data; }
int data;
bool wr, re;
sc_event e;
};
struct MyMod: Mod //// Class derived from an SC_MODULE DOULOS050
{
sc_in<bool> p;
MyMod(sc_module_name n)
: Mod(n)
{
SC_THREAD(p1);
SC_THREAD(p2);
}
Chan ch; //// Instance of pseudo-channel DOULOS048
void p1() { ch.write(333); }
void p2() { int i; ch.read(i); sc_assert(i == 333); }
SC_HAS_PROCESS(MyMod);
};
struct C0: sc_module, virtual sc_interface //// Combining channel and interface in one class DOULOS015
{
void write(int i) { data = i; }
void read(int& i) { i = data; }
int data;
SC_CTOR(C0)
{
SC_THREAD(action);
}
void action() {
sc_assert(std::string(sc_get_current_process_handle().get_process_object()->basename()) == "action");
}
};
struct C1: virtual public sc_interface //// Combining channel and interface in one class DOULOS015
{
void write(int i) { data = i; }
void read(int& i) { i = data; }
int data;
};
struct I_F: virtual public sc_interface
{
virtual void method() = 0;
};
struct C2: I_F //// Channel derived from neither sc_module nor sc_prim_channel DOULOS049
{
void method() {}
};
struct C3: sc_object, I_F //// Channel derived from sc_object only
//// (and derived from neither sc_module nor sc_prim_channel) DOULOS049
{
void method() {}
};
void check_form_of_suffix(std::string s)
{
std::string charset = "0123456789";
while (!s.empty())
{
sc_assert(s[0] == '_');
s = s.substr(1);
sc_assert(!s.empty());
do
{
sc_assert(charset.find(s[0]) < charset.size());
s = s.substr(1);
} while (!s.empty() && (s[0] != '_'));
}
}
struct Modtype: sc_module
{
Modtype(sc_module_name n = sc_gen_unique_name("Modtype"))
{
if (global_count == 0)
sc_assert(std::string(basename()) == "mt");
else
{
std::string s = std::string(basename());
sc_assert(s.substr(0,7) == "Modtype");
sc_assert(s.size() > 7);
check_form_of_suffix(s.substr(7));
}
++ global_count;
}
void dump() {
sc_assert(std::string(sc_get_current_process_handle().get_process_object()->basename()) == "thread");
++ global_count;
}
};
typedef sc_signal<Modtype*> MS; //// Pointer-to-module used as the type of a signal DOULOS051
template<class T>
struct S
{
T t;
};
SC_MODULE(Moda)
{
sc_port<C0> p0;
sc_port<C1> p1;
sc_port<C2> p2;
sc_port<C3> p3;
sc_port<MS> p4;
Modtype mt;
SC_CTOR(Moda): mt("mt")
{
sc_assert(std::string(name()) == "top.moda");
SC_THREAD(thread);
}
void thread();
};
SC_MODULE(Modb)
{
sc_port<C0> p0;
sc_port<C1> p1;
sc_port<C2> p2;
sc_port<C3> p3;
sc_port<MS> p4;
SC_CTOR(Modb)
{
sc_assert(std::string(name()) == "top.modb");
SC_THREAD(thread);
SC_THREAD(funny);
}
void thread();
void funny();
};
void Moda::thread()
{
p1->write(999);
p2->method();
p3->method();
p4->write(&mt);
}
void Modb::thread()
{
wait(SC_ZERO_TIME);
int i; p1->read(i);
sc_assert(i == 999);
p2->method();
p3->method();
wait(SC_ZERO_TIME);
(p4->read())->dump();
}
void Modb::funny() { C1 c1; C2 c2; C3 c3; }
struct Link
{
Link *link;
sc_module *m; //// Pointer-to-module DOULOS006
sc_signal<int> *s; //// Pointer-to-signal
sc_in<int> *p; //// Pointer-to-port DOULOS008
};
SC_MODULE(Top)
{
SC_MODULE(Nested) //// Nested modules DOULOS005
{
sc_in<int> *pp; //// Pointer-to-port DOULOS008
SC_CTOR(Nested)
{
SC_METHOD(action);
pp = new sc_in<int>; //// Dynamic port instantiation DOULOS008
sensitive << *pp; //// Sensitivity separated from SC_METHOD DOULOS011
}
void action() { op = sc_min(3, (*pp).read() + 1); }
sc_out<int> op; //// Out-of-order declaration DOULOS052
};
Nested n;
Link* link;
sc_signal<bool> b;
sc_signal<int> *sig; //// Pointer-to-signal
MyMod mymod;
Moda moda;
Modb modb;
C0 c0;
C1 c1;
C2 c2;
C3 c3;
S<Modtype> Sm; //// Using sc_module as a template parameter DOULOS051
MS ms; //// Pointer-to-module used as the type of a signal DOULOS051
Mod0 mod0;
SC_CTOR(Top)
: n("n"), mymod("mymod"), moda("moda"), modb("modb"), c0("c0"), mod0("mod0")
{
link = new Link;
link->m = new Mod("mod_1");
link->p = new sc_in<int>;
link->link = new Link;
link->link->m = new Mod("mod_2"); //// Buried dynamic module instantiation DOULOS002
link->link->s = new sc_signal<int>;//// Buried dynamic channel instantiation
link->link->p = new sc_in<int>; //// Buried dynamic port instantiation DOULOS008
sig = new sc_signal<int>; //// Dynamic channel instantiation
n.op(*sig);
(*(n.pp)).bind(*sig); //// Binding dynamically allocated port DOULOS008
mymod.p(b);
moda.p0(c0);
moda.p1(c1);
moda.p2(c2);
moda.p3(c3);
moda.p4(ms);
modb.p0(c0);
modb.p1(c1);
modb.p2(c2);
modb.p3(c3);
modb.p4(ms);
}
};
int sc_main(int argc, char* argv[])
{
cout << "Should be silent except for some renaming warnings..." << endl;
sc_signal<int> s;
Top top("top");
top.link->p->bind(s);
top.link->link->p->bind(s); //// Binding dynamically allocated port DOULOS008
sc_start();
sc_assert(global_count == 10);
sc_assert(top.sig->read() == 3);
cout << endl << "Success" << endl;
return 0;
}