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

Last change on this file since 881 was 881, checked in by cfuguet, 8 years ago

reconf: introduce a configuration function in the vci_xicu

  • This configuration function consists in a vector of writable registers (up to 32) which are directly connected to an output port (one port per register).
File size: 16.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        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        data =
331            (((r_msk_pti[idx] & r_pti_pending) ? 1 : 0) << 0) |
332            (((r_msk_hwi[idx] & r_hwi_pending) ? 1 : 0) << 1) |
333            (((r_msk_wti[idx] & r_wti_pending) ? 1 : 0) << 2) |
334            ((soclib::common::ctz<uint32_t>(r_msk_pti[idx] & r_pti_pending) & 0x1f) <<  8) |
335            ((soclib::common::ctz<uint32_t>(r_msk_hwi[idx] & r_hwi_pending) & 0x1f) << 16) |
336            ((soclib::common::ctz<uint32_t>(r_msk_wti[idx] & r_wti_pending) & 0x1f) << 24);
337
338#if SOCLIB_MODULE_DEBUG
339std::cout << "[" << name() << "] Read XICU_PRIO[" << std::dec << idx << "] = "
340<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
341#endif
342        return true;
343
344    case XICU_CONFIG:
345        data = (m_irq_count << 24) | (m_wti_count << 16) | (m_hwi_count << 8) | m_pti_count;
346#if SOCLIB_MODULE_DEBUG
347std::cout << "[" << name() << "] Read XICU_CONFIG = " << std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
348#endif
349        return true;
350
351    case XICU_CFG_REG:
352        CHECK_BOUNDS(cfg);
353        data = r_cfg_reg[idx];
354
355#if SOCLIB_MODULE_DEBUG
356std::cout << "[" << name() << "] Read XICU_CFG_REG[" << std::dec << idx << "] = "
357<< std::hex << (int)data << std::dec << " time = " << m_clock_cycles << std::endl;
358#endif
359        return true;
360    }
361    return false;
362} // end on_read()
363
364////////////////////////
365tmpl(void)::transition()
366{
367#if SOCLIB_MODULE_DEBUG
368    m_clock_cycles++;
369#endif
370
371    if (!p_resetn.read())
372    {
373        m_vci_fsm.reset();
374
375        for ( size_t i = 0; i<m_pti_count; ++i )
376        {
377            r_pti_per[i] = 0;
378            r_pti_val[i] = 0;
379        }
380        for ( size_t i = 0; i<m_wti_count; ++i )
381        {
382            r_wti_reg[i] = 0;
383        }
384        for ( size_t i = 0; i<m_irq_count; ++i )
385        {
386            r_msk_pti[i] = 0;
387            r_msk_wti[i] = 0;
388            r_msk_hwi[i] = 0;
389        }
390        for ( size_t i = 0; i<m_cfg_count; ++i )
391        {
392            r_cfg_reg[i] = 0;
393        }
394        r_pti_pending = 0;
395        r_wti_pending = 0;
396        r_hwi_pending = 0;
397
398        return;
399    }
400
401    // update timer interrupt vector
402    for ( size_t i = 0; i<m_pti_count; ++i )
403    {
404        uint32_t per = r_pti_per[i];
405
406        if ( per && --r_pti_val[i] == 0 )
407        {
408            r_pti_pending |= 1<<i;
409            r_pti_val[i] = per;
410        }
411    }
412
413    // update pending hardware interrupt vector
414    uint32_t hwi_pending = 0;
415    for ( size_t i = 0; i<m_hwi_count; ++i )
416        hwi_pending |= (p_hwi[i].read() ? 1 : 0) << i;
417    r_hwi_pending = hwi_pending;
418
419    m_vci_fsm.transition();
420}
421
422//////////////////////////////////////////
423tmpl(void)::print_trace( size_t channel )
424{
425    assert( (channel < m_irq_count) and
426    "ERROR in XICU print_trace() : channel larger than proc number");
427
428    std::cout << "XICU " << name() << std::hex
429              << " / HWI_MASK = " << r_msk_hwi[channel]
430              << " / SWI_MASK = " << r_msk_wti[channel]
431              << " / PTI_MASK = " << r_msk_pti[channel]
432              << " / HWI = " << r_hwi_pending
433              << " / WTI = " << r_wti_pending
434              << " / PTI = " << r_pti_pending
435              << std::endl;
436}
437
438///////////////////////
439tmpl(void)::genMoore()
440{
441    m_vci_fsm.genMoore();
442
443    // output irqs
444    for ( size_t i = 0; i<m_irq_count; ++i )
445    {
446        bool b = (r_msk_pti[i] & r_pti_pending) ||
447                 (r_msk_wti[i] & r_wti_pending) ||
448                 (r_msk_hwi[i] & r_hwi_pending);
449
450#if SOCLIB_MODULE_DEBUG
451if ( b ) std::cout << "p_irq[" << i << "] = " << b << std::endl;
452#endif
453        p_irq[i] = b;
454    }
455
456    // output cfg registers
457    for ( size_t i = 0; i<m_cfg_count; ++i )
458    {
459        p_cfg[i] = r_cfg_reg[i];
460    }
461}
462
463//////////////////////////////////////////////////
464tmpl(/**/)::VciXicu( sc_core::sc_module_name name,
465                     const MappingTable      &mt,
466                     const                   IntTab &index,
467                     size_t                  pti_count,
468                     size_t                  hwi_count,
469                     size_t                  wti_count,
470                     size_t                  irq_count,
471                     size_t                  cfg_count )
472           : caba::BaseModule(name),
473           m_seglist(mt.getSegmentList(index)),
474           m_vci_fsm(p_vci, m_seglist),
475           m_pti_count(pti_count),
476           m_hwi_count(hwi_count),
477           m_wti_count(wti_count),
478           m_irq_count(irq_count),
479           m_cfg_count(cfg_count),
480           r_msk_pti(new uint32_t[irq_count]),
481           r_msk_wti(new uint32_t[irq_count]),
482           r_msk_hwi(new uint32_t[irq_count]),
483           r_pti_pending(0),
484           r_wti_pending(0),
485           r_hwi_pending(0),
486           r_pti_per(new uint32_t[pti_count]),
487           r_pti_val(new uint32_t[pti_count]),
488           r_wti_reg(new uint32_t[wti_count]),
489           m_clock_cycles(0),
490           p_clk("clk"),
491           p_resetn("resetn"),
492           p_vci("vci"),
493           p_irq(soclib::common::alloc_elems<sc_core::sc_out<bool> >("irq", irq_count)),
494           p_hwi(soclib::common::alloc_elems<sc_core::sc_in<bool> >("hwi", hwi_count))
495{
496    std::cout << "  - Building VciXicu : " << name << std::endl;
497
498    std::list<soclib::common::Segment>::iterator seg;
499    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
500    {
501        std::cout << "    => segment " << seg->name()
502                  << " / base = " << std::hex << seg->baseAddress()
503                  << " / size = " << seg->size() << std::endl;
504    }
505
506    if ( cfg_count > 0 )
507    {
508        r_cfg_reg = new uint32_t[cfg_count];
509        p_cfg = soclib::common::alloc_elems<sc_core::sc_out<uint32_t> >("cfg", cfg_count);
510    }
511
512    m_vci_fsm.on_read_write( on_read, on_write );
513
514    SC_METHOD(transition);
515    dont_initialize();
516    sensitive << p_clk.pos();
517
518    SC_METHOD(genMoore);
519    dont_initialize();
520    sensitive << p_clk.neg();
521}
522
523//////////////////////
524tmpl(/**/)::~VciXicu()
525{
526    delete [] r_msk_pti;
527    delete [] r_msk_wti;
528    delete [] r_msk_hwi;
529    delete [] r_pti_per;
530    delete [] r_pti_val;
531    delete [] r_wti_reg;
532    soclib::common::dealloc_elems(p_irq, m_irq_count);
533    soclib::common::dealloc_elems(p_hwi, m_hwi_count);
534    if ( m_cfg_count > 0 )
535    {
536        delete [] r_cfg_reg;
537        soclib::common::dealloc_elems(p_cfg, m_cfg_count);
538    }
539}
540
541}}
542
543// Local Variables:
544// tab-width: 4
545// c-basic-offset: 4
546// c-file-offsets:((innamespace . 0)(inline-open . 0))
547// indent-tabs-mode: nil
548// End:
549
550// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
551
Note: See TracBrowser for help on using the repository browser.