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

Last change on this file since 391 was 391, checked in by lambert, 11 years ago

Bug fix in Vci_mem_cache :

  • When line evicion in write fsm to IXR_CMD, second word should be shifted for 64 bits support
  • Fixing assert message for vci_param_ext, only support for cell_size = 8

Adding include in Vci_block_device_tsar to fix compiling problem

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