Professional Documents
Culture Documents
References:
An Introduction to SystemC 1.0 : Bernard Niemann, Fraunhoffer Institute for Integrated Circuits SystemC Tutorial: John Moondanos, Strategic CAD labs, Intel Corp. GSRC Visiting Fellow, UC Berkeley SystemC 2.0.1 Language Reference Manual SystemC Tutorial: Anonymous Author Compositional Approach to SystemC Design : Semantics of SystemC : R.K Shyamasundar, IBM Research Lab Doulos SystemC Tutorial The NEW YORKER Cartoon Bank
Modules in SystemC
A module is the basic structural building block in SystemC. Modules may contain:
Ports Data Members Channel Processes Member functions not registered as processes Instances of other modules
A new type of module is created by deriving from the container class sc_module
Publicly deriving from class sc_module. Or alternatively, a module can be created with use of the SC_MODULE macro.
Modules in SystemC
An example for the former would be:
class my_module : public sc_module { .... };
Module Constructor
Every module can have a module constructor Accepts one argument which is the module name Will be thoroughly explained in the upcoming sections
Modules Instantiation
Instantiation develops hierarchy through out the design
Declaration
SC_MODULE(ex2) { . . . ex1 ex1_instance; SC_CTOR(ex2) : ex1_instance(ex1_anyname) { //body } };
Modules Instantiation
Pointer
SC_MODULE(ex2) { . . . ex1 *ex1_instance; SC_CTOR(ex2) { ex1_instance = new ex1(ex1_anyname); //body } };
Module Destructor
SC_MODULE(ex2) { ~ex2() { delete ex1_instance; } };
Processes in SystemC
An argument that begs the question: Processes are small pieces of code that run concurrently with other processes. All high-level system level design (SLD) tools use an underlying model of a network of processes. Functionality is described in processes. Processes must be contained within a module. They are registered as processes with the SystemC kernel, using a process declaration in the module constructor. Processes accept no arguments and produce no output
NAND Gate
#include "systemc.h" SC_MODULE(nand2) //declare nand2 sc_module { sc_in<bool> A, B; //input signal ports sc_out<bool> F; //output signal ports void do_nand2() //a C++ function { F.write( !(A.read() && B.read()) ); } SC_CTOR(nand2) { SC_METHOD(do_nand2); //register do_nand2 with kernel sensitive << A << B: //sensitivity list } };
XOR Gate
#include "systemc.h" #inclue "nand2.h" SC_MODULE(xor2) { sc_in<bool> A, B; sc_out<bool> F; nand2 n1, n2, n3, n4; sc_signal<bool> S1, S2, S3; SC_CTOR(xor2) : n1("N1"), n2("N2"), n3("N3"), n4("N4") { n1.A(A); n1.B(B); n1.F(S1);
XOR Constructor
Must have four instances of nand2. After the port declarations, they are declared. And a label must be declared for each instance. The four labels, N1, N2, N3 and N4 are passed to the constructors of the instances of nand2 by using an initializer list on the constructor of xor2. Lastly, the ports are wired up. This can be done using parentheses () or << and >>.
Using << and >> only allows the ports and signals to be listed by position (n2). Using () allows either by position (n3) or by name (n1 and n4).
More on Modules
They map functionality of HW/SW blocks The basic building block of every system Can contain a whole hierarchy of sub-modules and provide private variable/signals. Modules can interface to each other via ports/interfaces/channels Module functionality is achieved by means of processes
Module Hierarchy
Interfaces
An interface consists of a set of operations (their prototype), not of their implementation which is a burden on the channels. There are two basic interfaces derived from sc_interface class: sc_signal_in_if<T> provides a virtual functional read( ) returning a reference to T sc_signal_inout_if<T> provides a virtual functional write( ) taking a reference to T an out interface is identical to an inout interface
Ports
They provide communication functions to modules Derived from SystemC class sc_port<> On the outside, they connect to channels by means of interfaces Typical channel (in RTL mode): sc_signal Specialized classes were derived: sc_in<class T>, sc_out<class T>, sc_inout<classT>, which are ports connected to N = 1 interfaces of type sc_signal_in_if<class T> The interface sc_signal_in_if<> defines the restricted set of available messages that can be send to the port clk. For instance, the functions: read() or default_event() are defined by this class.
Channels
SystemCs communication medium This feature of SystemC differentiates it from other HDLs such as Verilog Provides abstraction at the interface level of components and thus achieves greater design modeling flexibilities By definition, modules are interconnected via channels and ports. In turn, channels and ports communication via a common interface Implementation of interfaces functions
Channels
Communication among modules and among processes within a module Any channel must:
be derived from sc_channel class be derived from one or more classes derived from sc_interface provide implementations for all pure virtual functions defined in its parents interfaces
Fifo Example
FIFO Completed
SC_MODULE(top) { public: fifo afifo; producer *pproducer; consumer *pconsumer; SC_CTOR(top) { pproducer=new producer(Producer); pproducer->out(afifo); pconsumer=new consumer(Consumer); pconsumer->in(afifo); } };
More on Processes
They provide module functionality Implemented as member functions of the module and declared to be SystemC process in SC_CTOR Three kinds of process available:
SC_METHOD SC_THREAD SC_CTHREAD
These macros are needed because a member function is not necessarily a process. The macros operate specifics registrations with the scheduler All these processes in the design run concurrently Code inside of each process is sequential
SC_METHOD
Sensitive to any changes on input ports (i.e., it is sensitive to a set of signals, on its sensitivity list. It can be sensitive to any change on a signal e.g., the positive or negative edge of a Boolean signal). Usually used to model purely combinational logic (i.e., NORs, NANDs, MUX) Cannot be suspended. All the function code is executed every time the SC_METHOD is invoked (whenever any of the inputs it is sensitive to change). Instructions are executed in order. Does not remember internal state among invocations (unless explicitly kept in member variables)
SC_THREAD
Still has a sensitivity list and may be sensitive to any change on a signal. It is reactivated whenever any of the inputs it is sensitive to changes. Once it is reactivated:
Instructions are executed infinitely fast (in terms of internal simulation time) until the next occurrence of a wait( ) statement. Instructions are executed in order. The next time the process is reactivated, the execution will continue after the wait( ) statement.
wait( ) suspends execution of the process until the process is invoked again
SC_THREAD
Akin to a Verilog initial block Executes only once during simulation and then suspends Designers commonly use an infinite loop inside an SC_THREAD to prevent it from ever exiting before the end of the simulation Adds the ability to be suspended to SC_METHOD processes by means of wait() calls (and derivatives) Remembers its internal state among invocations (i.e., execution resumes from where it was left) Very useful for clocked systems, memory elements, multi-cycle behavior
An Example of SC_THREAD
void do_count() { while(true) { if(reset) { value = 0; } else if (count) { value++; q.write(value); } wait(); } }
Another Example
SC_MODULE(my_module) { sc_in<bool> id; sc_in<bool> clock; sc_in<sc_uint<3> > in_a; sc_in<sc_uint<3> > in_b; sc_out<sc_uint<3> > out_c; void my_thread(); SC_CTOR(my_module) { SC_THREAD(my_thread); sensitive << clock.pos(); } }; //my_module.cpp void my_module:: my_thread() { while(true) { if (id.read()) out_c.write(in_a.read()); else out_c.write(in_b.read()); wait(); } };
SC_CTHREAD
Will be deprecated in future releases Almost identical to SC_THREAD, but implements clocked threads Sensitive only to one edge of one and only one clock It is not triggered if inputs other than the clock change Models the behavior of unregistered inputs and registered outputs Useful for high level simulations, where the clock is used as the only synchronization device Adds wait_until( ) and watching( ) semantics for easy deployment
SC_CTHREAD
Once invoked: The statements execute until a wait( ) statement is encountered. At the wait( ) statement, the process execution is suspended At the next execution, process execution starts from the statement after the wait( ) statement Local variables defined in the process function are saved each time the process is suspended
Counter in SystemC
Counter in SystemC
SC_MODULE(countsub) { sc_in<double> in1; sc_in<double> in2; sc_out<double> sum; sc_out<double> diff; sc_in<bool> clk; void addsub(); //Constructor: SC_CTOR(addsub) { //Declare addsub as SC_METHOD SC_METHOD(addsub); dont_intialize(); //make it sensitive to positive clock sensitive_pos << clk; } }; //Definition of addsub method void countsub::addsub() { double a; double b; a = in1.read(); b = in2.read(); sum.write(a+b); diff.write(a-b); };
The End