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

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

reconf: fix a bug on the PRIO register of the vci_xicu component

  • fix: the CTZ function returns an undefined value when passing 0 as the argument.
File size: 17.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        case XICU_CFG_REG:
203        CHECK_BOUNDS(cfg);
204        r_cfg_reg[idx] = data;
205
206#if SOCLIB_MODULE_DEBUG
207std::cout << "[" << name() << "] Write CFG_REG[" << std::dec << idx << "] = "
208<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
209#endif
210        return true;
211    }
212    return false;
213} // end on_write()
214
215/////////////////////////////////////////////////////
216tmpl(bool)::on_read( int                        seg,
217                     typename vci_param::addr_t addr,
218                     typename vci_param::data_t &data)
219{
220    size_t cell = (size_t)addr / vci_param::B;
221    size_t idx = cell & 0x1f;
222    size_t func = (cell >> 5) & 0x1f;
223
224    switch (func)
225    {
226        case XICU_WTI_REG:
227        CHECK_BOUNDS(wti);
228        data = r_wti_reg[idx];
229        r_wti_pending &= ~(1<<idx);
230
231#if SOCLIB_MODULE_DEBUG
232std::cout << "[" << name() << "] Read XICU_WTI_REG[" << 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_PER:
238        CHECK_BOUNDS(pti);
239        data = r_pti_per[idx];
240
241#if SOCLIB_MODULE_DEBUG
242std::cout << "[" << name() << "] Read XICU_PTI_PER[" << 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_VAL:
248        CHECK_BOUNDS(pti);
249        data = r_pti_val[idx];
250
251#if SOCLIB_MODULE_DEBUG
252std::cout << "[" << name() << "] Read XICU_PTI_VAL[" << std::dec << idx << "] = "
253<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
254#endif
255        return true;
256
257        case XICU_PTI_ACK:
258        CHECK_BOUNDS(pti);
259        r_pti_pending &= ~(1<<idx);
260        data = 0;
261
262#if SOCLIB_MODULE_DEBUG
263std::cout << "[" << name() << "] Read XICU_PTI_ACK[" << 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_MSK_PTI:
269        CHECK_BOUNDS(irq);
270        data = r_msk_pti[idx];
271
272#if SOCLIB_MODULE_DEBUG
273std::cout << "[" << name() << "] Read XICU_MSK_PTI[" << 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_PTI_ACTIVE:
279        CHECK_BOUNDS(irq);
280        data = r_msk_pti[idx] & r_pti_pending;
281
282#if SOCLIB_MODULE_DEBUG
283std::cout << "[" << name() << "] Read XICU_PTI_ACTIVE[" << 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_MSK_HWI:
289        CHECK_BOUNDS(irq);
290        data = r_msk_hwi[idx];
291
292#if SOCLIB_MODULE_DEBUG
293std::cout << "[" << name() << "] Read XICU_MSK_HWI[" << 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_HWI_ACTIVE:
299        CHECK_BOUNDS(irq);
300        data = r_msk_hwi[idx] & r_hwi_pending;
301
302#if SOCLIB_MODULE_DEBUG
303std::cout << "[" << name() << "] Read XICU_HWI_ACTIVE[" << 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_MSK_WTI:
309        CHECK_BOUNDS(irq);
310        data = r_msk_wti[idx];
311
312#if SOCLIB_MODULE_DEBUG
313std::cout << "[" << name() << "] Read XICU_MSK_WTI[" << 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_WTI_ACTIVE:
319        CHECK_BOUNDS(irq);
320        data = r_msk_wti[idx] & r_wti_pending;
321
322#if SOCLIB_MODULE_DEBUG
323std::cout << "[" << name() << "] Read XICU_WTI_ACTIVE[" << std::dec << idx << "] = "
324<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
325#endif
326        return true;
327
328        case XICU_PRIO:
329        CHECK_BOUNDS(irq);
330        {
331            uint32_t pti_active = r_msk_pti[idx] & r_pti_pending;
332            uint32_t hwi_active = r_msk_hwi[idx] & r_hwi_pending;
333            uint32_t wti_active = r_msk_wti[idx] & r_wti_pending;
334            uint32_t t = pti_active ? 1 : 0;
335            uint32_t h = hwi_active ? 1 : 0;
336            uint32_t w = wti_active ? 1 : 0;
337            uint32_t prio_pti = t ? soclib::common::ctz<uint32_t>(pti_active) : 0;
338            uint32_t prio_hwi = h ? soclib::common::ctz<uint32_t>(hwi_active) : 0;
339            uint32_t prio_wti = w ? soclib::common::ctz<uint32_t>(wti_active) : 0;
340
341            data = (t << 0) | (h << 1) | (w << 2) |
342                   (prio_pti << 8 ) | (prio_hwi << 16) | (prio_wti << 24);
343        }
344#if SOCLIB_MODULE_DEBUG
345std::cout << "[" << name() << "] Read XICU_PRIO[" << std::dec << idx << "] = "
346<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
347#endif
348        return true;
349
350        case XICU_CONFIG:
351        data = (m_irq_count << 24) | (m_wti_count << 16) | (m_hwi_count << 8) | m_pti_count;
352
353#if SOCLIB_MODULE_DEBUG
354std::cout << "[" << name() << "] Read XICU_CONFIG = "
355<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
356#endif
357        return true;
358
359        case XICU_CFG_REG:
360        CHECK_BOUNDS(cfg);
361        data = r_cfg_reg[idx];
362
363#if SOCLIB_MODULE_DEBUG
364std::cout << "[" << name() << "] Read XICU_CFG_REG[" << std::dec << idx << "] = "
365<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
366#endif
367        return true;
368    }
369    return false;
370} // end on_read()
371
372////////////////////////
373tmpl(void)::transition()
374{
375#if SOCLIB_MODULE_DEBUG
376    m_clock_cycles++;
377#endif
378
379    if (!p_resetn.read())
380    {
381        m_vci_fsm.reset();
382
383        for ( size_t i = 0; i<m_pti_count; ++i )
384        {
385            r_pti_per[i] = 0;
386            r_pti_val[i] = 0;
387        }
388        for ( size_t i = 0; i<m_wti_count; ++i )
389        {
390            r_wti_reg[i] = 0;
391        }
392        for ( size_t i = 0; i<m_irq_count; ++i )
393        {
394            r_msk_pti[i] = 0;
395            r_msk_wti[i] = 0;
396            r_msk_hwi[i] = 0;
397        }
398        for ( size_t i = 0; i<m_cfg_count; ++i )
399        {
400            r_cfg_reg[i] = 0;
401        }
402        r_pti_pending = 0;
403        r_wti_pending = 0;
404        r_hwi_pending = 0;
405
406        return;
407    }
408
409    // update timer interrupt vector
410    for ( size_t i = 0; i<m_pti_count; ++i )
411    {
412        uint32_t per = r_pti_per[i];
413
414        if ( per && --r_pti_val[i] == 0 )
415        {
416            r_pti_pending |= 1<<i;
417            r_pti_val[i] = per;
418        }
419    }
420
421    // update pending hardware interrupt vector
422    uint32_t hwi_pending = 0;
423    for ( size_t i = 0; i<m_hwi_count; ++i )
424        hwi_pending |= (p_hwi[i].read() ? 1 : 0) << i;
425    r_hwi_pending = hwi_pending;
426
427    m_vci_fsm.transition();
428}
429
430//////////////////////////////////////////
431tmpl(void)::print_trace( size_t channel )
432{
433    assert( (channel < m_irq_count) and
434    "ERROR in XICU print_trace() : channel larger than proc number");
435
436    std::cout << "XICU " << name() << std::hex
437              << " / HWI_MASK = " << r_msk_hwi[channel]
438              << " / SWI_MASK = " << r_msk_wti[channel]
439              << " / PTI_MASK = " << r_msk_pti[channel]
440              << " / HWI = " << r_hwi_pending
441              << " / WTI = " << r_wti_pending
442              << " / PTI = " << r_pti_pending
443              << std::endl;
444}
445
446///////////////////////
447tmpl(void)::genMoore()
448{
449    m_vci_fsm.genMoore();
450
451    // output irqs
452    for ( size_t i = 0; i<m_irq_count; ++i )
453    {
454        bool b = (r_msk_pti[i] & r_pti_pending) ||
455                 (r_msk_wti[i] & r_wti_pending) ||
456                 (r_msk_hwi[i] & r_hwi_pending);
457
458#if SOCLIB_MODULE_DEBUG
459if ( b && !p_irq[i].read())
460{
461    std::cout << "[" << name() << "] set p_irq[" << i << "] / "
462              << std::hex
463              << " msk_pti[" << i << "] = " << r_msk_pti[i] << " / "
464              << " pti_pending = " << r_pti_pending << " / "
465              << " msk_wti[" << i << "] = " << r_msk_wti[i] << " / "
466              << " wti_pending = " << r_wti_pending << " / "
467              << " msk_hwi[" << i << "] = " << r_msk_hwi[i] << " / "
468              << " hwi_pending = " << r_hwi_pending
469              << std::dec << std::endl;
470}
471if ( !b && p_irq[i].read())
472{
473    std::cout << "[" << name() << "] unset p_irq[" << i << "]" << std::endl;
474}
475#endif
476        p_irq[i] = b;
477    }
478
479    // output cfg registers
480    for ( size_t i = 0; i<m_cfg_count; ++i )
481    {
482        p_cfg[i] = r_cfg_reg[i];
483    }
484}
485
486//////////////////////////////////////////////////
487tmpl(/**/)::VciXicu( sc_core::sc_module_name name,
488                     const MappingTable      &mt,
489                     const                   IntTab &index,
490                     size_t                  pti_count,
491                     size_t                  hwi_count,
492                     size_t                  wti_count,
493                     size_t                  irq_count,
494                     size_t                  cfg_count )
495           : caba::BaseModule(name),
496           m_seglist(mt.getSegmentList(index)),
497           m_vci_fsm(p_vci, m_seglist),
498           m_pti_count(pti_count),
499           m_hwi_count(hwi_count),
500           m_wti_count(wti_count),
501           m_irq_count(irq_count),
502           m_cfg_count(cfg_count),
503           r_msk_pti(new uint32_t[irq_count]),
504           r_msk_wti(new uint32_t[irq_count]),
505           r_msk_hwi(new uint32_t[irq_count]),
506           r_pti_pending(0),
507           r_wti_pending(0),
508           r_hwi_pending(0),
509           r_pti_per(new uint32_t[pti_count]),
510           r_pti_val(new uint32_t[pti_count]),
511           r_wti_reg(new uint32_t[wti_count]),
512           m_clock_cycles(0),
513           p_clk("clk"),
514           p_resetn("resetn"),
515           p_vci("vci"),
516           p_irq(soclib::common::alloc_elems<sc_core::sc_out<bool> >("irq", irq_count)),
517           p_hwi(soclib::common::alloc_elems<sc_core::sc_in<bool> >("hwi", hwi_count))
518{
519    std::cout << "  - Building VciXicu : " << name << std::endl;
520
521    std::list<soclib::common::Segment>::iterator seg;
522    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
523    {
524        std::cout << "    => segment " << seg->name()
525                  << " / base = " << std::hex << seg->baseAddress()
526                  << " / size = " << seg->size() << std::endl;
527    }
528
529    if ( cfg_count > 0 )
530    {
531        r_cfg_reg = new uint32_t[cfg_count];
532        p_cfg = soclib::common::alloc_elems<sc_core::sc_out<uint32_t> >("cfg", cfg_count);
533    }
534
535    m_vci_fsm.on_read_write( on_read, on_write );
536
537    SC_METHOD(transition);
538    dont_initialize();
539    sensitive << p_clk.pos();
540
541    SC_METHOD(genMoore);
542    dont_initialize();
543    sensitive << p_clk.neg();
544}
545
546//////////////////////
547tmpl(/**/)::~VciXicu()
548{
549    delete [] r_msk_pti;
550    delete [] r_msk_wti;
551    delete [] r_msk_hwi;
552    delete [] r_pti_per;
553    delete [] r_pti_val;
554    delete [] r_wti_reg;
555    soclib::common::dealloc_elems(p_irq, m_irq_count);
556    soclib::common::dealloc_elems(p_hwi, m_hwi_count);
557    if ( m_cfg_count > 0 )
558    {
559        delete [] r_cfg_reg;
560        soclib::common::dealloc_elems(p_cfg, m_cfg_count);
561    }
562}
563
564}}
565
566// Local Variables:
567// tab-width: 4
568// c-basic-offset: 4
569// c-file-offsets:((innamespace . 0)(inline-open . 0))
570// indent-tabs-mode: nil
571// End:
572
573// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
574
Note: See TracBrowser for help on using the repository browser.