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

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

ntroducing support for 40 bits physical addresses.

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