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

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

Bug fix in the vci_cc_vcache_wrapper and vci_mem_cache components
(and the corresponding dspin coherence versions)

vci_cc_vcache_wrapper:

In the VCI_CMD FSM of the cc_vcache, for the SC command as for the
CAS command, we must set the CONS bit in the VCI packet. In the
same manner we must unset the CONTIG bit in the VCI packet for these
two commands.
These two kind of commands have two flits with the same VCI address.

vci_mem_cache

In the state WRITE_DIR_REQ, we don't have to rewrite the registers
address or word index because they will be assigned with the correct
values in the WRITE_IDLE or WRITE_RSP states.

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