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

Last change on this file since 422 was 422, checked in by alain, 11 years ago

cosmetic

File size: 249.8 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(this->name(), 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    std::cout << "  - Building VciMemCache : " << name << std::endl;
417
418    assert(IS_POW_OF_2(nsets));
419    assert(IS_POW_OF_2(nwords));
420    assert(IS_POW_OF_2(nways));
421    assert(nsets);
422    assert(nwords);
423    assert(nways);
424
425    // check Transaction table size
426    assert((uint32_log2(trt_lines) <= vci_param_ext::T) and
427    "MEMC ERROR : Need more bits for VCI TRDID field");
428
429    // check internal and external data width
430    assert( (vci_param_int::B == 4 ) and
431    "MEMC ERROR : VCI internal data width must be 32 bits");
432         
433    assert( (vci_param_ext::B == 8) and
434    "MEMC ERROR : VCI external data width must be 64 bits");
435
436    // Check coherence between internal & external addresses
437    assert( (vci_param_int::N == vci_param_ext::N) and
438    "MEMC ERROR : VCI internal & external addresses must have the same width");
439         
440    // Get the segments associated to the MemCache
441    std::list<soclib::common::Segment>::iterator seg;
442    size_t i = 0;
443
444    for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++)
445    {
446        std::cout << "    => segment " << seg->name()
447                  << " / base = " << std::hex << seg->baseAddress()
448                  << " / size = " << seg->size() << std::endl; 
449        m_nseg++;
450    }
451
452    m_seg = new soclib::common::Segment*[m_nseg];
453
454    for(seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++)
455    {
456        m_seg[i] = & (*seg);
457        i++;
458    }
459
460    // Allocation for IXR_RSP FSM
461    r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
462
463    // Allocation for XRAM_RSP FSM
464    r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
465    r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
466    r_xram_rsp_to_ixr_cmd_data = new sc_signal<data_t>[nwords];
467
468    // Allocation for READ FSM
469    r_read_data                = new sc_signal<data_t>[nwords];
470    r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
471
472    // Allocation for WRITE FSM
473    r_write_data               = new sc_signal<data_t>[nwords];
474    r_write_be                 = new sc_signal<be_t>[nwords];
475    r_write_to_cc_send_data    = new sc_signal<data_t>[nwords];
476    r_write_to_cc_send_be      = new sc_signal<be_t>[nwords];
477    r_write_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
478
479    // Allocation for CAS FSM
480    r_cas_to_ixr_cmd_data      = new sc_signal<data_t>[nwords];
481    r_cas_data                 = new sc_signal<data_t>[nwords];
482    r_cas_rdata                = new sc_signal<data_t>[2];
483
484
485    SC_METHOD(transition);
486    dont_initialize();
487    sensitive << p_clk.pos();
488
489    SC_METHOD(genMoore);
490    dont_initialize();
491    sensitive << p_clk.neg();
492} // end constructor
493
494///////////////////////////////////////////////////////////////////////
495tmpl(void) ::start_monitor(addr_t addr, addr_t length)
496///////////////////////////////////////////////////////////////////////
497{
498  m_monitor_ok        = true;
499  m_monitor_base      = addr;
500  m_monitor_length    = length;
501}
502
503///////////////////////////////////////////////////////////////////////
504tmpl(void) ::stop_monitor()
505///////////////////////////////////////////////////////////////////////
506{
507  m_monitor_ok        = false;
508}
509
510////////////////////////////////////////////////
511tmpl(void) ::check_monitor( const char  *buf, 
512                            addr_t      addr, 
513                            data_t      data,
514                            bool        read )
515////////////////////////////////////////////////
516{
517  if((addr >= m_monitor_base) and
518      (addr < m_monitor_base + m_monitor_length))
519  {
520    if ( read ) std::cout << " Monitor MEMC Read  ";
521    else        std::cout << " Monitor MEMC Write "; 
522    std::cout << buf
523              << " / Address = " << std::hex << addr
524              << " / Data = " << data
525              << " at cycle " << std::dec << m_cpt_cycles << std::endl;
526  }
527}
528
529/////////////////////////////////////////////////////
530tmpl(void) ::copies_monitor(addr_t addr)
531/////////////////////////////////////////////////////
532{
533  DirectoryEntry entry = m_cache_directory.read_neutral(addr);
534
535  if((entry.count != m_debug_previous_count) or
536      (entry.valid != m_debug_previous_hit))
537  {
538    std::cout << "Monitor MEMC " << name()
539              << " at cycle " << std::dec << m_cpt_cycles
540              << " for address " << std::hex << addr
541              << " / HIT = " << entry.valid
542              << " / COUNT = " << std::dec << entry.count << std::endl;
543  }
544  m_debug_previous_count = entry.count;
545  m_debug_previous_hit = entry.valid;
546}
547
548//////////////////////////////////////////////////
549tmpl(void) ::print_trace()
550//////////////////////////////////////////////////
551{
552  std::cout << "MEMC " << name() << std::endl;
553  std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]
554            << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]
555            << " | " << read_fsm_str[r_read_fsm.read()]
556            << " | " << write_fsm_str[r_write_fsm.read()]
557            << " | " << cas_fsm_str[r_cas_fsm.read()]
558            << " | " << cleanup_fsm_str[r_cleanup_fsm.read()] << std::endl;
559  std::cout << "  "  << cc_send_fsm_str[r_cc_send_fsm.read()]
560            << " | " << cc_receive_fsm_str[r_cc_receive_fsm.read()]
561            << " | " << multi_ack_fsm_str[r_multi_ack_fsm.read()]
562            << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]
563            << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]
564            << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
565  std::cout << "  "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]
566            << " | " << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]
567            << " | " << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]
568            << " | " << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
569}
570
571/////////////////////////////////////////
572tmpl(void) ::print_stats()
573/////////////////////////////////////////
574{
575  std::cout << "----------------------------------" << std::dec << std::endl;
576  std::cout
577      << "MEM_CACHE " << name() << " / Time = " << m_cpt_cycles << std::endl
578      << "- READ RATE            = " << (double) m_cpt_read/m_cpt_cycles << std::endl
579      << "- READ TOTAL           = " << m_cpt_read << std::endl
580      << "- READ MISS RATE       = " << (double) m_cpt_read_miss/m_cpt_read << std::endl
581      << "- WRITE RATE           = " << (double) m_cpt_write/m_cpt_cycles << std::endl
582      << "- WRITE TOTAL          = " << m_cpt_write << std::endl
583      << "- WRITE MISS RATE      = " << (double) m_cpt_write_miss/m_cpt_write << std::endl
584      << "- WRITE BURST LENGTH   = " << (double) m_cpt_write_cells/m_cpt_write << std::endl
585      << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
586      << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
587      << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
588      << "- UPDATE RATE          = " << (double) m_cpt_update/m_cpt_cycles << std::endl
589      << "- UPDATE ARITY         = " << (double) m_cpt_update_mult/m_cpt_update << std::endl
590      << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast) /m_cpt_cycles << std::endl
591      << "- INVAL MULTICAST ARITY= " << (double) m_cpt_inval_mult/ (m_cpt_inval-m_cpt_inval_brdcast) << std::endl
592      << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl
593      << "- SAVE DIRTY RATE      = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl
594      << "- CLEANUP RATE         = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl
595      << "- LL RATE              = " << (double) m_cpt_ll/m_cpt_cycles << std::endl
596      << "- SC RATE              = " << (double) m_cpt_sc/m_cpt_cycles << std::endl
597      << "- CAS RATE             = " << (double) m_cpt_cas/m_cpt_cycles << std::endl;
598}
599
600/////////////////////////////////
601tmpl(/**/) ::~VciMemCache()
602/////////////////////////////////
603{
604  delete [] r_ixr_rsp_to_xram_rsp_rok;
605
606  delete [] r_xram_rsp_victim_data;
607  delete [] r_xram_rsp_to_tgt_rsp_data;
608  delete [] r_xram_rsp_to_ixr_cmd_data;
609
610  delete [] r_read_data;
611  delete [] r_read_to_tgt_rsp_data;
612
613  delete [] r_write_data;
614  delete [] r_write_be;
615  delete [] r_write_to_cc_send_data;
616}
617
618//////////////////////////////////
619tmpl(void) ::transition()
620//////////////////////////////////
621{
622  using soclib::common::uint32_log2;
623
624  // RESET
625  if(! p_resetn.read())
626  {
627
628    // Initializing FSMs
629    r_tgt_cmd_fsm    = TGT_CMD_IDLE;
630    r_tgt_rsp_fsm    = TGT_RSP_READ_IDLE;
631    r_cc_send_fsm    = CC_SEND_XRAM_RSP_IDLE;
632    r_cc_receive_fsm = CC_RECEIVE_IDLE;
633    r_multi_ack_fsm  = MULTI_ACK_IDLE;
634    r_read_fsm       = READ_IDLE;
635    r_write_fsm      = WRITE_IDLE;
636    r_cas_fsm        = CAS_IDLE;
637    r_cleanup_fsm    = CLEANUP_IDLE;
638    r_alloc_dir_fsm  = ALLOC_DIR_RESET;
639    r_alloc_heap_fsm = ALLOC_HEAP_RESET;
640    r_alloc_trt_fsm  = ALLOC_TRT_READ;
641    r_alloc_upt_fsm  = ALLOC_UPT_WRITE;
642    r_ixr_rsp_fsm    = IXR_RSP_IDLE;
643    r_xram_rsp_fsm   = XRAM_RSP_IDLE;
644    r_ixr_cmd_fsm    = IXR_CMD_READ_IDLE;
645
646    m_debug_global         = false;
647    m_debug_tgt_cmd_fsm    = false;
648    m_debug_tgt_rsp_fsm    = false;
649    m_debug_cc_send_fsm    = false;
650    m_debug_cc_receive_fsm = false;
651    m_debug_multi_ack_fsm  = false;
652    m_debug_read_fsm       = false;
653    m_debug_write_fsm      = false;
654    m_debug_cas_fsm        = false;
655    m_debug_cleanup_fsm    = false;
656    m_debug_ixr_cmd_fsm    = false;
657    m_debug_ixr_rsp_fsm    = false;
658    m_debug_xram_rsp_fsm   = false;
659    m_debug_previous_hit   = false;
660    m_debug_previous_count = 0;
661
662    //  Initializing Tables
663    m_trt.init();
664    m_upt.init();
665    m_llsc_table.init();
666
667    // initializing FIFOs and communication Buffers
668
669    m_cmd_read_addr_fifo.init();
670    m_cmd_read_length_fifo.init();
671    m_cmd_read_srcid_fifo.init();
672    m_cmd_read_trdid_fifo.init();
673    m_cmd_read_pktid_fifo.init();
674
675    m_cmd_write_addr_fifo.init();
676    m_cmd_write_eop_fifo.init();
677    m_cmd_write_srcid_fifo.init();
678    m_cmd_write_trdid_fifo.init();
679    m_cmd_write_pktid_fifo.init();
680    m_cmd_write_data_fifo.init();
681
682    m_cmd_cas_addr_fifo.init()  ;
683    m_cmd_cas_srcid_fifo.init() ;
684    m_cmd_cas_trdid_fifo.init() ;
685    m_cmd_cas_pktid_fifo.init() ;
686    m_cmd_cas_wdata_fifo.init() ;
687    m_cmd_cas_eop_fifo.init()   ;
688
689    r_read_to_tgt_rsp_req = false;
690    r_read_to_ixr_cmd_req = false;
691
692    r_write_to_tgt_rsp_req          = false;
693    r_write_to_ixr_cmd_req          = false;
694    r_write_to_cc_send_multi_req   = false;
695    r_write_to_cc_send_brdcast_req = false;
696    r_write_to_multi_ack_req        = false;
697
698    m_write_to_cc_send_inst_fifo.init();
699    m_write_to_cc_send_srcid_fifo.init();
700#if L1_MULTI_CACHE
701    m_write_to_cc_send_cache_id_fifo.init();
702#endif
703
704    r_cleanup_to_tgt_rsp_req      = false;
705
706    m_cc_receive_to_cleanup_fifo.init();
707
708    r_multi_ack_to_tgt_rsp_req     = false;
709
710    m_cc_receive_to_multi_ack_fifo.init();
711
712    r_cas_to_tgt_rsp_req          = false;
713    r_cas_cpt                     = 0    ;
714    r_cas_lfsr                    = -1   ;
715    r_cas_to_ixr_cmd_req          = false;
716    r_cas_to_cc_send_multi_req   = false;
717    r_cas_to_cc_send_brdcast_req = false;
718
719    m_cas_to_cc_send_inst_fifo.init();
720    m_cas_to_cc_send_srcid_fifo.init();
721#if L1_MULTI_CACHE
722    m_cas_to_cc_send_cache_id_fifo.init();
723#endif
724
725    for(size_t i=0; i<m_trt_lines ; i++)
726    {
727      r_ixr_rsp_to_xram_rsp_rok[i] = false;
728    }
729
730    r_xram_rsp_to_tgt_rsp_req          = false;
731    r_xram_rsp_to_cc_send_multi_req   = false;
732    r_xram_rsp_to_cc_send_brdcast_req = false;
733    r_xram_rsp_to_ixr_cmd_req          = false;
734    r_xram_rsp_trt_index               = 0;
735
736    m_xram_rsp_to_cc_send_inst_fifo.init();
737    m_xram_rsp_to_cc_send_srcid_fifo.init();
738#if L1_MULTI_CACHE
739    m_xram_rsp_to_cc_send_cache_id_fifo.init();
740#endif
741
742    r_ixr_cmd_cpt          = 0;
743    r_alloc_dir_reset_cpt  = 0;
744    r_alloc_heap_reset_cpt = 0;
745
746    r_tgt_rsp_key_sent  = false;
747
748    // Activity counters
749    m_cpt_cycles        = 0;
750    m_cpt_read          = 0;
751    m_cpt_read_miss     = 0;
752    m_cpt_write         = 0;
753    m_cpt_write_miss    = 0;
754    m_cpt_write_cells   = 0;
755    m_cpt_write_dirty   = 0;
756    m_cpt_update        = 0;
757    m_cpt_update_mult   = 0;
758    m_cpt_inval_brdcast = 0;
759    m_cpt_inval         = 0;
760    m_cpt_inval_mult    = 0;
761    m_cpt_cleanup       = 0;
762    m_cpt_ll            = 0;
763    m_cpt_sc            = 0;
764    m_cpt_cas           = 0;
765    m_cpt_trt_full      = 0;
766    m_cpt_trt_rb        = 0;
767
768    return;
769  }
770
771  bool    cmd_read_fifo_put = false;
772  bool    cmd_read_fifo_get = false;
773
774  bool    cmd_write_fifo_put = false;
775  bool    cmd_write_fifo_get = false;
776
777  bool    cmd_cas_fifo_put = false;
778  bool    cmd_cas_fifo_get = false;
779
780  bool    cc_receive_to_cleanup_fifo_get = false;
781  bool    cc_receive_to_cleanup_fifo_put = false;
782   
783  bool    cc_receive_to_multi_ack_fifo_get = false;
784  bool    cc_receive_to_multi_ack_fifo_put = false;
785
786  bool    write_to_cc_send_fifo_put   = false;
787  bool    write_to_cc_send_fifo_get   = false;
788  bool    write_to_cc_send_fifo_inst  = false;
789  size_t  write_to_cc_send_fifo_srcid = 0;
790
791#if L1_MULTI_CACHE
792  size_t  write_to_cc_send_fifo_cache_id = 0;
793#endif
794
795  bool    xram_rsp_to_cc_send_fifo_put   = false;
796  bool    xram_rsp_to_cc_send_fifo_get   = false;
797  bool    xram_rsp_to_cc_send_fifo_inst  = false;
798  size_t  xram_rsp_to_cc_send_fifo_srcid = 0;
799
800#if L1_MULTI_CACHE
801  size_t  xram_rsp_to_cc_send_fifo_cache_id = 0;
802#endif
803
804  bool    cas_to_cc_send_fifo_put   = false;
805  bool    cas_to_cc_send_fifo_get   = false;
806  bool    cas_to_cc_send_fifo_inst  = false;
807  size_t  cas_to_cc_send_fifo_srcid = 0;
808
809#if L1_MULTI_CACHE
810  size_t  cas_to_cc_send_fifo_cache_id = 0;
811#endif
812
813  m_debug_global         = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
814  m_debug_tgt_cmd_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
815  m_debug_tgt_rsp_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
816  m_debug_cc_send_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
817  m_debug_cc_receive_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
818  m_debug_multi_ack_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
819  m_debug_read_fsm       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
820  m_debug_write_fsm      = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
821  m_debug_cas_fsm        = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
822  m_debug_cleanup_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
823  m_debug_ixr_cmd_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
824  m_debug_ixr_rsp_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
825  m_debug_xram_rsp_fsm   = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
826
827#if DEBUG_MEMC_GLOBAL
828  if(m_debug_global)
829  {
830    std::cout
831        << "---------------------------------------------"           << std::dec << std::endl
832        << "MEM_CACHE "            << name() 
833        << " ; Time = "            << m_cpt_cycles                                << std::endl
834        << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
835        << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
836        << " - CC_SEND FSM  = "    << cc_send_fsm_str[r_cc_send_fsm.read()]       << std::endl
837        << " - CC_RECEIVE FSM  = " << cc_receive_fsm_str[r_cc_receive_fsm.read()] << std::endl
838        << " - MULTI_ACK FSM  = "  << multi_ack_fsm_str[r_multi_ack_fsm.read()]   << std::endl
839        << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
840        << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
841        << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
842        << " - CLEANUP FSM    = "  << cleanup_fsm_str[r_cleanup_fsm.read()]       << std::endl
843        << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
844        << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
845        << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
846        << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
847        << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
848        << " - ALLOC_UPT FSM  = "  << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]   << std::endl
849        << " - ALLOC_HEAP FSM = "  << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
850  }
851#endif
852
853  ////////////////////////////////////////////////////////////////////////////////////
854  //    TGT_CMD FSM
855  ////////////////////////////////////////////////////////////////////////////////////
856  // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
857  //
858  // There are 5 types of accepted commands :
859  // - READ   : A READ request has a length of 1 VCI cell. It can be a single word
860  //            or an entire cache line, depending on the PLEN value.
861  // - WRITE  : A WRITE request has a maximum length of 16 cells, and can only
862  //            concern words in a same line.
863  // - CAS    : A CAS request has a length of 2 cells or 4 cells.
864  // - LL     : An LL request has a length of 1 cell.
865  // - SC     : An SC request has a length of 2 cells. First cell contains the
866  //            acces key, second cell the data to write in case of success.
867  ////////////////////////////////////////////////////////////////////////////////////
868
869  switch(r_tgt_cmd_fsm.read())
870  {
871      //////////////////
872    case TGT_CMD_IDLE:
873      if(p_vci_tgt.cmdval)
874      {
875
876#if DEBUG_MEMC_TGT_CMD
877        if(m_debug_tgt_cmd_fsm)
878        {
879          std::cout
880              << "  <MEMC " << name()
881              << " TGT_CMD_IDLE> Receive command from srcid "
882              << std::dec << p_vci_tgt.srcid.read()
883              << " / for address "
884              << std::hex << p_vci_tgt.address.read()
885              << std::endl;
886        }
887#endif
888        // checking segmentation violation
889        addr_t  address = p_vci_tgt.address.read();
890        uint32_t    plen    = p_vci_tgt.plen.read();
891        bool found = false;
892        for(size_t seg_id = 0 ; seg_id < m_nseg ; seg_id++)
893        {
894          if(m_seg[seg_id]->contains(address) &&
895              m_seg[seg_id]->contains(address + plen - vci_param_int::B))
896          {
897            found = true;
898          }
899        }
900        if(not found)
901        {
902          std::cout << "VCI_MEM_CACHE ERROR " << name() << std::endl;
903          std::cout
904              << "Out of segment VCI address in TGT_CMD_IDLE state (address = "
905              << std::hex << address << ", srcid = " << p_vci_tgt.srcid.read()
906              << std::dec << ", cycle = " << m_cpt_cycles << ")" << std::endl;
907          exit(0);
908        }
909
910        if(p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
911        {
912          // check that the pktid is either :
913          // TYPE_READ_DATA_UNC
914          // TYPE_READ_DATA_MISS
915          // TYPE_READ_INS_UNC
916          // TYPE_READ_INS_MISS
917          // ==> bit2 must be zero with the TSAR encoding
918          // ==> mask = 0b0100 = 0x4
919          assert(((p_vci_tgt.pktid.read() & 0x4) == 0x0) &&
920                 "The type specified in the pktid field is incompatible with the READ CMD");
921          r_tgt_cmd_fsm = TGT_CMD_READ;
922        }
923        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
924        {
925          // check that the pktid is TYPE_WRITE
926          // ==> TYPE_WRITE = X100 with the TSAR encoding
927          // ==> mask = 0b0111 = 0x7
928          assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) &&
929                 "The type specified in the pktid field is incompatible with the WRITE CMD");
930          r_tgt_cmd_fsm = TGT_CMD_WRITE;
931        }
932        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
933        {
934          // check that the pktid is TYPE_LL
935          // ==> TYPE_LL = X110 with the TSAR encoding
936          // ==> mask = 0b0111 = 0x7
937          assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) &&
938                 "The type specified in the pktid field is incompatible with the LL CMD");
939          r_tgt_cmd_fsm = TGT_CMD_READ;
940        }
941        else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
942        {
943          // check that the pktid is either :
944          // TYPE_CAS
945          // TYPE_SC
946          // ==> TYPE_CAS = X101 with the TSAR encoding
947          // ==> TYPE_SC  = X111 with the TSAR encoding
948          // ==> mask = 0b0101 = 0x5
949          assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) &&
950                 "The type specified in the pktid field is incompatible with the NOP CMD");
951
952          if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS)
953            r_tgt_cmd_fsm = TGT_CMD_CAS;
954          else // TYPE_SC
955            r_tgt_cmd_fsm = TGT_CMD_WRITE;
956        }
957        else
958        {
959          std::cout << "VCI_MEM_CACHE ERROR " << name()
960                    << " TGT_CMD_IDLE state" << std::endl;
961          std::cout << " illegal VCI command type" << std::endl;
962          exit(0);
963        }
964      }
965      break;
966
967      //////////////////
968    case TGT_CMD_READ:
969      // This test checks that the read does not cross a cache line limit.
970      // It must not be taken into account when dealing with an LL CMD.
971      if(((m_x[(addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) && 
972          (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ))
973      {
974        std::cout
975            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
976            << std::endl;
977        std::cout
978            << " illegal address/plen combination for VCI read command" << std::endl;
979        exit(0);
980      }
981      if(!p_vci_tgt.eop.read())
982      {
983        std::cout
984            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
985            << std::endl;
986        std::cout
987            << " read or ll command packets must contain one single flit"
988            << std::endl;
989        exit(0);
990      }
991      if((p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) && (p_vci_tgt.plen.read() != 8))
992      {
993        std::cout
994            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
995            << std::endl;
996        std::cout
997            << " ll command packets must have a plen of 8"
998            << std::endl;
999        exit(0);
1000      }
1001
1002      if(p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok())
1003      {
1004
1005#if DEBUG_MEMC_TGT_CMD
1006if(m_debug_tgt_cmd_fsm)
1007std::cout << "  <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:"
1008          << " address = " << std::hex << p_vci_tgt.address.read()
1009          << " / srcid = " << p_vci_tgt.srcid.read()
1010          << " / trdid = " << p_vci_tgt.trdid.read()
1011          << " / pktid = " << p_vci_tgt.pktid.read()
1012          << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1013#endif
1014        cmd_read_fifo_put = true;
1015        if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
1016          m_cpt_ll++;
1017        else
1018          m_cpt_read++;
1019        r_tgt_cmd_fsm = TGT_CMD_IDLE;
1020      }
1021      break;
1022
1023      ///////////////////
1024    case TGT_CMD_WRITE:
1025      if(p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok())
1026      {
1027
1028#if DEBUG_MEMC_TGT_CMD
1029if(m_debug_tgt_cmd_fsm)
1030std::cout << "  <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:"
1031          << " address = " << std::hex << p_vci_tgt.address.read()
1032          << " / srcid = " << p_vci_tgt.srcid.read()
1033          << " / trdid = " << p_vci_tgt.trdid.read()
1034          << " / pktid = " << p_vci_tgt.pktid.read()
1035          << " / wdata = " << p_vci_tgt.wdata.read()
1036          << " / be = " << p_vci_tgt.be.read()
1037          << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1038#endif
1039        cmd_write_fifo_put = true;
1040        if(p_vci_tgt.eop)  r_tgt_cmd_fsm = TGT_CMD_IDLE;
1041      }
1042      break;
1043
1044      ////////////////////
1045    case TGT_CMD_CAS:
1046      if((p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16))
1047      {
1048        std::cout
1049            << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
1050            << std::endl
1051            << "illegal format for CAS command " << std::endl;
1052
1053        exit(0);
1054      }
1055
1056      if(p_vci_tgt.cmdval && m_cmd_cas_addr_fifo.wok())
1057      {
1058
1059#if DEBUG_MEMC_TGT_CMD
1060if(m_debug_tgt_cmd_fsm)
1061std::cout << "  <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
1062          << " address = " << std::hex << p_vci_tgt.address.read()
1063          << " srcid = " << p_vci_tgt.srcid.read()
1064          << " trdid = " << p_vci_tgt.trdid.read()
1065          << " pktid = " << p_vci_tgt.pktid.read()
1066          << " wdata = " << p_vci_tgt.wdata.read()
1067          << " be = " << p_vci_tgt.be.read()
1068          << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
1069#endif
1070        cmd_cas_fifo_put = true;
1071        if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE;
1072      }
1073      break;
1074  } // end switch tgt_cmd_fsm
1075
1076  /////////////////////////////////////////////////////////////////////////
1077  //    MULTI_ACK FSM
1078  /////////////////////////////////////////////////////////////////////////
1079  // This FSM controls the response to the multicast update or multicast
1080  // inval coherence requests sent by the memory cache to the L1 caches and
1081  // update the UPT.
1082  //
1083  // It can be update or inval requests initiated by the WRITE or CAS FSM,
1084  // or inval requests initiated by the XRAM_RSP FSM.
1085  // It can also be a direct request from the WRITE FSM.
1086  //
1087  // The FSM decrements the proper entry in UPT.
1088  // It sends a request to the TGT_RSP FSM to complete the pending
1089  // write transaction (acknowledge response to the writer processor),
1090  // and clear the UPT entry when all responses have been received.
1091  //
1092  // All those response packets are one flit packet.
1093  // The index in the Table is defined in the UPDT_TABLE INDEX field, and
1094  // the transaction type is defined in the UPT entry.
1095  ////////////////////////////////////////////////////////////////////////
1096
1097  switch(r_multi_ack_fsm.read())
1098  {
1099    ///////////////////
1100    case MULTI_ACK_IDLE:
1101      {
1102        bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok();
1103
1104        // No CC_RECEIVE FSM request and no WRITE FSM request
1105        if( not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read()) break;
1106
1107        // handling WRITE FSM request to decrement update table response counter
1108        // if no CC_RECEIVE FSM request
1109        if(not multi_ack_fifo_rok)
1110        {
1111          r_write_to_multi_ack_req = false;
1112          r_multi_ack_upt_index    = r_write_to_multi_ack_upt_index.read();
1113          r_multi_ack_fsm          = MULTI_ACK_UPT_LOCK;
1114
1115          break;
1116        }
1117
1118        // Handling CC_RECEIVE FSM request
1119        uint64_t flit = m_cc_receive_to_multi_ack_fifo.read();
1120
1121        uint8_t updt_index = 
1122          DspinDhccpParam::dspin_get(flit, DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
1123
1124        assert( (updt_index < m_upt.size()) and
1125        "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : index too large for UPT");
1126
1127        cc_receive_to_multi_ack_fifo_get = true;
1128        r_multi_ack_upt_index           = updt_index;
1129        r_multi_ack_fsm                 = MULTI_ACK_UPT_LOCK;
1130
1131#if DEBUG_MEMC_MULTI_ACK
1132        if(m_debug_multi_ack_fsm)
1133        {
1134          std::cout
1135            <<  "  <MEMC " << name()
1136            << " MULTI_ACK_IDLE> Response for UPT entry "
1137            << updt_index
1138            << std::endl;
1139        }
1140#endif
1141        break;
1142      }
1143
1144    ////////////////////////
1145    case MULTI_ACK_UPT_LOCK:
1146      {
1147        // get lock to the UPDATE table
1148        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
1149
1150        // decrement the number of expected responses
1151        size_t count = 0;
1152        bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
1153
1154        if(not valid)
1155        {
1156          std::cout
1157            << "VCI_MEM_CACHE ERROR " << name()
1158            << " MULTI_ACK_UPT_LOCK state" << std::endl
1159            << "unsuccessful access to decrement the UPT"
1160            << std::endl;
1161
1162          exit(0);
1163        }
1164
1165        if(count == 0)
1166        {
1167          r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR;
1168        }
1169        else
1170        {
1171          r_multi_ack_fsm = MULTI_ACK_IDLE;
1172        }
1173
1174#if DEBUG_MEMC_MULTI_ACK
1175        if(m_debug_multi_ack_fsm)
1176        {
1177          std::cout
1178            << "  <MEMC " << name()
1179            << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:"
1180            << " entry = "       << r_multi_ack_upt_index.read()
1181            << " / rsp_count = " << std::dec << count
1182            << std::endl;
1183        }
1184#endif
1185        break;
1186      }
1187
1188    /////////////////////////
1189    case MULTI_ACK_UPT_CLEAR:
1190      {
1191        if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)
1192        {
1193          std::cout
1194            << "VCI_MEM_CACHE ERROR " << name()
1195            << " MULTI_ACK_UPT_CLEAR state"
1196            << " bad UPT allocation"
1197            << std::endl;
1198
1199          exit(0);
1200        }
1201
1202        r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read());
1203        r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read());
1204        r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read());
1205        r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read());
1206        bool need_rsp     = m_upt.need_rsp(r_multi_ack_upt_index.read());
1207
1208        // clear the UPT entry
1209        m_upt.clear(r_multi_ack_upt_index.read());
1210
1211        if(need_rsp)
1212        {
1213          r_multi_ack_fsm = MULTI_ACK_WRITE_RSP;
1214        }
1215        else
1216        {
1217          r_multi_ack_fsm = MULTI_ACK_IDLE;
1218        }
1219
1220#if DEBUG_MEMC_MULTI_ACK
1221        if(m_debug_multi_ack_fsm)
1222        {
1223          std::cout
1224            <<  "  <MEMC " << name()
1225            << " MULTI_ACK_UPT_CLEAR> Clear UPT entry "
1226            << r_multi_ack_upt_index.read()
1227            << std::endl;
1228        }
1229#endif
1230        break;
1231      }
1232
1233    /////////////////////////
1234    case MULTI_ACK_WRITE_RSP:
1235      {
1236        // Post a request to TGT_RSP FSM
1237        // Wait if pending request to the TGT_RSP FSM
1238        if(r_multi_ack_to_tgt_rsp_req.read()) break;
1239
1240        r_multi_ack_to_tgt_rsp_req   = true;
1241        r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read();
1242        r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read();
1243        r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read();
1244        r_multi_ack_fsm              = MULTI_ACK_IDLE;
1245
1246#if DEBUG_MEMC_MULTI_ACK
1247        if(m_debug_multi_ack_fsm)
1248        {
1249          std::cout
1250            << "  <MEMC " << name()
1251            << " MULTI_ACK_WRITE_RSP> Request TGT_RSP FSM to send a response to srcid "
1252            << r_multi_ack_srcid.read()
1253            << std::endl;
1254        }
1255#endif
1256        break;
1257      }
1258  } // end switch r_multi_ack_fsm
1259
1260  ////////////////////////////////////////////////////////////////////////////////////
1261  //    READ FSM
1262  ////////////////////////////////////////////////////////////////////////////////////
1263  // The READ FSM controls the VCI read  and ll requests.
1264  // It takes the lock protecting the cache directory to check the cache line status:
1265  // - In case of HIT
1266  //   The fsm copies the data (one line, or one single word)
1267  //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
1268  //   The requesting initiator is registered in the cache directory.
1269  //   If the number of copy is larger than 1, the new copy is registered
1270  //   in the HEAP.
1271  //   If the number of copy is larger than the threshold, the HEAP is cleared,
1272  //   and the corresponding line switches to the counter mode.
1273  // - In case of MISS
1274  //   The READ fsm takes the lock protecting the transaction tab.
1275  //   If a read transaction to the XRAM for this line already exists,
1276  //   or if the transaction tab is full, the fsm is stalled.
1277  //   If a TRT entry is free, the READ request is registered in TRT,
1278  //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
1279  //   The READ FSM returns in the IDLE state as the read transaction will be
1280  //   completed when the missing line will be received.
1281  ////////////////////////////////////////////////////////////////////////////////////
1282
1283  switch(r_read_fsm.read())
1284  {
1285    ///////////////
1286    case READ_IDLE:
1287      // waiting a read request
1288    {
1289      if(m_cmd_read_addr_fifo.rok())
1290      {
1291
1292#if DEBUG_MEMC_READ
1293if(m_debug_read_fsm)
1294std::cout << "  <MEMC " << name() << " READ_IDLE> Read request"
1295          << " : address = " << std::hex << m_cmd_read_addr_fifo.read()
1296          << " / srcid = " << m_cmd_read_srcid_fifo.read()
1297          << " / trdid = " << m_cmd_read_trdid_fifo.read()
1298          << " / pktid = " << 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 = " << std::hex << entry.owner.srcid
1465          << " / owner_ins = " << std::dec << 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 = " << std::hex << heap_entry.owner.srcid
1629          << " owner_ins = " << std::dec << 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::hex << 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
2499if(m_debug_write_fsm)
2500{
2501    std::cout << "  <MEMC " << name() << " WRITE_RSP> Post a request to TGT_RSP FSM"
2502              << " : rsrcid = " << std::hex << r_write_srcid.read() << std::endl;
2503    if(m_cmd_write_addr_fifo.rok())
2504    {
2505        std::cout << "                    New Write request: "
2506                  << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
2507                  << " / address = " << 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
2523if(m_debug_write_fsm)
2524std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
2525#endif
2526        size_t  hit_index = 0;
2527        size_t  wok_index = 0;
2528        addr_t  addr  = (addr_t) r_write_address.read();
2529        bool    hit_read  = m_trt.hit_read(m_nline[addr], hit_index);
2530        bool    hit_write = m_trt.hit_write(m_nline[addr]);
2531        bool    wok       = !m_trt.full(wok_index);
2532
2533        if(hit_read)      // register the modified data in TRT
2534        {
2535          r_write_trt_index = hit_index;
2536          r_write_fsm       = WRITE_MISS_TRT_DATA;
2537          m_cpt_write_miss++;
2538        }
2539        else if(wok && !hit_write)      // set a new entry in TRT
2540        {
2541          r_write_trt_index = wok_index;
2542          r_write_fsm       = WRITE_MISS_TRT_SET;
2543          m_cpt_write_miss++;
2544        }
2545        else    // wait an empty entry in TRT
2546        {
2547          r_write_fsm       = WRITE_WAIT;
2548          m_cpt_trt_full++;
2549        }
2550      }
2551      break;
2552    }
2553
2554    ////////////////
2555    case WRITE_WAIT:  // release the locks protecting the shared ressources
2556    {
2557
2558#if DEBUG_MEMC_WRITE
2559if(m_debug_write_fsm)
2560std::cout << "  <MEMC " << name() << " WRITE_WAIT> Releases the locks before retry" << std::endl;
2561#endif
2562      r_write_fsm = WRITE_DIR_REQ;
2563      break;
2564    }
2565
2566    ////////////////////////
2567    case WRITE_MISS_TRT_SET:  // register a new transaction in TRT (Write Buffer)
2568    {
2569      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2570      {
2571        std::vector<be_t>   be_vector;
2572        std::vector<data_t> data_vector;
2573        be_vector.clear();
2574        data_vector.clear();
2575        for(size_t i=0; i<m_words; i++)
2576        {
2577          be_vector.push_back(r_write_be[i]);
2578          data_vector.push_back(r_write_data[i]);
2579        }
2580        m_trt.set(r_write_trt_index.read(),
2581                              true,     // read request to XRAM
2582                              m_nline[(addr_t)(r_write_address.read())],
2583                              r_write_srcid.read(),
2584                              r_write_trdid.read(),
2585                              r_write_pktid.read(),
2586                              false,      // not a processor read
2587                              0,        // not a single word
2588                              0,            // word index
2589                              be_vector,
2590                              data_vector);
2591        r_write_fsm = WRITE_MISS_XRAM_REQ;
2592
2593#if DEBUG_MEMC_WRITE
2594if(m_debug_write_fsm)
2595std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
2596#endif
2597      }
2598      break;
2599    }
2600
2601    /////////////////////////
2602    case WRITE_MISS_TRT_DATA: // update an entry in TRT (used as a Write Buffer)
2603    {
2604      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2605      {
2606        std::vector<be_t> be_vector;
2607        std::vector<data_t> data_vector;
2608        be_vector.clear();
2609        data_vector.clear();
2610        for(size_t i=0; i<m_words; i++)
2611        {
2612          be_vector.push_back(r_write_be[i]);
2613          data_vector.push_back(r_write_data[i]);
2614        }
2615        m_trt.write_data_mask(r_write_trt_index.read(),
2616                                          be_vector,
2617                                          data_vector);
2618        r_write_fsm = WRITE_RSP;
2619
2620#if DEBUG_MEMC_WRITE
2621if(m_debug_write_fsm)
2622std::cout << "  <MEMC " << name() << " WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2623#endif
2624      }
2625      break;
2626    }
2627
2628    /////////////////////////
2629    case WRITE_MISS_XRAM_REQ: // send a GET request to IXR_CMD FSM
2630    {
2631      if(!r_write_to_ixr_cmd_req)
2632      {
2633        r_write_to_ixr_cmd_req   = true;
2634        r_write_to_ixr_cmd_write = false;
2635        r_write_to_ixr_cmd_nline = m_nline[(addr_t)(r_write_address.read())];
2636        r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
2637        r_write_fsm              = WRITE_RSP;
2638
2639#if DEBUG_MEMC_WRITE
2640if(m_debug_write_fsm)
2641std::cout << "  <MEMC " << name() << " WRITE_MISS_XRAM_REQ> Post a GET request to the IXR_CMD FSM" << std::endl;
2642#endif
2643      }
2644      break;
2645    }
2646
2647    ///////////////////////
2648    case WRITE_BC_TRT_LOCK:     // Check TRT not full
2649    {
2650      if(r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)
2651      {
2652        size_t wok_index = 0;
2653        bool wok = !m_trt.full(wok_index);
2654        if(wok)       // set a new entry in TRT
2655        {
2656          r_write_trt_index = wok_index;
2657          r_write_fsm       = WRITE_BC_UPT_LOCK;
2658        }
2659        else  // wait an empty entry in TRT
2660        {
2661          r_write_fsm       = WRITE_WAIT;
2662        }
2663
2664#if DEBUG_MEMC_WRITE
2665if(m_debug_write_fsm)
2666std::cout << "  <MEMC " << name() << " WRITE_BC_TRT_LOCK> Check TRT"
2667          << " : wok = " << wok << " / index = " << wok_index << std::endl;
2668#endif
2669      }
2670      break;
2671    }
2672
2673    //////////////////////
2674    case WRITE_BC_UPT_LOCK:      // register BC transaction in UPT
2675    {
2676      if(r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE)
2677      {
2678        bool        wok       = false;
2679        size_t      index     = 0;
2680        size_t      srcid     = r_write_srcid.read();
2681        size_t      trdid     = r_write_trdid.read();
2682        size_t      pktid     = r_write_pktid.read();
2683        addr_t      nline     = m_nline[(addr_t)(r_write_address.read())];
2684        size_t      nb_copies = r_write_count.read();
2685
2686        wok =m_upt.set(false,  // it's an inval transaction
2687                              true,     // it's a broadcast
2688                              true,     // it needs a response
2689                              srcid,
2690                              trdid,
2691                              pktid,
2692                              nline,
2693                              nb_copies,
2694                              index);
2695
2696#if DEBUG_MEMC_WRITE
2697if( m_debug_write_fsm and wok )
2698std::cout << "  <MEMC " << name() << " WRITE_BC_UPT_LOCK> Register broadcast inval in UPT"
2699          << " / nb_copies = " << r_write_count.read() << std::endl;
2700#endif
2701        r_write_upt_index = index;
2702
2703        if(wok) r_write_fsm = WRITE_BC_DIR_INVAL;
2704        else       r_write_fsm = WRITE_WAIT;
2705      }
2706      break;
2707    }
2708
2709    ////////////////////////
2710    case WRITE_BC_DIR_INVAL:
2711    {
2712      // Register a put transaction to XRAM in TRT
2713      // and invalidate the line in directory
2714      if((r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE) ||
2715          (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE) ||
2716          (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE))
2717      {
2718        std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_BC_DIR_INVAL state" << std::endl;
2719        std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
2720        exit(0);
2721      }
2722
2723      // register a write request to XRAM in TRT
2724      m_trt.set(r_write_trt_index.read(),
2725                            false,    // write request to XRAM
2726                            m_nline[(addr_t)(r_write_address.read())],
2727                            0,
2728                            0,
2729                            0,
2730                            false,    // not a processor read
2731                            0,        // not a single word
2732                            0,            // word index
2733                            std::vector<be_t> (m_words,0),
2734                            std::vector<data_t> (m_words,0));
2735
2736      // invalidate directory entry
2737      DirectoryEntry entry;
2738      entry.valid         = false;
2739      entry.dirty         = false;
2740      entry.tag         = 0;
2741      entry.is_cnt        = false;
2742      entry.lock          = false;
2743      entry.owner.srcid   = 0;
2744#if L1_MULTI_CACHE
2745      entry.owner.cache_id= 0;
2746#endif
2747      entry.owner.inst    = false;
2748      entry.ptr           = 0;
2749      entry.count         = 0;
2750      size_t set          = m_y[(addr_t)(r_write_address.read())];
2751      size_t way          = r_write_way.read();
2752
2753      m_cache_directory.write(set, way, entry);
2754
2755#if DEBUG_MEMC_WRITE
2756if(m_debug_write_fsm)
2757std::cout << "  <MEMC " << name() << " WRITE_BC_DIR_INVAL> Invalidate the directory entry: @ = "
2758          << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
2759#endif
2760      r_write_fsm = WRITE_BC_CC_SEND;
2761      break;
2762    }
2763
2764    //////////////////////
2765    case WRITE_BC_CC_SEND:    // Post a coherence broadcast request to CC_SEND FSM
2766    {
2767      if(!r_write_to_cc_send_multi_req.read() && !r_write_to_cc_send_brdcast_req.read())
2768      {
2769        r_write_to_cc_send_multi_req   = false;
2770        r_write_to_cc_send_brdcast_req = true;
2771        r_write_to_cc_send_trdid       = r_write_upt_index.read();
2772        r_write_to_cc_send_nline       = m_nline[(addr_t)(r_write_address.read())];
2773        r_write_to_cc_send_index       = 0;
2774        r_write_to_cc_send_count       = 0;
2775
2776        for(size_t i=0; i<m_words ; i++)
2777        {
2778          r_write_to_cc_send_be[i]=0;
2779          r_write_to_cc_send_data[i] = 0;
2780        }
2781        r_write_fsm = WRITE_BC_XRAM_REQ;
2782
2783#if DEBUG_MEMC_WRITE
2784if(m_debug_write_fsm)
2785{
2786    std::cout << "  <MEMC " << name() 
2787              << " WRITE_BC_CC_SEND> Post a broadcast request to CC_SEND FSM" << std::endl;
2788}
2789#endif
2790      }
2791      break;
2792    }
2793
2794    ///////////////////////
2795    case WRITE_BC_XRAM_REQ:   // Post a put request to IXR_CMD FSM
2796    {
2797      if(!r_write_to_ixr_cmd_req)
2798      {
2799        r_write_to_ixr_cmd_req     = true;
2800        r_write_to_ixr_cmd_write   = true;
2801        r_write_to_ixr_cmd_nline   = m_nline[(addr_t)(r_write_address.read())];
2802        r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
2803
2804        for(size_t i=0; i<m_words; i++) r_write_to_ixr_cmd_data[i] = r_write_data[i];
2805
2806        r_write_fsm = WRITE_IDLE;
2807
2808#if DEBUG_MEMC_WRITE
2809if(m_debug_write_fsm)
2810{
2811     std::cout << "  <MEMC " << name() 
2812               << " WRITE_BC_XRAM_REQ> Post a put request to IXR_CMD FSM" << std::endl;
2813}
2814#endif
2815      }
2816      break;
2817    }
2818  } // end switch r_write_fsm
2819
2820  ///////////////////////////////////////////////////////////////////////
2821  //    IXR_CMD FSM
2822  ///////////////////////////////////////////////////////////////////////
2823  // The IXR_CMD fsm controls the command packets to the XRAM :
2824  // It handles requests from the READ, WRITE, CAS, XRAM_RSP FSMs
2825  // with a round-robin priority.
2826  //
2827  // - It sends a single flit VCI read request to the XRAM in case of MISS
2828  // posted by the READ, WRITE or CAS FSMs : the TRDID field contains
2829  // the Transaction Tab index.
2830  // The VCI response is a multi-flit packet : the N cells contain
2831  // the N data words.
2832  //
2833  // - It sends a multi-flit VCI write when the XRAM_RSP FSM, WRITE FSM
2834  // or CAS FSM request to save a dirty line to the XRAM.
2835  // The VCI response is a single flit packet.
2836  ////////////////////////////////////////////////////////////////////////
2837
2838  switch(r_ixr_cmd_fsm.read())
2839  {
2840    ////////////////////////
2841    case IXR_CMD_READ_IDLE:
2842    {
2843      if     (r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2844      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2845      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2846      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2847      break;
2848    }
2849    ////////////////////////
2850    case IXR_CMD_WRITE_IDLE:
2851    {
2852      if     (r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2853      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2854      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2855      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2856      break;
2857    }
2858    ////////////////////////
2859    case IXR_CMD_CAS_IDLE:
2860    {
2861      if     (r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2862      else if(r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2863      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2864      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2865      break;
2866    }
2867    ////////////////////////
2868    case IXR_CMD_XRAM_IDLE:
2869    {
2870      if     (r_read_to_ixr_cmd_req)     r_ixr_cmd_fsm = IXR_CMD_READ;
2871      else if(r_write_to_ixr_cmd_req)    r_ixr_cmd_fsm = IXR_CMD_WRITE;
2872      else if(r_cas_to_ixr_cmd_req)      r_ixr_cmd_fsm = IXR_CMD_CAS;
2873      else if(r_xram_rsp_to_ixr_cmd_req) r_ixr_cmd_fsm = IXR_CMD_XRAM;
2874      break;
2875    }
2876    //////////////////       // send a get from READ FSM
2877    case IXR_CMD_READ:
2878    {
2879      if(p_vci_ixr.cmdack)
2880      {
2881        r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;
2882        r_read_to_ixr_cmd_req = false;
2883
2884#if DEBUG_MEMC_IXR_CMD
2885if(m_debug_ixr_cmd_fsm)
2886std::cout << "  <MEMC " << name() << " IXR_CMD_READ>"
2887          << " Send a get request to xram / address = " << std::hex
2888          << (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2889#endif
2890      }
2891      break;
2892    }
2893    ///////////////////
2894    case IXR_CMD_WRITE:     // send a put or get from WRITE FSM
2895    {
2896      if(p_vci_ixr.cmdack)
2897      {
2898        if(r_write_to_ixr_cmd_write.read())   // PUT
2899        {
2900          if(r_ixr_cmd_cpt.read() == (m_words - 2))
2901          {
2902            r_ixr_cmd_cpt = 0;
2903            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2904            r_write_to_ixr_cmd_req = false;
2905          }
2906          else
2907          {
2908            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
2909          }
2910
2911#if DEBUG_MEMC_IXR_CMD
2912if(m_debug_ixr_cmd_fsm)
2913std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE>"
2914          << " Send a put request to xram / address = " << std::hex
2915          << (addr_t)((r_write_to_ixr_cmd_nline.read() * m_words +
2916                      r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
2917#endif
2918        }
2919        else                                  // GET
2920        {
2921          r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2922          r_write_to_ixr_cmd_req = false;
2923
2924#if DEBUG_MEMC_IXR_CMD
2925if(m_debug_ixr_cmd_fsm)
2926std::cout << "  <MEMC " << name() << " IXR_CMD_WRITE>"
2927          << " Send a get request to xram / address = " << std::hex
2928          << (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2929#endif
2930        }
2931      }
2932      break;
2933    }
2934    /////////////////
2935    case IXR_CMD_CAS:      // send a put or get command from CAS FSM
2936    {
2937      if(p_vci_ixr.cmdack)
2938      {
2939        if(r_cas_to_ixr_cmd_write.read()) // PUT
2940        {
2941          if(r_ixr_cmd_cpt.read() == (m_words - 2))
2942          {
2943            r_ixr_cmd_cpt = 0;
2944            r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2945            r_cas_to_ixr_cmd_req = false;
2946          }
2947          else
2948          {
2949            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
2950          }
2951
2952#if DEBUG_MEMC_IXR_CMD
2953if(m_debug_ixr_cmd_fsm)
2954std::cout << "  <MEMC " << name() << " IXR_CMD_CAS>"
2955          << " Send a put request to xram / address = " << std::hex
2956          << (addr_t)( (r_cas_to_ixr_cmd_nline.read() * m_words +
2957                      r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
2958#endif
2959        }
2960        else                            // GET
2961        {
2962          r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2963          r_cas_to_ixr_cmd_req = false;
2964
2965#if DEBUG_MEMC_IXR_CMD
2966if(m_debug_ixr_cmd_fsm)
2967std::cout << "  <MEMC " << name() << " IXR_CMD_CAS>"
2968          << " Send a get request to xram / address = " << std::hex
2969          << (addr_t)(r_cas_to_ixr_cmd_nline.read()*m_words*4) << std::endl;
2970#endif
2971        }
2972      }
2973      break;
2974    }
2975    //////////////////
2976    case IXR_CMD_XRAM:     // send a put from XRAM_RSP FSM
2977    {
2978      if(p_vci_ixr.cmdack)
2979      {
2980        if(r_ixr_cmd_cpt.read() == (m_words - 2))
2981        {
2982          r_ixr_cmd_cpt = 0;
2983          r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
2984          r_xram_rsp_to_ixr_cmd_req = false;
2985        }
2986        else
2987        {
2988          r_ixr_cmd_cpt = r_ixr_cmd_cpt + 2;
2989        }
2990
2991#if DEBUG_MEMC_IXR_CMD
2992if(m_debug_ixr_cmd_fsm)
2993std::cout << "  <MEMC " << name() << " IXR_CMD_XRAM>"
2994          << " Send a put request to xram / address = " << std::hex
2995          << (addr_t)( (r_xram_rsp_to_ixr_cmd_nline.read() * m_words +
2996                       r_ixr_cmd_cpt.read()) * 4 ) << std::endl;
2997#endif
2998      }
2999      break;
3000    }
3001
3002  } // end switch r_ixr_cmd_fsm
3003
3004  ////////////////////////////////////////////////////////////////////////////
3005  //                IXR_RSP FSM
3006  ////////////////////////////////////////////////////////////////////////////
3007  // The IXR_RSP FSM receives the response packets from the XRAM,
3008  // for both put transaction, and get transaction.
3009  //
3010  // - A response to a put request is a single-cell VCI packet.
3011  // The Transaction Tab index is contained in the RTRDID field.
3012  // The FSM takes the lock protecting the TRT, and the corresponding
3013  // entry is erased.
3014  //
3015  // - A response to a get request is a multi-cell VCI packet.
3016  // The Transaction Tab index is contained in the RTRDID field.
3017  // The N cells contain the N words of the cache line in the RDATA field.
3018  // The FSM takes the lock protecting the TRT to store the line in the TRT
3019  // (taking into account the write requests already stored in the TRT).
3020  // When the line is completely written, the corresponding rok signal is set.
3021  ///////////////////////////////////////////////////////////////////////////////
3022
3023  switch(r_ixr_rsp_fsm.read())
3024  {
3025    //////////////////
3026    case IXR_RSP_IDLE:  // test transaction type: PUT/GET
3027    {
3028      if(p_vci_ixr.rspval.read())
3029      {
3030        r_ixr_rsp_cpt   = 0;
3031        r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
3032        if(p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read() &0x1))   // PUT transaction
3033        {
3034          r_ixr_rsp_fsm = IXR_RSP_ACK;
3035
3036#if DEBUG_MEMC_IXR_RSP
3037if(m_debug_ixr_rsp_fsm)
3038{
3039    std::cout << "  <MEMC " << name() 
3040              << " IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
3041}
3042#endif
3043        }
3044        else                                                         // GET transaction
3045        {
3046          r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
3047
3048#if DEBUG_MEMC_IXR_RSP
3049if(m_debug_ixr_rsp_fsm)
3050{
3051    std::cout << "  <MEMC " << name() 
3052              << " IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
3053}
3054#endif
3055        }
3056      }
3057      break;
3058    }
3059    /////////////////
3060    case IXR_RSP_ACK:        // Aknowledge the VCI response for a PUT
3061    {
3062      if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
3063
3064#if DEBUG_MEMC_IXR_RSP
3065if(m_debug_ixr_rsp_fsm)
3066{
3067    std::cout << "  <MEMC " << name() << " IXR_RSP_ACK>" << std::endl;
3068}
3069#endif
3070      break;
3071    }
3072    ////////////////////////
3073    case IXR_RSP_TRT_ERASE:   // erase the entry in the TRT
3074    {
3075      if(r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP)
3076      {
3077        m_trt.erase(r_ixr_rsp_trt_index.read());
3078        r_ixr_rsp_fsm = IXR_RSP_IDLE;
3079
3080#if DEBUG_MEMC_IXR_RSP
3081if(m_debug_ixr_rsp_fsm)
3082{
3083          std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_ERASE> Erase TRT entry "
3084                    << r_ixr_rsp_trt_index.read() << std::endl;
3085        }
3086#endif
3087      }
3088      break;
3089    }
3090    //////////////////////
3091    case IXR_RSP_TRT_READ:    // write a 64 bits data in the TRT
3092    {
3093      if((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval)
3094      {
3095        size_t      index    = r_ixr_rsp_trt_index.read();
3096        bool        eop      = p_vci_ixr.reop.read();
3097        wide_data_t data     = p_vci_ixr.rdata.read();
3098        bool        error    = ((p_vci_ixr.rerror.read() & 0x1) == 1);
3099
3100        assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-2))) || p_vci_ixr.rerror.read())
3101               and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
3102
3103        m_trt.write_rsp( index,
3104                         r_ixr_rsp_cpt.read(),
3105                         data,
3106                         error);
3107
3108        r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 2;
3109
3110        if(eop)
3111        {
3112          r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
3113          r_ixr_rsp_fsm = IXR_RSP_IDLE;
3114        }
3115
3116#if DEBUG_MEMC_IXR_RSP
3117if(m_debug_ixr_rsp_fsm)
3118{
3119    std::cout << "  <MEMC " << name() << " IXR_RSP_TRT_READ> Writing a word in TRT : "
3120              << " index = " << std::dec << index
3121              << " / word = " << r_ixr_rsp_cpt.read()
3122              << " / data = " << std::hex << data << std::endl;
3123}
3124#endif
3125      }
3126      break;
3127    }
3128  } // end swich r_ixr_rsp_fsm
3129
3130  ////////////////////////////////////////////////////////////////////////////
3131  //                XRAM_RSP FSM
3132  ////////////////////////////////////////////////////////////////////////////
3133  // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
3134  // The cache line has been written in the TRT by the IXR_CMD_FSM.
3135  // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
3136  // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
3137  // as the number of entries in the TRT, that are handled with
3138  // a round-robin priority...
3139  //
3140  // When a response is available, the corresponding TRT entry
3141  // is copied in a local buffer to be written in the cache.
3142  // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
3143  // It selects a cache slot and writes the line in the cache.
3144  // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
3145  // FSM to return the cache line to the registered processor.
3146  // If there is no empty slot, a victim line is evicted, and
3147  // invalidate requests are sent to the L1 caches containing copies.
3148  // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
3149  // FSM to save the victim line to the XRAM, and register the write transaction
3150  // in the TRT (using the entry previously used by the read transaction).
3151  ///////////////////////////////////////////////////////////////////////////////
3152
3153  switch(r_xram_rsp_fsm.read())
3154  {
3155    ///////////////////
3156    case XRAM_RSP_IDLE: // scan the XRAM responses / select a TRT index (round robin)
3157    {
3158      size_t ptr   = r_xram_rsp_trt_index.read();
3159      size_t lines = m_trt_lines;
3160      for(size_t i=0 ; i<lines ; i++)
3161      {
3162        size_t index = (i+ptr+1) %lines;
3163        if(r_ixr_rsp_to_xram_rsp_rok[index])
3164        {
3165          r_xram_rsp_trt_index             = index;
3166          r_ixr_rsp_to_xram_rsp_rok[index] = false;
3167          r_xram_rsp_fsm                   = XRAM_RSP_DIR_LOCK;
3168
3169#if DEBUG_MEMC_XRAM_RSP
3170if(m_debug_xram_rsp_fsm)
3171std::cout << "  <MEMC " << name() << " XRAM_RSP_IDLE>"
3172          << " Available cache line in TRT:"
3173          << " index = " << std::dec << index << std::endl;
3174#endif
3175          break;
3176        }
3177      }
3178      break;
3179    }
3180    ///////////////////////
3181    case XRAM_RSP_DIR_LOCK: // Takes the DIR lock and the TRT lock
3182                            // Copy the TRT entry in a local buffer
3183    {
3184      if((r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) &&
3185          (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP))
3186      {
3187        // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
3188        size_t  index = r_xram_rsp_trt_index.read();
3189        r_xram_rsp_trt_buf.copy( m_trt.read(index) ); 
3190
3191        r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
3192
3193//        TransactionTabEntry trt_entry(m_trt.read(index));
3194//        r_xram_rsp_trt_buf.copy(trt_entry);           // TRT entry local buffer
3195
3196#if DEBUG_MEMC_XRAM_RSP
3197if(m_debug_xram_rsp_fsm)
3198std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_LOCK>"
3199          << " Get access to DIR and TRT" << std::endl;
3200#endif
3201      }
3202      break;
3203    }
3204    ///////////////////////
3205    case XRAM_RSP_TRT_COPY: // Select a victim cache line
3206                            // and copy it in a local buffer
3207    {
3208      if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) and
3209           (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP) )
3210      {
3211        // selects & extracts a victim line from cache
3212        size_t way = 0;
3213        size_t set = m_y[(addr_t)(r_xram_rsp_trt_buf.nline * m_words * 4)];
3214
3215        DirectoryEntry victim(m_cache_directory.select(set, way));
3216
3217        bool inval = (victim.count && victim.valid) ;
3218
3219        // copy the victim line in a local buffer
3220        m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
3221
3222        r_xram_rsp_victim_copy      = victim.owner.srcid;
3223
3224#if L1_MULTI_CACHE
3225        r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
3226#endif
3227        r_xram_rsp_victim_copy_inst = victim.owner.inst;
3228        r_xram_rsp_victim_count     = victim.count;
3229        r_xram_rsp_victim_ptr       = victim.ptr;
3230        r_xram_rsp_victim_way       = way;
3231        r_xram_rsp_victim_set       = set;
3232        r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
3233        r_xram_rsp_victim_is_cnt    = victim.is_cnt;
3234        r_xram_rsp_victim_inval     = inval ;
3235        r_xram_rsp_victim_dirty     = victim.dirty;
3236
3237        if(!r_xram_rsp_trt_buf.rerror)
3238        {
3239          r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
3240        }
3241        else
3242        {
3243          r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;
3244        }
3245
3246#if DEBUG_MEMC_XRAM_RSP
3247if(m_debug_xram_rsp_fsm)
3248std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_COPY>"
3249          << " Select a slot: "
3250          << " way = " << std::dec << way
3251          << " / set = " << set
3252          << " / inval_required = " << inval << std::endl;
3253#endif
3254      }
3255      else
3256      {
3257        std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_TRT_COPY" 
3258                  << " bad TRT or DIR allocation" << std::endl;
3259        exit(0);
3260      }
3261      break;
3262    }
3263    /////////////////////////
3264    case XRAM_RSP_INVAL_LOCK: // Take the UPT lock to check a possible pending inval
3265    {
3266      if(r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP)
3267      {
3268        size_t index = 0;
3269        if(m_upt.search_inval(r_xram_rsp_trt_buf.nline, index))  // pending inval
3270        {
3271          r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3272
3273#if DEBUG_MEMC_XRAM_RSP
3274if(m_debug_xram_rsp_fsm)
3275std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3276          << " Get acces to UPT, but line invalidation registered" 
3277          << " / nline = " << std::hex << r_xram_rsp_trt_buf.nline
3278          << " / index = " << std::dec << index << std::endl;
3279#endif
3280
3281        }
3282        else if(m_upt.is_full() && r_xram_rsp_victim_inval.read()) // UPT full
3283        {
3284          r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3285
3286#if DEBUG_MEMC_XRAM_RSP
3287if(m_debug_xram_rsp_fsm)
3288std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3289          << " Get acces to UPT, but inval required and UPT full" << std::endl;
3290#endif
3291        }
3292        else
3293        {
3294          r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
3295
3296#if DEBUG_MEMC_XRAM_RSP
3297if(m_debug_xram_rsp_fsm)
3298std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_LOCK>"
3299          << " Get acces to UPT" << std::endl;
3300#endif
3301        }
3302      }
3303      break;
3304    }
3305    /////////////////////////
3306    case XRAM_RSP_INVAL_WAIT: // release all locks and returns to DIR_LOCK to retry
3307    {
3308
3309#if DEBUG_MEMC_XRAM_RSP
3310if(m_debug_xram_rsp_fsm)
3311std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL_WAIT>"
3312          << " Release all locks and retry" << std::endl;
3313#endif
3314      r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
3315      break;
3316    }
3317    ///////////////////////
3318    case XRAM_RSP_DIR_UPDT:   // updates the cache (both data & directory)
3319                              // and possibly set an inval request in UPT
3320    {
3321      // check if this is an instruction read, this means pktid is either
3322      // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
3323      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3324      bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) && r_xram_rsp_trt_buf.proc_read;
3325
3326      // check if this is a cached read, this means pktid is either
3327      // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
3328      // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3329      bool cached_read = (r_xram_rsp_trt_buf.pktid & 0x1) && r_xram_rsp_trt_buf.proc_read;
3330
3331      bool dirty = false;
3332
3333      // update cache data
3334      size_t set   = r_xram_rsp_victim_set.read();
3335      size_t way   = r_xram_rsp_victim_way.read();
3336      for(size_t word=0; word<m_words ; word++)
3337      {
3338        m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
3339
3340        dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[word] != 0);
3341
3342        if(m_monitor_ok)
3343        {
3344          addr_t address = r_xram_rsp_trt_buf.nline<<6 | word<<2;
3345          check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[word], false);
3346        }
3347      }
3348
3349      // update cache directory
3350      DirectoryEntry entry;
3351      entry.valid   = true;
3352      entry.is_cnt  = false;
3353      entry.lock    = false;
3354      entry.dirty   = dirty;
3355      entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
3356      entry.ptr     = 0;
3357      if(cached_read)
3358      {
3359        entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
3360#if L1_MULTI_CACHE
3361        entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
3362#endif
3363        entry.owner.inst    = inst_read;
3364        entry.count         = 1;
3365      }
3366      else
3367      {
3368        entry.owner.srcid    = 0;
3369#if L1_MULTI_CACHE
3370        entry.owner.cache_id = 0;
3371#endif
3372        entry.owner.inst     = 0;
3373        entry.count          = 0;
3374      }
3375      m_cache_directory.write(set, way, entry);
3376
3377      // request an invalidattion request in UPT for victim line
3378      if(r_xram_rsp_victim_inval.read())
3379      {
3380        bool   broadcast    = r_xram_rsp_victim_is_cnt.read();
3381        size_t index        = 0;
3382        size_t count_copies = r_xram_rsp_victim_count.read();
3383
3384        bool   wok = m_upt.set(false,      // it's an inval transaction
3385                               broadcast,  // set broadcast bit
3386                               false,      // it does not need a response
3387                               0,          // srcid
3388                               0,          // trdid
3389                               0,          // pktid
3390                               r_xram_rsp_victim_nline.read(),
3391                               count_copies,
3392                               index);
3393
3394        r_xram_rsp_upt_index = index;
3395
3396        if(!wok)
3397        {
3398          std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_DIR_UPDT"
3399                    << " update_tab entry free but write unsuccessful" << std::endl;
3400          exit(0);
3401        }
3402      }
3403
3404#if DEBUG_MEMC_XRAM_RSP
3405if(m_debug_xram_rsp_fsm)
3406{
3407std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_UPDT>" 
3408          << " Cache update: "
3409          << " way = " << std::dec << way
3410          << " / set = " << set
3411          << " / owner_id = " << std::hex << entry.owner.srcid
3412          << " / owner_ins = " << std::dec << entry.owner.inst
3413          << " / count = " << entry.count
3414          << " / is_cnt = " << entry.is_cnt << std::endl;
3415if(r_xram_rsp_victim_inval.read())
3416std::cout << "                           Invalidation request for victim line "
3417          << std::hex << r_xram_rsp_victim_nline.read()
3418          << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
3419}
3420#endif
3421
3422      // If the victim is not dirty, we don't need another XRAM put transaction,
3423      // and we can erase the TRT entry
3424      if(!r_xram_rsp_victim_dirty.read())  m_trt.erase(r_xram_rsp_trt_index.read());
3425
3426      // Next state
3427      if(r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
3428      else if(r_xram_rsp_trt_buf.proc_read)    r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3429      else if(r_xram_rsp_victim_inval.read())  r_xram_rsp_fsm = XRAM_RSP_INVAL;
3430      else                                     r_xram_rsp_fsm = XRAM_RSP_IDLE;
3431      break;
3432    }
3433    ////////////////////////
3434    case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (PUT to XRAM) if the victim is dirty
3435    {
3436      if(r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP)
3437      {
3438        m_trt.set(r_xram_rsp_trt_index.read(),
3439                              false,       // write to XRAM
3440                              r_xram_rsp_victim_nline.read(),  // line index
3441                              0,
3442                              0,
3443                              0,
3444                              false,
3445                              0,
3446                              0,
3447                              std::vector<be_t> (m_words,0),
3448                              std::vector<data_t> (m_words,0));
3449
3450#if DEBUG_MEMC_XRAM_RSP
3451if(m_debug_xram_rsp_fsm)
3452std::cout << "  <MEMC " << name() << " XRAM_RSP_TRT_DIRTY>"
3453          << " Set TRT entry for the put transaction"
3454          << " / dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3455#endif
3456        if(r_xram_rsp_trt_buf.proc_read)         r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3457        else if(r_xram_rsp_victim_inval.read())  r_xram_rsp_fsm = XRAM_RSP_INVAL;
3458        else                                     r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3459      }
3460      break;
3461    }
3462    //////////////////////
3463    case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
3464    {
3465      if(!r_xram_rsp_to_tgt_rsp_req.read())
3466      {
3467        r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
3468        r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
3469        r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
3470        for(size_t i=0; i < m_words; i++) 
3471        {
3472            r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3473        }
3474        r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3475        r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3476        r_xram_rsp_to_tgt_rsp_ll_key = r_xram_rsp_trt_buf.ll_key;
3477        r_xram_rsp_to_tgt_rsp_rerror = false;
3478        r_xram_rsp_to_tgt_rsp_req    = true;
3479
3480        if(r_xram_rsp_victim_inval)      r_xram_rsp_fsm = XRAM_RSP_INVAL;
3481        else if(r_xram_rsp_victim_dirty) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3482        else                             r_xram_rsp_fsm = XRAM_RSP_IDLE;
3483
3484#if DEBUG_MEMC_XRAM_RSP
3485if(m_debug_xram_rsp_fsm)
3486std::cout << "  <MEMC " << name() << " XRAM_RSP_DIR_RSP>"
3487          << " Request the TGT_RSP FSM to return data:"
3488          << " rsrcid = " << std::hex << r_xram_rsp_trt_buf.srcid
3489          << " / address = " << std::hex << r_xram_rsp_trt_buf.nline*m_words*4
3490          << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
3491#endif
3492      }
3493      break;
3494    }
3495    ////////////////////
3496    case XRAM_RSP_INVAL:  // send invalidate request to CC_SEND FSM
3497    {
3498      if(!r_xram_rsp_to_cc_send_multi_req.read() &&
3499          !r_xram_rsp_to_cc_send_brdcast_req.read())
3500      {
3501        bool multi_req = !r_xram_rsp_victim_is_cnt.read();
3502        bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
3503        bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3504
3505        r_xram_rsp_to_cc_send_multi_req    = last_multi_req;
3506        r_xram_rsp_to_cc_send_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
3507        r_xram_rsp_to_cc_send_nline        = r_xram_rsp_victim_nline.read();
3508        r_xram_rsp_to_cc_send_trdid        = r_xram_rsp_upt_index;
3509        xram_rsp_to_cc_send_fifo_srcid     = r_xram_rsp_victim_copy.read();
3510        xram_rsp_to_cc_send_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
3511#if L1_MULTI_CACHE
3512        xram_rsp_to_cc_send_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
3513#endif
3514        xram_rsp_to_cc_send_fifo_put       = multi_req;
3515        r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
3516
3517        if(r_xram_rsp_victim_dirty)  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3518        else if(not_last_multi_req)  r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3519        else                         r_xram_rsp_fsm = XRAM_RSP_IDLE;
3520
3521#if DEBUG_MEMC_XRAM_RSP
3522if(m_debug_xram_rsp_fsm)
3523std::cout << "  <MEMC " << name() << " XRAM_RSP_INVAL>"
3524          << " Send an inval request to CC_SEND FSM"
3525          << " / victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3526#endif
3527      }
3528      break;
3529    }
3530    //////////////////////////
3531    case XRAM_RSP_WRITE_DIRTY:  // send a write request to IXR_CMD FSM
3532    {
3533      if(!r_xram_rsp_to_ixr_cmd_req.read())
3534      {
3535        r_xram_rsp_to_ixr_cmd_req = true;
3536        r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
3537        r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
3538        for(size_t i=0; i<m_words ; i++) 
3539        {
3540            r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
3541        }
3542        m_cpt_write_dirty++;
3543
3544        bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
3545        bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3546
3547        if(not_last_multi_req)   r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3548        else                     r_xram_rsp_fsm = XRAM_RSP_IDLE;
3549
3550#if DEBUG_MEMC_XRAM_RSP
3551if(m_debug_xram_rsp_fsm)
3552std::cout << "  <MEMC " << name() << " XRAM_RSP_WRITE_DIRTY>"
3553          << " Send the put request to IXR_CMD FSM"
3554          << " / victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3555#endif
3556      }
3557      break;
3558    }
3559    /////////////////////////
3560    case XRAM_RSP_HEAP_REQ:    // Get the lock to the HEAP
3561    {
3562      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
3563      {
3564        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3565      }
3566
3567#if DEBUG_MEMC_XRAM_RSP
3568if(m_debug_xram_rsp_fsm)
3569std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_REQ>"
3570          << " Requesting HEAP lock" << std::endl;
3571#endif
3572      break;
3573    }
3574    /////////////////////////
3575    case XRAM_RSP_HEAP_ERASE: // erase the copies and send invalidations
3576    {
3577      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP)
3578      {
3579        HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
3580
3581        xram_rsp_to_cc_send_fifo_srcid    = entry.owner.srcid;
3582#if L1_MULTI_CACHE
3583        xram_rsp_to_cc_send_fifo_cache_id = entry.owner.cache_id;
3584#endif
3585        xram_rsp_to_cc_send_fifo_inst  = entry.owner.inst;
3586        xram_rsp_to_cc_send_fifo_put   = true;
3587        if(m_xram_rsp_to_cc_send_inst_fifo.wok())
3588        {
3589          r_xram_rsp_next_ptr = entry.next;
3590          if(entry.next == r_xram_rsp_next_ptr.read())   // last copy
3591          {
3592            r_xram_rsp_to_cc_send_multi_req = true;
3593            r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
3594          }
3595          else
3596          {
3597            r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3598          }
3599        }
3600        else
3601        {
3602          r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3603        }
3604
3605#if DEBUG_MEMC_XRAM_RSP
3606if(m_debug_xram_rsp_fsm)
3607std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_ERASE>"
3608          << " Erase copy:"
3609          << " srcid = " << std::dec << entry.owner.srcid
3610          << " / inst = " << std::dec << entry.owner.inst << std::endl;
3611#endif
3612      }
3613      break;
3614    }
3615    /////////////////////////
3616    case XRAM_RSP_HEAP_LAST:  // last copy
3617    {
3618      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP)
3619      {
3620        std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST"
3621                   << " bad HEAP allocation" << std::endl;
3622        exit(0);
3623      }
3624      size_t free_pointer = m_heap.next_free_ptr();
3625
3626      HeapEntry last_entry;
3627      last_entry.owner.srcid    = 0;
3628#if L1_MULTI_CACHE
3629      last_entry.owner.cache_id = 0;
3630#endif
3631      last_entry.owner.inst     = false;
3632      if(m_heap.is_full())
3633      {
3634        last_entry.next     = r_xram_rsp_next_ptr.read();
3635        m_heap.unset_full();
3636      }
3637      else
3638      {
3639        last_entry.next     = free_pointer;
3640      }
3641
3642      m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
3643      m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
3644
3645      r_xram_rsp_fsm = XRAM_RSP_IDLE;
3646
3647#if DEBUG_MEMC_XRAM_RSP
3648if(m_debug_xram_rsp_fsm)
3649std::cout << "  <MEMC " << name() << " XRAM_RSP_HEAP_LAST>"
3650          << " Heap housekeeping" << std::endl;
3651#endif
3652      break;
3653    }
3654    // ///////////////////////
3655    case XRAM_RSP_ERROR_ERASE:  // erase TRT entry in case of error
3656    {
3657      m_trt.erase(r_xram_rsp_trt_index.read());
3658
3659      // Next state
3660      if(r_xram_rsp_trt_buf.proc_read) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3661      else                             r_xram_rsp_fsm = XRAM_RSP_IDLE;
3662
3663#if DEBUG_MEMC_XRAM_RSP
3664if(m_debug_xram_rsp_fsm)
3665std::cout << "  <MEMC " << name() << " XRAM_RSP_ERROR_ERASE>"
3666          << " Error reported by XRAM / erase the TRT entry" << std::endl;
3667#endif
3668      break;
3669    }
3670    ////////////////////////
3671    case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3672    {
3673      if(!r_xram_rsp_to_tgt_rsp_req.read()) 
3674      {
3675        r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3676        r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3677        r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3678        for(size_t i=0; i < m_words; i++) 
3679        {
3680            r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3681        }
3682        r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3683        r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3684        r_xram_rsp_to_tgt_rsp_rerror = true;
3685        r_xram_rsp_to_tgt_rsp_req    = true;
3686
3687        r_xram_rsp_fsm = XRAM_RSP_IDLE;
3688
3689#if DEBUG_MEMC_XRAM_RSP
3690if(m_debug_xram_rsp_fsm)
3691    std::cout << "  <MEMC " << name() 
3692              << " XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3693              << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
3694#endif
3695      }
3696      break;
3697    }
3698  } // end swich r_xram_rsp_fsm
3699
3700  ////////////////////////////////////////////////////////////////////////////////////
3701  //    CLEANUP FSM
3702  ////////////////////////////////////////////////////////////////////////////////////
3703  // The CLEANUP FSM handles the cleanup request from L1 caches.
3704  // It accesses the cache directory and the heap to update the list of copies.
3705  ////////////////////////////////////////////////////////////////////////////////////
3706
3707  switch(r_cleanup_fsm.read())
3708  {
3709    //////////////////
3710    case CLEANUP_IDLE:     // Get first DSPIN flit of the CLEANUP command
3711    {
3712      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
3713
3714      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
3715
3716      uint32_t srcid =
3717        DspinDhccpParam::dspin_get(
3718            flit,
3719            DspinDhccpParam::CLEANUP_SRCID);
3720
3721      uint8_t type =
3722        DspinDhccpParam::dspin_get(
3723            flit,
3724            DspinDhccpParam::FROM_L1_TYPE);
3725
3726      r_cleanup_way_index =
3727        DspinDhccpParam::dspin_get(
3728            flit,
3729            DspinDhccpParam::CLEANUP_WAY_INDEX);
3730
3731      r_cleanup_nline =
3732        DspinDhccpParam::dspin_get(
3733            flit,
3734            DspinDhccpParam::CLEANUP_NLINE_MSB) << 32;
3735
3736      r_cleanup_inst  = (type == DspinDhccpParam::TYPE_CLEANUP_INST);
3737      r_cleanup_srcid = srcid;
3738
3739      if(srcid >= m_initiators)
3740      {
3741        std::cout
3742            << "VCI_MEM_CACHE ERROR " << name()
3743            << " CLEANUP_IDLE state"  << std::endl
3744            << "illegal srcid for cleanup request" << std::endl;
3745
3746        exit(0);
3747      }
3748
3749      m_cpt_cleanup++;
3750      cc_receive_to_cleanup_fifo_get = true;
3751      r_cleanup_fsm                  = CLEANUP_GET_NLINE;
3752
3753#if DEBUG_MEMC_CLEANUP
3754      if(m_debug_cleanup_fsm)
3755      {
3756        std::cout
3757            << "  <MEMC "         << name()
3758            << " CLEANUP_IDLE> Cleanup request:" << std::hex
3759            << " / owner_id = "   << srcid
3760            << " / owner_ins = "  << (type == DspinDhccpParam::TYPE_CLEANUP_INST)
3761            << std::endl;
3762      }
3763#endif
3764      break;
3765    }
3766
3767    ///////////////////////
3768    case CLEANUP_GET_NLINE:  // GET second DSPIN flit of the cleanup command
3769    {
3770      if(not m_cc_receive_to_cleanup_fifo.rok()) break;
3771
3772      uint64_t flit = m_cc_receive_to_cleanup_fifo.read();
3773
3774      addr_t nline = r_cleanup_nline.read() |
3775        DspinDhccpParam::dspin_get(flit, DspinDhccpParam::CLEANUP_NLINE_LSB);
3776
3777      cc_receive_to_cleanup_fifo_get = true;
3778      r_cleanup_nline                = nline;
3779      r_cleanup_fsm                  = CLEANUP_DIR_REQ;
3780
3781#if DEBUG_MEMC_CLEANUP
3782      if(m_debug_cleanup_fsm)
3783      {
3784        std::cout
3785            << "  <MEMC "         << name()
3786            << " CLEANUP_GET_NLINE> Cleanup request:"
3787            << std::hex
3788            << " / address = "    << nline * m_words * 4
3789            << std::endl;
3790      }
3791#endif
3792      break;
3793    }
3794
3795    /////////////////////
3796    case CLEANUP_DIR_REQ:
3797    {
3798      // Get the lock to the directory
3799      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP) break;
3800
3801      r_cleanup_fsm = CLEANUP_DIR_LOCK;
3802
3803#if DEBUG_MEMC_CLEANUP
3804      if(m_debug_cleanup_fsm)
3805      {
3806        std::cout
3807            << "  <MEMC " << name() << " CLEANUP_DIR_REQ> Requesting DIR lock "
3808            << std::endl;
3809      }
3810#endif
3811      break;
3812    }
3813
3814    //////////////////////
3815    case CLEANUP_DIR_LOCK:
3816    {
3817      // test directory status
3818      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
3819      {
3820        std::cout
3821            << "VCI_MEM_CACHE ERROR " << name()
3822            << " CLEANUP_DIR_LOCK state"
3823            << " bad DIR allocation" << std::endl;
3824
3825        exit(0);
3826      }
3827
3828      // Read the directory
3829      size_t way = 0;
3830      addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
3831
3832      DirectoryEntry entry   = m_cache_directory.read(cleanup_address , way);
3833      r_cleanup_is_cnt       = entry.is_cnt;
3834      r_cleanup_dirty        = entry.dirty;
3835      r_cleanup_tag          = entry.tag;
3836      r_cleanup_lock         = entry.lock;
3837      r_cleanup_way          = way;
3838      r_cleanup_count        = entry.count;
3839      r_cleanup_ptr          = entry.ptr;
3840      r_cleanup_copy         = entry.owner.srcid;
3841      r_cleanup_copy_inst    = entry.owner.inst;
3842#if L1_MULTI_CACHE
3843      r_cleanup_copy_cache   = entry.owner.cache_id;
3844#endif
3845
3846      // hit :
3847      // the copy must be cleared
3848      if(entry.valid)
3849      {
3850        assert(
3851            (entry.count > 0) &&
3852            "VCI MEM CACHE ERROR: "
3853            "In CLEANUP_DIR_LOCK, CLEANUP command on a valid entry "
3854            "with no copies");
3855
3856        // no access to the heap
3857        if((entry.count == 1) || (entry.is_cnt))
3858        {
3859          r_cleanup_fsm = CLEANUP_DIR_WRITE;
3860        }
3861        // access to the heap
3862        else
3863        {
3864          r_cleanup_fsm = CLEANUP_HEAP_REQ;
3865        }
3866      }
3867      // miss :
3868      // we must check the update table for a pending
3869      // invalidation transaction
3870      else
3871      {
3872        r_cleanup_fsm = CLEANUP_UPT_LOCK;
3873      }
3874
3875#if DEBUG_MEMC_CLEANUP
3876      if(m_debug_cleanup_fsm)
3877      {
3878        std::cout
3879            << "  <MEMC " << name()
3880            << " CLEANUP_DIR_LOCK> Test directory status: "
3881            << std::hex
3882            << " line = "         << cleanup_address
3883            << " / hit = "        << entry.valid
3884            << " / dir_id = "     << entry.owner.srcid
3885            << " / dir_ins = "    << entry.owner.inst
3886            << " / search_id = "  << r_cleanup_srcid.read()
3887            << " / search_ins = " << r_cleanup_inst.read()
3888            << " / count = "      << entry.count
3889            << " / is_cnt = "     << entry.is_cnt
3890            << std::endl;
3891      }
3892#endif
3893      break;
3894    }
3895
3896    ///////////////////////
3897    case CLEANUP_DIR_WRITE:
3898    {
3899      // Update the directory entry without heap access
3900      if(r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP)
3901      {
3902        std::cout
3903            << "VCI_MEM_CACHE ERROR " << name()
3904            << " CLEANUP_DIR_WRITE state"
3905            << " bad DIR allocation" << std::endl;
3906
3907        exit(0);
3908      }
3909
3910      size_t way         = r_cleanup_way.read();
3911      size_t set         = m_y[(addr_t)(r_cleanup_nline.read()*m_words*4)];
3912      bool   match_srcid = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3913
3914#if L1_MULTI_CACHE
3915      match_srcid       &= (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3916#endif
3917
3918      bool   match_inst  = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
3919      bool   match       = match_srcid && match_inst;
3920
3921      if(not r_cleanup_is_cnt.read() and not match)
3922      {
3923        std::cout
3924            << "VCI_MEM_CACHE ERROR : Cleanup request on a valid"
3925            << "entry using linked list mode with no corresponding"
3926            << "directory or heap entry"
3927            << std::endl;
3928
3929        exit(1);
3930      }
3931
3932      // update the cache directory (for the copies)
3933      DirectoryEntry entry;
3934      entry.valid       = true;
3935      entry.is_cnt      = r_cleanup_is_cnt.read();
3936      entry.dirty       = r_cleanup_dirty.read();
3937      entry.tag         = r_cleanup_tag.read();
3938      entry.lock        = r_cleanup_lock.read();
3939      entry.ptr         = r_cleanup_ptr.read();
3940      entry.count       = r_cleanup_count.read() - 1;
3941      entry.owner.srcid = 0;
3942      entry.owner.inst  = 0;
3943
3944#if L1_MULTI_CACHE
3945      entry.owner.cache_id = 0;
3946#endif
3947
3948      m_cache_directory.write(set, way, entry);
3949
3950      r_cleanup_fsm = CLEANUP_SEND_ACK;
3951
3952#if DEBUG_MEMC_CLEANUP
3953      if(m_debug_cleanup_fsm)
3954      {
3955        std::cout
3956            << "  <MEMC " << name()
3957            << " CLEANUP_DIR_WRITE> Update directory:"
3958            << std::hex
3959            << " address = "   << r_cleanup_nline.read() * m_words * 4
3960            << " / dir_id = "  << entry.owner.srcid
3961            << " / dir_ins = " << entry.owner.inst
3962            << " / count = "   << entry.count
3963            << " / is_cnt = "  << entry.is_cnt
3964            << std::endl;
3965      }
3966#endif
3967
3968      break;
3969    }
3970
3971    //////////////////////
3972    case CLEANUP_HEAP_REQ:
3973    {
3974      // get the lock to the HEAP directory
3975      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP) break;
3976
3977      r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3978
3979#if DEBUG_MEMC_CLEANUP
3980      if(m_debug_cleanup_fsm)
3981      {
3982        std::cout
3983            << "  <MEMC " << name()
3984            << " CLEANUP_HEAP_REQ> HEAP lock acquired "
3985            << std::endl;
3986      }
3987#endif
3988      break;
3989    }
3990
3991    //////////////////////
3992    case CLEANUP_HEAP_LOCK:
3993    {
3994      // two cases are handled in this state :
3995      // 1. the matching copy is directly in the directory
3996      // 2. the matching copy is the first copy in the heap
3997      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
3998      {
3999        std::cout
4000            << "VCI_MEM_CACHE ERROR " << name()
4001            << " CLEANUP_HEAP_LOCK state"
4002            << " bad HEAP allocation" << std::endl;
4003
4004        exit(0);
4005      }
4006
4007      size_t way            = r_cleanup_way.read();
4008      size_t set            = m_y[(addr_t)(r_cleanup_nline.read() *m_words*4)];
4009
4010      HeapEntry heap_entry  = m_heap.read(r_cleanup_ptr.read());
4011      bool last             = (heap_entry.next == r_cleanup_ptr.read());
4012
4013      // match_dir computation
4014      bool match_dir_srcid  = (r_cleanup_copy.read()      == r_cleanup_srcid.read());
4015      bool match_dir_inst   = (r_cleanup_copy_inst.read() == r_cleanup_inst.read());
4016      bool match_dir        = match_dir_srcid  and match_dir_inst;
4017
4018      // match_heap computation
4019      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4020      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
4021      bool match_heap       = match_heap_srcid and match_heap_inst;
4022
4023      r_cleanup_prev_ptr    = r_cleanup_ptr.read();
4024      r_cleanup_prev_srcid  = heap_entry.owner.srcid;
4025      r_cleanup_prev_inst   = heap_entry.owner.inst;
4026
4027#if L1_MULTI_CACHE
4028      match_dir  = match_dir  and(r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
4029      match_heap = match_heap and(heap_entry.owner.cache_id   == r_cleanup_pktid.read());
4030      r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4031#endif
4032
4033      if(not match_dir and not match_heap and last)
4034      {
4035        std::cout
4036            << "VCI_MEM_CACHE ERROR " << name()
4037            << " CLEANUP_HEAP_LOCK state"
4038            << " hit but copy not found"
4039            << std::endl;
4040/**/
4041        std::cout
4042          << "r_cleanup_srcid = " << r_cleanup_srcid.read()
4043          << " / r_cleanup_inst = " << r_cleanup_inst.read() << std::endl
4044          << "r_cleanup_copy = " << r_cleanup_copy.read()
4045          << " / r_cleanup_copy_inst = " << r_cleanup_copy_inst.read() << std::endl
4046          << "heap_entry.owner.srcid = " << heap_entry.owner.srcid
4047          << " / heap_entry.owner.inst = " << heap_entry.owner.inst << std::endl;
4048/**/
4049        exit(0);
4050      }
4051
4052      if(match_dir and match_heap)
4053      {
4054        std::cout
4055            << "VCI_MEM_CACHE ERROR " << name()
4056            << " CLEANUP_HEAP_LOCK state"
4057            << " two copies matching the cleanup owner id"
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
4069        exit(0);
4070      }
4071
4072      DirectoryEntry dir_entry;
4073      dir_entry.valid          = true;
4074      dir_entry.is_cnt         = r_cleanup_is_cnt.read();
4075      dir_entry.dirty          = r_cleanup_dirty.read();
4076      dir_entry.tag            = r_cleanup_tag.read();
4077      dir_entry.lock           = r_cleanup_lock.read();
4078      dir_entry.count          = r_cleanup_count.read()-1;
4079
4080      // the matching copy is registered in the directory and
4081      // it must be replaced by the first copy registered in
4082      // the heap. The corresponding entry must be freed
4083      if(match_dir)
4084      {
4085        dir_entry.ptr            = heap_entry.next;
4086        dir_entry.owner.srcid    = heap_entry.owner.srcid;
4087        dir_entry.owner.inst     = heap_entry.owner.inst;
4088
4089#if L1_MULTI_CACHE
4090        dir_entry.owner.cache_id = heap_entry.owner.cache_id;
4091#endif
4092
4093        r_cleanup_next_ptr       = r_cleanup_ptr.read();
4094        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
4095      }
4096
4097      // the matching copy is the first copy in the heap
4098      // It must be freed and the copy registered in directory
4099      // must point to the next copy in heap
4100      else if(match_heap)
4101      {
4102        dir_entry.ptr            = heap_entry.next;
4103        dir_entry.owner.srcid    = r_cleanup_copy.read();
4104        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
4105
4106#if L1_MULTI_CACHE
4107        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
4108#endif
4109
4110        r_cleanup_next_ptr       = r_cleanup_ptr.read();
4111        r_cleanup_fsm            = CLEANUP_HEAP_FREE;
4112      }
4113
4114      // The matching copy is in the heap, but is not the first copy
4115      // The directory entry must be modified to decrement count
4116      else
4117      {
4118        dir_entry.ptr            = r_cleanup_ptr.read();
4119        dir_entry.owner.srcid    = r_cleanup_copy.read();
4120        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
4121
4122#if L1_MULTI_CACHE
4123        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
4124#endif
4125
4126        r_cleanup_next_ptr       = heap_entry.next;
4127        r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
4128      }
4129
4130      m_cache_directory.write(set,way,dir_entry);
4131
4132#if DEBUG_MEMC_CLEANUP
4133      if(m_debug_cleanup_fsm)
4134      {
4135        std::cout
4136            << "  <MEMC " << name()
4137            << " CLEANUP_HEAP_LOCK> Checks matching:"
4138            << " address = "      << r_cleanup_nline.read() * m_words * 4
4139            << " / dir_id = "     << r_cleanup_copy.read()
4140            << " / dir_ins = "    << r_cleanup_copy_inst.read()
4141            << " / heap_id = "    << heap_entry.owner.srcid
4142            << " / heap_ins = "   << heap_entry.owner.inst
4143            << " / search_id = "  << r_cleanup_srcid.read()
4144            << " / search_ins = " << r_cleanup_inst.read()
4145            << std::endl;
4146      }
4147#endif
4148      break;
4149    }
4150
4151    ////////////////////////
4152    case CLEANUP_HEAP_SEARCH:
4153    {
4154      // This state is handling the case where the copy
4155      // is in the heap, but is not the first in the linked list
4156      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4157      {
4158        std::cout
4159            << "VCI_MEM_CACHE ERROR " << name()
4160            << " CLEANUP_HEAP_SEARCH state"
4161            << " bad HEAP allocation" << std::endl;
4162
4163        exit(0);
4164      }
4165
4166      HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
4167
4168      bool last             = (heap_entry.next        == r_cleanup_next_ptr.read());
4169      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4170      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
4171      bool match_heap       = match_heap_srcid && match_heap_inst;
4172
4173#if L1_MULTI_CACHE
4174      match_heap = match_heap and(heap_entry.owner.cache_id == r_cleanup_pktid.read());
4175#endif
4176
4177      if(not match_heap and last)
4178      {
4179        std::cout
4180            << "VCI_MEM_CACHE_ERROR " << name()
4181            << " CLEANUP_HEAP_SEARCH state"
4182            << " cleanup on valid line but copy not found"
4183            << std::endl;
4184
4185        exit(0);
4186      }
4187
4188      // the matching copy must be removed
4189      if(match_heap)
4190      {
4191        // re-use ressources
4192        r_cleanup_ptr = heap_entry.next;
4193        r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
4194      }
4195      // test the next in the linked list
4196      else
4197      {
4198        r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
4199        r_cleanup_prev_srcid    = heap_entry.owner.srcid;
4200        r_cleanup_prev_inst     = heap_entry.owner.inst;
4201        r_cleanup_next_ptr      = heap_entry.next;
4202
4203        r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
4204
4205#if L1_MULTI_CACHE
4206        r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4207#endif
4208      }
4209
4210#if DEBUG_MEMC_CLEANUP
4211      if(m_debug_cleanup_fsm)
4212      {
4213        if(not match_heap)
4214        {
4215          std::cout
4216              << "  <MEMC " << name()
4217              << " CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
4218              << std::endl;
4219        }
4220        else
4221        {
4222          std::cout
4223              << "  <MEMC " << name()
4224              << " CLEANUP_HEAP_SEARCH> Matching copy found:"
4225              << std::endl;
4226        }
4227
4228        std::cout
4229            << " address = "      << r_cleanup_nline.read() * m_words * 4
4230            << " / heap_id = "    << heap_entry.owner.srcid
4231            << " / heap_ins = "   << heap_entry.owner.inst
4232            << " / search_id = "  << r_cleanup_srcid.read()
4233            << " / search_ins = " << r_cleanup_inst.read()
4234            << " / last = "       << last
4235            << std::endl;
4236      }
4237#endif
4238      break;
4239    }
4240
4241    case CLEANUP_HEAP_CLEAN:
4242    {
4243      // remove a copy in the linked list
4244      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4245      {
4246        std::cout
4247            << "VCI_MEM_CACHE ERROR " << name()
4248            << " CLEANUP_HEAP_CLEAN state"
4249            << "Bad HEAP allocation"  << std::endl;
4250
4251        exit(0);
4252      }
4253
4254      HeapEntry heap_entry;
4255      heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4256      heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4257
4258#if L1_MULTI_CACHE
4259      heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4260#endif
4261
4262      bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
4263
4264      // this is the last entry of the list of copies
4265      if(last)
4266      {
4267        heap_entry.next = r_cleanup_prev_ptr.read();
4268      }
4269      // this is not the last entry
4270      else
4271      {
4272        heap_entry.next = r_cleanup_ptr.read();
4273      }
4274
4275      m_heap.write(r_cleanup_prev_ptr.read(), heap_entry);
4276
4277      r_cleanup_fsm = CLEANUP_HEAP_FREE;
4278
4279#if DEBUG_MEMC_CLEANUP
4280      if(m_debug_cleanup_fsm)
4281      {
4282        std::cout
4283            << "  <MEMC " << name()
4284            << " CLEANUP_HEAP_SEARCH> Remove the copy in the linked list"
4285            << std::endl;
4286      }
4287#endif
4288      break;
4289    }
4290
4291    case CLEANUP_HEAP_FREE:
4292    {
4293      // The heap entry pointed by r_cleanup_next_ptr is freed
4294      // and becomes the head of the list of free entries
4295      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4296      {
4297        std::cout
4298            << "VCI_MEM_CACHE ERROR " << name()
4299            << " CLEANUP_HEAP_CLEAN state" << std::endl
4300            << "Bad HEAP allocation" << std::endl;
4301
4302        exit(0);
4303      }
4304
4305      HeapEntry heap_entry;
4306      heap_entry.owner.srcid    = 0;
4307      heap_entry.owner.inst     = false;
4308
4309#if L1_MULTI_CACHE
4310      heap_entry.owner.cache_id = 0;
4311#endif
4312
4313      if(m_heap.is_full())
4314      {
4315        heap_entry.next = r_cleanup_next_ptr.read();
4316      }
4317      else
4318      {
4319        heap_entry.next = m_heap.next_free_ptr();
4320      }
4321
4322      m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4323      m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4324      m_heap.unset_full();
4325
4326      r_cleanup_fsm = CLEANUP_SEND_ACK;
4327
4328#if DEBUG_MEMC_CLEANUP
4329      if(m_debug_cleanup_fsm)
4330      {
4331        std::cout
4332            << "  <MEMC " << name()
4333            << " CLEANUP_HEAP_SEARCH> Update the list of free entries"
4334            << std::endl;
4335      }
4336#endif
4337      break;
4338    }
4339
4340    case CLEANUP_UPT_LOCK:
4341    {
4342      // search pending invalidate transaction matching the Cleanup NLINE in the UPDATE TABLE
4343      // get the lock in the UPDATE_TABLE
4344      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP) break;
4345
4346      size_t index = 0;
4347      bool   match_inval;
4348
4349      match_inval = m_upt.search_inval(r_cleanup_nline.read(), index);
4350
4351      // no pending inval
4352      if(not match_inval)
4353      {
4354        r_cleanup_fsm = CLEANUP_SEND_ACK;
4355
4356#if DEBUG_MEMC_CLEANUP
4357        if(m_debug_cleanup_fsm)
4358        {
4359          std::cout
4360              << "  <MEMC " << name()
4361              << " CLEANUP_UPT_LOCK> Unexpected cleanup"
4362              << " with no corresponding UPT entry:"
4363              << " address = " << std::hex
4364              << (r_cleanup_nline.read() *4*m_words)
4365              << std::endl;
4366        }
4367#endif
4368        break;
4369      }
4370
4371      // pending inval
4372      r_cleanup_write_srcid    = m_upt.srcid(index);
4373      r_cleanup_write_trdid    = m_upt.trdid(index);
4374      r_cleanup_write_pktid    = m_upt.pktid(index);
4375      r_cleanup_write_need_rsp = m_upt.need_rsp(index);
4376      r_cleanup_index          = index;
4377
4378      r_cleanup_fsm         = CLEANUP_UPT_DECREMENT;
4379
4380#if DEBUG_MEMC_CLEANUP
4381      if(m_debug_cleanup_fsm)
4382      {
4383        std::cout
4384            << "  <MEMC " << name()
4385            << " CLEANUP_UPT_LOCK> Cleanup matching pending"
4386            << " invalidate transaction on UPT:"
4387            << std::hex
4388            << " address = "   << r_cleanup_nline.read() * m_words * 4
4389            << " upt_entry = " << index
4390            << std::endl;
4391      }
4392#endif
4393      break;
4394    }
4395
4396    case CLEANUP_UPT_DECREMENT:
4397    {
4398      // decrement response counter in UPT matching entry
4399      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4400      {
4401        std::cout
4402            << "VCI_MEM_CACHE ERROR "         << name()
4403            << " CLEANUP_UPT_DECREMENT state" << std::endl
4404            << "Bad UPT allocation"
4405            << std::endl;
4406
4407        exit(0);
4408      }
4409
4410      size_t count = 0;
4411      m_upt.decrement(r_cleanup_index.read(), count);
4412
4413      // invalidation transaction finished
4414      // (all acknowledgements received)
4415      if(count == 0)
4416      {
4417        r_cleanup_fsm = CLEANUP_UPT_CLEAR;
4418      }
4419      // invalidation transaction not finished
4420      else
4421      {
4422        r_cleanup_fsm = CLEANUP_SEND_ACK ;
4423      }
4424
4425#if DEBUG_MEMC_CLEANUP
4426      if(m_debug_cleanup_fsm)
4427      {
4428        std::cout
4429            << "  <MEMC "      << name()
4430            << " CLEANUP_UPT_DECREMENT> Decrement response counter in UPT:"
4431            << " UPT_index = " << r_cleanup_index.read()
4432            << " rsp_count = " << count
4433            << std::endl;
4434      }
4435#endif
4436      break;
4437    }
4438
4439    case CLEANUP_UPT_CLEAR:
4440    {
4441      // Clear UPT entry of finished invalidation transaction
4442      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4443      {
4444        std::cout
4445            << "VCI_MEM_CACHE ERROR "     << name()
4446            << " CLEANUP_UPT_CLEAR state" << std::endl
4447            << "Bad UPT allocation"
4448            << std::endl;
4449
4450        exit(0);
4451      }
4452
4453      m_upt.clear(r_cleanup_index.read());
4454
4455      if(r_cleanup_write_need_rsp.read())
4456      {
4457        r_cleanup_fsm = CLEANUP_WRITE_RSP;
4458      }
4459      else
4460      {
4461        r_cleanup_fsm = CLEANUP_SEND_ACK;
4462      }
4463
4464#if DEBUG_MEMC_CLEANUP
4465      if(m_debug_cleanup_fsm)
4466      {
4467        std::cout
4468            << "  <MEMC "      << name()
4469            << " CLEANUP_UPT_CLEAR> Clear entry in UPT:"
4470            << " UPT_index = " << r_cleanup_index.read()
4471            << std::endl;
4472      }
4473#endif
4474      break;
4475    }
4476
4477    case CLEANUP_WRITE_RSP:
4478    {
4479      // response to a previous write on the direct network
4480      // wait if pending request to the TGT_RSP FSM
4481      if(r_cleanup_to_tgt_rsp_req.read()) break;
4482
4483      // no pending request
4484      r_cleanup_to_tgt_rsp_req     = true;
4485      r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4486      r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4487      r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4488
4489      r_cleanup_fsm                = CLEANUP_SEND_ACK;
4490
4491#if DEBUG_MEMC_CLEANUP
4492      if(m_debug_cleanup_fsm)
4493      {
4494        std::cout
4495            << "  <MEMC " << name()
4496            << " CLEANUP_WRITE_RSP> Send a response to a previous"
4497            << " write request waiting for coherence transaction completion: "
4498            << " rsrcid = "   << std::hex << r_cleanup_write_srcid.read()
4499            << " / rtrdid = " << std::hex << r_cleanup_write_trdid.read()
4500            << std::endl;
4501      }
4502#endif
4503      break;
4504    }
4505
4506    case CLEANUP_SEND_ACK:
4507    {
4508      // acknowledgement to a cleanup command
4509      // on the coherence network (request to the CC_SEND FSM).
4510      // wait if pending request to the CC_SEND FSM
4511      if(r_cleanup_to_cc_send_req.read()) break;
4512
4513      r_cleanup_to_cc_send_req       = true;
4514      r_cleanup_to_cc_send_set_index = r_cleanup_nline.read() & 0xFFFF;
4515      r_cleanup_to_cc_send_way_index = r_cleanup_way_index.read();
4516      r_cleanup_to_cc_send_srcid     = r_cleanup_srcid.read();
4517      r_cleanup_to_cc_send_inst      = r_cleanup_inst.read();
4518
4519      r_cleanup_fsm = CLEANUP_IDLE;
4520
4521#if DEBUG_MEMC_CLEANUP
4522      if(m_debug_cleanup_fsm)
4523      {
4524        std::cout
4525            << "  <MEMC " << name()
4526            << " CLEANUP_SEND_ACK> Send the response to a cleanup request:"
4527            << " srcid = " << std::dec << r_cleanup_srcid.read()
4528            << std::endl;
4529      }
4530#endif
4531      break;
4532    }
4533  } // end switch cleanup fsm
4534
4535  ////////////////////////////////////////////////////////////////////////////////////
4536  //    CAS FSM
4537  ////////////////////////////////////////////////////////////////////////////////////
4538  // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4539  // that are handled as "compare-and-swap instructions.
4540  //
4541  // This command contains two or four flits:
4542  // - In case of 32 bits atomic access, the first flit contains the value read
4543  // by a previous LL instruction, the second flit contains the value to be writen.
4544  // - In case of 64 bits atomic access, the 2 first flits contains the value read
4545  // by a previous LL instruction, the 2 next flits contains the value to be writen.
4546  //
4547  // The target address is cachable. If it is replicated in other L1 caches
4548  // than the writer, a coherence operation is done.
4549  //
4550  // It access the directory to check hit / miss.
4551  // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4552  // If a read transaction to the XRAM for this line already exists,
4553  // or if the transaction table is full, it goes to the WAIT state
4554  // to release the locks and try again. When the GET transaction has been
4555  // launched, it goes to the WAIT state and try again.
4556  // The CAS request is not consumed in the FIFO until a HIT is obtained.
4557  // - In case of hit...
4558  ///////////////////////////////////////////////////////////////////////////////////
4559
4560  switch(r_cas_fsm.read())
4561  {
4562      /////////////
4563    case CAS_IDLE:     // fill the local rdata buffers
4564    {
4565      if(m_cmd_cas_addr_fifo.rok())
4566      {
4567
4568#if DEBUG_MEMC_CAS
4569        if(m_debug_cas_fsm)
4570        {
4571          std::cout << "  <MEMC " << name() << " CAS_IDLE> CAS command: " << std::hex
4572                    << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4573                    << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4574                    << " wdata = " << m_cmd_cas_wdata_fifo.read()
4575                    << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4576                    << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4577        }
4578#endif
4579        if(m_cmd_cas_eop_fifo.read())
4580        {
4581          m_cpt_cas++;
4582          r_cas_fsm = CAS_DIR_REQ;
4583        }
4584        else  // we keep the last word in the FIFO
4585        {
4586          cmd_cas_fifo_get = true;
4587        }
4588        // We fill the two buffers
4589        if(r_cas_cpt.read() < 2)    // 32 bits access
4590          r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4591
4592        if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4593          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4594
4595        if(r_cas_cpt.read() >3)  // more than 4 flits...
4596        {
4597          std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4598                    << std::endl;
4599          exit(0);
4600        }
4601
4602        if(r_cas_cpt.read() ==2)
4603          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4604
4605        r_cas_cpt = r_cas_cpt.read() +1;
4606      }
4607      break;
4608    }
4609
4610    /////////////////
4611    case CAS_DIR_REQ:
4612    {
4613      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4614      {
4615        r_cas_fsm = CAS_DIR_LOCK;
4616      }
4617
4618#if DEBUG_MEMC_CAS
4619      if(m_debug_cas_fsm)
4620      {
4621        std::cout
4622            << "  <MEMC " << name() << " CAS_DIR_REQ> Requesting DIR lock "
4623            << std::endl;
4624      }
4625#endif
4626      break;
4627    }
4628
4629    /////////////////
4630    case CAS_DIR_LOCK:  // Read the directory
4631    {
4632      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4633      {
4634        size_t way = 0;
4635        DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4636
4637        r_cas_is_cnt     = entry.is_cnt;
4638        r_cas_dirty      = entry.dirty;
4639        r_cas_tag        = entry.tag;
4640        r_cas_way        = way;
4641        r_cas_copy       = entry.owner.srcid;
4642#if L1_MULTI_CACHE
4643        r_cas_copy_cache = entry.owner.cache_id;
4644#endif
4645        r_cas_copy_inst  = entry.owner.inst;
4646        r_cas_ptr        = entry.ptr;
4647        r_cas_count      = entry.count;
4648
4649        if(entry.valid)  r_cas_fsm = CAS_DIR_HIT_READ;
4650        else             r_cas_fsm = CAS_MISS_TRT_LOCK;
4651
4652#if DEBUG_MEMC_CAS
4653        if(m_debug_cas_fsm)
4654        {
4655          std::cout << "  <MEMC " << name() << " CAS_DIR_LOCK> Directory acces"
4656                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4657                    << " / hit = " << std::dec << entry.valid
4658                    << " / count = " << entry.count
4659                    << " / is_cnt = " << entry.is_cnt << std::endl;
4660        }
4661#endif
4662      }
4663      else
4664      {
4665        std::cout
4666            << "VCI_MEM_CACHE ERROR " << name()
4667            << " CAS_DIR_LOCK state" << std::endl
4668            << "Bad DIR allocation"   << std::endl;
4669
4670        exit(0);
4671      }
4672
4673      break;
4674    }
4675    /////////////////////
4676    case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4677                            // and check data change in cache
4678    {
4679      size_t way  = r_cas_way.read();
4680      size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4681
4682      // update directory (lock & dirty bits)
4683      DirectoryEntry entry;
4684      entry.valid          = true;
4685      entry.is_cnt         = r_cas_is_cnt.read();
4686      entry.dirty          = true;
4687      entry.lock           = true;
4688      entry.tag            = r_cas_tag.read();
4689      entry.owner.srcid    = r_cas_copy.read();
4690#if L1_MULTI_CACHE
4691      entry.owner.cache_id = r_cas_copy_cache.read();
4692#endif
4693      entry.owner.inst     = r_cas_copy_inst.read();
4694      entry.count          = r_cas_count.read();
4695      entry.ptr            = r_cas_ptr.read();
4696
4697      m_cache_directory.write(set, way, entry);
4698
4699      // Stored data from cache in buffer to do the comparison in next state
4700      m_cache_data.read_line(way, set, r_cas_data);
4701
4702      r_cas_fsm = CAS_DIR_HIT_COMPARE;
4703
4704#if DEBUG_MEMC_CAS
4705if(m_debug_cas_fsm)
4706std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_READ> Read data from "
4707          << " cache and store it in buffer" << std::endl;
4708#endif
4709      break;
4710    }
4711
4712    case CAS_DIR_HIT_COMPARE:
4713    {
4714      size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4715
4716      // Read data in buffer & check data change
4717      bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
4718
4719      if(r_cas_cpt.read() == 4)     // 64 bits CAS
4720        ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
4721
4722      // to avoid livelock, force the atomic access to fail pseudo-randomly
4723      bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
4724      r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
4725
4726      // cas success
4727      if(ok and not forced_fail)
4728      {
4729        r_cas_fsm = CAS_DIR_HIT_WRITE;
4730      }
4731      // cas failure
4732      else
4733      {
4734        r_cas_fsm = CAS_RSP_FAIL;
4735      }
4736
4737#if DEBUG_MEMC_CAS
4738if(m_debug_cas_fsm)
4739std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_COMPARE> Compare the old"
4740          << " and the new data"
4741          << " / expected value = " << r_cas_rdata[0].read()
4742          << " / actual value = "   << r_cas_data[word].read()
4743          << " / forced_fail = "    << forced_fail << std::endl;
4744#endif
4745      break;
4746    }
4747    //////////////////////
4748    case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4749      // write data in cache if no CC request
4750    {
4751      // The CAS is a success => sw access to the llsc_global_table
4752      m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
4753
4754      // test coherence request
4755      if(r_cas_count.read())   // replicated line
4756      {
4757        if(r_cas_is_cnt.read())
4758        {
4759          r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4760        }
4761        else if(!r_cas_to_cc_send_multi_req.read() &&
4762                !r_cas_to_cc_send_brdcast_req.read())
4763        {
4764          r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4765        }
4766        else
4767        {
4768          r_cas_fsm = CAS_WAIT;
4769        }
4770      }
4771      else                    // no copies
4772      {
4773        size_t way  = r_cas_way.read();
4774        size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4775        size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4776
4777        // cache update
4778        m_cache_data.write(way, set, word, r_cas_wdata.read());
4779        if(r_cas_cpt.read() == 4)
4780          m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4781
4782        r_cas_fsm = CAS_RSP_SUCCESS;
4783
4784        // monitor
4785        if(m_monitor_ok)
4786        {
4787          addr_t address = m_cmd_cas_addr_fifo.read();
4788          char buf[80];
4789          snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
4790                   (int)m_cmd_cas_srcid_fifo.read());
4791          check_monitor(buf, address, r_cas_wdata.read(), false);
4792
4793          if(r_cas_cpt.read() == 4)
4794            check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
4795        }
4796
4797#if DEBUG_MEMC_CAS
4798if(m_debug_cas_fsm)
4799std::cout << "  <MEMC " << name() << " CAS_DIR_HIT_WRITE> Update cache:"
4800          << " way = " << std::dec << way
4801          << " / set = " << set
4802          << " / word = " << word
4803          << " / value = " << r_cas_wdata.read()
4804          << " / count = " << r_cas_count.read() 
4805          << " / global_llsc_table access" << std::endl;
4806#endif
4807      }
4808      break;
4809    }
4810    /////////////////
4811    case CAS_UPT_LOCK:  // try to register the transaction in UPT
4812      // and write data in cache if successful registration
4813      // releases locks to retry later if UPT full
4814    {
4815      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
4816      {
4817        bool        wok        = false;
4818        size_t      index      = 0;
4819        size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4820        size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4821        size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4822        addr_t      nline      = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
4823        size_t      nb_copies  = r_cas_count.read();
4824
4825        wok = m_upt.set(true,  // it's an update transaction
4826                               false,   // it's not a broadcast
4827                               true,    // it needs a response
4828                               srcid,
4829                               trdid,
4830                               pktid,
4831                               nline,
4832                               nb_copies,
4833                               index);
4834        if(wok)   // coherence transaction registered in UPT
4835        {
4836          // cache update
4837          size_t way  = r_cas_way.read();
4838          size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
4839          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4840
4841          m_cache_data.write(way, set, word, r_cas_wdata.read());
4842          if(r_cas_cpt.read() ==4)
4843            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4844
4845          r_cas_upt_index = index;
4846          r_cas_fsm = CAS_UPT_HEAP_LOCK;
4847
4848          // monitor
4849          if(m_monitor_ok)
4850          {
4851            addr_t address = m_cmd_cas_addr_fifo.read();
4852            char buf[80];
4853            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
4854                     (int)m_cmd_cas_srcid_fifo.read());
4855            check_monitor(buf, address, r_cas_wdata.read(), false);
4856
4857            if(r_cas_cpt.read() ==4)
4858              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
4859          }
4860        }
4861        else       //  releases the locks protecting UPT and DIR UPT full
4862        {
4863          r_cas_fsm = CAS_WAIT;
4864        }
4865
4866#if DEBUG_MEMC_CAS
4867if(m_debug_cas_fsm)
4868std::cout << "  <MEMC " << name()
4869          << " CAS_UPT_LOCK> Register multi-update transaction in UPT"
4870          << " / wok = " << wok
4871          << " / nline  = " << std::hex << nline
4872          << " / count = " << nb_copies << std::endl;
4873#endif
4874      }
4875      break;
4876    }
4877    /////////////
4878    case CAS_WAIT:   // release all locks and retry from beginning
4879    {
4880
4881#if DEBUG_MEMC_CAS
4882      if(m_debug_cas_fsm)
4883      {
4884        std::cout << "  <MEMC " << name()
4885                  << " CAS_WAIT> Release all locks" << std::endl;
4886      }
4887#endif
4888      r_cas_fsm = CAS_DIR_REQ;
4889      break;
4890    }
4891    //////////////////
4892    case CAS_UPT_HEAP_LOCK:  // lock the heap
4893    {
4894      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4895      {
4896
4897#if DEBUG_MEMC_CAS
4898        if(m_debug_cas_fsm)
4899        {
4900          std::cout << "  <MEMC " << name()
4901                    << " CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4902        }
4903#endif
4904        r_cas_fsm = CAS_UPT_REQ;
4905      }
4906      break;
4907    }
4908    ////////////////
4909    case CAS_UPT_REQ:  // send a first update request to CC_SEND FSM
4910    {
4911      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4912             "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4913
4914      if(!r_cas_to_cc_send_multi_req.read() && !r_cas_to_cc_send_brdcast_req.read())
4915      {
4916        r_cas_to_cc_send_brdcast_req  = false;
4917        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
4918        r_cas_to_cc_send_nline        = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
4919        r_cas_to_cc_send_index        = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
4920        r_cas_to_cc_send_wdata        = r_cas_wdata.read();
4921
4922        if(r_cas_cpt.read() == 4)
4923        {
4924          r_cas_to_cc_send_is_long    = true;
4925          r_cas_to_cc_send_wdata_high = m_cmd_cas_wdata_fifo.read();
4926        }
4927        else
4928        {
4929          r_cas_to_cc_send_is_long    = false;
4930          r_cas_to_cc_send_wdata_high = 0;
4931        }
4932
4933        // We put the first copy in the fifo
4934        cas_to_cc_send_fifo_put     = true;
4935        cas_to_cc_send_fifo_inst    = r_cas_copy_inst.read();
4936        cas_to_cc_send_fifo_srcid   = r_cas_copy.read();
4937#if L1_MULTI_CACHE
4938        cas_to_cc_send_fifo_cache_id= r_cas_copy_cache.read();
4939#endif
4940        if(r_cas_count.read() == 1)  // one single copy
4941        {
4942          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4943          // update responses
4944          cmd_cas_fifo_get            = true;
4945          r_cas_to_cc_send_multi_req = true;
4946          r_cas_cpt = 0;
4947        }
4948        else      // several copies
4949        {
4950          r_cas_fsm = CAS_UPT_NEXT;
4951        }
4952
4953#if DEBUG_MEMC_CAS
4954        if(m_debug_cas_fsm)
4955        {
4956          std::cout << "  <MEMC " << name() << " CAS_UPT_REQ> Send the first update request to CC_SEND FSM "
4957                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4958                    << " / wdata = " << std::hex << r_cas_wdata.read()
4959                    << " / srcid = " << std::dec << r_cas_copy.read()
4960                    << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
4961        }
4962#endif
4963      }
4964      break;
4965    }
4966    /////////////////
4967    case CAS_UPT_NEXT:     // send a multi-update request to CC_SEND FSM
4968    {
4969      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4970             and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4971
4972      HeapEntry entry = m_heap.read(r_cas_ptr.read());
4973      cas_to_cc_send_fifo_srcid    = entry.owner.srcid;
4974#if L1_MULTI_CACHE
4975      cas_to_cc_send_fifo_cache_id = entry.owner.cache_id;
4976#endif
4977      cas_to_cc_send_fifo_inst     = entry.owner.inst;
4978      cas_to_cc_send_fifo_put = true;
4979
4980      if(m_cas_to_cc_send_inst_fifo.wok())   // request accepted by CC_SEND FSM
4981      {
4982        r_cas_ptr = entry.next;
4983        if(entry.next == r_cas_ptr.read())    // last copy
4984        {
4985          r_cas_to_cc_send_multi_req = true;
4986          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4987          // all update responses
4988          cmd_cas_fifo_get = true;
4989          r_cas_cpt        = 0;
4990        }
4991      }
4992
4993#if DEBUG_MEMC_CAS
4994      if(m_debug_cas_fsm)
4995      {
4996        std::cout << "  <MEMC " << name() << " CAS_UPT_NEXT> Send the next update request to CC_SEND FSM "
4997                  << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4998                  << " / wdata = " << std::hex << r_cas_wdata.read()
4999                  << " / srcid = " << std::dec << entry.owner.srcid
5000                  << " / inst = " << std::dec << entry.owner.inst << std::endl;
5001      }
5002#endif
5003      break;
5004    }
5005    /////////////////////
5006    case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
5007    {
5008      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5009      {
5010        if(!r_cas_to_ixr_cmd_req)    // we can transfer the request to IXR_CMD FSM
5011        {
5012          // fill the data buffer
5013          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
5014          for(size_t i = 0; i<m_words; i++)
5015          {
5016            if(i == word)
5017            {
5018              r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
5019            }
5020            else if((i == word+1) && (r_cas_cpt.read() == 4))   // 64 bit CAS
5021            {
5022              r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
5023            }
5024            else
5025            {
5026              r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
5027            }
5028          }
5029          size_t wok_index = 0;
5030          bool   wok       = !m_trt.full(wok_index);
5031          if(wok)
5032          {
5033            r_cas_trt_index = wok_index;
5034            r_cas_fsm       = CAS_BC_UPT_LOCK;
5035          }
5036          else
5037          {
5038            r_cas_fsm       = CAS_WAIT;
5039          }
5040        }
5041        else
5042        {
5043          r_cas_fsm = CAS_WAIT;
5044        }
5045      }
5046      break;
5047    }
5048    /////////////////////
5049    case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
5050                           // write data in cache in case of successful registration
5051    {
5052      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
5053      {
5054        bool        wok       = false;
5055        size_t      index     = 0;
5056        size_t      srcid     = m_cmd_cas_srcid_fifo.read();
5057        size_t      trdid     = m_cmd_cas_trdid_fifo.read();
5058        size_t      pktid     = m_cmd_cas_pktid_fifo.read();
5059        addr_t      nline     = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5060        size_t      nb_copies = r_cas_count.read();
5061
5062        // register a broadcast inval transaction in UPT
5063        wok = m_upt.set(false,  // it's an inval transaction
5064                               true,    // it's a broadcast
5065                               true,    // it needs a response
5066                               srcid,
5067                               trdid,
5068                               pktid,
5069                               nline,
5070                               nb_copies,
5071                               index);
5072
5073        if(wok)     // UPT not full
5074        {
5075          // cache update
5076          size_t way  = r_cas_way.read();
5077          size_t set  = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
5078          size_t word = m_x[(addr_t)(m_cmd_cas_addr_fifo.read())];
5079
5080          m_cache_data.write(way, set, word, r_cas_wdata.read());
5081          if(r_cas_cpt.read() ==4)
5082            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
5083
5084          // monitor
5085          if(m_monitor_ok)
5086          {
5087            addr_t address = m_cmd_cas_addr_fifo.read();
5088            char buf[80];
5089            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", 
5090                     (int)m_cmd_cas_srcid_fifo.read());
5091            check_monitor(buf, address, r_cas_wdata.read(), false);
5092            if(r_cas_cpt.read() ==4)
5093              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read(), false);
5094          }
5095          r_cas_upt_index = index;
5096          r_cas_fsm = CAS_BC_DIR_INVAL;
5097
5098#if DEBUG_MEMC_CAS
5099if(m_debug_cas_fsm)
5100std::cout << "  <MEMC " << name() 
5101          << " CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
5102          << " / nline = " << std::hex << nline
5103          << " / count = " << std::dec << nb_copies
5104          << " / upt_index = " << index << std::endl;
5105#endif
5106        }
5107        else      //  releases the lock protecting UPT
5108        {
5109          r_cas_fsm = CAS_WAIT;
5110        }
5111      }
5112      break;
5113    }
5114    //////////////////////
5115    case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
5116    {
5117      if((r_alloc_trt_fsm.read() == ALLOC_TRT_CAS) &&
5118          (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS) &&
5119          (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS))
5120      {
5121        // set TRT
5122        m_trt.set(r_cas_trt_index.read(),
5123                              false,    // PUT request to XRAM
5124                              m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())],
5125                              0,
5126                              0,
5127                              0,
5128                              false,    // not a processor read
5129                              0,
5130                              0,
5131                              std::vector<be_t> (m_words,0),
5132                              std::vector<data_t> (m_words,0));
5133
5134        // invalidate directory entry
5135        DirectoryEntry entry;
5136        entry.valid         = false;
5137        entry.dirty         = false;
5138        entry.tag         = 0;
5139        entry.is_cnt        = false;
5140        entry.lock          = false;
5141        entry.count         = 0;
5142        entry.owner.srcid   = 0;
5143#if L1_MULTI_CACHE
5144        entry.owner.cache_id= 0;
5145#endif
5146        entry.owner.inst    = false;
5147        entry.ptr           = 0;
5148        size_t set          = m_y[(addr_t)(m_cmd_cas_addr_fifo.read())];
5149        size_t way          = r_cas_way.read();
5150        m_cache_directory.write(set, way, entry);
5151
5152        r_cas_fsm = CAS_BC_CC_SEND;
5153
5154#if DEBUG_MEMC_CAS
5155if(m_debug_cas_fsm)
5156std::cout << "  <MEMC " << name() 
5157          << " CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
5158          << " / nline = " << std::hex << m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())]
5159          << " / set = " << std::dec << set << " / way = " << way << std::endl;
5160#endif
5161      }
5162      else
5163      {
5164        assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
5165      }
5166      break;
5167    }
5168    ///////////////////
5169    case CAS_BC_CC_SEND:  // Request the broadcast inval to CC_SEND FSM
5170    {
5171      if(!r_cas_to_cc_send_multi_req.read() &&
5172          !r_cas_to_cc_send_brdcast_req.read())
5173      {
5174        r_cas_to_cc_send_multi_req    = false;
5175        r_cas_to_cc_send_brdcast_req  = true;
5176        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
5177        r_cas_to_cc_send_nline        = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5178        r_cas_to_cc_send_index        = 0;
5179        r_cas_to_cc_send_wdata        = 0;
5180
5181        r_cas_fsm = CAS_BC_XRAM_REQ;
5182      }
5183      break;
5184    }
5185    ////////////////////
5186    case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
5187    {
5188      if(!r_cas_to_ixr_cmd_req)
5189      {
5190        r_cas_to_ixr_cmd_req     = true;
5191        r_cas_to_ixr_cmd_write   = true;
5192        r_cas_to_ixr_cmd_nline   = m_nline[(addr_t)(m_cmd_cas_addr_fifo.read())];
5193        r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
5194        r_cas_fsm                = CAS_IDLE;
5195        cmd_cas_fifo_get         = true;
5196        r_cas_cpt                = 0;
5197
5198#if DEBUG_MEMC_CAS
5199if(m_debug_cas_fsm)
5200std::cout << "  <MEMC " << name() 
5201          << " CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
5202          << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5203          << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5204#endif
5205      }
5206      else
5207      {
5208        std::cout << "ERROR in MEM_CACHE / CAS_BC_XRAM_REQ state" 
5209                  << " : request should not have been previously set" << std::endl;
5210      }
5211      break;
5212    }
5213    /////////////////
5214    case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
5215    {
5216      if(!r_cas_to_tgt_rsp_req)
5217      {
5218        cmd_cas_fifo_get     = true;
5219        r_cas_cpt              = 0;
5220        r_cas_to_tgt_rsp_req = true;
5221        r_cas_to_tgt_rsp_data  = 1;
5222        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5223        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5224        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5225        r_cas_fsm              = CAS_IDLE;
5226
5227#if DEBUG_MEMC_CAS
5228if(m_debug_cas_fsm)
5229std::cout << "  <MEMC " << name() 
5230          << " CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
5231#endif
5232      }
5233      break;
5234    }
5235    ////////////////////
5236    case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
5237    {
5238      if(!r_cas_to_tgt_rsp_req)
5239      {
5240        cmd_cas_fifo_get       = true;
5241        r_cas_cpt              = 0;
5242        r_cas_to_tgt_rsp_req = true;
5243        r_cas_to_tgt_rsp_data  = 0;
5244        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5245        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5246        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5247        r_cas_fsm              = CAS_IDLE;
5248
5249#if DEBUG_MEMC_CAS
5250if(m_debug_cas_fsm)
5251std::cout << "  <MEMC " << name() 
5252          << " CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
5253#endif
5254      }
5255      break;
5256    }
5257    /////////////////////
5258    case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
5259    {
5260      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5261      {
5262        size_t   index = 0;
5263        bool hit_read = m_trt.hit_read(
5264                          m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],index);
5265        bool hit_write = m_trt.hit_write(
5266                           m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]);
5267        bool wok = !m_trt.full(index);
5268
5269#if DEBUG_MEMC_CAS
5270        if(m_debug_cas_fsm)
5271        {
5272          std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_LOCK> Check TRT state"
5273                    << " / hit_read = "  << hit_read
5274                    << " / hit_write = " << hit_write
5275                    << " / wok = " << wok
5276                    << " / index = " << index << std::endl;
5277        }
5278#endif
5279
5280        if(hit_read || !wok || hit_write)    // missing line already requested or no space in TRT
5281        {
5282          r_cas_fsm = CAS_WAIT;
5283        }
5284        else
5285        {
5286          r_cas_trt_index = index;
5287          r_cas_fsm       = CAS_MISS_TRT_SET;
5288        }
5289      }
5290      break;
5291    }
5292    ////////////////////
5293    case CAS_MISS_TRT_SET: // register the GET transaction in TRT
5294    {
5295      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5296      {
5297        std::vector<be_t> be_vector;
5298        std::vector<data_t> data_vector;
5299        be_vector.clear();
5300        data_vector.clear();
5301        for(size_t i=0; i<m_words; i++)
5302        {
5303          be_vector.push_back(0);
5304          data_vector.push_back(0);
5305        }
5306
5307        m_trt.set(r_cas_trt_index.read(),
5308                              true,   // read request
5309                              m_nline[(addr_t) m_cmd_cas_addr_fifo.read()],
5310                              m_cmd_cas_srcid_fifo.read(),
5311                              m_cmd_cas_trdid_fifo.read(),
5312                              m_cmd_cas_pktid_fifo.read(),
5313                              false,    // write request from processor
5314                              0,
5315                              0,
5316                              be_vector,
5317                              data_vector);
5318        r_cas_fsm = CAS_MISS_XRAM_REQ;
5319
5320#if DEBUG_MEMC_CAS
5321        if(m_debug_cas_fsm)
5322        {
5323          std::cout << "  <MEMC " << name() << " CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
5324                    << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5325                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5326        }
5327#endif
5328      }
5329      break;
5330    }
5331    //////////////////////
5332    case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
5333    {
5334      if(!r_cas_to_ixr_cmd_req)
5335      {
5336        r_cas_to_ixr_cmd_req        = true;
5337        r_cas_to_ixr_cmd_write      = false;
5338        r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
5339        r_cas_to_ixr_cmd_nline      = m_nline[(addr_t) m_cmd_cas_addr_fifo.read()];
5340        r_cas_fsm                   = CAS_WAIT;
5341
5342#if DEBUG_MEMC_CAS
5343        if(m_debug_cas_fsm)
5344        {
5345          std::cout << "  <MEMC " << name() << " CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
5346                    << " / nline = " << m_nline[(addr_t) m_cmd_cas_addr_fifo.read()]
5347                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5348        }
5349#endif
5350      }
5351      break;
5352    }
5353  } // end switch r_cas_fsm
5354
5355
5356  //////////////////////////////////////////////////////////////////////////////
5357  //    CC_SEND FSM
5358  //////////////////////////////////////////////////////////////////////////////
5359  // The CC_SEND fsm controls the DSPIN initiator port on the coherence
5360  // network, used to update or invalidate cache lines in L1 caches.
5361  //
5362  // This fsm is used also to acknowledge CLEANUP a command after request from
5363  // the CLEANUP fsm.
5364  //
5365  // It implements a round-robin priority between the four possible client FSMs
5366  // XRAM_RSP, WRITE, CAS and CLEANUP. Each FSM can request the next services:
5367  // - r_xram_rsp_to_cc_send_multi_req : multi-inval
5368  //   r_xram_rsp_to_cc_send_brdcast_req : broadcast-inval
5369  // - r_write_to_cc_send_multi_req : multi-update
5370  //   r_write_to_cc_send_brdcast_req : broadcast-inval
5371  // - r_cas_to_cc_send_multi_req : multi-update
5372  //   r_cas_to_cc_send_brdcast_req : broadcast-inval
5373  // - r_cleanup_to_cc_send_req : cleanup acknowledgement
5374  //
5375  // An inval request is a double DSPIN flit command containing:
5376  // 1. the index of the line to be invalidated.
5377  //
5378  // An update request is a multi-flit DSPIN command containing:
5379  // 1. the index of the cache line to be updated.
5380  // 2. the index of the first modified word in the line.
5381  // 3. the data to update
5382  ///////////////////////////////////////////////////////////////////////////////
5383
5384  switch(r_cc_send_fsm.read())
5385  {
5386    case CC_SEND_WRITE_IDLE:
5387      {
5388        // XRAM_RSP FSM has highest priority
5389        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5390            r_xram_rsp_to_cc_send_multi_req.read())
5391        {
5392          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5393          m_cpt_inval++;
5394          break;
5395        }
5396
5397        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5398        {
5399          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5400          m_cpt_inval++;
5401          break;
5402        }
5403
5404        if(m_cas_to_cc_send_inst_fifo.rok() ||
5405            r_cas_to_cc_send_multi_req.read())
5406        {
5407          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5408          m_cpt_update++;
5409          break;
5410        }
5411
5412        if(r_cas_to_cc_send_brdcast_req.read())
5413        {
5414          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5415          m_cpt_inval++;
5416          break;
5417        }
5418
5419        if (r_cleanup_to_cc_send_req.read())
5420        {
5421          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5422          break;
5423        }
5424
5425        if(m_write_to_cc_send_inst_fifo.rok() ||
5426            r_write_to_cc_send_multi_req.read())
5427        {
5428          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5429          m_cpt_update++;
5430          break;
5431        }
5432
5433        if(r_write_to_cc_send_brdcast_req.read())
5434        {
5435          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5436          m_cpt_inval++;
5437        }
5438        break;
5439      }
5440
5441    case CC_SEND_XRAM_RSP_IDLE:
5442      {
5443        // CAS FSM has highest priority
5444        if(m_cas_to_cc_send_inst_fifo.rok() ||
5445            r_cas_to_cc_send_multi_req.read())
5446        {
5447          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5448          m_cpt_update++;
5449          break;
5450        }
5451
5452        if(r_cas_to_cc_send_brdcast_req.read())
5453        {
5454          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5455          m_cpt_inval++;
5456          break;
5457        }
5458
5459        if(r_cleanup_to_cc_send_req.read())
5460        {
5461          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5462          break;
5463        }
5464
5465        if(m_write_to_cc_send_inst_fifo.rok() ||
5466            r_write_to_cc_send_multi_req.read())
5467        {
5468          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5469          m_cpt_update++;
5470          break;
5471        }
5472
5473        if(r_write_to_cc_send_brdcast_req.read())
5474        {
5475          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5476          m_cpt_inval++;
5477          break;
5478        }
5479
5480        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5481            r_xram_rsp_to_cc_send_multi_req.read())
5482        {
5483          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5484          m_cpt_inval++;
5485          break;
5486        }
5487
5488        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5489        {
5490          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5491          m_cpt_inval++;
5492        }
5493
5494        break;
5495      }
5496
5497    case CC_SEND_CAS_IDLE:
5498      {
5499        // CLEANUP FSM has highest priority
5500        if(r_cleanup_to_cc_send_req.read())
5501        {
5502          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5503          break;
5504        }
5505
5506        if(m_write_to_cc_send_inst_fifo.rok() ||
5507            r_write_to_cc_send_multi_req.read())
5508        {
5509          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5510          m_cpt_update++;
5511          break;
5512        }
5513
5514        if(r_write_to_cc_send_brdcast_req.read())
5515        {
5516          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5517          m_cpt_inval++;
5518          break;
5519        }
5520
5521        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5522            r_xram_rsp_to_cc_send_multi_req.read())
5523        {
5524          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5525          m_cpt_inval++;
5526          break;
5527        }
5528
5529        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5530        {
5531          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5532          m_cpt_inval++;
5533          break;
5534        }
5535
5536        if(m_cas_to_cc_send_inst_fifo.rok() ||
5537            r_cas_to_cc_send_multi_req.read())
5538        {
5539          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5540          m_cpt_update++;
5541          break;
5542        }
5543
5544        if(r_cas_to_cc_send_brdcast_req.read())
5545        {
5546          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5547          m_cpt_inval++;
5548        }
5549        break;
5550      }
5551
5552    case CC_SEND_CLEANUP_IDLE:
5553      {
5554        // WRITE FSM has highest priority
5555        if(m_write_to_cc_send_inst_fifo.rok() ||
5556            r_write_to_cc_send_multi_req.read())
5557        {
5558          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5559          m_cpt_update++;
5560          break;
5561        }
5562
5563        if(r_write_to_cc_send_brdcast_req.read())
5564        {
5565          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5566          m_cpt_inval++;
5567          break;
5568        }
5569
5570        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5571            r_xram_rsp_to_cc_send_multi_req.read())
5572        {
5573          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5574          m_cpt_inval++;
5575          break;
5576        }
5577
5578        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5579        {
5580          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5581          m_cpt_inval++;
5582          break;
5583        }
5584
5585        if(m_cas_to_cc_send_inst_fifo.rok() ||
5586            r_cas_to_cc_send_multi_req.read())
5587        {
5588          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5589          m_cpt_update++;
5590          break;
5591        }
5592
5593        if(r_cas_to_cc_send_brdcast_req.read())
5594        {
5595          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5596          m_cpt_inval++;
5597          break;
5598        }
5599
5600        if(r_cleanup_to_cc_send_req.read())
5601        {
5602          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5603        }
5604
5605        break;
5606      }
5607
5608    case CC_SEND_CLEANUP_ACK:
5609      {
5610        // send only flit for a cleanup acknowledgement (from CLEANUP FSM)
5611        if(not p_dspin_out.read) break;
5612
5613        r_cleanup_to_cc_send_req = false;
5614        r_cc_send_fsm = CC_SEND_CLEANUP_IDLE;
5615
5616#if DEBUG_MEMC_CC_SEND
5617if(m_debug_cc_send_fsm)
5618std::cout << "  <MEMC " << name() 
5619          << " CC_SEND_CLEANUP_ACK> Cleanup Ack for srcid "
5620          << std::hex << r_cleanup_to_cc_send_srcid.read() << std::endl;
5621#endif
5622        break;
5623      }
5624
5625    case CC_SEND_XRAM_RSP_INVAL_HEADER:
5626      {
5627        // send first flit multi-inval (from XRAM_RSP FSM)
5628        if(m_xram_rsp_to_cc_send_inst_fifo.rok())
5629        {
5630          if(not p_dspin_out.read) break;
5631
5632          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_NLINE;
5633          break;
5634        }
5635
5636        if(r_xram_rsp_to_cc_send_multi_req.read())
5637        {
5638          r_xram_rsp_to_cc_send_multi_req = false;
5639        }
5640
5641        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5642        break;
5643      }
5644
5645    case CC_SEND_XRAM_RSP_INVAL_NLINE:
5646      {
5647        // send second flit multi-inval (from XRAM_RSP FSM)
5648        if(not p_dspin_out.read) break;
5649
5650        m_cpt_inval_mult++;
5651
5652        xram_rsp_to_cc_send_fifo_get = true;
5653        r_cc_send_fsm                = CC_SEND_XRAM_RSP_INVAL_HEADER;
5654
5655#if DEBUG_MEMC_CC_SEND
5656if(m_debug_cc_send_fsm)
5657std::cout << "  <MEMC " << name() 
5658          << " CC_SEND_XRAM_RSP_INVAL_NLINE> BC-Inval for line "
5659          << std::hex << r_xram_rsp_to_cc_send_nline.read() << std::endl;
5660#endif
5661        break;
5662      }
5663
5664    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
5665      {
5666        // send first flit broadcast-inval (from XRAM_RSP FSM)
5667        if(not p_dspin_out.read) break;
5668
5669        r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_NLINE;
5670        break;
5671      }
5672
5673    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
5674      {
5675        // send second flit broadcast-inval (from XRAM_RSP FSM)
5676        if(not p_dspin_out.read) break;
5677
5678        m_cpt_inval_brdcast++;
5679
5680        r_xram_rsp_to_cc_send_brdcast_req = false;
5681        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5682
5683#if DEBUG_MEMC_CC_SEND
5684if(m_debug_cc_send_fsm)
5685std::cout << "  <MEMC " << name() 
5686          << " CC_SEND_XRAM_RSP_BRDCAST_NLINE> BC-Inval for line "
5687          << std::hex << r_xram_rsp_to_cc_send_nline.read() << std::endl;
5688#endif
5689        break;
5690      }
5691
5692    case CC_SEND_WRITE_BRDCAST_HEADER:
5693      {
5694        // send first flit broadcast-inval (from WRITE FSM)
5695        if(not p_dspin_out.read) break;
5696
5697        r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_NLINE;
5698        break;
5699      }
5700
5701    case CC_SEND_WRITE_BRDCAST_NLINE:
5702      {
5703        // send second flit broadcast-inval (from WRITE FSM)
5704        if(not p_dspin_out.read) break;
5705
5706        m_cpt_inval_brdcast++;
5707
5708        r_write_to_cc_send_brdcast_req = false;
5709        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5710
5711#if DEBUG_MEMC_CC_SEND
5712if(m_debug_cc_send_fsm)
5713std::cout << "  <MEMC " << name()
5714          << " CC_SEND_WRITE_BRDCAST_NLINE> BC-Inval for line "
5715          << std::hex << r_write_to_cc_send_nline.read() << std::endl;
5716#endif
5717        break;
5718      }
5719
5720    case CC_SEND_WRITE_UPDT_HEADER:
5721      {
5722        // send first flit for a multi-update (from WRITE FSM)
5723        if(m_write_to_cc_send_inst_fifo.rok())
5724        {
5725          if(not p_dspin_out.read) break;
5726
5727          r_cc_send_fsm = CC_SEND_WRITE_UPDT_NLINE;
5728          break;
5729        }
5730
5731        if(r_write_to_cc_send_multi_req.read())
5732        {
5733          r_write_to_cc_send_multi_req = false;
5734        }
5735
5736        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5737        break;
5738      }
5739
5740    case CC_SEND_WRITE_UPDT_NLINE:
5741      {
5742        // send second flit for a multi-update (from WRITE FSM)
5743        if(not p_dspin_out.read) break;
5744
5745        m_cpt_update_mult++;
5746
5747        r_cc_send_cpt = 0;
5748        r_cc_send_fsm = CC_SEND_WRITE_UPDT_DATA;
5749
5750#if DEBUG_MEMC_CC_SEND
5751        if(m_debug_cc_send_fsm)
5752        {
5753          std::cout
5754            << "  <MEMC " << name()
5755            << " CC_SEND_WRITE_UPDT_NLINE> Multicast-Update for line "
5756            << r_write_to_cc_send_nline.read()
5757            << std::endl;
5758        }
5759#endif
5760        break;
5761      }
5762
5763    case CC_SEND_WRITE_UPDT_DATA:
5764      {
5765        // send N data flits for a multi-update (from WRITE FSM)
5766        if(not p_dspin_out.read) break;
5767
5768        if(r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1))
5769        {
5770          write_to_cc_send_fifo_get = true;
5771          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5772          break;
5773        }
5774
5775        r_cc_send_cpt = r_cc_send_cpt.read() + 1;
5776        break;
5777      }
5778
5779    case CC_SEND_CAS_BRDCAST_HEADER:
5780      {
5781        // send first flit for a broadcast-inval (from CAS FSM)
5782        if(not p_dspin_out.read) break;
5783
5784        r_cc_send_fsm = CC_SEND_CAS_BRDCAST_NLINE;
5785        break;
5786      }
5787
5788    case CC_SEND_CAS_BRDCAST_NLINE:
5789      {
5790        // send second flit broadcast-inval (from CAS FSM)
5791        if(not p_dspin_out.read) break;
5792
5793        m_cpt_inval_brdcast++;
5794
5795        r_cas_to_cc_send_brdcast_req = false;
5796        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5797
5798#if DEBUG_MEMC_CC_SEND
5799        if(m_debug_cc_send_fsm)
5800        {
5801          std::cout
5802            << "  <MEMC " << name()
5803            << " CC_SEND_CAS_BRDCAST_NLINE> Broadcast-Inval for line "
5804            << r_cas_to_cc_send_nline.read()
5805            << std::endl;
5806        }
5807#endif
5808        break;
5809      }
5810
5811    case CC_SEND_CAS_UPDT_HEADER:
5812      {
5813        // send first flit for a multi-update (from CAS FSM)
5814        if(m_cas_to_cc_send_inst_fifo.rok())
5815        {
5816          if(not p_dspin_out.read) break;
5817
5818          r_cc_send_fsm = CC_SEND_CAS_UPDT_NLINE;
5819          break;
5820        }
5821
5822        // no more packets to send for the multi-update
5823        if(r_cas_to_cc_send_multi_req.read())
5824        {
5825          r_cas_to_cc_send_multi_req = false;
5826        }
5827
5828        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5829        break;
5830      }
5831
5832    case CC_SEND_CAS_UPDT_NLINE:
5833      {
5834        // send second flit for a multi-update (from CAS FSM)
5835        if(not p_dspin_out.read) break;
5836
5837        m_cpt_update_mult++;
5838
5839        r_cc_send_cpt = 0;
5840        r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA;
5841
5842#if DEBUG_MEMC_CC_SEND
5843        if(m_debug_cc_send_fsm)
5844        {
5845          std::cout
5846            << "  <MEMC " << name()
5847            << " CC_SEND_CAS_UPDT_NLINE> Multicast-Update for line "
5848            << r_cas_to_cc_send_nline.read()
5849            << std::endl;
5850        }
5851#endif
5852        break;
5853      }
5854
5855    case CC_SEND_CAS_UPDT_DATA:
5856      {
5857        // send first data for a multi-update (from CAS FSM)
5858        if(not p_dspin_out.read) break;
5859
5860        if(r_cas_to_cc_send_is_long.read())
5861        {
5862          r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA_HIGH;
5863          break;
5864        }
5865
5866        cas_to_cc_send_fifo_get = true;
5867        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5868        break;
5869      }
5870
5871    case CC_SEND_CAS_UPDT_DATA_HIGH:
5872      {
5873        // send second data for a multi-update (from CAS FSM)
5874        if(not p_dspin_out.read) break;
5875
5876        cas_to_cc_send_fifo_get = true;
5877        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5878        break;
5879      }
5880  }
5881  // end switch r_cc_send_fsm
5882
5883  //////////////////////////////////////////////////////////////////////////////
5884  //    CC_RECEIVE FSM
5885  //////////////////////////////////////////////////////////////////////////////
5886  // The CC_RECEIVE fsm controls the DSPIN target port on the coherence
5887  // network.
5888  ///////////////////////////////////////////////////////////////////////////////
5889
5890  switch(r_cc_receive_fsm.read())
5891  {
5892    /////////////////////
5893    case CC_RECEIVE_IDLE:
5894      {
5895        if(not p_dspin_in.write) break;
5896
5897        uint8_t type =
5898          DspinDhccpParam::dspin_get(
5899              p_dspin_in.data.read(),
5900              DspinDhccpParam::FROM_L1_TYPE);
5901
5902        if((type == DspinDhccpParam::TYPE_CLEANUP_DATA) ||
5903           (type == DspinDhccpParam::TYPE_CLEANUP_INST) )
5904        { 
5905          r_cc_receive_fsm = CC_RECEIVE_CLEANUP;
5906          break;
5907        }
5908       
5909        if(type == DspinDhccpParam::TYPE_MULTI_ACK)
5910        {
5911          r_cc_receive_fsm = CC_RECEIVE_MULTI_ACK;
5912          break;
5913        }
5914
5915        assert(
5916            false && 
5917            "VCI_MEM_CACHE ERROR: Illegal type in coherence request");
5918       
5919        break;
5920      }
5921    ////////////////////////
5922    case CC_RECEIVE_CLEANUP:  // write first CLEANUP flit in CC_RECEIVE to CLEANUP fifo
5923      {
5924        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
5925
5926        assert( not p_dspin_in.eop.read() and
5927        "VCI_MEM_CACHE ERROR in CC_RECEIVE : CLEANUP command must have two flits");
5928
5929        cc_receive_to_cleanup_fifo_put = true;
5930        r_cc_receive_fsm               = CC_RECEIVE_CLEANUP_EOP;
5931
5932        break;
5933      }
5934    ////////////////////////////
5935    case CC_RECEIVE_CLEANUP_EOP:  // write second CLEANUP flit in CC_RECEIVE to CLEANUP fifo
5936      {
5937        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
5938
5939        assert( p_dspin_in.eop.read() and
5940        "VCI_MEM_CACHE ERROR in CC_RECEIVE : CLEANUP command must have two flits");
5941
5942        cc_receive_to_cleanup_fifo_put = true;
5943        r_cc_receive_fsm               = CC_RECEIVE_IDLE;
5944
5945        break;
5946      }
5947
5948    //////////////////////////
5949    case CC_RECEIVE_MULTI_ACK:
5950      {
5951        // wait for a WOK in the CC_RECEIVE to MULTI_ACK fifo
5952        if(not p_dspin_in.write or not m_cc_receive_to_multi_ack_fifo.wok()) break;
5953
5954        assert( p_dspin_in.eop.read() and
5955        "VCI_MEM_CACHE ERROR in CC_RECEIVE : MULTI_ACK command must have one flit");
5956
5957        cc_receive_to_multi_ack_fifo_put  = true;
5958        r_cc_receive_fsm                  = CC_RECEIVE_IDLE;
5959        break;
5960      }
5961  }
5962  /////////////////////////////////////////////////////////////////////
5963  //    TGT_RSP FSM
5964  /////////////////////////////////////////////////////////////////////
5965  // The TGT_RSP fsm sends the responses on the VCI target port
5966  // with a round robin priority between six requests :
5967  // - r_read_to_tgt_rsp_req
5968  // - r_write_to_tgt_rsp_req
5969  // - r_cas_to_tgt_rsp_req
5970  // - r_cleanup_to_tgt_rsp_req
5971  // - r_xram_rsp_to_tgt_rsp_req
5972  // - r_multi_ack_to_tgt_rsp_req
5973  // The  ordering is :  read > write > cas > xram > init > cleanup
5974  /////////////////////////////////////////////////////////////////////
5975
5976  switch(r_tgt_rsp_fsm.read())
5977  {
5978    case TGT_RSP_READ_IDLE:
5979    { 
5980      // write requests have the highest priority
5981      if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5982      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5983      else if(r_xram_rsp_to_tgt_rsp_req)
5984      {
5985        r_tgt_rsp_fsm = TGT_RSP_XRAM;
5986        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5987      }
5988      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5989      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5990      else if(r_read_to_tgt_rsp_req)
5991      {
5992        r_tgt_rsp_fsm = TGT_RSP_READ;
5993        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5994      }
5995      break;
5996    }
5997    ////////////////////////
5998    case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
5999    {
6000      if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS;
6001      else if(r_xram_rsp_to_tgt_rsp_req)
6002      {
6003        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6004        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6005      }
6006      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6007      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6008      else if(r_read_to_tgt_rsp_req)
6009      {
6010        r_tgt_rsp_fsm = TGT_RSP_READ;
6011        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6012      }
6013
6014      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6015      break;
6016    }
6017    ///////////////////////
6018    case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
6019    {
6020      if(r_xram_rsp_to_tgt_rsp_req)
6021      {
6022        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6023        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6024      }
6025      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6026      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6027      else if(r_read_to_tgt_rsp_req)
6028      {
6029        r_tgt_rsp_fsm = TGT_RSP_READ;
6030        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6031      }
6032      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6033      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6034      break;
6035    }
6036    ///////////////////////
6037    case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
6038    {
6039
6040      if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6041      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6042      else if(r_read_to_tgt_rsp_req)
6043      {
6044        r_tgt_rsp_fsm = TGT_RSP_READ;
6045        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6046      }
6047      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6048      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6049      else if(r_xram_rsp_to_tgt_rsp_req)
6050      {
6051        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6052        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6053      }
6054      break;
6055    }
6056    ///////////////////////
6057    case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
6058    {
6059      if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6060      else if(r_read_to_tgt_rsp_req)
6061      {
6062        r_tgt_rsp_fsm = TGT_RSP_READ;
6063        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6064      }
6065      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6066      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6067      else if(r_xram_rsp_to_tgt_rsp_req)
6068      {
6069        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6070        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6071      }
6072      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT;
6073      break;
6074    }
6075    ///////////////////////
6076    case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
6077    {
6078      if(r_read_to_tgt_rsp_req)
6079      {
6080        r_tgt_rsp_fsm = TGT_RSP_READ;
6081        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6082      }
6083      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6084      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6085      else if(r_xram_rsp_to_tgt_rsp_req)
6086      {
6087        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6088        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6089      }
6090      else 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      break;
6093    }
6094    //////////////////
6095    case TGT_RSP_READ:    // send the response to a read
6096    {
6097      if ( p_vci_tgt.rspack )
6098      {
6099
6100#if DEBUG_MEMC_TGT_RSP
6101if( m_debug_tgt_rsp_fsm )
6102{
6103  std::cout
6104    << "  <MEMC " << name() << " TGT_RSP_READ> Read response"
6105    << " / rsrcid = " << std::hex << r_read_to_tgt_rsp_srcid.read()
6106    << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
6107    << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
6108    << " / rdata = " << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6109    << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6110}
6111#endif
6112 
6113        uint32_t last_word_idx = r_read_to_tgt_rsp_word.read() + r_read_to_tgt_rsp_length.read() - 1;
6114        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
6115        bool     is_ll         = ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
6116
6117        if ( (is_last_word and not is_ll) or (r_tgt_rsp_key_sent.read() and is_ll))
6118        {
6119          // Last word in case of READ or second flit in case if LL
6120          r_tgt_rsp_key_sent    = false;
6121          r_read_to_tgt_rsp_req = false;
6122          r_tgt_rsp_fsm         = TGT_RSP_READ_IDLE;
6123        }
6124        else
6125        {
6126          if (is_ll)
6127          {
6128            r_tgt_rsp_key_sent = true;                // Send second flit of ll
6129          }
6130          else
6131          {
6132            r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1; // Send next word of read
6133          }
6134        }
6135      }
6136      break;
6137    }
6138    //////////////////
6139    case TGT_RSP_WRITE:   // send the write acknowledge
6140    {
6141      if(p_vci_tgt.rspack)
6142      {
6143
6144#if DEBUG_MEMC_TGT_RSP
6145if(m_debug_tgt_rsp_fsm)
6146std::cout << "  <MEMC " << name() << " TGT_RSP_WRITE> Write response"
6147          << " / rsrcid = " << std::hex << r_write_to_tgt_rsp_srcid.read()
6148          << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
6149          << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
6150#endif
6151        r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
6152        r_write_to_tgt_rsp_req = false;
6153      }
6154      break;
6155    }
6156    ///////////////////
6157    case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
6158    {
6159      if(p_vci_tgt.rspack)
6160      {
6161
6162#if DEBUG_MEMC_TGT_RSP
6163if(m_debug_tgt_rsp_fsm)
6164std::cout << "  <MEMC " << name() << " TGT_RSP_CLEANUP> Cleanup response"
6165          << " / rsrcid = " << std::hex << r_cleanup_to_tgt_rsp_srcid.read()
6166          << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
6167          << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
6168#endif
6169        r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
6170        r_cleanup_to_tgt_rsp_req = false;
6171      }
6172      break;
6173    }
6174    //////////////////
6175    case TGT_RSP_CAS:    // send one atomic word response
6176    {
6177      if(p_vci_tgt.rspack)
6178      {
6179
6180#if DEBUG_MEMC_TGT_RSP
6181if(m_debug_tgt_rsp_fsm)
6182std::cout << "  <MEMC " << name() << " TGT_RSP_CAS> CAS response"
6183          << " / rsrcid = " << std::hex << r_cas_to_tgt_rsp_srcid.read()
6184          << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
6185          << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
6186#endif
6187        r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
6188        r_cas_to_tgt_rsp_req = false;
6189      }
6190      break;
6191    }
6192
6193    ///////////////////////
6194    case TGT_RSP_XRAM:    // send the response after XRAM access
6195    {
6196      if ( p_vci_tgt.rspack )
6197      {
6198
6199#if DEBUG_MEMC_TGT_RSP
6200if( m_debug_tgt_rsp_fsm )
6201std::cout << "  <MEMC " << name() << " TGT_RSP_XRAM> Response following XRAM access"
6202          << " / rsrcid = " << std::hex << r_xram_rsp_to_tgt_rsp_srcid.read()
6203          << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
6204          << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
6205          << " / rdata = " << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6206          << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6207#endif
6208        uint32_t last_word_idx = r_xram_rsp_to_tgt_rsp_word.read() + r_xram_rsp_to_tgt_rsp_length.read() - 1;
6209        bool     is_last_word  = (r_tgt_rsp_cpt.read() == last_word_idx);
6210        bool     is_ll         = ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL);
6211        bool     is_error      = r_xram_rsp_to_tgt_rsp_rerror.read();
6212
6213        if (((is_last_word or is_error) and not is_ll) or
6214             (r_tgt_rsp_key_sent.read() and     is_ll))
6215        {
6216          // Last word sent in case of READ or second flit sent in case if LL
6217          r_tgt_rsp_key_sent        = false;
6218          r_xram_rsp_to_tgt_rsp_req = false;
6219          r_tgt_rsp_fsm             = TGT_RSP_XRAM_IDLE;
6220        }
6221        else
6222        {
6223          if (is_ll)
6224          {
6225            r_tgt_rsp_key_sent = true;                     // Send second flit of ll
6226          }                                                                           
6227          else
6228          {
6229            r_tgt_rsp_cpt      = r_tgt_rsp_cpt.read() + 1; // Send next word of read
6230          }
6231        }
6232      }
6233      break;
6234    }
6235    //////////////////
6236    case TGT_RSP_INIT:    // send the write response after coherence transaction
6237    {
6238      if(p_vci_tgt.rspack)
6239      {
6240
6241#if DEBUG_MEMC_TGT_RSP
6242if(m_debug_tgt_rsp_fsm)
6243std::cout << "  <MEMC " << name() << " TGT_RSP_INIT> Write response after coherence transaction"
6244          << " / rsrcid = " << std::hex << r_multi_ack_to_tgt_rsp_srcid.read()
6245          << " / rtrdid = " << r_multi_ack_to_tgt_rsp_trdid.read()
6246          << " / rpktid = " << r_multi_ack_to_tgt_rsp_pktid.read() << std::endl;
6247#endif
6248        r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
6249        r_multi_ack_to_tgt_rsp_req = false;
6250      }
6251      break;
6252    }
6253  } // end switch tgt_rsp_fsm
6254
6255  ////////////////////////////////////////////////////////////////////////////////////
6256  //    ALLOC_UPT FSM
6257  ////////////////////////////////////////////////////////////////////////////////////
6258  // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
6259  // with a round robin priority between three FSMs : MULTI_ACK > WRITE > XRAM_RSP > CLEANUP
6260  // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
6261  // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
6262  // - The MULTI_ACK FSM complete those trasactions and erase the UPT entry.
6263  // - The CLEANUP  FSM decrement an entry in UPT.
6264  // The resource is always allocated.
6265  /////////////////////////////////////////////////////////////////////////////////////
6266
6267  switch(r_alloc_upt_fsm.read())
6268  {
6269
6270      ////////////////////////
6271    case ALLOC_UPT_MULTI_ACK:
6272      if((r_multi_ack_fsm.read() != MULTI_ACK_UPT_LOCK) &&
6273          (r_multi_ack_fsm.read() != MULTI_ACK_UPT_CLEAR))
6274      {
6275        if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
6276            (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
6277          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
6278
6279        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6280          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6281
6282        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6283          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6284
6285        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6286                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6287          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6288      }
6289      break;
6290
6291      /////////////////////
6292    case ALLOC_UPT_WRITE:
6293      if((r_write_fsm.read() != WRITE_UPT_LOCK) &&
6294          (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
6295      {
6296        if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6297          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6298
6299        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6300          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6301
6302        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6303                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6304          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6305
6306        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
6307          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
6308      }
6309      break;
6310
6311      ////////////////////////
6312    case ALLOC_UPT_XRAM_RSP:
6313      if(r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
6314      {