source: branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 351

Last change on this file since 351 was 351, checked in by joannou, 11 years ago

Got rid of intermediate v5 version. _dspin_coherence versions changed to main version for v5. Changed components names and platforms to fit the new names

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