source: soft/giet_vm/giet_drivers/xcu_driver.c @ 269

Last change on this file since 269 was 263, checked in by alain, 11 years ago

Introducing support for TSAR fixed format cluster index (cluster_xy)
We have now 4 parameters defined in map.xml:

  • X_WIDTH, Y_WIDTH define the fixed format (typically X_WIDTH = 4 / Y_WIDTH = 4)
  • X_SIZE, Y_SIZE define the actual TSAR 2D mesh variable size (from 1 to 16)
File size: 11.6 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : xcu_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The xcu_driver.c and xcu_driver.h files are part ot the GIET-VM nano-kernel.
8// This driver supports the SoCLib vci_xicu, that is a vectorised interrupt
9// controler supporting IPI (Inter Processor Interrupts) and integrated timers.
10//
11// It can exist several interrupt controller unit in the architecture
12// (one per cluster), and each one can contain several channels.
13// The number of XICU channels is equal to NB_PROCS_MAX, because there is
14// one private XICU channel per processor in a cluster.
15////////////////////////////////////////////////////////////////////////////////
16// The virtual base address of the segment associated to the component is:
17//
[263]18//      seg_xcu_base + cluster_xy * vseg_cluster_increment
[258]19//
20// The seg_xcu_base and vseg_cluster_increment values must be defined
21// in giet_vsegs.ld file.
22////////////////////////////////////////////////////////////////////////////////
23
24#include <giet_config.h>
25#include <xcu_driver.h>
[263]26#include <tty_driver.h>
27#include <mapping_info.h>
[258]28#include <utils.h>
29
[263]30#if !defined(X_SIZE)
31# error: You must define X_SIZE in the hard_config.h file
[258]32#endif
33
[263]34#if !defined(Y_SIZE)
35# error: You must define X_SIZE in the hard_config.h file
[258]36#endif
37
[263]38#if !defined(X_WIDTH)
39# error: You must define X_WIDTH in the hard_config.h file
40#endif
41
42#if !defined(Y_WIDTH)
43# error: You must define X_WIDTH in the hard_config.h file
44#endif
45
[258]46#if !defined(NB_PROCS_MAX)
47# error: You must define NB_PROCS_MAX in the hard_config.h file
48#endif
49
50#if !defined( USE_XICU )
51# error: You must define USE_XICU in the hard_config.h file
52#endif
53
54////////////////////////////////////////////////////////////////////////////////
55//     _xcu_set_mask()
56// This function set the mask register for the XICU channel identified
57// by the cluster index and the processor index.
58// All '1' bits are set / all '0' bits are not modified.
59// Returns 0 if success, > 0 if error.
60////////////////////////////////////////////////////////////////////////////////
[263]61unsigned int _xcu_set_mask( unsigned int cluster_xy, 
62                            unsigned int proc_id,
[258]63                            unsigned int value,
[263]64                            unsigned int irq_type ) 
[258]65{
66    // parameters checking
[263]67    unsigned int x = cluster_xy >> Y_WIDTH;
68    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
69    if (x >= X_SIZE)             return 1; 
70    if (y >= Y_SIZE)             return 1; 
71    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]72
73#if USE_XICU
74    unsigned int* xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
[263]75                                (cluster_xy * (unsigned int)&vseg_cluster_increment));
76    unsigned int func;
77    if      (irq_type == IRQ_TYPE_PTI) func = XICU_MSK_PTI_ENABLE;
78    else if (irq_type == IRQ_TYPE_SWI) func = XICU_MSK_WTI_ENABLE;
79    else                               func = XICU_MSK_HWI_ENABLE;
80    xcu_address[XICU_REG(func,proc_id)] = value;
[258]81    return 0;
82#else
83    _tty_get_lock( 0 );
84    _puts("[GIET ERROR] _xcu_set_mask should not be used if USE_XICU is not set\n");
85    _tty_release_lock( 0 );
86    return 1;
87#endif
88}
89
90////////////////////////////////////////////////////////////////////////////////
91//     _xcu_get_index()
92// This function returns the index of the highest priority (smaller index)
93// - active HWI (Hardware Interrupt), or
94// - active PTI (Timer Interrupt), or
95// - active SWI (Software Interrupt).
96// The ICU channel is identified by the cluster index and the processor index.
97// Returns 0 if success, > 0 if error.
98////////////////////////////////////////////////////////////////////////////////
[263]99unsigned int _xcu_get_index( unsigned int cluster_xy, 
[258]100                             unsigned int proc_id, 
101                             unsigned int * buffer) 
102{
103    // parameters checking
[263]104    unsigned int x = cluster_xy >> Y_WIDTH;
105    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
106    if (x >= X_SIZE)             return 1; 
107    if (y >= Y_SIZE)             return 1; 
108    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]109
110#if USE_XICU
111    unsigned int* xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
[263]112                                (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]113
114    unsigned int prio = xcu_address[XICU_REG(XICU_PRIO, proc_id)];
115    unsigned int pti_ok = (prio & 0x00000001);
116    unsigned int hwi_ok = (prio & 0x00000002);
117    unsigned int swi_ok = (prio & 0x00000004);
118    unsigned int pti_id = (prio & 0x00001F00) >> 8;
119    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
120    unsigned int swi_id = (prio & 0x1F000000) >> 24;
121    if      (pti_ok)  *buffer = pti_id;
122    else if (hwi_ok)  *buffer = hwi_id;
123    else if (swi_ok)  *buffer = swi_id; 
124    else              *buffer = 32; 
125    return 0;
126#else
127    _tty_get_lock( 0 );
128    _puts("[GIET ERROR] _xcu_get_index should not be used if USE_XICU is not set\n");
129    _tty_release_lock( 0 );
130    return 1;
131#endif
132}
133
134////////////////////////////////////////////////////////////////////////////////
135//     _xcu_send_ipi()
136// This function can be used only in an architecture using  XICU components.
137// It writes the "wdata" value in the mailbox defined by the cluster index
138// and the processor index.
139// Returns 0 if success, > 0 if error.
140////////////////////////////////////////////////////////////////////////////////
[263]141unsigned int _xcu_send_ipi( unsigned int cluster_xy,
[258]142                            unsigned int proc_id,
143                            unsigned int wdata )
144{ 
145    // parameters checking
[263]146    unsigned int x = cluster_xy >> Y_WIDTH;
147    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
148    if (x >= X_SIZE)             return 1; 
149    if (y >= Y_SIZE)             return 1; 
150    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]151
152#if USE_XICU
153    unsigned int* xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
[263]154                                 (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]155    xcu_address[XICU_REG(XICU_WTI_REG, proc_id)] = wdata;
156    return 0; 
157#else
158    _tty_get_lock( 0 );
159    _puts("[GIET ERROR] _xcu_send_ipi should not be used if USE_XICU is not set\n");
160    _tty_release_lock( 0 );
161    return 1;
162#endif
163} 
164
165////////////////////////////////////////////////////////////////////////////////
166//    _xcu_timer_start()
167// This function activates a timer contained in XICU by writing in the
168// proper register the period value.
169// Returns 0 if success, > 0 if error.
170////////////////////////////////////////////////////////////////////////////////
[263]171unsigned int _xcu_timer_start( unsigned int cluster_xy,
172                               unsigned int proc_id,
[258]173                               unsigned int period )
174{
175    // parameters checking
[263]176    unsigned int x = cluster_xy >> Y_WIDTH;
177    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
178    if (x >= X_SIZE)             return 1; 
179    if (y >= Y_SIZE)             return 1; 
180    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]181
182#if USE_XICU
183    unsigned int* xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
[263]184                                (cluster_xy * (unsigned int)&vseg_cluster_increment));
185    xcu_address[XICU_REG(XICU_PTI_PER, proc_id)] = period;
[258]186    return 0;
187#else
188    _tty_get_lock( 0 );
189    _puts("[GIET ERROR] _xcu_timer_start should not be used if USE_XICU is not set\n");
190    _tty_release_lock( 0 );
191    return 1;
192#endif
193}
194
195//////////////////////////////////////////////////////////////////////////////
196//     _xcu_timer_stop()
197// This function desactivates a timer in XICU component
198// by writing in the proper register.
199// Returns 0 if success, > 0 if error.
200//////////////////////////////////////////////////////////////////////////////
[263]201unsigned int _xcu_timer_stop( unsigned int cluster_xy, 
202                              unsigned int proc_id) 
[258]203{
204    // parameters checking
[263]205    unsigned int x = cluster_xy >> Y_WIDTH;
206    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
207    if (x >= X_SIZE)             return 1; 
208    if (y >= Y_SIZE)             return 1; 
209    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]210
211#if USE_XICU
212    unsigned int * xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
[263]213                                 (cluster_xy * (unsigned int)&vseg_cluster_increment));
214    xcu_address[XICU_REG(XICU_PTI_PER, proc_id)] = 0;
[258]215    return 0;
216#else
217    _tty_get_lock( 0 );
218    _puts("[GIET ERROR] _xcu_timer_stop should not be used if USE_XICU is not set\n");
219    _tty_release_lock( 0 );
220    return 1;
221#endif
222}
223
224//////////////////////////////////////////////////////////////////////////////
225//     _xcu_timer_reset_irq()
226// This function acknowlegge a timer interrupt in XICU
227// component by reading in the proper register.
228// It can be used by both the isr_switch() for a "system" timer,
229// or by the _isr_timer() for an "user" timer.
230// Returns 0 if success, > 0 if error.
231//////////////////////////////////////////////////////////////////////////////
[263]232unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
233                                   unsigned int proc_id ) 
[258]234{
235    // parameters checking
[263]236    unsigned int x = cluster_xy >> Y_WIDTH;
237    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
238    if (x >= X_SIZE)             return 1; 
239    if (y >= Y_SIZE)             return 1; 
240    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]241
242#if USE_XICU
243    unsigned int * xcu_address = (unsigned int *) ((unsigned int)&seg_xcu_base +
[263]244                                 (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]245
[263]246    unsigned int bloup = xcu_address[XICU_REG(XICU_PTI_ACK, proc_id)];
[258]247    bloup++; // to avoid a warning
248    return 0;
249#else
250    _tty_get_lock( 0 );
251    _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
252    _tty_release_lock( 0 );
253    return 1;
254#endif
255}
256
257//////////////////////////////////////////////////////////////////////////////
258//     _xcu_timer_reset_cpt()
259// This function resets a timer counter. To do so, we re-write the period
260// in the proper register, what causes the count to restart.
261// The period value is read from the same (TIMER_PERIOD) register,
262// this is why in appearance we do nothing useful (read a value
263// from a register and write this value in the same register)
264// This function is called during a context switch (user or preemptive)
265/////////////////////////////////////////////////////////////////////////////
[263]266unsigned int _xcu_timer_reset_cpt( unsigned int cluster_xy, 
267                                   unsigned int proc_id ) 
[258]268{
269    // parameters checking
[263]270    unsigned int x = cluster_xy >> Y_WIDTH;
271    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
272    if (x >= X_SIZE)             return 1; 
273    if (y >= Y_SIZE)             return 1; 
274    if (proc_id >= NB_PROCS_MAX) return 1; 
[258]275
276#if USE_XICU
277    unsigned int * xcu_address = (unsigned int *) ((unsigned int) &seg_xcu_base + 
[263]278                                 (cluster_xy * (unsigned int)&vseg_cluster_increment));
[258]279
[263]280    unsigned int period = xcu_address[XICU_REG(XICU_PTI_PER, proc_id)];
[258]281
282    // we write 0 first because if the timer is currently running,
283    // the corresponding timer counter is not reset
[263]284    xcu_address[XICU_REG(XICU_PTI_PER, proc_id)] = 0;
285    xcu_address[XICU_REG(XICU_PTI_PER, proc_id)] = period;
[258]286    return 0;
287#else
288    _tty_get_lock( 0 );
289    _puts("[GIET ERROR] _xcu_timer_reset_irq should not be used if USE_XICU is not set\n");
290    _tty_release_lock( 0 );
291    return 1;
292#endif
293}
294
295
296// Local Variables:
297// tab-width: 4
298// c-basic-offset: 4
299// c-file-offsets:((innamespace . 0)(inline-open . 0))
300// indent-tabs-mode: nil
301// End:
302// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
303
Note: See TracBrowser for help on using the repository browser.