source: soft/giet_vm/giet_drivers/mwr_driver.c @ 765

Last change on this file since 765 was 709, checked in by alain, 9 years ago

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
File size: 8.9 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : mwr_driver.c
[518]3// Date     : 27/02/2015
[258]4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
[320]9#include <hard_config.h>
[518]10#include <mapping_info.h>
[258]11#include <mwr_driver.h>
[563]12#include <xcu_driver.h>
[554]13#include <ctx_handler.h>
[258]14#include <utils.h>
[529]15#include <kernel_locks.h>
[456]16#include <tty0.h>
[518]17#include <io.h>
[258]18
[263]19#if !defined(X_SIZE)
20# error: You must define X_SIZE in the hard_config.h file
[258]21#endif
22
[263]23#if !defined(Y_SIZE)
24# error: You must define X_SIZE in the hard_config.h file
[258]25#endif
26
[263]27#if !defined(X_WIDTH)
28# error: You must define X_WIDTH in the hard_config.h file
29#endif
30
31#if !defined(Y_WIDTH)
32# error: You must define X_WIDTH in the hard_config.h file
33#endif
34
[320]35#if !defined(SEG_MWR_BASE)
36# error: You must define SEG_MWR_BASE in the hard_config.h file
37#endif
38
[333]39#if !defined(PERI_CLUSTER_INCREMENT)
40# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
[320]41#endif
42
[630]43/////////////////////////////////////////////////////////////////////////////
44//      Extern variables
45/////////////////////////////////////////////////////////////////////////////
[518]46
[630]47// allocated in the boot.c or kernel_init.c files
48extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
49
[518]50/////////////////////////////////////////////////////////////////////////////
[630]51//      Global variables
[529]52/////////////////////////////////////////////////////////////////////////////
[630]53// All arrays are indexed by the cluster index.
54/////////////////////////////////////////////////////////////////////////////
[529]55
[554]56// Lock protecting exclusive access
[529]57__attribute__((section(".kdata")))
58simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
59
[554]60// Coprocessor type
[529]61__attribute__((section(".kdata")))
[554]62unsigned int  _coproc_type[X_SIZE*Y_SIZE];
[529]63
[554]64// coprocessor characteristics
65__attribute__((section(".kdata")))
66unsigned int   _coproc_info[X_SIZE*Y_SIZE];
67
68// Coprocessor running mode
69__attribute__((section(".kdata")))
70unsigned int  _coproc_mode[X_SIZE*Y_SIZE];
71
72// coprocessor status (for MODE_DMA_IRQ)
73__attribute__((section(".kdata")))
74unsigned int   _coproc_error[X_SIZE*Y_SIZE];
75
[709]76// descheduled thread trdid (for MODE_DMA_IRQ)
[554]77__attribute__((section(".kdata")))
[709]78unsigned int   _coproc_trdid[X_SIZE*Y_SIZE];
[554]79
[529]80/////////////////////////////////////////////////////////////////////////////
[518]81// This function returns the value contained in a private register
82// of the coprocessor contained in cluster "cluster_xy".
83/////////////////////////////////////////////////////////////////////////////
84unsigned int _mwr_get_coproc_register( unsigned int cluster_xy, // cluster
85                                       unsigned int index )     // register
[258]86{
[518]87    unsigned int vaddr =
88        SEG_MWR_BASE + 
89        (cluster_xy * PERI_CLUSTER_INCREMENT) + 
90        (index << 2);
[258]91
[518]92    return ioread32( (void*)vaddr );
93}
[258]94
[518]95/////////////////////////////////////////////////////////////////////////////
96// This function sets a new value in a private register
97// of the coprocessor contained in cluster "clustenr_xy".
98/////////////////////////////////////////////////////////////////////////////
99void _mwr_set_coproc_register( unsigned int cluster_xy,   // cluster index
100                               unsigned int index,        // register index
101                               unsigned int value )       // writte value
102{
103    unsigned int vaddr =
104        SEG_MWR_BASE + 
105        (cluster_xy * PERI_CLUSTER_INCREMENT) +
106        (index << 2);
107       
108    iowrite32( (void*)vaddr, value );
109}
[258]110
[518]111/////////////////////////////////////////////////////////////////////////////
112// This function returns the value contained in a channel register
113// defined by the "index" and "channel" arguments, in the MWMR_DMA component
114// contained in cluster "cluster_xy".
115/////////////////////////////////////////////////////////////////////////////
116unsigned int _mwr_get_channel_register( unsigned int cluster_xy, // cluster
117                                        unsigned int channel,    // channel
118                                        unsigned int index )     // register
119{
120    unsigned int vaddr =
121        SEG_MWR_BASE + 
122        (cluster_xy * PERI_CLUSTER_INCREMENT) + 
[554]123        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
[518]124        (index << 2);
[258]125
[518]126    return ioread32( (void*)vaddr );
127}
[258]128
[518]129/////////////////////////////////////////////////////////////////////////////
130// This function sets a new value in a channel register
131// defined by the "index" and "channel") arguments, in the MWMR_DMA component
132// contained in cluster "cluster_xy".
[554]133////////////////////////////////////////////////////////////////////////////yy
[518]134void _mwr_set_channel_register( unsigned int cluster_xy,  // cluster index
135                                unsigned int channel,     // channel index
136                                unsigned int index,       // register index
137                                unsigned int value )      // written value
138{
139    unsigned int vaddr =
140        SEG_MWR_BASE + 
141        (cluster_xy * PERI_CLUSTER_INCREMENT) +
[554]142        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
[518]143        (index << 2);
144       
145    iowrite32( (void*)vaddr, value );
[258]146}
147
[554]148////////////////////////////////////////////////////////////////////////////yy
149// This Interrupt service routine is called in two situations:
150// - The MWR_DMA component is running in MODE_DMA_IRQ, and all the
151//   communication channels have successfully completed.
152// - The MWR_DMA component is running in any mode, and at least one
153//   communication channel is reporting a VCI error.
154////////////////////////////////////////////////////////////////////////////yy
155void _mwr_isr( unsigned int irq_type,  // unused : should be HWI
[518]156               unsigned int irq_id,    // index returned by XCU
[554]157               unsigned int bloup )    // unused : should be 0         
[518]158{
[554]159    // get coprocessor coordinates and characteristics
[630]160    // processor executing ISR and coprocessor are in the same cluster
[518]161    unsigned int gpid       = _get_procid();
162    unsigned int cluster_xy = gpid >> P_WIDTH;
163    unsigned int x          = cluster_xy >> Y_WIDTH;
164    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[554]165    unsigned int cluster_id = x * Y_SIZE + y;
166    unsigned int info       = _coproc_info[cluster_id];
167    unsigned int nb_to      = info & 0xFF;
168    unsigned int nb_from    = (info>>8) & 0xFF;
[630]169
[554]170    unsigned int channel;
171    unsigned int status;
172    unsigned int error = 0;
[258]173
[630]174    // check status, report errors and reset for all channels
[554]175    for ( channel = 0 ; channel < (nb_to + nb_from) ; channel++ )
176    {
177        status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
[518]178
[554]179        if ( status == MWR_CHANNEL_BUSY )          // strange => report error
180        {
181            _printf("\n[GIET_ERROR] in _mwr_isr() : channel %d is busy\n", channel );
182            error = 1;
183        }
184        else if ( status == MWR_CHANNEL_ERROR_DATA ) 
185        {
186            _printf("\n[GIET_ERROR] in _mwr_isr() : DATA_ERROR / channel %d\n", channel );
187            error = 1;
188        }
189        else if ( status == MWR_CHANNEL_ERROR_LOCK )
190        {
191            _printf("\n[GIET_ERROR] in _mwr_isr() : LOCK_ERROR / channel %d\n", channel );
192            error = 1;
193        }
194        else if ( status == MWR_CHANNEL_ERROR_DESC )
195        {
196            _printf("\n[GIET_ERROR] in _mwr_isr() : DESC_ERROR / channel %d\n", channel );
197            error = 1;
198        }
[518]199
[554]200        // reset channel
201        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
202    }
203
204    // register error
205    _coproc_error[cluster_id]  = error;
206
[709]207    // identify thread waiting on coprocessor completion (can run in a remote cluster)
208    unsigned int r_x       = (_coproc_trdid[cluster_id]>>24) & 0xFF;
209    unsigned int r_y       = (_coproc_trdid[cluster_id]>>16) & 0xFF;
210    unsigned int r_p       = (_coproc_trdid[cluster_id]>> 8) & 0xFF;
211    unsigned int r_ltid    = (_coproc_trdid[cluster_id]    ) & 0xFF;
[554]212
[630]213    // Reset NORUN_MASK_IOC bit
214    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[r_x][r_y][r_p];
[709]215    unsigned int*       ptr     = &psched->context[r_ltid].slot[CTX_NORUN_ID];
[668]216    _atomic_and( ptr , ~NORUN_MASK_COPROC );
[554]217
[709]218    // send a WAKUP WTI to processor running the sleeping thread
219    _xcu_send_wti( (r_x<<Y_WIDTH) + r_y,
[630]220                   r_p, 
[554]221                   0 );          // don't force context switch
222
223#if GIET_DEBUG_COPROC 
[563]224unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[554]225_printf("\n[GIET DEBUG COPROC] P[%d,%d,%d] executes _mwr_isr() at cycle %d\n"
[709]226        "  for thread %d running on P[%d,%d,%d] / error = %d\n",
[668]227        x , y , p , _get_proctime() , r_ltid , r_x , r_y , r_p , error );
[554]228#endif
[630]229}  // end _mwr_isr()
[518]230
231
232
[258]233// Local Variables:
234// tab-width: 4
235// c-basic-offset: 4
236// c-file-offsets:((innamespace . 0)(inline-open . 0))
237// indent-tabs-mode: nil
238// End:
239// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
240
Note: See TracBrowser for help on using the repository browser.