253 sclive)

Upload: gagan-chopra

Post on 03-Apr-2018

237 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 253 SCLive)

    1/29

    SCLive

    A Linux Live Distribution for SystemC

    Home

    AboutDownload

    User Guide

    SCBook

    Moi

    Archive

    Archive for the SytemC Tutorials Category

    Running the SystemC TLM2 Examples

    September 30, 2009 scliveLeave a comment

    This short tutorial is for those of you eager to run TLM 2 examples inside SCLive 3.0.

    I will take an arbitrary example here to illustrate the simple procedure.

    1) Open a terminal window and navigate to the examples directory:

    cd ~/software/TLM-2009-07-15/examples/tlm/lt/

    2) In there you will find the src (source directory) as well as the build-unix directory. Go to the build-unix

    directory and execute the makefile.

    cd build-unix

    make run

    3) This will compile and link the example. Finally this will run the resulting executable (lt.exe) example

    inside the terminal window. Alternatively you can run the executable yourself by typing:

    ./lt.exe | less

    4) To clean up the directory simply execute the command:

    make clean

    Et Voila!

    David Cabanis

    Categories: SytemC Tutorials

    SystemC Tutorial: interfaces and channels

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    2/29

    January 11, 2008 sclive6 comments

    Forewords

    Inheritance and multiple inheritances are a pivotal part of interfaces and channels building. Channels in

    SystemC can be viewed as, a sophisticated form of communication mechanism; Akin to signals or wires in

    found in other HDLs. However what differentiates SystemC from common HDLs is the ability given to

    the designer to handcraft his own channels. Furthermore, the use of interfaces enables the separation ofthe modules implementation from the communication scheme used in between modules; This is an

    essential part of system level modeling.

    In this section we will examine the existing predefined SystemC channels as well as look at the creation of

    user defined primitive and hierarchical channels.

    Inheritance and SystemC channels/ Interface loose coupling

    For the creation of channels, SystemC borrows from C++ a convenient principle called: the class

    interface. This principle is also known as abstract base classes and is used to define a common interface

    for related derived classes.

    Sometimes in C++, designers want to create a class that will define a set of access methods that should beused by all the classes that will be derived from it; however this class in itself will never be used to create

    objects. This type of classes is an abstract base class. In SystemC, abstract base classes are used to define

    all the access methods that a channel should have. Consequently, a channel will be a C++ class derived

    from an abstract base class and will implement the access methods defined inside its abstract base parent

    class.

    An abstract base class is created in C++ through the definition of one or more pure virtual methods as part

    of that class. A pure virtual method by definition is a method that will only be implemented inside a

    derived class from the abstract base class. The semantics for the declaration of a C++ pure virtual method

    is as follows:

    virtual function_name (args>)=0;

    For instance the following line of code declares a method called bustWrite that takes three input

    arguments and returns an integer type:

    virtual void burstWrite( int destAddress, int numBytes, sc_lv *data ) = 0;

    The keyword virtual and the =0 are the essential parts of this declaration as they indicate to the

    compiler that burstWrite is a pure virtual method and therefore, that the class containing this declaration

    can never be made into an object.

    Once one or a number of abstract base classes (interfaces) have been designed, channels can be

    implemented by simply inheriting one or more of the base classes and implementing their virtual methods.

    Following the creation of channel, instances of that channel can be made as any other C++ object.

    Primitive Channels

    The SystemC language extension distinguishes between two kinds of channels implementation: Primitive

    channels and non-primitive ones also referred as hierarchical channels. Primitive channel as their nameimply, have restrictions in regards to their construction. Firstly, any primitive channel is derived from both,

    its associated interfaces and the predefined SystemC class: sc_prim_channel. In addition, a primitive

    channel is not allowed to contain SystemC structures for instance threads, methods, other channels et

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    3/29

    caetera. However, although primitive channel appear limited, they uniquely support the SystemC defined

    request_update() and update() access methods.

    The SystemC library defines a number of versatile primitive channels namely: sc_buffer, sc_fifo,

    sc_mutex, sc_semaphore, sc_signal, sc_signal_resolved, sc_signal_rv. Those channels can be

    used individually or can be combined as part of a non-primitive channel to create more complex

    communication mechanisms. These channels can be declared as follows:

    // A 3216 bits elements fifosc_fifo inputFifo(32);// A 16 bits bussc_signal dataBus;// A 4 tokens semaphoresc_semaphore gateKeeper(4);

    The predefined SystemC primitive channels rely on a number of access methods to allow users to examine

    or alter their internal state. As previously highlighted, those methods are defined inside the channels

    interface. For channels used to hold values, the read() and write() methods are provided. Most predefined

    channels also support the common methods: print(), dump(), trace()and kind(). The print(), dump() andtrace() methods are used to display the internal values of a given primitive channel either using the output

    stream or a trace file in the case of the trace() method. The purpose of the kind() method is used to

    identify the current primitive channel by providing its kind as a string information.

    Along with access and display methods, most primitive channels support queries of events. These methods

    may be used for two purposes: examining if a specific channel has currently had an event as part of an

    expression; such as an if statement or supply information related to the activity/events of a channel as

    part of a sensitivity list of a SystemC process. The following examples illustrate the different method

    available for specific channels.

    // A non blocking write on an sc_signaldataBus.write(1010111101010101);// A blocking write on a variable of type sc_lvsc_lv busVar = dataBus.read();while ( inputFifo.num_free() != 0 )// A blocking write on an sc_fifoinputFifo.write(dataBus.read());// A blocking access to an sc_semaphoregateKeeper.wait();// A non blocking access to an sc_semaphoreif ( gateKeeper.trywait() != 0 )cout

  • 7/29/2019 253 SCLive)

    4/29

    // unlock (give) the semaphorevirtual int post() = 0; // Line 13

    // get the value of the semphorevirtual int get_value() const = 0; // Line 16

    protected:// constructorsimple_semaphore_if() { } // Line 21

    };

    // Creation of the semaphore Channelclass simple_semaphore: public simple_semaphore_if, public sc_prim_channel{

    public:// constructorsexplicit simple_semaphore( int init_value_ );

    // interface methods// lock (take) the semaphore, block if// not availablevirtual int wait(); // Line 37

    // lock (take) the semaphore, return -1 if// not availablevirtual int trywait(); // Line 40

    // unlock (give) the semaphorevirtual int post(); // Line 43

    // get the value of the semaphorevirtual int get_value() const // Line 46{ return m_value; }

    protected:// support methodsbool in_use() const // Line 53{ return ( m_value

  • 7/29/2019 253 SCLive)

    5/29

    int simple_semaphore::post() {++ m_value;m_free.notify();return 0;

    }

    The first part of this example defines the interface for the semaphores channel. line 1 declares the

    interface class named simple_semaphore_if and inherits virtually, the sc_interface SystemC predefined

    class. The virtual inheritance is used here to prevent any problems related to repeated inheritance later-on

    during the creation of the simple_semaphore channel. The lines 7 to 16 declare pure virtual methods thatwill be used to access the semaphore channel. Finally the line 21 defines a default constructor for the

    interface. Following the interface declaration, we find the declaration of the semaphore channel called

    simple_semaphore. The class is created through the inheritance of both the simple_semaphore_if

    interface class and the SystemC sc_prim_channel pre-defined class. The lines 37 to 46 make the

    previously pure virtual methods defined inside the interface into effective methods inside the channel. A

    local method is created in line 53 to used to keep track of the current value of the semaphore. Lastly in

    lines 58 and 59 we find the definitions of internal member variables used by the semaphore channel. The

    ultimate part of this example implements each individual methods defined inside the semaphore channel.

    Hierarchical Channel

    Up until now we have considered the simplest form of channels: the primary channels. Although primary

    channels are of great use, one of the main advantages that SystemC has over conventional HDLs, is its

    ability to create complex communication mechanisms in the form of hierarchical channels.

    Hierarchical channels are used as a convenient way to abstract exchanges between communicating

    objects such as sc_modules. Commonly hierarchical channels are used as transactors, converting high

    level commands to RTL style signals and vice versa.

    Herarchical channel can be considered in a lot of ways as, more sohisticated forms of sc_modules. As

    such, a hierarchical channel can contain ports, as well as, a hierarchy of sc_modules or other channels.

    Furthermore, hierarchical channels may contain SystemC processes such as: SC_METHODS orSC_THREAD. However, unlike their sc_modules counterparts, hierarchical channels will also provide

    methods for implementing the functions defined inside their associated interfaces.

    As we mention earlier, a channel is always created from one or multiple existing interfaces. An interface

    in SystemC is an abstract class derived from the existing SystemC class: sc_interface.

    By definition interfaces will only define pure virtual access methods. These methods will eventually have

    to be implemented in any deriving channels. The following illustrates the creation of a user defined

    interface called dma_interface with a methods called: burstWrite() and bustRead().

    class dma_interface: virtual public sc_interface {public:

    virtual void burstWrite(int destAddress, int numBytes, sc_lv *data ) = 0;virtual void burstRead(int sourceAddress, int numBytes, sc_lv* data) = 0;

    };

    Commonly the inheritance of the pre-defined SystemC class: sc_interface, is done as, public and virtual.

    The virtual mechanism is used as a safety net, preventing the rise of issues related to repeated inheritance

    when a channel inherits more that one interface.

    After the creation of an interface, numerous channels can be created to provide the required

    implementation of the interfaces methods. The creation of a hierarchical channel differs from a primitive

    one, only by the type of the inherited pre-defined SystemC class: sc_channel. Along with the sc_channelclass, one to any number of interface classes can be inherited. The following code illustrates the creation

    of a channel called: dma_channel, publicly inheriting form the interface class: dma_interface.

    class dma_channel: public dma_interface, public sc_channel {

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    6/29

    public:sc_out_rv address_p;sc_inout_rv data_p;sc_out_resolved rw_p;dma_channel(sc_module_name nm): sc_channel(nm)

    ,address_p(address_p),data_p(data_p),rw_p(rw_p)

    { }virtual void burstWrite( int destAddress, int numBytes, sc_lv *data );virtual void burstRead(int sourceAddress, int numBytes, sc_lv* data);

    };

    void dma_channel::burstWrite( int destAddress, int numBytes, sc_lv *data ) {sc_lv *ite = data;for (int i=0; iwrite(destAddress++);data_p->write( *(ite++) );wait(10, SC_NS);cout write(SC_LOGIC_Z);

    address_p->write(ZZZZZZZZZZZZZZZZ);data_p->write(ZZZZZZZZ);wait(10, SC_NS);

    }}

    void dma_channel::burstRead(int sourceAddress, int numBytes, sc_lv* data) {for (int i=0; iwrite(sourceAddress++);wait(10, SC_NS);rw_p->write(SC_LOGIC_1); // Read pulsewait(10, SC_NS);*(data++) = data_p->read();cout write(ZZZZZZZZZZZZZZZZ);data_p->write(ZZZZZZZZ);wait(10, SC_NS);

    }}

    The first part of this code illustrates the creation of the hierarchical channel called dma_channel. This is

    done through the multiple inheritance of the sc_channel class and the dma_interface class.

    Ports are created to illustrate the flexibility of channels. Those port are initialised inside the constructor of

    that class.

    The last part of the dma_channel class declaration restates the existance of the burstWrite() andburstRead() methods found in the parent class: dma_interface.

    Lastly the code illustrates the implementation of the two methods burstWrite() and burstRead(). The code

    itself is of little importance but it demonstrates how high level transactions can be refined into low-level

    RTL signal activities.

    For the pupose of completeness of this example the following code illustrates how can this channel could

    be used in a verification environment.

    This code shows the creation of a simple testbench sending a burstWrite() and a burstRead() request to a

    slave RTL memory via the dma_channel.

    class test_bench: public sc_module {public:sc_port master_port;

    void stimuli()

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    7/29

    {sc_lv data_sent[10] = {20, 21, 22, 23, 24, 25,26,27,28,29};sc_lv data_rcv[10] = {0,0,0,0,0,0,0,0,0,0};master_port->burstWrite(100, 10, data_sent);wait(100, SC_NS);master_port->burstRead(100, 10, data_rcv);for (int i=0; i

  • 7/29/2019 253 SCLive)

    8/29

    uut.address_p(address_s);uut.data_p(data_s);uut.rw_p(rw_s);

    sc_start();return 0;

    }

    Summary

    In this section we covered the existance of two kind of channels in SystemC: primitive, hierarchical. The

    main differences between those two kinds being: primitive channels cannot contain SystemC structural

    objects (ports, channels, processes) but can use the update() method to implement non blocking update

    mechanisims; The hierachical channels however can have structural objects but cannot use the update()

    method.

    I addition we illustrated the creation of both a primitive and hierarchical channel as well as their use in the

    context of a verification environment.

    The code for this tutorial can be found HERE.

    Et voila !

    David Cabanis

    Categories: SytemC Tutorials

    SystemC Tutorial: threads, methods and sc_spawn

    January 10, 2008 sclive20 comments

    Forewords

    This tutorial is intended to be a basic introduction to the notions of concurrent processes in SystemC. We

    will touch on the SystemC ability to dynamically spawn processes.

    Processes in SystemC

    One of the essential element of the SystemC language is concurrency. This is achieved through what we

    will call processes. Processes are similar to processes in VHDL or always/initial in Verilog. In principle

    processes are block of sequential code similar to functions. However, unlike functions, processes are not

    explicitly called by the user. Processes can in effect be seen as always active; For that reason they areconsidered to be concurrent.

    In the SystemC language there are two distinct kinds of processes namely: SC_METHOD and

    SC_THREAD. These two kind of processes are typically created statically; In other words they are

    created prior to the execution of the simulation. Alternatively SystemC allows processes to be created

    dynamically via a dedicated function called: sc_spawn() .

    The SC_THREAD process

    As a first step we will look at the SystemC SC_THREAD. A thread by definition is a process that will

    automatically execute itself at the very start of a simulation run and then will suspend itself for the rest of

    the simulation.Threads are versatile processes in the sense that they can be halted at any moment and any number of

    times during their execution. Interestingly, although the thread is mean to be executed only once

    throughout the simulation, most of times we want to be able to use threads for the whole duration of the

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    9/29

    simulation. In order to achieve this, we use a simple trick that consist in creating an infinite loop within a

    thread. Consequently we prevent the thread from ever reaching its sequential end. The following example

    illustrates how to create a simple thread used to generate a clock generator.

    void run() {while(true) {

    clock_signal.write(SC_LOGIC_0);wait(10, SC_NS);clock_signal.write(SC_LOGIC_1);

    wait(10, SC_NS);}

    }

    Three main observations can be made:

    The funtion run does not have any input or return parameters. This typical of a SystemC static

    process such as SC_THREAD or SC_METHOD.

    An infinite while loop is used to prevent the function run from ever reaching its end. This does not

    have to be used for all SC_THREAD implementations; however it is a common occurrence.

    We are using wait function calls to force a temporary suspension of the function run and the

    update of the clock_signal value. This can only be used by SC_THREAD processes.

    Up until now we have only created a C++ member function that will be used as a thread. At this time we

    will need to indicate to the SystemC simulation kernel that this specific member function (in our case

    run) should be treated as a concurrent thread and not as a basic C++ member function. This will be done

    through an operation called processes registration. To put it simply this consists in enumerating how

    individual functions should be treated. This simple operation is done inside the constructor of a module.

    The following code will illustrate how this is achieved.

    sample_module(sc_module_name nm):sc_module(nm) {SC_THREAD(run);

    }

    In this example we assume the existence of a SystemC called sample_module. The process registration

    of the member function run as an SC_THREAD is done by passing the name of the selected function

    (run) as an argument of the macro SC_THREAD.

    The SC_METHOD process

    The SC_METHOD is in many ways similar to the SC_THREAD. However there are two main

    differences: SC_METHOD will run more than once by design and methods cannot be suspended by a wait

    statement during their execution. The following code illustrates this.

    void log() {count_signal.write(count_signal.read()+1);if (count_signal.read() >= 10) {

    cout

  • 7/29/2019 253 SCLive)

    10/29

    SystemC support two kind of sensitivity: Dynamic and static. For the purpose of this tutorial we will

    concern ourselves only with that later. Both SC_THREAD and SC_METHOD may have a sensitivity list

    although they are not obliged to. In the example of the SC_THREAD covered previously we did not use a

    static sensitivity list; For the SC_METHOD example we will have to.

    As seen before the SystemC requires a kernel registration to identify which member function it needs to

    treat as a SC_METHOD (no explicit suspension allowed) or an SC_THREAD (suspensions allowed). In

    the case of the method processes we will use the macro SC_METHOD. The following code illustrates the

    registration of the log function as a SC_METHOD.

    sample_module(sc_module_name nm):sc_module(nm) {SC_METHOD(log);

    sensitive

  • 7/29/2019 253 SCLive)

    11/29

    A very basic example of the function sc_spawn is as follows. Assuming that we have an existing member

    function as such:

    void spawned_th(bool value) {cout

  • 7/29/2019 253 SCLive)

    12/29

    int global_th(const bool& in_value, int& out_value) {cout

  • 7/29/2019 253 SCLive)

    13/29

    C++ implements Object-Orientation on the C language. For most Hardware Engineers, the principles of

    Object-Orientation seem fairly remote from the creation of Hardware components. However ironically,

    Object-Orientation was created from design techniques used in Hardware designs. Data abstraction is the

    central aspect of Object-Orientation which incidentally, is found in everyday hardware designs through

    the use of publicly visible ports and private internal signals. Furthermore, the principle of

    composition used in C++ for creating hierarchical design is almost identical to component instantiation

    found in hardware designs. The coming sections will introduce the basics of C++ by looking at the

    creation of an hardware component.

    The Class

    The class in C++ is called an Abstract Data Type (ADT); it defines both data members and access

    functions (also called methods). Both data members and access functions are said to be private by default.

    In other words, data members and access functions are not visible from the outside world. This ADT

    mechanism is analogous to a package and package body in VHDL. The designer is responsible for making

    publicly available the essential set of access functions for manipulating an ADT. The semantics for a C++

    class declaration is as follows:

    class counter

    {

    int value;

    public:

    void do_reset() { value = 0 ; }

    void do_count_up() { value++ ; }

    int do_read() { return value; }

    };

    In this example we see the declaration of an ADT called: counter with a data member value and

    publicly available access functions: do_reset, do_count_up and do_read. Although this class

    declaration is complete; commonly, a class declaration will also contain specialised functions such as

    constructors and a destructor. When constructors are used, they provide initial values for the ADTs data

    members. This mechanism is the only allowed mean for setting a default value to any data member.

    A destructor is used to perform clean-up operations before an instance of the ADT become out of scope.

    Pragmatically, the destructor is used for closing previously opened files or de-allocating dynamicallyallocated memory.

    An example of an ADT with constructors and a destructor is as follows:

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    14/29

    class counter

    {

    int value;

    public:

    void do_reset() { value = 0 ; }

    void do_count_up() { value++ ; }

    int do_read() { return value; }

    counter() {

    cout

  • 7/29/2019 253 SCLive)

    15/29

    first_counter.do_reset();

    second_counter.do_reset();

    }

    In this example two instances of the counter ADT are created. The first_counter instance uses the

    default constructor not requiring any arguments. The second_counter instance uses a more

    sophisticated constructor form that passes an argument.

    Messages are send to individual objects via the dot notation which is similar to what is used for struct

    data structures.

    The building of more complex objects can be achieved through the composition mechanism. This

    mechanism is akin to component instantiation in Hardware design.

    The following example illustrates the principle of hierarchical design through composition.

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    16/29

    class modulo_counter

    {

    counter internal_counter;

    int terminal_count;

    public:

    void do_reset() { internal_counter.do_reset(); }

    void do_count_up() {

    if ( internal_counter.do_read() < terminal_count ) {

    internal_counter.do_count_up();

    } else { internal_counter.do_reset(); }

    }

    int do_read() { return internal_counter.do_read(); }

    modulo_counter(int tc):

    terminal_count(tc),

    internal_counter(0) {

    cout

  • 7/29/2019 253 SCLive)

    17/29

    if ( do_read() < terminal_count ) {

    counter::do_count_up(); }

    else { do_reset(); }

    }

    modulo_counter(int tc): terminal_count(tc), counter(0) {

    cout

  • 7/29/2019 253 SCLive)

    18/29

    class modulo_counter : public counter {

    protected:

    int terminal_count;

    public:

    void do_count_up() {

    if ( value < terminal_count ) { value++; }

    else { value = 0; }

    }

    modulo_counter(int tc): terminal_count(tc), counter(0) {

    cout

  • 7/29/2019 253 SCLive)

    19/29

    class down_counter: virtual public reg {

    public:

    void do_count_down() { value; }

    };

    class up_down_counter: public up_counter, public down_counter { };

    In this example the up_down_counter ADT is created from two parent classes: up_counter and

    down_counter. The up_down_counter does not require any code since it inherits all of its

    implementation from its parent classes. It is important to point out that both the up_counter and

    down_conter are inheriting virtually the register class. The virtual inheritance is used here to prevent

    multiple declarations of the value, do_reset, do_read, do_write inside the up_down_counter

    since this ADT inherits those attributes twice, though both the up_counter and down_counter

    inheritance.

    Template Class

    The template mechanism is used for creating more versatile ADTs. Templates can be used for variable

    types or values. An example of a simple template class is as follows:

    template class barrel_counter {

    private:

    int value;

    public:

    void do_reset() { value = min; }

    void do_count_up() {

    if (value< max ) { value++; }

    else {value = min; }

    }

    int do_read() { return value; }

    barrel_counter(): value(min) { }

    };

    int main(int argc, char *argv[])

    {

    barrel_counter first_counter;

    barrel_counter second_counter;

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    20/29

    for (int i=0; i < 60; i++) {

    first_counter.do_count_up();

    second_counter.do_count_up();

    cout

  • 7/29/2019 253 SCLive)

    21/29

    template class adder {

    private:

    T result;

    public:

    T add( T a, T b ) {

    result = a + b ;

    return result ;

    }

    };

    int main(int argc, char *argv[]) {

    adder integer_adder;

    adder float_adder;

    int int_result = integer_adder.add(3, 5);

    float float_result = float_adder.add(6.7, 10.2);

    cout

  • 7/29/2019 253 SCLive)

    22/29

    Categories: SytemC Tutorials

    SystemC Tutorial: ports

    October 20, 2006 sclive13 comments

    Forewords

    These tutorials do not try to teach you everything about SystemC in large chapters taken from the

    language reference manual (LRM). Instead they focus on the most important aspects of the language,

    basic and advanced covering them in tutorials designed to take around ten minutes each.

    Ports

    A Port is an essential element of any SystemC model. Ports are used by modules as a gateway to and from

    the outside world. In a simplistic way, one can consider a port like the pin of a hardware component.

    In HDLs such as VHDL or Verilog, ports are very much like the pins metaphor; In the case of SystemC

    ports have a substantially more generalized purpose and as a result they are far more sophisticated anduseful than their HDLs counterparts.

    A simple SystemC port declaration would look like the following code:

    sc_in my_input;

    As can be observed the semantic is kept to a minimum level of complexity; The port has a name my_input

    and in this particular instance, it is of input mode since we used thesc_in port type (or port mode if

    you prefer). The last observation that we can make from this simple line of code is the use of the bool

    data type inside the of thesc_in port type. This data type refers to the kind of data that will be

    exchanged on that port. In other words we are expecting to receive boolean values on the my_inputport.

    As you would expect, numerous predefined port types exist in SystemC; Such as:sc_in,

    sc_out, sc_inout, etc. All of those ports are almost identical to their HDL equivalents in

    VHDL or Verilog; they have a name, a type and a mode (in, out, etc). As a mater of fact, these kinds of

    ports are commonly used in RTL SystemC. However, as we indicated earlier, SystemC ports are much

    more than just RTL like ports; This is because SystemC ports not only have a name and a type but most

    importantly they define the access mechanisms that should be used on them. Pragmatically the access

    mechanisms are just a list of allowed messages that can be used on them. If we consider thesc_in

    port of the previous example, SystemC defines that one can use the read() message on it. Not surprisingly,

    ansc_outport would allow the use of the write() message. The following code illustrates the use of an

    sc_in and an sc_out ports.

    // More code not shown here

    sc_in my_input;sc_out my_output;

    // More code not shown here

    void do_run() {if (my_input.read() == true) {

    my_output.write(false);} else {my_output.write(true);}}

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    23/29

    };

    // More code not shown here

    For the sake of simplicity the creators of the SystemC language have provided operators that can be used

    instead of the read() and write() messages. Consequently the following code is also acceptable:

    // More code not shown

    void do_run() {if (my_input == true) {my_output = false;} else {my_output = true;}}

    // More code not shown

    The list of access messages allowed on specific ports has already been defined for the existing SystemC

    ports. However SystemC allows the user to define his/her very own set of messages for his/her very own

    ports. For instance one could imagine the existence of a high-level port used on a CPU model that could

    receive messages such as: dma_request() orinterrupt_request() form the outside world.

    The creation of user defined ports goes beyond the scope of this tutorial and can only be covered when

    you will have gained an understanding of the notion of SystemC interfaces.

    Ports and Modules

    Up until now we only considered ports in isolation. Prosaically ports are parts of modules and are used to

    pass data of some form in and out of the modules. SystemC ports are by definition object instances ofpredefined classes (sc_in,sc_out, etc.) . As a result they can be accessed from within any member

    function defined inside the module. For instance the following code would be a valid way of using ports:

    class portsTutorial: public sc_module {public:sc_in my_input;sc_out my_output;

    SC_HAS_PROCESS(portsTutorial);

    portsTutorial(sc_module_name nm): sc_module(nm) {SC_METHOD(do_run);sensitive

  • 7/29/2019 253 SCLive)

    24/29

    Ports and signals have a special relationship since ports will connect to other ports via signals (also known

    as channels). More importantly, ports and signals share a common language. All the messages that can be

    used on a port should also be available on the signals (channels) connected to that port. As a result

    specific ports can only be connected to compatible signals; for instance an sc_in or an sc_out port

    can be connected to an sc_signal however and sc_fifo_in or an sc_fifo_out port can only be

    connected to an sc_fifo kind of channel. The following code illustrates the use of ports with signals:

    // Top levelclass top: public sc_module {public:sc_signal sig_1, sig_2;

    portsTutorial uut;

    top(sc_module_name nm): sc_module(nm), uut(uut) {uut.my_input(sig_1);uut.my_output(sig_2);}};

    As can be observed the connection of a port and a signal is a simple operation.Nevertheless this semantics may look surprising since a usual object-orientedmessage is of the form: object_name.message(parameters) . In this case,uut.my_input(sig_1) is composed of two objects: uut which is the componentsname and my_input which is the ports name and finally sig_1 is a parameter. Inother words we have: object_name.object_name(parameter) but no messagecall on the object. The reason is a simple one; the creators of SystemC used an

    overloading trick to make ports/signals connections appear simpler. In fact if youwanted to be a object-orientation purist you could write the following code to thesame effect:

    top(sc_module_name nm): sc_module(nm), uut(uut) {uut.my_input.bind(sig_1);uut.my_output.bind(sig_2);}

    The bind() message is effectively what is being used to connect a port to a signal(channel) although in the previous example it was hidden through an overloading

    trick.Lastly, there is yet anther way to connect your ports to your signals this is doneusing positional mapping where the signals are mapped to the ports by position. Anexample of positional mapping is as follows:

    top(sc_module_name nm): sc_module(nm), uut(uut) {uut(sig_1, sig_2);}

    This style is certainly the most succinct way of connecting a component to a set of signals however it is

    usually seen as a more error prone way since the signals can easily be miss-ordered.

    Summary

    This tutorial covered the basic uses of ports in a SystemC model. Ports are part of modules and are used to

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    25/29

    connect modules together via signals (channels). In this tutorial wefocused on the predefined SystemC

    ports however, most commonly the user creates its own port kind defining its own set of messages that

    can be exchanged on those ports. The subject of user defined port we be covered in an other tutorial.

    The pdf file and the source files for this tutorial can be found HERE.

    David Cabanis.

    Categories: SytemC Tutorials

    SystemC Tutorial: modules

    September 8, 2006 sclive3 comments

    Forewords

    These tutorials do not try to teach you everything about SystemC in large chapters taken from the

    language reference manual (LRM). Instead they focus on the most important aspects of the language,

    basic and advanced covering them in tutorials designed to take around ten minutes each.

    Modules

    A module is a C++ class it encapsulates a hardware or software description. SystemC defines that any

    module has to be derived from the existing class sc_module. SystemC modules are analogous to Verilog

    modules or VHDL entity/architecture pairs, as they represent the basic building block of a hierarchical

    system. By definition, modules communicate with other modules through channels and via ports.

    Typically a module will contain numerous concurrent processes used to implement their required

    behaviour.

    The following code illustrates the creation of the simplest of modules:

    1 // module tutorial2 SC_MODULE(module_test) {3 SC_CTOR(module_test) {4 cout

  • 7/29/2019 253 SCLive)

    26/29

    This latest version requires a few clarifications to understand some of the subtletiesof SystemC.First, the creation of a SystemC module requires the inheritance of a specializedclass called sc_module. This class defines common features found in any modulesuch as their names. As you would expect the sc_module class feature some morecomplex elements that are beyond the scope of this tutorial.

    The second observation that we can make is the existance of the function:module_test. This function is known in C++ as a constructor and is typically used toperform variables initialization. The other important role of the C++ constructor is tomake sure that all the parents used by the current class have been initialized too. Inthe case of a SystemC module its parent class is always the sc_module class. As aresult the constructor module_test has to initialise the class sc_module. Thankfully,the only part of the sc_module class that needs to be initialized is its name of type:sc_module_name. Therefore the following code: module_test(sc_module_name nm)

    defines a parameter for the constructor function called nm of type sc_module_nameand then uses that parameter to initialize the parent class by passing it to the

    constructor of the sc_module class with this semantic: sc_module(nm).

    Module Instances

    A module by itself isnt of much use until we start creating instances of it. To createan instance of a module we use a semantics very similar to existing HDLs likeVerilog:

    module_test module_test_1(module_test_1);

    Where, module_test is the type of the instance, module_test_1 is the logical name ofthe instance and module_test_1 is the name (string) passed to the constructor ofthe module_test class. This name according to the previous discussion is of typesc_module_name. As can be observed, the sc_module_name data type is verysimilar to a string data type.To put this module instance in context, the following code will illustrate how amodule can be instantiated inside the main function of a SystemC program(sc_main):

    1 // Main program2 int sc_main(int argc, char* argv[])3 {4 module_test module_test_1(module_test_1);5 sc_start();6 return (0);7 }

    The result from the following code would be:

    SystemC 2.2.05jun06_beta Sep 9 2006 10:21:39Copyright (c) 1996-2006 by all ContributorsALL RIGHTS RESERVED

    This is my first module

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    27/29

    A variation on the way that we create a module instance is by declaring a pointer to amodule instead of a module. This method is commonly used to allocate the memoryresources on the mass storage instead of the precious RAM. The following codeillustrate this:

    1 // Main program2 int sc_main(int argc, char* argv[])3 {4 module_test *module_test_1 =5 new module_test(module_test_1);6 sc_start();7 delete module_test_1;8 return (0);9 }

    In this example we used the newinstruction to allocate memory for a module_testinstance and we assign the address of the memory location onto the pointer

    module_test.

    Summary

    This tutorial covered the use of SystemCs modules. A module is a C++ class derivedfrom an existing class: sc_module; consequenlty all SystemC modules requireinitialization to provide their parent class (sc_module) an expected name of type(sc_module_name).This tutorial also covered module instantiations, as demonstrated, instantiating amodule is a simple afair all that is required is a logical name and a string.

    The pdf file for this document and c++ code can be find HERE.

    et Voila !

    David Cabanis

    Categories: SytemC Tutorials

    RSS feed

    Categories

    Burning ISO Files

    Contributed Addon Modules

    Customizing SCLive

    How-tos

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    28/29

    Releases

    SytemC Tutorials

    Tips and Tricks

    Uncategorized

    Virtual Machines

    Recent Posts

    Running the SystemC TLM2 Examples

    Adding Modules to SCLive Manually

    Adding new modules via script

    SCLive 3.0 Release Candidate is Out

    Creating a Persistant SCLive 3.0 on a USB Flash Drive

    Meta

    Register

    Log in

    Entries RSS

    Comments RSS

    WordPress.com

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/

    of 29 06-10-2012 07:00

  • 7/29/2019 253 SCLive)

    29/29

    Blog Stats

    137,537 hits

    TopWordPress

    Blog at WordPress.com. Theme: INove byNeoEase.

    mC Tutorials SCLive http://sclive.wordpress.com/category/sytemc-tutorials/