source: branches/fault_tolerance/module/infrastructure_component/interrupt_infrastructure/vci_xicu/caba/source/src/vci_xicu.cpp @ 647

Last change on this file since 647 was 647, checked in by cfuguet, 10 years ago

Creating branch for fault tolerance support on the TSAR architecture.

Some components from the SOCLIB repository which will be modified has
been copied in this branch.

File size: 15.3 KB
Line 
1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6
24 *         Nicolas Pouillon <nipo@ssji.net>, 2009
25 */
26
27#include <strings.h>
28
29#include "xicu.h"
30#include "register.h"
31#include "arithmetics.h"
32#include "alloc_elems.h"
33#include "../include/vci_xicu.h"
34
35namespace soclib {
36namespace caba {
37
38using namespace soclib;
39
40#define tmpl(t) template<typename vci_param> t VciXicu<vci_param>
41
42#ifdef SOCLIB_MODULE_DEBUG
43#define CHECK_BOUNDS(x)                                                \
44    do {                                                               \
45        if ( idx >= (m_##x##_count) ) {                                \
46            std::cout << name() << " error: " #x " index " << idx      \
47                      << " out of bounds ("                            \
48                      << m_##x##_count << ")"                          \
49                      << std::endl;                                    \
50            return false;                                              \
51        }                                                              \
52    } while(0)
53#else
54#define CHECK_BOUNDS(x) do { if ( idx >= (m_##x##_count) ) return false; } while(0)
55#endif
56
57//////////////////////////////////////////////////////
58tmpl(bool)::on_write( int                        seg, 
59                      typename vci_param::addr_t addr, 
60                      typename vci_param::data_t data, 
61                      int                        be)
62{
63        size_t cell = (size_t)addr / vci_param::B;
64        size_t idx = cell & 0x1f;
65        size_t func = (cell >> 5) & 0x1f;
66
67    if ( be != 0xf )
68        return false;
69
70        switch (func) 
71    {
72        case XICU_WTI_REG:
73        CHECK_BOUNDS(wti);
74        r_wti_reg[idx] = data;
75        r_wti_pending |= 1<<idx;
76
77#if SOCLIB_MODULE_DEBUG
78std::cout << "[" << name() << "] Write WTI_REG[" << std::dec << idx << "] = " 
79<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
80#endif
81        return true;
82
83        case XICU_PTI_PER:
84        CHECK_BOUNDS(pti);
85        r_pti_per[idx] = data;
86        if ( !data ) 
87        {
88            r_pti_pending &= ~(1<<idx);
89            r_pti_val[idx] = 0;
90        } 
91        else if (r_pti_val[idx] == 0) 
92        {
93            r_pti_val[idx] = data;
94        }
95
96#if SOCLIB_MODULE_DEBUG
97std::cout << "[" << name() << "] Write PTI_PER[" << std::dec << idx << "] = " 
98<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
99#endif
100        return true;
101
102        case XICU_PTI_VAL:
103        CHECK_BOUNDS(pti);
104        r_pti_val[idx] = data;
105
106#if SOCLIB_MODULE_DEBUG
107std::cout << "[" << name() << "] Write PTI_VAL[" << std::dec << idx << "] = " 
108<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
109#endif
110        return true;
111
112        case XICU_MSK_PTI:
113        CHECK_BOUNDS(irq);
114        r_msk_pti[idx] = data;
115
116#if SOCLIB_MODULE_DEBUG
117std::cout << "[" << name() << "] Write MASK_PTI[" << std::dec << idx << "] = " 
118<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
119#endif
120        return true;
121
122        case XICU_MSK_PTI_ENABLE:
123        CHECK_BOUNDS(irq);
124        r_msk_pti[idx] |= data;
125
126#if SOCLIB_MODULE_DEBUG
127std::cout << "[" << name() << "] Write PTI_ENABLE[" << std::dec << idx << "] = " 
128<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
129#endif
130        return true;
131
132        case XICU_MSK_PTI_DISABLE:
133        CHECK_BOUNDS(irq);
134        r_msk_pti[idx] &= ~data;
135
136#if SOCLIB_MODULE_DEBUG
137std::cout << "[" << name() << "] Write PTI_DISABLE[" << std::dec << idx << "] = " 
138<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
139#endif
140        return true;
141
142        case XICU_MSK_HWI:
143        CHECK_BOUNDS(irq);
144        r_msk_hwi[idx] = data;
145
146#if SOCLIB_MODULE_DEBUG
147std::cout << "[" << name() << "] Write MSK_HWI[" << std::dec << idx << "] = " 
148<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
149#endif
150        return true;
151
152        case XICU_MSK_HWI_ENABLE:
153        CHECK_BOUNDS(irq);
154        r_msk_hwi[idx] |= data;
155
156#if SOCLIB_MODULE_DEBUG
157std::cout << "[" << name() << "] Write HWI_ENABLE[" << std::dec << idx << "] = " 
158<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
159#endif
160        return true;
161
162        case XICU_MSK_HWI_DISABLE:
163        CHECK_BOUNDS(irq);
164        r_msk_hwi[idx] &= ~data;
165
166#if SOCLIB_MODULE_DEBUG
167std::cout << "[" << name() << "] Write HWI_DISABLE[" << std::dec << idx << "] = " 
168<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
169#endif
170        return true;
171
172        case XICU_MSK_WTI:
173        CHECK_BOUNDS(irq);
174        r_msk_wti[idx] = data;
175
176#if SOCLIB_MODULE_DEBUG
177std::cout << "[" << name() << "] Write MSK_WTI[" << std::dec << idx << "] = " 
178<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
179#endif
180        return true;
181
182        case XICU_MSK_WTI_ENABLE:
183        CHECK_BOUNDS(irq);
184        r_msk_wti[idx] |= data;
185
186#if SOCLIB_MODULE_DEBUG
187std::cout << "[" << name() << "] Write WTI_ENABLE[" << std::dec << idx << "] = " 
188<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
189#endif
190        return true;
191
192        case XICU_MSK_WTI_DISABLE:
193        CHECK_BOUNDS(irq);
194        r_msk_wti[idx] &= ~data;
195
196#if SOCLIB_MODULE_DEBUG
197std::cout << "[" << name() << "] Write WTI_DISABLE[" << std::dec << idx << "] = " 
198<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
199#endif
200        return true;
201        }
202        return false;
203} // end on_write()
204
205/////////////////////////////////////////////////////
206tmpl(bool)::on_read( int                        seg, 
207                     typename vci_param::addr_t addr, 
208                     typename vci_param::data_t &data)
209{
210        size_t cell = (size_t)addr / vci_param::B;
211    size_t idx = cell & 0x1f;
212        size_t func = (cell >> 5) & 0x1f;
213
214        switch (func) 
215    {
216    case XICU_WTI_REG:
217        CHECK_BOUNDS(wti);
218        data = r_wti_reg[idx];
219        r_wti_pending &= ~(1<<idx);       
220
221#if SOCLIB_MODULE_DEBUG
222std::cout << "[" << name() << "] Read XICU_WTI_REG[" << std::dec << idx << "] = " 
223<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
224#endif
225        return true;
226
227        case XICU_PTI_PER:
228        CHECK_BOUNDS(pti);
229        data = r_pti_per[idx];
230
231#if SOCLIB_MODULE_DEBUG
232std::cout << "[" << name() << "] Read XICU_PTI_PER[" << std::dec << idx << "] = " 
233<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
234#endif
235        return true;
236
237        case XICU_PTI_VAL:
238        CHECK_BOUNDS(pti);
239        data = r_pti_val[idx];
240
241#if SOCLIB_MODULE_DEBUG
242std::cout << "[" << name() << "] Read XICU_PTI_VAL[" << std::dec << idx << "] = " 
243<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
244#endif
245        return true;
246
247        case XICU_PTI_ACK:
248        CHECK_BOUNDS(pti);
249        r_pti_pending &= ~(1<<idx);
250        data = 0;
251
252#if SOCLIB_MODULE_DEBUG
253std::cout << "[" << name() << "] Read XICU_PTI_ACK[" << std::dec << idx << "] = " 
254<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
255#endif
256        return true;
257
258        case XICU_MSK_PTI:
259        CHECK_BOUNDS(irq);
260        data = r_msk_pti[idx];
261
262#if SOCLIB_MODULE_DEBUG
263std::cout << "[" << name() << "] Read XICU_MSK_PTI[" << std::dec << idx << "] = " 
264<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
265#endif
266        return true;
267
268        case XICU_PTI_ACTIVE:
269        CHECK_BOUNDS(irq);
270        data = r_msk_pti[idx] & r_pti_pending;
271
272#if SOCLIB_MODULE_DEBUG
273std::cout << "[" << name() << "] Read XICU_PTI_ACTIVE[" << std::dec << idx << "] = " 
274<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
275#endif
276        return true;
277
278        case XICU_MSK_HWI:
279        CHECK_BOUNDS(irq);
280        data = r_msk_hwi[idx];
281
282#if SOCLIB_MODULE_DEBUG
283std::cout << "[" << name() << "] Read XICU_MSK_HWI[" << std::dec << idx << "] = " 
284<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
285#endif
286        return true;
287
288        case XICU_HWI_ACTIVE:
289        CHECK_BOUNDS(irq);
290        data = r_msk_hwi[idx] & r_hwi_pending;
291
292#if SOCLIB_MODULE_DEBUG
293std::cout << "[" << name() << "] Read XICU_HWI_ACTIVE[" << std::dec << idx << "] = " 
294<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
295#endif
296        return true;
297
298        case XICU_MSK_WTI:
299        CHECK_BOUNDS(irq);
300        data = r_msk_wti[idx];
301
302#if SOCLIB_MODULE_DEBUG
303std::cout << "[" << name() << "] Read XICU_MSK_WTI[" << std::dec << idx << "] = " 
304<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
305#endif
306        return true;
307
308        case XICU_WTI_ACTIVE:
309        CHECK_BOUNDS(irq);
310        data = r_msk_wti[idx] & r_wti_pending;
311
312#if SOCLIB_MODULE_DEBUG
313std::cout << "[" << name() << "] Read XICU_WTI_ACTIVE[" << std::dec << idx << "] = " 
314<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
315#endif
316        return true;
317
318        case XICU_PRIO:
319        CHECK_BOUNDS(irq);
320        data = 
321            (((r_msk_pti[idx] & r_pti_pending) ? 1 : 0) << 0) |
322            (((r_msk_hwi[idx] & r_hwi_pending) ? 1 : 0) << 1) |
323            (((r_msk_wti[idx] & r_wti_pending) ? 1 : 0) << 2) |
324            ((soclib::common::ctz<uint32_t>(r_msk_pti[idx] & r_pti_pending) & 0x1f) <<  8) |
325            ((soclib::common::ctz<uint32_t>(r_msk_hwi[idx] & r_hwi_pending) & 0x1f) << 16) |
326            ((soclib::common::ctz<uint32_t>(r_msk_wti[idx] & r_wti_pending) & 0x1f) << 24);
327
328#if SOCLIB_MODULE_DEBUG
329std::cout << "[" << name() << "] Read XICU_PRIO[" << std::dec << idx << "] = " 
330<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
331#endif
332        return true;
333
334    case XICU_CONFIG:
335        data = (m_irq_count << 24) | (m_wti_count << 16) | (m_hwi_count << 8) | m_pti_count;
336#if SOCLIB_MODULE_DEBUG
337std::cout << "[" << name() << "] Read XICU_CONFIG = " << std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
338#endif
339        return true;
340        }
341        return false;
342} // end on_read()
343
344////////////////////////
345tmpl(void)::transition()
346{
347#if SOCLIB_MODULE_DEBUG
348    m_clock_cycles++;
349#endif
350
351        if (!p_resetn.read()) 
352    {
353                m_vci_fsm.reset();
354
355        for ( size_t i = 0; i<m_pti_count; ++i ) 
356        {
357            r_pti_per[i] = 0;
358            r_pti_val[i] = 0;
359        }
360        for ( size_t i = 0; i<m_wti_count; ++i )
361        {
362            r_wti_reg[i] = 0;
363        }
364        for ( size_t i = 0; i<m_irq_count; ++i ) 
365        {
366            r_msk_pti[i] = 0;
367            r_msk_wti[i] = 0;
368            r_msk_hwi[i] = 0;
369        }
370        r_pti_pending = 0;
371        r_wti_pending = 0;
372        r_hwi_pending = 0;
373
374                return;
375        }
376
377    // update timer interrupt vector
378    for ( size_t i = 0; i<m_pti_count; ++i ) 
379    {
380        uint32_t per = r_pti_per[i];
381
382        if ( per && --r_pti_val[i] == 0 ) 
383        {
384            r_pti_pending |= 1<<i;
385            r_pti_val[i] = per;
386        }
387    }
388
389    // update pending hardware interrupt vector
390    uint32_t hwi_pending = 0;
391    for ( size_t i = 0; i<m_hwi_count; ++i )
392        hwi_pending |= (p_hwi[i].read() ? 1 : 0) << i;
393    r_hwi_pending = hwi_pending;
394
395        m_vci_fsm.transition();
396}
397
398//////////////////////////////////////////
399tmpl(void)::print_trace( size_t channel )
400{
401    assert( (channel < m_irq_count) and
402    "ERROR in XICU print_trace() : channel larger than proc number");
403   
404    std::cout << "XICU " << name() << std::hex
405              << " / HWI_MASK = " << r_msk_hwi[channel]
406              << " / SWI_MASK = " << r_msk_wti[channel]
407              << " / PTI_MASK = " << r_msk_pti[channel] 
408              << " / HWI = " << r_hwi_pending
409              << " / WTI = " << r_wti_pending
410              << " / PTI = " << r_pti_pending
411              << std::endl;
412}
413
414///////////////////////
415tmpl(void)::genMoore()
416{
417        m_vci_fsm.genMoore();
418
419    // output irqs
420    for ( size_t i = 0; i<m_irq_count; ++i ) 
421    {
422        bool b = (r_msk_pti[i] & r_pti_pending) ||
423                 (r_msk_wti[i] & r_wti_pending) ||
424                 (r_msk_hwi[i] & r_hwi_pending);
425
426#if SOCLIB_MODULE_DEBUG
427if ( b ) std::cout << "p_irq[" << i << "] = " << b << std::endl;
428#endif
429        p_irq[i] = b;
430    }
431}
432
433//////////////////////////////////////////////////
434tmpl(/**/)::VciXicu( sc_core::sc_module_name name,
435                     const MappingTable      &mt,
436                     const                   IntTab &index,
437                     size_t                  pti_count,
438                     size_t                  hwi_count,
439                     size_t                  wti_count,
440                     size_t                  irq_count )
441           : caba::BaseModule(name),
442           m_seglist(mt.getSegmentList(index)),
443           m_vci_fsm(p_vci, m_seglist),
444           m_pti_count(pti_count),
445           m_hwi_count(hwi_count),
446           m_wti_count(wti_count),
447           m_irq_count(irq_count),
448           r_msk_pti(new uint32_t[irq_count]),
449           r_msk_wti(new uint32_t[irq_count]),
450           r_msk_hwi(new uint32_t[irq_count]),
451           r_pti_pending(0),
452           r_wti_pending(0),
453           r_hwi_pending(0),
454           r_pti_per(new uint32_t[pti_count]),
455           r_pti_val(new uint32_t[pti_count]),
456           r_wti_reg(new uint32_t[wti_count]),
457           m_clock_cycles(0),
458           p_clk("clk"),
459           p_resetn("resetn"),
460           p_vci("vci"),
461           p_irq(soclib::common::alloc_elems<sc_core::sc_out<bool> >("irq", irq_count)),
462           p_hwi(soclib::common::alloc_elems<sc_core::sc_in<bool> >("hwi", hwi_count))
463{
464    std::cout << "  - Building VciXicu : " << name << std::endl;
465
466    std::list<soclib::common::Segment>::iterator seg;
467    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
468    {
469        std::cout << "    => segment " << seg->name()
470                  << " / base = " << std::hex << seg->baseAddress()
471                  << " / size = " << seg->size() << std::endl; 
472    }
473 
474        m_vci_fsm.on_read_write( on_read, on_write );
475
476        SC_METHOD(transition);
477        dont_initialize();
478        sensitive << p_clk.pos();
479
480        SC_METHOD(genMoore);
481        dont_initialize();
482        sensitive << p_clk.neg();
483}
484
485//////////////////////
486tmpl(/**/)::~VciXicu()
487{
488    delete [] r_msk_pti;
489    delete [] r_msk_wti;
490    delete [] r_msk_hwi;
491    delete [] r_pti_per;
492    delete [] r_pti_val;
493    delete [] r_wti_reg;
494    soclib::common::dealloc_elems(p_irq, m_irq_count);
495    soclib::common::dealloc_elems(p_hwi, m_hwi_count);
496}
497
498}}
499
500// Local Variables:
501// tab-width: 4
502// c-basic-offset: 4
503// c-file-offsets:((innamespace . 0)(inline-open . 0))
504// indent-tabs-mode: nil
505// End:
506
507// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
508
Note: See TracBrowser for help on using the repository browser.