source: branches/wt_ideal/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 920

Last change on this file since 920 was 920, checked in by meunier, 9 years ago
  • Adding branch wt_ideal -- "ideal" write-through
File size: 216.9 KB
Line 
1/* -*- c++ -*-
2 *
3 * File       : vci_mem_cache.cpp
4 * Date       : 30/10/2008
5 * Copyright  : UPMC / LIP6
6 * Authors    : Alain Greiner / Eric Guthmuller / Quentin Meunier
7 *
8 * SOCLIB_LGPL_HEADER_BEGIN
9 *
10 * This file is part of SoCLib, GNU LGPLv2.1.
11 *
12 * SoCLib is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published
14 * by the Free Software Foundation; version 2.1 of the License.
15 *
16 * SoCLib is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with SoCLib; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * 02110-1301 USA
25 *
26 * SOCLIB_LGPL_HEADER_END
27 *
28 * Maintainers: alain.greiner@lip6.fr
29 *              cesar.fuguet-tortolero@lip6.fr
30 *              quentin.meunier@lip6.fr
31 */
32
33
34#include "../include/vci_mem_cache.h"
35#include "mem_cache.h"
36
37//////   debug services   /////////////////////////////////////////////////////////////
38// All debug messages are conditionned by two variables:
39// - compile time   : DEBUG_MEMC_*** : defined below
40// - execution time : m_debug  = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
41///////////////////////////////////////////////////////////////////////////////////////
42
43#define DEBUG_MEMC_GLOBAL    0 // synthetic trace of all FSMs
44#define DEBUG_MEMC_CONFIG    1 // detailed trace of CONFIG FSM
45#define DEBUG_MEMC_READ      1 // detailed trace of READ FSM
46#define DEBUG_MEMC_WRITE     1 // detailed trace of WRITE FSM
47#define DEBUG_MEMC_CAS       1 // detailed trace of CAS FSM
48#define DEBUG_MEMC_IXR_CMD   1 // detailed trace of IXR_CMD FSM
49#define DEBUG_MEMC_IXR_RSP   1 // detailed trace of IXR_RSP FSM
50#define DEBUG_MEMC_XRAM_RSP  1 // detailed trace of XRAM_RSP FSM
51#define DEBUG_MEMC_CC_SEND   1 // detailed trace of CC_SEND FSM
52#define DEBUG_MEMC_MULTI_ACK 1 // detailed trace of MULTI_ACK FSM
53#define DEBUG_MEMC_TGT_CMD   1 // detailed trace of TGT_CMD FSM
54#define DEBUG_MEMC_TGT_RSP   1 // detailed trace of TGT_RSP FSM
55#define DEBUG_MEMC_CLEANUP   1 // detailed trace of CLEANUP FSM
56
57#define RANDOMIZE_CAS        1
58
59namespace soclib { namespace caba {
60
61    const char *tgt_cmd_fsm_str[] =
62    {
63        "TGT_CMD_IDLE",
64        "TGT_CMD_READ",
65        "TGT_CMD_WRITE",
66        "TGT_CMD_CAS",
67        "TGT_CMD_CONFIG",
68        "TGT_CMD_ERROR"
69    };
70    const char *tgt_rsp_fsm_str[] =
71    {
72        "TGT_RSP_READ_IDLE",
73        "TGT_RSP_WRITE_IDLE",
74        "TGT_RSP_CAS_IDLE",
75        "TGT_RSP_XRAM_IDLE",
76        "TGT_RSP_MULTI_ACK_IDLE",
77        "TGT_RSP_CLEANUP_IDLE",
78        "TGT_RSP_TGT_CMD_IDLE",
79        "TGT_RSP_CONFIG_IDLE",
80        "TGT_RSP_READ",
81        "TGT_RSP_WRITE",
82        "TGT_RSP_CAS",
83        "TGT_RSP_XRAM",
84        "TGT_RSP_TGT_CMD",
85        "TGT_RSP_CONFIG"
86    };
87    const char *config_fsm_str[] =
88    {
89        "CONFIG_IDLE",
90        "CONFIG_LOOP",
91        "CONFIG_WAIT",
92        "CONFIG_RSP",
93        "CONFIG_DIR_REQ",
94        "CONFIG_DIR_ACCESS",
95        "CONFIG_TRT_LOCK",
96        "CONFIG_TRT_SET",
97        "CONFIG_PUT_REQ"
98    };
99    const char *read_fsm_str[] =
100    {
101        "READ_IDLE",
102        "READ_DIR_REQ",
103        "READ_DIR_LOCK",
104        "READ_DIR_HIT",
105        "READ_RSP",
106        "READ_TRT_LOCK",
107        "READ_TRT_SET",
108        "READ_TRT_REQ"
109    };
110    const char *write_fsm_str[] =
111    {
112        "WRITE_IDLE",
113        "WRITE_NEXT",
114        "WRITE_DIR_REQ",
115        "WRITE_DIR_LOCK",
116        "WRITE_DIR_HIT",
117        "WRITE_RSP",
118        "WRITE_MISS_TRT_LOCK",
119        "WRITE_MISS_TRT_DATA",
120        "WRITE_MISS_TRT_SET",
121        "WRITE_MISS_XRAM_REQ",
122        "WRITE_WAIT"
123    };
124    const char *ixr_rsp_fsm_str[] =
125    {
126        "IXR_RSP_IDLE",
127        "IXR_RSP_TRT_ERASE",
128        "IXR_RSP_TRT_READ"
129    };
130    const char *xram_rsp_fsm_str[] =
131    {
132        "XRAM_RSP_IDLE",
133        "XRAM_RSP_TRT_COPY",
134        "XRAM_RSP_TRT_DIRTY",
135        "XRAM_RSP_DIR_LOCK",
136        "XRAM_RSP_DIR_UPDT",
137        "XRAM_RSP_DIR_RSP",
138        "XRAM_RSP_WRITE_DIRTY",
139        "XRAM_RSP_ERROR_ERASE",
140        "XRAM_RSP_ERROR_RSP"
141    };
142    const char *ixr_cmd_fsm_str[] =
143    {
144        "IXR_CMD_READ_IDLE",
145        "IXR_CMD_WRITE_IDLE",
146        "IXR_CMD_CAS_IDLE",
147        "IXR_CMD_XRAM_IDLE",
148        "IXR_CMD_CONFIG_IDLE",
149        "IXR_CMD_READ_TRT",
150        "IXR_CMD_WRITE_TRT",
151        "IXR_CMD_CAS_TRT",
152        "IXR_CMD_XRAM_TRT",
153        "IXR_CMD_CONFIG_TRT",
154        "IXR_CMD_READ_SEND",
155        "IXR_CMD_WRITE_SEND",
156        "IXR_CMD_CAS_SEND",
157        "IXR_CMD_XRAM_SEND",
158        "IXR_CMD_CONFIG_SEND"
159    };
160    const char *cas_fsm_str[] =
161    {
162        "CAS_IDLE",
163        "CAS_DIR_REQ",
164        "CAS_DIR_LOCK",
165        "CAS_DIR_HIT_READ",
166        "CAS_DIR_HIT_COMPARE",
167        "CAS_DIR_HIT_WRITE",
168        "CAS_RSP_FAIL",
169        "CAS_RSP_SUCCESS",
170        "CAS_MISS_TRT_LOCK",
171        "CAS_MISS_TRT_SET",
172        "CAS_MISS_XRAM_REQ",
173        "CAS_WAIT"
174    };
175    const char *alloc_dir_fsm_str[] =
176    {
177        "ALLOC_DIR_RESET",
178        "ALLOC_DIR_READ",
179        "ALLOC_DIR_WRITE",
180        "ALLOC_DIR_CAS",
181        "ALLOC_DIR_XRAM_RSP",
182        "ALLOC_DIR_CONFIG"
183    };
184    const char *alloc_trt_fsm_str[] =
185    {
186        "ALLOC_TRT_READ",
187        "ALLOC_TRT_WRITE",
188        "ALLOC_TRT_CAS",
189        "ALLOC_TRT_XRAM_RSP",
190        "ALLOC_TRT_IXR_RSP",
191        "ALLOC_TRT_IXR_CMD",
192        "ALLOC_TRT_CONFIG"
193    };
194
195#define tmpl(x) \
196    template<typename vci_param_int, \
197    typename vci_param_ext, \
198    size_t memc_dspin_in_width,  \
199    size_t memc_dspin_out_width> x \
200    VciMemCache<vci_param_int, vci_param_ext, memc_dspin_in_width, memc_dspin_out_width>
201
202    using namespace soclib::common;
203
204    ////////////////////////////////
205    //  Constructor
206    ////////////////////////////////
207
208    tmpl(/**/)::VciMemCache(
209            sc_module_name name,
210            const MappingTable &mtp, // mapping table for direct network
211            const MappingTable &mtx, // mapping table for external network
212            const IntTab &srcid_x,   // global index on external network
213            const IntTab &tgtid_d,   // global index on direct network
214            const size_t x_width,    // number of x bits in platform
215            const size_t y_width,    // number of x bits in platform
216            const size_t nways,      // number of ways per set
217            const size_t nsets,      // number of associative sets
218            const size_t nwords,     // number of words in cache line
219            const size_t max_copies, // max number of copies in heap
220            const size_t heap_size,  // number of heap entries
221            const size_t trt_lines,  // number of TRT entries
222            const size_t upt_lines,  // number of UPT entries
223            const size_t ivt_lines,  // number of IVT entries
224            const size_t debug_start_cycle,
225            const bool   debug_ok)
226
227        : soclib::caba::BaseModule(name),
228
229        p_clk("p_clk"),
230        p_resetn("p_resetn"),
231        p_irq ("p_irq"),
232        p_vci_tgt("p_vci_tgt"),
233        p_vci_ixr("p_vci_ixr"),
234        p_dspin_p2m("p_dspin_p2m"),
235        p_dspin_m2p("p_dspin_m2p"),
236        p_dspin_clack("p_dspin_clack"),
237
238        m_seglist(mtp.getSegmentList(tgtid_d)),
239        m_nseg(0),
240        m_srcid_x(mtx.indexForId(srcid_x)),
241        m_initiators(1 << vci_param_int::S),
242        m_ways(nways),
243        m_sets(nsets),
244        m_words(nwords),
245        m_x_width(x_width),
246        m_y_width(y_width),
247        m_debug_start_cycle(debug_start_cycle),
248        m_debug_ok(debug_ok),
249        m_trt_lines(trt_lines),
250        m_trt(this->name(), trt_lines, nwords),
251        m_cache_directory(nways, nsets, nwords, vci_param_int::N),
252        m_cache_data(nways, nsets, nwords),
253        m_llsc_table(),
254
255#define L2 soclib::common::uint32_log2
256        m_x(L2(m_words), 2),
257        m_y(L2(m_sets), L2(m_words) + 2),
258        m_z(vci_param_int::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
259        m_nline(vci_param_int::N - L2(m_words) - 2, L2(m_words) + 2),
260#undef L2
261
262        // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits)
263        //   0b00000    /   0b11111    /   0b00000    /   0b11111
264        m_broadcast_boundaries(0x7C1F),
265
266        // CONFIG interface
267        m_config_addr_mask((1 << 12) - 1),
268
269        m_config_regr_width(7),
270        m_config_func_width(3),
271        m_config_regr_idx_mask((1 << m_config_regr_width) - 1),
272        m_config_func_idx_mask((1 << m_config_func_width) - 1),
273
274        //  FIFOs
275        m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
276        m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
277        m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
278        m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
279        m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
280
281        m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
282        m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
283        m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
284        m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
285        m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
286        m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
287        m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
288
289        m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4),
290        m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4),
291        m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4),
292        m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4),
293        m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4),
294        m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4),
295
296        r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
297
298        r_config_fsm("r_config_fsm"),
299
300        r_read_fsm("r_read_fsm"),
301
302        r_write_fsm("r_write_fsm"),
303
304        r_cas_fsm("r_cas_fsm"),
305
306        r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
307        r_xram_rsp_fsm("r_xram_rsp_fsm"),
308
309        r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
310
311        r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
312
313        r_alloc_dir_fsm("r_alloc_dir_fsm"),
314        r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"),
315        r_alloc_trt_fsm("r_alloc_trt_fsm")
316#if MONITOR_MEMCACHE_FSM == 1
317        ,
318        p_read_fsm("p_read_fsm"),
319        p_write_fsm("p_write_fsm"),
320        p_xram_rsp_fsm("p_xram_rsp_fsm"),
321        p_cas_fsm("p_cas_fsm"),
322        p_config_fsm("p_config_fsm"),
323        p_alloc_dir_fsm("p_alloc_dir_fsm"),
324        p_alloc_trt_fsm("p_alloc_trt_fsm"),
325        p_tgt_cmd_fsm("p_tgt_cmd_fsm"),
326        p_tgt_rsp_fsm("p_tgt_rsp_fsm"),
327        p_ixr_cmd_fsm("p_ixr_cmd_fsm"),
328        p_ixr_rsp_fsm("p_ixr_rsp_fsm"),
329        p_multi_ack_fsm("p_multi_ack_fsm"),
330
331        m_cc_vcaches()
332#endif
333    {
334        std::cout << "  - Building VciMemCache : " << name << std::endl;
335
336        assert(IS_POW_OF_2(nsets));
337        assert(IS_POW_OF_2(nwords));
338        assert(IS_POW_OF_2(nways));
339        assert(nsets);
340        assert(nwords);
341        assert(nways);
342
343        // check Transaction table size
344        assert((uint32_log2(trt_lines) <= vci_param_ext::T) and
345                "MEMC ERROR : Need more bits for VCI TRDID field");
346
347        // check internal and external data width
348        assert((vci_param_int::B == 4) and
349                "MEMC ERROR : VCI internal data width must be 32 bits");
350
351        assert((vci_param_ext::B == 8) and
352                "MEMC ERROR : VCI external data width must be 64 bits");
353
354        // Check coherence between internal & external addresses
355        assert((vci_param_int::N == vci_param_ext::N) and
356                "MEMC ERROR : VCI internal & external addresses must have the same width");
357
358        // Get the segments associated to the MemCache
359        std::list<soclib::common::Segment>::iterator seg;
360        size_t i = 0;
361
362        for (seg = m_seglist.begin(); seg != m_seglist.end(); seg++)
363        {
364            std::cout << "    => segment " << seg->name()
365                << " / base = " << std::hex << seg->baseAddress()
366                << " / size = " << seg->size() << std::endl;
367            m_nseg++;
368        }
369
370        assert((m_nseg > 0) and
371                "MEMC ERROR : At least one segment must be mapped to this component");
372
373        m_seg = new soclib::common::Segment*[m_nseg];
374
375        for (seg = m_seglist.begin(); seg != m_seglist.end(); seg++)
376        {
377            if (seg->special()) m_seg_config = i;
378            m_seg[i] = & (*seg);
379            i++;
380        }
381
382        addr_t gid = m_seg[0]->baseAddress() >> (vci_param_int::N - x_width - y_width);
383        m_x_self = (gid >> m_y_width) & ((1 << m_x_width) - 1);
384        m_y_self =  gid               & ((1 << m_y_width) - 1);
385
386        // Allocation for IXR_RSP FSM
387        r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
388
389        // Allocation for XRAM_RSP FSM
390        r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
391        r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
392
393        // Allocation for READ FSM
394        r_read_data                = new sc_signal<data_t>[nwords];
395        r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
396
397        // Allocation for WRITE FSM
398        r_write_data               = new sc_signal<data_t>[nwords];
399        r_write_be                 = new sc_signal<be_t>[nwords];
400
401        // Allocation for CAS FSM
402        r_cas_data                 = new sc_signal<data_t>[nwords];
403        r_cas_rdata                = new sc_signal<data_t>[2];
404
405        // Allocation for IXR_CMD FSM
406        r_ixr_cmd_wdata            = new sc_signal<data_t>[nwords];
407
408        // Allocation for debug
409        m_debug_previous_data      = new data_t[nwords];
410        m_debug_data               = new data_t[nwords];
411
412        SC_METHOD(transition);
413        dont_initialize();
414        sensitive << p_clk.pos();
415
416        SC_METHOD(genMoore);
417        dont_initialize();
418        sensitive << p_clk.neg();
419    } // end constructor
420
421
422    ////////////////////////////////////////////////////////////////////////////
423    tmpl(void)::set_vcache_list(std::list<L1Cache *> l1_caches)
424    ////////////////////////////////////////////////////////////////////////////
425    {
426        // Copying pointers to L1 caches into m_cc_vcaches list
427        for (typename std::list<L1Cache *>::iterator it = l1_caches.begin(); it != l1_caches.end(); it++) {
428            m_cc_vcaches.push_back(*it);
429        }
430    }
431
432
433    ///////////////////////////////////////////////////////////////////////////
434    tmpl(void)::cc_vcaches_direct_update(
435            addr_t addr,
436            uint32_t data,
437            uint32_t be,
438            int32_t srcid)
439    ///////////////////////////////////////////////////////////////////////////
440    {
441        for (typename std::list<L1Cache *>::iterator it = m_cc_vcaches.begin();
442                it != m_cc_vcaches.end(); it++)
443        {
444            (*it)->cache_direct_update(addr, data, be, srcid);
445        }
446    }
447
448
449
450    ///////////////////////////////////////////////////////////////////////////
451    tmpl(void)::cc_vcaches_direct_update(
452            addr_t addr,
453            sc_signal<uint32_t> * data,
454            sc_signal<uint32_t> * be,
455            int32_t srcid)
456    ///////////////////////////////////////////////////////////////////////////
457    {
458        addr_t mask = ~((m_words << 2) - 1);
459        addr_t base_addr = addr & mask;
460        for (size_t word = 0; word < m_words; word++)
461        {
462            if (be[word] != 0)
463            {
464                for (typename std::list<L1Cache *>::iterator it = m_cc_vcaches.begin();
465                        it != m_cc_vcaches.end(); it++)
466                {
467                    (*it)->cache_direct_update(base_addr + word * 4, data[word].read(), be[word].read(), srcid);
468                }
469            }
470        }
471    }
472
473
474    //////////////////////////////////////////////////////////
475    tmpl(void)::cache_monitor(addr_t addr, bool single_word)
476    //////////////////////////////////////////////////////////
477    {
478        size_t way  = 0;
479        size_t set  = 0;
480        size_t word = ((size_t) addr & 0x3F) >> 2;
481
482        DirectoryEntry entry = m_cache_directory.read_neutral(addr, &way, &set);
483
484        // read data and compute data_change
485        bool data_change = false;
486        if (entry.valid)
487        {
488            if (single_word)
489            {
490                m_debug_data[word] = m_cache_data.read(way, set, word);
491                if (m_debug_previous_valid and
492                     (m_debug_data[word] != m_debug_previous_data[word]))
493                {
494                    data_change = true;
495                }
496            }
497            else
498            {
499                for (size_t wcur = 0; wcur < m_words; wcur++)
500                {
501                    m_debug_data[wcur] = m_cache_data.read(way, set, wcur);
502                    if (m_debug_previous_valid and
503                         (m_debug_data[wcur] != m_debug_previous_data[wcur]))
504                    {
505                        data_change = true;
506                    }
507                }
508            }
509        }
510
511        // print values if any change
512        if ((entry.valid != m_debug_previous_valid) or
513            (entry.valid and (entry.count != m_debug_previous_count)) or
514            (entry.valid and (entry.dirty != m_debug_previous_dirty)) or data_change)
515        {
516            std::cout << "Monitor MEMC " << name()
517                      << " at cycle " << std::dec << m_cpt_cycles
518                      << " for address " << std::hex << addr
519                      << " / VAL = " << std::dec << entry.valid
520                      << " / WAY = " << way
521                      << " / COUNT = " << entry.count
522                      << " / DIRTY = " << entry.dirty
523                      << " / DATA_CHANGE = " << data_change;
524            if (single_word)
525            {
526                 std::cout << std::hex << " / value = " << m_debug_data[word] << std::endl;
527            }
528            else
529            {
530                std::cout << std::hex << std::endl
531                          << "/0:" << m_debug_data[0]
532                          << "/1:" << m_debug_data[1]
533                          << "/2:" << m_debug_data[2]
534                          << "/3:" << m_debug_data[3]
535                          << "/4:" << m_debug_data[4]
536                          << "/5:" << m_debug_data[5]
537                          << "/6:" << m_debug_data[6]
538                          << "/7:" << m_debug_data[7]
539                          << "/8:" << m_debug_data[8]
540                          << "/9:" << m_debug_data[9]
541                          << "/A:" << m_debug_data[10]
542                          << "/B:" << m_debug_data[11]
543                          << "/C:" << m_debug_data[12]
544                          << "/D:" << m_debug_data[13]
545                          << "/E:" << m_debug_data[14]
546                          << "/F:" << m_debug_data[15]
547                          << std::endl;
548            }
549        }
550
551        // register values
552        m_debug_previous_count = entry.count;
553        m_debug_previous_valid = entry.valid;
554        m_debug_previous_dirty = entry.dirty;
555        for (size_t wcur = 0; wcur < m_words; wcur++)
556        {
557            m_debug_previous_data[wcur] = m_debug_data[wcur];
558        }
559    }
560
561
562    /////////////////////////////////////////////////////
563    tmpl(uint32_t)::req_distance(uint32_t req_srcid)
564    /////////////////////////////////////////////////////
565    {
566        const uint32_t srcid_width = vci_param_int::S;
567
568        uint8_t req_x = (req_srcid >> (srcid_width - m_x_width));
569        uint8_t req_y = (req_srcid >> (srcid_width - m_x_width - m_y_width)) & ((1 << m_y_width) - 1);
570
571        return abs(m_x_self - req_x) + abs(m_y_self - req_y) + 1;
572    }
573
574
575    /////////////////////////////////////////////////////
576    tmpl(bool)::is_local_req(uint32_t req_srcid)
577    /////////////////////////////////////////////////////
578    {
579        return req_distance(req_srcid) == 1;
580    }
581
582    /////////////////////////////////////////////////////
583    tmpl(int)::read_instrumentation(uint32_t regr, uint32_t & rdata)
584    /////////////////////////////////////////////////////
585    {
586        int error = 0;
587
588        switch (regr)
589        {
590            ///////////////////////////////////////////////////////
591            //       DIRECT instrumentation registers            //
592            // Registers of 32 bits and therefore only LO is     //
593            // implemented.                                      //
594            //                                                   //
595            // The HI may be used in future implementations      //
596            ///////////////////////////////////////////////////////
597
598            // LOCAL
599
600            case MEMC_LOCAL_READ_LO   : rdata = m_cpt_read_local        ; break;
601            case MEMC_LOCAL_WRITE_LO  : rdata = m_cpt_write_flits_local ; break;
602            case MEMC_LOCAL_LL_LO     : rdata = m_cpt_ll_local          ; break;
603            case MEMC_LOCAL_SC_LO     : rdata = m_cpt_sc_local          ; break;
604            case MEMC_LOCAL_CAS_LO    : rdata = m_cpt_cas_local         ; break;
605            case MEMC_LOCAL_READ_HI   :
606            case MEMC_LOCAL_WRITE_HI  :
607            case MEMC_LOCAL_LL_HI     :
608            case MEMC_LOCAL_SC_HI     :
609            case MEMC_LOCAL_CAS_HI    : rdata = 0; break;
610
611            // REMOTE
612
613            case MEMC_REMOTE_READ_LO  : rdata = m_cpt_read_remote        ; break;
614            case MEMC_REMOTE_WRITE_LO : rdata = m_cpt_write_flits_remote ; break;
615            case MEMC_REMOTE_LL_LO    : rdata = m_cpt_ll_remote          ; break;
616            case MEMC_REMOTE_SC_LO    : rdata = m_cpt_sc_remote          ; break;
617            case MEMC_REMOTE_CAS_LO   : rdata = m_cpt_cas_remote         ; break;
618            case MEMC_REMOTE_READ_HI  :
619            case MEMC_REMOTE_WRITE_HI :
620            case MEMC_REMOTE_LL_HI    :
621            case MEMC_REMOTE_SC_HI    :
622            case MEMC_REMOTE_CAS_HI   : rdata = 0; break;
623
624            // COST
625
626            case MEMC_COST_READ_LO    : rdata = m_cpt_read_cost ; break;
627            case MEMC_COST_WRITE_LO   : rdata = m_cpt_write_cost; break;
628            case MEMC_COST_LL_LO      : rdata = m_cpt_ll_cost   ; break;
629            case MEMC_COST_SC_LO      : rdata = m_cpt_sc_cost   ; break;
630            case MEMC_COST_CAS_LO     : rdata = m_cpt_cas_cost  ; break;
631            case MEMC_COST_READ_HI    :
632            case MEMC_COST_WRITE_HI   :
633            case MEMC_COST_LL_HI      :
634            case MEMC_COST_SC_HI      :
635            case MEMC_COST_CAS_HI     : rdata = 0; break;
636
637            ///////////////////////////////////////////////////////
638            //       COHERENCE instrumentation registers         //
639            // Registers of 32 bits and therefore only LO is     //
640            // implemented.                                      //
641            //                                                   //
642            // The HI may be used in future implementations      //
643            ///////////////////////////////////////////////////////
644
645            // LOCAL
646
647            case MEMC_LOCAL_MUPDATE_LO  : rdata = m_cpt_update_local; break;
648            case MEMC_LOCAL_MINVAL_LO   : rdata = 0; break;
649            case MEMC_LOCAL_CLEANUP_LO  : rdata = 0; break;
650            case MEMC_LOCAL_MUPDATE_HI  :
651            case MEMC_LOCAL_MINVAL_HI   :
652            case MEMC_LOCAL_CLEANUP_HI  : rdata = 0; break;
653
654            // REMOTE
655
656            case MEMC_REMOTE_MUPDATE_LO : rdata = m_cpt_update_remote; break;
657            case MEMC_REMOTE_MINVAL_LO  : rdata = 0; break;
658            case MEMC_REMOTE_CLEANUP_LO : rdata = 0; break;
659            case MEMC_REMOTE_MUPDATE_HI :
660            case MEMC_REMOTE_MINVAL_HI  :
661            case MEMC_REMOTE_CLEANUP_HI : rdata = 0; break;
662
663            // COST
664
665            case MEMC_COST_MUPDATE_LO   : rdata = m_cpt_update_cost; break;
666            case MEMC_COST_MINVAL_LO    : rdata = 0; break;
667            case MEMC_COST_CLEANUP_LO   : rdata = 0; break;
668            case MEMC_COST_MUPDATE_HI   :
669            case MEMC_COST_MINVAL_HI    :
670            case MEMC_COST_CLEANUP_HI   : rdata = 0; break;
671
672            // TOTAL
673
674            case MEMC_TOTAL_MUPDATE_LO  : rdata = m_cpt_update; break;
675            case MEMC_TOTAL_MINVAL_LO   : rdata = 0; break;
676            case MEMC_TOTAL_BINVAL_LO   : rdata = m_cpt_binval; break;
677            case MEMC_TOTAL_MUPDATE_HI  :
678            case MEMC_TOTAL_MINVAL_HI   :
679            case MEMC_TOTAL_BINVAL_HI   : rdata = 0; break;
680
681            // unknown register
682
683            default                     : error = 1;
684        }
685
686        return error;
687    }
688
689    //////////////////////////////////////////////////
690    tmpl(void)::print_trace(size_t detailed)
691    //////////////////////////////////////////////////
692    {
693        std::cout << "MEMC " << name() << std::endl;
694        std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]
695            << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]
696            << " | " << read_fsm_str[r_read_fsm.read()]
697            << " | " << write_fsm_str[r_write_fsm.read()]
698            << " | " << cas_fsm_str[r_cas_fsm.read()]
699            << " | " << config_fsm_str[r_config_fsm.read()]
700            << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]
701            << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]
702            << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm.read()] << std::endl;
703        std::cout << "  "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]
704            << " | " << alloc_trt_fsm_str[r_alloc_trt_fsm.read()] << std::endl;
705
706        if (detailed) m_trt.print(0);
707    }
708
709
710    /////////////////////////////////////////
711    tmpl(void)::reset_counters()
712    /////////////////////////////////////////
713    {
714        m_cpt_reset_count        = m_cpt_cycles;
715
716        m_cpt_read_local         = 0;
717        m_cpt_read_remote        = 0;
718        m_cpt_read_cost          = 0;
719
720        m_cpt_write_local        = 0;
721        m_cpt_write_remote       = 0;
722        m_cpt_write_flits_local  = 0;
723        m_cpt_write_flits_remote = 0;
724        m_cpt_write_cost         = 0;
725
726        m_cpt_ll_local           = 0;
727        m_cpt_ll_remote          = 0;
728        m_cpt_ll_cost            = 0;
729
730        m_cpt_sc_local           = 0;
731        m_cpt_sc_remote          = 0;
732        m_cpt_sc_cost            = 0;
733
734        m_cpt_cas_local          = 0;
735        m_cpt_cas_remote         = 0;
736        m_cpt_cas_cost           = 0;
737
738        m_cpt_update             = 0;
739        m_cpt_update_local       = 0;
740        m_cpt_update_remote      = 0;
741        m_cpt_update_cost        = 0;
742
743        m_cpt_binval             = 0;
744        m_cpt_write_broadcast    = 0;
745
746        m_cpt_read_miss          = 0;
747        m_cpt_write_miss         = 0;
748        m_cpt_write_dirty        = 0;
749
750        m_cpt_trt_rb             = 0;
751        m_cpt_trt_full           = 0;
752        m_cpt_get                = 0;
753        m_cpt_put                = 0;
754    }
755
756    /////////////////////////////////////////
757    tmpl(void)::print_stats(bool activity_counters, bool stats)
758    /////////////////////////////////////////
759    {
760        std::cout << "**********************************" << std::dec << std::endl;
761        std::cout << "*** MEM_CACHE " << name() << std::endl;
762        std::cout << "**********************************" << std::dec << std::endl;
763        if (activity_counters)
764        {
765            std::cout << "----------------------------------" << std::dec << std::endl;
766            std::cout << "---     Activity Counters      ---" << std::dec << std::endl;
767            std::cout << "----------------------------------" << std::dec << std::endl;
768            std::cout
769                << "[000] COUNTERS RESET AT CYCLE   = " << m_cpt_reset_count << std::endl
770                << "[001] NUMBER OF CYCLES          = " << m_cpt_cycles << std::endl
771                << std::endl
772                << "[010] LOCAL READ                = " << m_cpt_read_local << std::endl
773                << "[011] REMOTE READ               = " << m_cpt_read_remote << std::endl
774                << "[012] READ COST (FLITS * DIST)  = " << m_cpt_read_cost << std::endl
775                << std::endl
776                << "[020] LOCAL WRITE               = " << m_cpt_write_local << std::endl
777                << "[021] REMOTE WRITE              = " << m_cpt_write_remote << std::endl
778                << "[022] WRITE FLITS LOCAL         = " << m_cpt_write_flits_local << std::endl
779                << "[023] WRITE FLITS REMOTE        = " << m_cpt_write_flits_remote << std::endl
780                << "[024] WRITE COST (FLITS * DIST) = " << m_cpt_write_cost << std::endl
781                << "[025] WRITE L1 MISS NCC         = " << "0" << std::endl
782                << std::endl
783                << "[030] LOCAL LL                  = " << m_cpt_ll_local << std::endl
784                << "[031] REMOTE LL                 = " << m_cpt_ll_remote << std::endl
785                << "[032] LL COST (FLITS * DIST)    = " << m_cpt_ll_cost << std::endl
786                << std::endl
787                << "[040] LOCAL SC                  = " << m_cpt_sc_local << std::endl
788                << "[041] REMOTE SC                 = " << m_cpt_sc_remote << std::endl
789                << "[042] SC COST (FLITS * DIST)    = " << m_cpt_sc_cost << std::endl
790                << std::endl
791                << "[050] LOCAL CAS                 = " << m_cpt_cas_local << std::endl
792                << "[051] REMOTE CAS                = " << m_cpt_cas_remote << std::endl
793                << "[052] CAS COST (FLITS * DIST)   = " << m_cpt_cas_cost << std::endl
794                << std::endl
795                /* m_cpt_update_* should always be 0 */
796                << "[060] REQUESTS TRIG. UPDATE     = " << m_cpt_update << std::endl
797                << "[061] LOCAL UPDATE              = " << m_cpt_update_local << std::endl
798                << "[062] REMOTE UPDATE             = " << m_cpt_update_remote << std::endl
799                << "[063] UPDT COST (FLITS * DIST)  = " << m_cpt_update_cost << std::endl
800                << std::endl
801                << "[070] REQUESTS TRIG. M_INV      = " << "0" << std::endl
802                << "[071] LOCAL M_INV               = " << "0" << std::endl
803                << "[072] REMOTE M_INV              = " << "0" << std::endl
804                << "[073] M_INV COST (FLITS * DIST) = " << "0" << std::endl
805                << std::endl
806                << "[080] BROADCAT INVAL            = " << m_cpt_binval << std::endl
807                << "[081] WRITE BROADCAST           = " << m_cpt_write_broadcast << std::endl
808                << "[082] GETM BROADCAST            = " << "0" << std::endl
809                << std::endl
810                << "[090] LOCAL CLEANUP             = " << "0" << std::endl
811                << "[091] REMOTE CLEANUP            = " << "0" << std::endl
812                << "[092] CLNUP COST (FLITS * DIST) = " << "0" << std::endl
813                << "[093] LOCAL CLEANUP DATA        = " << "0" << std::endl
814                << "[094] REMOTE CLEANUP DATA       = " << "0" << std::endl
815                << "[095] CLEANUP DATA COST         = " << "0" << std::endl
816                << std::endl
817                << "[100] READ MISS                 = " << m_cpt_read_miss << std::endl
818                << "[101] WRITE MISS                = " << m_cpt_write_miss << std::endl
819                << "[102] WRITE DIRTY               = " << m_cpt_write_dirty << std::endl
820                << "[103] GETM MISS                 = " << "0" << std::endl
821                << std::endl
822                << "[110] RD BLOCKED BY HIT IN TRT  = " << m_cpt_trt_rb << std::endl
823                << "[111] TRANS BLOCKED BY FULL TRT = " << m_cpt_trt_full << std::endl
824                << "[120] PUT (UNIMPLEMENTED)       = " << m_cpt_put << std::endl
825                << "[121] GET (UNIMPLEMENTED)       = " << m_cpt_get << std::endl
826                << "[130] MIN HEAP SLOT AV. (UNIMP) = " << "0" << std::endl
827                << std::endl
828                << "[140] NCC TO CC (READ)          = " << "0" << std::endl
829                << "[141] NCC TO CC (WRITE)         = " << "0" << std::endl
830                << std::endl
831                << "[150] LOCAL GETM                = " << "0" << std::endl
832                << "[151] REMOTE GETM               = " << "0" << std::endl
833                << "[152] GETM COST (FLITS * DIST)  = " << "0" << std::endl
834                << std::endl
835                << "[160] LOCAL INVAL RO            = " << "0" << std::endl
836                << "[161] REMOTE INVAL RO           = " << "0" << std::endl
837                << "[162] INVAL RO COST             = " << "0" << std::endl
838                << std::endl;
839        }
840        // No more computed stats
841    }
842
843
844    /////////////////////////////////
845    tmpl(/**/)::~VciMemCache()
846    /////////////////////////////////
847    {
848        delete [] m_seg;
849
850        delete [] r_ixr_rsp_to_xram_rsp_rok;
851        delete [] r_xram_rsp_victim_data;
852        delete [] r_xram_rsp_to_tgt_rsp_data;
853
854        delete [] r_read_data;
855        delete [] r_read_to_tgt_rsp_data;
856
857        delete [] r_write_data;
858        delete [] r_write_be;
859
860        delete [] r_cas_data;
861        delete [] r_cas_rdata;
862
863        delete [] r_ixr_cmd_wdata;
864        delete [] m_debug_previous_data;
865        delete [] m_debug_data;
866
867        //print_stats();
868    }
869
870    //////////////////////////////////
871    tmpl(void)::transition()
872    //////////////////////////////////
873    {
874        using soclib::common::uint32_log2;
875
876        // RESET
877        if (!p_resetn.read())
878        {
879            // Initializing FSMs
880            r_tgt_cmd_fsm    = TGT_CMD_IDLE;
881            r_config_fsm     = CONFIG_IDLE;
882            r_tgt_rsp_fsm    = TGT_RSP_READ_IDLE;
883            r_read_fsm       = READ_IDLE;
884            r_write_fsm      = WRITE_IDLE;
885            r_cas_fsm        = CAS_IDLE;
886            r_alloc_dir_fsm  = ALLOC_DIR_RESET;
887            r_alloc_trt_fsm  = ALLOC_TRT_READ;
888            r_ixr_rsp_fsm    = IXR_RSP_IDLE;
889            r_xram_rsp_fsm   = XRAM_RSP_IDLE;
890            r_ixr_cmd_fsm    = IXR_CMD_READ_IDLE;
891
892            m_debug                = false;
893            m_debug_previous_valid = false;
894            m_debug_previous_dirty = false;
895            m_debug_previous_count = 0;
896
897            //  Initializing Tables
898            m_trt.init();
899            m_llsc_table.init();
900
901            // initializing FIFOs and communication Buffers
902
903            m_cmd_read_addr_fifo.init();
904            m_cmd_read_length_fifo.init();
905            m_cmd_read_srcid_fifo.init();
906            m_cmd_read_trdid_fifo.init();
907            m_cmd_read_pktid_fifo.init();
908
909            m_cmd_write_addr_fifo.init();
910            m_cmd_write_eop_fifo.init();
911            m_cmd_write_srcid_fifo.init();
912            m_cmd_write_trdid_fifo.init();
913            m_cmd_write_pktid_fifo.init();
914            m_cmd_write_data_fifo.init();
915
916            m_cmd_cas_addr_fifo.init();
917            m_cmd_cas_srcid_fifo.init();
918            m_cmd_cas_trdid_fifo.init();
919            m_cmd_cas_pktid_fifo.init();
920            m_cmd_cas_wdata_fifo.init();
921            m_cmd_cas_eop_fifo.init();
922
923            r_config_cmd  = MEMC_CMD_NOP;
924            r_config_lock = false;
925
926            r_tgt_cmd_to_tgt_rsp_req = false;
927
928            r_read_to_tgt_rsp_req = false;
929            r_read_to_ixr_cmd_req = false;
930
931            r_write_to_tgt_rsp_req   = false;
932            r_write_to_ixr_cmd_req   = false;
933
934            r_cas_to_tgt_rsp_req = false;
935            r_cas_cpt            = 0;
936            r_cas_lfsr           = -1;
937            r_cas_to_ixr_cmd_req = false;
938
939            for (size_t i = 0; i < m_trt_lines ; i++)
940            {
941                r_ixr_rsp_to_xram_rsp_rok[i] = false;
942            }
943
944            r_xram_rsp_to_tgt_rsp_req    = false;
945            r_xram_rsp_to_ixr_cmd_req    = false;
946            r_xram_rsp_trt_index         = 0;
947            r_xram_rsp_rerror_irq        = false;
948            r_xram_rsp_rerror_irq_enable = false;
949
950            r_alloc_dir_reset_cpt  = 0;
951
952            r_tgt_rsp_key_sent  = false;
953
954            // Activity counters
955            m_cpt_cycles             = 0;
956            m_cpt_reset_count        = 0;
957
958            m_cpt_read_local         = 0;
959            m_cpt_read_remote        = 0;
960            m_cpt_read_cost          = 0;
961
962            m_cpt_write_local        = 0;
963            m_cpt_write_remote       = 0;
964            m_cpt_write_flits_local  = 0;
965            m_cpt_write_flits_remote = 0;
966            m_cpt_write_cost         = 0;
967
968            m_cpt_ll_local           = 0;
969            m_cpt_ll_remote          = 0;
970            m_cpt_ll_cost            = 0;
971
972            m_cpt_sc_local           = 0;
973            m_cpt_sc_remote          = 0;
974            m_cpt_sc_cost            = 0;
975
976            m_cpt_cas_local          = 0;
977            m_cpt_cas_remote         = 0;
978            m_cpt_cas_cost           = 0;
979
980            m_cpt_update             = 0;
981            m_cpt_update_local       = 0;
982            m_cpt_update_remote      = 0;
983            m_cpt_update_cost        = 0;
984
985            m_cpt_binval             = 0;
986            m_cpt_write_broadcast    = 0;
987
988            m_cpt_read_miss          = 0;
989            m_cpt_write_miss         = 0;
990            m_cpt_write_dirty        = 0;
991
992            m_cpt_trt_rb             = 0;
993            m_cpt_trt_full           = 0;
994            m_cpt_get                = 0;
995            m_cpt_put                = 0;
996
997            return;
998        }
999
1000        bool cmd_read_fifo_put = false;
1001        bool cmd_read_fifo_get = false;
1002
1003        bool cmd_write_fifo_put = false;
1004        bool cmd_write_fifo_get = false;
1005
1006        bool cmd_cas_fifo_put = false;
1007        bool cmd_cas_fifo_get = false;
1008
1009        bool config_rsp_lines_incr         = false;
1010        bool config_rsp_lines_ixr_rsp_decr = false;
1011
1012        m_debug = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
1013
1014#if DEBUG_MEMC_GLOBAL
1015        if (m_debug)
1016        {
1017            std::cout
1018                << "---------------------------------------------"           << std::dec << std::endl
1019                << "MEM_CACHE "            << name()
1020                << " ; Time = "            << m_cpt_cycles                                << std::endl
1021                << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
1022                << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
1023                << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
1024                << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
1025                << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
1026                << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
1027                << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
1028                << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
1029                << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
1030                << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
1031        }
1032#endif
1033
1034        ////////////////////////////////////////////////////////////////////////////////////
1035        //    TGT_CMD FSM
1036        ////////////////////////////////////////////////////////////////////////////////////
1037        // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors,
1038        // and dispatch these commands to the proper FSM through dedicated FIFOs.
1039        //
1040        // There are 5 types of commands accepted in the XRAM segment:
1041        // - READ   : A READ request has a length of 1 VCI flit. It can be a single word
1042        //            or an entire cache line, depending on the PLEN value => READ FSM
1043        // - WRITE  : A WRITE request has a maximum length of 16 flits, and can only
1044        //            concern words in a same line => WRITE FSM
1045        // - CAS    : A CAS request has a length of 2 flits or 4 flits => CAS FSM
1046        // - LL     : An LL request has a length of 1 flit => READ FSM
1047        // - SC     : An SC request has a length of 2 flits. First flit contains the
1048        //            acces key, second flit the data to write => WRITE FSM.
1049        //
1050        // The READ/WRITE commands accepted in the configuration segment are targeting
1051        // configuration or status registers. They must contain one single flit.
1052        // - For almost all addressable registers, the response is returned immediately.
1053        // - For MEMC_CMD_TYPE, the response is delayed until the operation is completed.
1054        ////////////////////////////////////////////////////////////////////////////////////
1055
1056
1057        switch (r_tgt_cmd_fsm.read())
1058        {
1059            //////////////////
1060            case TGT_CMD_IDLE:     // waiting a VCI command (RAM or CONFIG)
1061                if (p_vci_tgt.cmdval)
1062                {
1063#if DEBUG_MEMC_TGT_CMD
1064                    if (m_debug)
1065                    {
1066                        std::cout << "  <MEMC " << name()
1067                            << " TGT_CMD_IDLE> Receive command from srcid "
1068                            << std::hex << p_vci_tgt.srcid.read()
1069                            << " / address " << std::hex << p_vci_tgt.address.read() << std::endl;
1070                    }
1071#endif
1072                    // checking segmentation violation
1073                    addr_t   address = p_vci_tgt.address.read();
1074                    uint32_t plen    = p_vci_tgt.plen.read();
1075                    bool     config  = false;
1076
1077                    for (size_t seg_id = 0; (seg_id < m_nseg) ; seg_id++)
1078                    {
1079                        if (m_seg[seg_id]->contains(address) &&
1080                                m_seg[seg_id]->contains(address + plen - vci_param_int::B))
1081                        {
1082                            if (m_seg[seg_id]->special()) config = true;
1083                        }
1084                    }
1085
1086                    if (config)     /////////// configuration command
1087                    {
1088                        if (!p_vci_tgt.eop.read()) r_tgt_cmd_fsm = TGT_CMD_ERROR;
1089                        else                       r_tgt_cmd_fsm = TGT_CMD_CONFIG;
1090                    }
1091                    else           //////////// memory access
1092                    {
1093                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
1094                        {
1095                            // check that the pktid is either :
1096                            // TYPE_READ_DATA_UNC
1097                            // TYPE_READ_DATA_MISS
1098                            // TYPE_READ_INS_UNC
1099                            // TYPE_READ_INS_MISS
1100                            // ==> bit2 must be zero with the TSAR encoding
1101                            // ==> mask = 0b0100 = 0x4
1102                            assert(((p_vci_tgt.pktid.read() & 0x4) == 0x0) and
1103                                    "The type specified in the pktid field is incompatible with the READ CMD");
1104                            r_tgt_cmd_fsm = TGT_CMD_READ;
1105                        }
1106                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
1107                        {
1108                            // check that the pktid is TYPE_WRITE
1109                            // ==> TYPE_WRITE = X100 with the TSAR encoding
1110                            // ==> mask = 0b0111 = 0x7
1111                            assert((((p_vci_tgt.pktid.read() & 0x7) == 0x4)  or ((p_vci_tgt.pktid.read() & 0x7) == 0x0)) and
1112                                    "The type specified in the pktid field is incompatible with the WRITE CMD");
1113                            r_tgt_cmd_fsm = TGT_CMD_WRITE;
1114                        }
1115                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
1116                        {
1117                            // check that the pktid is TYPE_LL
1118                            // ==> TYPE_LL = X110 with the TSAR encoding
1119                            // ==> mask = 0b0111 = 0x7
1120                            assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) and
1121                                    "The type specified in the pktid field is incompatible with the LL CMD");
1122                            r_tgt_cmd_fsm = TGT_CMD_READ;
1123                        }
1124                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
1125                        {
1126                            // check that the pktid is either :
1127                            // TYPE_CAS
1128                            // TYPE_SC
1129                            // ==> TYPE_CAS = X101 with the TSAR encoding
1130                            // ==> TYPE_SC  = X111 with the TSAR encoding
1131                            // ==> mask = 0b0101 = 0x5
1132                            assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) and
1133                                    "The type specified in the pktid field is incompatible with the NOP CMD");
1134
1135                            if ((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS)
1136                            {
1137                                r_tgt_cmd_fsm = TGT_CMD_CAS;
1138                            }
1139                            else
1140                            {
1141                                r_tgt_cmd_fsm = TGT_CMD_WRITE;
1142                            }
1143                        }
1144                        else
1145                        {
1146                            r_tgt_cmd_fsm = TGT_CMD_ERROR;
1147                        }
1148                    }
1149                }
1150                break;
1151
1152                ///////////////////
1153            case TGT_CMD_ERROR:  // response error must be sent
1154
1155                // wait if pending request
1156                if (r_tgt_cmd_to_tgt_rsp_req.read()) break;
1157
1158                // consume all the command packet flits before sending response error
1159                if (p_vci_tgt.cmdval and p_vci_tgt.eop)
1160                {
1161                    r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
1162                    r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
1163                    r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
1164                    r_tgt_cmd_to_tgt_rsp_req   = true;
1165                    r_tgt_cmd_to_tgt_rsp_error = 1;
1166                    r_tgt_cmd_fsm              = TGT_CMD_IDLE;
1167
1168#if DEBUG_MEMC_TGT_CMD
1169                    if (m_debug)
1170                    {
1171                        std::cout << "  <MEMC " << name()
1172                            << " TGT_CMD_ERROR> Segmentation violation:"
1173                            << " address = " << std::hex << p_vci_tgt.address.read()
1174                            << " / srcid = " << p_vci_tgt.srcid.read()
1175                            << " / trdid = " << p_vci_tgt.trdid.read()
1176                            << " / pktid = " << p_vci_tgt.pktid.read()
1177                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1178                    }
1179#endif
1180                }
1181                break;
1182
1183                ////////////////////
1184            case TGT_CMD_CONFIG:    // execute config request and return response
1185            {
1186                ///////////////////////////////////////////////////////////
1187                //  Decoding CONFIG interface commands                   //
1188                //                                                       //
1189                //  VCI ADDRESS                                          //
1190                //  ================================================     //
1191                //  GLOBAL | LOCAL | ... | FUNC_IDX | REGS_IDX | 00      //
1192                //   IDX   |  IDX  |     | (3 bits) | (7 bits) |         //
1193                //  ================================================     //
1194                //                                                       //
1195                //  For instrumentation : FUNC_IDX = 0b001               //
1196                //                                                       //
1197                //  REGS_IDX                                             //
1198                //  ============================================         //
1199                //       Z     |    Y      |    X     |   W              //
1200                //    (1 bit)  | (2 bits)  | (3 bits) | (1 bit)          //
1201                //  ============================================         //
1202                //                                                       //
1203                //  Z : DIRECT / COHERENCE                               //
1204                //  Y : SUBTYPE (LOCAL, REMOTE, OTHER)                   //
1205                //  X : REGISTER INDEX                                   //
1206                //  W : HI / LO                                          //
1207                //                                                       //
1208                //  For configuration: FUNC_IDX = 0b000                  //
1209                //                                                       //
1210                //  REGS_IDX                                             //
1211                //  ============================================         //
1212                //             RESERVED             |    X     |         //
1213                //             (4 bits)             | (3 bits) |         //
1214                //  ============================================         //
1215                //                                                       //
1216                //  X : REGISTER INDEX                                   //
1217                //                                                       //
1218                //  For WRITE MISS error signaling: FUNC = 0x010         //
1219                //                                                       //
1220                //  REGS_IDX                                             //
1221                //  ============================================         //
1222                //             RESERVED             |    X     |         //
1223                //             (4 bits)             | (3 bits) |         //
1224                //  ============================================         //
1225                //                                                       //
1226                //  X : REGISTER INDEX                                   //
1227                //                                                       //
1228                ///////////////////////////////////////////////////////////
1229
1230                addr_t addr_lsb = p_vci_tgt.address.read() & m_config_addr_mask;
1231
1232                addr_t cell = (addr_lsb / vci_param_int::B);
1233
1234                size_t regr = cell & m_config_regr_idx_mask;
1235
1236                size_t func = (cell >> m_config_regr_width) & m_config_func_idx_mask;
1237
1238                bool     need_rsp;
1239                int      error;
1240                uint32_t rdata = 0; // default value
1241                uint32_t wdata = p_vci_tgt.wdata.read();
1242
1243                switch (func)
1244                {
1245                    // memory operation
1246                    case MEMC_CONFIG:
1247                    {
1248                        if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_READ) // get lock
1249                                and (regr == MEMC_LOCK))
1250                        {
1251                            rdata         = (uint32_t) r_config_lock.read();
1252                            need_rsp      = true;
1253                            error         = 0;
1254                            r_config_lock = true;
1255                        }
1256                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)  // release lock
1257                                and (regr == MEMC_LOCK))
1258                        {
1259                            need_rsp = true;
1260                            error    = 0;
1261                            r_config_lock = false;
1262                        }
1263                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_lo
1264                                and (regr == MEMC_ADDR_LO))
1265                        {
1266                            assert(((wdata % (m_words * vci_param_int::B)) == 0) and
1267                                    "VCI_MEM_CACHE CONFIG ERROR: The buffer must be aligned on a cache line");
1268
1269                            need_rsp = true;
1270                            error    = 0;
1271                            r_config_address = (r_config_address.read() & 0xFFFFFFFF00000000LL) |
1272                                ((addr_t)wdata);
1273                        }
1274                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_hi
1275                                and (regr == MEMC_ADDR_HI))
1276
1277                        {
1278                            need_rsp = true;
1279                            error    = 0;
1280                            r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) |
1281                                (((addr_t) wdata) << 32);
1282                        }
1283                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set buf_lines
1284                                and (regr == MEMC_BUF_LENGTH))
1285                        {
1286                            need_rsp = true;
1287                            error    = 0;
1288                            size_t lines = wdata / (m_words << 2);
1289                            if (wdata % (m_words << 2)) lines++;
1290                            r_config_cmd_lines = lines;
1291                            r_config_rsp_lines = 0;
1292                        }
1293                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set cmd type
1294                                and (regr == MEMC_CMD_TYPE))
1295                        {
1296                            need_rsp     = false;
1297                            error        = 0;
1298                            r_config_cmd = wdata;
1299
1300                            // prepare delayed response from CONFIG FSM
1301                            r_config_srcid = p_vci_tgt.srcid.read();
1302                            r_config_trdid = p_vci_tgt.trdid.read();
1303                            r_config_pktid = p_vci_tgt.pktid.read();
1304                        }
1305                        else
1306                        {
1307                            need_rsp = true;
1308                            error    = 1;
1309                        }
1310
1311                        break;
1312                    }
1313
1314                    // instrumentation registers
1315                    case MEMC_INSTRM:
1316                    {
1317                        need_rsp = true;
1318
1319                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
1320                        {
1321                            error = read_instrumentation(regr, rdata);
1322                        }
1323                        else
1324                        {
1325                            error = 1;
1326                        }
1327
1328                        break;
1329                    }
1330
1331                    // xram GET bus error registers
1332                    case MEMC_RERROR:
1333                    {
1334                        need_rsp = true;
1335                        error    = 0;
1336
1337                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
1338                        {
1339                            switch (regr)
1340                            {
1341                                case MEMC_RERROR_IRQ_ENABLE:
1342                                    r_xram_rsp_rerror_irq_enable = (p_vci_tgt.wdata.read() != 0);
1343
1344                                    break;
1345
1346                                default:
1347                                    error = 1;
1348                                    break;
1349                            }
1350                        }
1351                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
1352                        {
1353                            switch (regr)
1354                            {
1355                                case MEMC_RERROR_SRCID:
1356                                    rdata = (uint32_t) r_xram_rsp_rerror_rsrcid.read();
1357                                    break;
1358
1359                                case MEMC_RERROR_ADDR_LO:
1360                                    rdata = (uint32_t) (r_xram_rsp_rerror_address.read()) & ((1ULL << 32) - 1);
1361
1362                                    break;
1363
1364                                case MEMC_RERROR_ADDR_HI:
1365                                    rdata = (uint32_t) (r_xram_rsp_rerror_address.read() >> 32) & ((1ULL << 32) - 1);
1366                                    break;
1367
1368                                case MEMC_RERROR_IRQ_RESET:
1369                                    if (not r_xram_rsp_rerror_irq.read()) break;
1370                                    r_xram_rsp_rerror_irq = false;
1371                                    break;
1372
1373                                case MEMC_RERROR_IRQ_ENABLE:
1374                                    rdata = (uint32_t) (r_xram_rsp_rerror_irq_enable.read()) ? 1 : 0;
1375                                    break;
1376
1377                                default:
1378                                    error = 1;
1379                                    break;
1380                            }
1381                        }
1382                        else
1383                        {
1384                            error = 1;
1385                        }
1386
1387                        break;
1388                    }
1389
1390                    //unknown function
1391                    default:
1392                    {
1393                        need_rsp = true;
1394                        error = 1;
1395                        break;
1396                    }
1397                }
1398
1399                if (need_rsp)
1400                {
1401                    // blocked if previous pending request to TGT_RSP FSM
1402                    if (r_tgt_cmd_to_tgt_rsp_req.read()) break;
1403
1404                    r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
1405                    r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
1406                    r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
1407                    r_tgt_cmd_to_tgt_rsp_req   = true;
1408                    r_tgt_cmd_to_tgt_rsp_error = error;
1409                    r_tgt_cmd_to_tgt_rsp_rdata = rdata;
1410                }
1411
1412                r_tgt_cmd_fsm = TGT_CMD_IDLE;
1413
1414#if DEBUG_MEMC_TGT_CMD
1415                if (m_debug)
1416                {
1417                    std::cout << "  <MEMC " << name() << " TGT_CMD_CONFIG> Configuration request:"
1418                        << " address = " << std::hex << p_vci_tgt.address.read()
1419                        << " / func = " << func
1420                        << " / regr = " << regr
1421                        << " / rdata = " << rdata
1422                        << " / wdata = " << p_vci_tgt.wdata.read()
1423                        << " / need_rsp = " << need_rsp
1424                        << " / error = " << error << std::endl;
1425                }
1426#endif
1427                break;
1428            }
1429            //////////////////
1430            case TGT_CMD_READ:    // Push a read request into read fifo
1431
1432                // check that the read does not cross a cache line limit.
1433                if (((m_x[(addr_t) p_vci_tgt.address.read()] + (p_vci_tgt.plen.read() >> 2)) > 16) and
1434                        (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ))
1435                {
1436                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
1437                        << " illegal address/plen for VCI read command" << std::endl;
1438                    exit(0);
1439                }
1440                // check single flit
1441                if (!p_vci_tgt.eop.read())
1442                {
1443                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
1444                        << " read command packet must contain one single flit" << std::endl;
1445                    exit(0);
1446                }
1447                // check plen for LL
1448                if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) and
1449                        (p_vci_tgt.plen.read() != 8))
1450                {
1451                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
1452                        << " ll command packets must have a plen of 8" << std::endl;
1453                    exit(0);
1454                }
1455
1456                if (p_vci_tgt.cmdval and m_cmd_read_addr_fifo.wok())
1457                {
1458
1459#if DEBUG_MEMC_TGT_CMD
1460                    if (m_debug)
1461                    {
1462                        std::cout << "  <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:"
1463                            << " address = " << std::hex << p_vci_tgt.address.read()
1464                            << " / srcid = " << p_vci_tgt.srcid.read()
1465                            << " / trdid = " << p_vci_tgt.trdid.read()
1466                            << " / pktid = " << p_vci_tgt.pktid.read()
1467                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1468                    }
1469#endif
1470                    cmd_read_fifo_put = true;
1471                    // <Activity counters>
1472                    if (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
1473                    {
1474                        if (is_local_req(p_vci_tgt.srcid.read()))
1475                        {
1476                            m_cpt_ll_local++;
1477                        }
1478                        else
1479                        {
1480                            m_cpt_ll_remote++;
1481                        }
1482                        // (1 (CMD) + 2 (RSP)) VCI flits for LL => 2 + 3 dspin flits
1483                        m_cpt_ll_cost += 5 * req_distance(p_vci_tgt.srcid.read());
1484                    }
1485                    else {
1486                        if (is_local_req(p_vci_tgt.srcid.read()))
1487                        {
1488                            m_cpt_read_local++;
1489                        }
1490                        else
1491                        {
1492                            m_cpt_read_remote++;
1493                        }
1494                        // (1 (CMD) + m_words (RSP)) flits VCI => 2 + m_words + 1 flits dspin
1495                        m_cpt_read_cost += (3 + m_words) * req_distance(p_vci_tgt.srcid.read());
1496                    }
1497                    // </Activity counters>
1498                    r_tgt_cmd_fsm = TGT_CMD_IDLE;
1499                }
1500                break;
1501
1502                ///////////////////
1503            case TGT_CMD_WRITE:
1504                if (p_vci_tgt.cmdval and m_cmd_write_addr_fifo.wok())
1505                {
1506                    uint32_t plen = p_vci_tgt.plen.read();
1507#if DEBUG_MEMC_TGT_CMD
1508                    if (m_debug)
1509                    {
1510                        std::cout << "  <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:"
1511                            << " address = " << std::hex << p_vci_tgt.address.read()
1512                            << " / srcid = " << p_vci_tgt.srcid.read()
1513                            << " / trdid = " << p_vci_tgt.trdid.read()
1514                            << " / pktid = " << p_vci_tgt.pktid.read()
1515                            << " / wdata = " << p_vci_tgt.wdata.read()
1516                            << " / be = " << p_vci_tgt.be.read()
1517                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1518                    }
1519#endif
1520                    cmd_write_fifo_put = true;
1521                    // <Activity counters>
1522                    if (p_vci_tgt.cmd.read() != vci_param_int::CMD_NOP)
1523                    {
1524                        if (is_local_req(p_vci_tgt.srcid.read()))
1525                        {
1526                            m_cpt_write_flits_local++;
1527                        }
1528                        else
1529                        {
1530                            m_cpt_write_flits_remote++;
1531                        }
1532                    }
1533                    // </Activity counters>
1534
1535                    if (p_vci_tgt.eop)
1536                    {
1537                        // <Activity counters>
1538                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
1539                        {
1540                            // SC
1541                            // (2 (CMD) + 1 (RSP)) flits VCI => 4 + (1 (success) || 2 (failure)) flits dspin
1542                            m_cpt_sc_cost += 5 * req_distance(p_vci_tgt.srcid.read());
1543
1544                            if (is_local_req(p_vci_tgt.srcid.read()))
1545                            {
1546                                m_cpt_sc_local++;
1547                            }
1548                            else
1549                            {
1550                                m_cpt_sc_remote++;
1551                            }
1552                        }
1553                        else {
1554                            // Writes
1555                            // (burst_size (CMD) + 1 (RSP) flits VCI => 2 + burst_size + 1 flits dspin
1556                            m_cpt_write_cost += (3 + (plen >> 2)) * req_distance(p_vci_tgt.srcid.read());
1557
1558                            if (is_local_req(p_vci_tgt.srcid.read()))
1559                            {
1560                                m_cpt_write_local++;
1561                            }
1562                            else
1563                            {
1564                                m_cpt_write_remote++;
1565                            }
1566                        }
1567                        // </Activity counters>
1568                        r_tgt_cmd_fsm = TGT_CMD_IDLE;
1569                    }
1570                }
1571                break;
1572
1573                /////////////////
1574            case TGT_CMD_CAS:
1575                if ((p_vci_tgt.plen.read() != 8) and (p_vci_tgt.plen.read() != 16))
1576                {
1577                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
1578                        << "illegal format for CAS command " << std::endl;
1579                    exit(0);
1580                }
1581
1582                if (p_vci_tgt.cmdval and m_cmd_cas_addr_fifo.wok())
1583                {
1584#if DEBUG_MEMC_TGT_CMD
1585                    if (m_debug)
1586                    {
1587                        std::cout << "  <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
1588                            << " address = " << std::hex << p_vci_tgt.address.read()
1589                            << " srcid = " << p_vci_tgt.srcid.read()
1590                            << " trdid = " << p_vci_tgt.trdid.read()
1591                            << " pktid = " << p_vci_tgt.pktid.read()
1592                            << " wdata = " << p_vci_tgt.wdata.read()
1593                            << " be = " << p_vci_tgt.be.read()
1594                            << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1595                    }
1596#endif
1597                    cmd_cas_fifo_put = true;
1598                    if (p_vci_tgt.eop)
1599                    {
1600                        // <Activity counters>
1601                        if (is_local_req(p_vci_tgt.srcid.read()))
1602                        {
1603                            m_cpt_cas_local++;
1604                        }
1605                        else
1606                        {
1607                            m_cpt_cas_remote++;
1608                        }
1609                        // (2 (CMD) + 1 (RSP)) flits VCI => 4 + (1 (success) || 2 (failure)) flits dspin
1610                        m_cpt_cas_cost += 5 * req_distance(p_vci_tgt.srcid.read());
1611                        // </Activity counters>
1612                        r_tgt_cmd_fsm = TGT_CMD_IDLE;
1613                    }
1614                }
1615                break;
1616        } // end switch tgt_cmd_fsm
1617
1618        ////////////////////////////////////////////////////////////////////////////////////
1619        //    CONFIG FSM
1620        ////////////////////////////////////////////////////////////////////////////////////
1621        // The CONFIG FSM handles the VCI configuration requests (INVAL & SYNC).
1622        // The target buffer can have any size, and there is one single command for
1623        // all cache lines covered by the target buffer.
1624        //
1625        // An INVAL or SYNC configuration operation is defined by the following registers:
1626        // - bool      r_config_cmd        : INVAL / SYNC / NOP
1627        // - uint64_t  r_config_address    : buffer base address
1628        // - uint32_t  r_config_cmd_lines  : number of lines to be handled
1629        // - uint32_t  r_config_rsp_lines  : number of lines not completed
1630        //
1631        // For both INVAL and SYNC commands, the CONFIG FSM contains the loop handling
1632        // all cache lines covered by the buffer. The various lines of a given buffer
1633        // can be pipelined: the CONFIG FSM does not wait the response for line (n) to send
1634        // the command for line (n+1). It decrements the r_config_cmd_lines counter until
1635        // the last request has been registered in TRT (for a SYNC), or in IVT (for an INVAL).
1636        // The r_config_rsp_lines counter contains the number of expected responses from
1637        // CLEANUP FSM (inval) or from IXR_RSP FSM (sync). This register is incremented by
1638        // the CONFIG FSM (each time a transaction is requested), and decremented by the
1639        // CLEANUP or IXR_RSP FSMs(each time a response is received. As this register can
1640        // be concurently accessed by those three FSMs, it is implemented as an [incr/decr]
1641        // counter.
1642        //
1643        // - INVAL request:
1644        //   For each line, it access to the DIR.
1645        //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
1646        //   In case of hit, with no copies in L1 caches, the line is invalidated and
1647        //   a response is requested to TGT_RSP FSM.
1648        //   If there is copies, a multi-inval, or a broadcast-inval coherence transaction
1649        //   is launched and registered in UPT. The multi-inval transaction completion
1650        //   is signaled by the CLEANUP FSM by decrementing the r_config_rsp_lines counter.
1651        //   The CONFIG INVAL response is sent only when the last line has been invalidated.
1652        //   There is no PUT transaction to XRAM, even if the invalidated line is dirty...
1653        //   TODO : The target buffer address must be aligned on a cache line boundary.
1654        //   This constraint can be released, but it requires to make 2 PUT transactions
1655        //   for the first and the last line...
1656        //
1657        // - SYNC request:
1658        //   For each line, it access to the DIR.
1659        //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
1660        //   In case of hit, a PUT transaction is registered in TRT and a request is sent
1661        //   to IXR_CMD FSM. The IXR_RSP FSM decrements the r_config_rsp_lines counter
1662        //   when a PUT response is received.
1663        //   The CONFIG SYNC response is sent only when the last PUT response is received.
1664        //
1665        // From the software point of view, a configuration request is a sequence
1666        // of 6 atomic accesses in an uncached segment. A dedicated lock is used
1667        // to handle only one configuration command at a given time:
1668        // - Read  MEMC_LOCK       : Get the lock
1669        // - Write MEMC_ADDR_LO    : Set the buffer address LSB
1670        // - Write MEMC_ADDR_HI    : Set the buffer address MSB
1671        // - Write MEMC_BUF_LENGTH : set buffer length (bytes)
1672        // - Write MEMC_CMD_TYPE   : launch the actual operation
1673        // - WRITE MEMC_LOCK       : release the lock
1674        ////////////////////////////////////////////////////////////////////////////////////
1675
1676        switch (r_config_fsm.read())
1677        {
1678            /////////////////
1679            case CONFIG_IDLE:  // waiting a config request
1680            {
1681                if (r_config_cmd.read() != MEMC_CMD_NOP)
1682                {
1683                    r_config_fsm = CONFIG_LOOP;
1684
1685#if DEBUG_MEMC_CONFIG
1686                    if (m_debug)
1687                    {
1688                        std::cout << "  <MEMC " << name() << " CONFIG_IDLE> Config Request received"
1689                            << " / address = " << std::hex << r_config_address.read()
1690                            << " / lines = " << std::dec << r_config_cmd_lines.read()
1691                            << " / type = " << r_config_cmd.read() << std::endl;
1692                    }
1693#endif
1694                }
1695                break;
1696            }
1697            /////////////////
1698            case CONFIG_LOOP:   // test if last line to be handled
1699            {
1700                if (r_config_cmd_lines.read() == 0)
1701                {
1702                    r_config_cmd = MEMC_CMD_NOP;
1703                    r_config_fsm = CONFIG_WAIT;
1704                }
1705                else
1706                {
1707                    r_config_fsm = CONFIG_DIR_REQ;
1708                }
1709
1710#if DEBUG_MEMC_CONFIG
1711                if (m_debug)
1712                {
1713                    std::cout << "  <MEMC " << name() << " CONFIG_LOOP>"
1714                        << " / address = " << std::hex << r_config_address.read()
1715                        << " / lines not handled = " << std::dec << r_config_cmd_lines.read()
1716                        << " / command = " << r_config_cmd.read() << std::endl;
1717                }
1718#endif
1719                break;
1720            }
1721            /////////////////
1722            case CONFIG_WAIT:   // wait completion (last response)
1723            {
1724                if (r_config_rsp_lines.read() == 0)  // last response received
1725                {
1726                    r_config_fsm = CONFIG_RSP;
1727                }
1728
1729#if DEBUG_MEMC_CONFIG
1730                if (m_debug)
1731                {
1732                    std::cout << "  <MEMC " << name() << " CONFIG_WAIT>"
1733                        << " / lines to do = " << std::dec << r_config_rsp_lines.read() << std::endl;
1734                }
1735#endif
1736                break;
1737            }
1738            ////////////////
1739            case CONFIG_RSP:  // request TGT_RSP FSM to return response
1740            {
1741                if (not r_config_to_tgt_rsp_req.read())
1742                {
1743                    r_config_to_tgt_rsp_srcid = r_config_srcid.read();
1744                    r_config_to_tgt_rsp_trdid = r_config_trdid.read();
1745                    r_config_to_tgt_rsp_pktid = r_config_pktid.read();
1746                    r_config_to_tgt_rsp_error = false;
1747                    r_config_to_tgt_rsp_req   = true;
1748                    r_config_fsm              = CONFIG_IDLE;
1749
1750#if DEBUG_MEMC_CONFIG
1751                    if (m_debug)
1752                    {
1753                        std::cout << "  <MEMC " << name() << " CONFIG_RSP> Request TGT_RSP FSM to send response:"
1754                            << " error = " << r_config_to_tgt_rsp_error.read()
1755                            << " / rsrcid = " << std::hex << r_config_srcid.read()
1756                            << " / rtrdid = " << std::hex << r_config_trdid.read()
1757                            << " / rpktid = " << std::hex << r_config_pktid.read() << std::endl;
1758                    }
1759#endif
1760                }
1761                break;
1762            }
1763            ////////////////////
1764            case CONFIG_DIR_REQ:  // Request directory lock
1765            {
1766                if (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG)
1767                {
1768                    r_config_fsm = CONFIG_DIR_ACCESS;
1769                }
1770
1771#if DEBUG_MEMC_CONFIG
1772                if (m_debug)
1773                {
1774                    std::cout << "  <MEMC " << name() << " CONFIG_DIR_REQ>"
1775                        << " Request DIR access" << std::endl;
1776                }
1777#endif
1778                break;
1779            }
1780            ///////////////////////
1781            case CONFIG_DIR_ACCESS:   // Access directory and decode config command
1782            {
1783                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
1784                "MEMC ERROR in CONFIG_DIR_ACCESS state: bad DIR allocation");
1785
1786                size_t way = 0;
1787                DirectoryEntry entry = m_cache_directory.read(r_config_address.read(), way);
1788
1789                r_config_dir_way        = way;
1790                r_config_dir_copy_inst  = entry.owner.inst;
1791                r_config_dir_copy_srcid = entry.owner.srcid;
1792                r_config_dir_is_cnt     = entry.is_cnt;
1793                r_config_dir_lock       = entry.lock;
1794                r_config_dir_count      = entry.count;
1795
1796                if (entry.valid and   // hit & inval command
1797                   (r_config_cmd.read() == MEMC_CMD_INVAL))
1798                {
1799                    // TODO QM : send Inval ?
1800                    r_config_fsm = CONFIG_IDLE;
1801                }
1802                else if (entry.valid and  // hit & sync command
1803                         entry.dirty and
1804                         (r_config_cmd.read() == MEMC_CMD_SYNC))
1805                {
1806                    r_config_fsm = CONFIG_TRT_LOCK;
1807                }
1808                else    // miss : return to LOOP
1809                {
1810                    r_config_cmd_lines = r_config_cmd_lines.read() - 1;
1811                    r_config_address   = r_config_address.read() + (m_words << 2);
1812                    r_config_fsm       = CONFIG_LOOP;
1813                }
1814
1815#if DEBUG_MEMC_CONFIG
1816                if (m_debug)
1817                {
1818                    std::cout << "  <MEMC " << name() << " CONFIG_DIR_ACCESS> Accessing directory: "
1819                        << " address = " << std::hex << r_config_address.read()
1820                        << " / hit = " << std::dec << entry.valid
1821                        << " / dirty = " << entry.dirty
1822                        << " / count = " << entry.count
1823                        << " / is_cnt = " << entry.is_cnt << std::endl;
1824                }
1825#endif
1826                break;
1827            }
1828            /////////////////////
1829            case CONFIG_TRT_LOCK:      // enter this state in case of SYNC command
1830                                       // to a dirty cache line
1831                                       // keep DIR lock, and try to get TRT lock
1832                                       // return to LOOP state if TRT full
1833                                       // reset dirty bit in DIR and register a PUT
1834                                       // transaction in TRT if not full.
1835            {
1836                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
1837                "MEMC ERROR in CONFIG_TRT_LOCK state: bad DIR allocation");
1838
1839                if (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG)
1840                {
1841                    size_t index = 0;
1842                    bool wok = not m_trt.full(index);
1843
1844                    if (not wok)
1845                    {
1846                        r_config_fsm = CONFIG_LOOP;
1847                    }
1848                    else
1849                    {
1850                        size_t way = r_config_dir_way.read();
1851                        size_t set = m_y[r_config_address.read()];
1852
1853                        // reset dirty bit in DIR
1854                        DirectoryEntry  entry;
1855                        entry.valid       = true;
1856                        entry.dirty       = false;
1857                        entry.tag         = m_z[r_config_address.read()];
1858                        entry.is_cnt      = r_config_dir_is_cnt.read();
1859                        entry.lock        = r_config_dir_lock.read();
1860                        entry.count       = r_config_dir_count.read();
1861                        entry.owner.inst  = r_config_dir_copy_inst.read();
1862                        entry.owner.srcid = r_config_dir_copy_srcid.read();
1863                        m_cache_directory.write(set, way, entry);
1864
1865                        r_config_trt_index = index;
1866                        r_config_fsm       = CONFIG_TRT_SET;
1867                    }
1868
1869#if DEBUG_MEMC_CONFIG
1870                    if (m_debug)
1871                    {
1872                        std::cout << "  <MEMC " << name() << " CONFIG_TRT_LOCK> Access TRT: "
1873                            << " wok = " << std::dec << wok
1874                            << " index = " << index << std::endl;
1875                    }
1876#endif
1877                }
1878                break;
1879            }
1880            ////////////////////
1881            case CONFIG_TRT_SET:       // read data in cache
1882            // and post a PUT request in TRT
1883            {
1884                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
1885                "MEMC ERROR in CONFIG_TRT_SET state: bad DIR allocation");
1886
1887                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG) and
1888                "MEMC ERROR in CONFIG_TRT_SET state: bad TRT allocation");
1889
1890                // read data into cache
1891                size_t way = r_config_dir_way.read();
1892                size_t set = m_y[r_config_address.read()];
1893                std::vector<data_t> data_vector;
1894                data_vector.clear();
1895                for (size_t word = 0; word < m_words; word++)
1896                {
1897                    uint32_t data = m_cache_data.read(way, set, word);
1898                    data_vector.push_back(data);
1899                }
1900
1901                // post the PUT request in TRT
1902                m_trt.set(r_config_trt_index.read(),
1903                          false,                            // PUT transaction
1904                          m_nline[r_config_address.read()], // line index
1905                          0,                                // srcid:       unused
1906                          0,                                // trdid:       unused
1907                          0,                                // pktid:       unused
1908                          false,                            // not proc_read
1909                          0,                                // read_length: unused
1910                          0,                                // word_index:  unused
1911                          std::vector<be_t>(m_words, 0xF),  // byte-enable: unused
1912                          data_vector,                      // data to be written
1913                          0,                                // ll_key:      unused
1914                          true);                            // requested by config FSM
1915                config_rsp_lines_incr = true;
1916                r_config_fsm          = CONFIG_PUT_REQ;
1917
1918#if DEBUG_MEMC_CONFIG
1919                if (m_debug)
1920                {
1921                    std::cout << "  <MEMC " << name() << " CONFIG_TRT_SET> PUT request in TRT:"
1922                        << " address = " << std::hex << r_config_address.read()
1923                        << " index = " << std::dec << r_config_trt_index.read() << std::endl;
1924                }
1925#endif
1926                break;
1927            }
1928            ////////////////////
1929            case CONFIG_PUT_REQ:       // post PUT request to IXR_CMD_FSM
1930            {
1931                if (not r_config_to_ixr_cmd_req.read())
1932                {
1933                    r_config_to_ixr_cmd_req   = true;
1934                    r_config_to_ixr_cmd_index = r_config_trt_index.read();
1935
1936                    // prepare next iteration
1937                    r_config_cmd_lines = r_config_cmd_lines.read() - 1;
1938                    r_config_address   = r_config_address.read() + (m_words << 2);
1939                    r_config_fsm       = CONFIG_LOOP;
1940
1941#if DEBUG_MEMC_CONFIG
1942                    if (m_debug)
1943                    {
1944                        std::cout << "  <MEMC " << name() << " CONFIG_PUT_REQ> post PUT request to IXR_CMD_FSM"
1945                            << " / address = " << std::hex << r_config_address.read() << std::endl;
1946                    }
1947#endif
1948                }
1949                break;
1950            }
1951        }  // end switch r_config_fsm
1952
1953
1954
1955        ////////////////////////////////////////////////////////////////////////////////////
1956        //    READ FSM
1957        ////////////////////////////////////////////////////////////////////////////////////
1958        // The READ FSM controls the VCI read  and ll requests.
1959        // It takes the lock protecting the cache directory to check the cache line status:
1960        // - In case of HIT
1961        //   The fsm copies the data (one line, or one single word)
1962        //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
1963        //   The requesting initiator is registered in the cache directory.
1964        //   If the number of copy is larger than 1, the new copy is registered
1965        //   in the HEAP.
1966        //   If the number of copy is larger than the threshold, the HEAP is cleared,
1967        //   and the corresponding line switches to the counter mode.
1968        // - In case of MISS
1969        //   The READ fsm takes the lock protecting the transaction tab.
1970        //   If a read transaction to the XRAM for this line already exists,
1971        //   or if the transaction tab is full, the fsm is stalled.
1972        //   If a TRT entry is free, the READ request is registered in TRT,
1973        //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
1974        //   The READ FSM returns in the IDLE state as the read transaction will be
1975        //   completed when the missing line will be received.
1976        ////////////////////////////////////////////////////////////////////////////////////
1977
1978        switch (r_read_fsm.read())
1979        {
1980            ///////////////
1981            case READ_IDLE:  // waiting a read request
1982            {
1983                if (m_cmd_read_addr_fifo.rok())
1984                {
1985
1986#if DEBUG_MEMC_READ
1987                    if (m_debug)
1988                    {
1989                        std::cout << "  <MEMC " << name() << " READ_IDLE> Read request"
1990                            << " : address = " << std::hex << m_cmd_read_addr_fifo.read()
1991                            << " / srcid = " << m_cmd_read_srcid_fifo.read()
1992                            << " / trdid = " << m_cmd_read_trdid_fifo.read()
1993                            << " / pktid = " << m_cmd_read_pktid_fifo.read()
1994                            << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1995                    }
1996#endif
1997                    r_read_fsm = READ_DIR_REQ;
1998                }
1999                break;
2000            }
2001            //////////////////
2002            case READ_DIR_REQ:  // Get the lock to the directory
2003            {
2004                if (r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
2005                {
2006                    r_read_fsm = READ_DIR_LOCK;
2007                }
2008
2009#if DEBUG_MEMC_READ
2010                if (m_debug)
2011                {
2012                    std::cout << "  <MEMC " << name() << " READ_DIR_REQ> Requesting DIR lock " << std::endl;
2013                }
2014#endif
2015                break;
2016            }
2017
2018            ///////////////////
2019            case READ_DIR_LOCK:  // check directory for hit / miss
2020            {
2021                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
2022                        "MEMC ERROR in READ_DIR_LOCK state: Bad DIR allocation");
2023
2024                size_t way = 0;
2025                DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
2026
2027                // access the global table ONLY when we have an LL cmd
2028                if ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)
2029                {
2030                    r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
2031                }
2032                r_read_is_cnt    = entry.is_cnt;
2033                r_read_dirty     = entry.dirty;
2034                r_read_lock      = entry.lock;
2035                r_read_tag       = entry.tag;
2036                r_read_way       = way;
2037                r_read_count     = entry.count;
2038                r_read_copy      = entry.owner.srcid;
2039                r_read_copy_inst = entry.owner.inst;
2040
2041                // check if this is a cached read, this means pktid is either
2042                // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
2043                // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
2044                if (entry.valid)    // hit
2045                {
2046                    r_read_fsm = READ_DIR_HIT;
2047                }
2048                else      // miss
2049                {
2050                    r_read_fsm = READ_TRT_LOCK;
2051                }
2052
2053#if DEBUG_MEMC_READ
2054                if (m_debug)
2055                {
2056                    std::cout << "  <MEMC " << name() << " READ_DIR_LOCK> Accessing directory: "
2057                        << " address = " << std::hex << m_cmd_read_addr_fifo.read()
2058                        << " / hit = " << std::dec << entry.valid
2059                        << " / count = " <<std::dec << entry.count
2060                        << " / is_cnt = " << entry.is_cnt;
2061                    if ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)
2062                    {
2063                        std::cout << " / LL access" << std::endl;
2064                    }
2065                    else
2066                    {
2067                        std::cout << std::endl;
2068                    }
2069                }
2070#endif
2071                break;
2072            }
2073            //////////////////
2074            case READ_DIR_HIT:    //  read data in cache & update the directory
2075            //  we enter this state in 3 cases:
2076            //  - the read request is uncachable
2077            //  - the cache line is in counter mode
2078            //  - the cache line is valid but not replicated
2079            {
2080                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
2081                        "MEMC ERROR in READ_DIR_HIT state: Bad DIR allocation");
2082
2083                // check if this is an instruction read, this means pktid is either
2084                // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
2085                // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
2086                bool inst_read = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
2087                // check if this is a cached read, this means pktid is either
2088                // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
2089                // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
2090                bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
2091                bool is_cnt      = r_read_is_cnt.read();
2092
2093                // read data in the cache
2094                size_t set = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
2095                size_t way = r_read_way.read();
2096
2097                m_cache_data.read_line(way, set, r_read_data);
2098
2099                // update the cache directory
2100                DirectoryEntry entry;
2101                entry.valid  = true;
2102                entry.is_cnt = is_cnt;
2103                entry.dirty  = r_read_dirty.read();
2104                entry.tag    = r_read_tag.read();
2105                entry.lock   = r_read_lock.read();
2106
2107                if (cached_read) // Cached read => we must update the copies
2108                {
2109                    if (!is_cnt)  // Not counter mode
2110                    {
2111                        entry.owner.srcid = m_cmd_read_srcid_fifo.read();
2112                        entry.owner.inst  = inst_read;
2113                        entry.count       = r_read_count.read() + 1;
2114                    }
2115                    else  // Counter mode
2116                    {
2117                        entry.owner.srcid = 0;
2118                        entry.owner.inst  = false;
2119                        entry.count       = r_read_count.read() + 1;
2120                    }
2121                }
2122                else // Uncached read
2123                {
2124                    entry.owner.srcid = r_read_copy.read();
2125                    entry.owner.inst  = r_read_copy_inst.read();
2126                    entry.count       = r_read_count.read();
2127                }
2128
2129#if DEBUG_MEMC_READ
2130                if (m_debug)
2131                {
2132                    std::cout << "  <MEMC " << name() << " READ_DIR_HIT> Update directory entry:"
2133                        << " addr = " << std::hex << m_cmd_read_addr_fifo.read()
2134                        << " / set = " << std::dec << set
2135                        << " / way = " << way
2136                        << " / owner_id = " << std::hex << entry.owner.srcid
2137                        << " / owner_ins = " << std::dec << entry.owner.inst
2138                        << " / count = " << entry.count
2139                        << " / is_cnt = " << entry.is_cnt << std::endl;
2140                }
2141#endif
2142                m_cache_directory.write(set, way, entry);
2143                r_read_fsm = READ_RSP;
2144                break;
2145            }
2146            ///////////////////
2147            case READ_RSP:    //  request the TGT_RSP FSM to return data
2148            {
2149                if (!r_read_to_tgt_rsp_req)
2150                {
2151                    for (size_t i = 0; i < m_words; i++)
2152                    {
2153                        r_read_to_tgt_rsp_data[i] = r_read_data[i];
2154                    }
2155                    r_read_to_tgt_rsp_word   = m_x[(addr_t) m_cmd_read_addr_fifo.read()];
2156                    r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
2157                    r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
2158                    r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
2159                    r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
2160                    r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
2161                    cmd_read_fifo_get        = true;
2162                    r_read_to_tgt_rsp_req    = true;
2163                    r_read_fsm               = READ_IDLE;
2164
2165#if DEBUG_MEMC_READ
2166                    if (m_debug)
2167                    {
2168                        std::cout << "  <MEMC " << name() << " READ_RSP> Request TGT_RSP FSM to return data:"
2169                            << " rsrcid = " << std::hex << m_cmd_read_srcid_fifo.read()
2170                            << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
2171                            << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
2172                    }
2173#endif
2174                }
2175                break;
2176            }
2177            ///////////////////
2178            case READ_TRT_LOCK: // read miss : check the Transaction Table
2179            {
2180                if (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
2181                {
2182                    size_t index     = 0;
2183                    addr_t addr      = (addr_t) m_cmd_read_addr_fifo.read();
2184                    bool   hit_read  = m_trt.hit_read(m_nline[addr], index);
2185                    bool   hit_write = m_trt.hit_write(m_nline[addr]);
2186                    bool   wok       = not m_trt.full(index);
2187
2188                    if (hit_read or !wok or hit_write) // line already requested or no space
2189                    {
2190                        if (!wok)                  m_cpt_trt_full++;
2191                        if (hit_read or hit_write) m_cpt_trt_rb++;
2192                        r_read_fsm = READ_IDLE;
2193                    }
2194                    else // missing line is requested to the XRAM
2195                    {
2196                        m_cpt_read_miss++;
2197                        r_read_trt_index = index;
2198                        r_read_fsm       = READ_TRT_SET;
2199                    }
2200
2201#if DEBUG_MEMC_READ
2202                    if (m_debug)
2203                    {
2204                        std::cout << "  <MEMC " << name() << " READ_TRT_LOCK> Check TRT:"
2205                            << " hit_read = " << hit_read
2206                            << " / hit_write = " << hit_write
2207                            << " / full = " << !wok << std::endl;
2208                    }
2209#endif
2210                }
2211                break;
2212            }
2213            //////////////////
2214            case READ_TRT_SET: // register get transaction in TRT
2215            {
2216                if (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
2217                {
2218                    m_trt.set(r_read_trt_index.read(),
2219                            true,      // GET
2220                            m_nline[(addr_t) (m_cmd_read_addr_fifo.read())],
2221                            m_cmd_read_srcid_fifo.read(),
2222                            m_cmd_read_trdid_fifo.read(),
2223                            m_cmd_read_pktid_fifo.read(),
2224                            true,      // proc read
2225                            m_cmd_read_length_fifo.read(),
2226                            m_x[(addr_t) (m_cmd_read_addr_fifo.read())],
2227                            std::vector<be_t> (m_words, 0),
2228                            std::vector<data_t> (m_words, 0),
2229                            r_read_ll_key.read());
2230#if DEBUG_MEMC_READ
2231                    if (m_debug)
2232                    {
2233                        std::cout << "  <MEMC " << name() << " READ_TRT_SET> Set a GET in TRT:"
2234                            << " address = " << std::hex << m_cmd_read_addr_fifo.read()
2235                            << " / srcid = " << std::hex << m_cmd_read_srcid_fifo.read() << std::endl;
2236                    }
2237#endif
2238                    r_read_fsm = READ_TRT_REQ;
2239                }
2240                break;
2241            }
2242
2243            //////////////////
2244            case READ_TRT_REQ:   // consume the read request in FIFO and send it to IXR_CMD_FSM
2245            {
2246                if (not r_read_to_ixr_cmd_req)
2247                {
2248                    cmd_read_fifo_get       = true;
2249                    r_read_to_ixr_cmd_req   = true;
2250                    r_read_to_ixr_cmd_index = r_read_trt_index.read();
2251                    r_read_fsm              = READ_IDLE;
2252
2253#if DEBUG_MEMC_READ
2254                    if (m_debug)
2255                    {
2256                        std::cout << "  <MEMC " << name() << " READ_TRT_REQ> Request GET transaction for address "
2257                            << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
2258                    }
2259#endif
2260                }
2261                break;
2262            }
2263        } // end switch read_fsm
2264
2265        ///////////////////////////////////////////////////////////////////////////////////
2266        //    WRITE FSM
2267        ///////////////////////////////////////////////////////////////////////////////////
2268        // The WRITE FSM handles the write bursts and sc requests sent by the processors.
2269        // All addresses in a burst must be in the same cache line.
2270        // A complete write burst is consumed in the FIFO & copied to a local buffer.
2271        // Then the FSM takes the lock protecting the cache directory, to check
2272        // if the line is in the cache.
2273        //
2274        // - In case of HIT, the cache is updated.
2275        //   If there is no other copy, an acknowledge response is immediately
2276        //   returned to the writing processor.
2277        //   If the data is cached by other processors, a coherence transaction must
2278        //   be launched (sc requests always require a coherence transaction):
2279        //   It is a multicast update if the line is not in counter mode: the processor
2280        //   takes the lock protecting the Update Table (UPT) to register this transaction.
2281        //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
2282        //   a multi-update request to all owners of the line (but the writer),
2283        //   through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM
2284        //   does not respond to the writing processor, as this response will be sent by
2285        //   the MULTI_ACK FSM when all update responses have been received.
2286        //   It is a broadcast invalidate if the line is in counter mode: The line
2287        //   should be erased in memory cache, and written in XRAM with a PUT transaction,
2288        //   after registration in TRT.
2289        //
2290        // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
2291        //   table (TRT). If a read transaction to the XRAM for this line already exists,
2292        //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
2293        //   the WRITE FSM register a new transaction in TRT, and sends a GET request
2294        //   to the XRAM. If the TRT is full, it releases the lock, and waits.
2295        //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
2296        /////////////////////////////////////////////////////////////////////////////////////
2297
2298        switch (r_write_fsm.read())
2299        {
2300            ////////////////
2301            case WRITE_IDLE:  // copy first word of a write burst in local buffer
2302            {
2303                if (not m_cmd_write_addr_fifo.rok()) break;
2304
2305                // consume a word in the FIFO & write it in the local buffer
2306                cmd_write_fifo_get  = true;
2307                size_t index        = m_x[(addr_t) (m_cmd_write_addr_fifo.read())];
2308
2309                r_write_address     = (addr_t) (m_cmd_write_addr_fifo.read());
2310                r_write_word_index  = index;
2311                r_write_word_count  = 0;
2312                r_write_data[index] = m_cmd_write_data_fifo.read();
2313                r_write_srcid       = m_cmd_write_srcid_fifo.read();
2314                r_write_trdid       = m_cmd_write_trdid_fifo.read();
2315                r_write_pktid       = m_cmd_write_pktid_fifo.read();
2316
2317                // if SC command, get the SC key
2318                if ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
2319                {
2320                    assert(not m_cmd_write_eop_fifo.read() &&
2321                            "MEMC ERROR in WRITE_IDLE state: "
2322                            "invalid packet format for SC command");
2323
2324                    r_write_sc_key = m_cmd_write_data_fifo.read();
2325                }
2326
2327                // initialize the be field for all words
2328                for (size_t word = 0; word < m_words; word++)
2329                {
2330                    if (word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
2331                    else               r_write_be[word] = 0x0;
2332                }
2333
2334                if (m_cmd_write_eop_fifo.read())
2335                {
2336                    r_write_fsm = WRITE_DIR_REQ;
2337                }
2338                else
2339                {
2340                    r_write_fsm = WRITE_NEXT;
2341                }
2342
2343#if DEBUG_MEMC_WRITE
2344                if (m_debug)
2345                {
2346                    std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
2347                        << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
2348                        << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
2349                        << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
2350                }
2351#endif
2352                break;
2353            }
2354            ////////////////
2355            case WRITE_NEXT:  // copy next word of a write burst in local buffer
2356            {
2357                if (not m_cmd_write_addr_fifo.rok()) break;
2358
2359                // check that the next word is in the same cache line
2360                assert((m_nline[(addr_t)(r_write_address.read())] ==
2361                            m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]) &&
2362                        "MEMC ERROR in WRITE_NEXT state: Illegal write burst");
2363
2364                size_t index = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
2365                bool   is_sc = ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC);
2366
2367                // check that SC command has constant address
2368                assert((not is_sc or (index == r_write_word_index)) &&
2369                        "MEMC ERROR in WRITE_NEXT state: "
2370                        "the address must be constant on a SC command");
2371
2372                // check that SC command has two flits
2373                assert((not is_sc or m_cmd_write_eop_fifo.read()) &&
2374                        "MEMC ERROR in WRITE_NEXT state: "
2375                        "invalid packet format for SC command");
2376
2377                // consume a word in the FIFO & write it in the local buffer
2378                cmd_write_fifo_get  = true;
2379
2380                r_write_be[index]   = m_cmd_write_be_fifo.read();
2381                r_write_data[index] = m_cmd_write_data_fifo.read();
2382
2383                // the first flit of a SC command is the reservation key and
2384                // therefore it must not be counted as a data to write
2385                if (not is_sc)
2386                {
2387                    r_write_word_count = r_write_word_count.read() + 1;
2388                }
2389
2390                if (m_cmd_write_eop_fifo.read())
2391                {
2392                    r_write_fsm = WRITE_DIR_REQ;
2393                }
2394
2395#if DEBUG_MEMC_WRITE
2396                if (m_debug)
2397                {
2398                    std::cout << "  <MEMC " << name()
2399                        << " WRITE_NEXT> Write another word in local buffer"
2400                        << std::endl;
2401                }
2402#endif
2403                break;
2404            }
2405            ///////////////////
2406            case WRITE_DIR_REQ: // Get the lock to the directory
2407                                // and access the llsc_global_table
2408            {
2409                if (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE) break;
2410
2411                if ((r_write_pktid.read() & 0x7) == TYPE_SC)
2412                {
2413                    // test address and key match of the SC command on the
2414                    // LL/SC table without removing reservation. The reservation
2415                    // will be erased after in this FSM.
2416                    bool sc_success = m_llsc_table.check(r_write_address.read(),
2417                            r_write_sc_key.read());
2418
2419                    r_write_sc_fail = not sc_success;
2420
2421                    if (not sc_success) r_write_fsm = WRITE_RSP;
2422                    else                r_write_fsm = WRITE_DIR_LOCK;
2423                }
2424                else
2425                {
2426                    // write burst
2427#define L2 soclib::common::uint32_log2
2428                    addr_t min = r_write_address.read();
2429                    addr_t max = r_write_address.read() +
2430                        (r_write_word_count.read() << L2(vci_param_int::B));
2431#undef L2
2432
2433                    m_llsc_table.sw(min, max);
2434
2435                    r_write_fsm = WRITE_DIR_LOCK;
2436                }
2437
2438#if DEBUG_MEMC_WRITE
2439                if (m_debug)
2440                {
2441                    std::cout << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
2442                        << std::endl;
2443                }
2444#endif
2445                break;
2446            }
2447            ////////////////////
2448            case WRITE_DIR_LOCK:     // access directory to check hit/miss
2449            {
2450                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE) and
2451                        "MEMC ERROR in ALLOC_DIR_LOCK state: Bad DIR allocation");
2452
2453                size_t way = 0;
2454                DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
2455
2456                if (entry.valid)    // hit
2457                {
2458                    // copy directory entry in local buffer in case of hit
2459                    r_write_is_cnt    = entry.is_cnt;
2460                    r_write_lock      = entry.lock;
2461                    r_write_tag       = entry.tag;
2462                    r_write_copy      = entry.owner.srcid;
2463                    r_write_copy_inst = entry.owner.inst;
2464                    r_write_count     = entry.count;
2465                    r_write_way       = way;
2466
2467                    r_write_fsm = WRITE_DIR_HIT;
2468                }
2469                else  // miss
2470                {
2471                    r_write_fsm = WRITE_MISS_TRT_LOCK;
2472                }
2473
2474#if DEBUG_MEMC_WRITE
2475                if (m_debug)
2476                {
2477                    std::cout << "  <MEMC " << name() << " WRITE_DIR_LOCK> Check the directory: "
2478                        << " address = " << std::hex << r_write_address.read()
2479                        << " / hit = " << std::dec << entry.valid
2480                        << " / count = " << entry.count
2481                        << " / is_cnt = " << entry.is_cnt ;
2482                    if ((r_write_pktid.read() & 0x7) == TYPE_SC)
2483                    {
2484                        std::cout << " / SC access" << std::endl;
2485                    }
2486                    else
2487                    {
2488                        std::cout << " / SW access" << std::endl;
2489                    }
2490                }
2491#endif
2492                break;
2493            }
2494            ///////////////////
2495            case WRITE_DIR_HIT:    // update the cache directory with Dirty bit
2496            // and update data cache
2497            {
2498                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE) and
2499                        "MEMC ERROR in ALLOC_DIR_HIT state: Bad DIR allocation");
2500
2501                DirectoryEntry entry;
2502                entry.valid       = true;
2503                entry.dirty       = true;
2504                entry.tag         = r_write_tag.read();
2505                entry.is_cnt      = r_write_is_cnt.read();
2506                entry.lock        = r_write_lock.read();
2507                entry.owner.srcid = r_write_copy.read();
2508                entry.owner.inst  = r_write_copy_inst.read();
2509                entry.count       = r_write_count.read();
2510
2511                size_t set = m_y[(addr_t) (r_write_address.read())];
2512                size_t way = r_write_way.read();
2513
2514                // update directory
2515                m_cache_directory.write(set, way, entry);
2516
2517                // write data in the cache
2518                // SC command
2519                if ((r_write_pktid.read() & 0x7) == TYPE_SC)
2520                {
2521                    m_llsc_table.sc(r_write_address.read(),
2522                            r_write_sc_key.read());
2523                }
2524
2525                for (size_t word = 0; word < m_words; word++)
2526                {
2527                    m_cache_data.write(way,
2528                            set,
2529                            word,
2530                            r_write_data[word].read(),
2531                            r_write_be[word].read());
2532                }
2533
2534                {
2535                    // Update L1 caches
2536                    int32_t srcid;
2537                    if ((r_write_pktid.read() & 0x7) == TYPE_SC)
2538                    {
2539                        // We must update all caches, incuding the one responsible for the SC
2540                        // We use a srcid not used by any cache
2541                        srcid = -1;
2542                    }
2543                    else
2544                    {
2545                        srcid = r_write_srcid;
2546                    }
2547
2548                    cc_vcaches_direct_update(r_write_address.read(), r_write_data, r_write_be, srcid);
2549                }
2550
2551                r_write_fsm = WRITE_RSP;
2552
2553#if DEBUG_MEMC_WRITE
2554                if (m_debug)
2555                {
2556                    std::cout << "  <MEMC " << name()
2557                        << " WRITE_DIR_HIT> Write into cache / No coherence transaction" << std::endl;
2558                }
2559#endif
2560                break;
2561            }
2562            ////////////////////
2563            case WRITE_RSP:  // Post a request to TGT_RSP FSM to acknowledge the write
2564            // In order to increase the Write requests throughput,
2565            // we don't wait to return in the IDLE state to consume
2566            // a new request in the write FIFO
2567            {
2568                if (not r_write_to_tgt_rsp_req.read())
2569                {
2570                    // post the request to TGT_RSP_FSM
2571                    r_write_to_tgt_rsp_req     = true;
2572                    r_write_to_tgt_rsp_srcid   = r_write_srcid.read();
2573                    r_write_to_tgt_rsp_trdid   = r_write_trdid.read();
2574                    r_write_to_tgt_rsp_pktid   = r_write_pktid.read();
2575                    r_write_to_tgt_rsp_sc_fail = r_write_sc_fail.read();
2576
2577                    // try to get a new write request from the FIFO
2578                    if (not m_cmd_write_addr_fifo.rok())
2579                    {
2580                        r_write_fsm = WRITE_IDLE;
2581                    }
2582                    else
2583                    {
2584                        // consume a word in the FIFO & write it in the local buffer
2585                        cmd_write_fifo_get  = true;
2586                        size_t index        = m_x[(addr_t) (m_cmd_write_addr_fifo.read())];
2587
2588                        r_write_address     = (addr_t) (m_cmd_write_addr_fifo.read());
2589                        r_write_word_index  = index;
2590                        r_write_word_count  = 0;
2591                        r_write_data[index] = m_cmd_write_data_fifo.read();
2592                        r_write_srcid       = m_cmd_write_srcid_fifo.read();
2593                        r_write_trdid       = m_cmd_write_trdid_fifo.read();
2594                        r_write_pktid       = m_cmd_write_pktid_fifo.read();
2595
2596                        // if SC command, get the SC key
2597                        if ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
2598                        {
2599                            assert(not m_cmd_write_eop_fifo.read() &&
2600                                    "MEMC ERROR in WRITE_RSP state: "
2601                                    "invalid packet format for SC command");
2602
2603                            r_write_sc_key = m_cmd_write_data_fifo.read();
2604                        }
2605
2606                        // initialize the be field for all words
2607                        for (size_t word = 0; word < m_words; word++)
2608                        {
2609                            if (word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
2610                            else               r_write_be[word] = 0x0;
2611                        }
2612
2613                        if (m_cmd_write_eop_fifo.read())
2614                        {
2615                            r_write_fsm = WRITE_DIR_REQ;
2616                        }
2617                        else
2618                        {
2619                            r_write_fsm = WRITE_NEXT;
2620                        }
2621                    }
2622
2623#if DEBUG_MEMC_WRITE
2624                    if (m_debug)
2625                    {
2626                        std::cout << "  <MEMC " << name() << " WRITE_RSP> Post a request to TGT_RSP FSM"
2627                            << " : rsrcid = " << std::hex << r_write_srcid.read() << std::endl;
2628                        if (m_cmd_write_addr_fifo.rok())
2629                        {
2630                            std::cout << "                    New Write request: "
2631                                << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
2632                                << " / address = " << m_cmd_write_addr_fifo.read()
2633                                << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
2634                        }
2635                    }
2636#endif
2637                }
2638                break;
2639            }
2640
2641            /////////////////////////
2642            case WRITE_MISS_TRT_LOCK: // Miss : check Transaction Table
2643            {
2644                if (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2645                {
2646
2647#if DEBUG_MEMC_WRITE
2648                    if (m_debug)
2649                    {
2650                        std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
2651                    }
2652#endif
2653                    size_t hit_index = 0;
2654                    size_t wok_index = 0;
2655                    addr_t addr = (addr_t) r_write_address.read();
2656                    bool   hit_read  = m_trt.hit_read(m_nline[addr], hit_index);
2657                    bool   hit_write = m_trt.hit_write(m_nline[addr]);
2658                    bool   wok       = not m_trt.full(wok_index);
2659
2660                    // wait an empty entry in TRT
2661                    if (not hit_read and (not wok or hit_write))
2662                    {
2663                        r_write_fsm = WRITE_WAIT;
2664                        m_cpt_trt_full++;
2665
2666                        break;
2667                    }
2668
2669                    if ((r_write_pktid.read() & 0x7) == TYPE_SC)
2670                    {
2671                        m_llsc_table.sc(r_write_address.read(),
2672                                r_write_sc_key.read());
2673                    }
2674
2675                    // register the modified data in TRT
2676                    if (hit_read)
2677                    {
2678                        r_write_trt_index = hit_index;
2679                        r_write_fsm       = WRITE_MISS_TRT_DATA;
2680                        m_cpt_write_miss++;
2681                        break;
2682                    }
2683
2684                    // set a new entry in TRT
2685                    if (wok and not hit_write)
2686                    {
2687                        r_write_trt_index = wok_index;
2688                        r_write_fsm       = WRITE_MISS_TRT_SET;
2689                        m_cpt_write_miss++;
2690                        break;
2691                    }
2692
2693                    assert(false && "VCI_MEM_CACHE ERROR: this part must not be reached");
2694                }
2695                break;
2696            }
2697
2698            ////////////////
2699            case WRITE_WAIT:  // release the locks protecting the shared ressources
2700            {
2701
2702#if DEBUG_MEMC_WRITE
2703                if (m_debug)
2704                {
2705                    std::cout << "  <MEMC " << name() << " WRITE_WAIT> Releases the locks before retry" << std::endl;
2706                }
2707#endif
2708                r_write_fsm = WRITE_DIR_REQ;
2709                break;
2710            }
2711
2712            ////////////////////////
2713            case WRITE_MISS_TRT_SET:  // register a new transaction in TRT (Write Buffer)
2714            {
2715                if (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2716                {
2717                    std::vector<be_t> be_vector;
2718                    std::vector<data_t> data_vector;
2719                    be_vector.clear();
2720                    data_vector.clear();
2721                    for (size_t i = 0; i < m_words; i++)
2722                    {
2723                        be_vector.push_back(r_write_be[i]);
2724                        data_vector.push_back(r_write_data[i]);
2725                    }
2726                    m_trt.set(r_write_trt_index.read(),
2727                            true,     // read request to XRAM
2728                            m_nline[(addr_t) (r_write_address.read())],
2729                            r_write_srcid.read(),
2730                            r_write_trdid.read(),
2731                            r_write_pktid.read(),
2732                            false,      // not a processor read
2733                            0,        // not a single word
2734                            0,            // word index
2735                            be_vector,
2736                            data_vector);
2737                    r_write_fsm = WRITE_MISS_XRAM_REQ;
2738
2739#if DEBUG_MEMC_WRITE
2740                    if (m_debug)
2741                    {
2742                        std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
2743                    }
2744#endif
2745                }
2746                break;
2747            }
2748
2749            /////////////////////////
2750            case WRITE_MISS_TRT_DATA: // update an entry in TRT (used as a Write Buffer)
2751            {
2752                if (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2753                {
2754                    std::vector<be_t> be_vector;
2755                    std::vector<data_t> data_vector;
2756                    be_vector.clear();
2757                    data_vector.clear();
2758                    for (size_t i = 0; i < m_words; i++)
2759                    {
2760                        be_vector.push_back(r_write_be[i]);
2761                        data_vector.push_back(r_write_data[i]);
2762                    }
2763                    m_trt.write_data_mask(r_write_trt_index.read(),
2764                            be_vector,
2765                            data_vector);
2766                    r_write_fsm = WRITE_RSP;
2767
2768#if DEBUG_MEMC_WRITE
2769                    if (m_debug)
2770                    {
2771                        std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2772                    }
2773#endif
2774                }
2775                break;
2776            }
2777            /////////////////////////
2778            case WRITE_MISS_XRAM_REQ: // send a GET request to IXR_CMD FSM
2779            {
2780                if (not r_write_to_ixr_cmd_req.read())
2781                {
2782                    r_write_to_ixr_cmd_req   = true;
2783                    r_write_to_ixr_cmd_index = r_write_trt_index.read();
2784                    r_write_fsm              = WRITE_RSP;
2785
2786#if DEBUG_MEMC_WRITE
2787                    if (m_debug)
2788                    {
2789                        std::cout << "  <MEMC " << name()
2790                            << " WRITE_MISS_XRAM_REQ> Post a GET request to the"
2791                            << " IXR_CMD FSM" << std::endl;
2792                    }
2793#endif
2794                }
2795                break;
2796            }
2797        } // end switch r_write_fsm
2798
2799        ///////////////////////////////////////////////////////////////////////
2800        //    IXR_CMD FSM
2801        ///////////////////////////////////////////////////////////////////////
2802        // The IXR_CMD fsm controls the command packets to the XRAM :
2803        // It handles requests from 5 FSMs with a round-robin priority:
2804        //  READ > WRITE > CAS > XRAM_RSP > CONFIG
2805        //
2806        // - It sends a single flit VCI read to the XRAM in case of
2807        //   GET request posted by the READ, WRITE or CAS FSMs.
2808        // - It sends a multi-flit VCI write in case of PUT request posted by
2809        //   the XRAM_RSP, WRITE, CAS, or CONFIG FSMs.
2810        //
2811        // For each client, there is three steps:
2812        // - IXR_CMD_*_IDLE : round-robin allocation to a client
2813        // - IXR_CMD_*_TRT  : access to TRT for address and data
2814        // - IXR_CMD_*_SEND : send the PUT or GET VCI command
2815        //
2816        // The address and data to be written (for a PUT) are stored in TRT.
2817        // The trdid field contains always the TRT entry index.
2818        ////////////////////////////////////////////////////////////////////////
2819
2820        switch (r_ixr_cmd_fsm.read())
2821        {
2822            ///////////////////////
2823            case IXR_CMD_READ_IDLE:
2824            {
2825                if      (r_write_to_ixr_cmd_req.read())      r_ixr_cmd_fsm = IXR_CMD_WRITE_TRT;
2826                else if (r_cas_to_ixr_cmd_req.read())        r_ixr_cmd_fsm = IXR_CMD_CAS_TRT;
2827                else if (r_xram_rsp_to_ixr_cmd_req.read())   r_ixr_cmd_fsm = IXR_CMD_XRAM_TRT;
2828                else if (r_config_to_ixr_cmd_req.read())     r_ixr_cmd_fsm = IXR_CMD_CONFIG_TRT;
2829                else if (r_read_to_ixr_cmd_req.read())       r_ixr_cmd_fsm = IXR_CMD_READ_TRT;
2830                break;
2831            }
2832            ////////////////////////
2833            case IXR_CMD_WRITE_IDLE:
2834            {
2835                if      (r_cas_to_ixr_cmd_req.read())        r_ixr_cmd_fsm = IXR_CMD_CAS_TRT;
2836                else if (r_xram_rsp_to_ixr_cmd_req.read())   r_ixr_cmd_fsm = IXR_CMD_XRAM_TRT;
2837                else if (r_config_to_ixr_cmd_req.read())     r_ixr_cmd_fsm = IXR_CMD_CONFIG_TRT;
2838                else if (r_read_to_ixr_cmd_req.read())       r_ixr_cmd_fsm = IXR_CMD_READ_TRT;
2839                else if (r_write_to_ixr_cmd_req.read())      r_ixr_cmd_fsm = IXR_CMD_WRITE_TRT;
2840                break;
2841            }
2842            //////////////////////
2843            case IXR_CMD_CAS_IDLE:
2844            {
2845                if      (r_xram_rsp_to_ixr_cmd_req.read())   r_ixr_cmd_fsm = IXR_CMD_XRAM_TRT;
2846                else if (r_config_to_ixr_cmd_req.read())     r_ixr_cmd_fsm = IXR_CMD_CONFIG_TRT;
2847                else if (r_read_to_ixr_cmd_req.read())       r_ixr_cmd_fsm = IXR_CMD_READ_TRT;
2848                else if (r_write_to_ixr_cmd_req.read())      r_ixr_cmd_fsm = IXR_CMD_WRITE_TRT;
2849                else if (r_cas_to_ixr_cmd_req.read())        r_ixr_cmd_fsm = IXR_CMD_CAS_TRT;
2850                break;
2851            }
2852            ///////////////////////
2853            case IXR_CMD_XRAM_IDLE:
2854            {
2855                if      (r_config_to_ixr_cmd_req.read())     r_ixr_cmd_fsm = IXR_CMD_CONFIG_TRT;
2856                else if (r_read_to_ixr_cmd_req.read())       r_ixr_cmd_fsm = IXR_CMD_READ_TRT;
2857                else if (r_write_to_ixr_cmd_req.read())      r_ixr_cmd_fsm = IXR_CMD_WRITE_TRT;
2858                else if (r_cas_to_ixr_cmd_req.read())        r_ixr_cmd_fsm = IXR_CMD_CAS_TRT;
2859                else if (r_xram_rsp_to_ixr_cmd_req.read())   r_ixr_cmd_fsm = IXR_CMD_XRAM_TRT;
2860                break;
2861            }
2862            /////////////////////////
2863            case IXR_CMD_CONFIG_IDLE:
2864            {
2865                if      (r_read_to_ixr_cmd_req.read())     r_ixr_cmd_fsm = IXR_CMD_READ_TRT;
2866                else if (r_write_to_ixr_cmd_req.read())    r_ixr_cmd_fsm = IXR_CMD_WRITE_TRT;
2867                else if (r_cas_to_ixr_cmd_req.read())      r_ixr_cmd_fsm = IXR_CMD_CAS_TRT;
2868                else if (r_xram_rsp_to_ixr_cmd_req.read()) r_ixr_cmd_fsm = IXR_CMD_XRAM_TRT;
2869                else if (r_config_to_ixr_cmd_req.read())   r_ixr_cmd_fsm = IXR_CMD_CONFIG_TRT;
2870                break;
2871            }
2872
2873            //////////////////////
2874            case IXR_CMD_READ_TRT:       // access TRT for a GET
2875            {
2876                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_CMD)
2877                {
2878                    TransactionTabEntry entry = m_trt.read(r_read_to_ixr_cmd_index.read());
2879                    r_ixr_cmd_address = entry.nline * (m_words << 2);
2880                    r_ixr_cmd_trdid   = r_read_to_ixr_cmd_index.read();
2881                    r_ixr_cmd_get     = true;
2882                    r_ixr_cmd_word    = 0;
2883                    r_ixr_cmd_fsm     = IXR_CMD_READ_SEND;
2884
2885#if DEBUG_MEMC_IXR_CMD
2886                    if (m_debug)
2887                    {
2888                        std::cout << "  <MEMC " << name() << " IXR_CMD_READ_TRT> TRT access"
2889                            << " index = " << std::dec << r_read_to_ixr_cmd_index.read()
2890                            << " / address = " << std::hex << (entry.nline * (m_words << 2)) << std::endl;
2891                    }
2892#endif
2893                }
2894                break;
2895            }
2896            ///////////////////////
2897            case IXR_CMD_WRITE_TRT: // access TRT for a PUT or a GET
2898            {
2899                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_CMD)
2900                {
2901                    TransactionTabEntry entry = m_trt.read(r_write_to_ixr_cmd_index.read());
2902                    r_ixr_cmd_address = entry.nline * (m_words << 2);
2903                    r_ixr_cmd_trdid   = r_write_to_ixr_cmd_index.read();
2904                    r_ixr_cmd_get     = entry.xram_read;
2905                    r_ixr_cmd_word    = 0;
2906                    r_ixr_cmd_fsm     = IXR_CMD_WRITE_SEND;
2907
2908                    // Read data from TRT if PUT transaction
2909                    if (not entry.xram_read)
2910                    {
2911                        for (size_t i = 0; i < m_words; i++)
2912                        {
2913                            r_ixr_cmd_wdata[i] = entry.wdata[i];
2914                        }
2915                    }
2916
2917#if DEBUG_MEMC_IXR_CMD
2918                    if (m_debug)
2919                    {
2920                        std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE_TRT> TRT access"
2921                            << " index = " << std::dec << r_write_to_ixr_cmd_index.read()
2922                            << " / address = " << std::hex << (entry.nline * (m_words << 2)) << std::endl;
2923                    }
2924#endif
2925                }
2926                break;
2927            }
2928            /////////////////////
2929            case IXR_CMD_CAS_TRT:       // access TRT for a PUT or a GET
2930            {
2931                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_CMD)
2932                {
2933                    TransactionTabEntry entry = m_trt.read(r_cas_to_ixr_cmd_index.read());
2934                    r_ixr_cmd_address = entry.nline * (m_words << 2);
2935                    r_ixr_cmd_trdid   = r_cas_to_ixr_cmd_index.read();
2936                    r_ixr_cmd_get     = entry.xram_read;
2937                    r_ixr_cmd_word    = 0;
2938                    r_ixr_cmd_fsm     = IXR_CMD_CAS_SEND;
2939
2940                    // Read data from TRT if PUT transaction
2941                    if (not entry.xram_read)
2942                    {
2943                        for (size_t i = 0; i < m_words; i++)
2944                        {
2945                            r_ixr_cmd_wdata[i] = entry.wdata[i];
2946                        }
2947                    }
2948
2949#if DEBUG_MEMC_IXR_CMD
2950                    if (m_debug)
2951                    {
2952                        std::cout << "  <MEMC " << name() << " IXR_CMD_CAS_TRT> TRT access"
2953                            << " index = " << std::dec << r_cas_to_ixr_cmd_index.read()
2954                            << " / address = " << std::hex << (entry.nline * (m_words << 2)) << std::endl;
2955                    }
2956#endif
2957                }
2958                break;
2959            }
2960            //////////////////////
2961            case IXR_CMD_XRAM_TRT:       // access TRT for a PUT
2962            {
2963                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_CMD)
2964                {
2965                    TransactionTabEntry entry = m_trt.read(r_xram_rsp_to_ixr_cmd_index.read());
2966                    r_ixr_cmd_address = entry.nline * (m_words << 2);
2967                    r_ixr_cmd_trdid   = r_xram_rsp_to_ixr_cmd_index.read();
2968                    r_ixr_cmd_get     = false;
2969                    r_ixr_cmd_word    = 0;
2970                    r_ixr_cmd_fsm     = IXR_CMD_XRAM_SEND;
2971                    for (size_t i = 0; i < m_words; i++)
2972                    {
2973                        r_ixr_cmd_wdata[i] = entry.wdata[i];
2974                    }
2975
2976#if DEBUG_MEMC_IXR_CMD
2977                    if (m_debug)
2978                    {
2979                        std::cout << "  <MEMC " << name() << " IXR_CMD_XRAM_TRT> TRT access"
2980                            << " index = " << std::dec << r_xram_rsp_to_ixr_cmd_index.read()
2981                            << " / address = " << std::hex << (entry.nline * (m_words << 2)) << std::endl;
2982                    }
2983#endif
2984                }
2985                break;
2986            }
2987            ////////////////////////
2988            case IXR_CMD_CONFIG_TRT:       // access TRT for a PUT
2989            {
2990                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_CMD)
2991                {
2992                    TransactionTabEntry entry = m_trt.read(r_config_to_ixr_cmd_index.read());
2993                    r_ixr_cmd_address = entry.nline * (m_words << 2);
2994                    r_ixr_cmd_trdid   = r_config_to_ixr_cmd_index.read();
2995                    r_ixr_cmd_get     = false;
2996                    r_ixr_cmd_word    = 0;
2997                    r_ixr_cmd_fsm     = IXR_CMD_CONFIG_SEND;
2998                    for (size_t i = 0; i < m_words; i++)
2999                    {
3000                        r_ixr_cmd_wdata[i] = entry.wdata[i];
3001                    }
3002
3003#if DEBUG_MEMC_IXR_CMD
3004                    if (m_debug)
3005                    {
3006                        std::cout << "  <MEMC " << name() << " IXR_CMD_CONFIG_TRT> TRT access"
3007                            << " index = " << std::dec << r_config_to_ixr_cmd_index.read()
3008                            << " / address = " << std::hex << (entry.nline * (m_words << 2)) << std::endl;
3009                    }
3010#endif
3011                }
3012                break;
3013            }
3014
3015            ///////////////////////
3016            case IXR_CMD_READ_SEND:      // send a get from READ FSM
3017            {
3018                if (p_vci_ixr.cmdack)
3019                {
3020                    r_ixr_cmd_fsm         = IXR_CMD_READ_IDLE;
3021                    r_read_to_ixr_cmd_req = false;
3022
3023#if DEBUG_MEMC_IXR_CMD
3024                    if (m_debug)
3025                    {
3026                        std::cout << "  <MEMC " << name() << " IXR_CMD_READ_SEND> GET request:" << std::hex
3027                            << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read()<<2) << std::endl;
3028                    }
3029#endif
3030                }
3031                break;
3032            }
3033            ////////////////////////
3034            case IXR_CMD_WRITE_SEND:     // send a put or get from WRITE FSM
3035            {
3036                if (p_vci_ixr.cmdack)
3037                {
3038                    if (not r_ixr_cmd_get.read())   // PUT
3039                    {
3040                        if (r_ixr_cmd_word.read() == (m_words - 2))
3041                        {
3042                            r_ixr_cmd_fsm          = IXR_CMD_WRITE_IDLE;
3043                            r_write_to_ixr_cmd_req = false;
3044                        }
3045                        else
3046                        {
3047                            r_ixr_cmd_word = r_ixr_cmd_word.read() + 2;
3048                        }
3049
3050#if DEBUG_MEMC_IXR_CMD
3051                        if (m_debug)
3052                        {
3053                            std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE_SEND> PUT request:" << std::hex
3054                                << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read()<<2) << std::endl;
3055                        }
3056#endif
3057                    }
3058                    else // GET
3059                    {
3060                        r_ixr_cmd_fsm          = IXR_CMD_WRITE_IDLE;
3061                        r_write_to_ixr_cmd_req = false;
3062
3063#if DEBUG_MEMC_IXR_CMD
3064                        if (m_debug)
3065                        {
3066                            std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE_SEND> GET request:" << std::hex
3067                                << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read()<<2) << std::endl;
3068                        }
3069#endif
3070                    }
3071                }
3072                break;
3073            }
3074            //////////////////////
3075            case IXR_CMD_CAS_SEND: // send a put or get command from CAS FSM
3076            {
3077                if (p_vci_ixr.cmdack)
3078                {
3079                    if (not r_ixr_cmd_get.read()) // PUT
3080                    {
3081                        if (r_ixr_cmd_word.read() == (m_words - 2))
3082                        {
3083                            r_ixr_cmd_fsm        = IXR_CMD_CAS_IDLE;
3084                            r_cas_to_ixr_cmd_req = false;
3085                        }
3086                        else
3087                        {
3088                            r_ixr_cmd_word = r_ixr_cmd_word.read() + 2;
3089                        }
3090
3091#if DEBUG_MEMC_IXR_CMD
3092                        if (m_debug)
3093                        {
3094                            std::cout << "  <MEMC " << name() << " IXR_CMD_CAS_SEND> PUT request:" << std::hex
3095                                << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read() << 2) << std::endl;
3096                        }
3097#endif
3098                    }
3099                    else // GET
3100                    {
3101                        r_ixr_cmd_fsm        = IXR_CMD_CAS_IDLE;
3102                        r_cas_to_ixr_cmd_req = false;
3103
3104#if DEBUG_MEMC_IXR_CMD
3105                        if (m_debug)
3106                        {
3107                            std::cout << "  <MEMC " << name() << " IXR_CMD_CAS_SEND> GET request:" << std::hex
3108                                << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read() << 2) << std::endl;
3109                        }
3110#endif
3111                    }
3112                }
3113                break;
3114            }
3115            ///////////////////////
3116            case IXR_CMD_XRAM_SEND: // send a put from XRAM_RSP FSM
3117            {
3118                if (p_vci_ixr.cmdack.read())
3119                {
3120                    if (r_ixr_cmd_word.read() == (m_words - 2))
3121                    {
3122                        r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
3123                        r_xram_rsp_to_ixr_cmd_req = false;
3124                    }
3125                    else
3126                    {
3127                        r_ixr_cmd_word = r_ixr_cmd_word.read() + 2;
3128                    }
3129
3130#if DEBUG_MEMC_IXR_CMD
3131                    if (m_debug)
3132                    {
3133                        std::cout << "  <MEMC " << name() << " IXR_CMD_XRAM_SEND> PUT request:" << std::hex
3134                            << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read() << 2) << std::endl;
3135                    }
3136#endif
3137                }
3138                break;
3139            }
3140            /////////////////////////
3141            case IXR_CMD_CONFIG_SEND:     // send a put from CONFIG FSM
3142            {
3143                if (p_vci_ixr.cmdack.read())
3144                {
3145                    if (r_ixr_cmd_word.read() == (m_words - 2))
3146                    {
3147                        r_ixr_cmd_fsm = IXR_CMD_CONFIG_IDLE;
3148                        r_config_to_ixr_cmd_req = false;
3149                    }
3150                    else
3151                    {
3152                        r_ixr_cmd_word = r_ixr_cmd_word.read() + 2;
3153                    }
3154
3155#if DEBUG_MEMC_IXR_CMD
3156                    if (m_debug)
3157                    {
3158                        std::cout << "  <MEMC " << name() << " IXR_CMD_CONFIG_SEND> PUT request:" << std::hex
3159                            << " address = " << r_ixr_cmd_address.read() + (r_ixr_cmd_word.read()<<2) << std::endl;
3160                    }
3161#endif
3162                }
3163                break;
3164            }
3165        } // end switch r_ixr_cmd_fsm
3166
3167        ////////////////////////////////////////////////////////////////////////////
3168        //                IXR_RSP FSM
3169        ////////////////////////////////////////////////////////////////////////////
3170        // The IXR_RSP FSM receives the response packets from the XRAM,
3171        // for both PUT transaction, and GET transaction.
3172        //
3173        // - A response to a PUT request is a single-cell VCI packet.
3174        // The TRT index is contained in the RTRDID field.
3175        // The FSM takes the lock protecting the TRT, and the corresponding
3176        // entry is erased. If an acknowledge was required (in case of software SYNC)
3177        // the r_config_rsp_lines counter is decremented.
3178        //
3179        // - A response to a GET request is a multi-cell VCI packet.
3180        // The TRT index is contained in the RTRDID field.
3181        // The N cells contain the N words of the cache line in the RDATA field.
3182        // The FSM takes the lock protecting the TRT to store the line in the TRT
3183        // (taking into account the write requests already stored in the TRT).
3184        // When the line is completely written, the r_ixr_rsp_to_xram_rsp_rok[index]
3185        // signal is set to inform the XRAM_RSP FSM.
3186        ///////////////////////////////////////////////////////////////////////////////
3187
3188        switch (r_ixr_rsp_fsm.read())
3189        {
3190            //////////////////
3191            case IXR_RSP_IDLE:  // test transaction type: PUT/GET
3192            {
3193                if (p_vci_ixr.rspval.read())
3194                {
3195                    r_ixr_rsp_cpt       = 0;
3196                    r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
3197
3198                    if (p_vci_ixr.reop.read() and not
3199                            p_vci_ixr.rerror.read())   // PUT
3200                    {
3201                        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
3202
3203#if DEBUG_MEMC_IXR_RSP
3204                        if (m_debug)
3205                            std::cout << "  <MEMC " << name()
3206                                << " IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
3207#endif
3208                    }
3209                    else // GET
3210                    {
3211                        r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
3212
3213#if DEBUG_MEMC_IXR_RSP
3214                        if (m_debug)
3215                        {
3216                            std::cout << "  <MEMC " << name()
3217                                << " IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
3218                        }
3219#endif
3220                    }
3221                }
3222                break;
3223            }
3224            ////////////////////////
3225            case IXR_RSP_TRT_ERASE:   // erase the entry in the TRT
3226                                      // decrease the line counter if config request
3227            {
3228                if (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP)
3229                {
3230                    size_t index = r_ixr_rsp_trt_index.read();
3231
3232                    if (m_trt.is_config(index)) // it's a config transaction
3233                    {
3234                        config_rsp_lines_ixr_rsp_decr = true;
3235                    }
3236
3237                    m_trt.erase(index);
3238                    r_ixr_rsp_fsm = IXR_RSP_IDLE;
3239
3240#if DEBUG_MEMC_IXR_RSP
3241                    if (m_debug)
3242                    {
3243                        std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_ERASE> Erase TRT entry "
3244                            << r_ixr_rsp_trt_index.read() << std::endl;
3245                    }
3246#endif
3247                }
3248                break;
3249            }
3250            //////////////////////
3251            case IXR_RSP_TRT_READ: // write a 64 bits data word in TRT
3252            {
3253                if ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) and p_vci_ixr.rspval)
3254                {
3255                    size_t      index  = r_ixr_rsp_trt_index.read();
3256                    size_t      word   = r_ixr_rsp_cpt.read();
3257                    bool        eop    = p_vci_ixr.reop.read();
3258                    wide_data_t data   = p_vci_ixr.rdata.read();
3259                    bool        rerror = ((p_vci_ixr.rerror.read() & 0x1) == 1);
3260
3261                    assert(((eop == (word == (m_words - 2))) or rerror) and
3262                    "MEMC ERROR in IXR_RSP_TRT_READ state : invalid response from XRAM");
3263
3264                    m_trt.write_rsp(index, word, data, rerror);
3265
3266                    r_ixr_rsp_cpt = word + 2;
3267
3268                    if (eop)
3269                    {
3270                        r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()] = true;
3271                        r_ixr_rsp_fsm = IXR_RSP_IDLE;
3272                    }
3273
3274#if DEBUG_MEMC_IXR_RSP
3275                    if (m_debug)
3276                    {
3277                        std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_READ> Writing 2 words in TRT : "
3278                            << " index = " << std::dec << index
3279                            << " / word = " << word
3280                            << " / data = " << std::hex << data << std::endl;
3281                    }
3282#endif
3283                }
3284                break;
3285            }
3286        } // end swich r_ixr_rsp_fsm
3287
3288        ////////////////////////////////////////////////////////////////////////////
3289        //                XRAM_RSP FSM
3290        ////////////////////////////////////////////////////////////////////////////
3291        // The XRAM_RSP FSM handles the incoming cache lines after an XRAM GET.
3292        // The cache line has been written in the TRT by the IXR_CMD_FSM.
3293        // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
3294        // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i] as the number
3295        // of entries in the TRT, that are handled with a round-robin priority...
3296        //
3297        // The FSM takes the lock protecting TRT, and the lock protecting DIR.
3298        // The selected TRT entry is copied in the local buffer r_xram_rsp_trt_buf.
3299        // It selects a cache slot and save the victim line in another local buffer
3300        // r_xram_rsp_victim_***.
3301        // It writes the line extracted from TRT in the cache.
3302        // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
3303        // FSM to return the cache line to the registered processor.
3304        // If there is no empty slot, a victim line is evicted, and
3305        // invalidate requests are sent to the L1 caches containing copies.
3306        // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
3307        // FSM to save the victim line to the XRAM, and register the write transaction
3308        // in the TRT (using the entry previously used by the read transaction).
3309        ///////////////////////////////////////////////////////////////////////////////
3310
3311        switch (r_xram_rsp_fsm.read())
3312        {
3313            ///////////////////
3314            case XRAM_RSP_IDLE: // scan the XRAM responses / select a TRT index (round robin)
3315            {
3316                size_t old = r_xram_rsp_trt_index.read();
3317                size_t lines = m_trt_lines;
3318                for (size_t i = 0; i < lines; i++)
3319                {
3320                    size_t index = (i + old + 1) % lines;
3321                    if (r_ixr_rsp_to_xram_rsp_rok[index])
3322                    {
3323                        r_xram_rsp_trt_index             = index;
3324                        r_ixr_rsp_to_xram_rsp_rok[index] = false;
3325                        r_xram_rsp_fsm                   = XRAM_RSP_DIR_LOCK;
3326
3327#if DEBUG_MEMC_XRAM_RSP
3328                        if (m_debug)
3329                        {
3330                            std::cout << "  <MEMC " << name() << " XRAM_RSP_IDLE>"
3331                                << " Available cache line in TRT:"
3332                                << " index = " << std::dec << index << std::endl;
3333                        }
3334#endif
3335                        break;
3336                    }
3337                }
3338                break;
3339            }
3340            ///////////////////////
3341            case XRAM_RSP_DIR_LOCK: // Takes the DIR lock and the TRT lock
3342            // Copy the TRT entry in a local buffer
3343            {
3344                if ((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) and
3345                        (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP))
3346                {
3347                    // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
3348                    size_t index = r_xram_rsp_trt_index.read();
3349                    r_xram_rsp_trt_buf.copy(m_trt.read(index));
3350                    r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
3351
3352#if DEBUG_MEMC_XRAM_RSP
3353                    if (m_debug)
3354                    {
3355                        std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_LOCK>"
3356                            << " Get access to DIR and TRT" << std::endl;
3357                    }
3358#endif
3359                }
3360                break;
3361            }
3362            ///////////////////////
3363            case XRAM_RSP_TRT_COPY: // Select a victim cache line
3364            // and copy it in a local buffer
3365            {
3366                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) and
3367                        "MEMC ERROR in XRAM_RSP_TRT_COPY state: Bad DIR allocation");
3368
3369                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) and
3370                        "MEMC ERROR in XRAM_RSP_TRT_COPY state: Bad TRT allocation");
3371
3372                // selects & extracts a victim line from cache
3373                size_t way = 0;
3374                size_t set = m_y[(addr_t) (r_xram_rsp_trt_buf.nline * m_words * 4)];
3375
3376                DirectoryEntry victim(m_cache_directory.select(set, way));
3377
3378                // copy the victim line in a local buffer (both data dir)
3379                m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
3380
3381                r_xram_rsp_victim_copy      = victim.owner.srcid;
3382                r_xram_rsp_victim_copy_inst = victim.owner.inst;
3383                r_xram_rsp_victim_count     = victim.count;
3384                r_xram_rsp_victim_way       = way;
3385                r_xram_rsp_victim_set       = set;
3386                r_xram_rsp_victim_nline     = (addr_t) victim.tag * m_sets + set;
3387                r_xram_rsp_victim_is_cnt    = victim.is_cnt;
3388                r_xram_rsp_victim_dirty     = victim.dirty;
3389
3390                if (not r_xram_rsp_trt_buf.rerror) r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
3391                else                               r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;
3392
3393#if DEBUG_MEMC_XRAM_RSP
3394                if (m_debug)
3395                {
3396                    std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_COPY>"
3397                        << " Select a victim slot: "
3398                        << " way = " << std::dec << way
3399                        << " / set = " << set << std::endl;
3400                }
3401#endif
3402                break;
3403            }
3404            ///////////////////////
3405            case XRAM_RSP_DIR_UPDT:   // updates the cache (both data & directory),
3406            // erases the TRT entry if victim not dirty
3407            {
3408                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) and
3409                        "MEMC ERROR in XRAM_RSP_DIR_UPDT state: Bad DIR allocation");
3410
3411                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) and
3412                        "MEMC ERROR in XRAM_RSP_DIR_UPDT state: Bad TRT allocation");
3413
3414                // check if this is an instruction read, this means pktid is either
3415                // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
3416                // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3417                bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) and r_xram_rsp_trt_buf.proc_read;
3418
3419                // check if this is a cached read, this means pktid is either
3420                // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
3421                // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3422                bool cached_read = (r_xram_rsp_trt_buf.pktid & 0x1) and r_xram_rsp_trt_buf.proc_read;
3423
3424                bool dirty = false;
3425
3426                // update cache data
3427                size_t set = r_xram_rsp_victim_set.read();
3428                size_t way = r_xram_rsp_victim_way.read();
3429
3430                for (size_t word = 0; word < m_words; word++)
3431                {
3432                    m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
3433                    dirty = dirty or (r_xram_rsp_trt_buf.wdata_be[word] != 0);
3434                   
3435                    // Update L1 Caches
3436                    // Note:
3437                    // This case cannot happen in dhccp because caches are inclusive
3438                    // Here the L1 caches are not inclusive, so they can contain a copy
3439                    if (r_xram_rsp_trt_buf.wdata_be[word] != 0)
3440                    {
3441                        addr_t addr = r_xram_rsp_trt_buf.nline * (m_words << 2) + (word << 2);
3442                        cc_vcaches_direct_update(addr,
3443                                r_xram_rsp_trt_buf.wdata[word],
3444                                r_xram_rsp_trt_buf.wdata_be[word],
3445                                r_xram_rsp_trt_buf.srcid);
3446
3447                    }
3448                }
3449
3450                // update cache directory
3451                DirectoryEntry entry;
3452                entry.valid  = true;
3453                entry.is_cnt = false;
3454                entry.lock   = false;
3455                entry.dirty  = dirty;
3456                entry.tag    = r_xram_rsp_trt_buf.nline / m_sets;
3457                if (cached_read)
3458                {
3459                    entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
3460                    entry.owner.inst  = inst_read;
3461                    entry.count       = 1;
3462                }
3463                else
3464                {
3465                    entry.owner.srcid = 0;
3466                    entry.owner.inst  = 0;
3467                    entry.count       = 0;
3468                }
3469                m_cache_directory.write(set, way, entry);
3470
3471#if DEBUG_MEMC_XRAM_RSP
3472                if (m_debug)
3473                {
3474                    std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_UPDT>"
3475                        << " Cache update: "
3476                        << " way = " << std::dec << way
3477                        << " / set = " << set
3478                        << " / owner_id = " << std::hex << entry.owner.srcid
3479                        << " / owner_ins = " << std::dec << entry.owner.inst
3480                        << " / count = " << entry.count
3481                        << " / is_cnt = " << entry.is_cnt << std::endl;
3482                }
3483#endif
3484
3485                // If the victim is not dirty, we don't need to reuse the TRT entry for
3486                // another PUT transaction, and we can erase the TRT entry
3487                if (not r_xram_rsp_victim_dirty.read())
3488                {
3489                    m_trt.erase(r_xram_rsp_trt_index.read());
3490                }
3491
3492                // Next state
3493                if (r_xram_rsp_victim_dirty.read())    r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
3494                else if (r_xram_rsp_trt_buf.proc_read) r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3495                else                                   r_xram_rsp_fsm = XRAM_RSP_IDLE;
3496                break;
3497            }
3498            ////////////////////////
3499            case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (PUT to XRAM) if the victim is dirty
3500            {
3501                if (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP)
3502                {
3503                    std::vector<data_t> data_vector;
3504                    data_vector.clear();
3505                    for (size_t i = 0; i < m_words; i++)
3506                    {
3507                        data_vector.push_back(r_xram_rsp_victim_data[i].read());
3508                    }
3509                    m_trt.set(r_xram_rsp_trt_index.read(),
3510                            false,                          // PUT
3511                            r_xram_rsp_victim_nline.read(), // line index
3512                            0,                              // unused
3513                            0,                              // unused
3514                            0,                              // unused
3515                            false,                          // not proc_read
3516                            0,                              // unused
3517                            0,                              // unused
3518                            std::vector<be_t>(m_words,0xF),
3519                            data_vector);
3520
3521#if DEBUG_MEMC_XRAM_RSP
3522                    if (m_debug)
3523                    {
3524                        std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_DIRTY>"
3525                            << " Set TRT entry for the put transaction"
3526                            << " / address = " << (r_xram_rsp_victim_nline.read() * m_words * 4) << std::endl;
3527                    }
3528#endif
3529                    if (r_xram_rsp_trt_buf.proc_read) r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3530                    else                              r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3531                }
3532                break;
3533            }
3534            //////////////////////
3535            case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
3536            {
3537                if (not r_xram_rsp_to_tgt_rsp_req.read())
3538                {
3539                    r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
3540                    r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
3541                    r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
3542                    for (size_t i = 0; i < m_words; i++)
3543                    {
3544                        r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3545                    }
3546                    r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3547                    r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3548                    r_xram_rsp_to_tgt_rsp_ll_key = r_xram_rsp_trt_buf.ll_key;
3549                    r_xram_rsp_to_tgt_rsp_rerror = false;
3550                    r_xram_rsp_to_tgt_rsp_req    = true;
3551
3552                    if (r_xram_rsp_victim_dirty.read()) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3553                    else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3554
3555#if DEBUG_MEMC_XRAM_RSP
3556                    if (m_debug)
3557                    {
3558                        std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_RSP>"
3559                            << " Request the TGT_RSP FSM to return data:"
3560                            << " rsrcid = " << std::hex << r_xram_rsp_trt_buf.srcid
3561                            << " / address = " << std::hex << r_xram_rsp_trt_buf.nline * m_words * 4
3562                            << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
3563                    }
3564#endif
3565                }
3566                break;
3567            }
3568            //////////////////////////
3569            case XRAM_RSP_WRITE_DIRTY:  // send a write request to IXR_CMD FSM
3570            {
3571                if (not r_xram_rsp_to_ixr_cmd_req.read())
3572                {
3573                    r_xram_rsp_to_ixr_cmd_req = true;
3574                    r_xram_rsp_to_ixr_cmd_index = r_xram_rsp_trt_index.read();
3575
3576                    m_cpt_write_dirty++;
3577
3578                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
3579
3580#if DEBUG_MEMC_XRAM_RSP
3581                    if (m_debug)
3582                    {
3583                        std::cout << "  <MEMC " << name() << " XRAM_RSP_WRITE_DIRTY>"
3584                            << " Send the put request to IXR_CMD FSM"
3585                            << " / address = " << r_xram_rsp_victim_nline.read() * m_words * 4 << std::endl;
3586                    }
3587#endif
3588                }
3589                break;
3590            }
3591            //////////////////////////
3592            case XRAM_RSP_ERROR_ERASE:  // erase TRT entry in case of error
3593            {
3594                m_trt.erase(r_xram_rsp_trt_index.read());
3595
3596                // Next state
3597                if (r_xram_rsp_trt_buf.proc_read)
3598                {
3599                    r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3600                }
3601                else
3602                {
3603                    // Trigger an interruption to signal a bus error from
3604                    // the XRAM because a processor WRITE MISS (XRAM GET
3605                    // transaction and not processor read).
3606                    //
3607                    // To avoid deadlocks we do not wait an error to be
3608                    // acknowledged before signaling another one.
3609                    // Therefore, when there is an active error, and other
3610                    // errors arrive, these are not considered
3611
3612                    if (!r_xram_rsp_rerror_irq.read() && r_xram_rsp_rerror_irq_enable.read()
3613                            && r_xram_rsp_trt_buf.xram_read)
3614                    {
3615                        r_xram_rsp_rerror_irq     = true;
3616                        r_xram_rsp_rerror_address = r_xram_rsp_trt_buf.nline * m_words * 4;
3617                        r_xram_rsp_rerror_rsrcid  = r_xram_rsp_trt_buf.srcid;
3618
3619#if DEBUG_MEMC_XRAM_RSP
3620                        if (m_debug)
3621                        {
3622                            std::cout
3623                                << "  <MEMC " << name() << " XRAM_RSP_ERROR_ERASE>"
3624                                << " Triggering interrupt to signal WRITE MISS bus error"
3625                                << " / irq_enable = " << r_xram_rsp_rerror_irq_enable.read()
3626                                << " / nline = "      << r_xram_rsp_trt_buf.nline
3627                                << " / rsrcid = "     << r_xram_rsp_trt_buf.srcid
3628                                << std::endl;
3629                        }
3630#endif
3631                    }
3632
3633                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
3634                }
3635
3636#if DEBUG_MEMC_XRAM_RSP
3637                if (m_debug)
3638                {
3639                    std::cout << "  <MEMC " << name() << " XRAM_RSP_ERROR_ERASE>"
3640                        << " Error reported by XRAM / erase the TRT entry" << std::endl;
3641                }
3642#endif
3643                break;
3644            }
3645            ////////////////////////
3646            case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3647            {
3648                if (!r_xram_rsp_to_tgt_rsp_req.read())
3649                {
3650                    r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3651                    r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3652                    r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3653                    for (size_t i = 0; i < m_words; i++)
3654                    {
3655                        r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3656                    }
3657                    r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3658                    r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3659                    r_xram_rsp_to_tgt_rsp_rerror = true;
3660                    r_xram_rsp_to_tgt_rsp_req    = true;
3661
3662                    r_xram_rsp_fsm = XRAM_RSP_IDLE;
3663
3664#if DEBUG_MEMC_XRAM_RSP
3665                    if (m_debug)
3666                    {
3667                        std::cout << "  <MEMC " << name()
3668                            << " XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3669                            << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
3670                    }
3671#endif
3672                }
3673                break;
3674            }
3675        } // end swich r_xram_rsp_fsm
3676
3677
3678        ////////////////////////////////////////////////////////////////////////////////////
3679        //    CAS FSM
3680        ////////////////////////////////////////////////////////////////////////////////////
3681        // The CAS FSM handles the CAS (Compare And Swap) atomic commands.
3682        //
3683        // This command contains two or four flits:
3684        // - In case of 32 bits atomic access, the first flit contains the value read
3685        // by a previous READ instruction, the second flit contains the value to be writen.
3686        // - In case of 64 bits atomic access, the 2 first flits contains the value read
3687        // by a previous READ instruction, the 2 next flits contains the value to be writen.
3688        //
3689        // The target address is cachable. If it is replicated in other L1 caches
3690        // than the writer, a coherence operation is done.
3691        //
3692        // It access the directory to check hit / miss.
3693        // - In case of miss, the CAS FSM must register a GET transaction in TRT.
3694        //   If a read transaction to the XRAM for this line already exists,
3695        //   or if the transaction table is full, it goes to the WAIT state
3696        //   to release the locks and try again. When the GET transaction has been
3697        //   launched, it goes to the WAIT state and try again.
3698        //   The CAS request is not consumed in the FIFO until a HIT is obtained.
3699        // - In case of hit...
3700        ///////////////////////////////////////////////////////////////////////////////////
3701
3702        switch (r_cas_fsm.read())
3703        {
3704            ////////////
3705            case CAS_IDLE:     // fill the local rdata buffers
3706            {
3707                if (m_cmd_cas_addr_fifo.rok())
3708                {
3709
3710#if DEBUG_MEMC_CAS
3711                    if (m_debug)
3712                    {
3713                        std::cout << "  <MEMC " << name() << " CAS_IDLE> CAS command: " << std::hex
3714                            << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
3715                            << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
3716                            << " wdata = " << m_cmd_cas_wdata_fifo.read()
3717                            << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
3718                            << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
3719                    }
3720#endif
3721                    if (m_cmd_cas_eop_fifo.read())
3722                    {
3723                        r_cas_fsm = CAS_DIR_REQ;
3724                    }
3725                    else  // we keep the last word in the FIFO
3726                    {
3727                        cmd_cas_fifo_get = true;
3728                    }
3729
3730                    // We fill the two buffers
3731                    if (r_cas_cpt.read() < 2)    // 32 bits access
3732                    {
3733                        r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
3734                    }
3735
3736                    if ((r_cas_cpt.read() == 1) and m_cmd_cas_eop_fifo.read())
3737                    {
3738                        r_cas_wdata = m_cmd_cas_wdata_fifo.read();
3739                    }
3740
3741                    assert((r_cas_cpt.read() <= 3) and  // no more than 4 flits...
3742                            "MEMC ERROR in CAS_IDLE state: illegal CAS command");
3743
3744                    if (r_cas_cpt.read() == 2)
3745                    {
3746                        r_cas_wdata = m_cmd_cas_wdata_fifo.read();
3747                    }
3748
3749                    r_cas_cpt = r_cas_cpt.read() + 1;
3750                }
3751                break;
3752            }
3753            /////////////////
3754            case CAS_DIR_REQ:
3755            {
3756                if (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
3757                {
3758                    r_cas_fsm = CAS_DIR_LOCK;
3759                }
3760
3761#if DEBUG_MEMC_CAS
3762                if (m_debug)
3763                {
3764                    std::cout << "  <MEMC " << name() << " CAS_DIR_REQ> Requesting DIR lock " << std::endl;
3765                }
3766#endif
3767                break;
3768            }
3769            /////////////////
3770            case CAS_DIR_LOCK:  // Read the directory
3771            {
3772                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CAS) and
3773                        "MEMC ERROR in CAS_DIR_LOCK: Bad DIR allocation");
3774
3775                size_t way = 0;
3776                DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
3777
3778                r_cas_is_cnt    = entry.is_cnt;
3779                r_cas_dirty     = entry.dirty;
3780                r_cas_tag       = entry.tag;
3781                r_cas_way       = way;
3782                r_cas_copy      = entry.owner.srcid;
3783                r_cas_copy_inst = entry.owner.inst;
3784
3785                if (entry.valid)  r_cas_fsm = CAS_DIR_HIT_READ;
3786                else              r_cas_fsm = CAS_MISS_TRT_LOCK;
3787
3788#if DEBUG_MEMC_CAS
3789                if (m_debug)
3790                {
3791                    std::cout << "  <MEMC " << name() << " CAS_DIR_LOCK> Directory acces"
3792                        << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
3793                        << " / hit = " << std::dec << entry.valid
3794                        << " / count = " << entry.count
3795                        << " / is_cnt = " << entry.is_cnt << std::endl;
3796                }
3797#endif
3798
3799                break;
3800            }
3801            /////////////////////
3802            case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
3803            // and check data change in cache
3804            {
3805                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CAS) and
3806                        "MEMC ERROR in CAS_DIR_HIT_READ: Bad DIR allocation");
3807
3808                size_t way = r_cas_way.read();
3809                size_t set = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
3810
3811                // update directory (lock & dirty bits)
3812                DirectoryEntry entry;
3813                entry.valid       = true;
3814                entry.is_cnt      = r_cas_is_cnt.read();
3815                entry.dirty       = true;
3816                entry.lock        = true;
3817                entry.tag         = r_cas_tag.read();
3818                entry.owner.srcid = r_cas_copy.read();
3819                entry.owner.inst  = r_cas_copy_inst.read();
3820
3821                m_cache_directory.write(set, way, entry);
3822
3823                // Store data from cache in buffer to do the comparison in next state
3824                m_cache_data.read_line(way, set, r_cas_data);
3825
3826                r_cas_fsm = CAS_DIR_HIT_COMPARE;
3827
3828#if DEBUG_MEMC_CAS
3829                if (m_debug)
3830                {
3831                    std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_READ> Read data from "
3832                        << " cache and store it in buffer" << std::endl;
3833                }
3834#endif
3835                break;
3836            }
3837            ////////////////////////
3838            case CAS_DIR_HIT_COMPARE:
3839            {
3840                size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
3841
3842                // check data change
3843                bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
3844
3845                if (r_cas_cpt.read() == 4)     // 64 bits CAS
3846                    ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
3847
3848                // to avoid livelock, force the atomic access to fail pseudo-randomly
3849                bool forced_fail = ((r_cas_lfsr % (64) == 0) and RANDOMIZE_CAS);
3850                r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
3851
3852                if (ok and not forced_fail) r_cas_fsm = CAS_DIR_HIT_WRITE;
3853                else                        r_cas_fsm = CAS_RSP_FAIL;
3854
3855#if DEBUG_MEMC_CAS
3856                if (m_debug)
3857                {
3858                    std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_COMPARE> Compare old and new data"
3859                        << " / expected value = " << std::hex << r_cas_rdata[0].read()
3860                        << " / actual value = "   << std::hex << r_cas_data[word].read()
3861                        << " / forced_fail = "    << std::dec << forced_fail << std::endl;
3862                }
3863#endif
3864                break;
3865            }
3866            //////////////////////
3867            case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
3868            // write data in cache if no CC request
3869            {
3870                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_CAS) and
3871                        "MEMC ERROR in CAS_DIR_HIT_WRITE: Bad DIR allocation");
3872
3873                // The CAS is a success => sw access to the llsc_global_table
3874                m_llsc_table.sw(m_cmd_cas_addr_fifo.read(), m_cmd_cas_addr_fifo.read());
3875
3876                size_t way  = r_cas_way.read();
3877                size_t set  = m_y[(addr_t) (m_cmd_cas_addr_fifo.read())];
3878                size_t word = m_x[(addr_t) (m_cmd_cas_addr_fifo.read())];
3879
3880                // cache update
3881                m_cache_data.write(way, set, word, r_cas_wdata.read());
3882                if (r_cas_cpt.read() == 4)
3883                {
3884                    m_cache_data.write(way, set, word + 1, m_cmd_cas_wdata_fifo.read());
3885                }
3886
3887                // Update L1 caches
3888                cc_vcaches_direct_update(m_cmd_cas_addr_fifo.read(), r_cas_wdata.read(), 0xF, -1);
3889                if (r_cas_cpt.read() == 4)
3890                {
3891                    cc_vcaches_direct_update(m_cmd_cas_addr_fifo.read() + 4, m_cmd_cas_wdata_fifo.read(), 0xF, -1);
3892                }
3893
3894                r_cas_fsm = CAS_RSP_SUCCESS;
3895
3896#if DEBUG_MEMC_CAS
3897                if (m_debug)
3898                {
3899                    std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_WRITE> Update cache:"
3900                        << " way = " << std::dec << way
3901                        << " / set = " << set
3902                        << " / word = " << word
3903                        << " / value = " << r_cas_wdata.read()
3904                        << " / global_llsc_table access" << std::endl;
3905                }
3906#endif
3907                break;
3908            }
3909            /////////////
3910            case CAS_WAIT:   // release all locks and retry from beginning
3911            {
3912
3913#if DEBUG_MEMC_CAS
3914                if (m_debug)
3915                {
3916                    std::cout << "  <MEMC " << name() << " CAS_WAIT> Release all locks" << std::endl;
3917                }
3918#endif
3919                r_cas_fsm = CAS_DIR_REQ;
3920                break;
3921            }
3922            //////////////////////
3923            case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
3924            {
3925                if (not r_cas_to_tgt_rsp_req.read())
3926                {
3927                    cmd_cas_fifo_get       = true;
3928                    r_cas_cpt              = 0;
3929                    r_cas_to_tgt_rsp_req   = true;
3930                    r_cas_to_tgt_rsp_data  = 1;
3931                    r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
3932                    r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
3933                    r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
3934                    r_cas_fsm              = CAS_IDLE;
3935
3936#if DEBUG_MEMC_CAS
3937                    if (m_debug)
3938                        std::cout << "  <MEMC " << name()
3939                            << " CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
3940#endif
3941                }
3942                break;
3943            }
3944            ////////////////////
3945            case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
3946            {
3947                if (not r_cas_to_tgt_rsp_req.read())
3948                {
3949                    cmd_cas_fifo_get       = true;
3950                    r_cas_cpt              = 0;
3951                    r_cas_to_tgt_rsp_req   = true;
3952                    r_cas_to_tgt_rsp_data  = 0;
3953                    r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
3954                    r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
3955                    r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
3956                    r_cas_fsm              = CAS_IDLE;
3957
3958#if DEBUG_MEMC_CAS
3959                    if (m_debug)
3960                    {
3961                        std::cout << "  <MEMC " << name()
3962                            << " CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
3963                    }
3964#endif
3965                }
3966                break;
3967            }
3968            ///////////////////////
3969            case CAS_MISS_TRT_LOCK: // cache miss : request access to transaction Table
3970            {
3971                if (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
3972                {
3973                    size_t index = 0;
3974                    bool hit_read = m_trt.hit_read(
3975                            m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],index);
3976                    bool hit_write = m_trt.hit_write(
3977                            m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]);
3978                    bool wok = not m_trt.full(index);
3979
3980#if DEBUG_MEMC_CAS
3981                    if (m_debug)
3982                    {
3983                        std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_LOCK> Check TRT state"
3984                            << " / hit_read = "  << hit_read
3985                            << " / hit_write = " << hit_write
3986                            << " / wok = " << wok
3987                            << " / index = " << index << std::endl;
3988                    }
3989#endif
3990
3991                    if (hit_read or !wok or hit_write)    // missing line already requested or TRT full
3992                    {
3993                        r_cas_fsm = CAS_WAIT;
3994                    }
3995                    else
3996                    {
3997                        r_cas_trt_index = index;
3998                        r_cas_fsm       = CAS_MISS_TRT_SET;
3999                    }
4000                }
4001                break;
4002            }
4003            //////////////////////
4004            case CAS_MISS_TRT_SET: // register the GET transaction in TRT
4005            {
4006                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_CAS) and
4007                        "MEMC ERROR in CAS_MISS_TRT_SET state: Bad TRT allocation");
4008
4009                std::vector<be_t> be_vector;
4010                std::vector<data_t> data_vector;
4011                be_vector.clear();
4012                data_vector.clear();
4013                for (size_t i = 0; i < m_words; i++)
4014                {
4015                    be_vector.push_back(0);
4016                    data_vector.push_back(0);
4017                }
4018
4019                m_trt.set(r_cas_trt_index.read(),
4020                        true,     // GET
4021                        m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],
4022                        m_cmd_cas_srcid_fifo.read(),
4023                        m_cmd_cas_trdid_fifo.read(),
4024                        m_cmd_cas_pktid_fifo.read(),
4025                        false,    // write request from processor
4026                        0,
4027                        0,
4028                        std::vector<be_t>(m_words, 0),
4029                        std::vector<data_t>(m_words, 0));
4030
4031                r_cas_fsm = CAS_MISS_XRAM_REQ;
4032
4033#if DEBUG_MEMC_CAS
4034                if (m_debug)
4035                {
4036                    std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_SET> Register GET transaction in TRT"
4037                        << " / address = " << std::hex << (addr_t)m_cmd_cas_addr_fifo.read()
4038                        << " / trt_index = " << std::dec << r_cas_trt_index.read() << std::endl;
4039                }
4040#endif
4041                break;
4042            }
4043            //////////////////////
4044            case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM a GET request
4045            {
4046                if (not r_cas_to_ixr_cmd_req.read())
4047                {
4048                    r_cas_to_ixr_cmd_req   = true;
4049                    r_cas_to_ixr_cmd_index = r_cas_trt_index.read();
4050                    r_cas_fsm              = CAS_WAIT;
4051
4052#if DEBUG_MEMC_CAS
4053                    if (m_debug)
4054                    {
4055                        std::cout << "  <MEMC " << name() << " CAS_MISS_XRAM_REQ> Request a GET transaction"
4056                            << " / address = " << std::hex << (addr_t) m_cmd_cas_addr_fifo.read()
4057                            << " / trt_index = " << std::dec << r_cas_trt_index.read() << std::endl;
4058                    }
4059#endif
4060                }
4061                break;
4062            }
4063        } // end switch r_cas_fsm
4064
4065
4066        //////////////////////////////////////////////////////////////////////////
4067        //    TGT_RSP FSM
4068        //////////////////////////////////////////////////////////////////////////
4069        // The TGT_RSP fsm sends the responses on the VCI target port
4070        // with a round robin priority between eight requests :
4071        // - r_config_to_tgt_rsp_req
4072        // - r_tgt_cmd_to_tgt_rsp_req
4073        // - r_read_to_tgt_rsp_req
4074        // - r_write_to_tgt_rsp_req
4075        // - r_cas_to_tgt_rsp_req
4076        // - r_xram_rsp_to_tgt_rsp_req
4077        //
4078        // The ordering is :
4079        //   config >tgt_cmd > read > write > cas > xram
4080        //////////////////////////////////////////////////////////////////////////
4081
4082        switch (r_tgt_rsp_fsm.read())
4083        {
4084            /////////////////////////
4085            case TGT_RSP_CONFIG_IDLE:  // tgt_cmd requests have the highest priority
4086            {
4087                if (r_tgt_cmd_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4088                else if (r_read_to_tgt_rsp_req)
4089                {
4090                    r_tgt_rsp_fsm = TGT_RSP_READ;
4091                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4092                }
4093                else if (r_write_to_tgt_rsp_req)     r_tgt_rsp_fsm = TGT_RSP_WRITE;
4094                else if (r_cas_to_tgt_rsp_req)       r_tgt_rsp_fsm = TGT_RSP_CAS;
4095                else if (r_xram_rsp_to_tgt_rsp_req)
4096                {
4097                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4098                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4099                }
4100                else if (r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4101                break;
4102            }
4103            //////////////////////////
4104            case TGT_RSP_TGT_CMD_IDLE: // read requests have the highest priority
4105            {
4106                if (r_read_to_tgt_rsp_req)
4107                {
4108                    r_tgt_rsp_fsm = TGT_RSP_READ;
4109                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4110                }
4111                else if (r_write_to_tgt_rsp_req)     r_tgt_rsp_fsm = TGT_RSP_WRITE;
4112                else if (r_cas_to_tgt_rsp_req)       r_tgt_rsp_fsm = TGT_RSP_CAS;
4113                else if (r_xram_rsp_to_tgt_rsp_req)
4114                {
4115                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4116                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4117                }
4118                else if (r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4119                else if (r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4120                break;
4121            }
4122            ///////////////////////
4123            case TGT_RSP_READ_IDLE: // write requests have the highest priority
4124            {
4125                if (r_write_to_tgt_rsp_req)          r_tgt_rsp_fsm = TGT_RSP_WRITE;
4126                else if (r_cas_to_tgt_rsp_req)       r_tgt_rsp_fsm = TGT_RSP_CAS;
4127                else if (r_xram_rsp_to_tgt_rsp_req)
4128                {
4129                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4130                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4131                }
4132                else if (r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4133                else if (r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4134                else if (r_read_to_tgt_rsp_req)
4135                {
4136                    r_tgt_rsp_fsm = TGT_RSP_READ;
4137                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4138                }
4139                break;
4140            }
4141            ////////////////////////
4142            case TGT_RSP_WRITE_IDLE: // cas requests have the highest priority
4143            {
4144                if (r_cas_to_tgt_rsp_req)            r_tgt_rsp_fsm = TGT_RSP_CAS;
4145                else if (r_xram_rsp_to_tgt_rsp_req)
4146                {
4147                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4148                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4149                }
4150                else if (r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4151                else if (r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4152                else if (r_read_to_tgt_rsp_req)
4153                {
4154                    r_tgt_rsp_fsm = TGT_RSP_READ;
4155                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4156                }
4157                else if (r_write_to_tgt_rsp_req)     r_tgt_rsp_fsm = TGT_RSP_WRITE;
4158                break;
4159            }
4160            ///////////////////////
4161            case TGT_RSP_CAS_IDLE: // xram_rsp requests have the highest priority
4162            {
4163                if (r_xram_rsp_to_tgt_rsp_req)
4164                {
4165                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4166                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4167                }
4168                else if (r_config_to_tgt_rsp_req)    r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4169                else if (r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4170                else if (r_read_to_tgt_rsp_req)
4171                {
4172                    r_tgt_rsp_fsm = TGT_RSP_READ;
4173                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4174                }
4175                else if (r_write_to_tgt_rsp_req)     r_tgt_rsp_fsm = TGT_RSP_WRITE;
4176                else if (r_cas_to_tgt_rsp_req)       r_tgt_rsp_fsm = TGT_RSP_CAS  ;
4177                break;
4178            }
4179            ///////////////////////
4180            case TGT_RSP_XRAM_IDLE: // multi ack requests have the highest priority
4181            {
4182
4183                if (r_config_to_tgt_rsp_req)         r_tgt_rsp_fsm = TGT_RSP_CONFIG;
4184                else if (r_tgt_cmd_to_tgt_rsp_req)   r_tgt_rsp_fsm = TGT_RSP_TGT_CMD;
4185                else if (r_read_to_tgt_rsp_req)
4186                {
4187                    r_tgt_rsp_fsm = TGT_RSP_READ;
4188                    r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4189                }
4190                else if (r_write_to_tgt_rsp_req)     r_tgt_rsp_fsm = TGT_RSP_WRITE;
4191                else if (r_cas_to_tgt_rsp_req)       r_tgt_rsp_fsm = TGT_RSP_CAS  ;
4192                else if (r_xram_rsp_to_tgt_rsp_req)
4193                {
4194                    r_tgt_rsp_fsm = TGT_RSP_XRAM;
4195                    r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4196                }
4197                break;
4198            }
4199            ////////////////////////////
4200            case TGT_RSP_CONFIG:  // send the response for a config transaction
4201            {
4202                if (p_vci_tgt.rspack)
4203                {
4204                    r_config_to_tgt_rsp_req = false;
4205                    r_tgt_rsp_fsm           = TGT_RSP_CONFIG_IDLE;
4206
4207#if DEBUG_MEMC_TGT_RSP
4208                    if (m_debug)
4209                    {
4210                        std::cout
4211                            << "  <MEMC " << name()
4212                            << " TGT_RSP_CONFIG>  Config transaction completed response"
4213                            << " / rsrcid = " << std::hex << r_config_to_tgt_rsp_srcid.read()
4214                            << " / rtrdid = " << r_config_to_tgt_rsp_trdid.read()
4215                            << " / rpktid = " << r_config_to_tgt_rsp_pktid.read()
4216                            << std::endl;
4217                    }
4218#endif
4219                }
4220                break;
4221            }
4222            /////////////////////
4223            case TGT_RSP_TGT_CMD: // send the response for a configuration access
4224            {
4225                if (p_vci_tgt.rspack)
4226                {
4227                    r_tgt_cmd_to_tgt_rsp_req = false;
4228                    r_tgt_rsp_fsm            = TGT_RSP_TGT_CMD_IDLE;
4229
4230#if DEBUG_MEMC_TGT_RSP
4231                    if (m_debug)
4232                    {
4233                        std::cout
4234                            << "  <MEMC " << name()
4235                            << " TGT_RSP_TGT_CMD> Send response for a configuration access"
4236                            << " / rsrcid = " << std::hex << r_tgt_cmd_to_tgt_rsp_srcid.read()
4237                            << " / rtrdid = " << r_tgt_cmd_to_tgt_rsp_trdid.read()
4238                            << " / rpktid = " << r_tgt_cmd_to_tgt_rsp_pktid.read()
4239                            << " / error = " << r_tgt_cmd_to_tgt_rsp_error.read()
4240                            << std::endl;
4241                    }
4242#endif
4243                }
4244                break;
4245            }
4246            //////////////////
4247            case TGT_RSP_READ:    // send the response to a read
4248            {
4249                if (p_vci_tgt.rspack)
4250                {
4251
4252#if DEBUG_MEMC_TGT_RSP
4253                    if (m_debug)
4254                    {
4255                        std::cout
4256                            << "  <MEMC " << name() << " TGT_RSP_READ> Read response"
4257                            << " / rsrcid = " << std::hex << r_read_to_tgt_rsp_srcid.read()
4258                            << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
4259                            << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
4260                            << " / rdata = " << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
4261                            << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
4262                    }
4263#endif
4264
4265                    uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() +
4266                        r_read_to_tgt_rsp_length.read() - 1;
4267                    bool is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
4268                    bool is_ll         = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
4269
4270                    if ((is_last_word and not is_ll) or
4271                       (r_tgt_rsp_key_sent.read() and is_ll))
4272                    {
4273                        // Last word in case of READ or second flit in case if LL
4274                        r_tgt_rsp_key_sent    = false;
4275                        r_read_to_tgt_rsp_req = false;
4276                        r_tgt_rsp_fsm         = TGT_RSP_READ_IDLE;
4277                    }
4278                    else
4279                    {
4280                        if (is_ll)
4281                        {
4282                            r_tgt_rsp_key_sent = true; // Send second flit of ll
4283                        }
4284                        else
4285                        {
4286                            r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1; // Send next word of read
4287                        }
4288                    }
4289                }
4290                break;
4291            }
4292            //////////////////
4293            case TGT_RSP_WRITE:   // send the write acknowledge
4294            {
4295                if (p_vci_tgt.rspack)
4296                {
4297#if DEBUG_MEMC_TGT_RSP
4298                    if (m_debug)
4299                    {
4300                        std::cout << "  <MEMC " << name() << " TGT_RSP_WRITE> Write response"
4301                            << " / rsrcid = " << std::hex << r_write_to_tgt_rsp_srcid.read()
4302                            << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
4303                            << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
4304                    }
4305#endif
4306                    r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
4307                    r_write_to_tgt_rsp_req = false;
4308                }
4309                break;
4310            }
4311            //////////////////
4312            case TGT_RSP_CAS:    // send one atomic word response
4313            {
4314                if (p_vci_tgt.rspack)
4315                {
4316
4317#if DEBUG_MEMC_TGT_RSP
4318                    if (m_debug)
4319                    {
4320                        std::cout << "  <MEMC " << name() << " TGT_RSP_CAS> CAS response"
4321                            << " / rsrcid = " << std::hex << r_cas_to_tgt_rsp_srcid.read()
4322                            << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
4323                            << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
4324                    }
4325#endif
4326                    r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
4327                    r_cas_to_tgt_rsp_req = false;
4328                }
4329                break;
4330            }
4331            //////////////////
4332            case TGT_RSP_XRAM:    // send the response after XRAM access
4333            {
4334                if (p_vci_tgt.rspack)
4335                {
4336#if DEBUG_MEMC_TGT_RSP
4337                    if (m_debug)
4338                    {
4339                        std::cout << "  <MEMC " << name() << " TGT_RSP_XRAM> Response following XRAM access"
4340                            << " / rsrcid = " << std::hex << r_xram_rsp_to_tgt_rsp_srcid.read()
4341                            << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
4342                            << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
4343                            << " / rdata = " << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
4344                            << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
4345                    }
4346#endif
4347                    uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() +
4348                        r_xram_rsp_to_tgt_rsp_length.read() - 1;
4349                    bool is_last_word = (r_tgt_rsp_cpt.read() == last_word_idx);
4350                    bool is_ll        = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
4351                    bool is_error     = r_xram_rsp_to_tgt_rsp_rerror.read();
4352
4353                    if (((is_last_word or is_error) and not is_ll) or
4354                            (r_tgt_rsp_key_sent.read() and is_ll))
4355                    {
4356                        // Last word sent in case of READ or second flit sent in case if LL
4357                        r_tgt_rsp_key_sent        = false;
4358                        r_xram_rsp_to_tgt_rsp_req = false;
4359                        r_tgt_rsp_fsm             = TGT_RSP_XRAM_IDLE;
4360                    }
4361                    else
4362                    {
4363                        if (is_ll)
4364                        {
4365                            r_tgt_rsp_key_sent = true; // Send second flit of ll
4366                        }
4367                        else
4368                        {
4369                            r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1; // Send next word of read
4370                        }
4371                    }
4372                }
4373                break;
4374            }
4375        } // end switch tgt_rsp_fsm
4376
4377
4378        ////////////////////////////////////////////////////////////////////////////////////
4379        //    ALLOC_DIR FSM
4380        ////////////////////////////////////////////////////////////////////////////////////
4381        // The ALLOC_DIR FSM allocates the access to the directory and
4382        // the data cache with a round robin priority between 6 user FSMs :
4383        // The cyclic ordering is CONFIG > READ > WRITE > CAS > CLEANUP > XRAM_RSP
4384        // The ressource is always allocated.
4385        /////////////////////////////////////////////////////////////////////////////////////
4386
4387        switch (r_alloc_dir_fsm.read())
4388        {
4389            /////////////////////
4390            case ALLOC_DIR_RESET: // Initializes the directory one SET per cycle.
4391                // All the WAYS of a SET initialized in parallel
4392
4393                r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
4394
4395                if (r_alloc_dir_reset_cpt.read() == (m_sets - 1))
4396                {
4397                    m_cache_directory.init();
4398                    r_alloc_dir_fsm = ALLOC_DIR_READ;
4399                }
4400                break;
4401
4402                //////////////////////
4403            case ALLOC_DIR_CONFIG:    // allocated to CONFIG FSM
4404                if ((r_config_fsm.read() != CONFIG_DIR_REQ) and
4405                    (r_config_fsm.read() != CONFIG_DIR_ACCESS) and
4406                    (r_config_fsm.read() != CONFIG_TRT_LOCK) and
4407                    (r_config_fsm.read() != CONFIG_TRT_SET))
4408                {
4409                    if (r_read_fsm.read() == READ_DIR_REQ)
4410                        r_alloc_dir_fsm = ALLOC_DIR_READ;
4411
4412                    else if (r_write_fsm.read() == WRITE_DIR_REQ)
4413                        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4414
4415                    else if (r_cas_fsm.read() == CAS_DIR_REQ)
4416                        r_alloc_dir_fsm = ALLOC_DIR_CAS;
4417
4418                    else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
4419                        r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4420                }
4421                break;
4422
4423                ////////////////////
4424            case ALLOC_DIR_READ:    // allocated to READ FSM
4425                if (((r_read_fsm.read() != READ_DIR_REQ) and
4426                     (r_read_fsm.read() != READ_DIR_LOCK) and
4427                     (r_read_fsm.read() != READ_TRT_LOCK))
4428                    or
4429                     ((r_read_fsm.read() == READ_TRT_LOCK) and
4430                     (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)))
4431                {
4432                    if (r_write_fsm.read() == WRITE_DIR_REQ)
4433                        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4434
4435                    else if (r_cas_fsm.read() == CAS_DIR_REQ)
4436                        r_alloc_dir_fsm = ALLOC_DIR_CAS;
4437
4438                    else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
4439                        r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4440
4441                    else if (r_config_fsm.read() == CONFIG_DIR_REQ)
4442                        r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
4443                }
4444                break;
4445
4446                /////////////////////
4447            case ALLOC_DIR_WRITE:    // allocated to WRITE FSM
4448                if (((r_write_fsm.read() != WRITE_DIR_REQ) and
4449                     (r_write_fsm.read() != WRITE_DIR_LOCK) and
4450                     (r_write_fsm.read() != WRITE_DIR_HIT) and
4451                     (r_write_fsm.read() != WRITE_MISS_TRT_LOCK))
4452                    or
4453                     ((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) and
4454                     (r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE)))
4455                {
4456                    if (r_cas_fsm.read() == CAS_DIR_REQ)
4457                        r_alloc_dir_fsm = ALLOC_DIR_CAS;
4458
4459                    else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
4460                        r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4461
4462                    else if (r_config_fsm.read() == CONFIG_DIR_REQ)
4463                        r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
4464
4465                    else if (r_read_fsm.read() == READ_DIR_REQ)
4466                        r_alloc_dir_fsm = ALLOC_DIR_READ;
4467                }
4468                break;
4469
4470                ///////////////////
4471            case ALLOC_DIR_CAS:    // allocated to CAS FSM
4472                if (((r_cas_fsm.read() != CAS_DIR_REQ) and
4473                     (r_cas_fsm.read() != CAS_DIR_LOCK) and
4474                     (r_cas_fsm.read() != CAS_DIR_HIT_READ) and
4475                     (r_cas_fsm.read() != CAS_DIR_HIT_COMPARE) and
4476                     (r_cas_fsm.read() != CAS_DIR_HIT_WRITE) and
4477                     (r_cas_fsm.read() != CAS_MISS_TRT_LOCK))
4478                    or
4479                     ((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) and
4480                      (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)))
4481                {
4482                    if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
4483                        r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4484
4485                    else if (r_config_fsm.read() == CONFIG_DIR_REQ)
4486                        r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
4487
4488                    else if (r_read_fsm.read() == READ_DIR_REQ)
4489                        r_alloc_dir_fsm = ALLOC_DIR_READ;
4490
4491                    else if (r_write_fsm.read() == WRITE_DIR_REQ)
4492                        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4493                }
4494                break;
4495
4496            ////////////////////////
4497            case ALLOC_DIR_XRAM_RSP:    // allocated to XRAM_RSP FSM
4498                if ((r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK) and
4499                        (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY))
4500                {
4501                    if (r_config_fsm.read() == CONFIG_DIR_REQ)
4502                        r_alloc_dir_fsm = ALLOC_DIR_CONFIG;
4503
4504                    else if (r_read_fsm.read() == READ_DIR_REQ)
4505                        r_alloc_dir_fsm = ALLOC_DIR_READ;
4506
4507                    else if (r_write_fsm.read() == WRITE_DIR_REQ)
4508                        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4509
4510                    else if (r_cas_fsm.read() == CAS_DIR_REQ)
4511                        r_alloc_dir_fsm = ALLOC_DIR_CAS;
4512                }
4513                break;
4514
4515        } // end switch alloc_dir_fsm
4516
4517        ////////////////////////////////////////////////////////////////////////////////////
4518        //    ALLOC_TRT FSM
4519        ////////////////////////////////////////////////////////////////////////////////////
4520        // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
4521        // with a round robin priority between 7 user FSMs :
4522        // The priority is READ > WRITE > CAS > IXR_CMD > XRAM_RSP > IXR_RSP > CONFIG
4523        // The ressource is always allocated.
4524        ///////////////////////////////////////////////////////////////////////////////////
4525
4526        switch (r_alloc_trt_fsm.read())
4527        {
4528            ////////////////////
4529            case ALLOC_TRT_READ:
4530                if (r_read_fsm.read() != READ_TRT_LOCK)
4531                {
4532                    if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4533                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4534
4535                    else if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4536                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4537
4538                    else if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4539                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4540                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4541                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4542                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4543                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4544
4545                    else if ((r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK) and
4546                            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4547                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4548
4549                    else if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4550                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4551                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4552
4553                    else if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4554                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4555                }
4556                break;
4557
4558            /////////////////////
4559            case ALLOC_TRT_WRITE:
4560                if ((r_write_fsm.read() != WRITE_MISS_TRT_LOCK))
4561                {
4562                    if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4563                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4564
4565                    else if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4566                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4567                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4568                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4569                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4570                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4571
4572                    else if ((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) and
4573                            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4574                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4575
4576                    else if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4577                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4578                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4579
4580                    else if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4581                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4582
4583                    else if (r_read_fsm.read() == READ_TRT_LOCK)
4584                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4585                }
4586                break;
4587
4588            ///////////////////
4589            case ALLOC_TRT_CAS:
4590                if (r_cas_fsm.read() != CAS_MISS_TRT_LOCK)
4591                {
4592                    if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4593                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4594                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4595                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4596                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4597                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4598
4599                    else if ((r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK) and
4600                             (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4601                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4602
4603                    else if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4604                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4605                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4606
4607                    else if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4608                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4609
4610                    else if (r_read_fsm.read() == READ_TRT_LOCK)
4611                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4612
4613                    else if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4614                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4615                }
4616                break;
4617
4618            ///////////////////////
4619            case ALLOC_TRT_IXR_CMD:
4620                if ((r_ixr_cmd_fsm.read() != IXR_CMD_READ_TRT) and
4621                        (r_ixr_cmd_fsm.read() != IXR_CMD_WRITE_TRT) and
4622                        (r_ixr_cmd_fsm.read() != IXR_CMD_CAS_TRT) and
4623                        (r_ixr_cmd_fsm.read() != IXR_CMD_XRAM_TRT) and
4624                        (r_ixr_cmd_fsm.read() != IXR_CMD_CONFIG_TRT))
4625                {
4626                    if ((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) and
4627                            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4628                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4629
4630                    else if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4631                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4632                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4633
4634                    else if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4635                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4636
4637                    else if (r_read_fsm.read() == READ_TRT_LOCK)
4638                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4639
4640                    else if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4641                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4642
4643                    else if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4644                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4645                }
4646                break;
4647
4648            ////////////////////////
4649            case ALLOC_TRT_XRAM_RSP:
4650                if (((r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK) or
4651                        (r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP)) and
4652                        (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY) and
4653                        (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT))
4654                {
4655                    if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4656                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4657                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4658
4659                    else if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4660                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4661
4662                    else if (r_read_fsm.read() == READ_TRT_LOCK)
4663                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4664
4665                    else if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4666                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4667
4668                    else if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4669                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4670
4671                    else if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4672                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4673                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4674                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4675                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4676                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4677
4678                }
4679                break;
4680
4681            ///////////////////////
4682            case ALLOC_TRT_IXR_RSP:
4683                if ((r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) and
4684                        (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ))
4685                {
4686                    if (r_config_fsm.read() == CONFIG_TRT_LOCK)
4687                        r_alloc_trt_fsm = ALLOC_TRT_CONFIG;
4688
4689                    else if (r_read_fsm.read() == READ_TRT_LOCK)
4690                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4691
4692                    else if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4693                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4694
4695                    else if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4696                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4697
4698                    else if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4699                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4700                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4701                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4702                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4703                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4704
4705                    else if ((r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK) and
4706                            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4707                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4708                }
4709                break;
4710
4711                //////////////////////
4712            case ALLOC_TRT_CONFIG:
4713                if ((r_config_fsm.read() != CONFIG_TRT_LOCK) and
4714                        (r_config_fsm.read() != CONFIG_TRT_SET))
4715                {
4716                    if (r_read_fsm.read() == READ_TRT_LOCK)
4717                        r_alloc_trt_fsm = ALLOC_TRT_READ;
4718
4719                    else if (r_write_fsm.read() == WRITE_MISS_TRT_LOCK)
4720                        r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4721
4722                    else if (r_cas_fsm.read() == CAS_MISS_TRT_LOCK)
4723                        r_alloc_trt_fsm = ALLOC_TRT_CAS;
4724
4725                    else if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_TRT) or
4726                            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_TRT) or
4727                            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_TRT) or
4728                            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_TRT) or
4729                            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_TRT))
4730                        r_alloc_trt_fsm = ALLOC_TRT_IXR_CMD;
4731
4732                    else if ((r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK) and
4733                            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
4734                        r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4735
4736                    else if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) or
4737                            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
4738                        r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4739                }
4740                break;
4741
4742        } // end switch alloc_trt_fsm
4743
4744        /////////////////////////////////////////////////////////////////////
4745        //    TGT_CMD to READ FIFO
4746        /////////////////////////////////////////////////////////////////////
4747
4748        m_cmd_read_addr_fifo.update(cmd_read_fifo_get, cmd_read_fifo_put,
4749                p_vci_tgt.address.read());
4750        m_cmd_read_length_fifo.update(cmd_read_fifo_get, cmd_read_fifo_put,
4751                p_vci_tgt.plen.read() >> 2);
4752        m_cmd_read_srcid_fifo.update(cmd_read_fifo_get, cmd_read_fifo_put,
4753                p_vci_tgt.srcid.read());
4754        m_cmd_read_trdid_fifo.update(cmd_read_fifo_get, cmd_read_fifo_put,
4755                p_vci_tgt.trdid.read());
4756        m_cmd_read_pktid_fifo.update(cmd_read_fifo_get, cmd_read_fifo_put,
4757                p_vci_tgt.pktid.read());
4758
4759        /////////////////////////////////////////////////////////////////////
4760        //    TGT_CMD to WRITE FIFO
4761        /////////////////////////////////////////////////////////////////////
4762
4763        m_cmd_write_addr_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4764                (addr_t)p_vci_tgt.address.read());
4765        m_cmd_write_eop_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4766                p_vci_tgt.eop.read());
4767        m_cmd_write_srcid_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4768                p_vci_tgt.srcid.read());
4769        m_cmd_write_trdid_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4770                p_vci_tgt.trdid.read());
4771        m_cmd_write_pktid_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4772                p_vci_tgt.pktid.read());
4773        m_cmd_write_data_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4774                p_vci_tgt.wdata.read());
4775        m_cmd_write_be_fifo.update(cmd_write_fifo_get, cmd_write_fifo_put,
4776                p_vci_tgt.be.read());
4777
4778        ////////////////////////////////////////////////////////////////////////////////////
4779        //    TGT_CMD to CAS FIFO
4780        ////////////////////////////////////////////////////////////////////////////////////
4781
4782        m_cmd_cas_addr_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4783                (addr_t)p_vci_tgt.address.read());
4784        m_cmd_cas_eop_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4785                p_vci_tgt.eop.read());
4786        m_cmd_cas_srcid_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4787                p_vci_tgt.srcid.read());
4788        m_cmd_cas_trdid_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4789                p_vci_tgt.trdid.read());
4790        m_cmd_cas_pktid_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4791                p_vci_tgt.pktid.read());
4792        m_cmd_cas_wdata_fifo.update(cmd_cas_fifo_get, cmd_cas_fifo_put,
4793                p_vci_tgt.wdata.read());
4794
4795
4796        m_cpt_cycles++;
4797
4798        ////////////////////////////////////////////////////////////////////////////////////
4799        //            Update r_config_rsp_lines counter.
4800        // The two sources of (increment / decrement) are CONFIG / IXR_RSP FSMs
4801        ////////////////////////////////////////////////////////////////////////////////////
4802        if (config_rsp_lines_incr and not config_rsp_lines_ixr_rsp_decr)
4803        {
4804            r_config_rsp_lines = r_config_rsp_lines.read() + 1;
4805        }
4806        if (not config_rsp_lines_incr and config_rsp_lines_ixr_rsp_decr)
4807        {
4808            r_config_rsp_lines = r_config_rsp_lines.read() - 1;
4809        }
4810
4811    } // end transition()
4812
4813    /////////////////////////////
4814    tmpl(void)::genMoore()
4815        /////////////////////////////
4816    {
4817#if MONITOR_MEMCACHE_FSM == 1
4818        p_read_fsm.write      (r_read_fsm.read());
4819        p_write_fsm.write     (r_write_fsm.read());
4820        p_xram_rsp_fsm.write  (r_xram_rsp_fsm.read());
4821        p_cas_fsm.write       (r_cas_fsm.read());
4822        p_config_fsm.write    (r_config_fsm.read());
4823        p_alloc_dir_fsm.write (r_alloc_dir_fsm.read());
4824        p_alloc_trt_fsm.write (r_alloc_trt_fsm.read());
4825        p_tgt_cmd_fsm.write   (r_tgt_cmd_fsm.read());
4826        p_tgt_rsp_fsm.write   (r_tgt_rsp_fsm.read());
4827        p_ixr_cmd_fsm.write   (r_ixr_cmd_fsm.read());
4828        p_ixr_rsp_fsm.write   (r_ixr_rsp_fsm.read());
4829        p_multi_ack_fsm.write (r_multi_ack_fsm.read());
4830#endif
4831
4832        ////////////////////////////////////////////////////////////
4833        // Command signals on the p_vci_ixr port
4834        ////////////////////////////////////////////////////////////
4835
4836        // DATA width is 8 bytes
4837        // The following values are not transmitted to XRAM
4838        //   p_vci_ixr.be
4839        //   p_vci_ixr.pktid
4840        //   p_vci_ixr.cons
4841        //   p_vci_ixr.wrap
4842        //   p_vci_ixr.contig
4843        //   p_vci_ixr.clen
4844        //   p_vci_ixr.cfixed
4845
4846        p_vci_ixr.plen    = 64;
4847        p_vci_ixr.srcid   = m_srcid_x;
4848        p_vci_ixr.trdid   = r_ixr_cmd_trdid.read();
4849        p_vci_ixr.address = (addr_t)r_ixr_cmd_address.read() + (r_ixr_cmd_word.read() << 2);
4850        p_vci_ixr.be      = 0xFF;
4851        p_vci_ixr.pktid   = 0;
4852        p_vci_ixr.cons    = false;
4853        p_vci_ixr.wrap    = false;
4854        p_vci_ixr.contig  = true;
4855        p_vci_ixr.clen    = 0;
4856        p_vci_ixr.cfixed  = false;
4857
4858        if ((r_ixr_cmd_fsm.read() == IXR_CMD_READ_SEND) or
4859            (r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_SEND) or
4860            (r_ixr_cmd_fsm.read() == IXR_CMD_CAS_SEND) or
4861            (r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_SEND) or
4862            (r_ixr_cmd_fsm.read() == IXR_CMD_CONFIG_SEND))
4863        {
4864            p_vci_ixr.cmdval  = true;
4865
4866            if (r_ixr_cmd_get.read())  // GET
4867            {
4868                p_vci_ixr.cmd   = vci_param_ext::CMD_READ;
4869                p_vci_ixr.wdata = 0;
4870                p_vci_ixr.eop   = true;
4871            }
4872            else                         // PUT
4873            {
4874                size_t word     = r_ixr_cmd_word.read();
4875                p_vci_ixr.cmd   = vci_param_ext::CMD_WRITE;
4876                p_vci_ixr.wdata = ((wide_data_t)(r_ixr_cmd_wdata[word].read()))  |
4877                    ((wide_data_t) (r_ixr_cmd_wdata[word + 1].read()) << 32);
4878                p_vci_ixr.eop   = (word == (m_words - 2));
4879            }
4880        }
4881        else
4882        {
4883            p_vci_ixr.cmdval = false;
4884        }
4885
4886        ////////////////////////////////////////////////////
4887        // Response signals on the p_vci_ixr port
4888        ////////////////////////////////////////////////////
4889
4890        if ((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) or
4891                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE))
4892        {
4893            p_vci_ixr.rspack = (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP);
4894        }
4895        else // r_ixr_rsp_fsm == IXR_RSP_IDLE
4896        {
4897            p_vci_ixr.rspack = false;
4898        }
4899
4900        ////////////////////////////////////////////////////
4901        // Command signals on the p_vci_tgt port
4902        ////////////////////////////////////////////////////
4903
4904        switch ((tgt_cmd_fsm_state_e) r_tgt_cmd_fsm.read())
4905        {
4906            case TGT_CMD_IDLE:
4907                p_vci_tgt.cmdack = false;
4908                break;
4909
4910            case TGT_CMD_CONFIG:
4911            {
4912                addr_t addr_lsb = p_vci_tgt.address.read() &
4913                                  m_config_addr_mask;
4914
4915                addr_t cell = (addr_lsb / vci_param_int::B);
4916
4917                size_t regr = cell & m_config_regr_idx_mask;
4918
4919                size_t func = (cell >> m_config_regr_width) &
4920                              m_config_func_idx_mask;
4921
4922                switch (func)
4923                {
4924                    case MEMC_CONFIG:
4925                        if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
4926                                and (regr == MEMC_CMD_TYPE))
4927                        {
4928                            p_vci_tgt.cmdack = true;
4929                        }
4930                        else
4931                        {
4932                            p_vci_tgt.cmdack = not r_tgt_cmd_to_tgt_rsp_req.read();
4933                        }
4934                        break;
4935
4936                    default:
4937                        p_vci_tgt.cmdack = not r_tgt_cmd_to_tgt_rsp_req.read();
4938                        break;
4939                }
4940
4941                break;
4942            }
4943            case TGT_CMD_ERROR:
4944                p_vci_tgt.cmdack = not r_tgt_cmd_to_tgt_rsp_req.read();
4945                break;
4946
4947            case TGT_CMD_READ:
4948                p_vci_tgt.cmdack = m_cmd_read_addr_fifo.wok();
4949                break;
4950
4951            case TGT_CMD_WRITE:
4952                p_vci_tgt.cmdack = m_cmd_write_addr_fifo.wok();
4953                break;
4954
4955            case TGT_CMD_CAS:
4956                p_vci_tgt.cmdack = m_cmd_cas_addr_fifo.wok();
4957                break;
4958        }
4959
4960        ////////////////////////////////////////////////////
4961        // Response signals on the p_vci_tgt port
4962        ////////////////////////////////////////////////////
4963
4964        switch (r_tgt_rsp_fsm.read())
4965        {
4966            case TGT_RSP_CONFIG_IDLE:
4967            case TGT_RSP_TGT_CMD_IDLE:
4968            case TGT_RSP_READ_IDLE:
4969            case TGT_RSP_WRITE_IDLE:
4970            case TGT_RSP_CAS_IDLE:
4971            case TGT_RSP_XRAM_IDLE:
4972            case TGT_RSP_MULTI_ACK_IDLE:
4973            case TGT_RSP_CLEANUP_IDLE:
4974            {
4975                p_vci_tgt.rspval = false;
4976                p_vci_tgt.rsrcid = 0;
4977                p_vci_tgt.rdata  = 0;
4978                p_vci_tgt.rpktid = 0;
4979                p_vci_tgt.rtrdid = 0;
4980                p_vci_tgt.rerror = 0;
4981                p_vci_tgt.reop   = false;
4982                break;
4983            }
4984            case TGT_RSP_CONFIG:
4985            {
4986                p_vci_tgt.rspval = true;
4987                p_vci_tgt.rdata  = 0;
4988                p_vci_tgt.rsrcid = r_config_to_tgt_rsp_srcid.read();
4989                p_vci_tgt.rtrdid = r_config_to_tgt_rsp_trdid.read();
4990                p_vci_tgt.rpktid = r_config_to_tgt_rsp_pktid.read();
4991                p_vci_tgt.rerror = r_config_to_tgt_rsp_error.read();
4992                p_vci_tgt.reop   = true;
4993                break;
4994            }
4995            case TGT_RSP_TGT_CMD:
4996            {
4997                p_vci_tgt.rspval = true;
4998                p_vci_tgt.rdata  = r_tgt_cmd_to_tgt_rsp_rdata.read();
4999                p_vci_tgt.rsrcid = r_tgt_cmd_to_tgt_rsp_srcid.read();
5000                p_vci_tgt.rtrdid = r_tgt_cmd_to_tgt_rsp_trdid.read();
5001                p_vci_tgt.rpktid = r_tgt_cmd_to_tgt_rsp_pktid.read();
5002                p_vci_tgt.rerror = r_tgt_cmd_to_tgt_rsp_error.read();
5003                p_vci_tgt.reop   = true;
5004                break;
5005            }
5006            case TGT_RSP_READ:
5007            {
5008                uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() + r_read_to_tgt_rsp_length - 1;
5009                bool is_last_word = (r_tgt_rsp_cpt.read() == last_word_idx);
5010                bool is_ll = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
5011
5012                p_vci_tgt.rspval  = true;
5013
5014                if (is_ll and not r_tgt_rsp_key_sent.read())
5015                {
5016                    // LL response first flit
5017                    p_vci_tgt.rdata = r_read_to_tgt_rsp_ll_key.read();
5018                }
5019                else
5020                {
5021                    // LL response second flit or READ response
5022                    p_vci_tgt.rdata = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5023                }
5024
5025                p_vci_tgt.rsrcid = r_read_to_tgt_rsp_srcid.read();
5026                p_vci_tgt.rtrdid = r_read_to_tgt_rsp_trdid.read();
5027                p_vci_tgt.rpktid = r_read_to_tgt_rsp_pktid.read();
5028                p_vci_tgt.rerror = 0;
5029                p_vci_tgt.reop   = (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll);
5030                break;
5031            }
5032
5033            case TGT_RSP_WRITE:
5034                p_vci_tgt.rspval = true;
5035                if (((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) and r_write_to_tgt_rsp_sc_fail.read())
5036                    p_vci_tgt.rdata = 1;
5037                else
5038                    p_vci_tgt.rdata = 0;
5039                p_vci_tgt.rsrcid = r_write_to_tgt_rsp_srcid.read();
5040                p_vci_tgt.rtrdid = r_write_to_tgt_rsp_trdid.read();
5041                p_vci_tgt.rpktid = r_write_to_tgt_rsp_pktid.read();
5042                p_vci_tgt.rerror = 0;
5043                p_vci_tgt.reop   = true;
5044                break;
5045
5046            case TGT_RSP_CAS:
5047                p_vci_tgt.rspval = true;
5048                p_vci_tgt.rdata  = r_cas_to_tgt_rsp_data.read();
5049                p_vci_tgt.rsrcid = r_cas_to_tgt_rsp_srcid.read();
5050                p_vci_tgt.rtrdid = r_cas_to_tgt_rsp_trdid.read();
5051                p_vci_tgt.rpktid = r_cas_to_tgt_rsp_pktid.read();
5052                p_vci_tgt.rerror = 0;
5053                p_vci_tgt.reop   = true;
5054                break;
5055
5056            case TGT_RSP_XRAM:
5057            {
5058                uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() + r_xram_rsp_to_tgt_rsp_length.read() - 1;
5059                bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
5060                bool     is_ll         = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
5061                bool     is_error      = r_xram_rsp_to_tgt_rsp_rerror.read();
5062
5063                p_vci_tgt.rspval = true;
5064
5065                if (is_ll and not r_tgt_rsp_key_sent.read())
5066                {
5067                    // LL response first flit
5068                    p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_ll_key.read();
5069                }
5070                else {
5071                    // LL response second flit or READ response
5072                    p_vci_tgt.rdata = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5073                }
5074
5075                p_vci_tgt.rsrcid = r_xram_rsp_to_tgt_rsp_srcid.read();
5076                p_vci_tgt.rtrdid = r_xram_rsp_to_tgt_rsp_trdid.read();
5077                p_vci_tgt.rpktid = r_xram_rsp_to_tgt_rsp_pktid.read();
5078                p_vci_tgt.rerror = is_error;
5079                p_vci_tgt.reop   = (((is_last_word or is_error) and not is_ll) or
5080                        (r_tgt_rsp_key_sent.read() and is_ll));
5081                break;
5082            }
5083
5084        } // end switch r_tgt_rsp_fsm
5085
5086        ////////////////////////////////////////////////////////////////////
5087        //  p_irq port
5088        //
5089        //  WRITE MISS response error signaling
5090        ////////////////////////////////////////////////////////////////////
5091
5092        p_irq = r_xram_rsp_rerror_irq.read() &&
5093            r_xram_rsp_rerror_irq_enable.read();
5094
5095        ////////////////////////////////////////////////////////////////////
5096        //  p_dspin_m2p port (CC_SEND FSM)
5097        ////////////////////////////////////////////////////////////////////
5098
5099        p_dspin_m2p.write = false;
5100        p_dspin_m2p.eop   = false;
5101        p_dspin_m2p.data  = 0;
5102
5103        ////////////////////////////////////////////////////////////////////
5104        //  p_dspin_clack port (CLEANUP FSM)
5105        ////////////////////////////////////////////////////////////////////
5106
5107        p_dspin_clack.write = false;
5108        p_dspin_clack.eop   = false;
5109        p_dspin_clack.data  = 0;
5110
5111        ///////////////////////////////////////////////////////////////////
5112        //  p_dspin_p2m port (CC_RECEIVE FSM)
5113        ///////////////////////////////////////////////////////////////////
5114
5115        p_dspin_p2m.read = false;
5116       
5117    } // end genMoore()
5118
5119}
5120} // end name space
5121
5122// Local Variables:
5123// tab-width: 4
5124// c-basic-offset: 4
5125// c-file-offsets:((innamespace . 0)(inline-open . 0))
5126// indent-tabs-mode: nil
5127// End:
5128
5129// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.