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

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