Changes between Version 19 and Version 20 of DsxDocumentation


Ignore:
Timestamp:
Feb 20, 2008, 3:43:02 PM (16 years ago)
Author:
Nicolas Pouillon
Comment:

New API

Legend:

Unmodified
Added
Removed
Modified
  • DsxDocumentation

    v19 v20  
    7171Three  platforms are currently supported :
    7272 * Any Linux (or Unix)  workstation  supporting the POSIX threads,
    73  * MP-SoC architecture using the Mutek/D operation system,
    74  * MP-SoC architecture using the Mutek/S operating system,
    75 
    76 Mutek/D is an embedded, POSIX compliant, distributed,  operating system for MP-SoCs,
     73 * MP-SoC architecture using the Mutek/S operating system (SRL directly implemented on Hexo),
     74 * MP-SoC architecture using the Mutek/H operation system (SRL with Posix threads on Hexo),
     75
     76Mutek/H is an embedded, POSIX compliant, distributed,  operating system for MP-SoCs,
    7777while Mutek/S is an optimized version: the performances are improved, and the memory
    7878footprint is reduced, at the cost of loosing the POSIX compatibility.
     
    109109A MWMR communication channel is a memory buffer handled as a software FIFO that can have several producers and several consumers. Each channel is protected by an implicit lock for exclusive access. Any MWMR transaction
    110110can be decomposed in five memory access:
    111  1.  get the lock protecting the MWMR (READ access). 
    112  1.  test the status of the MWMR (READ access).
     111 1.  get the lock protecting the MWMR (LL access). 
     112 1.  get the lock protecting the MWMR (SC access). 
     113 1.  test the status of the MWMR (3-words READ access).
    113114 1.  transfer a burst of data between a local buffer and the MWMR (READ/WRITE access).
    114  1.  update the status of the MWMR (WRITE access).
    115  1.  release the lock (WRITE access).
     115 1.  update the status of the MWMR and release the lock (4-words WRITE access).
    116116
    117117Any data transfer to or from a MWMR channel mut be an integer number of items. The item width is an
     
    126126 1. ''status'' : channel state (number of stored items, read & write pointers)
    127127 1. ''buffer'' : channel buffer containing the data
    128  1. ''lock'' : lock protecting exclusive access
    129128
    130129=== C3) Synchronization barrier definition ===
     
    200199=== D1) SoCLib components  ===
    201200
    202 In the current version of DSX, each hardware component must be described by a Python
    203 class that defines the component interface, and the component parameters.
    204201The list of available components can be found in SoclibComponents.
    205 For all components, the instance name is mandatory, but all other parameters have default values and can be skipped:
    206 {{{
    207 # creation of a MIPS R3000 processor core
    208 my_proc = Mips( 'proc' )
    209 
    210 # creation of a cache controler
    211 my_cache = Xcache( 'cache',
     202As it is possible to mix CABA and TLM-T simulation models in the same hardware architecture,
     203the system designer can specify the type of simulation model used for each hardware component.
     204For all components, the instance name is mandatory.
     205{{{
     206# definition of the hardware architecture
     207archi = soclib.Architecture()
     208
     209# instanciation of a MIPS R3000 processor (MIPS ISS in a CABA wrapper), with CPUID = 0
     210my_proc = archi.create('caba:iss_wrapper', 'proc', iss_t = 'common:mipsel', ident = 0)
     211
     212# instanciation of a CABA cache controler. Both instruction and data caches contain 32 lines of 8 bytes
     213my_cache = archi.create('caba:vci_xcache', 'cache',
    212214                        dcache_lines = 32,
    213215                        dcache_words = 8,
     
    223225c1.a // c2.b
    224226}}}
     227
    225228Depending on the component type, the port designation can vary:
    226  * When the number of ports is fixed, the ports are attributs : My_Proc0.cache define the cache port of the MIPS processor.
    227  * When the number of port is not fixed (typivally for interconnect component, the ports are allocated through a dedicated method : the getTarget() method of the !LocalCrossbar component allocates a VCI target port, the getInit() method allocates an VCI Initiator port.
     229 * When the port is alone, the port is an attribute : My_Proc0.dcache define the data cache port of the processor.
     230 * When the number of ports is fixed, the ports are in a array : My_Proc0.irq[3] define the 4th irq line of the processor.
     231 * When the number of port in a port array is not fixed (typically for interconnect component), the ports are allocated through a dedicated method on the port array : the new() method on !Vgmn.from_initiator allocates a VCI target port.
    228232The following example describes asimple system with two processor and on e embedded memory:
    229233{{{
    230234# components instanciacion
    231 my_proc0 = Mips( 'proc0' )
    232 my_cache0 = Xcache( 'cache0' )
    233 my_proc1 = Mips( 'proc1' )
    234 my_cache1 = Xcache( 'cache1' )
    235 my_ram = MultiRam( 'ram' )
    236 my_crossbar = LocalCrossbar( 'crossbar' )
    237                      
     235my_proc0 = archi.create('caba:iss_wrapper', 'proc0', iss_t = 'common:mipsel', ident = 0)
     236my_cache0 = archi.create('caba:vci_xcache', 'cache0',
     237                        dcache_lines = 32,
     238                        dcache_words = 8,
     239                        dcache_lines = 32,
     240                        dcache_words = 8)
     241my_proc1 = archi.create('caba:iss_wrapper', 'proc1', iss_t = 'common:mipsel', ident = 1)
     242my_cache1 = archi.create('caba:vci_xcache', 'cache1',
     243                        dcache_lines = 32,
     244                        dcache_words = 8,
     245                        dcache_lines = 32,
     246                        dcache_words = 8)
     247my_ram = archi.create('caba:vci_ram', 'ram' )
     248my_vgmn = archi.create('caba:vci_vgmn', 'vgmn' )
     249
    238250# components connexion
    239 my_proc0.cache // my_cache0.cache
    240 my_proc1.cache // my_cache1.cache
    241 my_crossbar.getTarget() // my_cache0.vci
    242 my_crossbar.getTarget() // my_cache1.vci
    243 my_crossbar.getInitiator() // my_cache0.vci
     251my_proc0.dcache // my_cache0.dcache
     252my_proc0.icache // my_cache0.icache
     253my_proc1.dcache // my_cache1.dcache
     254my_proc1.icache // my_cache1.icache
     255my_vgmn.from_initiator.new() // my_cache0.vci
     256my_vgmn.from_initiator.new() // my_cache1.vci
     257my_vgmn.to_target.new() // my_ram.vci
    244258}}}
    245259
    246260=== D3) Address space segmentation ===
    247 
    248 All hardware components defining the hardware architecture should be grouped in a single object.
    249 As any MP-SoC architecture build with the SoCLib library uses a VCI interconnect hardware component,
    250 this component must be declared as the ''root'' of the architecture :
    251 {{{
    252 my_architecture = Hardware( vgmn )
    253 }}}
    254261
    255262In any shared memory architecture, the address space is a shared resource.  This resource is structured in several segments. A segment has a name, a base address, a size
     
    259266The DSX/L language allows the system designer to define the various segments used by a given application,
    260267and to link those segments to the hardware components.
    261 The base address and the segment size are optional parameters :
    262 {{{
    263 # segments definition
    264 seg_data1 = Segment( 'seg1', Cached )
    265 seg_data2 = Segment( 'seg2', Uncached )
    266 seg_reset = Segment( 'reset', Cached, addr = 0xBFC00000 )
    267 
    268 # Instanciating a VCI target hardware component
    269 # and assigning  the segments to this component
    270 my_ram = MultiRam ( 'ram', seg_data1, seg_data2, seg_reset )
     268{{{
     269my_ram = archi.create('caba:vci_ram', 'ram' )
     270my_ram.addSegment('cram0', 0x40000, 0x320)
     271my_ram.addSegment('mipsel_reset', 0xbfc00000, 0x100)
    271272}}}
    272273
     
    275276{{{
    276277# mapping table construction
    277 my_mt = MappingTable()
    278 # mapping table initialisation
    279 my_hardware.setConfig( 'maptab', my_mt )
     278my_mt = archi.create('common:mapping_table', 'mt', [4], [4], 0xc00000)
    280279}}}
    281280 
     
    283282
    284283As DSX/L is based on Python, it is possible to define generic, parametrized architectutes, that can
    285 be reused for various applications. Those reusable architectures are derived classes
    286 from the basic '''Architecture''' class. The implementation is defined in the architecture() method.
    287 
    288 As an example we define a parameterized multi-processors architecture, called !MultiProc, and containing
    289 a variable number of processors. The parameter(s) must be named, and the actual parameter value is defined
    290 when the architecture is instanciated. The parameter is referenced with the ''getParam()'' method, and it
    291 is possible to define a default value.
     284be reused for various applications. Those reusable architectures are functions.
     285
    292286{{{
    293287#################################
    294288# generic architecture definition
    295289#################################
    296 class MultiProc(Architecture) :
    297     defaults = { ’nbcpu’ : 2 }
    298     def architecture(self):
    299 
    300         # segments definition
    301         self.reset = Segment( ’reset’, address = 0xbfc00000, type = Cached )
    302         self.code = Segment( ’code’, type = Cached )
    303         self.data = Segment( ’data’, type = Uncached )
    304 
    305         # components instanciation and connexion
    306         self.vgmn = Vgmn( ’vgmn’ )
    307         self.ram = MultiRam( ’ram’, self.reset, self.code, self.data )
    308         # processors and caches
    309         self.cpus = []
    310         for i in self.getParam( ’nbcpu’ ):
    311             m = Mips( ’mips%d’%i )
    312             self.cpus.append( m )
    313             c = Xcache( ’cache%d’%i )
    314             g:c.cache // m.cache )
    315             c.vci // self.vgmn.getTarget() )
    316         self.vgmn.getTarget() // self.c1
    317         self.vgmn.getTarget() // self.c2
    318         self.vgmn.getInit() // self.ram
    319 
    320         # base definition
    321         self.setBase( self.vgmn )
    322 
    323         # segment table initialization
    324         self.setConfig(’mapping_table’, MappingTable() )
     290def MultiProc(nbcpu = 2):
     291    archi = soclib.Architecture()
     292
     293    vgmn = archi.create('caba:vci_vgmn', 'vgmn' )
     294
     295    for i in range(nbcpu):
     296        proc = archi.create('caba:iss_wrapper', 'proc%d'%i, iss_t = 'common:mipsel', ident = i)
     297        cache = archi.create('caba:vci_xcache', 'cache%d'%i,
     298                        dcache_lines = 32,
     299                        dcache_words = 8,
     300                        dcache_lines = 32,
     301                        dcache_words = 8)
     302
     303        proc.dcache // cache.dcache
     304        proc.icache // cache.icache
     305
     306    my_ram = archi.create('caba:vci_ram', 'ram' )
     307    my_ram.addSegment( ’reset’, 0xbfc00000, true )
     308    my_ram.addSegment( ’code’, 0x40000000, true )
     309    my_ram.addSegment( ’data0’, 0x20000000, true )
     310    my_ram.addSegment( ’data1’, 0x30000000, false )
     311
     312    my_vgmn.to_target.new() // my_ram.vci
    325313
    326314####################################
    327315# generic architecture instanciation
    328316####################################
    329 my_board = MultiProc( nbcpu = 4 ) 
     317my_architecture = MultiProc( nbcpu = 4 ) 
    330318}}}
    331319 
     
    339327As it is possible to define various mapping for a given TCG, and a given architecture, we must define a third object : this ''mapper'' will contain all the mapping directives defined by the system designer.
    340328{{{
    341 my_mapper = Mapper( my_tcg, my_architecture )
     329my_mapper = Mapper( my_architecture, my_tcg )
    342330}}}
    343331
    344332=== E2) Mapper definition ===
    345333
    346 The mapper has a method ''map()'' that is used to assign a software object to an hardware component.
     334The mapper has a method `map()` that is used to assign a software object to an hardware component.
    347335An hardware component can be a processor, a segment associated to an embedded memory bank,
    348336or a segment associated to an addressable peripheral.
    349337{{{
    350338# Mapper definition
    351 my_mapper = Mapper( my_tcg, my_architecture )
     339my_mapper = Mapper( my_architecture, my_tcg )
    352340 
    353 # a segment seg_x is designated by my_architecture.seg_x
    354 
    355341# For a MWMR channel, 4 software elements must be placed
    356342my_mapper.map( my_channel, 
    357         lock = my_archi.seg_locks,  # The lock protecting the channel is placed in segment seg_locks
    358         status = my_archi.seg_data,  # The channel status is placed in segment seg_data
    359         desc = my_archi.segdata, # The channel descriptor is placed in segment seg_readonly
    360         buffer = my_archi.sgdata ) # The channel buffer is placed in segment seg_data
     343        status = 'data0',  # The channel status is placed in segment seg_data
     344        desc = 'data1', # The channel descriptor is placed in segment seg_readonly
     345        buffer = 'data1' ) # The channel buffer is placed in segment seg_data
    361346
    362347# for a software task, 4 software objects must be placed
    363348my_mappe.map( my_task,
    364         desc = my_archi.seg_data,  # The task descriptor is placed in segment seg_readonly
    365         status = my_archi.seg_data,  # The task state is placed in segment seg_data
    366         stack = my_archi.seg_data,   # The private task stack  is placed in segment seg_stack
    367         run = my_archi.cpu0 )   # task will be running on cpu0
     349        desc = 'data0',  # The task descriptor is placed in segment seg_readonly
     350        status = 'data1',  # The task state is placed in segment seg_data
     351        stack = 'data0',   # The private task stack  is placed in segment seg_stack
     352        run = 'proc0' )   # task will be running on processor no 0
    368353}}}
    369354
     
    376361 * Software only (Tcg object)
    377362  * Posix() for generating native workstation code
    378  * Software and hardware (Mapper object)
     363 * Software and hardware (Mapper object). Those always generate the associated SystemC simulator
    379364  * MutekS() to use Mutek/S as supporting embedded OS
    380   * MutekD() to use Mutel/D as supporting embedded OS
    381   * any hardware generator (those on next lines), this will create a platform automatically loading the embedded software
     365  * MutekH() to use Mutel/H as supporting embedded OS
    382366 * Hardware only (Hardware object)
    383   * Caba() to create a CABA netlist (with SoCLib)
    384   * Tlmt() to create a TLM-T netlist (with SoCLib)
    385 
    386 User may want to have a convenience Makefile in platform root which would build all code,
    387 it may be created passing all generators created to generate code to TopMakefile()
     367  * soclib.PfDriver() to create a SystemC netlist (with SoCLib)
    388368
    389369Example: Let's create
    390  * An application mapped on an hardware platform with CABA and TLM-T simulators
     370 * An application mapped on an hardware platform with SystemC simulators
    391371 * a corresponding application for the workstation
    392  * a top Makefile:
    393372
    394373{{{
    395374
    396375soft = Tcg( ... )
    397 hard = Hardware( ... )
     376hard = soclib.Architecture( ... )
    398377
    399378mapping = Mapper( hard, soft )
     
    404383
    405384muteks_generator = MutekS()
    406 caba_generator = Caba()
    407 tlmt_generator = Tlmt()
    408385
    409386posix_generator = Posix()
     
    411388# MutekS and simulators (Caba / Tlmt) generates platform and embedded software for a mapping:
    412389
    413 mapping.generate( muteks_generator, caba_generator, tlmt_generator )
     390mapping.generate( muteks_generator )
    414391
    415392# Posix generates code for a Tcg
    416393
    417394tcg.generate( posix_generator )
    418 
    419 # TopMakefile takes the used generators:
    420 
    421 TopMakefile( muteks_generator, caba_generator, tlmt_generator, posix_generator )
    422 }}}
    423 
     395}}}
     396