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

Last change on this file since 310 was 310, checked in by cfuguet, 12 years ago

Introducing FROM_L1_BC and FROM_MC_BC in dspin param class to
access the Broadcast bit in flit.
Replacing BROADCAST_BC by FROM_MC_BC in memory cache

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