Changes between Version 47 and Version 48 of Writing Rules/Tlmt


Ignore:
Timestamp:
Feb 21, 2008, 9:39:33 PM (16 years ago)
Author:
fpecheux
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Writing Rules/Tlmt

    v47 v48  
    1313
    1414This document describes the modeling rules for writing TLM-T SystemC simulation models for SoCLib.
    15 These rules enforce the PDES (Parallel Discrete Event Simulation) principles. Each PDES process involved in the simulation has its own local time, and PDES processes synchronize through messages piggybacked with time information.
    16 Models complying to these rules can be used with the "standard" OSCI simulation engine (SystemC 2.x), but can also be used also with others simulation engines, especially distributed, parallelized simulation engines.
     15These rules enforce the PDES (Parallel Discrete Event Simulation) principles. Each PDES process involved in
     16the simulation has its own local time, and PDES processes synchronize through messages piggybacked with time information.
     17Models complying to these rules can be used with the "standard" OSCI simulation engine (SystemC 2.x), but can
     18also be used also with others simulation engines, especially distributed, parallelized simulation engines.
    1719
    1820The interested user should also look at the [WritingRules/General general SoCLib rules].
     
    2022= B) Single VCI initiator and single VCI target =
    2123
    22 Figure 1 presents a minimal system containing one single initiator, '''!VciSimpleInitiator''' , and one single target, '''!VciSimpleTarget''' . The '''!VciSimpleInitiator''' module behavior is modeled by the SC_THREAD  '''execLoop()''', that contains an infinite loop.  The call-back function '''rspReceived()''' is executed when a VCI response packet is received by the initiator module.
     24Figure 1 presents a minimal system containing one single initiator, '''!VciSimpleInitiator''' , and one single
     25target, '''!VciSimpleTarget''' . The '''!VciSimpleInitiator''' module behavior is modeled by
     26the SC_THREAD  '''execLoop()''', that contains an infinite loop.
     27The call-back function '''rspReceived()''' is executed when a VCI response packet is received by the initiator module.
    2328
    2429[[Image(tlmt_figure_1.png, nolink)]]
    2530
    2631Unlike the initiator, the target module has a purely reactive behaviour and is therefore modeled as a call-back function.
    27 Actually, there is no need to use a SC_THREAD : The target behaviour is entirely described by the call-back function '''cmdReceived()''',
     32In other words, there is no need to use a SC_THREAD : The target behaviour is entirely described by the call-back function '''cmdReceived()''',
    2833that is executed when a VCI command packet is received by the target module.
    2934
    30 The VCI communication channel is a point-to-point bi-directionnal channel, encapsulating two separated uni-directionnal channels : one to transmit the VCI command packet, one to transmit the VCI response packet.
     35The VCI communication channel is a point-to-point bi-directionnal channel, encapsulating two separated uni-directionnal
     36channels: one to transmit the VCI command packet, one to transmit the VCI response packet.
    3137
    3238= C) VCI initiator Modeling =
    3339
    34 In the proposed example, the initiator module is modeled by the '''!VciSimpleInitiator''' class. This class inherits from the '''soclib::tlmt::!BaseModule''' class, that acts as the root class for all TLM-T modules. The process time, as well as other useful process attributes, is contained in a C++ structure called a '''tlmt_core::tlmt_thread_context'''.As there is only one thread in this module, there is only one member variable '''c0''' of type '''tlmt_core::tlmt_thread_context'''. '''c0''' mostly corresponds to the PDES process local time ('''H''' on the figure). In all the TLM-T models, time is handled by the '''tlmt_core::tlmt_time''' class. In order to get the time associated to the initiator process, one should use the getter function '''time()''' on the '''c0''' object, and the setter functions '''set_time()''' and '''update_time()''' to assign a new time to the process.
    35 
    36 The '''execLoop()''' method, describing the initiator behaviour must be declared as a member function of the '''!VciSimpleInitiator''' class.
    37 
    38 Finally, the class '''!VciSimpleInitiator''' must contain a member variable '''p_vci''', of type '''!VciInitiator'''. This object has a template parameter <'''vci_param'''> defining the widths of the VCI ADDRESS and DATA fields.
     40In the proposed example, the initiator module is modeled by the '''!VciSimpleInitiator''' class.
     41This class inherits from the '''soclib::tlmt::!BaseModule''' class, that acts as the root class for all TLM-T modules.
     42The process time, as well as other useful process attributes, is contained in a C++ structure called
     43a '''tlmt_core::tlmt_thread_context'''. As there is only one thread in this module, there is only one member
     44variable '''c0''' of type '''tlmt_core::tlmt_thread_context'''. '''c0''' mostly contains the PDES process local
     45time ('''H''' on the figure). In all the TLM-T models, time is handled by the '''tlmt_core::tlmt_time''' class.
     46In order to get the time associated to the initiator process, one should use the getter
     47function '''time()''' on the '''c0''' object, and should use the setter functions
     48'''set_time()''' and '''update_time()''' to assign a new time to the PDES process.
     49
     50The '''execLoop()''' method, describing the initiator behaviour must be declared as a member function of
     51the '''!VciSimpleInitiator''' class.
     52
     53Finally, the class '''!VciSimpleInitiator''' must contain a member variable '''p_vci''', of type '''!VciInitiator'''.
     54This object has a template parameter <'''vci_param'''> defining the widths of the VCI ADDRESS and DATA fields.
    3955
    4056== C.1) Sending a VCI command packet ==
    4157
    42 To send a VCI command packet, the '''execLoop()''' method must use the '''send()''' method, that is a member function of the '''p_vci''' port. The prototype is the following:
    43 {{{
    44 void send(vci_cmd_packet<vci_param> *cmd,       // VCI command packet   
    45           tlmt_core::tlmt_time time);           // initiator local time
    46 }}}
    47 
    48 The informations transported by a VCI command packet are defined below:
     58To send a VCI command packet, the '''execLoop()''' method must use the '''send()''' method, that is a member function of
     59the '''p_vci''' port. The prototype is the following:
     60{{{
     61void send(soclib::tlmt::vci_cmd_packet<vci_param> *cmd, // pointer to a VCI command packet     
     62          tlmt_core::tlmt_time time);                   // initiator local time
     63}}}
     64
     65The contents of a VCI command packet is defined below:
    4966{{{
    5067template<typename vci_param>
     
    6683The possible values for the '''cmd''' filed are  `vci_param::CMD_READ`, `vci_param::CMD_WRITE`, `vci_param::CMD_READ_LOCKED`,
    6784and `vci_param::CMD_STORE_COND`.
    68 The '''contig''' field can be used for optimisation.
    69 
    70 The '''send()''' function is non-blocking. To implement a blocking transaction (such as a cache line read, where the processor is ''frozen'' during the VCI transaction), the model designer must use the SystemC '''sc_core::wait(x)''' primitive ('''x''' being of type '''sc_core::sc_event''') : the '''execLoop()''' thread is then suspended, and will be reactivated when the response packet is actually received.
     85The '''contig''' field can be used for optimization.
     86
     87The '''send()''' function is non-blocking.
     88To implement a blocking transaction (such as a cache line read, where the processor is ''frozen'' during the VCI transaction),
     89the model designer must use the SystemC '''sc_core::wait(x)''' primitive ('''x''' being of type '''sc_core::sc_event'''):
     90the '''execLoop()''' thread is then suspended, and will be reactivated when the response packet is actually received.
    7191
    7292== C.2) Receiving a VCI response packet ==
    7393
    74 To receive a VCI response packet, a call-back function must be defined as a member function of the class '''!VciSimpleInitiator'''. This call-back function (named '''rspReceived()''' in the example), is executed each time a VCI response packet is received on the '''p_vci''' port. The function name is not constrained, but the arguments must respect the following prototype:
    75 {{{
    76 tmpl(tlmt_core::tlmt_return&)::callback(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
    77             const tlmt_core::tlmt_time &time,
    78             void *private_data)
    79 }}}
    80 
    81 The informations transported by a VCI response packet are defined below:
     94To receive a VCI response packet, a call-back function must be defined as a member function of the
     95class '''!VciSimpleInitiator'''. This call-back function (named '''rspReceived()''' in the example), must be
     96declared in the '''!VciSimpleInitiator''' class and
     97is executed each time a VCI response packet is received on the '''p_vci''' port. The function name is not
     98constrained, but the arguments must respect the following prototype:
     99{{{
     100tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     101         const tlmt_core::tlmt_time &time,
     102         void *private_data);
     103}}}
     104
     105The contents of a VCI response packet is defined below:
    82106{{{
    83107template<typename vci_param>
     
    94118}}}
    95119
    96 The actions executed by the call-back function depend on the response transaction type ('''cmd''' field), as well as the '''pktid''' and '''trdid''' fields.
     120The second parameter, '''time''', is of type '''tlmt_core::tlmt_time''' and corresponds to the time of the response. The third parameter,
     121'''private_data''' has a default value of '''NULL''' and is not used when transmitting or receiving VCI packets.
     122
     123
     124The actions executed by the call-back function depend on the response transaction type ('''cmd''' field), as well as
     125the '''pktid''' and '''trdid''' fields.
    97126
    98127In the proposed example :
    99  * In case of of a blocking read , the call-back function updates the local time, and activates the suspended thread.
     128 * In case of of a blocking read , the call-back function updates the local time, and reactivates the suspended thread.
    100129 * In case of a non-blocking write, the call-back function does nothing.
    101130 
    102131== C.3) Initiator Constructor ==
    103132
    104 The constructor of the class '''!VciSimpleInitiator''' must initialize all the member variables, including the '''p_vci''' port. The '''rspReceived()''' call-back function being executed in the context of the thread sending the response packet, a link between the '''p_vci''' port and the call-back function must be established. Moreover, the '''p_vci''' port must contain a pointer to the initiator thread context '''c0'''.
     133The constructor of the class '''!VciSimpleInitiator''' must initialize all the member variables, including
     134the '''p_vci''' port. The '''rspReceived()''' call-back function being executed in the context of the thread sending
     135the response packet, a link between the '''p_vci''' port and the call-back function must be established.
     136Moreover, the '''p_vci''' port must contain a pointer to the initiator thread context '''c0'''. This allows the target to
     137get information on the initiator that actually sends VCI packets (the initiator local time, the initiator activity, etc).
    105138
    106139The '''!VciInitiator''' constructor for the '''p_vci_''' object must be called with the following arguments:
     
    112145== C.4) Lookahead parameter ==
    113146
    114 The SystemC simulation engine behaves as a cooperative, non-preemptive multi-tasks system. Any thread in the system must stop execution after at some point, in order to allow the other threads to execute. With the proposed approach, a TLM-T initiator will never stop if it does not execute blocking communication (such as a processor that has all code and data in the L1 caches).
    115 
    116 To solve this issue, it is necessary to define - for each initiator module- a '''lookahead''' parameter. This parameter defines the maximum number of cycles that can be executed by the thread before it is automatically stopped. The '''lookahead''' parameter allows the system designer to bound the de-synchronization time interval between threads.
    117 
    118 A small value for this parameter results in a better timing accuracy for the simulation, but implies a larger number of context switches, and a slower simulation speed.
     147The SystemC simulation engine behaves as a cooperative, non-preemptive multi-tasks system. Any thread in the system must stop execution
     148after at some point, in order to allow the other threads to execute. With the proposed approach, a TLM-T initiator will never stop if
     149it does not execute blocking communication (such as a processor that has all code and data in the L1 caches).
     150
     151To solve this issue, it is necessary to define -for each initiator module- a '''lookahead''' parameter. This parameter defines the maximum
     152number of cycles that can be executed by the thread before it is automatically stopped. The '''lookahead''' parameter allows the system designer
     153to bound the de-synchronization time interval between threads.
     154
     155A small value for this parameter results in a better timing accuracy for the simulation, but implies a larger number of context switches,
     156and a slower simulation speed.
    119157
    120158== C.4) VCI initiator example ==
    121159
    122160{{{
    123 template <typename vci_param>
    124 class my_initiator : tlmt::BaseModule {
     161
     162////////////////////////// vci_simple_initiator.h ////////////////////////////////
     163
     164#ifndef VCI_SIMPLE_INITIATOR_H
     165#define VCI_TLMT_SIMPLE_INITIATOR_H
     166
     167#include <tlmt>
     168#include "tlmt_base_module.h"
     169#include "vci_ports.h"
     170
     171namespace soclib { namespace tlmt {
     172
     173template<typename vci_param>
     174class VciSimpleInitiator
     175    : public soclib::tlmt::BaseModule
     176{
     177    tlmt_core::tlmt_thread_context c0;
     178    sc_core::sc_event m_rsp_received;
     179    tlmt_core::tlmt_return m_return;
     180    soclib::tlmt::vci_cmd_packet<vci_param> cmd;
     181
     182    uint32_t addresses[8];       // address table,
     183    uint32_t localbuf[8];        // local buffer
     184   
     185    uint32_t m_counter;          // iteration counter
     186    uint32_t m_lookahead;        // lookahead value
     187    uint32_t m_index;            // initiator index
     188   
     189protected:
     190    SC_HAS_PROCESS(VciSimpleInitiator);
     191
    125192public:
    126     VciInitiatorPort <vci_param>  p_vci;
     193    soclib::tlmt::VciInitiator<vci_param> p_vci;
     194
     195    VciSimpleInitiator( sc_core::sc_module_name name,
     196                                uint32_t initiator index,
     197                                uint32_t lookahead );
     198
     199    tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     200         const tlmt_core::tlmt_time &time,
     201         void *private_data);
     202    void behavior();
     203};
     204
     205}}
     206
     207#endif
     208
     209////////////////////////// vci_simple_initiator.cpp ////////////////////////////////
     210
     211#include "../include/vci_simple_initiator.h"
     212
     213namespace soclib { namespace tlmt {
     214
     215#define tmpl(x) template<typename vci_param> x VciSimpleInitiator<vci_param>
     216
     217tmpl(tlmt_core::tlmt_return&)::rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     218        const tlmt_core::tlmt_time &time,
     219        void *private_data)
     220{
     221    if(pkt->cmd == vci_param::VCI_CMD_READ) {
     222        c0.set_time(time + tlmt_core::tlmt_time(pkt->length));
     223        m_rsp_received.notify(sc_core::SC_ZERO_TIME) ;
     224    }
     225    return m_return;
     226}
     227
     228tmpl(void)::behavior()
     229{
     230
     231        for(;;) {
     232
     233                // sending a read VCI packet
    127234               
    128     //////// constructor
    129     my_initiator (sc_module_name name,
    130                          uint32_t initiatorIndex
    131                          uint32_t lookahead) :
    132     p_vci(“vci”, this, &my_initiator::rspReceived, &m_time),
    133     tlmt::BaseModule(name),
    134     m_time(0)
    135     {
    136     m_index = InitiatorIndex;
    137     m_lookahed = lookahead;
    138     m_counter = 0;
    139     SC_THREAD(execLoop);
    140     } // end constructor
     235                cmd.cmd = vci_param::CMD_READ;  // a VCI read packet
     236                addresses[0] = 0xBFC00000;      // the start address
     237                cmd.address = addresses;        // assigned
     238                cmd.be = 0xF;                   // reading full words
     239                cmd.contig = true;              // at successive addresses
     240                cmd.buf = localbuf;             // storing the read results in localbuf
     241                cmd.length = 8;                 // packet of 8 words
     242                cmd.srcid = 0;                  // srcid=0
     243                cmd.trdid = 0;                  // trdid=0
     244                cmd.pktid = 0;                  // pktid=0
     245
     246                tlmt_core::tlmt_return ret;        // in case a test on the send function is needed
     247                ret = p_vci.send(&cmd, c0.time()); // sending the packet
     248                sc_core::wait(m_rsp_received);     // and waiting for the response packet
     249
     250                // sending a write VCI packet
    141251               
    142 private:
    143     tlmt_time m_time;  // local clock
    144     uint32_t m_index;  // initiator index
    145     uint32_t m_counter;  // iteration counter
    146     uint32_t m_lookahed;  // lookahead value
    147     vci_param::data_t m_data[8];         // local buffer
    148     vci_cmd_t   m_cmd;  // paquet VCI commande
    149     sc_event  m_rsp_received; // synchronisation signal
    150 
    151     //////// thread
    152     void execLoop()
    153     {
    154     while(1) {
    155         …
    156         m_cmd.cmd = VCI_CMD_READ;
    157         p_vci.send(&m_cmd, m_time.getTime());   // lecture bloquante
    158         wait(m_rsp_resceived);
    159         …
    160         m_cmd.cmd = VCI_CMD_WRITE;     
    161         p_vci.send(&m_cmd, m_time.getTime());   // écriture non bloquante
    162         ...
    163         // lookahead management
    164         m_counter++ ;
    165         if (m_counter >= m_lookahead) {
    166             m_counter = 0 ;
    167             wait(SC_ZERO_TIME) ;
    168         } // end if
    169         m_time.addtime(1) ;
    170         } // end while
    171     } // end execLoop()
    172 
    173     //////////////// call-back function
    174     void  rspReceived(vci_cmd_t *cmd, uint32_t rsp_time)
    175     {
    176     if(cmd == VCI_CMD_READ) {
    177         m_time.set_time(rsp_time + length);
    178         m_rsp_received.notify(SC_ZERO_TIME) ;
    179     }
    180     } // end rspReceived()
    181 } // end class my_initiator
     252                localbuf[0]=0x00112233;         // first, fill the write local buffer with write data
     253               
     254                cmd.cmd = vci_param::CMD_WRITE; // then issue the VCI write packet
     255                addresses[0] = 0x10000000;      // starting with this address
     256                cmd.address = addresses;
     257                cmd.be = 0xF;
     258                cmd.contig = 0;
     259                cmd.buf = localbuf;
     260                cmd.length = 1;
     261                cmd.srcid = 0;
     262                cmd.trdid = 0;
     263                cmd.pktid = 0;
     264
     265                ret = p_vci.send(&cmd, c0.time()); // Don't wait for the answer
     266
     267                // lookahead management
     268                m_counter++ ;
     269                if (m_counter >= m_lookahead) {
     270                   m_counter = 0 ;
     271                   sc_core::wait(sc_core::SC_ZERO_TIME) ;
     272                } // end if
     273               
     274                // process time= process time+1
     275                c0.set_time(c0.time()+tlmt_core::tlmt_time(1)) ;
     276
     277        }
     278}
     279
     280tmpl(/**/)::VciSimpleInitiator( sc_core::sc_module_name name,
     281                                uint32_t initiator index,
     282                                uint32_t lookahead)
     283                   : soclib::tlmt::BaseModule(name),
     284                     m_index(initiator_index),
     285                     m_lookahead(lookahead),
     286                     m_counter(0),
     287                   p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleInitiator,soclib::tlmt::vci_rsp_packet<vci_param> *>(
     288                                         this, &VciSimpleInitiator<vci_param>::rspReceived), &c0)
     289{
     290        SC_THREAD(behavior);
     291}
     292
     293}}
     294
    182295}}}
    183296
    184297= D) VCI target modeling =
    185298
    186 In the proposed example, the target handle two types of command : a read burst of 8 words, and a write burst of 8 words. To simplify the model, there is no error management.
    187 
    188 The class '''my_target''' inherit the class '''!BaseModule''', that is the basis for all TLM-T modules. The class '''my_target''' contains a member variable '''p_vci''' of type '''!VciTargetPort'''. This object has a template parameter '''<vci_param>''' defining the widths of the VCI ADRESS & DATA fields.
     299In the proposed example, the target handles two types of command: a read burst of 8 words, and a write burst of 8 words.
     300To simplify the model, there is no error management.
     301
     302The class '''!VciSimpleTarget''' inherits from the class '''!BaseModule'''. The class '''!VciSimpleTarget''' contains a member
     303variable '''p_vci''' of type '''!VciTarget'''. This object has a template parameter '''<vci_param>''' defining the widths of
     304the VCI ADDRESS and DATA fields.
    189305
    190306== D.1) Receiving a VCI command packet ==
    191307
    192 To receive a VCI command packet, a call-back function must be defined as a member function of the class '''my_target'''. This call-back function (named '''cmdReceived()''' in the example), will be executed each time a VCI command packet is received on the '''p_vci''' port. The function name is not constrained, but the arguments must respect the following prototype:
    193 {{{
    194 uint32_t  cmdReceived(vci_cmd_t  *cmd,
    195                uint32_t  time)
     308To receive a VCI command packet, a call-back function must be defined as a member function of the class '''!VciSimpleTarget'''.
     309This call-back function (named '''cmdReceived()''' in the example), will be executed each time a VCI command packet is received on
     310the '''p_vci''' port. The function name is not constrained, but the arguments must respect the following prototype:
     311{{{
     312tlmt_core::tlmt_return &cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     313         const tlmt_core::tlmt_time &time,
     314         void *private_data);
    196315}}} 
    197316For the read and write transactions, the actual data transfer is performed by this '''cmdReceived()''' function.
    198 To avoid multiple data copies, only the pointer on the initiator data buffer is transported in the VCI command pacquet (source buffer for a write transaction, or destination buffer for a read transaction).
     317To avoid multiple data copies, only the pointer on the initiator data buffer is transported in the VCI command packet
     318(source buffer for a write transaction, or destination buffer for a read transaction).
    199319
    200320== D.2) Sending a VCI response packet ==
    201321
    202 To send a VCI response packet the '''cmdReceived()''' function must use the '''send()''' method, that is a member function of the class '''!VciTargetPort''', and has the following prototype:
    203 {{{
    204 void  send( vci_rsp_t *cmd,     
    205            uint32_t time)       
    206 }}}
    207 For a reactive target, the response packet date is computed as the command packet date plus the target intrinsic latency.
     322To send a VCI response packet the '''cmdReceived()''' function must use the '''send()''' method, that is a member function of
     323the class '''!VciTarget''', and has the following prototype:
     324{{{
     325void send(soclib::tlmt::vci_rsp_packet<vci_param> *rsp, // pointer to a VCI response packet     
     326          tlmt_core::tlmt_time time);                   // initiator local time
     327}}}
     328For a reactive target, the response packet time is computed as the command packet time plus the target intrinsic latency.
    208329
    209330== D.3) Target Constructor ==
    210331
    211 The constructor of the class '''my_target''' must initialize all the member variables, including the '''p_vci''' port. The '''cmdReceived()''' call-back function being executed in the context of the thread sending the command packet, a link between the '''p_vci''' port and the call-back function must be established.
    212 The '''!VciTargetPort''' constructor must be called with the following arguments:
    213 {{{
    214 p_vci(“vci”, this, &my_initiator::cmdReceived)
     332The constructor of the class '''!VciSimpleTarget''' must initialize all the member variables, including
     333the '''p_vci''' port. The '''cmdReceived()''' call-back function being executed in the context of the thread sending the command packet,
     334a link between the '''p_vci''' port and the call-back function must be established.
     335The '''!VciTarget''' constructor must be called with the following arguments:
     336{{{
     337p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleTarget,soclib::tlmt::vci_cmd_packet<vci_param> *>(
     338                                   this, &VciSimpleTarget<vci_param>::cmdReceived))
    215339}}}
    216340 
    217341== D.4) VCI target example ==
    218342 {{{
    219 template <typename vci_param>
    220 class my_target : tlmt::BaseModule {
     343
     344////////////////////////// vci_simple_target.h ////////////////////////////////
     345
     346#ifndef VCI_SIMPLE_TARGET_H
     347#define VCI_SIMPLE_TARGET_H
     348
     349#include <tlmt>
     350#include "tlmt_base_module.h"
     351#include "vci_ports.h"
     352
     353namespace soclib { namespace tlmt {
     354
     355template<typename vci_param>
     356class VciSimpleTarget
     357    : public soclib::tlmt::BaseModule
     358{
     359private:
     360    tlmt_core::tlmt_return m_return;
     361    uint32_t m_index;
     362    uint32_t m_latency;
     363    soclib::tlmt::vci_rsp_packet<vci_param> rsp;
     364   
    221365public:
    222     VciTargetPort<vci_param>  p_vci;
    223 
    224     ////////////// constructor
    225     my_target (sc_module_name   name,
     366    soclib::tlmt::VciTarget<vci_param> p_vci;
     367
     368    VciSimpleTarget(sc_core::sc_module_name name,
    226369              uint32_t  targetIndex,
    227               uint32_t  latency):
    228     p_vci(“vci”,this, &my_target::cmdReceived),
    229     tlmt::BaseModule(name)
    230     {
    231     m_latency = latency;
    232     m_index = targetIndex;
    233     } // end constructor
     370              uint32_t  latency);
     371
     372    tlmt_core::tlmt_return &cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     373         const tlmt_core::tlmt_time &time,
     374         void *private_data);
     375};
     376
     377}}
     378
     379#endif
     380
     381////////////////////////// vci_simple_target.cpp ////////////////////////////////
     382
     383#include "../include/vci_simple_target.h"
     384
     385namespace soclib { namespace tlmt {
     386
     387#define tmpl(x) template<typename vci_param> x VciSimpleTarget<vci_param>
     388
     389tmpl(tlmt_core::tlmt_return&)::cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     390        const tlmt_core::tlmt_time &time,
     391        void *private_data)
     392{
     393    uint32_t m_data[128];
    234394       
    235 private:
    236     vci_param::data_t  m_data[8];  // local buffer
    237     uint32_t  m_latency;         // target latency
    238     uint32_t  m_index;  // target index
    239     vci_rsp_t  m_rsp;  // paquet VCI réponse
    240 
    241     /////////////// call-back function
    242     uint32_t  cmdReceived(vci_cmd_t *cmd,
    243                 uint32_t cmd_time)
    244     {
    245     if(cmd->cmd == VCI_CMD_WRITE) {
    246         for(int i = 0 ; i < length ; i++) m_data[i] = cmd->buf[i];
     395    if(pkt->cmd == vci_param::VCI_CMD_WRITE) {
     396        for(int i = 0 ; i < pkt->length ; i++)
     397                m_data[i] = cmd->buf[i];
    247398        }
    248     if(cmd->cmd == VCI_CMD_READ) {
    249         for(int i = 0 ; i < length ; i++) cmd->buf[i] = m_data[i];
     399    if(pkt->cmd == vci_param::VCI_CMD_READ) {
     400        for(int i = 0 ; i < pkt->length ; i++)
     401                cmd->buf[i] = m_data[i];
    250402        }
    251     m_rsp.srcid = cmd->srcid;
    252     m_rsp.trdid  = cmd->trdid;
    253     m_rsp.pktid = cmd>pktid;
    254     m_rsp.length = cmd->length;
    255     m_rsp.error = 0;
    256     rsp_time = cmd_time + latency;
    257     p_vci.send(&m_rsp, rsp_time) ;
    258     return (rsp_time + cmd->length);
    259    } // end cmdReceived()
    260 } // end class my_target
     403    rsp.srcid = pkt->srcid;
     404    rsp.trdid  = pkt->trdid;
     405    rsp.pktid = pkt->pktid;
     406    rsp.length = pkt->length;
     407    rsp.error = 0;
     408    p_vci.send(&m_rsp, time+tlmt_core::tlmt_time(latency+pkt->length)) ;
     409    m_return.time=time+tlmt_core::tlmt_time(latency+pkt->length;
     410    return (m_return);
     411}
     412
     413tmpl(/**/)::VciSimpleTarget(sc_core::sc_module_name name,
     414              uint32_t  targetIndex,
     415              uint32_t  latency)
     416        : soclib::tlmt::BaseModule(name),
     417        m_index(targetIndex),
     418        m_latency(latency),
     419        p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleTarget,soclib::tlmt::vci_cmd_packet<vci_param> *>(
     420                                   this, &VciSimpleTarget<vci_param>::cmdReceived))
     421{
     422}
     423
     424}}
     425
    261426}}}
    262427
     
    265430The VCI interconnect used for the TLM-T simulation is a generic simulation model, named '''!VciVgmn'''.
    266431The two main parameters are the number of initiators, and the number of targets. In TLM-T simulation,
    267 we don't want to reproduce the cycle-accurate behavior of a particular interconnect. We only want to simulate the contention in the network, when several VCI intitiators try to reach the same VCI target.
    268 Therefore, the network is actually modeled as a complete cross-bar : In a physical network such as the multi-stage network described in Figure 2.a, conflicts can appear at any intermediate switch. In the '''!VciVgmn''' network described in Figure 2.b, conflicts can only happen at the output ports. It is possible to specify a specific latency for each input/output couple. As in most physical interconnects, the general arbitration policy is round-robin.
     432we don't want to reproduce the cycle-accurate behavior of a particular interconnect. We only want to simulate the contention in
     433the network, when several VCI intitiators try to reach the same VCI target.
     434Therefore, the network is actually modeled as a complete cross-bar : In a physical network such as the multi-stage network described
     435in Figure 2.a, conflicts can appear at any intermediate switch. In the '''!VciVgmn''' network described in Figure 2.b, conflicts can
     436only happen at the output ports. It is possible to specify a specific latency for each input/output couple. As in most physical
     437interconnects, the general arbitration policy is round-robin.
    269438
    270439[[Image(tlmt_figure_2.png, nolink)]]
     
    272441== E.1) Generic network modeling ==
    273442
    274  There is actually two fully independent networks for VCI command packets and VCI response packets. There is a routing function for each input port, and an arbitration function for each output port, but the two networks are not symmetrical :
    275  * For the command network, the arbitration policy is distributed: there is one arbitration thread for each output port (i.e. one arbitration thread for each VCI target). Each arbitration thread is modeled by a SC_THREAD, and contain a local clock.
    276  * For the response network, there is no conflicts, and there is no need for arbitration. Therefore, there is no thread (and no local time) and the response network is implemented by simple function calls.
     443 There is actually two fully independent networks for VCI command packets and VCI response packets. There is a routing function for each input
     444 port, and an arbitration function for each output port, but the two networks are not symmetrical :
     445 * For the command network, the arbitration policy is distributed: there is one arbitration thread for each output port
     446 (i.e. one arbitration thread for each VCI target). Each arbitration thread is modeled by a SC_THREAD, and contains a local clock.
     447 * For the response network, there are no conflicts, and there is no need for arbitration. Therefore, there is no thread
     448 (and no local time) and the response network is implemented by simple function calls.
    277449
    278450This is illustrated in Figure 3 for a network with 2 initiators and three targets : 
     
    280452[[Image(tlmt_figure_3.png, nolink)]]
    281453
    282 == E.2) VCI initiators and targets synchronisations ==
    283 
    284 As described in sections B & C, each VCI initiator TLM-T module contains a thread and a local clock. But, in order to increase the TLM-T simulation speed,  the VCI targets are generally described by reactive call-back functions. Therefore, there is no thread, and no local clock in the TLM-T module describing a VCI target. For a VCI target, the local clock is actually the clock associated to the corresponding arbitration thread contained in the '''!VciVgmn''' module.
    285 
    286 As described in Figure 4, when a VCI command packet - sent by the corresponding arbitration thread - is received by a VCI target, two synchronization mechanisms are activated :
    287  * The '''cmdReceived()''' function sends a VCI response packet with a date to the source initiator, through the '''!VciVgmn''' response network. The corresponding date can be used to update the initiator local clock.
    288  * The '''cmdReceived()''' function returns a date to the arbitration thread. This date is used to update the arbitration thread local clock. 
     454== E.2) VCI initiators and targets synchronizations ==
     455
     456As described in sections B & C, each VCI initiator TLM-T module contains a thread and a local clock. But, in order to increase the TLM-T simulation
     457speed,  the VCI targets are generally described as reactive call-back functions. Therefore, there is no thread, and no local clock in the TLM-T
     458module describing a VCI target. For a VCI target, the local clock is actually the clock associated to the corresponding arbitration
     459thread contained in the '''!VciVgmn''' module.
     460
     461As described in Figure 4, when a VCI command packet - sent by the corresponding arbitration thread - is received by a VCI target,
     462two synchronization mechanisms are activated :
     463 * The '''cmdReceived()''' function sends a VCI response packet with an associated time to the source initiator, through
     464 the '''!VciVgmn''' response network. The corresponding time can be used to update the initiator local clock.
     465 * The '''cmdReceived()''' function returns a time to the arbitration thread. This time is used to update the arbitration thread local
     466 clock. 
    289467
    290468[[Image(tlmt_figure_4.png, nolink)]]
     
    292470= F) Interrupt modeling =
    293471
    294 Interrupts are asynchronous events that are not transported by the VCI network.
    295 
    296 As illustrated in Figure 5, each interrupt line is modeled by a specific point to point, uni-directional channel. It use two ports of type '''!SynchroOutPort''' and '''!SynchroInPort''' that must be declared as member variables of the source and destination modules respectively.
     472Interrupts are asynchronous events that are not carried by the VCI network.
     473
     474As illustrated in Figure 5, each interrupt line is modeled by a specific point to point, uni-directional channel. This channel uses two ports of
     475type '''tlmt_core::tlmt_out<bool>''' and '''tlmt_core::tlmt_in<bool>''' that must be declared as member variables of the source and
     476destination modules respectively.
    297477
    298478[[Image(tlmt_figure_5.png, nolink)]]
     
    300480== F.1) Source modeling ==
    301481
    302 The source module (named '''my_source''' in this example) must contain a member variable '''p_irq''' of type '''!SynchroOutPort'''. To activate, or desactivate an interruption, the source module must use the '''send()''' method, that is a member function of the '''!SynchroOutPort''' class. Those interrupt packets transport both a Boolean, and a date. The '''send()''' prototype is defined as follows :
    303 {{{
    304 void  send( bool  val, uint32_t  time)
     482The source module (named '''!VciSimpleSourceInterrupt''' in this example) must contain a member variable '''p_irq''' of
     483type '''tlmt_core::tlmt_out<bool>'''. To activate, or desactivate an interruption, the source module must use the '''send()''' method,
     484that is a member function of the '''tlmt_core::tlmt_out<bool>''' class. These interrupt packets transport both a Boolean,
     485and a time. The '''send()''' prototype is defined as follows :
     486{{{
     487void  send( bool  val, const tlmt_core::tlmt_time &time)
    305488}}}
    306489
    307490== F.2) Destination modeling ==
    308491
    309 The destination module (named here '''my_processor''') must contain a member variable '''p_irq''' of type
    310 '''!SynchroInPortt''', and a call-back function (named here '''irqReceived()''' that is executed when an interrupt packet is received on the '''p_irq''' port.
    311 
    312 A link between the '''p_irq''' port and the call-back function mus be established by the port constructor in the constructor of the class '''my_processor''' :
    313 {{{
    314 p_irq(“irq”, this, &my_processor::irqReceived)
    315 }}}
    316 
    317 In the Parallel Discrete Event Simulation, the pessimistic approach suppose that any PDES process is not allowed to update his local time until he has received messages  on all input ports with dates larger than his local time.
    318 
    319 Therefore, a SC_THREAD modeling the behavior of a processor containing an '''!SynchroInPort''' should in principle wait a dated packet on this interrupt port before executing instructions. Such behavior would be very inefficient, and could create dead-lock situations.
     492The destination module (named here '''!VciProcessor''') must contain a member variable '''p_irq''' of type
     493'''tlmt_core::tlmt_in<bool>''', and a call-back function (named here '''irqReceived()''' that is executed when an interrupt
     494packet is received on the '''p_irq''' port.
     495
     496A link between the '''p_irq''' port and the call-back function must be established by the port constructor in the constructor of
     497the class '''VciProcessor''' :
     498{{{
     499tlmt_core::tlmt_callback < VciProcessor,bool >(this, &VciProcessor < iss_t,
     500           vci_param >::irqReceived);
     501}}}
     502
     503In the Parallel Discrete Event Simulation, the pessimistic approach relies on the fact that any PDES process is not allowed to update
     504his local time until it has received messages on all its input ports with times greater than its local time.
     505
     506Therefore, a SC_THREAD modeling the behavior of a processor containing an '''tlmt_core::tlmt_in<bool>''' should in principle
     507wait a timestamped packet on its interrupt port before executing instructions. However, such a behavior would be very inefficient,
     508and is prone to dead-lock situations.
    320509
    321510The recommended policy for handling interrupts is the following:
    322  * The call-back function '''irqReceived()''' sets the member variables '''m_irqpending''' and '''m_irqtime''', when a interrupt packet is received on the '''p_irq''' port.
    323  * The '''execLoop()''' thread must test the '''m_irqpending''' variable at each cycle (i.e. in each iteration of the infinite loop).
    324  * If there is no interrupt pending, the thread continues execution. If an interrupt is pending, and the interrupt date is larger than the local time, the thread continues execution. If the interrupt date is equal or smaller than the local time, the interrupt is handled.
    325 
    326 Such violation of the the pessimistic parallel simulation create a loss of accuracy on the interrupt handling date. This inaccuracy in the TLM-T simulation is acceptable, as interrupts are asynchronous events, and the timing error is bounded by the '''m_lookahead''' parameter.
     511 * The call-back function '''irqReceived()''' sets the member variables '''m_irqpending''' and '''m_irqtime''', when a interrupt packet
     512 is received on the '''p_irq''' port.
     513 * The '''execLoop()''' thread must test the '''m_irqpending''' variable at each cycle (i.e. in each iteration of
     514 the infinite loop).
     515 * If there is no interrupt pending, the thread continues its execution. If an interrupt is pending, and the interrupt time is greater
     516 than the local time, the thread continues execution. If the interrupt time is equal or smaller than the local time, the interrupt
     517 is handled.
     518
     519Such a violation of the the pessimistic parallel simulation principles creates a loss of accuracy on the interrupt handling
     520timestamp. This loss of accuracy in the TLM-T simulation is acceptable, as interrupts are asynchronous events, and the timing error
     521is bounded by the '''m_lookahead''' parameter.
    327522
    328523== F.3)  Processor with interrupt example ==
    329524
    330525{{{
    331 class my_processor : tlmt::BaseModule {
     526
     527////////////////////////// vci_processor.h ////////////////////////////////
     528
     529namespace soclib { namespace tlmt {
     530
     531template<typename iss_t,typename vci_param>
     532class VciProcessor
     533    : public soclib::tlmt::BaseModule
     534{
     535    tlmt_core::tlmt_thread_context c0;
     536    sc_core::sc_event m_rsp_received;
     537    tlmt_core::tlmt_return m_return;
     538    bool  m_irqpendig;  // pending interrupt request
     539    tlmt_core::tlmt_time  m_irqtime;  // irq date
     540    uint32_t  m_counter;  // iteration counter
     541    uint32_t  m_lookahead;  // lookahead value
     542   
     543protected:
     544    SC_HAS_PROCESS(VciProcessor);
     545
    332546public:
    333     SynchroInPort               p_irq;
    334                
    335   ////// constructor
    336     my_processor (sc_module_name        name,
    337                   uint32_t  lookahead) :
    338     p_irq(“irq”, this, &my_initiator::irqReceived),
    339     m_time(0),
    340     tlmt::BaseModule(name)
     547    soclib::tlmt::VciInitiator<vci_param> p_vci;
     548    tlmt_core::tlmt_in<bool> p_irq;
     549
     550    VciProcessor( sc_core::sc_module_name name, int id );
     551
     552    tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     553                const tlmt_core::tlmt_time &time,
     554                void *private_data);
     555    tlmt_core::tlmt_return &irqReceived(bool,
     556                const tlmt_core::tlmt_time &time,
     557                void *private_data);
     558    void execLoop();
     559};
     560
     561}}
     562
     563////////////////////////// vci_processor.cpp ////////////////////////////////
     564
     565#include "../include/vci_processor.h"
     566
     567namespace soclib
     568{
     569  namespace tlmt
     570  {
     571
     572#define tmpl(x) template<typename iss_t, typename vci_param> x VciProcessor<vci_param>
     573
     574    tmpl (tlmt_core::tlmt_return &)::rspReceived (soclib::tlmt:: vci_rsp_packet < vci_param > *pkt,
     575                                                  const tlmt_core:: tlmt_time & time, void *private_data)
    341576    {
    342     m_lookahed = lookahead;
    343     m_counter = 0;
    344     m_irqset = false;
    345     SC_THREAD(execLoop);
    346 } // end constructor
    347                
    348 private:
    349     tlmt_time  m_time;  // local clock
    350     bool  m_irqpendig;  // pending interrupt request
    351     uint32_t  m_irqtime;  // irq date
    352     uint32_t  m_counter;  // iteration counter
    353     uint32_t  m_lookahed;  // lookahead value
    354 
    355     /////////////// thread
    356     void execLoop()
     577      if (pkt->cmd == vci_param::CMD_WRITE)
     578        m_write_error = (pkt->error != 0);
     579      else
     580        m_write_error = false;
     581      if (pkt->cmd == vci_param::CMD_READ)
     582        m_read_error = (pkt->error != 0);
     583      else
     584        m_read_error = false;
     585      m_rsptime = time + tlmt_core::tlmt_time (pkt->length);
     586      m_vci_pending = false;
     587      m_rsp_received.notify (sc_core::SC_ZERO_TIME);
     588
     589      return m_return;
     590    }
     591
     592    tmpl (tlmt_core::tlmt_return &)::irqReceived (bool v, const tlmt_core::
     593                                                  tlmt_time & time, void *private_data)
    357594    {
    358     while(1) {
    359         ...
    360         // test interrupts
    361         if (m_irqpending && (m_irqtime <= m_time.getTime())) {
    362                                         // traitement interrupt
    363                                         }
     595      m_irqpending = val;
     596      m_irqtime = time;   
     597   
     598      return m_return;
     599    }
     600
     601
     602    tmpl (void)::execLoop ()
     603        {
     604                while(1) {
     605                        ...
     606                        // test interrupts
     607                        if (m_irqpending && (m_irqtime <= c0.time()))
     608                        {
     609                                // interrupt handling   
     610                        }
    364611                                ...
    365         // lookahead management
    366         m_counter++ ;
    367         if (m_counter >= m_lookahead) {
    368             m_counter = 0 ;
    369             wait(SC_ZERO_TIME) ;
    370             } // end if
    371         m_time.addtime(1) ;
    372         } // end while
    373     } // end execLoop()
    374 
    375 ///////////////////////////////////////
    376      void  irqReceived(bool val, sc_time time)
     612                        // lookahead management
     613                        m_counter++ ;
     614                        if (m_counter >= m_lookahead) {
     615                                m_counter = 0 ;
     616                                sc_core::wait(sc_core::SC_ZERO_TIME) ;
     617                        } // end if
     618                        c0.set_time(c0.time()+tlmt_core::tlmt_time(1)) ;
     619                } // end while
     620        }
     621       
     622  tmpl ( /**/)::VciProcessor(
     623          sc_core::sc_module_name name,
     624          int id )
     625: soclib::tlmt::BaseModule (name),
     626  m_counter (0),
     627  m_lookahead (10),
     628  p_vci("vci",new tlmt_core::tlmt_callback<VciProcessor,vci_rsp_packet<vci_param>*>(
     629        this,&VciProcessor<vci_param>::rspReceived),&c0),
     630  p_irq("irq",new tlmt_core::tlmt_callback<VciProcesspr,bool>(
     631        this,&VciProcessor<vci_param>::irqReceived))
    377632    {
    378     m_irqpending = val;
    379     m_irqtime = time;
    380     } // end irqReceived()
    381 } // end class my_processor
    382 }}}
    383 
     633      SC_THREAD (execLoop);
     634    }
     635
     636}}
     637
     638}}}
     639