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

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

reconf: introduce vci_xicu component

  • A reconfiguration subfunction will be added to this component
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.