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

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

Introducing missing debug strings in the vci_mem_cache cpp file

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