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

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