source: branches/reconfiguration/modules/vci_xicu/caba/source/src/vci_xicu.cpp @ 999

Last change on this file since 999 was 999, checked in by cfuguet, 9 years ago

reconf: introduce a mechanism in the reconf:vci_xicu component to
simulate stuck-at-0 faults on mailboxes.

File size: 17.5 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        if (idx == m_faulty_wti_reg) {
75            data &= m_faulty_wti_msk;
76        }
77        r_wti_pending |= 1<<idx;
78        r_wti_reg[idx] = data;
79
80#if SOCLIB_MODULE_DEBUG
81std::cout << "[" << name() << "] Write WTI_REG[" << std::dec << idx << "] = "
82<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
83#endif
84        return true;
85
86        case XICU_PTI_PER:
87        CHECK_BOUNDS(pti);
88        r_pti_per[idx] = data;
89        if ( !data )
90        {
91            r_pti_pending &= ~(1<<idx);
92            r_pti_val[idx] = 0;
93        }
94        else if (r_pti_val[idx] == 0)
95        {
96            r_pti_val[idx] = data;
97        }
98
99#if SOCLIB_MODULE_DEBUG
100std::cout << "[" << name() << "] Write PTI_PER[" << std::dec << idx << "] = "
101<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
102#endif
103        return true;
104
105        case XICU_PTI_VAL:
106        CHECK_BOUNDS(pti);
107        r_pti_val[idx] = data;
108
109#if SOCLIB_MODULE_DEBUG
110std::cout << "[" << name() << "] Write PTI_VAL[" << std::dec << idx << "] = "
111<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
112#endif
113        return true;
114
115        case XICU_MSK_PTI:
116        CHECK_BOUNDS(irq);
117        r_msk_pti[idx] = data;
118
119#if SOCLIB_MODULE_DEBUG
120std::cout << "[" << name() << "] Write MASK_PTI[" << std::dec << idx << "] = "
121<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
122#endif
123        return true;
124
125        case XICU_MSK_PTI_ENABLE:
126        CHECK_BOUNDS(irq);
127        r_msk_pti[idx] |= data;
128
129#if SOCLIB_MODULE_DEBUG
130std::cout << "[" << name() << "] Write PTI_ENABLE[" << std::dec << idx << "] = "
131<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
132#endif
133        return true;
134
135        case XICU_MSK_PTI_DISABLE:
136        CHECK_BOUNDS(irq);
137        r_msk_pti[idx] &= ~data;
138
139#if SOCLIB_MODULE_DEBUG
140std::cout << "[" << name() << "] Write PTI_DISABLE[" << std::dec << idx << "] = "
141<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
142#endif
143        return true;
144
145        case XICU_MSK_HWI:
146        CHECK_BOUNDS(irq);
147        r_msk_hwi[idx] = data;
148
149#if SOCLIB_MODULE_DEBUG
150std::cout << "[" << name() << "] Write MSK_HWI[" << std::dec << idx << "] = "
151<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
152#endif
153        return true;
154
155        case XICU_MSK_HWI_ENABLE:
156        CHECK_BOUNDS(irq);
157        r_msk_hwi[idx] |= data;
158
159#if SOCLIB_MODULE_DEBUG
160std::cout << "[" << name() << "] Write HWI_ENABLE[" << std::dec << idx << "] = "
161<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
162#endif
163        return true;
164
165        case XICU_MSK_HWI_DISABLE:
166        CHECK_BOUNDS(irq);
167        r_msk_hwi[idx] &= ~data;
168
169#if SOCLIB_MODULE_DEBUG
170std::cout << "[" << name() << "] Write HWI_DISABLE[" << std::dec << idx << "] = "
171<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
172#endif
173        return true;
174
175        case XICU_MSK_WTI:
176        CHECK_BOUNDS(irq);
177        r_msk_wti[idx] = data;
178
179#if SOCLIB_MODULE_DEBUG
180std::cout << "[" << name() << "] Write MSK_WTI[" << std::dec << idx << "] = "
181<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
182#endif
183        return true;
184
185        case XICU_MSK_WTI_ENABLE:
186        CHECK_BOUNDS(irq);
187        r_msk_wti[idx] |= data;
188
189#if SOCLIB_MODULE_DEBUG
190std::cout << "[" << name() << "] Write WTI_ENABLE[" << std::dec << idx << "] = "
191<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
192#endif
193        return true;
194
195        case XICU_MSK_WTI_DISABLE:
196        CHECK_BOUNDS(irq);
197        r_msk_wti[idx] &= ~data;
198
199#if SOCLIB_MODULE_DEBUG
200std::cout << "[" << name() << "] Write WTI_DISABLE[" << std::dec << idx << "] = "
201<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
202#endif
203        return true;
204
205        case XICU_CFG_REG:
206        CHECK_BOUNDS(cfg);
207        r_cfg_reg[idx] = data;
208
209#if SOCLIB_MODULE_DEBUG
210std::cout << "[" << name() << "] Write CFG_REG[" << std::dec << idx << "] = "
211<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
212#endif
213        return true;
214    }
215    return false;
216} // end on_write()
217
218/////////////////////////////////////////////////////
219tmpl(bool)::on_read( int                        seg,
220                     typename vci_param::addr_t addr,
221                     typename vci_param::data_t &data)
222{
223    size_t cell = (size_t)addr / vci_param::B;
224    size_t idx = cell & 0x1f;
225    size_t func = (cell >> 5) & 0x1f;
226
227    switch (func)
228    {
229        case XICU_WTI_REG:
230        CHECK_BOUNDS(wti);
231        data = r_wti_reg[idx];
232        r_wti_pending &= ~(1<<idx);
233
234#if SOCLIB_MODULE_DEBUG
235std::cout << "[" << name() << "] Read XICU_WTI_REG[" << std::dec << idx << "] = "
236<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
237#endif
238        return true;
239
240        case XICU_PTI_PER:
241        CHECK_BOUNDS(pti);
242        data = r_pti_per[idx];
243
244#if SOCLIB_MODULE_DEBUG
245std::cout << "[" << name() << "] Read XICU_PTI_PER[" << std::dec << idx << "] = "
246<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
247#endif
248        return true;
249
250        case XICU_PTI_VAL:
251        CHECK_BOUNDS(pti);
252        data = r_pti_val[idx];
253
254#if SOCLIB_MODULE_DEBUG
255std::cout << "[" << name() << "] Read XICU_PTI_VAL[" << std::dec << idx << "] = "
256<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
257#endif
258        return true;
259
260        case XICU_PTI_ACK:
261        CHECK_BOUNDS(pti);
262        r_pti_pending &= ~(1<<idx);
263        data = 0;
264
265#if SOCLIB_MODULE_DEBUG
266std::cout << "[" << name() << "] Read XICU_PTI_ACK[" << std::dec << idx << "] = "
267<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
268#endif
269        return true;
270
271        case XICU_MSK_PTI:
272        CHECK_BOUNDS(irq);
273        data = r_msk_pti[idx];
274
275#if SOCLIB_MODULE_DEBUG
276std::cout << "[" << name() << "] Read XICU_MSK_PTI[" << std::dec << idx << "] = "
277<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
278#endif
279        return true;
280
281        case XICU_PTI_ACTIVE:
282        CHECK_BOUNDS(irq);
283        data = r_msk_pti[idx] & r_pti_pending;
284
285#if SOCLIB_MODULE_DEBUG
286std::cout << "[" << name() << "] Read XICU_PTI_ACTIVE[" << std::dec << idx << "] = "
287<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
288#endif
289        return true;
290
291        case XICU_MSK_HWI:
292        CHECK_BOUNDS(irq);
293        data = r_msk_hwi[idx];
294
295#if SOCLIB_MODULE_DEBUG
296std::cout << "[" << name() << "] Read XICU_MSK_HWI[" << std::dec << idx << "] = "
297<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
298#endif
299        return true;
300
301        case XICU_HWI_ACTIVE:
302        CHECK_BOUNDS(irq);
303        data = r_msk_hwi[idx] & r_hwi_pending;
304
305#if SOCLIB_MODULE_DEBUG
306std::cout << "[" << name() << "] Read XICU_HWI_ACTIVE[" << std::dec << idx << "] = "
307<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
308#endif
309        return true;
310
311        case XICU_MSK_WTI:
312        CHECK_BOUNDS(irq);
313        data = r_msk_wti[idx];
314
315#if SOCLIB_MODULE_DEBUG
316std::cout << "[" << name() << "] Read XICU_MSK_WTI[" << std::dec << idx << "] = "
317<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
318#endif
319        return true;
320
321        case XICU_WTI_ACTIVE:
322        CHECK_BOUNDS(irq);
323        data = r_msk_wti[idx] & r_wti_pending;
324
325#if SOCLIB_MODULE_DEBUG
326std::cout << "[" << name() << "] Read XICU_WTI_ACTIVE[" << std::dec << idx << "] = "
327<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
328#endif
329        return true;
330
331        case XICU_PRIO:
332        CHECK_BOUNDS(irq);
333        {
334            uint32_t pti_active = r_msk_pti[idx] & r_pti_pending;
335            uint32_t hwi_active = r_msk_hwi[idx] & r_hwi_pending;
336            uint32_t wti_active = r_msk_wti[idx] & r_wti_pending;
337            uint32_t t = pti_active ? 1 : 0;
338            uint32_t h = hwi_active ? 1 : 0;
339            uint32_t w = wti_active ? 1 : 0;
340            uint32_t prio_pti = t ? soclib::common::ctz<uint32_t>(pti_active) : 0;
341            uint32_t prio_hwi = h ? soclib::common::ctz<uint32_t>(hwi_active) : 0;
342            uint32_t prio_wti = w ? soclib::common::ctz<uint32_t>(wti_active) : 0;
343
344            data = (t << 0) | (h << 1) | (w << 2) |
345                   (prio_pti << 8 ) | (prio_hwi << 16) | (prio_wti << 24);
346        }
347#if SOCLIB_MODULE_DEBUG
348std::cout << "[" << name() << "] Read XICU_PRIO[" << std::dec << idx << "] = "
349<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
350#endif
351        return true;
352
353        case XICU_CONFIG:
354        data = (m_irq_count << 24) | (m_wti_count << 16) | (m_hwi_count << 8) | m_pti_count;
355
356#if SOCLIB_MODULE_DEBUG
357std::cout << "[" << name() << "] Read XICU_CONFIG = "
358<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
359#endif
360        return true;
361
362        case XICU_CFG_REG:
363        CHECK_BOUNDS(cfg);
364        data = r_cfg_reg[idx];
365
366#if SOCLIB_MODULE_DEBUG
367std::cout << "[" << name() << "] Read XICU_CFG_REG[" << std::dec << idx << "] = "
368<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
369#endif
370        return true;
371    }
372    return false;
373} // end on_read()
374
375////////////////////////
376tmpl(void)::transition()
377{
378#if SOCLIB_MODULE_DEBUG
379    m_clock_cycles++;
380#endif
381
382    if (!p_resetn.read())
383    {
384        m_vci_fsm.reset();
385
386        for ( size_t i = 0; i<m_pti_count; ++i )
387        {
388            r_pti_per[i] = 0;
389            r_pti_val[i] = 0;
390        }
391        for ( size_t i = 0; i<m_wti_count; ++i )
392        {
393            r_wti_reg[i] = 0;
394        }
395        for ( size_t i = 0; i<m_irq_count; ++i )
396        {
397            r_msk_pti[i] = 0;
398            r_msk_wti[i] = 0;
399            r_msk_hwi[i] = 0;
400        }
401        for ( size_t i = 0; i<m_cfg_count; ++i )
402        {
403            r_cfg_reg[i] = 0;
404        }
405        r_pti_pending = 0;
406        r_wti_pending = 0;
407        r_hwi_pending = 0;
408
409        return;
410    }
411
412    // update timer interrupt vector
413    for ( size_t i = 0; i<m_pti_count; ++i )
414    {
415        uint32_t per = r_pti_per[i];
416
417        if ( per && --r_pti_val[i] == 0 )
418        {
419            r_pti_pending |= 1<<i;
420            r_pti_val[i] = per;
421        }
422    }
423
424    // update pending hardware interrupt vector
425    uint32_t hwi_pending = 0;
426    for ( size_t i = 0; i<m_hwi_count; ++i )
427        hwi_pending |= (p_hwi[i].read() ? 1 : 0) << i;
428    r_hwi_pending = hwi_pending;
429
430    m_vci_fsm.transition();
431}
432
433//////////////////////////////////////////
434tmpl(void)::print_trace( size_t channel )
435{
436    assert( (channel < m_irq_count) and
437    "ERROR in XICU print_trace() : channel larger than proc number");
438
439    std::cout << "XICU " << name() << std::hex
440              << " / HWI_MASK = " << r_msk_hwi[channel]
441              << " / SWI_MASK = " << r_msk_wti[channel]
442              << " / PTI_MASK = " << r_msk_pti[channel]
443              << " / HWI = " << r_hwi_pending
444              << " / WTI = " << r_wti_pending
445              << " / PTI = " << r_pti_pending
446              << std::endl;
447}
448
449///////////////////////
450tmpl(void)::genMoore()
451{
452    m_vci_fsm.genMoore();
453
454    // output irqs
455    for ( size_t i = 0; i<m_irq_count; ++i )
456    {
457        bool b = (r_msk_pti[i] & r_pti_pending) ||
458                 (r_msk_wti[i] & r_wti_pending) ||
459                 (r_msk_hwi[i] & r_hwi_pending);
460
461#if SOCLIB_MODULE_DEBUG
462if ( b && !p_irq[i].read())
463{
464    std::cout << "[" << name() << "] set p_irq[" << i << "] / "
465              << std::hex
466              << " msk_pti[" << i << "] = " << r_msk_pti[i] << " / "
467              << " pti_pending = " << r_pti_pending << " / "
468              << " msk_wti[" << i << "] = " << r_msk_wti[i] << " / "
469              << " wti_pending = " << r_wti_pending << " / "
470              << " msk_hwi[" << i << "] = " << r_msk_hwi[i] << " / "
471              << " hwi_pending = " << r_hwi_pending
472              << std::dec << std::endl;
473}
474if ( !b && p_irq[i].read())
475{
476    std::cout << "[" << name() << "] unset p_irq[" << i << "]" << std::endl;
477}
478#endif
479        p_irq[i] = b;
480    }
481
482    // output cfg registers
483    for ( size_t i = 0; i<m_cfg_count; ++i )
484    {
485        p_cfg[i] = r_cfg_reg[i];
486    }
487}
488
489//////////////////////////////////////////////////
490tmpl(/**/)::VciXicu( sc_core::sc_module_name name,
491                     const MappingTable      &mt,
492                     const                   IntTab &index,
493                     size_t                  pti_count,
494                     size_t                  hwi_count,
495                     size_t                  wti_count,
496                     size_t                  irq_count,
497                     size_t                  cfg_count )
498           : caba::BaseModule(name),
499           m_seglist(mt.getSegmentList(index)),
500           m_vci_fsm(p_vci, m_seglist),
501           m_pti_count(pti_count),
502           m_hwi_count(hwi_count),
503           m_wti_count(wti_count),
504           m_irq_count(irq_count),
505           m_cfg_count(cfg_count),
506           r_msk_pti(new uint32_t[irq_count]),
507           r_msk_wti(new uint32_t[irq_count]),
508           r_msk_hwi(new uint32_t[irq_count]),
509           r_pti_pending(0),
510           r_wti_pending(0),
511           r_hwi_pending(0),
512           r_pti_per(new uint32_t[pti_count]),
513           r_pti_val(new uint32_t[pti_count]),
514           r_wti_reg(new uint32_t[wti_count]),
515           m_faulty_wti_reg(0xFFFFFFFF),
516           m_faulty_wti_msk(0x00000000),
517           m_clock_cycles(0),
518           p_clk("clk"),
519           p_resetn("resetn"),
520           p_vci("vci"),
521           p_irq(soclib::common::alloc_elems<sc_core::sc_out<bool> >("irq", irq_count)),
522           p_hwi(soclib::common::alloc_elems<sc_core::sc_in<bool> >("hwi", hwi_count))
523{
524    std::cout << "  - Building VciXicu : " << name << std::endl;
525
526    std::list<soclib::common::Segment>::iterator seg;
527    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
528    {
529        std::cout << "    => segment " << seg->name()
530                  << " / base = " << std::hex << seg->baseAddress()
531                  << " / size = " << seg->size() << std::endl;
532    }
533
534    if ( cfg_count > 0 )
535    {
536        r_cfg_reg = new uint32_t[cfg_count];
537        p_cfg = soclib::common::alloc_elems<sc_core::sc_out<uint32_t> >("cfg", cfg_count);
538    }
539
540    m_vci_fsm.on_read_write( on_read, on_write );
541
542    SC_METHOD(transition);
543    dont_initialize();
544    sensitive << p_clk.pos();
545
546    SC_METHOD(genMoore);
547    dont_initialize();
548    sensitive << p_clk.neg();
549}
550
551//////////////////////
552tmpl(/**/)::~VciXicu()
553{
554    delete [] r_msk_pti;
555    delete [] r_msk_wti;
556    delete [] r_msk_hwi;
557    delete [] r_pti_per;
558    delete [] r_pti_val;
559    delete [] r_wti_reg;
560    soclib::common::dealloc_elems(p_irq, m_irq_count);
561    soclib::common::dealloc_elems(p_hwi, m_hwi_count);
562    if ( m_cfg_count > 0 )
563    {
564        delete [] r_cfg_reg;
565        soclib::common::dealloc_elems(p_cfg, m_cfg_count);
566    }
567}
568
569}}
570
571// Local Variables:
572// tab-width: 4
573// c-basic-offset: 4
574// c-file-offsets:((innamespace . 0)(inline-open . 0))
575// indent-tabs-mode: nil
576// End:
577
578// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
579
Note: See TracBrowser for help on using the repository browser.