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

Last change on this file since 561 was 554, checked in by alain, 9 years ago

Modify the _mwr_isr() to support descheduling/rescheduling of the
task using a coprocessor in DMA mode.

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