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

Last change on this file since 319 was 319, checked in by cfuguet, 11 years ago

Fix bug in vci_mem_cache_dspin_coherence. The write signal
in the dspin port must depend on the rok of clients fifos when
in state HEADER of multicast update or invalidate

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