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

Last change on this file since 708 was 668, checked in by alain, 9 years ago

Fix a bug in mwr_isr.c

File size: 8.9 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : mwr_driver.c
3// Date     : 27/02/2015
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
9#include <hard_config.h>
10#include <mapping_info.h>
11#include <mwr_driver.h>
12#include <xcu_driver.h>
13#include <ctx_handler.h>
14#include <utils.h>
15#include <kernel_locks.h>
16#include <tty0.h>
17#include <io.h>
18
19#if !defined(X_SIZE)
20# error: You must define X_SIZE in the hard_config.h file
21#endif
22
23#if !defined(Y_SIZE)
24# error: You must define X_SIZE in the hard_config.h file
25#endif
26
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
35#if !defined(SEG_MWR_BASE)
36# error: You must define SEG_MWR_BASE in the hard_config.h file
37#endif
38
39#if !defined(PERI_CLUSTER_INCREMENT)
40# error: You must define PERI_CLUSTER_INCREMENT in the hard_config.h file
41#endif
42
43/////////////////////////////////////////////////////////////////////////////
44//      Extern variables
45/////////////////////////////////////////////////////////////////////////////
46
47// allocated in the boot.c or kernel_init.c files
48extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
49
50/////////////////////////////////////////////////////////////////////////////
51//      Global variables
52/////////////////////////////////////////////////////////////////////////////
53// All arrays are indexed by the cluster index.
54/////////////////////////////////////////////////////////////////////////////
55
56// Lock protecting exclusive access
57__attribute__((section(".kdata")))
58simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
59
60// Coprocessor type
61__attribute__((section(".kdata")))
62unsigned int  _coproc_type[X_SIZE*Y_SIZE];
63
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
76// descheduled task gtid (for MODE_DMA_IRQ)
77__attribute__((section(".kdata")))
78unsigned int   _coproc_gtid[X_SIZE*Y_SIZE];
79
80/////////////////////////////////////////////////////////////////////////////
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
86{
87    unsigned int vaddr =
88        SEG_MWR_BASE + 
89        (cluster_xy * PERI_CLUSTER_INCREMENT) + 
90        (index << 2);
91
92    return ioread32( (void*)vaddr );
93}
94
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}
110
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) + 
123        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
124        (index << 2);
125
126    return ioread32( (void*)vaddr );
127}
128
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".
133////////////////////////////////////////////////////////////////////////////yy
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) +
142        ((channel + 1) * (MWR_CHANNEL_SPAN << 2)) +
143        (index << 2);
144       
145    iowrite32( (void*)vaddr, value );
146}
147
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
156               unsigned int irq_id,    // index returned by XCU
157               unsigned int bloup )    // unused : should be 0         
158{
159    // get coprocessor coordinates and characteristics
160    // processor executing ISR and coprocessor are in the same cluster
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);
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;
169
170    unsigned int channel;
171    unsigned int status;
172    unsigned int error = 0;
173
174    // check status, report errors and reset for all channels
175    for ( channel = 0 ; channel < (nb_to + nb_from) ; channel++ )
176    {
177        status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
178
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        }
199
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
207    // identify task waiting on coprocessor completion
208    // this task can run in a remote cluster
209    unsigned int r_gtid    = _coproc_gtid[cluster_id];
210    unsigned int r_procid  = r_gtid>>16;
211    unsigned int r_ltid    = r_gtid & 0xFFFF;
212    unsigned int r_cluster = r_procid >> P_WIDTH;
213    unsigned int r_x       = r_cluster >> Y_WIDTH;
214    unsigned int r_y       = r_cluster & ((1<<Y_WIDTH)-1);
215    unsigned int r_p       = r_procid & ((1<<P_WIDTH)-1);
216
217    // Reset NORUN_MASK_IOC bit
218    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[r_x][r_y][r_p];
219    unsigned int*       ptr     = &psched->context[r_ltid][CTX_NORUN_ID];
220    _atomic_and( ptr , ~NORUN_MASK_COPROC );
221
222    // send a WAKUP WTI to processor running the sleeping task
223    _xcu_send_wti( r_cluster,   
224                   r_p, 
225                   0 );          // don't force context switch
226
227#if GIET_DEBUG_COPROC 
228unsigned int p          = gpid & ((1<<P_WIDTH)-1);
229_printf("\n[GIET DEBUG COPROC] P[%d,%d,%d] executes _mwr_isr() at cycle %d\n"
230        "  for task %d running on P[%d,%d,%d] / error = %d\n",
231        x , y , p , _get_proctime() , r_ltid , r_x , r_y , r_p , error );
232#endif
233}  // end _mwr_isr()
234
235
236
237// Local Variables:
238// tab-width: 4
239// c-basic-offset: 4
240// c-file-offsets:((innamespace . 0)(inline-open . 0))
241// indent-tabs-mode: nil
242// End:
243// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
244
Note: See TracBrowser for help on using the repository browser.