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

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

Erasing always false condition in the if statement of the
WRITE_UPT_REQ state.

In this state the r_write_count register, is always bigger than 0.

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