Changes between Version 1 and Version 2 of Writing Rules/Tlmt


Ignore:
Timestamp:
Dec 24, 2007, 7:09:19 PM (16 years ago)
Author:
alain
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Writing Rules/Tlmt

    v1 v2  
    1010= A) Introduction =
    1111
    12 This manual describes the modeling rules for writing TLM-T SystemC simulation models for SoCLib.
    13 Those rules enforce the PDES (Parallel Discrete Event Simulation) principles. Each PDES process involved in the
    14 simulation has is own, local time, and processes synchronize through timed messages.
     12This document describes the modeling rules for writing TLM-T SystemC simulation models for SoCLib.
     13Those rules enforce the PDES (Parallel Discrete Event Simulation) principles. Each PDES process involved in the simulation has is own, local time, and processes synchronize through timed messages.
    1514Models complying with those rules can be used with the "standard" OSCI simulation engine (SystemC 2.x), but can be used also with others simulation engines, especially distributed, parallelized simulation engines.
    1615
     
    185184}}}
    186185
    187 
    188 
    189 
    190 As VCI signals can have variable widths, all VCI components must be defined with templates. The [source:trunk/soclib/systemc/include/caba/interface/vci_param.h caba/interface/vci_param.h] file contains the definition of the VCI parameters object. This object must be passed as a template parameter to the component.
    191 
    192 A typical VCI component declaration is:
    193 {{{
    194 #include "caba/util/base_module.h"
    195 #include "caba/interface/vci_target.h"
    196 
    197 namespace soclib { namespace caba {
    198 
    199 template<typename vci_params>
    200 class VciExampleModule
    201     : soclib::caba::BaseModule
    202 {
    203 
    204 };
    205 }}
    206 }}}
    207 
    208 The SystemC top cell defining the system architecture must include the following file, defining the advanced VCI signals :
    209  * [source:trunk/soclib/systemc/include/caba/interface/vci_signals.h caba/interface/vci_signals.h].
    210 
    211 A SoCLib hardware component that has no VCI interface should use a dedicated VCI  wrapper in order to be connected to the VCI interconnect.
    212 
    213 == B3) Address space segmentation ==
    214 
    215 In a shared memory architecture, the address space segmentation (or memory map) is a global characteristic of the system.
    216 This memory map must be defined by the system designer, and is used by both software, and hardware components.
    217 
    218 Most hardware components use this memory map:
    219  * VCI interconnect components contain a ''routing table'' used to decode the VCI address MSB bits and
    220    route VCI commands to the proper targets.
    221  * VCI target components must be able to check for segmentation violation when receiving a
    222    command packet. Therefore, the base address and size of the segment allocated to a given
    223    VCI target must be ''known'' by this target.
    224  * A cache controller supporting uncached segments can contain a ''cacheability table''
    225    addressed by the VCI address MSB bits.
    226 
    227 In order to simplify the memory map definition, and the hardware component configuration, a
    228 generic object, called ''mapping table'' has been defined in
    229 [source:trunk/soclib/systemc/include/common/mapping_table.h common/mapping_table.h].
    230 This is an associative table of memory segments. Any segment must be allocated to one single
    231 VCI target. The segment object is defined in
    232 [source:trunk/soclib/systemc/include/common/segment.h common/segment.h],
    233 and contains five attributes:
    234 {{{
    235 const std::string   m_name;           // segment's name
    236 addr_t              m_base_address;   // base address
    237 size_t              m_size;           // size (bytes)
    238 IntTab              m_target_index;   // VCI target index
    239 bool                m_cacheability;   // cacheable
    240 }}}
    241 
    242 Any hardware component using the memory map should have a constant reference to the mapping table as constructor argument.
    243 
    244 == B4) Component definition ==
    245 
    246 The component ''XXX.h'' file contains the following informations
    247 
    248 '''Interface definition'''
    249 A typical VCI target component will contain the following ports:
    250 {{{
    251 sc_in<bool>                         p_resetn;
    252 sc_in<bool>                         p_clk;
    253 soclib::caba::VciTarget<vci_param>  p_vci;
    254 }}}
    255 
    256 '''Internal registers definition'''
    257 
    258 All internal registers should be defined with the  ''sc_signal'' type.
    259 
    260 This point is a bit tricky: It allows the model designer to benefit from the delayed update
    261 mechanism associated by SystemC to the sc_signal type. When a single module contains several
    262 interacting FSMs, it helps to write the `Transition()`, as the registers values are not updated
    263 until the exit from the transition function. Conversely, any member variable declared with the
    264 `sc_signal` type is considered as a register.
    265 
    266 A typical VCI target will contain the following registers :
    267 {{{
    268 sc_signal<int>                          r_vci_fsm;
    269 sc_signal<typename vci_param::trdid_t>  r_buf_trdid;
    270 sc_signal<typename vci_param::pktid_t>  r_buf_srcid;
    271 sc_signal<typename vci_param::srcid_t>  r_buf_srcid;
    272 }}}
    273 
    274 ''`typename vci_param::trdid_t` and others are generically-defined VCI field types''
    275 
    276 '''Structural parameters definition'''
    277 
    278 All structural parameters should be be defined as member variables. The values are generally defined by a constructor argument.
    279 Instance name is stored in [source:trunk/soclib/systemc/include/common/base_module.h soclib::common::BaseModule], inherited by
    280 [source:trunk/soclib/systemc/include/caba/util/base_module.h soclib::caba::BaseModule].
    281 For example, a VCI target will contain a reference to the the assigned segment, in order to check
    282 possible segmentation errors during execution.
    283 
    284 {{{
    285 const soclib::common::Segment   m_segment;
    286 }}}
    287 
    288 == B5) Constructor & destructor ==
    289 
    290 Any hardware component must have an instance name, and most SoCLib component must have
    291 a VCI index. Moreover, generic simulation models can have structural parameters. The parameter
    292 values must be defined as constructor arguments, and used by the constructor to configure the hardware ressources. A constructor  argument frequently
    293 used is a reference on the [source:trunk/soclib/systemc/include/common/mapping_table.h soclib::common::MappingTable], that defines the segmentation of the system address space.
    294 A typical VCI component will have the following constructor arguments:
    295 
    296 {{{
    297 VciExampleModule(
    298     sc_module_name                     insname,
    299     const soclib::common::IntTab       &index,
    300     const soclib::common::MappingTable &mt);
    301 }}}
    302 
    303 In this example, the first argument is the instance name, the second argument is the VCI target index, and the third argument is the mapping table.
    304 
    305 Moreover, the constructor must define the sensitivity list of the Transition(), genMoore() and genMealy()
    306 methods, that are described below.
    307  * sensitivity list of the transition() method contains only the clock rising edge.
    308  * sensitivity list of the genMoore() method contains only the clock falling edge.
    309  * sensitivity list of the genMealy() method contains the clock falling edge, as well as all input ports thare in the support of the Mealy generation function.
    310 
    311 Be careful: the constructor should NOT initialize the registers.
    312 The register initialization must be an hardware mechanism explicitly described in the Transition function on reset condition.
    313 
    314 == B6) member functions ==
    315 
    316 The component behaviour is described by simple member functions. The type ot those methods
    317 (Transition, genMoore, or genMealy) is defined by the sensitivity lists, as specified in B5.
    318 
    319 '''transition() method'''
    320 
    321 For each hardware component, there is only one `Transition()` method. It is called
    322 once per cycle, as the sensitivity list contains only the clock rising edge. This method
    323 computes the next values of the registers (variables that have the `sc_signal` type).
    324 No output port can be assigned in this method. Each register should be assigned only once.
    325 
    326 '''genMoore() method'''
    327 
    328 For each hardware component, there is only one `genMoore()` method. It is called once
    329 per cycle, as the sensitivity list contains only the clock falling edge. This method computes
    330 the values of the Moore output ports. (variables that have the `sc_out` type).
    331 No register can be assigned in this method. Each output port can be assigned only once.
    332 No input port can be read in this method
    333 
    334 '''genMealy() methods'''
    335 
    336 For each hardware component, there is zero, one or several `genMealy()` methods (it can be useful
    337 to have one separated `gemealy()` method for each output port). These methods can be called several times per cycle. The sensitivity list can contain several input ports. This method computes the Mealy values of the ouput ports, using only the register values and the input ports values.
    338 No register can be assigned in this method. Each output port can be assigned only once.
    339 
    340 = C) Complete example =
    341 
    342 == C1) Component definition ==
    343 
    344 Let's take the [source:trunk/soclib/systemc/include/caba/target/vci_locks.h soclib::caba::VciLocks]
    345 component definition and comment it.
    346 
    347 {{{
    348 #include <systemc.h>
    349 #include "caba/util/base_module.h"
    350 #include "caba/interface/vci_target.h"
    351 #include "common/mapping_table.h"
    352 
    353 // Have this component in the soclib::caba namespace
    354 namespace soclib { namespace caba {
    355 
    356 // Here we pass the VCI parameters as a template argument. This is intended because VCI parameters
    357 // change data type widths, therefore change some compile-time intrinsics
    358 template<typename vci_param>
    359 class VciLocks
    360     : public soclib::caba::BaseModule
    361 {
    362 
    363     // We have only one FSM in this component. It handles the
    364     // VCI target port. The states are:
    365     enum vci_target_fsm_state_e {
    366         IDLE,
    367         WRITE_RSP,
    368         READ_RSP,
    369         ERROR_RSP,
    370     };
    371 
    372     // The register holding the FSM state:
    373     sc_signal<int> r_vci_fsm;
    374 
    375     // Some registers used to save useful data between command & response
    376     sc_signal<typename vci_param::srcid_t> r_buf_srcid;
    377     sc_signal<typename vci_param::trdid_t> r_buf_trdid;
    378     sc_signal<typename vci_param::pktid_t> r_buf_pktid;
    379     sc_signal<typename vci_param::eop_t>   r_buf_eop;
    380     sc_signal<bool>                        r_buf_value;
    381 
    382     // Pointer on the table of locks (allocated in the constructor)
    383     sc_signal<bool>             *r_contents;
    384 
    385     // The segment assigned to this peripheral
    386     soclib::common::Segment m_segment;
    387 
    388 protected:
    389     // Mandatory SystemC construct
    390     SC_HAS_PROCESS(VciLocks);
    391 
    392 public:
    393     // The ports
    394     sc_in<bool> p_resetn;
    395     sc_in<bool> p_clk;
    396     soclib::caba::VciTarget<vci_param> p_vci;
    397 
    398     // Constructor & descructor, explained above
    399     VciLocks(
    400         sc_module_name insname,
    401         const soclib::common::IntTab &index,
    402         const soclib::common::MappingTable &mt);
    403     ~VciLocks();
    404 
    405 private:
    406     // The FSM functions
    407     void transition();
    408     void genMoore();
    409 };
    410 
    411 // Namespace closing
    412 }}
    413 }}}
    414 
    415 == C2) Component implementation ==
    416 
    417 Here is the [source:trunk/soclib/systemc/src/caba/target/vci_locks.cc soclib::caba::VciLocks] component implementation:
    418 
    419 {{{
    420 #include "caba/target/vci_locks.h"
    421 
    422 // Namespace, again
    423 namespace soclib { namespace caba {
    424 
    425 // This macro is an helper function to factor out the template parameters
    426 // This is useful in two ways:
    427 // * It makes the syntax clearer
    428 // * It makes template parameters changes easier (only one line to change them all)
    429 // x is the method's return value
    430 #define tmpl(x) template<typename vci_param> x VciLocks<vci_param>
    431 
    432 // The /**/ is a hack to pass no argument to a macro taking one. (constructor has no
    433 // return value in C++)
    434 tmpl(/**/)::VciLocks(
    435     sc_module_name insname,
    436     const soclib::common::IntTab &index,
    437     const soclib::common::MappingTable &mt)
    438 // This is the C++ construct for parent construction and
    439 // member variables initialization.
    440 // We initialize the BaseModule with the component's name
    441     : soclib::caba::BaseModule(insname),
    442 // and get the segment from the mapping table and our index
    443       m_segment(mt.getSegment(index))
    444 {
    445 
    446     // There is one lock every 32-bit word in memory. We
    447     // allocate an array of bool for the locks
    448     r_contents = new sc_signal<bool>[m_segment.size()/4];
    449 
    450     // Sensitivity list for transition() and genMoore(), no genMealy()
    451     // in this component
    452     SC_METHOD(transition);
    453     dont_initialize();
    454     sensitive << p_clk.pos();
    455        
    456     SC_METHOD(genMoore);
    457     dont_initialize();
    458     sensitive << p_clk.neg();
    459 }
    460 
    461 tmpl(/**/)::~VciLocks()
    462 {
    463     // Here we must delete dynamically-allocated data...
    464     delete [] r_contents;
    465 }
    466 
    467 tmpl(void)::transition()
    468 {
    469     // On reset condition, we initialize the component,
    470     // from FSMs to internal data.
    471     if (!p_resetn) {
    472         for (size_t i=0; i<m_segment.size()/4; ++i)
    473             r_contents[i] = false;
    474         r_vci_fsm = IDLE;
    475         return;
    476     }
    477 
    478     // We are not on reset case.
    479 
    480     // Take the address, transform it into an index in our locks table.
    481     typename vci_param::addr_t address = p_vci.address.read();
    482     uint32_t cell = (address-m_segment.baseAddress())/4;
    483 
    484     // Implement the VCI target FSM
    485     switch (r_vci_fsm) {
    486     case IDLE:
    487         if ( ! p_vci.cmdval.read() )
    488             break;
    489         /*
    490          * We only accept 1-word request packets
    491          * and we check for segmentation violations
    492          */
    493         if ( ! p_vci.eop.read() ||
    494              ! m_segment.contains(address) )
    495             r_vci_fsm = ERROR_RSP;
    496         else {
    497             switch (p_vci.cmd.read()) {
    498             case VCI_CMD_READ:
    499                 r_buf_value = r_contents[cell];
    500                 r_contents[cell] = true;
    501                 r_vci_fsm = READ_RSP;
    502                 break;
    503             case VCI_CMD_WRITE:
    504                 r_contents[cell] = false;
    505                 r_vci_fsm = WRITE_RSP;
    506                 break;
    507             default:
    508                 r_vci_fsm = ERROR_RSP;
    509                 break;
    510             }
    511         }
    512         r_buf_srcid = p_vci.srcid.read();
    513         r_buf_trdid = p_vci.trdid.read();
    514         r_buf_pktid = p_vci.pktid.read();
    515         r_buf_eop = p_vci.eop.read();
    516         break;
    517 
    518     // In those states, we only wait for response to be accepted.
    519     case WRITE_RSP:
    520     case READ_RSP:
    521     case ERROR_RSP:
    522         if ( p_vci.rspack.read() )
    523             r_vci_fsm = IDLE;
    524         break;
    525     }
    526 }
    527 
    528 tmpl(void)::genMoore()
    529 {
    530     // This is an helper function defined in the VciTarget port definition
    531     p_vci.rspSetIds( r_buf_srcid.read(), r_buf_trdid.read(), r_buf_pktid.read() );
    532 
    533     // Depending on the state, we give back the expected response.
    534     switch (r_vci_fsm) {
    535     case IDLE:
    536         p_vci.rspNop();
    537         break;
    538     case WRITE_RSP:
    539         p_vci.rspWrite( r_buf_eop.read() );
    540         break;
    541     case READ_RSP:
    542         p_vci.rspRead( r_buf_eop.read(), r_buf_value.read() );
    543         break;
    544     case ERROR_RSP:
    545         p_vci.rspError( r_buf_eop.read() );
    546         break;
    547     }
    548 
    549     // We only accept commands in Idle state
    550     p_vci.cmdack = (r_vci_fsm == IDLE);
    551 }
    552 }}
    553 
    554 }}}
    555 
    556 Component instanciation could be (`template_inst.cc`):
    557 {{{
    558 #include "caba/target/vci_locks.cc"
    559 template class soclib::caba::VciLocks<soclib::caba::VciParams<4,1,32,1,1,1,8,1,1,1> >;
    560 }}}
    561 
    562 Command line:
    563 {{{
    564 g++ -c -o obj.o -I/path/to/soclib/systemc/src -I/path/to/soclib/systemc/include template_inst.cc -I/path/to/systemc $(OTHER_CFLAGS)
    565 }}}
    566