Changes between Initial Version and Version 1 of Writing Rules/TLM2


Ignore:
Timestamp:
Sep 18, 2008, 3:15:53 PM (16 years ago)
Author:
alain
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Writing Rules/TLM2

    v1 v1  
     1 {{{
     2#!html
     3<h1>Writing efficient TLM-T SystemC simulation models for SoCLib</h1>
     4}}}
     5
     6Authors : Alain Greiner, François Pêcheux, Emmanuel Viaud, Nicolas Pouillon
     7 
     8[[PageOutline]]
     9
     10= A) Introduction =
     11
     12'''This document is under development'''.
     13
     14This new document describes the modeling rules for writing TLM-T SystemC simulation models for SoCLib.
     15This is the second release, as the modeling rules have been modified to respect the TLM2.0 standard.
     16
     17In TLM2.0, both the '''payload''' (defining the actual content of the exchanged packets), and the '''phase'''
     18(defining the actual communication protocol steps) are template parameters.
     19Therefore, specific '''payload''' and '''phase''' types have been defined for SoCLib.
     20Those types are well suited for the VCI/OCP protocol, but they more general and can
     21used to describe any shared-memory architecture using routed network on chip.
     22 
     23The TLM-T rules used in SoCLib enforce the PDES (Parallel Discrete Event Simulation) principles. Each PDES process involved in
     24the simulation has its own local time, and PDES processes synchronize through messages piggybacked with time information.
     25Models complying to these rules can be used with the "standard" OSCI simulation engine (SystemC 2.x), but can
     26also be used also with others simulation engines, especially distributed, parallelized simulation engines.
     27
     28Before writing a new model, it is useful to have a look at the [WritingRules/General general SoCLib rules].
     29
     30= B) Single VCI initiator and single VCI target =
     31
     32Figure 1 presents a minimal system containing one single initiator, '''!VciSimpleInitiator''' , and one single
     33target, '''!VciSimpleTarget''' . The '''!VciSimpleInitiator''' module behavior is modeled by
     34the SC_THREAD  '''execLoop()''', that contains an infinite loop.
     35
     36[[Image(tlmt_figure_1.png, nolink)]]
     37
     38Unlike the initiator, the target module has a purely reactive behaviour and there is no  need to use a SC_THREAD :
     39The target behaviour is entirely described by the call-back function,
     40that is executed in the context of the '''execLoop() thread when a VCI command packet is received by the target module.
     41
     42The VCI communication channel is a point-to-point bi-directionnal channel, encapsulating two separated uni-directionnal
     43channels: one to transmit the VCI command packet, one to transmit the VCI response packet.
     44
     45= C) VCI initiator Modeling =
     46
     47In the proposed example, the initiator module is modeled by the '''!VciSimpleInitiator''' class.
     48This class inherits from the '''soclib::tlmt::!BaseModule''' class, that acts as the root class for all TLM-T modules.
     49The process time, as well as other useful process attributes, is contained in a C++ structure called
     50a '''tlmt_core::tlmt_thread_context'''. As there is only one thread in this module, there is only one member
     51variable '''c0''' of type '''tlmt_core::tlmt_thread_context'''. '''c0''' mostly contains the PDES process local
     52time ('''H''' on the figure). In all the TLM-T models, time is handled by the '''tlmt_core::tlmt_time''' class.
     53In order to get the time associated to the initiator process, one should use the getter
     54function '''time()''' on the '''c0''' object, and should use the setter functions
     55'''set_time()''' and '''update_time()''' to assign a new time to the PDES process.
     56
     57The '''execLoop()''' method, describing the initiator behaviour must be declared as a member function of
     58the '''!VciSimpleInitiator''' class.
     59
     60Finally, the class '''!VciSimpleInitiator''' must contain a member variable '''p_vci''', of type '''!VciInitiator'''.
     61This object has a template parameter <'''vci_param'''> defining the widths of the VCI ADDRESS and DATA fields.
     62
     63== C.1) Sending a VCI command packet ==
     64
     65To send a VCI command packet, the '''execLoop()''' method must use the '''send()''' method, that is a member function of
     66the '''p_vci''' port. The prototype is the following:
     67{{{
     68void send(soclib::tlmt::vci_cmd_packet<vci_param> *cmd, // pointer to a VCI command packet     
     69          tlmt_core::tlmt_time time);                   // initiator local time
     70}}}
     71
     72The contents of a VCI command packet is defined below:
     73{{{
     74template<typename vci_param>
     75class vci_cmd_packet
     76{
     77public:
     78        typename vci_param::cmd_t cmd;        // VCI transaction type
     79        typename vci_param::addr_t address;   // address on the target side
     80        uint32_t int be;                      // byte_enable value (same value for all packet words)
     81        bool contig;                          // contiguous addresses (when true)
     82        typename vci_param::data_t *buf;      // pointer to the local buffer on the initiator
     83        size_t nwords;                        // number of words in the packet
     84        uint32_t srcid;                       // VCI Source ID
     85        uint32_t trdid;                       // VCI Thread ID
     86        uint32_t pktid;                       // VCI Packet ID
     87};
     88}}}
     89
     90The possible values for the '''cmd''' filed are  `vci_param::CMD_READ`, `vci_param::CMD_WRITE`, `vci_param::CMD_READ_LOCKED`,
     91and `vci_param::CMD_STORE_COND`.
     92The '''contig''' field can be used for optimization.
     93
     94The '''send()''' function is non-blocking.
     95To implement a blocking transaction (such as a cache line read, where the processor is ''frozen'' during the VCI transaction),
     96the model designer must use the SystemC '''sc_core::wait(x)''' primitive ('''x''' being of type '''sc_core::sc_event'''):
     97the '''execLoop()''' thread is then suspended, and will be reactivated when the response packet is actually received.
     98
     99== C.2) Receiving a VCI response packet ==
     100
     101To receive a VCI response packet, a call-back function must be defined as a member function of the
     102class '''!VciSimpleInitiator'''. This call-back function (named '''rspReceived()''' in the example), must be
     103declared in the '''!VciSimpleInitiator''' class and
     104is executed each time a VCI response packet is received on the '''p_vci''' port. The function name is not
     105constrained, but the arguments must respect the following prototype:
     106{{{
     107tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     108         const tlmt_core::tlmt_time &time,
     109         void *private_data);
     110}}}
     111
     112The contents of a VCI response packet is defined below:
     113{{{
     114template<typename vci_param>
     115class vci_rsp_packet
     116{
     117public:
     118        typename vci_param::cmd_t cmd;    // VCI transaction type
     119        size_t nwords;                    // number of words in the packet
     120        uint32_t error;                   // error code (0 if no error)
     121        uint32_t srcid;                   // VCI Source ID
     122        uint32_t trdid;                   // VCI Thread ID
     123        uint32_t pktid;                   // VCI Packet ID
     124};
     125}}}
     126
     127The second parameter, '''time''', is of type '''tlmt_core::tlmt_time''' and corresponds to the time of the response. The third parameter,
     128'''private_data''' has a default value of '''NULL''' and is not used when transmitting or receiving VCI packets.
     129
     130
     131The actions executed by the call-back function depend on the response transaction type ('''cmd''' field), as well as
     132the '''pktid''' and '''trdid''' fields.
     133
     134In the proposed example :
     135 * In case of of a blocking read , the call-back function updates the local time, and reactivates the suspended thread.
     136 * In case of a non-blocking write, the call-back function does nothing.
     137 
     138== C.3) Initiator Constructor ==
     139
     140The constructor of the class '''!VciSimpleInitiator''' must initialize all the member variables, including
     141the '''p_vci''' port. The '''rspReceived()''' call-back function being executed in the context of the thread sending
     142the response packet, a link between the '''p_vci''' port and the call-back function must be established.
     143Moreover, the '''p_vci''' port must contain a pointer to the initiator thread context '''c0'''. This allows the target to
     144get information on the initiator that actually sends VCI packets (the initiator local time, the initiator activity, etc).
     145
     146The '''!VciInitiator''' constructor for the '''p_vci_''' object must be called with the following arguments:
     147{{{
     148p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleInitiator,soclib::tlmt::vci_rsp_packet<vci_param> *>(
     149                                         this, &VciSimpleInitiator<vci_param>::rspReceived), &c0)
     150}}}
     151 
     152== C.4) Lookahead parameter ==
     153
     154The SystemC simulation engine behaves as a cooperative, non-preemptive multi-tasks system. Any thread in the system must stop execution
     155after at some point, in order to allow the other threads to execute. With the proposed approach, a TLM-T initiator will never stop if
     156it does not execute blocking communication (such as a processor that has all code and data in the L1 caches).
     157
     158To solve this issue, it is necessary to define -for each initiator module- a '''lookahead''' parameter. This parameter defines the maximum
     159number of cycles that can be executed by the thread before it is automatically stopped. The '''lookahead''' parameter allows the system designer
     160to bound the de-synchronization time interval between threads.
     161
     162A small value for this parameter results in a better timing accuracy for the simulation, but implies a larger number of context switches,
     163and a slower simulation speed.
     164
     165== C.4) VCI initiator example ==
     166
     167{{{
     168
     169////////////////////////// vci_simple_initiator.h ////////////////////////////////
     170
     171#ifndef VCI_SIMPLE_INITIATOR_H
     172#define VCI_SIMPLE_INITIATOR_H
     173
     174#include <tlmt>
     175#include "tlmt_base_module.h"
     176#include "vci_ports.h"
     177
     178namespace soclib { namespace tlmt {
     179
     180template<typename vci_param>
     181class VciSimpleInitiator
     182    : public soclib::tlmt::BaseModule
     183{
     184    tlmt_core::tlmt_thread_context c0;
     185    sc_core::sc_event m_rsp_received;
     186    tlmt_core::tlmt_return m_return;
     187    soclib::tlmt::vci_cmd_packet<vci_param> cmd;
     188
     189    uint32_t addresses[8];       // address table,
     190    uint32_t localbuf[8];        // local buffer
     191   
     192    uint32_t m_counter;          // iteration counter
     193    uint32_t m_lookahead;        // lookahead value
     194    uint32_t m_index;            // initiator index
     195   
     196protected:
     197    SC_HAS_PROCESS(VciSimpleInitiator);
     198
     199public:
     200    soclib::tlmt::VciInitiator<vci_param> p_vci;
     201
     202    VciSimpleInitiator( sc_core::sc_module_name name,
     203                                uint32_t initiator index,
     204                                uint32_t lookahead );
     205
     206    tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     207         const tlmt_core::tlmt_time &time,
     208         void *private_data);
     209    void behavior();
     210};
     211
     212}}
     213
     214#endif
     215
     216////////////////////////// vci_simple_initiator.cpp ////////////////////////////////
     217
     218#include "../include/vci_simple_initiator.h"
     219
     220namespace soclib { namespace tlmt {
     221
     222#define tmpl(x) template<typename vci_param> x VciSimpleInitiator<vci_param>
     223
     224tmpl(tlmt_core::tlmt_return&)::rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     225        const tlmt_core::tlmt_time &time,
     226        void *private_data)
     227{
     228    if(pkt->cmd == vci_param::VCI_CMD_READ) {
     229        c0.set_time(time + tlmt_core::tlmt_time(pkt->length));
     230        m_rsp_received.notify(sc_core::SC_ZERO_TIME) ;
     231    }
     232    return m_return;
     233}
     234
     235tmpl(void)::behavior()
     236{
     237
     238        for(;;) {
     239
     240                // sending a read VCI packet
     241               
     242                cmd.cmd = vci_param::CMD_READ;  // a VCI read packet
     243                addresses[0] = 0xBFC00000;      // the start address
     244                cmd.address = addresses;        // assigned
     245                cmd.be = 0xF;                   // reading full words
     246                cmd.contig = true;              // at successive addresses
     247                cmd.buf = localbuf;             // storing the read results in localbuf
     248                cmd.length = 8;                 // packet of 8 words
     249                cmd.srcid = 0;                  // srcid=0
     250                cmd.trdid = 0;                  // trdid=0
     251                cmd.pktid = 0;                  // pktid=0
     252
     253                tlmt_core::tlmt_return ret;        // in case a test on the send function is needed
     254                ret = p_vci.send(&cmd, c0.time()); // sending the packet
     255                sc_core::wait(m_rsp_received);     // and waiting for the response packet
     256
     257                // sending a write VCI packet
     258               
     259                localbuf[0]=0x00112233;         // first, fill the write local buffer with write data
     260               
     261                cmd.cmd = vci_param::CMD_WRITE; // then issue the VCI write packet
     262                addresses[0] = 0x10000000;      // starting with this address
     263                cmd.address = addresses;
     264                cmd.be = 0xF;
     265                cmd.contig = 0;
     266                cmd.buf = localbuf;
     267                cmd.length = 1;
     268                cmd.srcid = 0;
     269                cmd.trdid = 0;
     270                cmd.pktid = 0;
     271
     272                ret = p_vci.send(&cmd, c0.time()); // Don't wait for the answer
     273
     274                // lookahead management
     275                m_counter++ ;
     276                if (m_counter >= m_lookahead) {
     277                   m_counter = 0 ;
     278                   sc_core::wait(sc_core::SC_ZERO_TIME) ;
     279                } // end if
     280               
     281                // process time= process time+1
     282                c0.set_time(c0.time()+tlmt_core::tlmt_time(1)) ;
     283
     284        }
     285}
     286
     287tmpl(/**/)::VciSimpleInitiator( sc_core::sc_module_name name,
     288                                uint32_t initiator index,
     289                                uint32_t lookahead)
     290                   : soclib::tlmt::BaseModule(name),
     291                     m_index(initiator_index),
     292                     m_lookahead(lookahead),
     293                     m_counter(0),
     294                   p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleInitiator,soclib::tlmt::vci_rsp_packet<vci_param> *>(
     295                                         this, &VciSimpleInitiator<vci_param>::rspReceived), &c0)
     296{
     297        SC_THREAD(behavior);
     298}
     299
     300}}
     301
     302}}}
     303
     304= D) VCI target modeling =
     305
     306In the proposed example, the target handles two types of command: a read burst of 8 words, and a write burst of 8 words.
     307To simplify the model, there is no error management.
     308
     309The class '''!VciSimpleTarget''' inherits from the class '''!BaseModule'''. The class '''!VciSimpleTarget''' contains a member
     310variable '''p_vci''' of type '''!VciTarget'''. This object has a template parameter '''<vci_param>''' defining the widths of
     311the VCI ADDRESS and DATA fields.
     312
     313== D.1) Receiving a VCI command packet ==
     314
     315To receive a VCI command packet, a call-back function must be defined as a member function of the class '''!VciSimpleTarget'''.
     316This call-back function (named '''cmdReceived()''' in the example), will be executed each time a VCI command packet is received on
     317the '''p_vci''' port. The function name is not constrained, but the arguments must respect the following prototype:
     318{{{
     319tlmt_core::tlmt_return &cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     320         const tlmt_core::tlmt_time &time,
     321         void *private_data);
     322}}} 
     323For the read and write transactions, the actual data transfer is performed by this '''cmdReceived()''' function.
     324To avoid multiple data copies, only the pointer on the initiator data buffer is transported in the VCI command packet
     325(source buffer for a write transaction, or destination buffer for a read transaction).
     326
     327== D.2) Sending a VCI response packet ==
     328
     329To send a VCI response packet the '''cmdReceived()''' function must use the '''send()''' method, that is a member function of
     330the class '''!VciTarget''', and has the following prototype:
     331{{{
     332void send(soclib::tlmt::vci_rsp_packet<vci_param> *rsp, // pointer to a VCI response packet     
     333          tlmt_core::tlmt_time time);                   // initiator local time
     334}}}
     335For a reactive target, the response packet time is computed as the command packet time plus the target intrinsic latency.
     336
     337== D.3) Target Constructor ==
     338
     339The constructor of the class '''!VciSimpleTarget''' must initialize all the member variables, including
     340the '''p_vci''' port. The '''cmdReceived()''' call-back function being executed in the context of the thread sending the command packet,
     341a link between the '''p_vci''' port and the call-back function must be established.
     342The '''!VciTarget''' constructor must be called with the following arguments:
     343{{{
     344p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleTarget,soclib::tlmt::vci_cmd_packet<vci_param> *>(
     345                                   this, &VciSimpleTarget<vci_param>::cmdReceived))
     346}}}
     347 
     348== D.4) VCI target example ==
     349 {{{
     350
     351////////////////////////// vci_simple_target.h ////////////////////////////////
     352
     353#ifndef VCI_SIMPLE_TARGET_H
     354#define VCI_SIMPLE_TARGET_H
     355
     356#include <tlmt>
     357#include "tlmt_base_module.h"
     358#include "vci_ports.h"
     359
     360namespace soclib { namespace tlmt {
     361
     362template<typename vci_param>
     363class VciSimpleTarget
     364    : public soclib::tlmt::BaseModule
     365{
     366private:
     367    tlmt_core::tlmt_return m_return;
     368    uint32_t m_index;
     369    uint32_t m_latency;
     370    soclib::tlmt::vci_rsp_packet<vci_param> rsp;
     371   
     372public:
     373    soclib::tlmt::VciTarget<vci_param> p_vci;
     374
     375    VciSimpleTarget(sc_core::sc_module_name name,
     376              uint32_t  targetIndex,
     377              uint32_t  latency);
     378
     379    tlmt_core::tlmt_return &cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     380         const tlmt_core::tlmt_time &time,
     381         void *private_data);
     382};
     383
     384}}
     385
     386#endif
     387
     388////////////////////////// vci_simple_target.cpp ////////////////////////////////
     389
     390#include "../include/vci_simple_target.h"
     391
     392namespace soclib { namespace tlmt {
     393
     394#define tmpl(x) template<typename vci_param> x VciSimpleTarget<vci_param>
     395
     396tmpl(tlmt_core::tlmt_return&)::cmdReceived(soclib::tlmt::vci_cmd_packet<vci_param> *pkt,
     397        const tlmt_core::tlmt_time &time,
     398        void *private_data)
     399{
     400    uint32_t m_data[128];
     401       
     402    if(pkt->cmd == vci_param::VCI_CMD_WRITE) {
     403        for(int i = 0 ; i < pkt->length ; i++)
     404                m_data[i] = cmd->buf[i];
     405        }
     406    if(pkt->cmd == vci_param::VCI_CMD_READ) {
     407        for(int i = 0 ; i < pkt->length ; i++)
     408                cmd->buf[i] = m_data[i];
     409        }
     410    rsp.srcid = pkt->srcid;
     411    rsp.trdid  = pkt->trdid;
     412    rsp.pktid = pkt->pktid;
     413    rsp.length = pkt->length;
     414    rsp.error = 0;
     415    p_vci.send(&m_rsp, time+tlmt_core::tlmt_time(latency+pkt->length)) ;
     416    m_return.time=time+tlmt_core::tlmt_time(latency+pkt->length;
     417    return (m_return);
     418}
     419
     420tmpl(/**/)::VciSimpleTarget(sc_core::sc_module_name name,
     421              uint32_t  targetIndex,
     422              uint32_t  latency)
     423        : soclib::tlmt::BaseModule(name),
     424        m_index(targetIndex),
     425        m_latency(latency),
     426        p_vci("vci", new tlmt_core::tlmt_callback<VciSimpleTarget,soclib::tlmt::vci_cmd_packet<vci_param> *>(
     427                                   this, &VciSimpleTarget<vci_param>::cmdReceived))
     428{
     429}
     430
     431}}
     432
     433}}}
     434
     435= E) VCI Interconnect =
     436
     437The VCI interconnect used for the TLM-T simulation is a generic simulation model, named '''!VciVgmn'''.
     438The two main parameters are the number of initiators, and the number of targets. In TLM-T simulation,
     439we don't want to reproduce the cycle-accurate behavior of a particular interconnect. We only want to simulate the contention in
     440the network, when several VCI intitiators try to reach the same VCI target.
     441Therefore, the network is actually modeled as a complete cross-bar : In a physical network such as the multi-stage network described
     442in Figure 2.a, conflicts can appear at any intermediate switch. In the '''!VciVgmn''' network described in Figure 2.b, conflicts can
     443only happen at the output ports. It is possible to specify a specific latency for each input/output couple. As in most physical
     444interconnects, the general arbitration policy is round-robin.
     445
     446[[Image(tlmt_figure_2.png, nolink)]]
     447
     448== E.1) Generic network modeling ==
     449
     450 There is actually two fully independent networks for VCI command packets and VCI response packets. There is a routing function for each input
     451 port, and an arbitration function for each output port, but the two networks are not symmetrical :
     452 * For the command network, the arbitration policy is distributed: there is one arbitration thread for each output port
     453 (i.e. one arbitration thread for each VCI target). Each arbitration thread is modeled by a SC_THREAD, and contains a local clock.
     454 * For the response network, there are no conflicts, and there is no need for arbitration. Therefore, there is no thread
     455 (and no local time) and the response network is implemented by simple function calls.
     456
     457This is illustrated in Figure 3 for a network with 2 initiators and three targets : 
     458
     459[[Image(tlmt_figure_3.png, nolink)]]
     460
     461== E.2) VCI initiators and targets synchronizations ==
     462
     463As 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
     464speed,  the VCI targets are generally described as reactive call-back functions. Therefore, there is no thread, and no local clock in the TLM-T
     465module describing a VCI target. For a VCI target, the local clock is actually the clock associated to the corresponding arbitration
     466thread contained in the '''!VciVgmn''' module.
     467
     468As described in Figure 4, when a VCI command packet - sent by the corresponding arbitration thread - is received by a VCI target,
     469two synchronization mechanisms are activated :
     470 * The '''cmdReceived()''' function sends a VCI response packet with an associated time to the source initiator, through
     471 the '''!VciVgmn''' response network. The corresponding time can be used to update the initiator local clock.
     472 * The '''cmdReceived()''' function returns a time to the arbitration thread. This time is used to update the arbitration thread local
     473 clock. 
     474
     475[[Image(tlmt_figure_4.png, nolink)]]
     476
     477= F) Interrupt modeling =
     478
     479Interrupts are asynchronous events that are not carried by the VCI network.
     480
     481As illustrated in Figure 5, each interrupt line is modeled by a specific point to point, uni-directional channel. This channel uses two ports of
     482type '''tlmt_core::tlmt_out<bool>''' and '''tlmt_core::tlmt_in<bool>''' that must be declared as member variables of the source and
     483destination modules respectively.
     484
     485[[Image(tlmt_figure_5.png, nolink)]]
     486
     487== F.1) Source modeling ==
     488
     489The source module (named '''!VciSimpleSourceInterrupt''' in this example) must contain a member variable '''p_irq''' of
     490type '''tlmt_core::tlmt_out<bool>'''. To activate, or desactivate an interruption, the source module must use the '''send()''' method,
     491that is a member function of the '''tlmt_core::tlmt_out<bool>''' class. These interrupt packets transport both a Boolean,
     492and a time. The '''send()''' prototype is defined as follows :
     493{{{
     494void  send( bool  val, const tlmt_core::tlmt_time &time)
     495}}}
     496
     497== F.2) Destination modeling ==
     498
     499The destination module (named here '''!VciProcessor''') must contain a member variable '''p_irq''' of type
     500'''tlmt_core::tlmt_in<bool>''', and a call-back function (named here '''irqReceived()''' that is executed when an interrupt
     501packet is received on the '''p_irq''' port.
     502
     503A link between the '''p_irq''' port and the call-back function must be established by the port constructor in the constructor of
     504the class '''VciProcessor''' :
     505{{{
     506tlmt_core::tlmt_callback < VciProcessor,bool >(this, &VciProcessor < iss_t,
     507           vci_param >::irqReceived);
     508}}}
     509
     510In the Parallel Discrete Event Simulation, the pessimistic approach relies on the fact that any PDES process is not allowed to update
     511his local time until it has received messages on all its input ports with times greater than its local time.
     512
     513Therefore, a SC_THREAD modeling the behavior of a processor containing an '''tlmt_core::tlmt_in<bool>''' should in principle
     514wait a timestamped packet on its interrupt port before executing instructions. However, such a behavior would be very inefficient,
     515and is prone to dead-lock situations.
     516
     517The recommended policy for handling interrupts is the following:
     518 * The call-back function '''irqReceived()''' sets the member variables '''m_irqpending''' and '''m_irqtime''', when a interrupt packet
     519 is received on the '''p_irq''' port.
     520 * The '''execLoop()''' thread must test the '''m_irqpending''' variable at each cycle (i.e. in each iteration of
     521 the infinite loop).
     522 * If there is no interrupt pending, the thread continues its execution. If an interrupt is pending, and the interrupt time is greater
     523 than the local time, the thread continues execution. If the interrupt time is equal or smaller than the local time, the interrupt
     524 is handled.
     525
     526Such a violation of the the pessimistic parallel simulation principles creates a loss of accuracy on the interrupt handling
     527timestamp. This loss of accuracy in the TLM-T simulation is acceptable, as interrupts are asynchronous events, and the timing error
     528is bounded by the '''m_lookahead''' parameter.
     529
     530== F.3)  Processor with interrupt example ==
     531
     532{{{
     533
     534////////////////////////// vci_processor.h ////////////////////////////////
     535
     536namespace soclib { namespace tlmt {
     537
     538template<typename iss_t,typename vci_param>
     539class VciProcessor
     540    : public soclib::tlmt::BaseModule
     541{
     542    tlmt_core::tlmt_thread_context c0;
     543    sc_core::sc_event m_rsp_received;
     544    tlmt_core::tlmt_return m_return;
     545    bool  m_irqpendig;  // pending interrupt request
     546    tlmt_core::tlmt_time  m_irqtime;  // irq date
     547    uint32_t  m_counter;  // iteration counter
     548    uint32_t  m_lookahead;  // lookahead value
     549   
     550protected:
     551    SC_HAS_PROCESS(VciProcessor);
     552
     553public:
     554    soclib::tlmt::VciInitiator<vci_param> p_vci;
     555    tlmt_core::tlmt_in<bool> p_irq;
     556
     557    VciProcessor( sc_core::sc_module_name name, int id );
     558
     559    tlmt_core::tlmt_return &rspReceived(soclib::tlmt::vci_rsp_packet<vci_param> *pkt,
     560                const tlmt_core::tlmt_time &time,
     561                void *private_data);
     562    tlmt_core::tlmt_return &irqReceived(bool,
     563                const tlmt_core::tlmt_time &time,
     564                void *private_data);
     565    void execLoop();
     566};
     567
     568}}
     569
     570////////////////////////// vci_processor.cpp ////////////////////////////////
     571
     572#include "../include/vci_processor.h"
     573
     574namespace soclib
     575{
     576  namespace tlmt
     577  {
     578
     579#define tmpl(x) template<typename iss_t, typename vci_param> x VciProcessor<vci_param>
     580
     581    tmpl (tlmt_core::tlmt_return &)::rspReceived (soclib::tlmt:: vci_rsp_packet < vci_param > *pkt,
     582                                                  const tlmt_core:: tlmt_time & time, void *private_data)
     583    {
     584      if (pkt->cmd == vci_param::CMD_WRITE)
     585        m_write_error = (pkt->error != 0);
     586      else
     587        m_write_error = false;
     588      if (pkt->cmd == vci_param::CMD_READ)
     589        m_read_error = (pkt->error != 0);
     590      else
     591        m_read_error = false;
     592      m_rsptime = time + tlmt_core::tlmt_time (pkt->length);
     593      m_vci_pending = false;
     594      m_rsp_received.notify (sc_core::SC_ZERO_TIME);
     595
     596      return m_return;
     597    }
     598
     599    tmpl (tlmt_core::tlmt_return &)::irqReceived (bool v, const tlmt_core::
     600                                                  tlmt_time & time, void *private_data)
     601    {
     602      m_irqpending = val;
     603      m_irqtime = time;   
     604   
     605      return m_return;
     606    }
     607
     608
     609    tmpl (void)::execLoop ()
     610        {
     611                while(1) {
     612                        ...
     613                        // test interrupts
     614                        if (m_irqpending && (m_irqtime <= c0.time()))
     615                        {
     616                                // interrupt handling   
     617                        }
     618                                ...
     619                        // lookahead management
     620                        m_counter++ ;
     621                        if (m_counter >= m_lookahead) {
     622                                m_counter = 0 ;
     623                                sc_core::wait(sc_core::SC_ZERO_TIME) ;
     624                        } // end if
     625                        c0.set_time(c0.time()+tlmt_core::tlmt_time(1)) ;
     626                } // end while
     627        }
     628       
     629  tmpl ( /**/)::VciProcessor(
     630          sc_core::sc_module_name name,
     631          int id )
     632: soclib::tlmt::BaseModule (name),
     633  m_counter (0),
     634  m_lookahead (10),
     635  p_vci("vci",new tlmt_core::tlmt_callback<VciProcessor,vci_rsp_packet<vci_param>*>(
     636        this,&VciProcessor<vci_param>::rspReceived),&c0),
     637  p_irq("irq",new tlmt_core::tlmt_callback<VciProcesspr,bool>(
     638        this,&VciProcessor<vci_param>::irqReceived))
     639    {
     640      SC_THREAD (execLoop);
     641    }
     642
     643}}
     644
     645}}}
     646