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

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

Added llsc table initialization in both vci_mem_cache and vci_mem_cache_dspin_coherence components'reset

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