source: trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 403

Last change on this file since 403 was 403, checked in by alain, 12 years ago

Updating vci_cc_vcache_wrapper and vci_mem_cache to comply with the new DSPIN signals (explcit EOP).

File size: 251.2 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
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*              eric.guthmuller@polytechnique.edu
30*              cesar.fuguet-tortolero@lip6.fr
31*              alexandre.joannou@lip6.fr
32*/
33
34#include "../include/vci_mem_cache.h"
35
36//////   debug services   ///////////////////////////////////////////////////////
37// All debug messages are conditionned by two variables:
38// - compile time   : DEBUG_MEMC_*** : defined below
39// - execution time : m_debug_***    : defined by constructor arguments
40//    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_READ      1 // detailed trace of READ FSM
45#define DEBUG_MEMC_WRITE     1 // detailed trace of WRITE FSM
46#define DEBUG_MEMC_CAS       1 // detailed trace of CAS FSM
47#define DEBUG_MEMC_IXR_CMD   1 // detailed trace of IXR_RSP FSM
48#define DEBUG_MEMC_IXR_RSP   1 // detailed trace of IXR_RSP FSM
49#define DEBUG_MEMC_XRAM_RSP  1 // detailed trace of XRAM_RSP FSM
50#define DEBUG_MEMC_CC_SEND   1 // detailed trace of CC_SEND FSM
51#define DEBUG_MEMC_MULTI_ACK 1 // detailed trace of MULTI_ACK FSM
52#define DEBUG_MEMC_TGT_CMD   1 // detailed trace of TGT_CMD FSM
53#define DEBUG_MEMC_TGT_RSP   1 // detailed trace of TGT_RSP FSM
54#define DEBUG_MEMC_CLEANUP   1 // detailed trace of CLEANUP FSM
55
56#define RANDOMIZE_CAS        1
57
58namespace soclib { namespace caba {
59
60const char *tgt_cmd_fsm_str[] =
61{
62  "TGT_CMD_IDLE",
63  "TGT_CMD_READ",
64  "TGT_CMD_WRITE",
65  "TGT_CMD_CAS"
66};
67const char *tgt_rsp_fsm_str[] =
68{
69  "TGT_RSP_READ_IDLE",
70  "TGT_RSP_WRITE_IDLE",
71  "TGT_RSP_CAS_IDLE",
72  "TGT_RSP_XRAM_IDLE",
73  "TGT_RSP_INIT_IDLE",
74  "TGT_RSP_CLEANUP_IDLE",
75  "TGT_RSP_READ",
76  "TGT_RSP_WRITE",
77  "TGT_RSP_CAS",
78  "TGT_RSP_XRAM",
79  "TGT_RSP_INIT",
80  "TGT_RSP_CLEANUP"
81};
82const char *cc_receive_fsm_str[] =
83{
84  "CC_RECEIVE_IDLE",
85  "CC_RECEIVE_CLEANUP",
86  "CC_RECEIVE_CLEANUP_EOP",
87  "CC_RECEIVE_MULTI_ACK"
88};
89const char *cc_send_fsm_str[] =
90{
91  "CC_SEND_XRAM_RSP_IDLE",
92  "CC_SEND_WRITE_IDLE",
93  "CC_SEND_CAS_IDLE",
94  "CC_SEND_CLEANUP_IDLE",
95  "CC_SEND_CLEANUP_ACK",
96  "CC_SEND_XRAM_RSP_BRDCAST_HEADER",
97  "CC_SEND_XRAM_RSP_BRDCAST_NLINE",
98  "CC_SEND_XRAM_RSP_INVAL_HEADER",
99  "CC_SEND_XRAM_RSP_INVAL_NLINE",
100  "CC_SEND_WRITE_BRDCAST_HEADER",
101  "CC_SEND_WRITE_BRDCAST_NLINE",
102  "CC_SEND_WRITE_UPDT_HEADER",
103  "CC_SEND_WRITE_UPDT_NLINE",
104  "CC_SEND_WRITE_UPDT_DATA",
105  "CC_SEND_CAS_BRDCAST_HEADER",
106  "CC_SEND_CAS_BRDCAST_NLINE",
107  "CC_SEND_CAS_UPDT_HEADER",
108  "CC_SEND_CAS_UPDT_NLINE",
109  "CC_SEND_CAS_UPDT_DATA",
110  "CC_SEND_CAS_UPDT_DATA_HIGH"
111};
112const char *multi_ack_fsm_str[] =
113{
114  "MULTI_ACK_IDLE",
115  "MULTI_ACK_UPT_LOCK",
116  "MULTI_ACK_UPT_CLEAR",
117  "MULTI_ACK_WRITE_RSP"
118};
119const char *read_fsm_str[] =
120{
121  "READ_IDLE",
122  "READ_DIR_REQ",
123  "READ_DIR_LOCK",
124  "READ_DIR_HIT",
125  "READ_HEAP_REQ",
126  "READ_HEAP_LOCK",
127  "READ_HEAP_WRITE",
128  "READ_HEAP_ERASE",
129  "READ_HEAP_LAST",
130  "READ_RSP",
131  "READ_TRT_LOCK",
132  "READ_TRT_SET",
133  "READ_TRT_REQ"
134};
135const char *write_fsm_str[] =
136{
137  "WRITE_IDLE",
138  "WRITE_NEXT",
139  "WRITE_DIR_REQ",
140  "WRITE_DIR_LOCK",
141  "WRITE_DIR_READ",
142  "WRITE_DIR_HIT",
143  "WRITE_UPT_LOCK",
144  "WRITE_UPT_HEAP_LOCK",
145  "WRITE_UPT_REQ",
146  "WRITE_UPT_NEXT",
147  "WRITE_UPT_DEC",
148  "WRITE_RSP",
149  "WRITE_MISS_TRT_LOCK",
150  "WRITE_MISS_TRT_DATA",
151  "WRITE_MISS_TRT_SET",
152  "WRITE_MISS_XRAM_REQ",
153  "WRITE_BC_TRT_LOCK",
154  "WRITE_BC_UPT_LOCK",
155  "WRITE_BC_DIR_INVAL",
156  "WRITE_BC_CC_SEND",
157  "WRITE_BC_XRAM_REQ",
158  "WRITE_WAIT"
159};
160const char *ixr_rsp_fsm_str[] =
161{
162  "IXR_RSP_IDLE",
163  "IXR_RSP_ACK",
164  "IXR_RSP_TRT_ERASE",
165  "IXR_RSP_TRT_READ"
166};
167const char *xram_rsp_fsm_str[] =
168{
169  "XRAM_RSP_IDLE",
170  "XRAM_RSP_TRT_COPY",
171  "XRAM_RSP_TRT_DIRTY",
172  "XRAM_RSP_DIR_LOCK",
173  "XRAM_RSP_DIR_UPDT",
174  "XRAM_RSP_DIR_RSP",
175  "XRAM_RSP_INVAL_LOCK",
176  "XRAM_RSP_INVAL_WAIT",
177  "XRAM_RSP_INVAL",
178  "XRAM_RSP_WRITE_DIRTY",
179  "XRAM_RSP_HEAP_REQ",
180  "XRAM_RSP_HEAP_ERASE",
181  "XRAM_RSP_HEAP_LAST",
182  "XRAM_RSP_ERROR_ERASE",
183  "XRAM_RSP_ERROR_RSP"
184};
185const char *ixr_cmd_fsm_str[] =
186{
187  "IXR_CMD_READ_IDLE",
188  "IXR_CMD_WRITE_IDLE",
189  "IXR_CMD_CAS_IDLE",
190  "IXR_CMD_XRAM_IDLE",
191  "IXR_CMD_READ",
192  "IXR_CMD_WRITE",
193  "IXR_CMD_CAS",
194  "IXR_CMD_XRAM"
195};
196const char *cas_fsm_str[] =
197{
198  "CAS_IDLE",
199  "CAS_DIR_REQ",
200  "CAS_DIR_LOCK",
201  "CAS_DIR_HIT_READ",
202  "CAS_DIR_HIT_COMPARE",
203  "CAS_DIR_HIT_WRITE",
204  "CAS_UPT_LOCK",
205  "CAS_UPT_HEAP_LOCK",
206  "CAS_UPT_REQ",
207  "CAS_UPT_NEXT",
208  "CAS_BC_TRT_LOCK",
209  "CAS_BC_UPT_LOCK",
210  "CAS_BC_DIR_INVAL",
211  "CAS_BC_CC_SEND",
212  "CAS_BC_XRAM_REQ",
213  "CAS_RSP_FAIL",
214  "CAS_RSP_SUCCESS",
215  "CAS_MISS_TRT_LOCK",
216  "CAS_MISS_TRT_SET",
217  "CAS_MISS_XRAM_REQ",
218  "CAS_WAIT"
219};
220const char *cleanup_fsm_str[] =
221{
222  "CLEANUP_IDLE",
223  "CLEANUP_GET_NLINE",
224  "CLEANUP_DIR_REQ",
225  "CLEANUP_DIR_LOCK",
226  "CLEANUP_DIR_WRITE",
227  "CLEANUP_HEAP_REQ",
228  "CLEANUP_HEAP_LOCK",
229  "CLEANUP_HEAP_SEARCH",
230  "CLEANUP_HEAP_CLEAN",
231  "CLEANUP_HEAP_FREE",
232  "CLEANUP_UPT_LOCK",
233  "CLEANUP_UPT_DECREMENT",
234  "CLEANUP_UPT_CLEAR",
235  "CLEANUP_WRITE_RSP",
236  "CLEANUP_SEND_ACK"
237};
238const char *alloc_dir_fsm_str[] =
239{
240  "ALLOC_DIR_RESET",
241  "ALLOC_DIR_READ",
242  "ALLOC_DIR_WRITE",
243  "ALLOC_DIR_CAS",
244  "ALLOC_DIR_CLEANUP",
245  "ALLOC_DIR_XRAM_RSP"
246};
247const char *alloc_trt_fsm_str[] =
248{
249  "ALLOC_TRT_READ",
250  "ALLOC_TRT_WRITE",
251  "ALLOC_TRT_CAS",
252  "ALLOC_TRT_XRAM_RSP",
253  "ALLOC_TRT_IXR_RSP"
254};
255const char *alloc_upt_fsm_str[] =
256{
257  "ALLOC_UPT_WRITE",
258  "ALLOC_UPT_XRAM_RSP",
259  "ALLOC_UPT_MULTI_ACK",
260  "ALLOC_UPT_CLEANUP",
261  "ALLOC_UPT_CAS"
262};
263const char *alloc_heap_fsm_str[] =
264{
265  "ALLOC_HEAP_RESET",
266  "ALLOC_HEAP_READ",
267  "ALLOC_HEAP_WRITE",
268  "ALLOC_HEAP_CAS",
269  "ALLOC_HEAP_CLEANUP",
270  "ALLOC_HEAP_XRAM_RSP"
271};
272
273#define tmpl(x) \
274  template<typename vci_param_int, \
275           typename vci_param_ext, \
276           size_t dspin_in_width,  \
277           size_t dspin_out_width> x \
278  VciMemCache<vci_param_int, vci_param_ext, dspin_in_width, dspin_out_width>
279
280using namespace soclib::common;
281
282////////////////////////////////
283//  Constructor
284////////////////////////////////
285
286tmpl(/**/) ::VciMemCache(
287  sc_module_name      name,
288  const MappingTable  &mtp,              // mapping table for direct network
289  const MappingTable  &mtx,              // mapping table for external network
290  const IntTab        &srcid_x,          // global index on external network
291  const IntTab        &tgtid_d,          // global index on direct network
292  const size_t        cc_global_id,      // global index on cc network
293  const size_t        nways,             // number of ways per set
294  const size_t        nsets,             // number of associative sets
295  const size_t        nwords,            // number of words in cache line
296  const size_t        max_copies,        // max number of copies in heap
297  const size_t        heap_size,         // number of heap entries
298  const size_t        trt_lines,         // number of TRT entries
299  const size_t        upt_lines,         // number of UPT entries
300  const size_t        debug_start_cycle,
301  const bool          debug_ok)
302
303  : soclib::caba::BaseModule(name),
304
305    p_clk( "p_clk" ),
306    p_resetn( "p_resetn" ),
307    p_vci_tgt( "p_vci_tgt" ),
308    p_vci_ixr( "p_vci_ixr" ),
309    p_dspin_in( "p_dspin_in" ),
310    p_dspin_out( "p_dspin_out" ),
311
312    m_seglist( mtp.getSegmentList(tgtid_d) ),
313    m_nseg( 0 ),
314    m_srcid_x( mtx.indexForId(srcid_x) ),
315    m_initiators( 1 << vci_param_int::S ),
316    m_heap_size( heap_size ),
317    m_ways( nways ),
318    m_sets( nsets ),
319    m_words( nwords ),
320    m_cc_global_id( cc_global_id ),
321    m_debug_start_cycle( debug_start_cycle ),
322    m_debug_ok( debug_ok ),
323    m_trt_lines(trt_lines),
324    m_trt(trt_lines, nwords),
325    m_upt_lines(upt_lines),
326    m_upt(upt_lines),
327    m_cache_directory(nways, nsets, nwords, vci_param_int::N),
328    m_cache_data(nways, nsets, nwords),
329    m_heap(m_heap_size),
330    m_max_copies( max_copies ),
331    m_llsc_table(),
332
333#define L2 soclib::common::uint32_log2
334    m_x(L2(m_words), 2),
335    m_y(L2(m_sets), L2(m_words) + 2),
336    m_z(vci_param_int::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
337    m_nline(vci_param_int::N - L2(m_words) - 2, L2(m_words) + 2),
338#undef L2
339
340    // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits)
341    //   0b00000    /   0b11111    /   0b00000    /   0b11111
342    m_broadcast_boundaries(0x7C1F),
343
344    //  FIFOs
345    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
346    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
347    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
348    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
349    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
350
351    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
352    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
353    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
354    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
355    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
356    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
357    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
358
359    m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4),
360    m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4),
361    m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4),
362    m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4),
363    m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4),
364    m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4),
365
366    m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4),
367    m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4),
368
369    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
370
371    r_read_fsm("r_read_fsm"),
372
373    r_write_fsm("r_write_fsm"),
374
375    m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8),
376    m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8),
377#if L1_MULTI_CACHE
378    m_write_to_cc_send_cache_id_fifo("m_write_to_cc_send_cache_id_fifo",8),
379#endif
380
381    r_multi_ack_fsm("r_multi_ack_fsm"),
382
383    r_cleanup_fsm("r_cleanup_fsm"),
384
385    r_cas_fsm("r_cas_fsm"),
386
387    m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8),
388    m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8),
389#if L1_MULTI_CACHE
390    m_cas_to_cc_send_cache_id_fifo("m_cas_to_cc_send_cache_id_fifo",8),
391#endif
392
393    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
394    r_xram_rsp_fsm("r_xram_rsp_fsm"),
395
396    m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8),
397    m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8),
398#if L1_MULTI_CACHE
399    m_xram_rsp_to_cc_send_cache_id_fifo("m_xram_rsp_to_cc_send_cache_id_fifo",8),
400#endif
401
402    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
403
404    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
405
406    r_cc_send_fsm("r_cc_send_fsm"),
407    r_cc_receive_fsm("r_cc_receive_fsm"),
408
409    r_alloc_dir_fsm("r_alloc_dir_fsm"),
410    r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"),
411    r_alloc_trt_fsm("r_alloc_trt_fsm"),
412    r_alloc_upt_fsm("r_alloc_upt_fsm"),
413    r_alloc_heap_fsm("r_alloc_heap_fsm"),
414    r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt")
415{
416    assert(IS_POW_OF_2(nsets));
417    assert(IS_POW_OF_2(nwords));
418    assert(IS_POW_OF_2(nways));
419    assert(nsets);
420    assert(nwords);
421    assert(nways);
422
423    // check Transaction table size
424    assert((uint32_log2(trt_lines) <= vci_param_ext::T) and
425         "MEMC ERROR : Need more bits for VCI TRDID field");
426
427    // check internal and external data width
428    assert( (vci_param_int::B == 4 ) and
429         "MEMC ERROR : VCI internal data width must be 32 bits");
430         
431    assert( (vci_param_ext::B == 8) and
432         "MEMC ERROR : VCI external data width must be 64 bits");
433
434    // Check coherence between internal & external addresses
435    assert( (vci_param_int::N == vci_param_ext::N) and
436         "MEMC ERROR : VCI internal & external addresses must have the same width");
437         
438    // Get the segments associated to the MemCache
439    std::list<soclib::common::Segment>::iterator seg;
440    size_t i = 0;
441
442    for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++)
443    {
444        m_nseg++;
445    }
446
447    m_seg = new soclib::common::Segment*[m_nseg];
448
449    for(seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++)
450    {
451        m_seg[i] = & (*seg);
452        i++;
453    }
454
455    // Allocation for IXR_RSP FSM
456    r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
457
458    // Allocation for XRAM_RSP FSM
459    r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
460    r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
461    r_xram_rsp_to_ixr_cmd_data = new sc_signal<data_t>[nwords];
462
463    // Allocation for READ FSM
464    r_read_data                = new sc_signal<data_t>[nwords];
465    r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
466
467    // Allocation for WRITE FSM
468    r_write_data               = new sc_signal<data_t>[nwords];
469    r_write_be                 = new sc_signal<be_t>[nwords];
470    r_write_to_cc_send_data    = new sc_signal<data_t>[nwords];
471    r_write_to_cc_send_be      = new sc_signal<be_t>[nwords];
472    r_write_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
473
474    // Allocation for CAS FSM
475    r_cas_to_ixr_cmd_data      = new sc_signal<data_t>[nwords];
476    r_cas_data                 = new sc_signal<data_t>[nwords];
477    r_cas_rdata                = new sc_signal<data_t>[2];
478
479
480    SC_METHOD(transition);
481    dont_initialize();
482    sensitive << p_clk.pos();
483
484    SC_METHOD(genMoore);
485    dont_initialize();
486    sensitive << p_clk.neg();
487} // end constructor
488
489///////////////////////////////////////////////////////////////////////
490tmpl(void) ::start_monitor(addr_t addr, addr_t length)
491///////////////////////////////////////////////////////////////////////
492{
493  m_monitor_ok        = true;
494  m_monitor_base      = addr;
495  m_monitor_length    = length;
496}
497
498///////////////////////////////////////////////////////////////////////
499tmpl(void) ::stop_monitor()
500///////////////////////////////////////////////////////////////////////
501{
502  m_monitor_ok        = false;
503}
504
505////////////////////////////////////////////////
506tmpl(void) ::check_monitor( const char  *buf, 
507                            addr_t      addr, 
508                            data_t      data,
509                            bool        read )
510////////////////////////////////////////////////
511{
512  if((addr >= m_monitor_base) and
513      (addr < m_monitor_base + m_monitor_length))
514  {
515    if ( read ) std::cout << " Monitor MEMC Read  ";
516    else        std::cout << " Monitor MEMC Write "; 
517    std::cout << buf
518              << " / Address = " << std::hex << addr
519              << " / Data = " << data
520              << " at cycle " << std::dec << m_cpt_cycles << std::endl;
521  }
522}
523
524/////////////////////////////////////////////////////
525tmpl(void) ::copies_monitor(addr_t addr)
526/////////////////////////////////////////////////////
527{
528  DirectoryEntry entry = m_cache_directory.read_neutral(addr);
529
530  if((entry.count != m_debug_previous_count) or
531      (entry.valid != m_debug_previous_hit))
532  {
533    std::cout << "Monitor MEMC " << name()
534              << " at cycle " << std::dec << m_cpt_cycles
535              << " for address " << std::hex << addr
536              << " / HIT = " << entry.valid
537              << " / COUNT = " << std::dec << entry.count << std::endl;
538  }
539  m_debug_previous_count = entry.count;
540  m_debug_previous_hit = entry.valid;
541}
542
543//////////////////////////////////////////////////
544tmpl(void) ::print_trace()
545//////////////////////////////////////////////////
546{
547  std::cout << "MEMC " << name() << std::endl;
548  std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]
549            << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]
550            << " | " << read_fsm_str[r_read_fsm.read()]
551            << " | " << write_fsm_str[r_write_fsm.read()]
552            << " | " << cas_fsm_str[r_cas_fsm.read()]
553            << " | " << cleanup_fsm_str[r_cleanup_fsm.read()] << std::endl;
554  std::cout << "  "  << cc_send_fsm_str[r_cc_send_fsm.read()]
555            << " | " << cc_receive_fsm_str[r_cc_receive_fsm.read()]
556            << " | " << multi_ack_fsm_str[r_multi_ack_fsm.read()]
557            << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]
558            << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]
559            << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
560  std::cout << "  "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]
561            << " | " << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]
562            << " | " << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]
563            << " | " << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
564}
565
566/////////////////////////////////////////
567tmpl(void) ::print_stats()
568/////////////////////////////////////////
569{
570  std::cout << "----------------------------------" << std::dec << std::endl;
571  std::cout
572      << "MEM_CACHE " << name() << " / Time = " << m_cpt_cycles << std::endl
573      << "- READ RATE            = " << (double) m_cpt_read/m_cpt_cycles << std::endl
574      << "- READ TOTAL           = " << m_cpt_read << std::endl
575      << "- READ MISS RATE       = " << (double) m_cpt_read_miss/m_cpt_read << std::endl
576      << "- WRITE RATE           = " << (double) m_cpt_write/m_cpt_cycles << std::endl
577      << "- WRITE TOTAL          = " << m_cpt_write << std::endl
578      << "- WRITE MISS RATE      = " << (double) m_cpt_write_miss/m_cpt_write << std::endl
579      << "- WRITE BURST LENGTH   = " << (double) m_cpt_write_cells/m_cpt_write << std::endl
580      << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
581      << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
582      << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
583      << "- UPDATE RATE          = " << (double) m_cpt_update/m_cpt_cycles << std::endl
584      << "- UPDATE ARITY         = " << (double) m_cpt_update_mult/m_cpt_update << std::endl
585      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast) /m_cpt_cycles << std::endl
586      << "- INVAL MULTICAST ARITY= " << (double) m_cpt_inval_mult/ (m_cpt_inval-m_cpt_inval_brdcast) << std::endl
587      << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl
588      << "- SAVE DIRTY RATE      = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl
589      << "- CLEANUP RATE         = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl
590      << "- LL RATE              = " << (double) m_cpt_ll/m_cpt_cycles << std::endl
591      << "- SC RATE              = " << (double) m_cpt_sc/m_cpt_cycles << std::endl
592      << "- CAS RATE             = " << (double) m_cpt_cas/m_cpt_cycles << std::endl;
593}
594
595/////////////////////////////////
596tmpl(/**/) ::~VciMemCache()
597/////////////////////////////////
598{
599  delete [] r_ixr_rsp_to_xram_rsp_rok;
600
601  delete [] r_xram_rsp_victim_data;
602  delete [] r_xram_rsp_to_tgt_rsp_data;
603  delete [] r_xram_rsp_to_ixr_cmd_data;
604
605  delete [] r_read_data;
606  delete [] r_read_to_tgt_rsp_data;
607
608  delete [] r_write_data;
609  delete [] r_write_be;
610  delete [] r_write_to_cc_send_data;
611}
612
613//////////////////////////////////
614tmpl(void) ::transition()
615//////////////////////////////////
616{
617  using soclib::common::uint32_log2;
618
619  // RESET
620  if(! p_resetn.read())
621  {
622
623    // Initializing FSMs
624    r_tgt_cmd_fsm    = TGT_CMD_IDLE;
625    r_tgt_rsp_fsm    = TGT_RSP_READ_IDLE;
626    r_cc_send_fsm    = CC_SEND_XRAM_RSP_IDLE;
627    r_cc_receive_fsm = CC_RECEIVE_IDLE;
628    r_multi_ack_fsm  = MULTI_ACK_IDLE;
629    r_read_fsm       = READ_IDLE;
630    r_write_fsm      = WRITE_IDLE;
631    r_cas_fsm        = CAS_IDLE;
632    r_cleanup_fsm    = CLEANUP_IDLE;
633    r_alloc_dir_fsm  = ALLOC_DIR_RESET;
634    r_alloc_heap_fsm = ALLOC_HEAP_RESET;
635    r_alloc_trt_fsm  = ALLOC_TRT_READ;
636    r_alloc_upt_fsm  = ALLOC_UPT_WRITE;
637    r_ixr_rsp_fsm    = IXR_RSP_IDLE;
638    r_xram_rsp_fsm   = XRAM_RSP_IDLE;
639    r_ixr_cmd_fsm    = IXR_CMD_READ_IDLE;
640
641    m_debug_global         = false;
642    m_debug_tgt_cmd_fsm    = false;
643    m_debug_tgt_rsp_fsm    = false;
644    m_debug_cc_send_fsm    = false;
645    m_debug_cc_receive_fsm = false;
646    m_debug_multi_ack_fsm  = false;
647    m_debug_read_fsm       = false;
648    m_debug_write_fsm      = false;
649    m_debug_cas_fsm        = false;
650    m_debug_cleanup_fsm    = false;
651    m_debug_ixr_cmd_fsm    = false;
652    m_debug_ixr_rsp_fsm    = false;
653    m_debug_xram_rsp_fsm   = false;
654    m_debug_previous_hit   = false;
655    m_debug_previous_count = 0;
656
657    //  Initializing Tables
658    m_trt.init();
659    m_upt.init();
660    m_llsc_table.init();
661
662    // initializing FIFOs and communication Buffers
663
664    m_cmd_read_addr_fifo.init();
665    m_cmd_read_length_fifo.init();
666    m_cmd_read_srcid_fifo.init();
667    m_cmd_read_trdid_fifo.init();
668    m_cmd_read_pktid_fifo.init();
669
670    m_cmd_write_addr_fifo.init();
671    m_cmd_write_eop_fifo.init();
672    m_cmd_write_srcid_fifo.init();
673    m_cmd_write_trdid_fifo.init();
674    m_cmd_write_pktid_fifo.init();
675    m_cmd_write_data_fifo.init();
676
677    m_cmd_cas_addr_fifo.init()  ;
678    m_cmd_cas_srcid_fifo.init() ;
679    m_cmd_cas_trdid_fifo.init() ;
680    m_cmd_cas_pktid_fifo.init() ;
681    m_cmd_cas_wdata_fifo.init() ;
682    m_cmd_cas_eop_fifo.init()   ;
683
684    r_read_to_tgt_rsp_req = false;
685    r_read_to_ixr_cmd_req = false;
686
687    r_write_to_tgt_rsp_req          = false;
688    r_write_to_ixr_cmd_req          = false;
689    r_write_to_cc_send_multi_req   = false;
690    r_write_to_cc_send_brdcast_req = false;
691    r_write_to_multi_ack_req        = false;
692
693    m_write_to_cc_send_inst_fifo.init();
694    m_write_to_cc_send_srcid_fifo.init();
695#if L1_MULTI_CACHE
696    m_write_to_cc_send_cache_id_fifo.init();
697#endif
698
699    r_cleanup_to_tgt_rsp_req      = false;
700
701    m_cc_receive_to_cleanup_fifo.init();
702
703    r_multi_ack_to_tgt_rsp_req     = false;
704
705    m_cc_receive_to_multi_ack_fifo.init();
706
707    r_cas_to_tgt_rsp_req          = false;
708    r_cas_cpt                     = 0    ;
709    r_cas_lfsr                    = -1   ;
710    r_cas_to_ixr_cmd_req          = false;
711    r_cas_to_cc_send_multi_req   = false;
712    r_cas_to_cc_send_brdcast_req = false;
713
714    m_cas_to_cc_send_inst_fifo.init();
715    m_cas_to_cc_send_srcid_fifo.init();
716#if L1_MULTI_CACHE
717    m_cas_to_cc_send_cache_id_fifo.init();
718#endif
719
720    for(size_t i=0; i<m_trt_lines ; i++)
721    {
722      r_ixr_rsp_to_xram_rsp_rok[i] = false;
723    }
724
725    r_xram_rsp_to_tgt_rsp_req          = false;
726    r_xram_rsp_to_cc_send_multi_req   = false;
727    r_xram_rsp_to_cc_send_brdcast_req = false;
728    r_xram_rsp_to_ixr_cmd_req          = false;
729    r_xram_rsp_trt_index               = 0;
730
731    m_xram_rsp_to_cc_send_inst_fifo.init();
732    m_xram_rsp_to_cc_send_srcid_fifo.init();
733#if L1_MULTI_CACHE
734    m_xram_rsp_to_cc_send_cache_id_fifo.init();
735#endif
736
737    r_ixr_cmd_cpt          = 0;
738    r_alloc_dir_reset_cpt  = 0;
739    r_alloc_heap_reset_cpt = 0;
740
741    r_tgt_rsp_key_sent  = false;
742
743    // Activity counters
744    m_cpt_cycles        = 0;
745    m_cpt_read          = 0;
746    m_cpt_read_miss     = 0;
747    m_cpt_write         = 0;
748    m_cpt_write_miss    = 0;
749    m_cpt_write_cells   = 0;
750    m_cpt_write_dirty   = 0;
751    m_cpt_update        = 0;
752    m_cpt_update_mult   = 0;
753    m_cpt_inval_brdcast = 0;
754    m_cpt_inval         = 0;
755    m_cpt_inval_mult    = 0;
756    m_cpt_cleanup       = 0;
757    m_cpt_ll            = 0;
758    m_cpt_sc            = 0;
759    m_cpt_cas           = 0;
760    m_cpt_trt_full      = 0;
761    m_cpt_trt_rb        = 0;
762
763    return;
764  }
765
766  bool    cmd_read_fifo_put = false;
767  bool    cmd_read_fifo_get = false;
768
769  bool    cmd_write_fifo_put = false;
770  bool    cmd_write_fifo_get = false;
771
772  bool    cmd_cas_fifo_put = false;
773  bool    cmd_cas_fifo_get = false;
774
775  bool    cc_receive_to_cleanup_fifo_get = false;
776  bool    cc_receive_to_cleanup_fifo_put = false;
777   
778  bool    cc_receive_to_multi_ack_fifo_get = false;
779  bool    cc_receive_to_multi_ack_fifo_put = false;
780
781  bool    write_to_cc_send_fifo_put   = false;
782  bool    write_to_cc_send_fifo_get   = false;
783  bool    write_to_cc_send_fifo_inst  = false;
784  size_t  write_to_cc_send_fifo_srcid = 0;
785
786#if L1_MULTI_CACHE
787  size_t  write_to_cc_send_fifo_cache_id = 0;
788#endif
789
790  bool    xram_rsp_to_cc_send_fifo_put   = false;
791  bool    xram_rsp_to_cc_send_fifo_get   = false;
792  bool    xram_rsp_to_cc_send_fifo_inst  = false;
793  size_t  xram_rsp_to_cc_send_fifo_srcid = 0;
794
795#if L1_MULTI_CACHE
796  size_t  xram_rsp_to_cc_send_fifo_cache_id = 0;
797#endif
798
799  bool    cas_to_cc_send_fifo_put   = false;
800  bool    cas_to_cc_send_fifo_get   = false;
801  bool    cas_to_cc_send_fifo_inst  = false;
802  size_t  cas_to_cc_send_fifo_srcid = 0;
803
804#if L1_MULTI_CACHE
805  size_t  cas_to_cc_send_fifo_cache_id = 0;
806#endif
807
808  m_debug_global         = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
809  m_debug_tgt_cmd_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
810  m_debug_tgt_rsp_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
811  m_debug_cc_send_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
812  m_debug_cc_receive_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
813  m_debug_multi_ack_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
814  m_debug_read_fsm       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
815  m_debug_write_fsm      = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
816  m_debug_cas_fsm        = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
817  m_debug_cleanup_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
818  m_debug_ixr_cmd_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
819  m_debug_ixr_rsp_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
820  m_debug_xram_rsp_fsm   = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
821
822#if DEBUG_MEMC_GLOBAL
823  if(m_debug_global)
824  {
825    std::cout
826        << "---------------------------------------------"           << std::dec << std::endl
827        << "MEM_CACHE "            << name() 
828        << " ; Time = "            << m_cpt_cycles                                << std::endl
829        << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
830        << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
831        << " - CC_SEND FSM  = "    << cc_send_fsm_str[r_cc_send_fsm.read()]       << std::endl
832        << " - CC_RECEIVE FSM  = " << cc_receive_fsm_str[r_cc_receive_fsm.read()] << std::endl
833        << " - MULTI_ACK FSM  = "  << multi_ack_fsm_str[r_multi_ack_fsm.read()]   << std::endl
834        << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
835        << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
836        << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
837        << " - CLEANUP FSM    = "  << cleanup_fsm_str[r_cleanup_fsm.read()]       << std::endl
838        << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
839        << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
840        << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
841        << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
842        << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
843        << " - ALLOC_UPT FSM  = "  << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]   << std::endl
844        << " - ALLOC_HEAP FSM = "  << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
845  }
846#endif
847
848  ////////////////////////////////////////////////////////////////////////////////////
849  //    TGT_CMD FSM
850  ////////////////////////////////////////////////////////////////////////////////////
851  // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
852  //
853  // There are 5 types of accepted commands :
854  // - READ   : A READ request has a length of 1 VCI cell. It can be a single word
855  //            or an entire cache line, depending on the PLEN value.
856  // - WRITE  : A WRITE request has a maximum length of 16 cells, and can only
857  //            concern words in a same line.
858  // - CAS    : A CAS request has a length of 2 cells or 4 cells.
859  // - LL     : An LL request has a length of 1 cell.
860  // - SC     : An SC request has a length of 2 cells. First cell contains the
861  //            acces key, second cell the data to write in case of success.
862  ////////////////////////////////////////////////////////////////////////////////////
863
864  switch(r_tgt_cmd_fsm.read())
865  {
866      //////////////////
867    case TGT_CMD_IDLE:
868      if(p_vci_tgt.cmdval)
869      {
870
871#if DEBUG_MEMC_TGT_CMD
872        if(m_debug_tgt_cmd_fsm)
873        {
874          std::cout
875              << "  <MEMC " << name()
876              << " TGT_CMD_IDLE> Receive command from srcid "
877              << std::dec << p_vci_tgt.srcid.read()
878              << " / for address "
879              << std::hex << p_vci_tgt.address.read()
880              << std::endl;
881        }
882#endif
883        // checking segmentation violation
884        addr_t  address = p_vci_tgt.address.read();
885        uint32_t    plen    = p_vci_tgt.plen.read();
886        bool found = false;
887        for(size_t seg_id = 0 ; seg_id < m_nseg ; seg_id++)
888        {
889          if(m_seg[seg_id]->contains(address) &&
890              m_seg[seg_id]->contains(address + plen - vci_param_int::B))
891          {
892            found = true;
893          }
894        }
895        if(not found)
896        {
897          std::cout << "VCI_MEM_CACHE ERROR " << name() << std::endl;
898          std::cout
899              << "Out of segment VCI address in TGT_CMD_IDLE state (address = "
900              << std::hex << address << ", srcid = " << p_vci_tgt.srcid.read()
901              << std::dec << ", cycle = " << m_cpt_cycles << ")" << std::endl;
902          exit(0);
903        }
904
905        if(p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
906        {
907          // check that the pktid is either :
908          // TYPE_READ_DATA_UNC
909          // TYPE_READ_DATA_MISS
910          // TYPE_READ_INS_UNC
911          // TYPE_READ_INS_MISS
912          // ==> bit2 must be zero with the TSAR encoding
913          // ==> mask = 0b0100 = 0x4
914          assert(((p_vci_tgt.pktid.read() & 0x4) == 0x0) &&
915                 "The type specified in the pktid field is incompatible with the READ CMD");
916          r_tgt_cmd_fsm = TGT_CMD_READ;
917        }
918        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
919        {
920          // check that the pktid is TYPE_WRITE
921          // ==> TYPE_WRITE = X100 with the TSAR encoding
922          // ==> mask = 0b0111 = 0x7
923          assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) &&
924                 "The type specified in the pktid field is incompatible with the WRITE CMD");
925          r_tgt_cmd_fsm = TGT_CMD_WRITE;
926        }
927        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
928        {
929          // check that the pktid is TYPE_LL
930          // ==> TYPE_LL = X110 with the TSAR encoding
931          // ==> mask = 0b0111 = 0x7
932          assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) &&
933                 "The type specified in the pktid field is incompatible with the LL CMD");
934          r_tgt_cmd_fsm = TGT_CMD_READ;
935        }
936        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
937        {
938          // check that the pktid is either :
939          // TYPE_CAS
940          // TYPE_SC
941          // ==> TYPE_CAS = X101 with the TSAR encoding
942          // ==> TYPE_SC  = X111 with the TSAR encoding
943          // ==> mask = 0b0101 = 0x5
944          assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) &&
945                 "The type specified in the pktid field is incompatible with the NOP CMD");
946
947          if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS)
948            r_tgt_cmd_fsm = TGT_CMD_CAS;
949          else // TYPE_SC
950            r_tgt_cmd_fsm = TGT_CMD_WRITE;
951        }
952        else
953        {
954          std::cout << "VCI_MEM_CACHE ERROR " << name()
955                    << " TGT_CMD_IDLE state" << std::endl;
956          std::cout << " illegal VCI command type" << std::endl;
957          exit(0);
958        }
959      }
960      break;
961
962      //////////////////
963    case TGT_CMD_READ:
964      // This test checks that the read does not cross a cache line limit.
965      // It must not be taken into account when dealing with an LL CMD.
966      if(((m_x[(addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) && 
967          (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ))
968      {
969        std::cout
970            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
971            << std::endl;
972        std::cout
973            << " illegal address/plen combination for VCI read command" << std::endl;
974        exit(0);
975      }
976      if(!p_vci_tgt.eop.read())
977      {
978        std::cout
979            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
980            << std::endl;
981        std::cout
982            << " read or ll command packets must contain one single flit"
983            << std::endl;
984        exit(0);
985      }
986      if((p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) && (p_vci_tgt.plen.read() != 8))
987      {
988        std::cout
989            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
990            << std::endl;
991        std::cout
992            << " ll command packets must have a plen of 8"
993            << std::endl;
994        exit(0);
995      }
996
997      if(p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok())
998      {
999
1000#if DEBUG_MEMC_TGT_CMD
1001        if(m_debug_tgt_cmd_fsm)
1002        {
1003          std::cout << "  <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:"
1004                    << " address = " << std::hex << p_vci_tgt.address.read()
1005                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
1006                    << " trdid = " << p_vci_tgt.trdid.read()
1007                    << " pktid = " << p_vci_tgt.pktid.read()
1008                    << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1009        }
1010#endif
1011        cmd_read_fifo_put = true;
1012        if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
1013          m_cpt_ll++;
1014        else
1015          m_cpt_read++;
1016        r_tgt_cmd_fsm = TGT_CMD_IDLE;
1017      }
1018      break;
1019
1020      ///////////////////
1021    case TGT_CMD_WRITE:
1022      if(p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok())
1023      {
1024
1025#if DEBUG_MEMC_TGT_CMD
1026        if(m_debug_tgt_cmd_fsm)
1027        {
1028          std::cout << "  <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:"
1029                    << " address = " << std::hex << p_vci_tgt.address.read()
1030                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
1031                    << " trdid = " << p_vci_tgt.trdid.read()
1032                    << " pktid = " << p_vci_tgt.pktid.read()
1033                    << " wdata = " << std::hex << p_vci_tgt.wdata.read()
1034                    << " be = " << p_vci_tgt.be.read()
1035                    << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1036        }
1037#endif
1038        cmd_write_fifo_put = true;
1039        if(p_vci_tgt.eop)  r_tgt_cmd_fsm = TGT_CMD_IDLE;
1040      }
1041      break;
1042
1043      ////////////////////
1044    case TGT_CMD_CAS:
1045      if((p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16))
1046      {
1047        std::cout
1048            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
1049            << std::endl
1050            << "illegal format for CAS command " << std::endl;
1051
1052        exit(0);
1053      }
1054
1055      if(p_vci_tgt.cmdval && m_cmd_cas_addr_fifo.wok())
1056      {
1057
1058#if DEBUG_MEMC_TGT_CMD
1059        if(m_debug_tgt_cmd_fsm)
1060        {
1061          std::cout << "  <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
1062                    << " address = " << std::hex << p_vci_tgt.address.read()
1063                    << " srcid = " << std::dec << p_vci_tgt.srcid.read()
1064                    << " trdid = " << p_vci_tgt.trdid.read()
1065                    << " pktid = " << p_vci_tgt.pktid.read()
1066                    << " wdata = " << std::hex << p_vci_tgt.wdata.read()
1067                    << " be = " << p_vci_tgt.be.read()
1068                    << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1069        }
1070#endif
1071        cmd_cas_fifo_put = true;
1072        if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE;
1073      }
1074      break;
1075  } // end switch tgt_cmd_fsm
1076
1077  /////////////////////////////////////////////////////////////////////////
1078  //    MULTI_ACK FSM
1079  /////////////////////////////////////////////////////////////////////////
1080  // This FSM controls the response to the multicast update or multicast
1081  // inval coherence requests sent by the memory cache to the L1 caches and
1082  // update the UPT.
1083  //
1084  // It can be update or inval requests initiated by the WRITE or CAS FSM,
1085  // or inval requests initiated by the XRAM_RSP FSM.
1086  // It can also be a direct request from the WRITE FSM.
1087  //
1088  // The FSM decrements the proper entry in UPT.
1089  // It sends a request to the TGT_RSP FSM to complete the pending
1090  // write transaction (acknowledge response to the writer processor),
1091  // and clear the UPT entry when all responses have been received.
1092  //
1093  // All those response packets are one flit packet.
1094  // The index in the Table is defined in the UPDT_TABLE INDEX field, and
1095  // the transaction type is defined in the UPT entry.
1096  ////////////////////////////////////////////////////////////////////////
1097
1098  switch(r_multi_ack_fsm.read())
1099  {
1100    ///////////////////
1101    case MULTI_ACK_IDLE:
1102      {
1103        bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok();
1104
1105        // No CC_RECEIVE FSM request and no WRITE FSM request
1106        if( not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read()) break;
1107
1108        // handling WRITE FSM request to decrement update table response counter
1109        // if no CC_RECEIVE FSM request
1110        if(not multi_ack_fifo_rok)
1111        {
1112          r_write_to_multi_ack_req = false;
1113          r_multi_ack_upt_index    = r_write_to_multi_ack_upt_index.read();
1114          r_multi_ack_fsm          = MULTI_ACK_UPT_LOCK;
1115
1116          break;
1117        }
1118
1119        // Handling CC_RECEIVE FSM request
1120        uint64_t flit = m_cc_receive_to_multi_ack_fifo.read();
1121
1122        uint8_t updt_index = 
1123          DspinDhccpParam::dspin_get(flit, DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
1124
1125        assert( (updt_index < m_upt.size()) and
1126        "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : index too large for UPT");
1127
1128        cc_receive_to_multi_ack_fifo_get = true;
1129        r_multi_ack_upt_index           = updt_index;
1130        r_multi_ack_fsm                 = MULTI_ACK_UPT_LOCK;
1131
1132#if DEBUG_MEMC_MULTI_ACK
1133        if(m_debug_multi_ack_fsm)
1134        {
1135          std::cout
1136            <<  "  <MEMC " << name()
1137            << " MULTI_ACK_IDLE> Response for UPT entry "
1138            << updt_index
1139            << std::endl;
1140        }
1141#endif
1142        break;
1143      }
1144
1145    ////////////////////////
1146    case MULTI_ACK_UPT_LOCK:
1147      {
1148        // get lock to the UPDATE table
1149        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
1150
1151        // decrement the number of expected responses
1152        size_t count = 0;
1153        bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
1154
1155        if(not valid)
1156        {
1157          std::cout
1158            << "VCI_MEM_CACHE ERROR " << name()
1159            << " MULTI_ACK_UPT_LOCK state" << std::endl
1160            << "unsuccessful access to decrement the UPT"
1161            << std::endl;
1162
1163          exit(0);
1164        }
1165
1166        if(count == 0)
1167        {
1168          r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR;
1169        }
1170        else
1171        {
1172          r_multi_ack_fsm = MULTI_ACK_IDLE;
1173        }
1174
1175#if DEBUG_MEMC_MULTI_ACK
1176        if(m_debug_multi_ack_fsm)
1177        {
1178          std::cout
1179            << "  <MEMC " << name()
1180            << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:"
1181            << " entry = "       << r_multi_ack_upt_index.read()
1182            << " / rsp_count = " << std::dec << count
1183            << std::endl;
1184        }
1185#endif
1186        break;
1187      }
1188
1189    /////////////////////////
1190    case MULTI_ACK_UPT_CLEAR:
1191      {
1192        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)
1193        {
1194          std::cout
1195            << "VCI_MEM_CACHE ERROR " << name()
1196            << " MULTI_ACK_UPT_CLEAR state"
1197            << " bad UPT allocation"
1198            << std::endl;
1199
1200          exit(0);
1201        }
1202
1203        r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read());
1204        r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read());
1205        r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read());
1206        r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read());
1207        bool need_rsp     = m_upt.need_rsp(r_multi_ack_upt_index.read());
1208
1209        // clear the UPT entry
1210        m_upt.clear(r_multi_ack_upt_index.read());
1211
1212        if(need_rsp)
1213        {
1214          r_multi_ack_fsm = MULTI_ACK_WRITE_RSP;
1215        }
1216        else
1217        {
1218          r_multi_ack_fsm = MULTI_ACK_IDLE;
1219        }
1220
1221#if DEBUG_MEMC_MULTI_ACK
1222        if(m_debug_multi_ack_fsm)
1223        {
1224          std::cout
1225            <<  "  <MEMC " << name()
1226            << " MULTI_ACK_UPT_CLEAR> Clear UPT entry "
1227            << r_multi_ack_upt_index.read()
1228            << std::endl;
1229        }
1230#endif
1231        break;
1232      }
1233
1234    /////////////////////////
1235    case MULTI_ACK_WRITE_RSP:
1236      {
1237        // Post a request to TGT_RSP FSM
1238        // Wait if pending request to the TGT_RSP FSM
1239        if(r_multi_ack_to_tgt_rsp_req.read()) break;
1240
1241        r_multi_ack_to_tgt_rsp_req   = true;
1242        r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read();
1243        r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read();
1244        r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read();
1245        r_multi_ack_fsm              = MULTI_ACK_IDLE;
1246
1247#if DEBUG_MEMC_MULTI_ACK
1248        if(m_debug_multi_ack_fsm)
1249        {
1250          std::cout
1251            << "  <MEMC " << name()
1252            << " MULTI_ACK_WRITE_RSP> Request TGT_RSP FSM to send a response to srcid "
1253            << r_multi_ack_srcid.read()
1254            << std::endl;
1255        }
1256#endif
1257        break;
1258      }
1259  } // end switch r_multi_ack_fsm
1260
1261  ////////////////////////////////////////////////////////////////////////////////////
1262  //    READ FSM
1263  ////////////////////////////////////////////////////////////////////////////////////
1264  // The READ FSM controls the VCI read  and ll requests.
1265  // It takes the lock protecting the cache directory to check the cache line status:
1266  // - In case of HIT
1267  //   The fsm copies the data (one line, or one single word)
1268  //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
1269  //   The requesting initiator is registered in the cache directory.
1270  //   If the number of copy is larger than 1, the new copy is registered
1271  //   in the HEAP.
1272  //   If the number of copy is larger than the threshold, the HEAP is cleared,
1273  //   and the corresponding line switches to the counter mode.
1274  // - In case of MISS
1275  //   The READ fsm takes the lock protecting the transaction tab.
1276  //   If a read transaction to the XRAM for this line already exists,
1277  //   or if the transaction tab is full, the fsm is stalled.
1278  //   If a TRT entry is free, the READ request is registered in TRT,
1279  //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
1280  //   The READ FSM returns in the IDLE state as the read transaction will be
1281  //   completed when the missing line will be received.
1282  ////////////////////////////////////////////////////////////////////////////////////
1283
1284  switch(r_read_fsm.read())
1285  {
1286    ///////////////
1287    case READ_IDLE:
1288      // waiting a read request
1289    {
1290      if(m_cmd_read_addr_fifo.rok())
1291      {
1292
1293#if DEBUG_MEMC_READ
1294if(m_debug_read_fsm)
1295std::cout << "  <MEMC " << name() << " READ_IDLE> Read request:"
1296          << " srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
1297          << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
1298          << " / pktid = " << std::hex << m_cmd_read_pktid_fifo.read()
1299          << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1300#endif
1301        r_read_fsm = READ_DIR_REQ;
1302      }
1303      break;
1304    }
1305
1306    ///////////////////
1307    case READ_DIR_REQ:
1308      // Get the lock to the directory
1309    {
1310      if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
1311      {
1312        r_read_fsm = READ_DIR_LOCK;
1313      }
1314
1315#if DEBUG_MEMC_READ
1316if(m_debug_read_fsm)
1317std::cout << "  <MEMC " << name() << " READ_DIR_REQ> Requesting DIR lock " << std::endl;
1318#endif
1319      break;
1320    }
1321
1322    ///////////////////
1323    case READ_DIR_LOCK:
1324      // check directory for hit / miss
1325    {
1326      if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
1327      {
1328        size_t way = 0;
1329        DirectoryEntry entry =
1330          m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
1331        if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)   // access the global table ONLY when we have an LL cmd
1332        {
1333          r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
1334        }
1335        r_read_is_cnt     = entry.is_cnt;
1336        r_read_dirty      = entry.dirty;
1337        r_read_lock       = entry.lock;
1338        r_read_tag        = entry.tag;
1339        r_read_way        = way;
1340        r_read_count      = entry.count;
1341        r_read_copy       = entry.owner.srcid;
1342
1343#if L1_MULTI_CACHE
1344        r_read_copy_cache = entry.owner.cache_id;
1345#endif
1346        r_read_copy_inst  = entry.owner.inst;
1347        r_read_ptr        = entry.ptr; // pointer to the heap
1348
1349        // check if this is a cached read, this means pktid is either
1350        // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
1351        // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
1352        bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
1353        if(entry.valid)    // hit
1354        {
1355          // test if we need to register a new copy in the heap
1356          if(entry.is_cnt || (entry.count == 0) || !cached_read)
1357          {
1358            r_read_fsm = READ_DIR_HIT;
1359          }
1360          else
1361          {
1362            r_read_fsm = READ_HEAP_REQ;
1363          }
1364        }
1365        else      // miss
1366        {
1367          r_read_fsm = READ_TRT_LOCK;
1368        }
1369
1370#if DEBUG_MEMC_READ
1371if(m_debug_read_fsm)
1372{
1373std::cout << "  <MEMC " << name() << " READ_DIR_LOCK> Accessing directory: "
1374          << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1375          << " / hit = " << std::dec << entry.valid
1376          << " / count = " <<std::dec << entry.count
1377          << " / is_cnt = " << entry.is_cnt;
1378if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) std::cout << " / LL access" << std::endl;
1379else                                                std::cout << std::endl;
1380}
1381#endif
1382      }
1383      else
1384      {
1385        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_DIR_LOCK state" 
1386                  << "Bad DIR allocation"   << std::endl;
1387        exit(0);
1388      }
1389      break;
1390    }
1391
1392    //////////////////
1393    case READ_DIR_HIT:
1394    {
1395      //  read data in cache & update the directory
1396      //  we enter this state in 3 cases:
1397      //  - the read request is uncachable
1398      //  - the cache line is in counter mode
1399      //  - the cache line is valid but not replcated
1400
1401      if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
1402      {
1403        // check if this is an instruction read, this means pktid is either
1404        // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
1405        // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
1406        bool inst_read    = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
1407        // check if this is a cached read, this means pktid is either
1408        // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
1409        // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
1410        bool cached_read  = (m_cmd_read_pktid_fifo.read() & 0x1);
1411        bool is_cnt       = r_read_is_cnt.read();
1412
1413        // read data in the cache
1414        size_t set        = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
1415        size_t way        = r_read_way.read();
1416
1417        m_cache_data.read_line(way, set, r_read_data);
1418
1419        // update the cache directory
1420        DirectoryEntry entry;
1421        entry.valid   = true;
1422        entry.is_cnt  = is_cnt;
1423        entry.dirty   = r_read_dirty.read();
1424        entry.tag     = r_read_tag.read();
1425        entry.lock    = r_read_lock.read();
1426        entry.ptr     = r_read_ptr.read();
1427        if(cached_read)   // Cached read => we must update the copies
1428        {
1429          if(!is_cnt)  // Not counter mode
1430          {
1431            entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1432#if L1_MULTI_CACHE
1433            entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1434#endif
1435            entry.owner.inst     = inst_read;
1436            entry.count          = r_read_count.read() + 1;
1437          }
1438          else  // Counter mode
1439          {
1440            entry.owner.srcid    = 0;
1441#if L1_MULTI_CACHE
1442            entry.owner.cache_id = 0;
1443#endif
1444            entry.owner.inst     = false;
1445            entry.count          = r_read_count.read() + 1;
1446          }
1447        }
1448        else  // Uncached read
1449        {
1450          entry.owner.srcid     = r_read_copy.read();
1451#if L1_MULTI_CACHE
1452          entry.owner.cache_id  = r_read_copy_cache.read();
1453#endif
1454          entry.owner.inst      = r_read_copy_inst.read();
1455          entry.count           = r_read_count.read();
1456        }
1457
1458#if DEBUG_MEMC_READ
1459if(m_debug_read_fsm)
1460std::cout << "  <MEMC " << name() << " READ_DIR_HIT> Update directory entry:"
1461          << " addr = " << std::hex << m_cmd_read_addr_fifo.read()
1462          << " / set = " << std::dec << set
1463          << " / way = " << way
1464          << " / owner_id = " << entry.owner.srcid
1465          << " / owner_ins = " << entry.owner.inst
1466          << " / count = " << entry.count
1467          << " / is_cnt = " << entry.is_cnt << std::endl;
1468#endif
1469
1470          if(m_monitor_ok)
1471          {
1472            char buf[80];
1473            snprintf(buf, 80, "READ_DIR_HIT srcid %d, ins %d", 
1474                     (int)m_cmd_read_srcid_fifo.read(), 
1475                     (int)((m_cmd_read_pktid_fifo.read()&0x2)!=0));
1476            check_monitor(buf, m_cmd_read_addr_fifo.read(), r_read_data[0], true);
1477          }
1478
1479
1480        m_cache_directory.write(set, way, entry);
1481        r_read_fsm    = READ_RSP;
1482      }
1483      break;
1484    }
1485
1486    ///////////////////
1487    case READ_HEAP_REQ:    // Get the lock to the HEAP directory
1488    {
1489      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
1490      {
1491        r_read_fsm = READ_HEAP_LOCK;
1492      }
1493
1494#if DEBUG_MEMC_READ
1495if(m_debug_read_fsm)
1496std::cout << "  <MEMC " << name() << " READ_HEAP_REQ>" 
1497          << " Requesting HEAP lock " << std::endl;
1498#endif
1499      break;
1500    }
1501
1502    ////////////////////
1503    case READ_HEAP_LOCK:   // read data in cache, update the directory
1504                           // and prepare the HEAP update
1505    {
1506      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
1507      {
1508        // enter counter mode when we reach the limit of copies or the heap is full
1509        bool go_cnt = (r_read_count.read() >= m_max_copies) || m_heap.is_full();
1510
1511        // read data in the cache
1512        size_t set = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
1513        size_t way = r_read_way.read();
1514
1515        m_cache_data.read_line(way, set, r_read_data);
1516
1517        // update the cache directory
1518        DirectoryEntry entry;
1519        entry.valid  = true;
1520        entry.is_cnt = go_cnt;
1521        entry.dirty  = r_read_dirty.read();
1522        entry.tag    = r_read_tag.read();
1523        entry.lock   = r_read_lock.read();
1524        entry.count  = r_read_count.read() + 1;
1525
1526        if(not go_cnt)         // Not entering counter mode
1527        {
1528          entry.owner.srcid    = r_read_copy.read();
1529#if L1_MULTI_CACHE
1530          entry.owner.cache_id = r_read_copy_cache.read();
1531#endif
1532          entry.owner.inst     = r_read_copy_inst.read();
1533          entry.ptr            = m_heap.next_free_ptr();   // set pointer on the heap
1534        }
1535        else                // Entering Counter mode
1536        {
1537          entry.owner.srcid    = 0;
1538#if L1_MULTI_CACHE
1539          entry.owner.cache_id = 0;
1540#endif
1541          entry.owner.inst     = false;
1542          entry.ptr            = 0;
1543        }
1544
1545        m_cache_directory.write(set, way, entry);
1546
1547        // prepare the heap update (add an entry, or clear the linked list)
1548        if(not go_cnt)      // not switching to counter mode
1549        {
1550          // We test if the next free entry in the heap is the last
1551          HeapEntry heap_entry = m_heap.next_free_entry();
1552          r_read_next_ptr      = heap_entry.next;
1553          r_read_last_free     = (heap_entry.next == m_heap.next_free_ptr());
1554
1555          r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
1556        }
1557        else            // switching to counter mode
1558        {
1559          if(r_read_count.read() >1)              // heap must be cleared
1560          {
1561            HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1562            r_read_next_ptr      = m_heap.next_free_ptr();
1563            m_heap.write_free_ptr(r_read_ptr.read());
1564
1565            if(next_entry.next == r_read_ptr.read())    // last entry
1566            {
1567              r_read_fsm = READ_HEAP_LAST;    // erase the entry
1568            }
1569            else                                        // not the last entry
1570            {
1571              r_read_ptr = next_entry.next;
1572              r_read_fsm = READ_HEAP_ERASE;   // erase the list
1573            }
1574          }
1575          else  // the heap is not used / nothing to do
1576          {
1577            r_read_fsm = READ_RSP;
1578          }
1579        }
1580
1581#if DEBUG_MEMC_READ
1582if(m_debug_read_fsm)
1583std::cout << "  <MEMC " << name() << " READ_HEAP_LOCK> Update directory:"
1584          << " tag = " << std::hex << entry.tag
1585          << " set = " << std::dec << set
1586          << " way = " << way
1587          << " count = " << entry.count
1588          << " is_cnt = " << entry.is_cnt << std::endl;
1589#endif
1590      }
1591      else
1592      {
1593        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LOCK" 
1594                  << "Bad HEAP allocation"   << std::endl;
1595        exit(0);
1596      }
1597      break;
1598    }
1599    /////////////////////
1600    case READ_HEAP_WRITE:       // add an entry in the heap
1601    {
1602      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
1603      {
1604        HeapEntry heap_entry;
1605        heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1606#if L1_MULTI_CACHE
1607        heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1608#endif
1609        heap_entry.owner.inst     = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
1610
1611        if(r_read_count.read() == 1)  // creation of a new linked list
1612        {
1613          heap_entry.next         = m_heap.next_free_ptr();
1614        }
1615        else                         // head insertion in existing list
1616        {
1617          heap_entry.next         = r_read_ptr.read();
1618        }
1619        m_heap.write_free_entry(heap_entry);
1620        m_heap.write_free_ptr(r_read_next_ptr.read());
1621        if(r_read_last_free.read())  m_heap.set_full();
1622
1623        r_read_fsm = READ_RSP;
1624
1625#if DEBUG_MEMC_READ
1626if(m_debug_read_fsm)
1627std::cout << "  <MEMC " << name() << " READ_HEAP_WRITE> Add an entry in the heap:"
1628          << " owner_id = " << heap_entry.owner.srcid
1629          << " owner_ins = " << heap_entry.owner.inst << std::endl;
1630#endif
1631      }
1632      else
1633      {
1634        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_WRITE" 
1635                  << "Bad HEAP allocation" << std::endl;
1636        exit(0);
1637      }
1638      break;
1639    }
1640    /////////////////////
1641    case READ_HEAP_ERASE:
1642    {
1643      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
1644      {
1645        HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1646        if(next_entry.next == r_read_ptr.read())
1647        {
1648          r_read_fsm = READ_HEAP_LAST;
1649        }
1650        else
1651        {
1652          r_read_ptr = next_entry.next;
1653          r_read_fsm = READ_HEAP_ERASE;
1654        }
1655      }
1656      else
1657      {
1658        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_ERASE" 
1659                  << "Bad HEAP allocation" << std::endl;
1660        exit(0);
1661      }
1662      break;
1663    }
1664
1665    ////////////////////
1666    case READ_HEAP_LAST:
1667    {
1668      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
1669      {
1670        HeapEntry last_entry;
1671        last_entry.owner.srcid    = 0;
1672#if L1_MULTI_CACHE
1673        last_entry.owner.cache_id = 0;
1674#endif
1675        last_entry.owner.inst     = false;
1676
1677        if(m_heap.is_full())
1678        {
1679          last_entry.next       = r_read_ptr.read();
1680          m_heap.unset_full();
1681        }
1682        else
1683        {
1684          last_entry.next       = r_read_next_ptr.read();
1685        }
1686        m_heap.write(r_read_ptr.read(),last_entry);
1687        r_read_fsm = READ_RSP;
1688      }
1689      else
1690      {
1691        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LAST" 
1692                  << "Bad HEAP allocation" << std::endl;
1693        exit(0);
1694      }
1695      break;
1696    }
1697    //////////////
1698    case READ_RSP:    //  request the TGT_RSP FSM to return data
1699    {
1700      if(!r_read_to_tgt_rsp_req)
1701      {
1702        for(size_t i=0 ; i<m_words ; i++)  r_read_to_tgt_rsp_data[i] = r_read_data[i];
1703        r_read_to_tgt_rsp_word   = m_x[(addr_t) m_cmd_read_addr_fifo.read()];
1704        r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
1705        r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
1706        r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
1707        r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
1708        r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
1709        cmd_read_fifo_get        = true;
1710        r_read_to_tgt_rsp_req    = true;
1711        r_read_fsm               = READ_IDLE;
1712
1713#if DEBUG_MEMC_READ
1714if(m_debug_read_fsm)
1715std::cout << "  <MEMC " << name() << " READ_RSP> Request TGT_RSP FSM to return data:"
1716          << " rsrcid = " << std::dec << m_cmd_read_srcid_fifo.read()
1717          << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
1718          << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1719#endif
1720      }
1721      break;
1722    }
1723    ///////////////////
1724    case READ_TRT_LOCK: // read miss : check the Transaction Table
1725    {
1726      if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
1727      {
1728        size_t      index     = 0;
1729        addr_t      addr      = (addr_t) m_cmd_read_addr_fifo.read();
1730        bool        hit_read  = m_trt.hit_read(m_nline[addr], index);
1731        bool        hit_write = m_trt.hit_write(m_nline[addr]);
1732        bool        wok       = !m_trt.full(index);
1733
1734        if(hit_read || !wok || hit_write)    // missing line already requested or no space
1735        {
1736          if(!wok)      m_cpt_trt_full++;
1737          if(hit_read || hit_write)   m_cpt_trt_rb++;
1738          r_read_fsm = READ_IDLE;
1739        }
1740        else                  // missing line is requested to the XRAM
1741        {
1742          m_cpt_read_miss++;
1743          r_read_trt_index = index;
1744          r_read_fsm       = READ_TRT_SET;
1745        }
1746
1747#if DEBUG_MEMC_READ
1748if(m_debug_read_fsm)
1749std::cout << "  <MEMC " << name() << " READ_TRT_LOCK> Check TRT:"
1750          << " hit_read = " << hit_read
1751          << " / hit_write = " << hit_write
1752          << " / full = " << !wok << std::endl;
1753#endif
1754      }
1755      break;
1756    }
1757
1758    //////////////////
1759    case READ_TRT_SET:      // register get transaction in TRT
1760    {
1761      if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
1762      {
1763        m_trt.set(r_read_trt_index.read(),
1764                              true,
1765                              m_nline[(addr_t)(m_cmd_read_addr_fifo.read())],
1766                              m_cmd_read_srcid_fifo.read(),
1767                              m_cmd_read_trdid_fifo.read(),
1768                              m_cmd_read_pktid_fifo.read(),
1769                              true,
1770                              m_cmd_read_length_fifo.read(),
1771                              m_x[(addr_t)(m_cmd_read_addr_fifo.read())],
1772                              std::vector<be_t> (m_words,0),
1773                              std::vector<data_t> (m_words,0),
1774                              r_read_ll_key.read());
1775#if DEBUG_MEMC_READ
1776if(m_debug_read_fsm)
1777std::cout << "  <MEMC " << name() << " READ_TRT_SET> Write in Transaction Table:"
1778          << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1779          << " / srcid = " << std::dec << m_cmd_read_srcid_fifo.read() << std::endl;
1780#endif
1781        r_read_fsm = READ_TRT_REQ;
1782      }
1783      break;
1784    }
1785
1786    //////////////////
1787    case READ_TRT_REQ:   // consume the read request in FIFO and send it to IXR_CMD_FSM
1788    {
1789      if(not r_read_to_ixr_cmd_req)
1790      {
1791        cmd_read_fifo_get       = true;
1792        r_read_to_ixr_cmd_req   = true;
1793        r_read_to_ixr_cmd_nline = m_nline[(addr_t)(m_cmd_read_addr_fifo.read())];
1794        r_read_to_ixr_cmd_trdid = r_read_trt_index.read();
1795        r_read_fsm              = READ_IDLE;
1796
1797#if DEBUG_MEMC_READ
1798if(m_debug_read_fsm)
1799std::cout << "  <MEMC " << name() << " READ_TRT_REQ> Request GET transaction for address "
1800          << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
1801#endif
1802      }
1803      break;
1804    }
1805  } // end switch read_fsm
1806
1807  ///////////////////////////////////////////////////////////////////////////////////
1808  //    WRITE FSM
1809  ///////////////////////////////////////////////////////////////////////////////////
1810  // The WRITE FSM handles the write bursts and sc requests sent by the processors.
1811  // All addresses in a burst must be in the same cache line.
1812  // A complete write burst is consumed in the FIFO & copied to a local buffer.
1813  // Then the FSM takes the lock protecting the cache directory, to check
1814  // if the line is in the cache.
1815  //
1816  // - In case of HIT, the cache is updated.
1817  //   If there is no other copy, an acknowledge response is immediately
1818  //   returned to the writing processor.
1819  //   If the data is cached by other processors, a coherence transaction must
1820  //   be launched (sc requests always require a coherence transaction):
1821  //   It is a multicast update if the line is not in counter mode, and the processor
1822  //   takes the lock protecting the Update Table (UPT) to register this transaction.
1823  //   It is a broadcast invalidate if the line is in counter mode.
1824  //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
1825  //   a multi-update request to all owners of the line (but the writer),
1826  //   through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM
1827  //   does not respond to the writing processor, as this response will be sent by
1828  //   the MULTI_ACK FSM when all update responses have been received.
1829  //
1830  // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
1831  //   table (TRT). If a read transaction to the XRAM for this line already exists,
1832  //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
1833  //   the WRITE FSM register a new transaction in TRT, and sends a read line request
1834  //   to the XRAM. If the TRT is full, it releases the lock, and waits.
1835  //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
1836  /////////////////////////////////////////////////////////////////////////////////////
1837
1838  switch(r_write_fsm.read())
1839  {
1840      ////////////////
1841    case WRITE_IDLE:  // copy first word of a write burst in local buffer
1842    {
1843      if(m_cmd_write_addr_fifo.rok())
1844      {
1845        if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
1846          m_cpt_sc++;
1847        else
1848        {
1849          m_cpt_write++;
1850          m_cpt_write_cells++;
1851        }
1852
1853        // consume a word in the FIFO & write it in the local buffer
1854        cmd_write_fifo_get  = true;
1855        size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
1856
1857        r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
1858        r_write_word_index  = index;
1859        r_write_word_count  = 1;
1860        r_write_data[index] = m_cmd_write_data_fifo.read();
1861        r_write_srcid       = m_cmd_write_srcid_fifo.read();
1862        r_write_trdid       = m_cmd_write_trdid_fifo.read();
1863        r_write_pktid       = m_cmd_write_pktid_fifo.read();
1864        r_write_pending_sc  = false;
1865
1866        // initialize the be field for all words
1867        for(size_t word=0 ; word<m_words ; word++)
1868        {
1869          if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
1870          else              r_write_be[word] = 0x0;
1871        }
1872
1873        if (m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
1874        {
1875          r_write_fsm = WRITE_DIR_REQ;
1876        }
1877        else
1878        {
1879          r_write_fsm = WRITE_NEXT;
1880        }
1881
1882#if DEBUG_MEMC_WRITE
1883        if(m_debug_write_fsm)
1884        {
1885          std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
1886                    << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
1887                    << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
1888                    << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
1889        }
1890#endif
1891      }
1892      break;
1893    }
1894
1895    ////////////////
1896    case WRITE_NEXT:  // copy next word of a write burst in local buffer
1897    {
1898      if(m_cmd_write_addr_fifo.rok())
1899      {
1900
1901#if DEBUG_MEMC_WRITE
1902        if(m_debug_write_fsm)
1903        {
1904          std::cout << "  <MEMC " << name()
1905                    << " WRITE_NEXT> Write another word in local buffer"
1906                    << std::endl;
1907        }
1908#endif
1909        m_cpt_write_cells++;
1910
1911        // check that the next word is in the same cache line
1912        if((m_nline[(addr_t)(r_write_address.read())]       !=
1913            m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]))
1914        {
1915          std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_NEXT state" << std::endl
1916                    << "all words in a write burst must be in same cache line" << std::endl;
1917
1918          exit(0);
1919        }
1920
1921        // consume a word in the FIFO & write it in the local buffer
1922        cmd_write_fifo_get  = true;
1923        size_t index        = r_write_word_index.read() + r_write_word_count.read();
1924
1925        r_write_be[index]   = m_cmd_write_be_fifo.read();
1926        r_write_data[index] = m_cmd_write_data_fifo.read();
1927        r_write_word_count  = r_write_word_count.read() + 1;
1928
1929        if(m_cmd_write_eop_fifo.read())
1930        {
1931          r_write_fsm = WRITE_DIR_REQ;
1932        }
1933      }
1934      break;
1935    }
1936
1937    ////////////////////
1938    case WRITE_DIR_REQ:
1939    {
1940      // Get the lock to the directory
1941      // and access the llsc_global_table
1942      if(r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE)
1943      {
1944        ///////////////////////////////////////////////////////////////////////
1945        // SC command treatment
1946        // We test the r_write_pending_sc register to know if we are returning
1947        // from the WAIT state.
1948        // In this case, the SC has already succeed and we cannot consume
1949        // another time from the FIFO. Also, we don't have to test another
1950        // time if the SC has succeed
1951        if(((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
1952        {
1953          if(not m_cmd_write_addr_fifo.rok()) break;
1954
1955          assert(m_cmd_write_eop_fifo.read() &&
1956                 "Error in VCI_MEM_CACHE : "
1957                 "invalid packet format for SC command");
1958
1959          size_t index    = r_write_word_index.read();
1960          bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
1961                                            r_write_data[index].read());
1962
1963          // consume a word in the FIFO & write it in the local buffer
1964          cmd_write_fifo_get  = true;
1965          r_write_data[index] = m_cmd_write_data_fifo.read();
1966          r_write_sc_fail     = not sc_success;
1967          r_write_pending_sc  = true;
1968
1969          if(not sc_success) r_write_fsm = WRITE_RSP;
1970          else               r_write_fsm = WRITE_DIR_LOCK;
1971
1972          break;
1973        }
1974
1975        ///////////////////////////////////////////////////////////////////////
1976        // WRITE command treatment or SC command returning from the WAIT state
1977        // In the second case, we must access the LL/SC global table to
1978        // erase any possible new reservation when we release the lock on the
1979        // directory
1980        m_llsc_table.sw(r_write_address.read());
1981
1982        r_write_fsm = WRITE_DIR_LOCK;
1983      }
1984
1985#if DEBUG_MEMC_WRITE
1986      if(m_debug_write_fsm)
1987      {
1988        std::cout
1989            << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
1990            << std::endl;
1991      }
1992#endif
1993
1994      break;
1995    }
1996
1997    ////////////////////
1998    case WRITE_DIR_LOCK:
1999      // access directory to check hit/miss
2000    {
2001      if(r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE)
2002      {
2003        size_t  way = 0;
2004        DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
2005
2006        if(entry.valid)    // hit
2007        {
2008          // copy directory entry in local buffer in case of hit
2009          r_write_is_cnt     = entry.is_cnt;
2010          r_write_lock       = entry.lock;
2011          r_write_tag        = entry.tag;
2012          r_write_copy       = entry.owner.srcid;
2013#if L1_MULTI_CACHE
2014          r_write_copy_cache = entry.owner.cache_id;
2015#endif
2016          r_write_copy_inst  = entry.owner.inst;
2017          r_write_count      = entry.count;
2018          r_write_ptr        = entry.ptr;
2019          r_write_way        = way;
2020
2021          if(entry.is_cnt && entry.count)
2022          {
2023            r_write_fsm = WRITE_DIR_READ;
2024          }
2025          else
2026          {
2027            r_write_fsm = WRITE_DIR_HIT;
2028          }
2029        }
2030        else  // miss
2031        {
2032          r_write_fsm = WRITE_MISS_TRT_LOCK;
2033        }
2034
2035#if DEBUG_MEMC_WRITE
2036        if(m_debug_write_fsm)
2037        {
2038          std::cout << "  <MEMC " << name() << " WRITE_DIR_LOCK> Check the directory: "
2039                    << " address = " << std::hex << r_write_address.read()
2040                    << " hit = " << std::dec << entry.valid
2041                    << " count = " << entry.count
2042                    << " is_cnt = " << entry.is_cnt << std::endl;
2043          if((r_write_pktid.read() & 0x7) == TYPE_SC)
2044            std::cout << "  <MEMC " << name() << " WRITE_DIR_LOCK> global_llsc_table SC access" << std::endl;
2045          else
2046            std::cout << "  <MEMC " << name() << " WRITE_DIR_LOCK> global_llsc_table SW access" << std::endl;
2047        }
2048#endif
2049      }
2050      else
2051      {
2052        std::cout << "VCI_MEM_CACHE ERROR " << name()
2053                  << " WRITE_DIR_LOCK state"        << std::endl
2054                  << "bad DIR allocation"           << std::endl;
2055
2056        exit(0);
2057      }
2058
2059      break;
2060    }
2061
2062    ////////////////////
2063    case WRITE_DIR_READ:  // read the cache and complete the buffer when be!=0xF
2064    {
2065      // update local buffer
2066      size_t set  = m_y[(addr_t)(r_write_address.read())];
2067      size_t way  = r_write_way.read();
2068      for(size_t word=0 ; word<m_words ; word++)
2069      {
2070        data_t mask = 0;
2071        if(r_write_be[word].read() & 0x1) mask = mask | 0x000000FF;
2072        if(r_write_be[word].read() & 0x2) mask = mask | 0x0000FF00;
2073        if(r_write_be[word].read() & 0x4) mask = mask | 0x00FF0000;
2074        if(r_write_be[word].read() & 0x8) mask = mask | 0xFF000000;
2075
2076        // complete only if mask is not null (for energy consumption)
2077        r_write_data[word]  = (r_write_data[word].read() & mask) |
2078                              (m_cache_data.read(way, set, word) & ~mask);
2079
2080      } // end for
2081
2082      // test if a coherence broadcast is required
2083      r_write_fsm = WRITE_BC_TRT_LOCK;
2084
2085#if DEBUG_MEMC_WRITE
2086      if(m_debug_write_fsm)
2087      {
2088        std::cout << "  <MEMC " << name() << " WRITE_DIR_READ> Read the cache to complete local buffer" << std::endl;
2089      }
2090#endif
2091      break;
2092    }
2093
2094    ///////////////////
2095    case WRITE_DIR_HIT:
2096    {
2097      // update the cache directory
2098      // update directory with Dirty bit
2099      DirectoryEntry entry;
2100      entry.valid          = true;
2101      entry.dirty          = true;
2102      entry.tag          = r_write_tag.read();
2103      entry.is_cnt         = r_write_is_cnt.read();
2104      entry.lock           = r_write_lock.read();
2105      entry.owner.srcid    = r_write_copy.read();
2106#if L1_MULTI_CACHE
2107      entry.owner.cache_id = r_write_copy_cache.read();
2108#endif
2109      entry.owner.inst     = r_write_copy_inst.read();
2110      entry.count          = r_write_count.read();
2111      entry.ptr            = r_write_ptr.read();
2112
2113      size_t set           = m_y[(addr_t)(r_write_address.read())];
2114      size_t way           = r_write_way.read();
2115
2116      // update directory
2117      m_cache_directory.write(set, way, entry);
2118
2119      // owner is true when the  the first registered copy is the writer itself
2120      bool owner = (((r_write_copy.read() == r_write_srcid.read())
2121#if L1_MULTI_CACHE
2122                     and(r_write_copy_cache.read() ==r_write_pktid.read())
2123#endif
2124                    ) and not r_write_copy_inst.read());
2125
2126      // no_update is true when there is no need for coherence transaction
2127      // (tests for sc requests)
2128      bool no_update = ((r_write_count.read() ==0) || (owner && (r_write_count.read() ==1) && (r_write_pktid.read() != TYPE_SC)));
2129
2130      // write data in the cache if no coherence transaction
2131      if(no_update)
2132      {
2133        for(size_t word=0 ; word<m_words ; word++)
2134        {
2135          m_cache_data.write(way, set, word, r_write_data[word].read(), r_write_be[word].read());
2136
2137          if(m_monitor_ok)
2138          {
2139            addr_t address = (r_write_address.read() & ~(addr_t) 0x3F) | word<<2;
2140            char buf[80];
2141            snprintf(buf, 80, "WRITE_DIR_HIT srcid %d", 
2142                     (int)r_write_srcid.read());
2143            check_monitor(buf, address, r_write_data[word].read(), false);
2144          }
2145        }
2146      }
2147
2148      if(owner and not no_update and(r_write_pktid.read() != TYPE_SC))
2149      {
2150        r_write_count = r_write_count.read() - 1;
2151      }
2152
2153      if(no_update)
2154      // Write transaction completed
2155      {
2156        r_write_fsm = WRITE_RSP;
2157      }
2158      else
2159      // coherence update required
2160      {
2161        if(!r_write_to_cc_send_multi_req.read()   &&
2162            !r_write_to_cc_send_brdcast_req.read())
2163        {
2164          r_write_fsm = WRITE_UPT_LOCK;
2165        }
2166        else
2167        {
2168          r_write_fsm = WRITE_WAIT;
2169        }
2170      }
2171
2172#if DEBUG_MEMC_WRITE
2173      if(m_debug_write_fsm)
2174      {
2175        if(no_update)
2176        {
2177          std::cout << "  <MEMC " << name() << " WRITE_DIR_HIT> Write into cache / No coherence transaction"
2178                    << std::endl;
2179        }
2180        else
2181        {
2182          std::cout << "  <MEMC " << name() << " WRITE_DIR_HIT> Coherence update required:"
2183                    << " is_cnt = " << r_write_is_cnt.read()
2184                    << " nb_copies = " << std::dec << r_write_count.read() << std::endl;
2185          if(owner)
2186            std::cout << "       ... but the first copy is the writer" << std::endl;
2187        }
2188      }
2189#endif
2190      break;
2191    }
2192
2193    ////////////////////
2194    case WRITE_UPT_LOCK:  // Try to register the update request in UPT
2195    {
2196      if(r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE)
2197      {
2198        bool        wok        = false;
2199        size_t      index      = 0;
2200        size_t      srcid      = r_write_srcid.read();
2201        size_t      trdid      = r_write_trdid.read();
2202        size_t      pktid      = r_write_pktid.read();
2203        addr_t      nline      = m_nline[(addr_t)(r_write_address.read())];
2204        size_t      nb_copies  = r_write_count.read();
2205        size_t      set        = m_y[(addr_t)(r_write_address.read())];
2206        size_t      way        = r_write_way.read();
2207
2208        wok = m_upt.set(true,  // it's an update transaction
2209                               false,    // it's not a broadcast
2210                               true,     // it needs a response
2211                               srcid,
2212                               trdid,
2213                               pktid,
2214                               nline,
2215                               nb_copies,
2216                               index);
2217        if(wok)       // write data in cache
2218        {
2219          for(size_t word=0 ; word<m_words ; word++)
2220          {
2221            m_cache_data.write(way, 
2222                               set, 
2223                               word, 
2224                               r_write_data[word].read(), 
2225                               r_write_be[word].read());
2226
2227            if(m_monitor_ok)
2228            {
2229              addr_t address = (r_write_address.read() & ~(addr_t) 0x3F) | word<<2;
2230              char buf[80];
2231              snprintf(buf, 80, "WRITE_UPT_LOCK srcid %d", (int)srcid);
2232              check_monitor(buf, address, r_write_data[word].read(), false);
2233            }
2234          }
2235        }
2236
2237#if DEBUG_MEMC_WRITE
2238        if(m_debug_write_fsm)
2239        {
2240          if(wok)
2241          {
2242            std::cout << "  <MEMC " << name() << " WRITE_UPT_LOCK> Register the multicast update in UPT / "
2243                      << " nb_copies = " << r_write_count.read() << std::endl;
2244          }
2245        }
2246#endif
2247        r_write_upt_index = index;
2248        //  releases the lock protecting UPT and the DIR if no entry...
2249        if(wok) r_write_fsm = WRITE_UPT_HEAP_LOCK;
2250        else    r_write_fsm = WRITE_WAIT;
2251      }
2252      break;
2253    }
2254
2255    /////////////////////////
2256    case WRITE_UPT_HEAP_LOCK:   // get access to heap
2257    {
2258      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE)
2259      {
2260
2261#if DEBUG_MEMC_WRITE
2262        if(m_debug_write_fsm)
2263        {
2264          std::cout << "  <MEMC " << name() << " WRITE_UPT_HEAP_LOCK> Get acces to the HEAP" << std::endl;
2265        }
2266#endif
2267        r_write_fsm = WRITE_UPT_REQ;
2268      }
2269      break;
2270    }
2271
2272    //////////////////
2273    case WRITE_UPT_REQ:
2274    {
2275      // prepare the coherence transaction for the CC_SEND FSM
2276      // and write the first copy in the FIFO
2277      // send the request if only one copy
2278
2279      if(!r_write_to_cc_send_multi_req.read() &&
2280          !r_write_to_cc_send_brdcast_req.read())    // no pending coherence request
2281      {
2282        r_write_to_cc_send_brdcast_req  = false;
2283        r_write_to_cc_send_trdid        = r_write_upt_index.read();
2284        r_write_to_cc_send_nline        = m_nline[(addr_t)(r_write_address.read())];
2285        r_write_to_cc_send_index        = r_write_word_index.read();
2286        r_write_to_cc_send_count        = r_write_word_count.read();
2287
2288        for(size_t i=0; i<m_words ; i++) r_write_to_cc_send_be[i]=r_write_be[i].read();
2289
2290        size_t min = r_write_word_index.read();
2291        size_t max = r_write_word_index.read() + r_write_word_count.read();
2292        for(size_t i=min ; i<max ; i++) r_write_to_cc_send_data[i] = r_write_data[i];
2293
2294        if((r_write_copy.read() != r_write_srcid.read()) or(r_write_pktid.read() == TYPE_SC) or
2295#if L1_MULTI_CACHE
2296            (r_write_copy_cache.read() != r_write_pktid.read()) or
2297#endif
2298            r_write_copy_inst.read())
2299        {
2300          // put the first srcid in the fifo
2301          write_to_cc_send_fifo_put     = true;
2302          write_to_cc_send_fifo_inst    = r_write_copy_inst.read();
2303          write_to_cc_send_fifo_srcid   = r_write_copy.read();
2304#if L1_MULTI_CACHE
2305          write_to_cc_send_fifo_cache_id= r_write_copy_cache.read();
2306#endif
2307          if(r_write_count.read() == 1)
2308          {
2309            r_write_fsm = WRITE_IDLE;
2310            r_write_to_cc_send_multi_req = true;
2311          }
2312          else
2313          {
2314            r_write_fsm = WRITE_UPT_NEXT;
2315            r_write_to_dec = false;
2316
2317          }
2318        }
2319        else
2320        {
2321          r_write_fsm = WRITE_UPT_NEXT;
2322          r_write_to_dec = false;
2323        }
2324
2325#if DEBUG_MEMC_WRITE
2326        if(m_debug_write_fsm)
2327        {
2328          std::cout << "  <MEMC " << name() << " WRITE_UPT_REQ> Post first request to CC_SEND FSM"
2329                    << " / srcid = " << std::dec << r_write_copy.read()
2330                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2331          if(r_write_count.read() == 1)
2332            std::cout << "         ... and this is the last" << std::endl;
2333        }
2334#endif
2335      }
2336      break;
2337    }
2338
2339    ///////////////////
2340    case WRITE_UPT_NEXT:
2341    {
2342      // continue the multi-update request to CC_SEND fsm
2343      // when there is copies in the heap.
2344      // if one copy in the heap is the writer itself
2345      // the corresponding SRCID should not be written in the fifo,
2346      // but the UPT counter must be decremented.
2347      // As this decrement is done in the WRITE_UPT_DEC state,
2348      // after the last copy has been found, the decrement request
2349      // must be  registered in the r_write_to_dec flip-flop.
2350
2351      HeapEntry entry = m_heap.read(r_write_ptr.read());
2352
2353      bool dec_upt_counter;
2354
2355      if(((entry.owner.srcid != r_write_srcid.read()) || (r_write_pktid.read() == TYPE_SC)) or
2356#if L1_MULTI_CACHE
2357          (entry.owner.cache_id != r_write_pktid.read()) or
2358#endif
2359          entry.owner.inst)             // put the next srcid in the fifo
2360      {
2361        dec_upt_counter                 = false;
2362        write_to_cc_send_fifo_put      = true;
2363        write_to_cc_send_fifo_inst     = entry.owner.inst;
2364        write_to_cc_send_fifo_srcid    = entry.owner.srcid;
2365#if L1_MULTI_CACHE
2366        write_to_cc_send_fifo_cache_id = entry.owner.cache_id;
2367#endif
2368
2369#if DEBUG_MEMC_WRITE
2370        if(m_debug_write_fsm)
2371        {
2372          std::cout << "  <MEMC " << name() << " WRITE_UPT_NEXT> Post another request to CC_SEND FSM"
2373                    << " / heap_index = " << std::dec << r_write_ptr.read()
2374                    << " / srcid = " << std::dec << r_write_copy.read()
2375                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2376          if(entry.next == r_write_ptr.read())
2377            std::cout << "        ... and this is the last" << std::endl;
2378        }
2379#endif
2380      }
2381      else                                // the UPT counter must be decremented
2382      {
2383        dec_upt_counter = true;
2384
2385#if DEBUG_MEMC_WRITE
2386        if(m_debug_write_fsm)
2387        {
2388          std::cout << "  <MEMC " << name() << " WRITE_UPT_NEXT> Skip one entry in heap matching the writer"
2389                    << " / heap_index = " << std::dec << r_write_ptr.read()
2390                    << " / srcid = " << std::dec << r_write_copy.read()
2391                    << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2392          if(entry.next == r_write_ptr.read())
2393            std::cout << "        ... and this is the last" << std::endl;
2394        }
2395#endif
2396      }
2397
2398      // register the possible UPT decrement request
2399      r_write_to_dec = dec_upt_counter or r_write_to_dec.read();
2400
2401      if(not m_write_to_cc_send_inst_fifo.wok())
2402      {
2403        std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_NEXT state" << std::endl
2404                  << "The write_to_cc_send_fifo should not be full" << std::endl
2405                  << "as the depth should be larger than the max number of copies" << std::endl;
2406        exit(0);
2407      }
2408
2409      r_write_ptr = entry.next;
2410
2411      if(entry.next == r_write_ptr.read())    // last copy
2412      {
2413        r_write_to_cc_send_multi_req = true;
2414        if(r_write_to_dec.read() or dec_upt_counter)   r_write_fsm = WRITE_UPT_DEC;
2415        else                                          r_write_fsm = WRITE_IDLE;
2416      }
2417      break;
2418    }
2419
2420    //////////////////
2421    case WRITE_UPT_DEC:
2422    {
2423      // If the initial writer has a copy, it should not
2424      // receive an update request, but the counter in the
2425      // update table must be decremented by the MULTI_ACK FSM.
2426
2427      if(!r_write_to_multi_ack_req.read())
2428      {
2429        r_write_to_multi_ack_req = true;
2430        r_write_to_multi_ack_upt_index = r_write_upt_index.read();
2431        r_write_fsm = WRITE_IDLE;
2432      }
2433      break;
2434    }
2435
2436    ///////////////
2437    case WRITE_RSP:
2438    {
2439      // Post a request to TGT_RSP FSM to acknowledge the write
2440      // In order to increase the Write requests throughput,
2441      // we don't wait to return in the IDLE state to consume
2442      // a new request in the write FIFO
2443
2444      if(!r_write_to_tgt_rsp_req.read())
2445      {
2446        // post the request to TGT_RSP_FSM
2447        r_write_to_tgt_rsp_req     = true;
2448        r_write_to_tgt_rsp_srcid   = r_write_srcid.read();
2449        r_write_to_tgt_rsp_trdid   = r_write_trdid.read();
2450        r_write_to_tgt_rsp_pktid   = r_write_pktid.read();
2451        r_write_to_tgt_rsp_sc_fail = r_write_sc_fail.read();
2452
2453        // try to get a new write request from the FIFO
2454        if(m_cmd_write_addr_fifo.rok())
2455        {
2456          if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
2457            m_cpt_sc++;
2458          else
2459          {
2460            m_cpt_write++;
2461            m_cpt_write_cells++;
2462          }
2463
2464          // consume a word in the FIFO & write it in the local buffer
2465          cmd_write_fifo_get  = true;
2466          size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
2467
2468          r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
2469          r_write_word_index  = index;
2470          r_write_word_count  = 1;
2471          r_write_data[index] = m_cmd_write_data_fifo.read();
2472          r_write_srcid       = m_cmd_write_srcid_fifo.read();
2473          r_write_trdid       = m_cmd_write_trdid_fifo.read();
2474          r_write_pktid       = m_cmd_write_pktid_fifo.read();
2475          r_write_pending_sc  = false;
2476
2477          // initialize the be field for all words
2478          for(size_t word=0 ; word<m_words ; word++)
2479          {
2480            if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
2481            else                 r_write_be[word] = 0x0;
2482          }
2483
2484          if(m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC))
2485          {
2486            r_write_fsm = WRITE_DIR_REQ;
2487          }
2488          else
2489          {
2490            r_write_fsm = WRITE_NEXT;
2491          }
2492        }
2493        else
2494        {
2495          r_write_fsm = WRITE_IDLE;
2496        }
2497
2498#if DEBUG_MEMC_WRITE
2499        if(m_debug_write_fsm)
2500        {
2501          std::cout << "  <MEMC " << name() << " WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
2502                    << std::dec << r_write_srcid.read() << std::endl;
2503          if(m_cmd_write_addr_fifo.rok())
2504          {
2505            std::cout << "                    New Write request: "
2506                      << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
2507                      << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
2508                      << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
2509          }
2510        }
2511#endif
2512      }
2513      break;
2514    }
2515
2516    /////////////////////////
2517    case WRITE_MISS_TRT_LOCK: // Miss : check Transaction Table
2518    {
2519      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2520      {
2521
2522#if DEBUG_MEMC_WRITE
2523        if(m_debug_write_fsm)
2524        {
2525          std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
2526        }
2527#endif
2528        size_t  hit_index = 0;
2529        size_t  wok_index = 0;
2530        addr_t  addr  = (addr_t) r_write_address.read();
2531        bool    hit_read  = m_trt.hit_read(m_nline[addr], hit_index);
2532        bool    hit_write = m_trt.hit_write(m_nline[addr]);
2533        bool    wok       = !m_trt.full(wok_index);
2534
2535        if(hit_read)      // register the modified data in TRT
2536        {
2537          r_write_trt_index = hit_index;
2538          r_write_fsm       = WRITE_MISS_TRT_DATA;
2539          m_cpt_write_miss++;
2540        }
2541        else if(wok && !hit_write)      // set a new entry in TRT
2542        {
2543          r_write_trt_index = wok_index;
2544          r_write_fsm       = WRITE_MISS_TRT_SET;
2545          m_cpt_write_miss++;
2546        }
2547        else    // wait an empty entry in TRT
2548        {
2549          r_write_fsm       = WRITE_WAIT;
2550          m_cpt_trt_full++;
2551        }
2552      }
2553      break;
2554    }
2555
2556    ////////////////
2557    case WRITE_WAIT:  // release the locks protecting the shared ressources
2558    {
2559#if DEBUG_MEMC_WRITE
2560      if(m_debug_write_fsm)
2561      {
2562        std::cout << "  <MEMC " << name() << " WRITE_WAIT> Releases the locks before retry" << std::endl;
2563      }
2564#endif
2565      r_write_fsm = WRITE_DIR_REQ;
2566      break;
2567    }
2568
2569    ////////////////////////
2570    case WRITE_MISS_TRT_SET:  // register a new transaction in TRT (Write Buffer)
2571    {
2572      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2573      {
2574        std::vector<be_t>   be_vector;
2575        std::vector<data_t> data_vector;
2576        be_vector.clear();
2577        data_vector.clear();
2578        for(size_t i=0; i<m_words; i++)
2579        {
2580          be_vector.push_back(r_write_be[i]);
2581          data_vector.push_back(r_write_data[i]);
2582        }
2583        m_trt.set(r_write_trt_index.read(),
2584                              true,     // read request to XRAM
2585                              m_nline[(addr_t)(r_write_address.read())],
2586                              r_write_srcid.read(),
2587                              r_write_trdid.read(),
2588                              r_write_pktid.read(),
2589                              false,      // not a processor read
2590                              0,        // not a single word
2591                              0,            // word index
2592                              be_vector,
2593                              data_vector);
2594        r_write_fsm = WRITE_MISS_XRAM_REQ;
2595
2596#if DEBUG_MEMC_WRITE
2597        if(m_debug_write_fsm)
2598        {
2599          std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
2600        }
2601#endif
2602      }
2603      break;
2604    }
2605
2606    /////////////////////////
2607    case WRITE_MISS_TRT_DATA: // update an entry in TRT (used as a Write Buffer)
2608    {
2609      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2610      {
2611        std::vector<be_t> be_vector;
2612        std::vector<data_t> data_vector;
2613        be_vector.clear();
2614        data_vector.clear();
2615        for(size_t i=0; i<m_words; i++)
2616        {
2617          be_vector.push_back(r_write_be[i]);
2618          data_vector.push_back(r_write_data[i]);
2619        }
2620        m_trt.write_data_mask(r_write_trt_index.read(),
2621                                          be_vector,
2622                                          data_vector);
2623        r_write_fsm = WRITE_RSP;
2624
2625#if DEBUG_MEMC_WRITE
2626        if(m_debug_write_fsm)
2627        {
2628          std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2629          m_trt.print(r_write_trt_index.read());
2630        }
2631#endif
2632      }
2633      break;
2634    }
2635
2636    /////////////////////////
2637    case WRITE_MISS_XRAM_REQ: // send a GET request to IXR_CMD FSM
2638    {
2639      if(!r_write_to_ixr_cmd_req)
2640      {
2641        r_write_to_ixr_cmd_req   = true;
2642        r_write_to_ixr_cmd_write = false;
2643        r_write_to_ixr_cmd_nline = m_nline[(addr_t)(r_write_address.read())];
2644        r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
2645        r_write_fsm              = WRITE_RSP;
2646
2647#if DEBUG_MEMC_WRITE
2648        if(m_debug_write_fsm)
2649        {
2650          std::cout << "  <MEMC " << name() << " WRITE_MISS_XRAM_REQ> Post a GET request to the IXR_CMD FSM" << std::endl;
2651        }
2652#endif
2653      }
2654      break;
2655    }
2656
2657    ///////////////////////
2658    case WRITE_BC_TRT_LOCK:     // Check TRT not full
2659    {
2660      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2661      {
2662        size_t wok_index = 0;
2663        bool wok = !m_trt.full(wok_index);
2664        if(wok)       // set a new entry in TRT
2665        {
2666          r_write_trt_index = wok_index;
2667          r_write_fsm       = WRITE_BC_UPT_LOCK;
2668        }
2669        else  // wait an empty entry in TRT
2670        {
2671          r_write_fsm       = WRITE_WAIT;
2672        }
2673
2674#if DEBUG_MEMC_WRITE
2675        if(m_debug_write_fsm)
2676        {
2677          std::cout << "  <MEMC " << name() << " WRITE_BC_TRT_LOCK> Check TRT : wok = "
2678                    << wok << " / index = " << wok_index << std::endl;
2679        }
2680#endif
2681      }
2682      break;
2683    }
2684
2685    //////////////////////
2686    case WRITE_BC_UPT_LOCK:      // register BC transaction in UPT
2687    {
2688      if(r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE)
2689      {
2690        bool        wok       = false;
2691        size_t      index     = 0;
2692        size_t      srcid     = r_write_srcid.read();
2693        size_t      trdid     = r_write_trdid.read();
2694        size_t      pktid     = r_write_pktid.read();
2695        addr_t      nline     = m_nline[(addr_t)(r_write_address.read())];
2696        size_t      nb_copies = r_write_count.read();
2697
2698        wok =m_upt.set(false,  // it's an inval transaction
2699                              true,     // it's a broadcast
2700                              true,     // it needs a response
2701                              srcid,
2702                              trdid,
2703                              pktid,
2704                              nline,
2705                              nb_copies,
2706                              index);
2707
2708#if DEBUG_MEMC_WRITE
2709        if(m_debug_write_fsm)
2710        {
2711          if(wok)
2712          {
2713            std::cout << "  <MEMC " << name() << " WRITE_BC_UPT_LOCK> Register the broadcast inval in UPT / "
2714                      << " nb_copies = " << r_write_count.read() << std::endl;
2715          }
2716        }
2717#endif
2718        r_write_upt_index = index;
2719
2720        if(wok) r_write_fsm = WRITE_BC_DIR_INVAL;
2721        else       r_write_fsm = WRITE_WAIT;
2722      }
2723      break;
2724    }
2725
2726    ////////////////////////
2727    case WRITE_BC_DIR_INVAL:
2728    {
2729      // Register a put transaction to XRAM in TRT
2730      // and invalidate the line in directory
2731      if((r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE) ||
2732          (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE) ||
2733          (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE))
2734      {
2735        std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_BC_DIR_INVAL state" << std::endl;
2736        std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
2737        exit(0);
2738      }
2739
2740      // register a write request to XRAM in TRT
2741      m_trt.set(r_write_trt_index.read(),
2742                            false,    // write request to XRAM
2743                            m_nline[(addr_t)(r_write_address.read())],
2744                            0,
2745                            0,
2746                            0,
2747                            false,    // not a processor read
2748                            0,        // not a single word
2749                            0,            // word index
2750                            std::vector<be_t> (m_words,0),
2751                            std::vector<data_t> (m_words,0));
2752
2753      // invalidate directory entry
2754      DirectoryEntry entry;
2755      entry.valid         = false;
2756      entry.dirty         = false;
2757      entry.tag         = 0;
2758      entry.is_cnt        = false;
2759      entry.lock          = false;
2760      entry.owner.srcid   = 0;
2761#if L1_MULTI_CACHE
2762      entry.owner.cache_id= 0;
2763#endif
2764      entry.owner.inst    = false;
2765      entry.ptr           = 0;
2766      entry.count         = 0;
2767      size_t set          = m_y[(addr_t)(r_write_address.read())];
2768      size_t way          = r_write_way.read();
2769
2770      m_cache_directory.write(set, way, entry);
2771
2772#if DEBUG_MEMC_WRITE
2773      if(m_debug_write_fsm)
2774      {
2775        std::cout << "  <MEMC " << name() << " WRITE_BC_DIR_INVAL> Invalidate the directory entry: @ = "
2776                  << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
2777      }
2778#endif
2779      r_write_fsm = WRITE_BC_CC_SEND;
2780      break;
2781    }
2782
2783    //////////////////////
2784    case WRITE_BC_CC_SEND:    // Post a coherence broadcast request to CC_SEND FSM
2785    {
2786      if(!r_write_to_cc_send_multi_req.read() && !r_write_to_cc_send_brdcast_req.read())
2787      {
2788        r_write_to_cc_send_multi_req   = false;
2789        r_write_to_cc_send_brdcast_req = true;
2790        r_write_to_cc_send_trdid       = r_write_upt_index.read();
2791        r_write_to_cc_send_nline       = m_nline[(addr_t)(r_write_address.read())];
2792        r_write_to_cc_send_index       = 0;
2793        r_write_to_cc_send_count       = 0;
2794
2795        for(size_t i=0; i<m_words ; i++)
2796        {
2797          r_write_to_cc_send_be[i]=0;
2798          r_write_to_cc_send_data[i] = 0;
2799        }
2800        r_write_fsm = WRITE_BC_XRAM_REQ;
2801
2802#if DEBUG_MEMC_WRITE
2803if(m_debug_write_fsm)
2804{
2805    std::cout << "  <MEMC " << name() 
2806              << " WRITE_BC_CC_SEND> Post a broadcast request to CC_SEND FSM" << std::endl;
2807}
2808#endif
2809      }
2810      break;
2811    }
2812
2813    ///////////////////////
2814    case WRITE_BC_XRAM_REQ:   // Post a put request to IXR_CMD FSM
2815    {
2816      if(!r_write_to_ixr_cmd_req)
2817      {
2818        r_write_to_ixr_cmd_req     = true;
2819        r_write_to_ixr_cmd_write   = true;
2820        r_write_to_ixr_cmd_nline   = m_nline[(addr_t)(r_write_address.read())];
2821        r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
2822
2823        for(size_t i=0; i<m_words; i++) r_write_to_ixr_cmd_data[i] = r_write_data[i];
2824
2825        r_write_fsm = WRITE_IDLE;
2826
2827#if DEBUG_MEMC_WRITE
2828if(m_debug_write_fsm)
2829{
2830     std::cout << "  <MEMC " << name() 
2831               << " WRITE_BC_XRAM_REQ> Post a put request to IXR_CMD FSM" << std::endl;
2832}
2833#endif
2834      }
2835      break;
2836    }
2837  } // end switch r_write_fsm
2838
2839  ///////////////////////////////////////////////////////////////////////
2840  //    IXR_CMD FSM
2841  ///////////////////////////////////////////////////////////////////////
2842  // The IXR_CMD fsm controls the command packets to the XRAM :
2843  // It handles requests from the READ, WRITE, CAS, XRAM_RSP FSMs
2844  // with a round-robin priority.
2845  //
2846  // - It sends a single flit VCI read request to the XRAM in case of MISS
2847  // posted by the READ, WRITE or CAS FSMs : the TRDID field contains
2848  // the Transaction Tab index.
2849  // The VCI response is a multi-flit packet : the N cells contain
2850  // the N data words.
2851  //
2852  // - It sends a multi-flit VCI write when the XRAM_RSP FSM, WRITE FSM
2853  // or CAS FSM request to save a dirty line to the XRAM.
2854  // The VCI response is a single flit packet.
2855  ////////////////////////////////////////////////////////////////////////
2856
2857  switch(r_ixr_cmd_fsm.read())
2858  {
2859    ////////////////////////
2860    case IXR_CMD_READ_IDLE:
2861    {
2862      if     (r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2863      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2864      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2865      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2866      break;
2867    }
2868    ////////////////////////
2869    case IXR_CMD_WRITE_IDLE:
2870    {
2871      if     (r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2872      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2873      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2874      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2875      break;
2876    }
2877    ////////////////////////
2878    case IXR_CMD_CAS_IDLE:
2879    {
2880      if     (r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2881      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2882      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2883      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2884      break;
2885    }
2886    ////////////////////////
2887    case IXR_CMD_XRAM_IDLE:
2888    {
2889      if     (r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2890      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2891      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2892      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2893      break;
2894    }
2895    //////////////////       // send a get from READ FSM
2896    case IXR_CMD_READ:
2897    {
2898      if(p_vci_ixr.cmdack)
2899      {
2900        r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;
2901        r_read_to_ixr_cmd_req = false;
2902
2903#if DEBUG_MEMC_IXR_CMD
2904if(m_debug_ixr_cmd_fsm)
2905std::cout << "  <MEMC " << name() << " IXR_CMD_READ>"
2906          << " Send a get request to xram / address = " << std::hex
2907          << (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2908#endif
2909      }
2910      break;
2911    }
2912    ///////////////////
2913    case IXR_CMD_WRITE:     // send a put or get from WRITE FSM
2914    {
2915      if(p_vci_ixr.cmdack)
2916      {
2917        if(r_write_to_ixr_cmd_write.read())   // PUT
2918        {
2919          if(r_ixr_cmd_cpt.read() == (m_words - 2))
2920          {
2921            r_ixr_cmd_cpt = 0;
2922            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2923            r_write_to_ixr_cmd_req = false;
2924          }
2925          else
2926          {
2927            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
2928          }
2929
2930#if DEBUG_MEMC_IXR_CMD
2931if(m_debug_ixr_cmd_fsm)
2932std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE>"
2933          << " Send a put request to xram / address = " << std::hex
2934          << (addr_t)((r_write_to_ixr_cmd_nline.read() * m_words +
2935                      r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
2936#endif
2937        }
2938        else                                  // GET
2939        {
2940          r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2941          r_write_to_ixr_cmd_req = false;
2942
2943#if DEBUG_MEMC_IXR_CMD
2944if(m_debug_ixr_cmd_fsm)
2945std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE>"
2946          << " Send a get request to xram / address = " << std::hex
2947          << (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2948#endif
2949        }
2950      }
2951      break;
2952    }
2953    /////////////////
2954    case IXR_CMD_CAS:      // send a put or get command from CAS FSM
2955    {
2956      if(p_vci_ixr.cmdack)
2957      {
2958        if(r_cas_to_ixr_cmd_write.read()) // PUT
2959        {
2960          if(r_ixr_cmd_cpt.read() == (m_words - 2))
2961          {
2962            r_ixr_cmd_cpt = 0;
2963            r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2964            r_cas_to_ixr_cmd_req = false;
2965          }
2966          else
2967          {
2968            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
2969          }
2970
2971#if DEBUG_MEMC_IXR_CMD
2972if(m_debug_ixr_cmd_fsm)
2973std::cout << "  <MEMC " << name() << " IXR_CMD_CAS>"
2974          << " Send a put request to xram / address = " << std::hex
2975          << (addr_t)( (r_cas_to_ixr_cmd_nline.read() * m_words +
2976                      r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
2977#endif
2978        }
2979        else                            // GET
2980        {
2981          r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2982          r_cas_to_ixr_cmd_req = false;
2983
2984#if DEBUG_MEMC_IXR_CMD
2985if(m_debug_ixr_cmd_fsm)
2986std::cout << "  <MEMC " << name() << " IXR_CMD_CAS>"
2987          << " Send a get request to xram / address = " << std::hex
2988          << (addr_t)(r_cas_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2989#endif
2990        }
2991      }
2992      break;
2993    }
2994    //////////////////
2995    case IXR_CMD_XRAM:     // send a put from XRAM_RSP FSM
2996    {
2997      if(p_vci_ixr.cmdack)
2998      {
2999        if(r_ixr_cmd_cpt.read() == (m_words - 2))
3000        {
3001          r_ixr_cmd_cpt = 0;
3002          r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
3003          r_xram_rsp_to_ixr_cmd_req = false;
3004        }
3005        else
3006        {
3007          r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
3008        }
3009
3010#if DEBUG_MEMC_IXR_CMD
3011if(m_debug_ixr_cmd_fsm)
3012std::cout << "  <MEMC " << name() << " IXR_CMD_XRAM>"
3013          << " Send a put request to xram / address = " << std::hex
3014          << (addr_t)( (r_xram_rsp_to_ixr_cmd_nline.read() * m_words +
3015                       r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
3016#endif
3017      }
3018      break;
3019    }
3020
3021  } // end switch r_ixr_cmd_fsm
3022
3023  ////////////////////////////////////////////////////////////////////////////
3024  //                IXR_RSP FSM
3025  ////////////////////////////////////////////////////////////////////////////
3026  // The IXR_RSP FSM receives the response packets from the XRAM,
3027  // for both put transaction, and get transaction.
3028  //
3029  // - A response to a put request is a single-cell VCI packet.
3030  // The Transaction Tab index is contained in the RTRDID field.
3031  // The FSM takes the lock protecting the TRT, and the corresponding
3032  // entry is erased.
3033  //
3034  // - A response to a get request is a multi-cell VCI packet.
3035  // The Transaction Tab index is contained in the RTRDID field.
3036  // The N cells contain the N words of the cache line in the RDATA field.
3037  // The FSM takes the lock protecting the TRT to store the line in the TRT
3038  // (taking into account the write requests already stored in the TRT).
3039  // When the line is completely written, the corresponding rok signal is set.
3040  ///////////////////////////////////////////////////////////////////////////////
3041
3042  switch(r_ixr_rsp_fsm.read())
3043  {
3044    //////////////////
3045    case IXR_RSP_IDLE:  // test transaction type: PUT/GET
3046    {
3047      if(p_vci_ixr.rspval.read())
3048      {
3049        r_ixr_rsp_cpt   = 0;
3050        r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
3051        if(p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read() &0x1))   // PUT transaction
3052        {
3053          r_ixr_rsp_fsm = IXR_RSP_ACK;
3054
3055#if DEBUG_MEMC_IXR_RSP
3056if(m_debug_ixr_rsp_fsm)
3057{
3058    std::cout << "  <MEMC " << name() 
3059              << " IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
3060}
3061#endif
3062        }
3063        else                                                         // GET transaction
3064        {
3065          r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
3066
3067#if DEBUG_MEMC_IXR_RSP
3068if(m_debug_ixr_rsp_fsm)
3069{
3070    std::cout << "  <MEMC " << name() 
3071              << " IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
3072}
3073#endif
3074        }
3075      }
3076      break;
3077    }
3078    /////////////////
3079    case IXR_RSP_ACK:        // Aknowledge the VCI response for a PUT
3080    {
3081      if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
3082
3083#if DEBUG_MEMC_IXR_RSP
3084if(m_debug_ixr_rsp_fsm)
3085{
3086    std::cout << "  <MEMC " << name() << " IXR_RSP_ACK>" << std::endl;
3087}
3088#endif
3089      break;
3090    }
3091    ////////////////////////
3092    case IXR_RSP_TRT_ERASE:   // erase the entry in the TRT
3093    {
3094      if(r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP)
3095      {
3096        m_trt.erase(r_ixr_rsp_trt_index.read());
3097        r_ixr_rsp_fsm = IXR_RSP_IDLE;
3098
3099#if DEBUG_MEMC_IXR_RSP
3100if(m_debug_ixr_rsp_fsm)
3101{
3102          std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_ERASE> Erase TRT entry "
3103                    << r_ixr_rsp_trt_index.read() << std::endl;
3104        }
3105#endif
3106      }
3107      break;
3108    }
3109    //////////////////////
3110    case IXR_RSP_TRT_READ:    // write a 64 bits data in the TRT
3111    {
3112      if((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval)
3113      {
3114        size_t      index    = r_ixr_rsp_trt_index.read();
3115        bool        eop      = p_vci_ixr.reop.read();
3116        wide_data_t data     = p_vci_ixr.rdata.read();
3117        bool        error    = ((p_vci_ixr.rerror.read() & 0x1) == 1);
3118
3119        assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-2))) || p_vci_ixr.rerror.read())
3120               and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
3121
3122        m_trt.write_rsp( index,
3123                         r_ixr_rsp_cpt.read(),
3124                         data,
3125                         error);
3126
3127        r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 2;
3128
3129        if(eop)
3130        {
3131          r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
3132          r_ixr_rsp_fsm = IXR_RSP_IDLE;
3133        }
3134
3135#if DEBUG_MEMC_IXR_RSP
3136if(m_debug_ixr_rsp_fsm)
3137{
3138    std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_READ> Writing a word in TRT : "
3139              << " index = " << std::dec << index
3140              << " / word = " << r_ixr_rsp_cpt.read()
3141              << " / data = " << std::hex << data << std::endl;
3142}
3143#endif
3144      }
3145      break;
3146    }
3147  } // end swich r_ixr_rsp_fsm
3148
3149  ////////////////////////////////////////////////////////////////////////////
3150  //                XRAM_RSP FSM
3151  ////////////////////////////////////////////////////////////////////////////
3152  // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
3153  // The cache line has been written in the TRT by the IXR_CMD_FSM.
3154  // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
3155  // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
3156  // as the number of entries in the TRT, that are handled with
3157  // a round-robin priority...
3158  //
3159  // When a response is available, the corresponding TRT entry
3160  // is copied in a local buffer to be written in the cache.
3161  // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
3162  // It selects a cache slot and writes the line in the cache.
3163  // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
3164  // FSM to return the cache line to the registered processor.
3165  // If there is no empty slot, a victim line is evicted, and
3166  // invalidate requests are sent to the L1 caches containing copies.
3167  // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
3168  // FSM to save the victim line to the XRAM, and register the write transaction
3169  // in the TRT (using the entry previously used by the read transaction).
3170  ///////////////////////////////////////////////////////////////////////////////
3171
3172  switch(r_xram_rsp_fsm.read())
3173  {
3174    ///////////////////
3175    case XRAM_RSP_IDLE: // scan the XRAM responses / select a TRT index (round robin)
3176    {
3177      size_t ptr   = r_xram_rsp_trt_index.read();
3178      size_t lines = m_trt_lines;
3179      for(size_t i=0 ; i<lines ; i++)
3180      {
3181        size_t index = (i+ptr+1) %lines;
3182        if(r_ixr_rsp_to_xram_rsp_rok[index])
3183        {
3184          r_xram_rsp_trt_index             = index;
3185          r_ixr_rsp_to_xram_rsp_rok[index] = false;
3186          r_xram_rsp_fsm                   = XRAM_RSP_DIR_LOCK;
3187
3188#if DEBUG_MEMC_XRAM_RSP
3189if(m_debug_xram_rsp_fsm)
3190std::cout << "  <MEMC " << name() << " XRAM_RSP_IDLE>"
3191          << " Available cache line in TRT:"
3192          << " index = " << std::dec << index << std::endl;
3193#endif
3194          break;
3195        }
3196      }
3197      break;
3198    }
3199    ///////////////////////
3200    case XRAM_RSP_DIR_LOCK: // Takes the DIR lock and the TRT lock
3201                            // Copy the TRT entry in a local buffer
3202    {
3203      if((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) &&
3204          (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP))
3205      {
3206        // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
3207        size_t  index = r_xram_rsp_trt_index.read();
3208        r_xram_rsp_trt_buf.copy( m_trt.read(index) ); 
3209
3210        r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
3211
3212//        TransactionTabEntry trt_entry(m_trt.read(index));
3213//        r_xram_rsp_trt_buf.copy(trt_entry);           // TRT entry local buffer
3214
3215#if DEBUG_MEMC_XRAM_RSP
3216if(m_debug_xram_rsp_fsm)
3217std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_LOCK>"
3218          << " Get access to DIR and TRT" << std::endl;
3219#endif
3220      }
3221      break;
3222    }
3223    ///////////////////////
3224    case XRAM_RSP_TRT_COPY: // Select a victim cache line
3225                            // and copy it in a local buffer
3226    {
3227      if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) and
3228           (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) )
3229      {
3230        // selects & extracts a victim line from cache
3231        size_t way = 0;
3232        size_t set = m_y[(addr_t)(r_xram_rsp_trt_buf.nline * m_words * 4)];
3233
3234        DirectoryEntry victim(m_cache_directory.select(set, way));
3235
3236        bool inval = (victim.count && victim.valid) ;
3237
3238        // copy the victim line in a local buffer
3239        m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
3240
3241        r_xram_rsp_victim_copy      = victim.owner.srcid;
3242
3243#if L1_MULTI_CACHE
3244        r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
3245#endif
3246        r_xram_rsp_victim_copy_inst = victim.owner.inst;
3247        r_xram_rsp_victim_count     = victim.count;
3248        r_xram_rsp_victim_ptr       = victim.ptr;
3249        r_xram_rsp_victim_way       = way;
3250        r_xram_rsp_victim_set       = set;
3251        r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
3252        r_xram_rsp_victim_is_cnt    = victim.is_cnt;
3253        r_xram_rsp_victim_inval     = inval ;
3254        r_xram_rsp_victim_dirty     = victim.dirty;
3255
3256        if(!r_xram_rsp_trt_buf.rerror)
3257        {
3258          r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
3259        }
3260        else
3261        {
3262          r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;
3263        }
3264
3265#if DEBUG_MEMC_XRAM_RSP
3266if(m_debug_xram_rsp_fsm)
3267std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_COPY>"
3268          << " Select a slot: "
3269          << " way = " << std::dec << way
3270          << " / set = " << set
3271          << " / inval_required = " << inval << std::endl;
3272#endif
3273      }
3274      else
3275      {
3276        std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_TRT_COPY" 
3277                  << " bad TRT or DIR allocation" << std::endl;
3278        exit(0);
3279      }
3280      break;
3281    }
3282    /////////////////////////
3283    case XRAM_RSP_INVAL_LOCK: // Take the UPT lock to check a possible pending inval
3284    {
3285      if(r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP)
3286      {
3287        size_t index = 0;
3288        if(m_upt.search_inval(r_xram_rsp_trt_buf.nline, index))  // pending inval
3289        {
3290          r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3291
3292#if DEBUG_MEMC_XRAM_RSP
3293if(m_debug_xram_rsp_fsm)
3294std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3295          << " Get acces to UPT, but line invalidation registered" 
3296          << " / nline = " << std::hex << r_xram_rsp_trt_buf.nline
3297          << " / index = " << std::dec << index << std::endl;
3298#endif
3299
3300        }
3301        else if(m_upt.is_full() && r_xram_rsp_victim_inval.read()) // UPT full
3302        {
3303          r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3304
3305#if DEBUG_MEMC_XRAM_RSP
3306if(m_debug_xram_rsp_fsm)
3307std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3308          << " Get acces to UPT, but inval required and UPT full" << std::endl;
3309#endif
3310        }
3311        else
3312        {
3313          r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
3314
3315#if DEBUG_MEMC_XRAM_RSP
3316if(m_debug_xram_rsp_fsm)
3317std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3318          << " Get acces to UPT" << std::endl;
3319#endif
3320        }
3321      }
3322      break;
3323    }
3324    /////////////////////////
3325    case XRAM_RSP_INVAL_WAIT: // release all locks and returns to DIR_LOCK to retry
3326    {
3327
3328#if DEBUG_MEMC_XRAM_RSP
3329if(m_debug_xram_rsp_fsm)
3330std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_WAIT>"
3331          << " Release all locks and retry" << std::endl;
3332#endif
3333      r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
3334      break;
3335    }
3336    ///////////////////////
3337    case XRAM_RSP_DIR_UPDT:   // updates the cache (both data & directory)
3338                              // and possibly set an inval request in UPT
3339    {
3340      // check if this is an instruction read, this means pktid is either
3341      // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
3342      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3343      bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) && r_xram_rsp_trt_buf.proc_read;
3344
3345      // check if this is a cached read, this means pktid is either
3346      // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
3347      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3348      bool cached_read = (r_xram_rsp_trt_buf.pktid & 0x1) && r_xram_rsp_trt_buf.proc_read;
3349
3350      bool dirty = false;
3351
3352      // update cache data
3353      size_t set   = r_xram_rsp_victim_set.read();
3354      size_t way   = r_xram_rsp_victim_way.read();
3355      for(size_t word=0; word<m_words ; word++)
3356      {
3357        m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
3358
3359        dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[word] != 0);
3360
3361        if(m_monitor_ok)
3362        {
3363          addr_t address = r_xram_rsp_trt_buf.nline<<6 | word<<2;
3364          check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[word], false);
3365        }
3366      }
3367
3368      // update cache directory
3369      DirectoryEntry entry;
3370      entry.valid   = true;
3371      entry.is_cnt  = false;
3372      entry.lock    = false;
3373      entry.dirty   = dirty;
3374      entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
3375      entry.ptr     = 0;
3376      if(cached_read)
3377      {
3378        entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
3379#if L1_MULTI_CACHE
3380        entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
3381#endif
3382        entry.owner.inst    = inst_read;
3383        entry.count         = 1;
3384      }
3385      else
3386      {
3387        entry.owner.srcid    = 0;
3388#if L1_MULTI_CACHE
3389        entry.owner.cache_id = 0;
3390#endif
3391        entry.owner.inst     = 0;
3392        entry.count          = 0;
3393      }
3394      m_cache_directory.write(set, way, entry);
3395
3396      // request an invalidattion request in UPT for victim line
3397      if(r_xram_rsp_victim_inval.read())
3398      {
3399        bool   broadcast    = r_xram_rsp_victim_is_cnt.read();
3400        size_t index        = 0;
3401        size_t count_copies = r_xram_rsp_victim_count.read();
3402
3403        bool   wok = m_upt.set(false,      // it's an inval transaction
3404                               broadcast,  // set broadcast bit
3405                               false,      // it does not need a response
3406                               0,          // srcid
3407                               0,          // trdid
3408                               0,          // pktid
3409                               r_xram_rsp_victim_nline.read(),
3410                               count_copies,
3411                               index);
3412
3413        r_xram_rsp_upt_index = index;
3414
3415        if(!wok)
3416        {
3417          std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_DIR_UPDT"
3418                    << " update_tab entry free but write unsuccessful" << std::endl;
3419          exit(0);
3420        }
3421      }
3422
3423#if DEBUG_MEMC_XRAM_RSP
3424if(m_debug_xram_rsp_fsm)
3425{
3426std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_UPDT>" 
3427          << " Cache update: "
3428          << " way = " << std::dec << way
3429          << " / set = " << set
3430          << " / owner_id = " << entry.owner.srcid
3431          << " / owner_ins = " << entry.owner.inst
3432          << " / count = " << entry.count
3433          << " / is_cnt = " << entry.is_cnt << std::endl;
3434if(r_xram_rsp_victim_inval.read())
3435std::cout << "                           Invalidation request for victim line "
3436          << std::hex << r_xram_rsp_victim_nline.read()
3437          << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
3438}
3439#endif
3440
3441      // If the victim is not dirty, we don't need another XRAM put transaction,
3442      // and we can erase the TRT entry
3443      if(!r_xram_rsp_victim_dirty.read())  m_trt.erase(r_xram_rsp_trt_index.read());
3444
3445      // Next state
3446      if(r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
3447      else if(r_xram_rsp_trt_buf.proc_read)    r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3448      else if(r_xram_rsp_victim_inval.read())  r_xram_rsp_fsm = XRAM_RSP_INVAL;
3449      else                                     r_xram_rsp_fsm = XRAM_RSP_IDLE;
3450      break;
3451    }
3452    ////////////////////////
3453    case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (PUT to XRAM) if the victim is dirty
3454    {
3455      if(r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP)
3456      {
3457        m_trt.set(r_xram_rsp_trt_index.read(),
3458                              false,       // write to XRAM
3459                              r_xram_rsp_victim_nline.read(),  // line index
3460                              0,
3461                              0,
3462                              0,
3463                              false,
3464                              0,
3465                              0,
3466                              std::vector<be_t> (m_words,0),
3467                              std::vector<data_t> (m_words,0));
3468
3469#if DEBUG_MEMC_XRAM_RSP
3470if(m_debug_xram_rsp_fsm)
3471std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_DIRTY>"
3472          << " Set TRT entry for the put transaction"
3473          << " / dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3474#endif
3475        if(r_xram_rsp_trt_buf.proc_read)         r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3476        else if(r_xram_rsp_victim_inval.read())  r_xram_rsp_fsm = XRAM_RSP_INVAL;
3477        else                                     r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3478      }
3479      break;
3480    }
3481    //////////////////////
3482    case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
3483    {
3484      if(!r_xram_rsp_to_tgt_rsp_req.read())
3485      {
3486        r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
3487        r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
3488        r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
3489        for(size_t i=0; i < m_words; i++) 
3490        {
3491            r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3492        }
3493        r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3494        r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3495        r_xram_rsp_to_tgt_rsp_ll_key = r_xram_rsp_trt_buf.ll_key;
3496        r_xram_rsp_to_tgt_rsp_rerror = false;
3497        r_xram_rsp_to_tgt_rsp_req    = true;
3498
3499        if(r_xram_rsp_victim_inval)      r_xram_rsp_fsm = XRAM_RSP_INVAL;
3500        else if(r_xram_rsp_victim_dirty) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3501        else                             r_xram_rsp_fsm = XRAM_RSP_IDLE;
3502
3503#if DEBUG_MEMC_XRAM_RSP
3504if(m_debug_xram_rsp_fsm)
3505std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_RSP>"
3506          << " Request the TGT_RSP FSM to return data:"
3507          << " rsrcid = " << std::dec << r_xram_rsp_trt_buf.srcid
3508          << " / address = " << std::hex << r_xram_rsp_trt_buf.nline*m_words*4
3509          << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
3510#endif
3511      }
3512      break;
3513    }
3514    ////////////////////
3515    case XRAM_RSP_INVAL:  // send invalidate request to CC_SEND FSM
3516    {
3517      if(!r_xram_rsp_to_cc_send_multi_req.read() &&
3518          !r_xram_rsp_to_cc_send_brdcast_req.read())
3519      {
3520        bool multi_req = !r_xram_rsp_victim_is_cnt.read();
3521        bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
3522        bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3523
3524        r_xram_rsp_to_cc_send_multi_req    = last_multi_req;
3525        r_xram_rsp_to_cc_send_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
3526        r_xram_rsp_to_cc_send_nline        = r_xram_rsp_victim_nline.read();
3527        r_xram_rsp_to_cc_send_trdid        = r_xram_rsp_upt_index;
3528        xram_rsp_to_cc_send_fifo_srcid     = r_xram_rsp_victim_copy.read();
3529        xram_rsp_to_cc_send_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
3530#if L1_MULTI_CACHE
3531        xram_rsp_to_cc_send_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
3532#endif
3533        xram_rsp_to_cc_send_fifo_put       = multi_req;
3534        r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
3535
3536        if(r_xram_rsp_victim_dirty)  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3537        else if(not_last_multi_req)  r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3538        else                         r_xram_rsp_fsm = XRAM_RSP_IDLE;
3539
3540#if DEBUG_MEMC_XRAM_RSP
3541if(m_debug_xram_rsp_fsm)
3542std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL>"
3543          << " Send an inval request to CC_SEND FSM"
3544          << " / victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3545#endif
3546      }
3547      break;
3548    }
3549    //////////////////////////
3550    case XRAM_RSP_WRITE_DIRTY:  // send a write request to IXR_CMD FSM
3551    {
3552      if(!r_xram_rsp_to_ixr_cmd_req.read())
3553      {
3554        r_xram_rsp_to_ixr_cmd_req = true;
3555        r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
3556        r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
3557        for(size_t i=0; i<m_words ; i++) 
3558        {
3559            r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
3560        }
3561        m_cpt_write_dirty++;
3562
3563        bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
3564        bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3565
3566        if(not_last_multi_req)   r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3567        else                     r_xram_rsp_fsm = XRAM_RSP_IDLE;
3568
3569#if DEBUG_MEMC_XRAM_RSP
3570if(m_debug_xram_rsp_fsm)
3571std::cout << "  <MEMC " << name() << " XRAM_RSP_WRITE_DIRTY>"
3572          << " Send the put request to IXR_CMD FSM"
3573          << " / victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3574#endif
3575      }
3576      break;
3577    }
3578    /////////////////////////
3579    case XRAM_RSP_HEAP_REQ:    // Get the lock to the HEAP
3580    {
3581      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
3582      {
3583        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3584      }
3585
3586#if DEBUG_MEMC_XRAM_RSP
3587if(m_debug_xram_rsp_fsm)
3588std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_REQ>"
3589          << " Requesting HEAP lock" << std::endl;
3590#endif
3591      break;
3592    }
3593    /////////////////////////
3594    case XRAM_RSP_HEAP_ERASE: // erase the copies and send invalidations
3595    {
3596      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
3597      {
3598        HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
3599
3600        xram_rsp_to_cc_send_fifo_srcid    = entry.owner.srcid;
3601#if L1_MULTI_CACHE
3602        xram_rsp_to_cc_send_fifo_cache_id = entry.owner.cache_id;
3603#endif
3604        xram_rsp_to_cc_send_fifo_inst  = entry.owner.inst;
3605        xram_rsp_to_cc_send_fifo_put   = true;
3606        if(m_xram_rsp_to_cc_send_inst_fifo.wok())
3607        {
3608          r_xram_rsp_next_ptr = entry.next;
3609          if(entry.next == r_xram_rsp_next_ptr.read())   // last copy
3610          {
3611            r_xram_rsp_to_cc_send_multi_req = true;
3612            r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
3613          }
3614          else
3615          {
3616            r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3617          }
3618        }
3619        else
3620        {
3621          r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3622        }
3623
3624#if DEBUG_MEMC_XRAM_RSP
3625if(m_debug_xram_rsp_fsm)
3626std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_ERASE>"
3627          << " Erase copy:"
3628          << " srcid = " << std::dec << entry.owner.srcid
3629          << " / inst = " << std::dec << entry.owner.inst << std::endl;
3630#endif
3631      }
3632      break;
3633    }
3634    /////////////////////////
3635    case XRAM_RSP_HEAP_LAST:  // last copy
3636    {
3637      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP)
3638      {
3639        std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST"
3640                   << " bad HEAP allocation" << std::endl;
3641        exit(0);
3642      }
3643      size_t free_pointer = m_heap.next_free_ptr();
3644
3645      HeapEntry last_entry;
3646      last_entry.owner.srcid    = 0;
3647#if L1_MULTI_CACHE
3648      last_entry.owner.cache_id = 0;
3649#endif
3650      last_entry.owner.inst     = false;
3651      if(m_heap.is_full())
3652      {
3653        last_entry.next     = r_xram_rsp_next_ptr.read();
3654        m_heap.unset_full();
3655      }
3656      else
3657      {
3658        last_entry.next     = free_pointer;
3659      }
3660
3661      m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
3662      m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
3663
3664      r_xram_rsp_fsm = XRAM_RSP_IDLE;
3665
3666#if DEBUG_MEMC_XRAM_RSP
3667if(m_debug_xram_rsp_fsm)
3668std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_LAST>"
3669          << " Heap housekeeping" << std::endl;
3670#endif
3671      break;
3672    }
3673    // ///////////////////////
3674    case XRAM_RSP_ERROR_ERASE:  // erase TRT entry in case of error
3675    {
3676      m_trt.erase(r_xram_rsp_trt_index.read());
3677
3678      // Next state
3679      if(r_xram_rsp_trt_buf.proc_read) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3680      else                             r_xram_rsp_fsm = XRAM_RSP_IDLE;
3681
3682#if DEBUG_MEMC_XRAM_RSP
3683if(m_debug_xram_rsp_fsm)
3684std::cout << "  <MEMC " << name() << " XRAM_RSP_ERROR_ERASE>"
3685          << " Error reported by XRAM / erase the TRT entry" << std::endl;
3686#endif
3687      break;
3688    }
3689    ////////////////////////
3690    case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3691    {
3692      if(!r_xram_rsp_to_tgt_rsp_req.read()) 
3693      {
3694        r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3695        r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3696        r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3697        for(size_t i=0; i < m_words; i++) 
3698        {
3699            r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3700        }
3701        r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3702        r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3703        r_xram_rsp_to_tgt_rsp_rerror = true;
3704        r_xram_rsp_to_tgt_rsp_req    = true;
3705
3706        r_xram_rsp_fsm = XRAM_RSP_IDLE;
3707
3708#if DEBUG_MEMC_XRAM_RSP
3709if(m_debug_xram_rsp_fsm)
3710    std::cout << "  <MEMC " << name() 
3711              << " XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3712              << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
3713#endif
3714      }
3715      break;
3716    }
3717  } // end swich r_xram_rsp_fsm
3718
3719  ////////////////////////////////////////////////////////////////////////////////////
3720  //    CLEANUP FSM
3721  ////////////////////////////////////////////////////////////////////////////////////
3722  // The CLEANUP FSM handles the cleanup request from L1 caches.
3723  // It accesses the cache directory and the heap to update the list of copies.
3724  ////////////////////////////////////////////////////////////////////////////////////
3725
3726  switch(r_cleanup_fsm.read())
3727  {
3728    //////////////////
3729    case CLEANUP_IDLE:     // Get first DSPIN flit of the CLEANUP command
3730    {
3731      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
3732
3733      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
3734
3735      uint32_t srcid =
3736        DspinDhccpParam::dspin_get(
3737            flit,
3738            DspinDhccpParam::CLEANUP_SRCID);
3739
3740      uint8_t type =
3741        DspinDhccpParam::dspin_get(
3742            flit,
3743            DspinDhccpParam::FROM_L1_TYPE);
3744
3745      r_cleanup_way_index =
3746        DspinDhccpParam::dspin_get(
3747            flit,
3748            DspinDhccpParam::CLEANUP_WAY_INDEX);
3749
3750      r_cleanup_nline =
3751        DspinDhccpParam::dspin_get(
3752            flit,
3753            DspinDhccpParam::CLEANUP_NLINE_MSB) << 32;
3754
3755      r_cleanup_inst  = (type == DspinDhccpParam::TYPE_CLEANUP_INST);
3756      r_cleanup_srcid = srcid;
3757
3758      if(srcid >= m_initiators)
3759      {
3760        std::cout
3761            << "VCI_MEM_CACHE ERROR " << name()
3762            << " CLEANUP_IDLE state"  << std::endl
3763            << "illegal srcid for cleanup request" << std::endl;
3764
3765        exit(0);
3766      }
3767
3768      m_cpt_cleanup++;
3769      cc_receive_to_cleanup_fifo_get = true;
3770      r_cleanup_fsm                  = CLEANUP_GET_NLINE;
3771
3772#if DEBUG_MEMC_CLEANUP
3773      if(m_debug_cleanup_fsm)
3774      {
3775        std::cout
3776            << "  <MEMC "         << name()
3777            << " CLEANUP_IDLE> Cleanup request:" << std::hex
3778            << " / owner_id = "   << srcid
3779            << " / owner_ins = "  << (type == DspinDhccpParam::TYPE_CLEANUP_INST)
3780            << std::endl;
3781      }
3782#endif
3783      break;
3784    }
3785
3786    ///////////////////////
3787    case CLEANUP_GET_NLINE:  // GET second DSPIN flit of the cleanup command
3788    {
3789      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
3790
3791      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
3792
3793      addr_t nline = r_cleanup_nline.read() |
3794        DspinDhccpParam::dspin_get(flit, DspinDhccpParam::CLEANUP_NLINE_LSB);
3795
3796      cc_receive_to_cleanup_fifo_get = true;
3797      r_cleanup_nline                = nline;
3798      r_cleanup_fsm                  = CLEANUP_DIR_REQ;
3799
3800#if DEBUG_MEMC_CLEANUP
3801      if(m_debug_cleanup_fsm)
3802      {
3803        std::cout
3804            << "  <MEMC "         << name()
3805            << " CLEANUP_GET_NLINE> Cleanup request:"
3806            << std::hex
3807            << " / address = "    << nline * m_words * 4
3808            << std::endl;
3809      }
3810#endif
3811      break;
3812    }
3813
3814    /////////////////////
3815    case CLEANUP_DIR_REQ:
3816    {
3817      // Get the lock to the directory
3818      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP) break;
3819
3820      r_cleanup_fsm = CLEANUP_DIR_LOCK;
3821
3822#if DEBUG_MEMC_CLEANUP
3823      if(m_debug_cleanup_fsm)
3824      {
3825        std::cout
3826            << "  <MEMC " << name() << " CLEANUP_DIR_REQ> Requesting DIR lock "
3827            << std::endl;
3828      }
3829#endif
3830      break;
3831    }
3832
3833    //////////////////////
3834    case CLEANUP_DIR_LOCK:
3835    {
3836      // test directory status
3837      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
3838      {
3839        std::cout
3840            << "VCI_MEM_CACHE ERROR " << name()
3841            << " CLEANUP_DIR_LOCK state"
3842            << " bad DIR allocation" << std::endl;
3843
3844        exit(0);
3845      }
3846
3847      // Read the directory
3848      size_t way = 0;
3849      addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
3850
3851      DirectoryEntry entry   = m_cache_directory.read(cleanup_address , way);
3852      r_cleanup_is_cnt       = entry.is_cnt;
3853      r_cleanup_dirty        = entry.dirty;
3854      r_cleanup_tag          = entry.tag;
3855      r_cleanup_lock         = entry.lock;
3856      r_cleanup_way          = way;
3857      r_cleanup_count        = entry.count;
3858      r_cleanup_ptr          = entry.ptr;
3859      r_cleanup_copy         = entry.owner.srcid;
3860      r_cleanup_copy_inst    = entry.owner.inst;
3861#if L1_MULTI_CACHE
3862      r_cleanup_copy_cache   = entry.owner.cache_id;
3863#endif
3864
3865      // hit :
3866      // the copy must be cleared
3867      if(entry.valid)
3868      {
3869        assert(
3870            (entry.count > 0) &&
3871            "VCI MEM CACHE ERROR: "
3872            "In CLEANUP_DIR_LOCK, CLEANUP command on a valid entry "
3873            "with no copies");
3874
3875        // no access to the heap
3876        if((entry.count == 1) || (entry.is_cnt))
3877        {
3878          r_cleanup_fsm = CLEANUP_DIR_WRITE;
3879        }
3880        // access to the heap
3881        else
3882        {
3883          r_cleanup_fsm = CLEANUP_HEAP_REQ;
3884        }
3885      }
3886      // miss :
3887      // we must check the update table for a pending
3888      // invalidation transaction
3889      else
3890      {
3891        r_cleanup_fsm = CLEANUP_UPT_LOCK;
3892      }
3893
3894#if DEBUG_MEMC_CLEANUP
3895      if(m_debug_cleanup_fsm)
3896      {
3897        std::cout
3898            << "  <MEMC " << name()
3899            << " CLEANUP_DIR_LOCK> Test directory status: "
3900            << std::hex
3901            << " line = "         << cleanup_address
3902            << " / hit = "        << entry.valid
3903            << " / dir_id = "     << entry.owner.srcid
3904            << " / dir_ins = "    << entry.owner.inst
3905            << " / search_id = "  << r_cleanup_srcid.read()
3906            << " / search_ins = " << r_cleanup_inst.read()
3907            << " / count = "      << entry.count
3908            << " / is_cnt = "     << entry.is_cnt
3909            << std::endl;
3910      }
3911#endif
3912      break;
3913    }
3914
3915    ///////////////////////
3916    case CLEANUP_DIR_WRITE:
3917    {
3918      // Update the directory entry without heap access
3919      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
3920      {
3921        std::cout
3922            << "VCI_MEM_CACHE ERROR " << name()
3923            << " CLEANUP_DIR_WRITE state"
3924            << " bad DIR allocation" << std::endl;
3925
3926        exit(0);
3927      }
3928
3929      size_t way         = r_cleanup_way.read();
3930      size_t set         = m_y[(addr_t)(r_cleanup_nline.read()*m_words*4)];
3931      bool   match_srcid = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3932
3933#if L1_MULTI_CACHE
3934      match_srcid       &= (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3935#endif
3936
3937      bool   match_inst  = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
3938      bool   match       = match_srcid && match_inst;
3939
3940      if(not r_cleanup_is_cnt.read() and not match)
3941      {
3942        std::cout
3943            << "VCI_MEM_CACHE ERROR : Cleanup request on a valid"
3944            << "entry using linked list mode with no corresponding"
3945            << "directory or heap entry"
3946            << std::endl;
3947
3948        exit(1);
3949      }
3950
3951      // update the cache directory (for the copies)
3952      DirectoryEntry entry;
3953      entry.valid       = true;
3954      entry.is_cnt      = r_cleanup_is_cnt.read();
3955      entry.dirty       = r_cleanup_dirty.read();
3956      entry.tag         = r_cleanup_tag.read();
3957      entry.lock        = r_cleanup_lock.read();
3958      entry.ptr         = r_cleanup_ptr.read();
3959      entry.count       = r_cleanup_count.read() - 1;
3960      entry.owner.srcid = 0;
3961      entry.owner.inst  = 0;
3962
3963#if L1_MULTI_CACHE
3964      entry.owner.cache_id = 0;
3965#endif
3966
3967      m_cache_directory.write(set, way, entry);
3968
3969      r_cleanup_fsm = CLEANUP_SEND_ACK;
3970
3971#if DEBUG_MEMC_CLEANUP
3972      if(m_debug_cleanup_fsm)
3973      {
3974        std::cout
3975            << "  <MEMC " << name()
3976            << " CLEANUP_DIR_WRITE> Update directory:"
3977            << std::hex
3978            << " address = "   << r_cleanup_nline.read() * m_words * 4
3979            << " / dir_id = "  << entry.owner.srcid
3980            << " / dir_ins = " << entry.owner.inst
3981            << " / count = "   << entry.count
3982            << " / is_cnt = "  << entry.is_cnt
3983            << std::endl;
3984      }
3985#endif
3986
3987      break;
3988    }
3989
3990    //////////////////////
3991    case CLEANUP_HEAP_REQ:
3992    {
3993      // get the lock to the HEAP directory
3994      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP) break;
3995
3996      r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3997
3998#if DEBUG_MEMC_CLEANUP
3999      if(m_debug_cleanup_fsm)
4000      {
4001        std::cout
4002            << "  <MEMC " << name()
4003            << " CLEANUP_HEAP_REQ> HEAP lock acquired "
4004            << std::endl;
4005      }
4006#endif
4007      break;
4008    }
4009
4010    //////////////////////
4011    case CLEANUP_HEAP_LOCK:
4012    {
4013      // two cases are handled in this state :
4014      // 1. the matching copy is directly in the directory
4015      // 2. the matching copy is the first copy in the heap
4016      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4017      {
4018        std::cout
4019            << "VCI_MEM_CACHE ERROR " << name()
4020            << " CLEANUP_HEAP_LOCK state"
4021            << " bad HEAP allocation" << std::endl;
4022
4023        exit(0);
4024      }
4025
4026      size_t way            = r_cleanup_way.read();
4027      size_t set            = m_y[(addr_t)(r_cleanup_nline.read() *m_words*4)];
4028
4029      HeapEntry heap_entry  = m_heap.read(r_cleanup_ptr.read());
4030      bool last             = (heap_entry.next == r_cleanup_ptr.read());
4031
4032      // match_dir computation
4033      bool match_dir_srcid  = (r_cleanup_copy.read()      == r_cleanup_srcid.read());
4034      bool match_dir_inst   = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
4035      bool match_dir        = match_dir_srcid  and match_dir_inst;
4036
4037      // match_heap computation
4038      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4039      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
4040      bool match_heap       = match_heap_srcid and match_heap_inst;
4041
4042      r_cleanup_prev_ptr    = r_cleanup_ptr.read();
4043      r_cleanup_prev_srcid  = heap_entry.owner.srcid;
4044      r_cleanup_prev_inst   = heap_entry.owner.inst;
4045
4046#if L1_MULTI_CACHE
4047      match_dir  = match_dir  and(r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
4048      match_heap = match_heap and(heap_entry.owner.cache_id   == r_cleanup_pktid.read());
4049      r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4050#endif
4051
4052      if(not match_dir and not match_heap and last)
4053      {
4054        std::cout
4055            << "VCI_MEM_CACHE ERROR " << name()
4056            << " CLEANUP_HEAP_LOCK state"
4057            << " hit but copy not found"
4058            << std::endl;
4059/**/
4060        std::cout
4061          << "r_cleanup_srcid = " << r_cleanup_srcid.read()
4062          << " / r_cleanup_inst = " << r_cleanup_inst.read() << std::endl
4063          << "r_cleanup_copy = " << r_cleanup_copy.read()
4064          << " / r_cleanup_copy_inst = " << r_cleanup_copy_inst.read() << std::endl
4065          << "heap_entry.owner.srcid = " << heap_entry.owner.srcid
4066          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl;
4067/**/
4068        exit(0);
4069      }
4070
4071      if(match_dir and match_heap)
4072      {
4073        std::cout
4074            << "VCI_MEM_CACHE ERROR " << name()
4075            << " CLEANUP_HEAP_LOCK state"
4076            << " two copies matching the cleanup owner id"
4077            << std::endl;
4078/**/
4079        std::cout
4080          << "r_cleanup_srcid = " << r_cleanup_srcid.read()
4081          << " / r_cleanup_inst = " << r_cleanup_inst.read() << std::endl
4082          << "r_cleanup_copy = " << r_cleanup_copy.read()
4083          << " / r_cleanup_copy_inst = " << r_cleanup_copy_inst.read() << std::endl
4084          << "heap_entry.owner.srcid = " << heap_entry.owner.srcid
4085          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl;
4086/**/
4087
4088        exit(0);
4089      }
4090
4091      DirectoryEntry dir_entry;
4092      dir_entry.valid          = true;
4093      dir_entry.is_cnt         = r_cleanup_is_cnt.read();
4094      dir_entry.dirty          = r_cleanup_dirty.read();
4095      dir_entry.tag            = r_cleanup_tag.read();
4096      dir_entry.lock           = r_cleanup_lock.read();
4097      dir_entry.count          = r_cleanup_count.read()-1;
4098
4099      // the matching copy is registered in the directory and
4100      // it must be replaced by the first copy registered in
4101      // the heap. The corresponding entry must be freed
4102      if(match_dir)
4103      {
4104        dir_entry.ptr            = heap_entry.next;
4105        dir_entry.owner.srcid    = heap_entry.owner.srcid;
4106        dir_entry.owner.inst     = heap_entry.owner.inst;
4107
4108#if L1_MULTI_CACHE
4109        dir_entry.owner.cache_id = heap_entry.owner.cache_id;
4110#endif
4111
4112        r_cleanup_next_ptr       = r_cleanup_ptr.read();
4113        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
4114      }
4115
4116      // the matching copy is the first copy in the heap
4117      // It must be freed and the copy registered in directory
4118      // must point to the next copy in heap
4119      else if(match_heap)
4120      {
4121        dir_entry.ptr            = heap_entry.next;
4122        dir_entry.owner.srcid    = r_cleanup_copy.read();
4123        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
4124
4125#if L1_MULTI_CACHE
4126        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
4127#endif
4128
4129        r_cleanup_next_ptr       = r_cleanup_ptr.read();
4130        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
4131      }
4132
4133      // The matching copy is in the heap, but is not the first copy
4134      // The directory entry must be modified to decrement count
4135      else
4136      {
4137        dir_entry.ptr            = r_cleanup_ptr.read();
4138        dir_entry.owner.srcid    = r_cleanup_copy.read();
4139        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
4140
4141#if L1_MULTI_CACHE
4142        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
4143#endif
4144
4145        r_cleanup_next_ptr       = heap_entry.next;
4146        r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
4147      }
4148
4149      m_cache_directory.write(set,way,dir_entry);
4150
4151#if DEBUG_MEMC_CLEANUP
4152      if(m_debug_cleanup_fsm)
4153      {
4154        std::cout
4155            << "  <MEMC " << name()
4156            << " CLEANUP_HEAP_LOCK> Checks matching:"
4157            << " address = "      << r_cleanup_nline.read() * m_words * 4
4158            << " / dir_id = "     << r_cleanup_copy.read()
4159            << " / dir_ins = "    << r_cleanup_copy_inst.read()
4160            << " / heap_id = "    << heap_entry.owner.srcid
4161            << " / heap_ins = "   << heap_entry.owner.inst
4162            << " / search_id = "  << r_cleanup_srcid.read()
4163            << " / search_ins = " << r_cleanup_inst.read()
4164            << std::endl;
4165      }
4166#endif
4167      break;
4168    }
4169
4170    ////////////////////////
4171    case CLEANUP_HEAP_SEARCH:
4172    {
4173      // This state is handling the case where the copy
4174      // is in the heap, but is not the first in the linked list
4175      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4176      {
4177        std::cout
4178            << "VCI_MEM_CACHE ERROR " << name()
4179            << " CLEANUP_HEAP_SEARCH state"
4180            << " bad HEAP allocation" << std::endl;
4181
4182        exit(0);
4183      }
4184
4185      HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
4186
4187      bool last             = (heap_entry.next        == r_cleanup_next_ptr.read());
4188      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4189      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
4190      bool match_heap       = match_heap_srcid && match_heap_inst;
4191
4192#if L1_MULTI_CACHE
4193      match_heap = match_heap and(heap_entry.owner.cache_id == r_cleanup_pktid.read());
4194#endif
4195
4196      if(not match_heap and last)
4197      {
4198        std::cout
4199            << "VCI_MEM_CACHE_ERROR " << name()
4200            << " CLEANUP_HEAP_SEARCH state"
4201            << " cleanup on valid line but copy not found"
4202            << std::endl;
4203
4204        exit(0);
4205      }
4206
4207      // the matching copy must be removed
4208      if(match_heap)
4209      {
4210        // re-use ressources
4211        r_cleanup_ptr = heap_entry.next;
4212        r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
4213      }
4214      // test the next in the linked list
4215      else
4216      {
4217        r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
4218        r_cleanup_prev_srcid    = heap_entry.owner.srcid;
4219        r_cleanup_prev_inst     = heap_entry.owner.inst;
4220        r_cleanup_next_ptr      = heap_entry.next;
4221
4222        r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
4223
4224#if L1_MULTI_CACHE
4225        r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4226#endif
4227      }
4228
4229#if DEBUG_MEMC_CLEANUP
4230      if(m_debug_cleanup_fsm)
4231      {
4232        if(not match_heap)
4233        {
4234          std::cout
4235              << "  <MEMC " << name()
4236              << " CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
4237              << std::endl;
4238        }
4239        else
4240        {
4241          std::cout
4242              << "  <MEMC " << name()
4243              << " CLEANUP_HEAP_SEARCH> Matching copy found:"
4244              << std::endl;
4245        }
4246
4247        std::cout
4248            << " address = "      << r_cleanup_nline.read() * m_words * 4
4249            << " / heap_id = "    << heap_entry.owner.srcid
4250            << " / heap_ins = "   << heap_entry.owner.inst
4251            << " / search_id = "  << r_cleanup_srcid.read()
4252            << " / search_ins = " << r_cleanup_inst.read()
4253            << " / last = "       << last
4254            << std::endl;
4255      }
4256#endif
4257      break;
4258    }
4259
4260    case CLEANUP_HEAP_CLEAN:
4261    {
4262      // remove a copy in the linked list
4263      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4264      {
4265        std::cout
4266            << "VCI_MEM_CACHE ERROR " << name()
4267            << " CLEANUP_HEAP_CLEAN state"
4268            << "Bad HEAP allocation"  << std::endl;
4269
4270        exit(0);
4271      }
4272
4273      HeapEntry heap_entry;
4274      heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4275      heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4276
4277#if L1_MULTI_CACHE
4278      heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4279#endif
4280
4281      bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
4282
4283      // this is the last entry of the list of copies
4284      if(last)
4285      {
4286        heap_entry.next = r_cleanup_prev_ptr.read();
4287      }
4288      // this is not the last entry
4289      else
4290      {
4291        heap_entry.next = r_cleanup_ptr.read();
4292      }
4293
4294      m_heap.write(r_cleanup_prev_ptr.read(), heap_entry);
4295
4296      r_cleanup_fsm = CLEANUP_HEAP_FREE;
4297
4298#if DEBUG_MEMC_CLEANUP
4299      if(m_debug_cleanup_fsm)
4300      {
4301        std::cout
4302            << "  <MEMC " << name()
4303            << " CLEANUP_HEAP_SEARCH> Remove the copy in the linked list"
4304            << std::endl;
4305      }
4306#endif
4307      break;
4308    }
4309
4310    case CLEANUP_HEAP_FREE:
4311    {
4312      // The heap entry pointed by r_cleanup_next_ptr is freed
4313      // and becomes the head of the list of free entries
4314      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4315      {
4316        std::cout
4317            << "VCI_MEM_CACHE ERROR " << name()
4318            << " CLEANUP_HEAP_CLEAN state" << std::endl
4319            << "Bad HEAP allocation" << std::endl;
4320
4321        exit(0);
4322      }
4323
4324      HeapEntry heap_entry;
4325      heap_entry.owner.srcid    = 0;
4326      heap_entry.owner.inst     = false;
4327
4328#if L1_MULTI_CACHE
4329      heap_entry.owner.cache_id = 0;
4330#endif
4331
4332      if(m_heap.is_full())
4333      {
4334        heap_entry.next = r_cleanup_next_ptr.read();
4335      }
4336      else
4337      {
4338        heap_entry.next = m_heap.next_free_ptr();
4339      }
4340
4341      m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4342      m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4343      m_heap.unset_full();
4344
4345      r_cleanup_fsm = CLEANUP_SEND_ACK;
4346
4347#if DEBUG_MEMC_CLEANUP
4348      if(m_debug_cleanup_fsm)
4349      {
4350        std::cout
4351            << "  <MEMC " << name()
4352            << " CLEANUP_HEAP_SEARCH> Update the list of free entries"
4353            << std::endl;
4354      }
4355#endif
4356      break;
4357    }
4358
4359    case CLEANUP_UPT_LOCK:
4360    {
4361      // search pending invalidate transaction matching the Cleanup NLINE in the UPDATE TABLE
4362      // get the lock in the UPDATE_TABLE
4363      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP) break;
4364
4365      size_t index = 0;
4366      bool   match_inval;
4367
4368      match_inval = m_upt.search_inval(r_cleanup_nline.read(), index);
4369
4370      // no pending inval
4371      if(not match_inval)
4372      {
4373        r_cleanup_fsm = CLEANUP_SEND_ACK;
4374
4375#if DEBUG_MEMC_CLEANUP
4376        if(m_debug_cleanup_fsm)
4377        {
4378          std::cout
4379              << "  <MEMC " << name()
4380              << " CLEANUP_UPT_LOCK> Unexpected cleanup"
4381              << " with no corresponding UPT entry:"
4382              << " address = " << std::hex
4383              << (r_cleanup_nline.read() *4*m_words)
4384              << std::endl;
4385        }
4386#endif
4387        break;
4388      }
4389
4390      // pending inval
4391      r_cleanup_write_srcid    = m_upt.srcid(index);
4392      r_cleanup_write_trdid    = m_upt.trdid(index);
4393      r_cleanup_write_pktid    = m_upt.pktid(index);
4394      r_cleanup_write_need_rsp = m_upt.need_rsp(index);
4395      r_cleanup_index          = index;
4396
4397      r_cleanup_fsm         = CLEANUP_UPT_DECREMENT;
4398
4399#if DEBUG_MEMC_CLEANUP
4400      if(m_debug_cleanup_fsm)
4401      {
4402        std::cout
4403            << "  <MEMC " << name()
4404            << " CLEANUP_UPT_LOCK> Cleanup matching pending"
4405            << " invalidate transaction on UPT:"
4406            << std::hex
4407            << " address = "   << r_cleanup_nline.read() * m_words * 4
4408            << " upt_entry = " << index
4409            << std::endl;
4410      }
4411#endif
4412      break;
4413    }
4414
4415    case CLEANUP_UPT_DECREMENT:
4416    {
4417      // decrement response counter in UPT matching entry
4418      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4419      {
4420        std::cout
4421            << "VCI_MEM_CACHE ERROR "         << name()
4422            << " CLEANUP_UPT_DECREMENT state" << std::endl
4423            << "Bad UPT allocation"
4424            << std::endl;
4425
4426        exit(0);
4427      }
4428
4429      size_t count = 0;
4430      m_upt.decrement(r_cleanup_index.read(), count);
4431
4432      // invalidation transaction finished
4433      // (all acknowledgements received)
4434      if(count == 0)
4435      {
4436        r_cleanup_fsm = CLEANUP_UPT_CLEAR;
4437      }
4438      // invalidation transaction not finished
4439      else
4440      {
4441        r_cleanup_fsm = CLEANUP_SEND_ACK ;
4442      }
4443
4444#if DEBUG_MEMC_CLEANUP
4445      if(m_debug_cleanup_fsm)
4446      {
4447        std::cout
4448            << "  <MEMC "      << name()
4449            << " CLEANUP_UPT_DECREMENT> Decrement response counter in UPT:"
4450            << " UPT_index = " << r_cleanup_index.read()
4451            << " rsp_count = " << count
4452            << std::endl;
4453      }
4454#endif
4455      break;
4456    }
4457
4458    case CLEANUP_UPT_CLEAR:
4459    {
4460      // Clear UPT entry of finished invalidation transaction
4461      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4462      {
4463        std::cout
4464            << "VCI_MEM_CACHE ERROR "     << name()
4465            << " CLEANUP_UPT_CLEAR state" << std::endl
4466            << "Bad UPT allocation"
4467            << std::endl;
4468
4469        exit(0);
4470      }
4471
4472      m_upt.clear(r_cleanup_index.read());
4473
4474      if(r_cleanup_write_need_rsp.read())
4475      {
4476        r_cleanup_fsm = CLEANUP_WRITE_RSP;
4477      }
4478      else
4479      {
4480        r_cleanup_fsm = CLEANUP_SEND_ACK;
4481      }
4482
4483#if DEBUG_MEMC_CLEANUP
4484      if(m_debug_cleanup_fsm)
4485      {
4486        std::cout
4487            << "  <MEMC "      << name()
4488            << " CLEANUP_UPT_CLEAR> Clear entry in UPT:"
4489            << " UPT_index = " << r_cleanup_index.read()
4490            << std::endl;
4491      }
4492#endif
4493      break;
4494    }
4495
4496    case CLEANUP_WRITE_RSP:
4497    {
4498      // response to a previous write on the direct network
4499      // wait if pending request to the TGT_RSP FSM
4500      if(r_cleanup_to_tgt_rsp_req.read()) break;
4501
4502      // no pending request
4503      r_cleanup_to_tgt_rsp_req     = true;
4504      r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4505      r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4506      r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4507
4508      r_cleanup_fsm                = CLEANUP_SEND_ACK;
4509
4510#if DEBUG_MEMC_CLEANUP
4511      if(m_debug_cleanup_fsm)
4512      {
4513        std::cout
4514            << "  <MEMC " << name()
4515            << " CLEANUP_WRITE_RSP> Send a response to a previous"
4516            << " write request waiting for coherence transaction completion: "
4517            << " rsrcid = "   << std::dec << r_cleanup_write_srcid.read()
4518            << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read()
4519            << std::endl;
4520      }
4521#endif
4522      break;
4523    }
4524
4525    case CLEANUP_SEND_ACK:
4526    {
4527      // acknowledgement to a cleanup command
4528      // on the coherence network (request to the CC_SEND FSM).
4529      // wait if pending request to the CC_SEND FSM
4530      if(r_cleanup_to_cc_send_req.read()) break;
4531
4532      r_cleanup_to_cc_send_req       = true;
4533      r_cleanup_to_cc_send_set_index = r_cleanup_nline.read() & 0xFFFF;
4534      r_cleanup_to_cc_send_way_index = r_cleanup_way_index.read();
4535      r_cleanup_to_cc_send_srcid     = r_cleanup_srcid.read();
4536      r_cleanup_to_cc_send_inst      = r_cleanup_inst.read();
4537
4538      r_cleanup_fsm = CLEANUP_IDLE;
4539
4540#if DEBUG_MEMC_CLEANUP
4541      if(m_debug_cleanup_fsm)
4542      {
4543        std::cout
4544            << "  <MEMC " << name()
4545            << " CLEANUP_SEND_ACK> Send the response to a cleanup request:"
4546            << " srcid = " << std::dec << r_cleanup_srcid.read()
4547            << std::endl;
4548      }
4549#endif
4550      break;
4551    }
4552  } // end switch cleanup fsm
4553
4554  ////////////////////////////////////////////////////////////////////////////////////
4555  //    CAS FSM
4556  ////////////////////////////////////////////////////////////////////////////////////
4557  // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4558  // that are handled as "compare-and-swap instructions.
4559  //
4560  // This command contains two or four flits:
4561  // - In case of 32 bits atomic access, the first flit contains the value read
4562  // by a previous LL instruction, the second flit contains the value to be writen.
4563  // - In case of 64 bits atomic access, the 2 first flits contains the value read
4564  // by a previous LL instruction, the 2 next flits contains the value to be writen.
4565  //
4566  // The target address is cachable. If it is replicated in other L1 caches
4567  // than the writer, a coherence operation is done.
4568  //
4569  // It access the directory to check hit / miss.
4570  // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4571  // If a read transaction to the XRAM for this line already exists,
4572  // or if the transaction table is full, it goes to the WAIT state
4573  // to release the locks and try again. When the GET transaction has been
4574  // launched, it goes to the WAIT state and try again.
4575  // The CAS request is not consumed in the FIFO until a HIT is obtained.
4576  // - In case of hit...
4577  ///////////////////////////////////////////////////////////////////////////////////
4578
4579  switch(r_cas_fsm.read())
4580  {
4581      /////////////
4582    case CAS_IDLE:     // fill the local rdata buffers
4583    {
4584      if(m_cmd_cas_addr_fifo.rok())
4585      {
4586
4587#if DEBUG_MEMC_CAS
4588        if(m_debug_cas_fsm)
4589        {
4590          std::cout << "  <MEMC " << name() << " CAS_IDLE> CAS command: " << std::hex
4591                    << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4592                    << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4593                    << " wdata = " << m_cmd_cas_wdata_fifo.read()
4594                    << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4595                    << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4596        }
4597#endif
4598        if(m_cmd_cas_eop_fifo.read())
4599        {
4600          m_cpt_cas++;
4601          r_cas_fsm = CAS_DIR_REQ;
4602        }
4603        else  // we keep the last word in the FIFO
4604        {
4605          cmd_cas_fifo_get = true;
4606        }
4607        // We fill the two buffers
4608        if(r_cas_cpt.read() < 2)    // 32 bits access
4609          r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4610
4611        if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4612          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4613
4614        if(r_cas_cpt.read() >3)  // more than 4 flits...
4615        {
4616          std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4617                    << std::endl;
4618          exit(0);
4619        }
4620
4621        if(r_cas_cpt.read() ==2)
4622          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4623
4624        r_cas_cpt = r_cas_cpt.read() +1;
4625      }
4626      break;
4627    }
4628
4629    /////////////////
4630    case CAS_DIR_REQ:
4631    {
4632      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4633      {
4634        r_cas_fsm = CAS_DIR_LOCK;
4635      }
4636
4637#if DEBUG_MEMC_CAS
4638      if(m_debug_cas_fsm)
4639      {
4640        std::cout
4641            << "  <MEMC " << name() << " CAS_DIR_REQ> Requesting DIR lock "
4642            << std::endl;
4643      }
4644#endif
4645      break;
4646    }
4647
4648    /////////////////
4649    case CAS_DIR_LOCK:  // Read the directory
4650    {
4651      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4652      {
4653        size_t way = 0;
4654        DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4655
4656        r_cas_is_cnt     = entry.is_cnt;
4657        r_cas_dirty      = entry.dirty;
4658        r_cas_tag        = entry.tag;
4659        r_cas_way        = way;
4660        r_cas_copy       = entry.owner.srcid;
4661#if L1_MULTI_CACHE
4662        r_cas_copy_cache = entry.owner.cache_id;
4663#endif
4664        r_cas_copy_inst  = entry.owner.inst;
4665        r_cas_ptr        = entry.ptr;
4666        r_cas_count      = entry.count;
4667
4668        if(entry.valid)  r_cas_fsm = CAS_DIR_HIT_READ;
4669        else             r_cas_fsm = CAS_MISS_TRT_LOCK;
4670
4671#if DEBUG_MEMC_CAS
4672        if(m_debug_cas_fsm)
4673        {
4674          std::cout << "  <MEMC " << name() << " CAS_DIR_LOCK> Directory acces"
4675                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4676                    << " / hit = " << std::dec << entry.valid
4677                    << " / count = " << entry.count
4678                    << " / is_cnt = " << entry.is_cnt << std::endl;
4679        }
4680#endif
4681      }
4682      else
4683      {
4684        std::cout
4685            << "VCI_MEM_CACHE ERROR " << name()
4686            << " CAS_DIR_LOCK state" << std::endl
4687            << "Bad DIR allocation"   << std::endl;
4688
4689        exit(0);
4690      }
4691
4692      break;
4693    }
4694    /////////////////////
4695    case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4696                            // and check data change in cache
4697    {
4698      size_t way  = r_cas_way.read();
4699      size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4700
4701      // update directory (lock & dirty bits)
4702      DirectoryEntry entry;
4703      entry.valid          = true;
4704      entry.is_cnt         = r_cas_is_cnt.read();
4705      entry.dirty          = true;
4706      entry.lock           = true;
4707      entry.tag            = r_cas_tag.read();
4708      entry.owner.srcid    = r_cas_copy.read();
4709#if L1_MULTI_CACHE
4710      entry.owner.cache_id = r_cas_copy_cache.read();
4711#endif
4712      entry.owner.inst     = r_cas_copy_inst.read();
4713      entry.count          = r_cas_count.read();
4714      entry.ptr            = r_cas_ptr.read();
4715
4716      m_cache_directory.write(set, way, entry);
4717
4718      // Stored data from cache in buffer to do the comparison in next state
4719      m_cache_data.read_line(way, set, r_cas_data);
4720
4721      r_cas_fsm = CAS_DIR_HIT_COMPARE;
4722
4723#if DEBUG_MEMC_CAS
4724      if(m_debug_cas_fsm)
4725      {
4726        std::cout
4727          << "  <MEMC " << name() << " CAS_DIR_HIT_READ> Read data from "
4728          << " cache and store it in buffer"
4729          << std::endl;
4730      }
4731#endif
4732      break;
4733    }
4734
4735    case CAS_DIR_HIT_COMPARE:
4736    {
4737      size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4738
4739      // Read data in buffer & check data change
4740      bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
4741
4742      if(r_cas_cpt.read() == 4)     // 64 bits CAS
4743        ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
4744
4745      // to avoid livelock, force the atomic access to fail pseudo-randomly
4746      bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
4747      r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
4748
4749      // cas success
4750      if(ok and not forced_fail)
4751      {
4752        r_cas_fsm = CAS_DIR_HIT_WRITE;
4753      }
4754      // cas failure
4755      else
4756      {
4757        r_cas_fsm = CAS_RSP_FAIL;
4758      }
4759
4760#if DEBUG_MEMC_CAS
4761      if(m_debug_cas_fsm)
4762      {
4763        std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_COMPARE> Compare the old"
4764                  << " and the new data"
4765                  << " / expected value = " << r_cas_rdata[0].read()
4766                  << " / actual value = "   << r_cas_data[word].read()
4767                  << " / forced_fail = "    << forced_fail << std::endl;
4768      }
4769#endif
4770      break;
4771    }
4772    //////////////////////
4773    case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4774      // write data in cache if no CC request
4775    {
4776      // The CAS is a success => sw access to the llsc_global_table
4777      m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
4778
4779      // test coherence request
4780      if(r_cas_count.read())   // replicated line
4781      {
4782        if(r_cas_is_cnt.read())
4783        {
4784          r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4785        }
4786        else if(!r_cas_to_cc_send_multi_req.read() &&
4787                !r_cas_to_cc_send_brdcast_req.read())
4788        {
4789          r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4790        }
4791        else
4792        {
4793          r_cas_fsm = CAS_WAIT;
4794        }
4795      }
4796      else                    // no copies
4797      {
4798        size_t way  = r_cas_way.read();
4799        size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4800        size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4801
4802        // cache update
4803        m_cache_data.write(way, set, word, r_cas_wdata.read());
4804        if(r_cas_cpt.read() == 4)
4805          m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4806
4807        r_cas_fsm = CAS_RSP_SUCCESS;
4808
4809        // monitor
4810        if(m_monitor_ok)
4811        {
4812          addr_t address = m_cmd_cas_addr_fifo.read();
4813          char buf[80];
4814          snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
4815                   (int)m_cmd_cas_srcid_fifo.read());
4816          check_monitor(buf, address, r_cas_wdata.read(), false);
4817
4818          if(r_cas_cpt.read() == 4)
4819            check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
4820        }
4821
4822#if DEBUG_MEMC_CAS
4823        if(m_debug_cas_fsm)
4824        {
4825          std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_WRITE> Update cache:"
4826                    << " way = " << std::dec << way
4827                    << " / set = " << set
4828                    << " / word = " << word
4829                    << " / value = " << r_cas_wdata.read()
4830                    << " / count = " << r_cas_count.read() << std::endl;
4831          std::cout << "  <MEMC "
4832                    << name() << " CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
4833        }
4834#endif
4835      }
4836      break;
4837    }
4838    /////////////////
4839    case CAS_UPT_LOCK:  // try to register the transaction in UPT
4840      // and write data in cache if successful registration
4841      // releases locks to retry later if UPT full
4842    {
4843      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
4844      {
4845        bool        wok        = false;
4846        size_t      index      = 0;
4847        size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4848        size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4849        size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4850        addr_t      nline      = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
4851        size_t      nb_copies  = r_cas_count.read();
4852
4853        wok = m_upt.set(true,  // it's an update transaction
4854                               false,   // it's not a broadcast
4855                               true,    // it needs a response
4856                               srcid,
4857                               trdid,
4858                               pktid,
4859                               nline,
4860                               nb_copies,
4861                               index);
4862        if(wok)   // coherence transaction registered in UPT
4863        {
4864          // cache update
4865          size_t way  = r_cas_way.read();
4866          size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4867          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4868
4869          m_cache_data.write(way, set, word, r_cas_wdata.read());
4870          if(r_cas_cpt.read() ==4)
4871            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4872
4873          r_cas_upt_index = index;
4874          r_cas_fsm = CAS_UPT_HEAP_LOCK;
4875
4876          // monitor
4877          if(m_monitor_ok)
4878          {
4879            addr_t address = m_cmd_cas_addr_fifo.read();
4880            char buf[80];
4881            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
4882                     (int)m_cmd_cas_srcid_fifo.read());
4883            check_monitor(buf, address, r_cas_wdata.read(), false);
4884
4885            if(r_cas_cpt.read() ==4)
4886              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
4887          }
4888        }
4889        else       //  releases the locks protecting UPT and DIR UPT full
4890        {
4891          r_cas_fsm = CAS_WAIT;
4892        }
4893
4894#if DEBUG_MEMC_CAS
4895        if(m_debug_cas_fsm)
4896        {
4897          std::cout << "  <MEMC " << name()
4898                    << " CAS_UPT_LOCK> Register multi-update transaction in UPT"
4899                    << " / wok = " << wok
4900                    << " / nline  = " << std::hex << nline
4901                    << " / count = " << nb_copies << std::endl;
4902        }
4903#endif
4904      }
4905      break;
4906    }
4907    /////////////
4908    case CAS_WAIT:   // release all locks and retry from beginning
4909    {
4910
4911#if DEBUG_MEMC_CAS
4912      if(m_debug_cas_fsm)
4913      {
4914        std::cout << "  <MEMC " << name()
4915                  << " CAS_WAIT> Release all locks" << std::endl;
4916      }
4917#endif
4918      r_cas_fsm = CAS_DIR_REQ;
4919      break;
4920    }
4921    //////////////////
4922    case CAS_UPT_HEAP_LOCK:  // lock the heap
4923    {
4924      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4925      {
4926
4927#if DEBUG_MEMC_CAS
4928        if(m_debug_cas_fsm)
4929        {
4930          std::cout << "  <MEMC " << name()
4931                    << " CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4932        }
4933#endif
4934        r_cas_fsm = CAS_UPT_REQ;
4935      }
4936      break;
4937    }
4938    ////////////////
4939    case CAS_UPT_REQ:  // send a first update request to CC_SEND FSM
4940    {
4941      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4942             "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4943
4944      if(!r_cas_to_cc_send_multi_req.read() && !r_cas_to_cc_send_brdcast_req.read())
4945      {
4946        r_cas_to_cc_send_brdcast_req  = false;
4947        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
4948        r_cas_to_cc_send_nline        = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
4949        r_cas_to_cc_send_index        = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4950        r_cas_to_cc_send_wdata        = r_cas_wdata.read();
4951
4952        if(r_cas_cpt.read() == 4)
4953        {
4954          r_cas_to_cc_send_is_long    = true;
4955          r_cas_to_cc_send_wdata_high = m_cmd_cas_wdata_fifo.read();
4956        }
4957        else
4958        {
4959          r_cas_to_cc_send_is_long    = false;
4960          r_cas_to_cc_send_wdata_high = 0;
4961        }
4962
4963        // We put the first copy in the fifo
4964        cas_to_cc_send_fifo_put     = true;
4965        cas_to_cc_send_fifo_inst    = r_cas_copy_inst.read();
4966        cas_to_cc_send_fifo_srcid   = r_cas_copy.read();
4967#if L1_MULTI_CACHE
4968        cas_to_cc_send_fifo_cache_id= r_cas_copy_cache.read();
4969#endif
4970        if(r_cas_count.read() == 1)  // one single copy
4971        {
4972          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4973          // update responses
4974          cmd_cas_fifo_get            = true;
4975          r_cas_to_cc_send_multi_req = true;
4976          r_cas_cpt = 0;
4977        }
4978        else      // several copies
4979        {
4980          r_cas_fsm = CAS_UPT_NEXT;
4981        }
4982
4983#if DEBUG_MEMC_CAS
4984        if(m_debug_cas_fsm)
4985        {
4986          std::cout << "  <MEMC " << name() << " CAS_UPT_REQ> Send the first update request to CC_SEND FSM "
4987                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4988                    << " / wdata = " << std::hex << r_cas_wdata.read()
4989                    << " / srcid = " << std::dec << r_cas_copy.read()
4990                    << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
4991        }
4992#endif
4993      }
4994      break;
4995    }
4996    /////////////////
4997    case CAS_UPT_NEXT:     // send a multi-update request to CC_SEND FSM
4998    {
4999      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
5000             and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
5001
5002      HeapEntry entry = m_heap.read(r_cas_ptr.read());
5003      cas_to_cc_send_fifo_srcid    = entry.owner.srcid;
5004#if L1_MULTI_CACHE
5005      cas_to_cc_send_fifo_cache_id = entry.owner.cache_id;
5006#endif
5007      cas_to_cc_send_fifo_inst     = entry.owner.inst;
5008      cas_to_cc_send_fifo_put = true;
5009
5010      if(m_cas_to_cc_send_inst_fifo.wok())   // request accepted by CC_SEND FSM
5011      {
5012        r_cas_ptr = entry.next;
5013        if(entry.next == r_cas_ptr.read())    // last copy
5014        {
5015          r_cas_to_cc_send_multi_req = true;
5016          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
5017          // all update responses
5018          cmd_cas_fifo_get = true;
5019          r_cas_cpt        = 0;
5020        }
5021      }
5022
5023#if DEBUG_MEMC_CAS
5024      if(m_debug_cas_fsm)
5025      {
5026        std::cout << "  <MEMC " << name() << " CAS_UPT_NEXT> Send the next update request to CC_SEND FSM "
5027                  << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
5028                  << " / wdata = " << std::hex << r_cas_wdata.read()
5029                  << " / srcid = " << std::dec << entry.owner.srcid
5030                  << " / inst = " << std::dec << entry.owner.inst << std::endl;
5031      }
5032#endif
5033      break;
5034    }
5035    /////////////////////
5036    case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
5037    {
5038      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5039      {
5040        if(!r_cas_to_ixr_cmd_req)    // we can transfer the request to IXR_CMD FSM
5041        {
5042          // fill the data buffer
5043          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
5044          for(size_t i = 0; i<m_words; i++)
5045          {
5046            if(i == word)
5047            {
5048              r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
5049            }
5050            else if((i == word+1) && (r_cas_cpt.read() == 4))   // 64 bit CAS
5051            {
5052              r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
5053            }
5054            else
5055            {
5056              r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
5057            }
5058          }
5059          size_t wok_index = 0;
5060          bool   wok       = !m_trt.full(wok_index);
5061          if(wok)
5062          {
5063            r_cas_trt_index = wok_index;
5064            r_cas_fsm       = CAS_BC_UPT_LOCK;
5065          }
5066          else
5067          {
5068            r_cas_fsm       = CAS_WAIT;
5069          }
5070        }
5071        else
5072        {
5073          r_cas_fsm = CAS_WAIT;
5074        }
5075      }
5076      break;
5077    }
5078    /////////////////////
5079    case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
5080                           // write data in cache in case of successful registration
5081    {
5082      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
5083      {
5084        bool        wok       = false;
5085        size_t      index     = 0;
5086        size_t      srcid     = m_cmd_cas_srcid_fifo.read();
5087        size_t      trdid     = m_cmd_cas_trdid_fifo.read();
5088        size_t      pktid     = m_cmd_cas_pktid_fifo.read();
5089        addr_t      nline     = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5090        size_t      nb_copies = r_cas_count.read();
5091
5092        // register a broadcast inval transaction in UPT
5093        wok = m_upt.set(false,  // it's an inval transaction
5094                               true,    // it's a broadcast
5095                               true,    // it needs a response
5096                               srcid,
5097                               trdid,
5098                               pktid,
5099                               nline,
5100                               nb_copies,
5101                               index);
5102
5103        if(wok)     // UPT not full
5104        {
5105          // cache update
5106          size_t way  = r_cas_way.read();
5107          size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
5108          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
5109
5110          m_cache_data.write(way, set, word, r_cas_wdata.read());
5111          if(r_cas_cpt.read() ==4)
5112            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
5113
5114          // monitor
5115          if(m_monitor_ok)
5116          {
5117            addr_t address = m_cmd_cas_addr_fifo.read();
5118            char buf[80];
5119            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
5120                     (int)m_cmd_cas_srcid_fifo.read());
5121            check_monitor(buf, address, r_cas_wdata.read(), false);
5122            if(r_cas_cpt.read() ==4)
5123              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
5124          }
5125          r_cas_upt_index = index;
5126          r_cas_fsm = CAS_BC_DIR_INVAL;
5127#if DEBUG_MEMC_CAS
5128          if(m_debug_cas_fsm)
5129          {
5130            std::cout << "  <MEMC " << name() << " CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
5131                      << " / nline = " << nline
5132                      << " / count = " << nb_copies
5133                      << " / upt_index = " << index << std::endl;
5134          }
5135#endif
5136        }
5137        else      //  releases the lock protecting UPT
5138        {
5139          r_cas_fsm = CAS_WAIT;
5140        }
5141      }
5142      break;
5143    }
5144    //////////////////
5145    case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
5146    {
5147      if((r_alloc_trt_fsm.read() == ALLOC_TRT_CAS) &&
5148          (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS) &&
5149          (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS))
5150      {
5151        // set TRT
5152        m_trt.set(r_cas_trt_index.read(),
5153                              false,    // PUT request to XRAM
5154                              m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())],
5155                              0,
5156                              0,
5157                              0,
5158                              false,    // not a processor read
5159                              0,
5160                              0,
5161                              std::vector<be_t> (m_words,0),
5162                              std::vector<data_t> (m_words,0));
5163
5164        // invalidate directory entry
5165        DirectoryEntry entry;
5166        entry.valid         = false;
5167        entry.dirty         = false;
5168        entry.tag         = 0;
5169        entry.is_cnt        = false;
5170        entry.lock          = false;
5171        entry.count         = 0;
5172        entry.owner.srcid   = 0;
5173#if L1_MULTI_CACHE
5174        entry.owner.cache_id= 0;
5175#endif
5176        entry.owner.inst    = false;
5177        entry.ptr           = 0;
5178        size_t set          = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
5179        size_t way          = r_cas_way.read();
5180        m_cache_directory.write(set, way, entry);
5181
5182        r_cas_fsm = CAS_BC_CC_SEND;
5183
5184#if DEBUG_MEMC_CAS
5185        if(m_debug_cas_fsm)
5186        {
5187          std::cout << "  <MEMC " << name() << " CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
5188                    << " / nline = " << std::hex << m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())]
5189                    << " / set = " << std::dec << set << " / way = " << way << std::endl;
5190        }
5191#endif
5192      }
5193      else
5194      {
5195        assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
5196      }
5197      break;
5198    }
5199    ///////////////////
5200    case CAS_BC_CC_SEND:  // Request the broadcast inval to CC_SEND FSM
5201    {
5202      if(!r_cas_to_cc_send_multi_req.read() &&
5203          !r_cas_to_cc_send_brdcast_req.read())
5204      {
5205        r_cas_to_cc_send_multi_req    = false;
5206        r_cas_to_cc_send_brdcast_req  = true;
5207        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
5208        r_cas_to_cc_send_nline        = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5209        r_cas_to_cc_send_index        = 0;
5210        r_cas_to_cc_send_wdata        = 0;
5211
5212        r_cas_fsm = CAS_BC_XRAM_REQ;
5213      }
5214      break;
5215    }
5216    ////////////////////
5217    case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
5218    {
5219      if(!r_cas_to_ixr_cmd_req)
5220      {
5221        r_cas_to_ixr_cmd_req     = true;
5222        r_cas_to_ixr_cmd_write   = true;
5223        r_cas_to_ixr_cmd_nline   = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5224        r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
5225        r_cas_fsm                = CAS_IDLE;
5226        cmd_cas_fifo_get         = true;
5227        r_cas_cpt                = 0;
5228
5229#if DEBUG_MEMC_CAS
5230        if(m_debug_cas_fsm)
5231        {
5232          std::cout << "  <MEMC " << name() << " CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
5233                    << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5234                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5235        }
5236#endif
5237      }
5238      else
5239      {
5240        std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
5241                  << std::endl;
5242      }
5243      break;
5244    }
5245    /////////////////
5246    case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
5247    {
5248      if(!r_cas_to_tgt_rsp_req)
5249      {
5250        cmd_cas_fifo_get     = true;
5251        r_cas_cpt              = 0;
5252        r_cas_to_tgt_rsp_req = true;
5253        r_cas_to_tgt_rsp_data  = 1;
5254        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5255        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5256        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5257        r_cas_fsm              = CAS_IDLE;
5258
5259#if DEBUG_MEMC_CAS
5260        if(m_debug_cas_fsm)
5261        {
5262          std::cout << "  <MEMC " << name() << " CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
5263        }
5264#endif
5265      }
5266      break;
5267    }
5268    ////////////////////
5269    case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
5270    {
5271      if(!r_cas_to_tgt_rsp_req)
5272      {
5273        cmd_cas_fifo_get       = true;
5274        r_cas_cpt              = 0;
5275        r_cas_to_tgt_rsp_req = true;
5276        r_cas_to_tgt_rsp_data  = 0;
5277        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5278        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5279        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5280        r_cas_fsm              = CAS_IDLE;
5281
5282#if DEBUG_MEMC_CAS
5283        if(m_debug_cas_fsm)
5284        {
5285          std::cout << "  <MEMC " << name() << " CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
5286        }
5287#endif
5288      }
5289      break;
5290    }
5291    /////////////////////
5292    case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
5293    {
5294      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5295      {
5296        size_t   index = 0;
5297        bool hit_read = m_trt.hit_read(
5298                          m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],index);
5299        bool hit_write = m_trt.hit_write(
5300                           m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]);
5301        bool wok = !m_trt.full(index);
5302
5303#if DEBUG_MEMC_CAS
5304        if(m_debug_cas_fsm)
5305        {
5306          std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_LOCK> Check TRT state"
5307                    << " / hit_read = "  << hit_read
5308                    << " / hit_write = " << hit_write
5309                    << " / wok = " << wok
5310                    << " / index = " << index << std::endl;
5311        }
5312#endif
5313
5314        if(hit_read || !wok || hit_write)    // missing line already requested or no space in TRT
5315        {
5316          r_cas_fsm = CAS_WAIT;
5317        }
5318        else
5319        {
5320          r_cas_trt_index = index;
5321          r_cas_fsm       = CAS_MISS_TRT_SET;
5322        }
5323      }
5324      break;
5325    }
5326    ////////////////////
5327    case CAS_MISS_TRT_SET: // register the GET transaction in TRT
5328    {
5329      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5330      {
5331        std::vector<be_t> be_vector;
5332        std::vector<data_t> data_vector;
5333        be_vector.clear();
5334        data_vector.clear();
5335        for(size_t i=0; i<m_words; i++)
5336        {
5337          be_vector.push_back(0);
5338          data_vector.push_back(0);
5339        }
5340
5341        m_trt.set(r_cas_trt_index.read(),
5342                              true,   // read request
5343                              m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],
5344                              m_cmd_cas_srcid_fifo.read(),
5345                              m_cmd_cas_trdid_fifo.read(),
5346                              m_cmd_cas_pktid_fifo.read(),
5347                              false,    // write request from processor
5348                              0,
5349                              0,
5350                              be_vector,
5351                              data_vector);
5352        r_cas_fsm = CAS_MISS_XRAM_REQ;
5353
5354#if DEBUG_MEMC_CAS
5355        if(m_debug_cas_fsm)
5356        {
5357          std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
5358                    << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5359                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5360        }
5361#endif
5362      }
5363      break;
5364    }
5365    //////////////////////
5366    case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
5367    {
5368      if(!r_cas_to_ixr_cmd_req)
5369      {
5370        r_cas_to_ixr_cmd_req        = true;
5371        r_cas_to_ixr_cmd_write      = false;
5372        r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
5373        r_cas_to_ixr_cmd_nline      = m_nline[(addr_t) m_cmd_cas_addr_fifo.read()];
5374        r_cas_fsm                   = CAS_WAIT;
5375
5376#if DEBUG_MEMC_CAS
5377        if(m_debug_cas_fsm)
5378        {
5379          std::cout << "  <MEMC " << name() << " CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
5380                    << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5381                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5382        }
5383#endif
5384      }
5385      break;
5386    }
5387  } // end switch r_cas_fsm
5388
5389
5390  //////////////////////////////////////////////////////////////////////////////
5391  //    CC_SEND FSM
5392  //////////////////////////////////////////////////////////////////////////////
5393  // The CC_SEND fsm controls the DSPIN initiator port on the coherence
5394  // network, used to update or invalidate cache lines in L1 caches.
5395  //
5396  // This fsm is used also to acknowledge CLEANUP a command after request from
5397  // the CLEANUP fsm.
5398  //
5399  // It implements a round-robin priority between the four possible client FSMs
5400  // XRAM_RSP, WRITE, CAS and CLEANUP. Each FSM can request the next services:
5401  // - r_xram_rsp_to_cc_send_multi_req : multi-inval
5402  //   r_xram_rsp_to_cc_send_brdcast_req : broadcast-inval
5403  // - r_write_to_cc_send_multi_req : multi-update
5404  //   r_write_to_cc_send_brdcast_req : broadcast-inval
5405  // - r_cas_to_cc_send_multi_req : multi-update
5406  //   r_cas_to_cc_send_brdcast_req : broadcast-inval
5407  // - r_cleanup_to_cc_send_req : cleanup acknowledgement
5408  //
5409  // An inval request is a double DSPIN flit command containing:
5410  // 1. the index of the line to be invalidated.
5411  //
5412  // An update request is a multi-flit DSPIN command containing:
5413  // 1. the index of the cache line to be updated.
5414  // 2. the index of the first modified word in the line.
5415  // 3. the data to update
5416  ///////////////////////////////////////////////////////////////////////////////
5417
5418  switch(r_cc_send_fsm.read())
5419  {
5420    case CC_SEND_WRITE_IDLE:
5421      {
5422        // XRAM_RSP FSM has highest priority
5423        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5424            r_xram_rsp_to_cc_send_multi_req.read())
5425        {
5426          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5427          m_cpt_inval++;
5428          break;
5429        }
5430
5431        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5432        {
5433          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5434          m_cpt_inval++;
5435          break;
5436        }
5437
5438        if(m_cas_to_cc_send_inst_fifo.rok() ||
5439            r_cas_to_cc_send_multi_req.read())
5440        {
5441          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5442          m_cpt_update++;
5443          break;
5444        }
5445
5446        if(r_cas_to_cc_send_brdcast_req.read())
5447        {
5448          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5449          m_cpt_inval++;
5450          break;
5451        }
5452
5453        if (r_cleanup_to_cc_send_req.read())
5454        {
5455          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5456          break;
5457        }
5458
5459        if(m_write_to_cc_send_inst_fifo.rok() ||
5460            r_write_to_cc_send_multi_req.read())
5461        {
5462          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5463          m_cpt_update++;
5464          break;
5465        }
5466
5467        if(r_write_to_cc_send_brdcast_req.read())
5468        {
5469          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5470          m_cpt_inval++;
5471        }
5472        break;
5473      }
5474
5475    case CC_SEND_XRAM_RSP_IDLE:
5476      {
5477        // CAS FSM has highest priority
5478        if(m_cas_to_cc_send_inst_fifo.rok() ||
5479            r_cas_to_cc_send_multi_req.read())
5480        {
5481          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5482          m_cpt_update++;
5483          break;
5484        }
5485
5486        if(r_cas_to_cc_send_brdcast_req.read())
5487        {
5488          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5489          m_cpt_inval++;
5490          break;
5491        }
5492
5493        if(r_cleanup_to_cc_send_req.read())
5494        {
5495          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5496          break;
5497        }
5498
5499        if(m_write_to_cc_send_inst_fifo.rok() ||
5500            r_write_to_cc_send_multi_req.read())
5501        {
5502          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5503          m_cpt_update++;
5504          break;
5505        }
5506
5507        if(r_write_to_cc_send_brdcast_req.read())
5508        {
5509          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5510          m_cpt_inval++;
5511          break;
5512        }
5513
5514        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5515            r_xram_rsp_to_cc_send_multi_req.read())
5516        {
5517          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5518          m_cpt_inval++;
5519          break;
5520        }
5521
5522        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5523        {
5524          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5525          m_cpt_inval++;
5526        }
5527
5528        break;
5529      }
5530
5531    case CC_SEND_CAS_IDLE:
5532      {
5533        // CLEANUP FSM has highest priority
5534        if(r_cleanup_to_cc_send_req.read())
5535        {
5536          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5537          break;
5538        }
5539
5540        if(m_write_to_cc_send_inst_fifo.rok() ||
5541            r_write_to_cc_send_multi_req.read())
5542        {
5543          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5544          m_cpt_update++;
5545          break;
5546        }
5547
5548        if(r_write_to_cc_send_brdcast_req.read())
5549        {
5550          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5551          m_cpt_inval++;
5552          break;
5553        }
5554
5555        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5556            r_xram_rsp_to_cc_send_multi_req.read())
5557        {
5558          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5559          m_cpt_inval++;
5560          break;
5561        }
5562
5563        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5564        {
5565          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5566          m_cpt_inval++;
5567          break;
5568        }
5569
5570        if(m_cas_to_cc_send_inst_fifo.rok() ||
5571            r_cas_to_cc_send_multi_req.read())
5572        {
5573          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5574          m_cpt_update++;
5575          break;
5576        }
5577
5578        if(r_cas_to_cc_send_brdcast_req.read())
5579        {
5580          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5581          m_cpt_inval++;
5582        }
5583        break;
5584      }
5585
5586    case CC_SEND_CLEANUP_IDLE:
5587      {
5588        // WRITE FSM has highest priority
5589        if(m_write_to_cc_send_inst_fifo.rok() ||
5590            r_write_to_cc_send_multi_req.read())
5591        {
5592          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5593          m_cpt_update++;
5594          break;
5595        }
5596
5597        if(r_write_to_cc_send_brdcast_req.read())
5598        {
5599          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5600          m_cpt_inval++;
5601          break;
5602        }
5603
5604        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5605            r_xram_rsp_to_cc_send_multi_req.read())
5606        {
5607          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5608          m_cpt_inval++;
5609          break;
5610        }
5611
5612        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5613        {
5614          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5615          m_cpt_inval++;
5616          break;
5617        }
5618
5619        if(m_cas_to_cc_send_inst_fifo.rok() ||
5620            r_cas_to_cc_send_multi_req.read())
5621        {
5622          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5623          m_cpt_update++;
5624          break;
5625        }
5626
5627        if(r_cas_to_cc_send_brdcast_req.read())
5628        {
5629          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5630          m_cpt_inval++;
5631          break;
5632        }
5633
5634        if(r_cleanup_to_cc_send_req.read())
5635        {
5636          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5637        }
5638
5639        break;
5640      }
5641
5642    case CC_SEND_CLEANUP_ACK:
5643      {
5644        // send only flit for a cleanup acknowledgement (from CLEANUP FSM)
5645        if(not p_dspin_out.read) break;
5646
5647        r_cleanup_to_cc_send_req = false;
5648        r_cc_send_fsm = CC_SEND_CLEANUP_IDLE;
5649
5650#if DEBUG_MEMC_CC_SEND
5651        if(m_debug_cc_send_fsm)
5652        {
5653          std::cout
5654            << "  <MEMC " << name()
5655            << " CC_SEND_CLEANUP_ACK> Cleanup Acknowledgement for srcid "
5656            << r_cleanup_to_cc_send_srcid.read()
5657            << std::endl;
5658        }
5659#endif
5660        break;
5661      }
5662
5663    case CC_SEND_XRAM_RSP_INVAL_HEADER:
5664      {
5665        // send first flit multi-inval (from XRAM_RSP FSM)
5666        if(m_xram_rsp_to_cc_send_inst_fifo.rok())
5667        {
5668          if(not p_dspin_out.read) break;
5669
5670          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_NLINE;
5671          break;
5672        }
5673
5674        if(r_xram_rsp_to_cc_send_multi_req.read())
5675        {
5676          r_xram_rsp_to_cc_send_multi_req = false;
5677        }
5678
5679        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5680        break;
5681      }
5682
5683    case CC_SEND_XRAM_RSP_INVAL_NLINE:
5684      {
5685        // send second flit multi-inval (from XRAM_RSP FSM)
5686        if(not p_dspin_out.read) break;
5687
5688        m_cpt_inval_mult++;
5689
5690        xram_rsp_to_cc_send_fifo_get = true;
5691        r_cc_send_fsm                = CC_SEND_XRAM_RSP_INVAL_HEADER;
5692
5693#if DEBUG_MEMC_CC_SEND
5694        if(m_debug_cc_send_fsm)
5695        {
5696          std::cout
5697            << "  <MEMC " << name()
5698            << " CC_SEND_XRAM_RSP_INVAL_NLINE> Broadcast-Inval for line "
5699            << r_xram_rsp_to_cc_send_nline.read()
5700            << std::endl;
5701        }
5702#endif
5703        break;
5704      }
5705
5706    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
5707      {
5708        // send first flit broadcast-inval (from XRAM_RSP FSM)
5709        if(not p_dspin_out.read) break;
5710
5711        r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_NLINE;
5712        break;
5713      }
5714
5715    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
5716      {
5717        // send second flit broadcast-inval (from XRAM_RSP FSM)
5718        if(not p_dspin_out.read) break;
5719
5720        m_cpt_inval_brdcast++;
5721
5722        r_xram_rsp_to_cc_send_brdcast_req = false;
5723        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5724
5725#if DEBUG_MEMC_CC_SEND
5726        if(m_debug_cc_send_fsm)
5727        {
5728          std::cout
5729            << "  <MEMC " << name()
5730            << " CC_SEND_XRAM_RSP_BRDCAST_NLINE> Broadcast-Inval for line "
5731            << r_xram_rsp_to_cc_send_nline.read()
5732            << std::endl;
5733        }
5734#endif
5735        break;
5736      }
5737
5738    case CC_SEND_WRITE_BRDCAST_HEADER:
5739      {
5740        // send first flit broadcast-inval (from WRITE FSM)
5741        if(not p_dspin_out.read) break;
5742
5743        r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_NLINE;
5744        break;
5745      }
5746
5747    case CC_SEND_WRITE_BRDCAST_NLINE:
5748      {
5749        // send second flit broadcast-inval (from WRITE FSM)
5750        if(not p_dspin_out.read) break;
5751
5752        m_cpt_inval_brdcast++;
5753
5754        r_write_to_cc_send_brdcast_req = false;
5755        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5756
5757#if DEBUG_MEMC_CC_SEND
5758        if(m_debug_cc_send_fsm)
5759        {
5760          std::cout
5761            << "  <MEMC " << name()
5762            << " CC_SEND_WRITE_BRDCAST_NLINE> Broadcast-Inval for line "
5763            << r_write_to_cc_send_nline.read()
5764            << std::endl;
5765        }
5766#endif
5767        break;
5768      }
5769
5770    case CC_SEND_WRITE_UPDT_HEADER:
5771      {
5772        // send first flit for a multi-update (from WRITE FSM)
5773        if(m_write_to_cc_send_inst_fifo.rok())
5774        {
5775          if(not p_dspin_out.read) break;
5776
5777          r_cc_send_fsm = CC_SEND_WRITE_UPDT_NLINE;
5778          break;
5779        }
5780
5781        if(r_write_to_cc_send_multi_req.read())
5782        {
5783          r_write_to_cc_send_multi_req = false;
5784        }
5785
5786        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5787        break;
5788      }
5789
5790    case CC_SEND_WRITE_UPDT_NLINE:
5791      {
5792        // send second flit for a multi-update (from WRITE FSM)
5793        if(not p_dspin_out.read) break;
5794
5795        m_cpt_update_mult++;
5796
5797        r_cc_send_cpt = 0;
5798        r_cc_send_fsm = CC_SEND_WRITE_UPDT_DATA;
5799
5800#if DEBUG_MEMC_CC_SEND
5801        if(m_debug_cc_send_fsm)
5802        {
5803          std::cout
5804            << "  <MEMC " << name()
5805            << " CC_SEND_WRITE_UPDT_NLINE> Multicast-Update for line "
5806            << r_write_to_cc_send_nline.read()
5807            << std::endl;
5808        }
5809#endif
5810        break;
5811      }
5812
5813    case CC_SEND_WRITE_UPDT_DATA:
5814      {
5815        // send N data flits for a multi-update (from WRITE FSM)
5816        if(not p_dspin_out.read) break;
5817
5818        if(r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1))
5819        {
5820          write_to_cc_send_fifo_get = true;
5821          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5822          break;
5823        }
5824
5825        r_cc_send_cpt = r_cc_send_cpt.read() + 1;
5826        break;
5827      }
5828
5829    case CC_SEND_CAS_BRDCAST_HEADER:
5830      {
5831        // send first flit for a broadcast-inval (from CAS FSM)
5832        if(not p_dspin_out.read) break;
5833
5834        r_cc_send_fsm = CC_SEND_CAS_BRDCAST_NLINE;
5835        break;
5836      }
5837
5838    case CC_SEND_CAS_BRDCAST_NLINE:
5839      {
5840        // send second flit broadcast-inval (from CAS FSM)
5841        if(not p_dspin_out.read) break;
5842
5843        m_cpt_inval_brdcast++;
5844
5845        r_cas_to_cc_send_brdcast_req = false;
5846        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5847
5848#if DEBUG_MEMC_CC_SEND
5849        if(m_debug_cc_send_fsm)
5850        {
5851          std::cout
5852            << "  <MEMC " << name()
5853            << " CC_SEND_CAS_BRDCAST_NLINE> Broadcast-Inval for line "
5854            << r_cas_to_cc_send_nline.read()
5855            << std::endl;
5856        }
5857#endif
5858        break;
5859      }
5860
5861    case CC_SEND_CAS_UPDT_HEADER:
5862      {
5863        // send first flit for a multi-update (from CAS FSM)
5864        if(m_cas_to_cc_send_inst_fifo.rok())
5865        {
5866          if(not p_dspin_out.read) break;
5867
5868          r_cc_send_fsm = CC_SEND_CAS_UPDT_NLINE;
5869          break;
5870        }
5871
5872        // no more packets to send for the multi-update
5873        if(r_cas_to_cc_send_multi_req.read())
5874        {
5875          r_cas_to_cc_send_multi_req = false;
5876        }
5877
5878        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5879        break;
5880      }
5881
5882    case CC_SEND_CAS_UPDT_NLINE:
5883      {
5884        // send second flit for a multi-update (from CAS FSM)
5885        if(not p_dspin_out.read) break;
5886
5887        m_cpt_update_mult++;
5888
5889        r_cc_send_cpt = 0;
5890        r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA;
5891
5892#if DEBUG_MEMC_CC_SEND
5893        if(m_debug_cc_send_fsm)
5894        {
5895          std::cout
5896            << "  <MEMC " << name()
5897            << " CC_SEND_CAS_UPDT_NLINE> Multicast-Update for line "
5898            << r_cas_to_cc_send_nline.read()
5899            << std::endl;
5900        }
5901#endif
5902        break;
5903      }
5904
5905    case CC_SEND_CAS_UPDT_DATA:
5906      {
5907        // send first data for a multi-update (from CAS FSM)
5908        if(not p_dspin_out.read) break;
5909
5910        if(r_cas_to_cc_send_is_long.read())
5911        {
5912          r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA_HIGH;
5913          break;
5914        }
5915
5916        cas_to_cc_send_fifo_get = true;
5917        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5918        break;
5919      }
5920
5921    case CC_SEND_CAS_UPDT_DATA_HIGH:
5922      {
5923        // send second data for a multi-update (from CAS FSM)
5924        if(not p_dspin_out.read) break;
5925
5926        cas_to_cc_send_fifo_get = true;
5927        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5928        break;
5929      }
5930  }
5931  // end switch r_cc_send_fsm
5932
5933  //////////////////////////////////////////////////////////////////////////////
5934  //    CC_RECEIVE FSM
5935  //////////////////////////////////////////////////////////////////////////////
5936  // The CC_RECEIVE fsm controls the DSPIN target port on the coherence
5937  // network.
5938  ///////////////////////////////////////////////////////////////////////////////
5939
5940  switch(r_cc_receive_fsm.read())
5941  {
5942    /////////////////////
5943    case CC_RECEIVE_IDLE:
5944      {
5945        if(not p_dspin_in.write) break;
5946
5947        uint8_t type =
5948          DspinDhccpParam::dspin_get(
5949              p_dspin_in.data.read(),
5950              DspinDhccpParam::FROM_L1_TYPE);
5951
5952        if((type == DspinDhccpParam::TYPE_CLEANUP_DATA) ||
5953           (type == DspinDhccpParam::TYPE_CLEANUP_INST) )
5954        { 
5955          r_cc_receive_fsm = CC_RECEIVE_CLEANUP;
5956          break;
5957        }
5958       
5959        if(type == DspinDhccpParam::TYPE_MULTI_ACK)
5960        {
5961          r_cc_receive_fsm = CC_RECEIVE_MULTI_ACK;
5962          break;
5963        }
5964
5965        assert(
5966            false && 
5967            "VCI_MEM_CACHE ERROR: Illegal type in coherence request");
5968       
5969        break;
5970      }
5971    ////////////////////////
5972    case CC_RECEIVE_CLEANUP:  // write first CLEANUP flit in CC_RECEIVE to CLEANUP fifo
5973      {
5974        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
5975
5976        assert( not p_dspin_in.eop.read() and
5977        "VCI_MEM_CACHE ERROR in CC_RECEIVE : CLEANUP command must have two flits");
5978
5979        cc_receive_to_cleanup_fifo_put = true;
5980        r_cc_receive_fsm               = CC_RECEIVE_CLEANUP_EOP;
5981
5982        break;
5983      }
5984    ////////////////////////////
5985    case CC_RECEIVE_CLEANUP_EOP:  // write second CLEANUP flit in CC_RECEIVE to CLEANUP fifo
5986      {
5987        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
5988
5989        assert( p_dspin_in.eop.read() and
5990        "VCI_MEM_CACHE ERROR in CC_RECEIVE : CLEANUP command must have two flits");
5991
5992        cc_receive_to_cleanup_fifo_put = true;
5993        r_cc_receive_fsm               = CC_RECEIVE_IDLE;
5994
5995        break;
5996      }
5997
5998    //////////////////////////
5999    case CC_RECEIVE_MULTI_ACK:
6000      {
6001        // wait for a WOK in the CC_RECEIVE to MULTI_ACK fifo
6002        if(not p_dspin_in.write or not m_cc_receive_to_multi_ack_fifo.wok()) break;
6003
6004        assert( p_dspin_in.eop.read() and
6005        "VCI_MEM_CACHE ERROR in CC_RECEIVE : MULTI_ACK command must have one flit");
6006
6007        cc_receive_to_multi_ack_fifo_put  = true;
6008        r_cc_receive_fsm                  = CC_RECEIVE_IDLE;
6009        break;
6010      }
6011  }
6012  /////////////////////////////////////////////////////////////////////
6013  //    TGT_RSP FSM
6014  /////////////////////////////////////////////////////////////////////
6015  // The TGT_RSP fsm sends the responses on the VCI target port
6016  // with a round robin priority between six requests :
6017  // - r_read_to_tgt_rsp_req
6018  // - r_write_to_tgt_rsp_req
6019  // - r_cas_to_tgt_rsp_req
6020  // - r_cleanup_to_tgt_rsp_req
6021  // - r_xram_rsp_to_tgt_rsp_req
6022  // - r_multi_ack_to_tgt_rsp_req
6023  // The  ordering is :  read > write > cas > xram > init > cleanup
6024  /////////////////////////////////////////////////////////////////////
6025
6026  switch(r_tgt_rsp_fsm.read())
6027  {
6028    case TGT_RSP_READ_IDLE:
6029    { 
6030      // write requests have the highest priority
6031      if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6032      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6033      else if(r_xram_rsp_to_tgt_rsp_req)
6034      {
6035        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6036        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6037      }
6038      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6039      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6040      else if(r_read_to_tgt_rsp_req)
6041      {
6042        r_tgt_rsp_fsm = TGT_RSP_READ;
6043        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6044      }
6045      break;
6046    }
6047    ////////////////////////
6048    case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
6049    {
6050      if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS;
6051      else if(r_xram_rsp_to_tgt_rsp_req)
6052      {
6053        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6054        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6055      }
6056      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6057      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6058      else if(r_read_to_tgt_rsp_req)
6059      {
6060        r_tgt_rsp_fsm = TGT_RSP_READ;
6061        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6062      }
6063
6064      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6065      break;
6066    }
6067    ///////////////////////
6068    case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
6069    {
6070      if(r_xram_rsp_to_tgt_rsp_req)
6071      {
6072        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6073        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6074      }
6075      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6076      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6077      else if(r_read_to_tgt_rsp_req)
6078      {
6079        r_tgt_rsp_fsm = TGT_RSP_READ;
6080        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6081      }
6082      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6083      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6084      break;
6085    }
6086    ///////////////////////
6087    case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
6088    {
6089
6090      if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6091      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6092      else if(r_read_to_tgt_rsp_req)
6093      {
6094        r_tgt_rsp_fsm = TGT_RSP_READ;
6095        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6096      }
6097      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6098      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6099      else if(r_xram_rsp_to_tgt_rsp_req)
6100      {
6101        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6102        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6103      }
6104      break;
6105    }
6106    ///////////////////////
6107    case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
6108    {
6109      if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6110      else if(r_read_to_tgt_rsp_req)
6111      {
6112        r_tgt_rsp_fsm = TGT_RSP_READ;
6113        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6114      }
6115      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6116      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6117      else if(r_xram_rsp_to_tgt_rsp_req)
6118      {
6119        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6120        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6121      }
6122      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT;
6123      break;
6124    }
6125    ///////////////////////
6126    case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
6127    {
6128      if(r_read_to_tgt_rsp_req)
6129      {
6130        r_tgt_rsp_fsm = TGT_RSP_READ;
6131        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6132      }
6133      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6134      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6135      else if(r_xram_rsp_to_tgt_rsp_req)
6136      {
6137        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6138        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6139      }
6140      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6141      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6142      break;
6143    }
6144    //////////////////
6145    case TGT_RSP_READ:    // send the response to a read
6146    {
6147      if ( p_vci_tgt.rspack )
6148      {
6149
6150#if DEBUG_MEMC_TGT_RSP
6151if( m_debug_tgt_rsp_fsm )
6152{
6153  std::cout
6154    << "  <MEMC " << name() << " TGT_RSP_READ> Read response"
6155    << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
6156    << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
6157    << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
6158    << " / rdata = " << std::hex << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6159    << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6160}
6161#endif
6162 
6163        uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() + r_read_to_tgt_rsp_length.read() - 1;
6164        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
6165        bool     is_ll         = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
6166
6167        if ( (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll))
6168        {
6169          // Last word in case of READ or second flit in case if LL
6170          r_tgt_rsp_key_sent    = false;
6171          r_read_to_tgt_rsp_req = false;
6172          r_tgt_rsp_fsm         = TGT_RSP_READ_IDLE;
6173        }
6174        else
6175        {
6176          if (is_ll)
6177          {
6178            r_tgt_rsp_key_sent = true;                // Send second flit of ll
6179          }
6180          else
6181          {
6182            r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1; // Send next word of read
6183          }
6184        }
6185      }
6186      break;
6187    }
6188    //////////////////
6189    case TGT_RSP_WRITE:   // send the write acknowledge
6190    {
6191      if(p_vci_tgt.rspack)
6192      {
6193
6194#if DEBUG_MEMC_TGT_RSP
6195        if(m_debug_tgt_rsp_fsm)
6196        {
6197          std::cout << "  <MEMC " << name() << " TGT_RSP_WRITE> Write response"
6198                    << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
6199                    << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
6200                    << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
6201        }
6202#endif
6203        r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
6204        r_write_to_tgt_rsp_req = false;
6205      }
6206      break;
6207    }
6208    ///////////////////
6209    case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
6210    {
6211      if(p_vci_tgt.rspack)
6212      {
6213
6214#if DEBUG_MEMC_TGT_RSP
6215        if(m_debug_tgt_rsp_fsm)
6216        {
6217          std::cout << "  <MEMC " << name() << " TGT_RSP_CLEANUP> Cleanup response"
6218                    << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
6219                    << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
6220                    << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
6221        }
6222#endif
6223        r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
6224        r_cleanup_to_tgt_rsp_req = false;
6225      }
6226      break;
6227    }
6228    //////////////////
6229    case TGT_RSP_CAS:    // send one atomic word response
6230    {
6231      if(p_vci_tgt.rspack)
6232      {
6233
6234#if DEBUG_MEMC_TGT_RSP
6235        if(m_debug_tgt_rsp_fsm)
6236        {
6237          std::cout << "  <MEMC " << name() << " TGT_RSP_CAS> CAS response"
6238                    << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
6239                    << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
6240                    << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
6241        }
6242#endif
6243        r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
6244        r_cas_to_tgt_rsp_req = false;
6245      }
6246      break;
6247    }
6248
6249    ///////////////////////
6250    case TGT_RSP_XRAM:    // send the response after XRAM access
6251    {
6252      if ( p_vci_tgt.rspack )
6253      {
6254
6255#if DEBUG_MEMC_TGT_RSP
6256if( m_debug_tgt_rsp_fsm )
6257{
6258  std::cout
6259    << "  <MEMC " << name() << " TGT_RSP_XRAM> Response following XRAM access"
6260    << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
6261    << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
6262    << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
6263    << " / rdata = " << std::hex << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6264    << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6265}
6266#endif
6267        uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() + r_xram_rsp_to_tgt_rsp_length.read() - 1;
6268        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
6269        bool     is_ll         = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
6270        bool     is_error      = r_xram_rsp_to_tgt_rsp_rerror.read();
6271
6272        if (((is_last_word or is_error) and not is_ll) or
6273             (r_tgt_rsp_key_sent.read() and     is_ll))
6274        {
6275          // Last word sent in case of READ or second flit sent in case if LL
6276          r_tgt_rsp_key_sent        = false;
6277          r_xram_rsp_to_tgt_rsp_req = false;
6278          r_tgt_rsp_fsm             = TGT_RSP_XRAM_IDLE;
6279        }
6280        else
6281        {
6282          if (is_ll)
6283          {
6284            r_tgt_rsp_key_sent = true;                     // Send second flit of ll
6285          }                                                                           
6286          else
6287          {
6288            r_tgt_rsp_cpt      = r_tgt_rsp_cpt.read() + 1; // Send next word of read
6289          }
6290        }
6291      }
6292      break;
6293    }
6294    //////////////////
6295    case TGT_RSP_INIT:    // send the write response after coherence transaction
6296    {
6297      if(p_vci_tgt.rspack)
6298      {
6299
6300#if DEBUG_MEMC_TGT_RSP
6301        if(m_debug_tgt_rsp_fsm)
6302        {
6303          std::cout << "  <MEMC " << name() << " TGT_RSP_INIT> Write response after coherence transaction"
6304                    << " / rsrcid = " << std::dec << r_multi_ack_to_tgt_rsp_srcid.read()
6305                    << " / rtrdid = " << r_multi_ack_to_tgt_rsp_trdid.read()
6306                    << " / rpktid = " << r_multi_ack_to_tgt_rsp_pktid.read() << std::endl;
6307        }
6308#endif
6309        r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
6310        r_multi_ack_to_tgt_rsp_req = false;
6311      }
6312      break;
6313    }
6314  } // end switch tgt_rsp_fsm
6315
6316  ////////////////////////////////////////////////////////////////////////////////////
6317  //    ALLOC_UPT FSM
6318  ////////////////////////////////////////////////////////////////////////////////////
6319  // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
6320  // with a round robin priority between three FSMs : MULTI_ACK > WRITE > XRAM_RSP > CLEANUP
6321  // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
6322  // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
6323  // - The MULTI_ACK FSM complete those trasactions and erase the UPT entry.
6324  // - The CLEANUP  FSM decrement an entry in UPT.
6325  // The resource is always allocated.
6326  /////////////////////////////////////////////////////////////////////////////////////
6327
6328  switch(r_alloc_upt_fsm.read())
6329  {
6330
6331      ////////////////////////
6332    case ALLOC_UPT_MULTI_ACK:
6333      if((r_multi_ack_fsm.read() != MULTI_ACK_UPT_LOCK) &&
6334          (r_multi_ack_fsm.read() != MULTI_ACK_UPT_CLEAR))
6335      {
6336        if((