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

Last change on this file since 331 was 331, checked in by joannou, 11 years ago

Renaming all files form vci_cc_vcache_wrapper_dspin_coherence and vci_mem_cache_dspin_coherence

File size: 249.0 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 << 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      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      // The matching copy is in the heap, but is not the first copy
4167      // The directory entry must be modified to decrement count
4168      else
4169      {
4170        dir_entry.ptr            = r_cleanup_ptr.read();
4171        dir_entry.owner.srcid    = r_cleanup_copy.read();
4172        dir_entry.owner.inst     = r_cleanup_copy_inst.read();
4173
4174#if L1_MULTI_CACHE
4175        dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
4176#endif
4177
4178        r_cleanup_next_ptr       = heap_entry.next;
4179        r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
4180      }
4181
4182      m_cache_directory.write(set,way,dir_entry);
4183
4184#if DEBUG_MEMC_CLEANUP
4185      if(m_debug_cleanup_fsm)
4186      {
4187        std::cout
4188            << "  <MEMC " << name()
4189            << ".CLEANUP_HEAP_LOCK> Checks matching:"
4190            << " address = "      << r_cleanup_nline.read() * m_words * 4
4191            << " / dir_id = "     << r_cleanup_copy.read()
4192            << " / dir_ins = "    << r_cleanup_copy_inst.read()
4193            << " / heap_id = "    << heap_entry.owner.srcid
4194            << " / heap_ins = "   << heap_entry.owner.inst
4195            << " / search_id = "  << r_cleanup_srcid.read()
4196            << " / search_ins = " << r_cleanup_inst.read()
4197            << std::endl;
4198      }
4199#endif
4200      break;
4201    }
4202
4203    case CLEANUP_HEAP_SEARCH:
4204    {
4205      // This state is handling the case where the copy
4206      // is in the heap, but is not the first in the linked list
4207      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4208      {
4209        std::cout
4210            << "VCI_MEM_CACHE ERROR " << name()
4211            << " CLEANUP_HEAP_SEARCH state"
4212            << " bad HEAP allocation" << std::endl;
4213
4214        exit(0);
4215      }
4216
4217      HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
4218
4219      bool last             = (heap_entry.next        == r_cleanup_next_ptr.read());
4220      bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4221      bool match_heap_inst  = (heap_entry.owner.inst  == r_cleanup_inst.read());
4222      bool match_heap       = match_heap_srcid && match_heap_inst;
4223
4224#if L1_MULTI_CACHE
4225      match_heap = match_heap and(heap_entry.owner.cache_id == r_cleanup_pktid.read());
4226#endif
4227
4228      if(not match_heap and last)
4229      {
4230        std::cout
4231            << "VCI_MEM_CACHE_ERROR " << name()
4232            << " CLEANUP_HEAP_SEARCH state"
4233            << " cleanup on valid line but copy not found"
4234            << std::endl;
4235
4236        exit(0);
4237      }
4238
4239      // the matching copy must be removed
4240      if(match_heap)
4241      {
4242        // re-use ressources
4243        r_cleanup_ptr = heap_entry.next;
4244        r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
4245      }
4246      // test the next in the linked list
4247      else
4248      {
4249        r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
4250        r_cleanup_prev_srcid    = heap_entry.owner.srcid;
4251        r_cleanup_prev_inst     = heap_entry.owner.inst;
4252        r_cleanup_next_ptr      = heap_entry.next;
4253
4254        r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
4255
4256#if L1_MULTI_CACHE
4257        r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4258#endif
4259      }
4260
4261#if DEBUG_MEMC_CLEANUP
4262      if(m_debug_cleanup_fsm)
4263      {
4264        if(not match_heap)
4265        {
4266          std::cout
4267              << "  <MEMC " << name()
4268              << ".CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
4269              << std::endl;
4270        }
4271        else
4272        {
4273          std::cout
4274              << "  <MEMC " << name()
4275              << ".CLEANUP_HEAP_SEARCH> Matching copy found:"
4276              << std::endl;
4277        }
4278
4279        std::cout
4280            << " address = "      << r_cleanup_nline.read() * m_words * 4
4281            << " / heap_id = "    << heap_entry.owner.srcid
4282            << " / heap_ins = "   << heap_entry.owner.inst
4283            << " / search_id = "  << r_cleanup_srcid.read()
4284            << " / search_ins = " << r_cleanup_inst.read()
4285            << " / last = "       << last
4286            << std::endl;
4287      }
4288#endif
4289      break;
4290    }
4291
4292    case CLEANUP_HEAP_CLEAN:
4293    {
4294      // remove a copy in the linked list
4295      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4296      {
4297        std::cout
4298            << "VCI_MEM_CACHE ERROR " << name()
4299            << " CLEANUP_HEAP_CLEAN state"
4300            << "Bad HEAP allocation"  << std::endl;
4301
4302        exit(0);
4303      }
4304
4305      HeapEntry heap_entry;
4306      heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4307      heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4308
4309#if L1_MULTI_CACHE
4310      heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4311#endif
4312
4313      bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
4314
4315      // this is the last entry of the list of copies
4316      if(last)
4317      {
4318        heap_entry.next = r_cleanup_prev_ptr.read();
4319      }
4320      // this is not the last entry
4321      else
4322      {
4323        heap_entry.next = r_cleanup_ptr.read();
4324      }
4325
4326      m_heap.write(r_cleanup_prev_ptr.read(), heap_entry);
4327
4328      r_cleanup_fsm = CLEANUP_HEAP_FREE;
4329
4330#if DEBUG_MEMC_CLEANUP
4331      if(m_debug_cleanup_fsm)
4332      {
4333        std::cout
4334            << "  <MEMC " << name()
4335            << ".CLEANUP_HEAP_SEARCH> Remove the copy in the linked list"
4336            << std::endl;
4337      }
4338#endif
4339      break;
4340    }
4341
4342    case CLEANUP_HEAP_FREE:
4343    {
4344      // The heap entry pointed by r_cleanup_next_ptr is freed
4345      // and becomes the head of the list of free entries
4346      if(r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP)
4347      {
4348        std::cout
4349            << "VCI_MEM_CACHE ERROR " << name()
4350            << " CLEANUP_HEAP_CLEAN state" << std::endl
4351            << "Bad HEAP allocation" << std::endl;
4352
4353        exit(0);
4354      }
4355
4356      HeapEntry heap_entry;
4357      heap_entry.owner.srcid    = 0;
4358      heap_entry.owner.inst     = false;
4359
4360#if L1_MULTI_CACHE
4361      heap_entry.owner.cache_id = 0;
4362#endif
4363
4364      if(m_heap.is_full())
4365      {
4366        heap_entry.next = r_cleanup_next_ptr.read();
4367      }
4368      else
4369      {
4370        heap_entry.next = m_heap.next_free_ptr();
4371      }
4372
4373      m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4374      m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4375      m_heap.unset_full();
4376
4377      r_cleanup_fsm = CLEANUP_SEND_ACK;
4378
4379#if DEBUG_MEMC_CLEANUP
4380      if(m_debug_cleanup_fsm)
4381      {
4382        std::cout
4383            << "  <MEMC " << name()
4384            << ".CLEANUP_HEAP_SEARCH> Update the list of free entries"
4385            << std::endl;
4386      }
4387#endif
4388      break;
4389    }
4390
4391    case CLEANUP_UPT_LOCK:
4392    {
4393      // search pending invalidate transaction matching the Cleanup NLINE in the UPDATE TABLE
4394      // get the lock in the UPDATE_TABLE
4395      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP) break;
4396
4397      size_t index = 0;
4398      bool   match_inval;
4399
4400      match_inval = m_update_tab.search_inval(r_cleanup_nline.read(), index);
4401
4402      // no pending inval
4403      if(not match_inval)
4404      {
4405        r_cleanup_fsm = CLEANUP_SEND_ACK;
4406
4407#if DEBUG_MEMC_CLEANUP
4408        if(m_debug_cleanup_fsm)
4409        {
4410          std::cout
4411              << "  <MEMC " << name()
4412              << ".CLEANUP_UPT_LOCK> Unexpected cleanup"
4413              << " with no corresponding UPT entry:"
4414              << " address = " << std::hex
4415              << (r_cleanup_nline.read() *4*m_words)
4416              << std::endl;
4417        }
4418#endif
4419        break;
4420      }
4421
4422      // pending inval
4423      r_cleanup_write_srcid    = m_update_tab.srcid(index);
4424      r_cleanup_write_trdid    = m_update_tab.trdid(index);
4425      r_cleanup_write_pktid    = m_update_tab.pktid(index);
4426      r_cleanup_write_need_rsp = m_update_tab.need_rsp(index);
4427      r_cleanup_index          = index;
4428
4429      r_cleanup_fsm         = CLEANUP_UPT_DECREMENT;
4430
4431#if DEBUG_MEMC_CLEANUP
4432      if(m_debug_cleanup_fsm)
4433      {
4434        std::cout
4435            << "  <MEMC " << name()
4436            << ".CLEANUP_UPT_LOCK> Cleanup matching pending"
4437            << " invalidate transaction on UPT:"
4438            << std::hex
4439            << " address = "   << r_cleanup_nline.read() * m_words * 4
4440            << " upt_entry = " << index
4441            << std::endl;
4442      }
4443#endif
4444      break;
4445    }
4446
4447    case CLEANUP_UPT_DECREMENT:
4448    {
4449      // decrement response counter in UPT matching entry
4450      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4451      {
4452        std::cout
4453            << "VCI_MEM_CACHE ERROR "         << name()
4454            << " CLEANUP_UPT_DECREMENT state" << std::endl
4455            << "Bad UPT allocation"
4456            << std::endl;
4457
4458        exit(0);
4459      }
4460
4461      size_t count = 0;
4462      m_update_tab.decrement(r_cleanup_index.read(), count);
4463
4464      // invalidation transaction finished
4465      // (all acknowledgements received)
4466      if(count == 0)
4467      {
4468        r_cleanup_fsm = CLEANUP_UPT_CLEAR;
4469      }
4470      // invalidation transaction not finished
4471      else
4472      {
4473        r_cleanup_fsm = CLEANUP_SEND_ACK ;
4474      }
4475
4476#if DEBUG_MEMC_CLEANUP
4477      if(m_debug_cleanup_fsm)
4478      {
4479        std::cout
4480            << "  <MEMC "      << name()
4481            << ".CLEANUP_UPT_DECREMENT> Decrement response counter in UPT:"
4482            << " UPT_index = " << r_cleanup_index.read()
4483            << " rsp_count = " << count
4484            << std::endl;
4485      }
4486#endif
4487      break;
4488    }
4489
4490    case CLEANUP_UPT_CLEAR:
4491    {
4492      // Clear UPT entry of finished invalidation transaction
4493      if(r_alloc_upt_fsm.read() != ALLOC_UPT_CLEANUP)
4494      {
4495        std::cout
4496            << "VCI_MEM_CACHE ERROR "     << name()
4497            << " CLEANUP_UPT_CLEAR state" << std::endl
4498            << "Bad UPT allocation"
4499            << std::endl;
4500
4501        exit(0);
4502      }
4503
4504      m_update_tab.clear(r_cleanup_index.read());
4505
4506      if(r_cleanup_write_need_rsp.read())
4507      {
4508        r_cleanup_fsm = CLEANUP_WRITE_RSP;
4509      }
4510      else
4511      {
4512        r_cleanup_fsm = CLEANUP_SEND_ACK;
4513      }
4514
4515#if DEBUG_MEMC_CLEANUP
4516      if(m_debug_cleanup_fsm)
4517      {
4518        std::cout
4519            << "  <MEMC "      << name()
4520            << ".CLEANUP_UPT_CLEAR> Clear entry in UPT:"
4521            << " UPT_index = " << r_cleanup_index.read()
4522            << std::endl;
4523      }
4524#endif
4525      break;
4526    }
4527
4528    case CLEANUP_WRITE_RSP:
4529    {
4530      // response to a previous write on the direct network
4531      // wait if pending request to the TGT_RSP FSM
4532      if(r_cleanup_to_tgt_rsp_req.read()) break;
4533
4534      // no pending request
4535      r_cleanup_to_tgt_rsp_req     = true;
4536      r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4537      r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4538      r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4539
4540      r_cleanup_fsm                = CLEANUP_SEND_ACK;
4541
4542#if DEBUG_MEMC_CLEANUP
4543      if(m_debug_cleanup_fsm)
4544      {
4545        std::cout
4546            << "  <MEMC " << name()
4547            << ".CLEANUP_WRITE_RSP> Send a response to a previous"
4548            << " write request waiting for coherence transaction completion: "
4549            << " rsrcid = "   << std::dec << r_cleanup_write_srcid.read()
4550            << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read()
4551            << std::endl;
4552      }
4553#endif
4554      break;
4555    }
4556
4557    case CLEANUP_SEND_ACK:
4558    {
4559      // acknowledgement to a cleanup command
4560      // on the coherence network (request to the CC_SEND FSM).
4561      // wait if pending request to the CC_SEND FSM
4562      if(r_cleanup_to_cc_send_req.read()) break;
4563
4564      r_cleanup_to_cc_send_req       = true;
4565      r_cleanup_to_cc_send_set_index = r_cleanup_nline.read() & 0xFFFF;
4566      r_cleanup_to_cc_send_way_index = r_cleanup_way_index.read();
4567      r_cleanup_to_cc_send_srcid     = r_cleanup_srcid.read();
4568      r_cleanup_to_cc_send_inst      = r_cleanup_inst.read();
4569
4570      r_cleanup_fsm = CLEANUP_IDLE;
4571
4572#if DEBUG_MEMC_CLEANUP
4573      if(m_debug_cleanup_fsm)
4574      {
4575        std::cout
4576            << "  <MEMC " << name()
4577            << ".CLEANUP_SEND_ACK> Send the response to a cleanup request:"
4578            << " srcid = " << std::dec << r_cleanup_srcid.read()
4579            << std::endl;
4580      }
4581#endif
4582      break;
4583    }
4584  } // end switch cleanup fsm
4585
4586  ////////////////////////////////////////////////////////////////////////////////////
4587  //    CAS FSM
4588  ////////////////////////////////////////////////////////////////////////////////////
4589  // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4590  // that are handled as "compare-and-swap instructions.
4591  //
4592  // This command contains two or four flits:
4593  // - In case of 32 bits atomic access, the first flit contains the value read
4594  // by a previous LL instruction, the second flit contains the value to be writen.
4595  // - In case of 64 bits atomic access, the 2 first flits contains the value read
4596  // by a previous LL instruction, the 2 next flits contains the value to be writen.
4597  //
4598  // The target address is cachable. If it is replicated in other L1 caches
4599  // than the writer, a coherence operation is done.
4600  //
4601  // It access the directory to check hit / miss.
4602  // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4603  // If a read transaction to the XRAM for this line already exists,
4604  // or if the transaction table is full, it goes to the WAIT state
4605  // to release the locks and try again. When the GET transaction has been
4606  // launched, it goes to the WAIT state and try again.
4607  // The CAS request is not consumed in the FIFO until a HIT is obtained.
4608  // - In case of hit...
4609  ///////////////////////////////////////////////////////////////////////////////////
4610
4611  switch(r_cas_fsm.read())
4612  {
4613      /////////////
4614    case CAS_IDLE:     // fill the local rdata buffers
4615    {
4616      if(m_cmd_cas_addr_fifo.rok())
4617      {
4618
4619#if DEBUG_MEMC_CAS
4620        if(m_debug_cas_fsm)
4621        {
4622          std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
4623                    << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4624                    << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4625                    << " wdata = " << m_cmd_cas_wdata_fifo.read()
4626                    << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4627                    << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4628        }
4629#endif
4630        if(m_cmd_cas_eop_fifo.read())
4631        {
4632          m_cpt_cas++;
4633          r_cas_fsm = CAS_DIR_REQ;
4634        }
4635        else  // we keep the last word in the FIFO
4636        {
4637          cmd_cas_fifo_get = true;
4638        }
4639        // We fill the two buffers
4640        if(r_cas_cpt.read() < 2)    // 32 bits access
4641          r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4642
4643        if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4644          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4645
4646        if(r_cas_cpt.read() >3)  // more than 4 flits...
4647        {
4648          std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4649                    << std::endl;
4650          exit(0);
4651        }
4652
4653        if(r_cas_cpt.read() ==2)
4654          r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4655
4656        r_cas_cpt = r_cas_cpt.read() +1;
4657      }
4658      break;
4659    }
4660
4661    /////////////////
4662    case CAS_DIR_REQ:
4663    {
4664      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4665      {
4666        r_cas_fsm = CAS_DIR_LOCK;
4667      }
4668
4669#if DEBUG_MEMC_CAS
4670      if(m_debug_cas_fsm)
4671      {
4672        std::cout
4673            << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
4674            << std::endl;
4675      }
4676#endif
4677      break;
4678    }
4679
4680    /////////////////
4681    case CAS_DIR_LOCK:  // Read the directory
4682    {
4683      if(r_alloc_dir_fsm.read() == ALLOC_DIR_CAS)
4684      {
4685        size_t way = 0;
4686        DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4687
4688        r_cas_is_cnt     = entry.is_cnt;
4689        r_cas_dirty      = entry.dirty;
4690        r_cas_tag        = entry.tag;
4691        r_cas_way        = way;
4692        r_cas_copy       = entry.owner.srcid;
4693#if L1_MULTI_CACHE
4694        r_cas_copy_cache = entry.owner.cache_id;
4695#endif
4696        r_cas_copy_inst  = entry.owner.inst;
4697        r_cas_ptr        = entry.ptr;
4698        r_cas_count      = entry.count;
4699
4700        if(entry.valid)  r_cas_fsm = CAS_DIR_HIT_READ;
4701        else             r_cas_fsm = CAS_MISS_TRT_LOCK;
4702
4703#if DEBUG_MEMC_CAS
4704        if(m_debug_cas_fsm)
4705        {
4706          std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
4707                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4708                    << " / hit = " << std::dec << entry.valid
4709                    << " / count = " << entry.count
4710                    << " / is_cnt = " << entry.is_cnt << std::endl;
4711        }
4712#endif
4713      }
4714      else
4715      {
4716        std::cout
4717            << "VCI_MEM_CACHE ERROR " << name()
4718            << " CAS_DIR_LOCK state" << std::endl
4719            << "Bad DIR allocation"   << std::endl;
4720
4721        exit(0);
4722      }
4723
4724      break;
4725    }
4726    /////////////////////
4727    case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4728                            // and check data change in cache
4729    {
4730      size_t way  = r_cas_way.read();
4731      size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4732
4733      // update directory (lock & dirty bits)
4734      DirectoryEntry entry;
4735      entry.valid          = true;
4736      entry.is_cnt         = r_cas_is_cnt.read();
4737      entry.dirty          = true;
4738      entry.lock           = true;
4739      entry.tag            = r_cas_tag.read();
4740      entry.owner.srcid    = r_cas_copy.read();
4741#if L1_MULTI_CACHE
4742      entry.owner.cache_id = r_cas_copy_cache.read();
4743#endif
4744      entry.owner.inst     = r_cas_copy_inst.read();
4745      entry.count          = r_cas_count.read();
4746      entry.ptr            = r_cas_ptr.read();
4747
4748      m_cache_directory.write(set, way, entry);
4749
4750      // Stored data from cache in buffer to do the comparison in next state
4751      m_cache_data.read_line(way, set, r_cas_data);
4752
4753      r_cas_fsm = CAS_DIR_HIT_COMPARE;
4754
4755#if DEBUG_MEMC_CAS
4756      if(m_debug_cas_fsm)
4757      {
4758        std::cout
4759          << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Read data from "
4760          << " cache and store it in buffer"
4761          << std::endl;
4762      }
4763#endif
4764      break;
4765    }
4766
4767    case CAS_DIR_HIT_COMPARE:
4768    {
4769      size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4770
4771      // Read data in buffer & check data change
4772      bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
4773
4774      if(r_cas_cpt.read() == 4)     // 64 bits CAS
4775        ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
4776
4777      // to avoid livelock, force the atomic access to fail pseudo-randomly
4778      bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
4779      r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
4780
4781      // cas success
4782      if(ok and not forced_fail)
4783      {
4784        r_cas_fsm = CAS_DIR_HIT_WRITE;
4785      }
4786      // cas failure
4787      else
4788      {
4789        r_cas_fsm = CAS_RSP_FAIL;
4790      }
4791
4792#if DEBUG_MEMC_CAS
4793      if(m_debug_cas_fsm)
4794      {
4795        std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_COMPARE> Compare the old"
4796                  << " and the new data"
4797                  << " / expected value = " << r_cas_rdata[0].read()
4798                  << " / actual value = "   << r_cas_data[word].read()
4799                  << " / forced_fail = "    << forced_fail << std::endl;
4800      }
4801#endif
4802      break;
4803    }
4804    //////////////////////
4805    case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4806      // write data in cache if no CC request
4807    {
4808      // The CAS is a success => sw access to the llsc_global_table
4809      m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
4810
4811      // test coherence request
4812      if(r_cas_count.read())   // replicated line
4813      {
4814        if(r_cas_is_cnt.read())
4815        {
4816          r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4817        }
4818        else if(!r_cas_to_cc_send_multi_req.read() &&
4819                !r_cas_to_cc_send_brdcast_req.read())
4820        {
4821          r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4822        }
4823        else
4824        {
4825          r_cas_fsm = CAS_WAIT;
4826        }
4827      }
4828      else                    // no copies
4829      {
4830        size_t way  = r_cas_way.read();
4831        size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4832        size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4833
4834        // cache update
4835        m_cache_data.write(way, set, word, r_cas_wdata.read());
4836        if(r_cas_cpt.read() == 4)
4837          m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4838
4839        r_cas_fsm = CAS_RSP_SUCCESS;
4840
4841        // monitor
4842        if(m_monitor_ok)
4843        {
4844          vci_addr_t address = m_cmd_cas_addr_fifo.read();
4845          char buf[80];
4846          snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4847          check_monitor(buf, address, r_cas_wdata.read());
4848
4849          if(r_cas_cpt.read() == 4)
4850            check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
4851        }
4852
4853#if DEBUG_MEMC_CAS
4854        if(m_debug_cas_fsm)
4855        {
4856          std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
4857                    << " way = " << std::dec << way
4858                    << " / set = " << set
4859                    << " / word = " << word
4860                    << " / value = " << r_cas_wdata.read()
4861                    << " / count = " << r_cas_count.read() << std::endl;
4862          std::cout << "  <MEMC "
4863                    << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
4864        }
4865#endif
4866      }
4867      break;
4868    }
4869    /////////////////
4870    case CAS_UPT_LOCK:  // try to register the transaction in UPT
4871      // and write data in cache if successful registration
4872      // releases locks to retry later if UPT full
4873    {
4874      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
4875      {
4876        bool        wok        = false;
4877        size_t      index      = 0;
4878        size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4879        size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4880        size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4881        addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4882        size_t      nb_copies  = r_cas_count.read();
4883
4884        wok = m_update_tab.set(true,  // it's an update transaction
4885                               false,   // it's not a broadcast
4886                               true,    // it needs a response
4887                               srcid,
4888                               trdid,
4889                               pktid,
4890                               nline,
4891                               nb_copies,
4892                               index);
4893        if(wok)   // coherence transaction registered in UPT
4894        {
4895          // cache update
4896          size_t way  = r_cas_way.read();
4897          size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4898          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4899
4900          m_cache_data.write(way, set, word, r_cas_wdata.read());
4901          if(r_cas_cpt.read() ==4)
4902            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4903
4904          r_cas_upt_index = index;
4905          r_cas_fsm = CAS_UPT_HEAP_LOCK;
4906
4907          // monitor
4908          if(m_monitor_ok)
4909          {
4910            vci_addr_t address = m_cmd_cas_addr_fifo.read();
4911            char buf[80];
4912            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4913            check_monitor(buf, address, r_cas_wdata.read());
4914
4915            if(r_cas_cpt.read() ==4)
4916              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
4917          }
4918        }
4919        else       //  releases the locks protecting UPT and DIR UPT full
4920        {
4921          r_cas_fsm = CAS_WAIT;
4922        }
4923
4924#if DEBUG_MEMC_CAS
4925        if(m_debug_cas_fsm)
4926        {
4927          std::cout << "  <MEMC " << name()
4928                    << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
4929                    << " / wok = " << wok
4930                    << " / nline  = " << std::hex << nline
4931                    << " / count = " << nb_copies << std::endl;
4932        }
4933#endif
4934      }
4935      break;
4936    }
4937    /////////////
4938    case CAS_WAIT:   // release all locks and retry from beginning
4939    {
4940
4941#if DEBUG_MEMC_CAS
4942      if(m_debug_cas_fsm)
4943      {
4944        std::cout << "  <MEMC " << name()
4945                  << ".CAS_WAIT> Release all locks" << std::endl;
4946      }
4947#endif
4948      r_cas_fsm = CAS_DIR_REQ;
4949      break;
4950    }
4951    //////////////////
4952    case CAS_UPT_HEAP_LOCK:  // lock the heap
4953    {
4954      if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4955      {
4956
4957#if DEBUG_MEMC_CAS
4958        if(m_debug_cas_fsm)
4959        {
4960          std::cout << "  <MEMC " << name()
4961                    << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4962        }
4963#endif
4964        r_cas_fsm = CAS_UPT_REQ;
4965      }
4966      break;
4967    }
4968    ////////////////
4969    case CAS_UPT_REQ:  // send a first update request to CC_SEND FSM
4970    {
4971      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4972             "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4973
4974      if(!r_cas_to_cc_send_multi_req.read() && !r_cas_to_cc_send_brdcast_req.read())
4975      {
4976        r_cas_to_cc_send_brdcast_req  = false;
4977        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
4978        r_cas_to_cc_send_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4979        r_cas_to_cc_send_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4980        r_cas_to_cc_send_wdata        = r_cas_wdata.read();
4981
4982        if(r_cas_cpt.read() == 4)
4983        {
4984          r_cas_to_cc_send_is_long    = true;
4985          r_cas_to_cc_send_wdata_high = m_cmd_cas_wdata_fifo.read();
4986        }
4987        else
4988        {
4989          r_cas_to_cc_send_is_long    = false;
4990          r_cas_to_cc_send_wdata_high = 0;
4991        }
4992
4993        // We put the first copy in the fifo
4994        cas_to_cc_send_fifo_put     = true;
4995        cas_to_cc_send_fifo_inst    = r_cas_copy_inst.read();
4996        cas_to_cc_send_fifo_srcid   = r_cas_copy.read();
4997#if L1_MULTI_CACHE
4998        cas_to_cc_send_fifo_cache_id= r_cas_copy_cache.read();
4999#endif
5000        if(r_cas_count.read() == 1)  // one single copy
5001        {
5002          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
5003          // update responses
5004          cmd_cas_fifo_get            = true;
5005          r_cas_to_cc_send_multi_req = true;
5006          r_cas_cpt = 0;
5007        }
5008        else      // several copies
5009        {
5010          r_cas_fsm = CAS_UPT_NEXT;
5011        }
5012
5013#if DEBUG_MEMC_CAS
5014        if(m_debug_cas_fsm)
5015        {
5016          std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to CC_SEND FSM "
5017                    << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
5018                    << " / wdata = " << std::hex << r_cas_wdata.read()
5019                    << " / srcid = " << std::dec << r_cas_copy.read()
5020                    << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
5021        }
5022#endif
5023      }
5024      break;
5025    }
5026    /////////////////
5027    case CAS_UPT_NEXT:     // send a multi-update request to CC_SEND FSM
5028    {
5029      assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
5030             and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
5031
5032      HeapEntry entry = m_heap.read(r_cas_ptr.read());
5033      cas_to_cc_send_fifo_srcid    = entry.owner.srcid;
5034#if L1_MULTI_CACHE
5035      cas_to_cc_send_fifo_cache_id = entry.owner.cache_id;
5036#endif
5037      cas_to_cc_send_fifo_inst     = entry.owner.inst;
5038      cas_to_cc_send_fifo_put = true;
5039
5040      if(m_cas_to_cc_send_inst_fifo.wok())   // request accepted by CC_SEND FSM
5041      {
5042        r_cas_ptr = entry.next;
5043        if(entry.next == r_cas_ptr.read())    // last copy
5044        {
5045          r_cas_to_cc_send_multi_req = true;
5046          r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
5047          // all update responses
5048          cmd_cas_fifo_get = true;
5049          r_cas_cpt        = 0;
5050        }
5051      }
5052
5053#if DEBUG_MEMC_CAS
5054      if(m_debug_cas_fsm)
5055      {
5056        std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to CC_SEND FSM "
5057                  << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
5058                  << " / wdata = " << std::hex << r_cas_wdata.read()
5059                  << " / srcid = " << std::dec << entry.owner.srcid
5060                  << " / inst = " << std::dec << entry.owner.inst << std::endl;
5061      }
5062#endif
5063      break;
5064    }
5065    /////////////////////
5066    case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
5067    {
5068      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5069      {
5070        if(!r_cas_to_ixr_cmd_req)    // we can transfer the request to IXR_CMD FSM
5071        {
5072          // fill the data buffer
5073          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5074          for(size_t i = 0; i<m_words; i++)
5075          {
5076            if(i == word)
5077            {
5078              r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
5079            }
5080            else if((i == word+1) && (r_cas_cpt.read() == 4))   // 64 bit CAS
5081            {
5082              r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
5083            }
5084            else
5085            {
5086              r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
5087            }
5088          }
5089          size_t wok_index = 0;
5090          bool   wok       = !m_transaction_tab.full(wok_index);
5091          if(wok)
5092          {
5093            r_cas_trt_index = wok_index;
5094            r_cas_fsm       = CAS_BC_UPT_LOCK;
5095          }
5096          else
5097          {
5098            r_cas_fsm       = CAS_WAIT;
5099          }
5100        }
5101        else
5102        {
5103          r_cas_fsm = CAS_WAIT;
5104        }
5105      }
5106      break;
5107    }
5108    ///////////////////
5109    case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
5110      // write data in cache in case of successful registration
5111    {
5112      if(r_alloc_upt_fsm.read() == ALLOC_UPT_CAS)
5113      {
5114        bool        wok       = false;
5115        size_t      index     = 0;
5116        size_t      srcid     = m_cmd_cas_srcid_fifo.read();
5117        size_t      trdid     = m_cmd_cas_trdid_fifo.read();
5118        size_t      pktid     = m_cmd_cas_pktid_fifo.read();
5119        addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5120        size_t      nb_copies = r_cas_count.read();
5121
5122        // register a broadcast inval transaction in UPT
5123        wok = m_update_tab.set(false,  // it's an inval transaction
5124                               true,    // it's a broadcast
5125                               true,    // it needs a response
5126                               srcid,
5127                               trdid,
5128                               pktid,
5129                               nline,
5130                               nb_copies,
5131                               index);
5132
5133        if(wok)     // UPT not full
5134        {
5135          // cache update
5136          size_t way  = r_cas_way.read();
5137          size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5138          size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5139
5140          m_cache_data.write(way, set, word, r_cas_wdata.read());
5141          if(r_cas_cpt.read() ==4)
5142            m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
5143
5144          // monitor
5145          if(m_monitor_ok)
5146          {
5147            vci_addr_t address = m_cmd_cas_addr_fifo.read();
5148            char buf[80];
5149            snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
5150            check_monitor(buf, address, r_cas_wdata.read());
5151            if(r_cas_cpt.read() ==4)
5152              check_monitor(buf, address+4, m_cmd_cas_wdata_fifo.read());
5153          }
5154          r_cas_upt_index = index;
5155          r_cas_fsm = CAS_BC_DIR_INVAL;
5156#if DEBUG_MEMC_CAS
5157          if(m_debug_cas_fsm)
5158          {
5159            std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
5160                      << " / nline = " << nline
5161                      << " / count = " << nb_copies
5162                      << " / upt_index = " << index << std::endl;
5163          }
5164#endif
5165        }
5166        else      //  releases the lock protecting UPT
5167        {
5168          r_cas_fsm = CAS_WAIT;
5169        }
5170      }
5171      break;
5172    }
5173    //////////////////
5174    case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
5175    {
5176      if((r_alloc_trt_fsm.read() == ALLOC_TRT_CAS) &&
5177          (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS) &&
5178          (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS))
5179      {
5180        // set TRT
5181        m_transaction_tab.set(r_cas_trt_index.read(),
5182                              false,    // PUT request to XRAM
5183                              m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())],
5184                              0,
5185                              0,
5186                              0,
5187                              false,    // not a processor read
5188                              0,
5189                              0,
5190                              std::vector<be_t> (m_words,0),
5191                              std::vector<data_t> (m_words,0));
5192
5193        // invalidate directory entry
5194        DirectoryEntry entry;
5195        entry.valid         = false;
5196        entry.dirty         = false;
5197        entry.tag         = 0;
5198        entry.is_cnt        = false;
5199        entry.lock          = false;
5200        entry.count         = 0;
5201        entry.owner.srcid   = 0;
5202#if L1_MULTI_CACHE
5203        entry.owner.cache_id= 0;
5204#endif
5205        entry.owner.inst    = false;
5206        entry.ptr           = 0;
5207        size_t set          = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5208        size_t way          = r_cas_way.read();
5209        m_cache_directory.write(set, way, entry);
5210
5211        r_cas_fsm = CAS_BC_CC_SEND;
5212
5213#if DEBUG_MEMC_CAS
5214        if(m_debug_cas_fsm)
5215        {
5216          std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
5217                    << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
5218                    << " / set = " << std::dec << set << " / way = " << way << std::endl;
5219        }
5220#endif
5221      }
5222      else
5223      {
5224        assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
5225      }
5226      break;
5227    }
5228    ///////////////////
5229    case CAS_BC_CC_SEND:  // Request the broadcast inval to CC_SEND FSM
5230    {
5231      if(!r_cas_to_cc_send_multi_req.read() &&
5232          !r_cas_to_cc_send_brdcast_req.read())
5233      {
5234        r_cas_to_cc_send_multi_req    = false;
5235        r_cas_to_cc_send_brdcast_req  = true;
5236        r_cas_to_cc_send_trdid        = r_cas_upt_index.read();
5237        r_cas_to_cc_send_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5238        r_cas_to_cc_send_index        = 0;
5239        r_cas_to_cc_send_wdata        = 0;
5240
5241        r_cas_fsm = CAS_BC_XRAM_REQ;
5242      }
5243      break;
5244    }
5245    ////////////////////
5246    case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
5247    {
5248      if(!r_cas_to_ixr_cmd_req)
5249      {
5250        r_cas_to_ixr_cmd_req     = true;
5251        r_cas_to_ixr_cmd_write   = true;
5252        r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
5253        r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
5254        r_cas_fsm                = CAS_IDLE;
5255        cmd_cas_fifo_get         = true;
5256        r_cas_cpt                = 0;
5257
5258#if DEBUG_MEMC_CAS
5259        if(m_debug_cas_fsm)
5260        {
5261          std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
5262                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
5263                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5264        }
5265#endif
5266      }
5267      else
5268      {
5269        std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
5270                  << std::endl;
5271      }
5272      break;
5273    }
5274    /////////////////
5275    case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
5276    {
5277      if(!r_cas_to_tgt_rsp_req)
5278      {
5279        cmd_cas_fifo_get     = true;
5280        r_cas_cpt              = 0;
5281        r_cas_to_tgt_rsp_req = true;
5282        r_cas_to_tgt_rsp_data  = 1;
5283        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5284        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5285        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5286        r_cas_fsm              = CAS_IDLE;
5287
5288#if DEBUG_MEMC_CAS
5289        if(m_debug_cas_fsm)
5290        {
5291          std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
5292        }
5293#endif
5294      }
5295      break;
5296    }
5297    ////////////////////
5298    case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
5299    {
5300      if(!r_cas_to_tgt_rsp_req)
5301      {
5302        cmd_cas_fifo_get       = true;
5303        r_cas_cpt              = 0;
5304        r_cas_to_tgt_rsp_req = true;
5305        r_cas_to_tgt_rsp_data  = 0;
5306        r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
5307        r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
5308        r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
5309        r_cas_fsm              = CAS_IDLE;
5310
5311#if DEBUG_MEMC_CAS
5312        if(m_debug_cas_fsm)
5313        {
5314          std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
5315        }
5316#endif
5317      }
5318      break;
5319    }
5320    /////////////////////
5321    case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
5322    {
5323      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5324      {
5325        size_t   index = 0;
5326        bool hit_read = m_transaction_tab.hit_read(
5327                          m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()],index);
5328        bool hit_write = m_transaction_tab.hit_write(
5329                           m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]);
5330        bool wok = !m_transaction_tab.full(index);
5331
5332#if DEBUG_MEMC_CAS
5333        if(m_debug_cas_fsm)
5334        {
5335          std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_LOCK> Check TRT state"
5336                    << " / hit_read = "  << hit_read
5337                    << " / hit_write = " << hit_write
5338                    << " / wok = " << wok
5339                    << " / index = " << index << std::endl;
5340        }
5341#endif
5342
5343        if(hit_read || !wok || hit_write)    // missing line already requested or no space in TRT
5344        {
5345          r_cas_fsm = CAS_WAIT;
5346        }
5347        else
5348        {
5349          r_cas_trt_index = index;
5350          r_cas_fsm       = CAS_MISS_TRT_SET;
5351        }
5352      }
5353      break;
5354    }
5355    ////////////////////
5356    case CAS_MISS_TRT_SET: // register the GET transaction in TRT
5357    {
5358      if(r_alloc_trt_fsm.read() == ALLOC_TRT_CAS)
5359      {
5360        std::vector<be_t> be_vector;
5361        std::vector<data_t> data_vector;
5362        be_vector.clear();
5363        data_vector.clear();
5364        for(size_t i=0; i<m_words; i++)
5365        {
5366          be_vector.push_back(0);
5367          data_vector.push_back(0);
5368        }
5369
5370        m_transaction_tab.set(r_cas_trt_index.read(),
5371                              true,   // read request
5372                              m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()],
5373                              m_cmd_cas_srcid_fifo.read(),
5374                              m_cmd_cas_trdid_fifo.read(),
5375                              m_cmd_cas_pktid_fifo.read(),
5376                              false,    // write request from processor
5377                              0,
5378                              0,
5379                              be_vector,
5380                              data_vector);
5381        r_cas_fsm = CAS_MISS_XRAM_REQ;
5382
5383#if DEBUG_MEMC_CAS
5384        if(m_debug_cas_fsm)
5385        {
5386          std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
5387                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
5388                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5389        }
5390#endif
5391      }
5392      break;
5393    }
5394    //////////////////////
5395    case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
5396    {
5397      if(!r_cas_to_ixr_cmd_req)
5398      {
5399        r_cas_to_ixr_cmd_req        = true;
5400        r_cas_to_ixr_cmd_write      = false;
5401        r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
5402        r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()];
5403        r_cas_fsm                   = CAS_WAIT;
5404
5405#if DEBUG_MEMC_CAS
5406        if(m_debug_cas_fsm)
5407        {
5408          std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
5409                    << " / nline = " << m_nline[(vci_addr_t) m_cmd_cas_addr_fifo.read()]
5410                    << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5411        }
5412#endif
5413      }
5414      break;
5415    }
5416  } // end switch r_cas_fsm
5417
5418
5419  //////////////////////////////////////////////////////////////////////////////
5420  //    CC_SEND FSM
5421  //////////////////////////////////////////////////////////////////////////////
5422  // The CC_SEND fsm controls the DSPIN initiator port on the coherence
5423  // network, used to update or invalidate cache lines in L1 caches.
5424  //
5425  // This fsm is used also to acknowledge CLEANUP a command after request from
5426  // the CLEANUP fsm.
5427  //
5428  // It implements a round-robin priority between the four possible client FSMs
5429  // XRAM_RSP, WRITE, CAS and CLEANUP. Each FSM can request the next services:
5430  // - r_xram_rsp_to_cc_send_multi_req : multi-inval
5431  //   r_xram_rsp_to_cc_send_brdcast_req : broadcast-inval
5432  // - r_write_to_cc_send_multi_req : multi-update
5433  //   r_write_to_cc_send_brdcast_req : broadcast-inval
5434  // - r_cas_to_cc_send_multi_req : multi-update
5435  //   r_cas_to_cc_send_brdcast_req : broadcast-inval
5436  // - r_cleanup_to_cc_send_req : cleanup acknowledgement
5437  //
5438  // An inval request is a double DSPIN flit command containing:
5439  // 1. the index of the line to be invalidated.
5440  //
5441  // An update request is a multi-flit DSPIN command containing:
5442  // 1. the index of the cache line to be updated.
5443  // 2. the index of the first modified word in the line.
5444  // 3. the data to update
5445  ///////////////////////////////////////////////////////////////////////////////
5446
5447  switch(r_cc_send_fsm.read())
5448  {
5449    case CC_SEND_WRITE_IDLE:
5450      {
5451        // XRAM_RSP FSM has highest priority
5452        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5453            r_xram_rsp_to_cc_send_multi_req.read())
5454        {
5455          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5456          m_cpt_inval++;
5457          break;
5458        }
5459
5460        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5461        {
5462          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5463          m_cpt_inval++;
5464          break;
5465        }
5466
5467        if(m_cas_to_cc_send_inst_fifo.rok() ||
5468            r_cas_to_cc_send_multi_req.read())
5469        {
5470          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5471          m_cpt_update++;
5472          break;
5473        }
5474
5475        if(r_cas_to_cc_send_brdcast_req.read())
5476        {
5477          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5478          m_cpt_inval++;
5479          break;
5480        }
5481
5482        if (r_cleanup_to_cc_send_req.read())
5483        {
5484          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5485          break;
5486        }
5487
5488        if(m_write_to_cc_send_inst_fifo.rok() ||
5489            r_write_to_cc_send_multi_req.read())
5490        {
5491          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5492          m_cpt_update++;
5493          break;
5494        }
5495
5496        if(r_write_to_cc_send_brdcast_req.read())
5497        {
5498          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5499          m_cpt_inval++;
5500        }
5501        break;
5502      }
5503
5504    case CC_SEND_XRAM_RSP_IDLE:
5505      {
5506        // CAS FSM has highest priority
5507        if(m_cas_to_cc_send_inst_fifo.rok() ||
5508            r_cas_to_cc_send_multi_req.read())
5509        {
5510          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5511          m_cpt_update++;
5512          break;
5513        }
5514
5515        if(r_cas_to_cc_send_brdcast_req.read())
5516        {
5517          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5518          m_cpt_inval++;
5519          break;
5520        }
5521
5522        if(r_cleanup_to_cc_send_req.read())
5523        {
5524          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5525          break;
5526        }
5527
5528        if(m_write_to_cc_send_inst_fifo.rok() ||
5529            r_write_to_cc_send_multi_req.read())
5530        {
5531          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5532          m_cpt_update++;
5533          break;
5534        }
5535
5536        if(r_write_to_cc_send_brdcast_req.read())
5537        {
5538          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5539          m_cpt_inval++;
5540          break;
5541        }
5542
5543        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5544            r_xram_rsp_to_cc_send_multi_req.read())
5545        {
5546          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5547          m_cpt_inval++;
5548          break;
5549        }
5550
5551        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5552        {
5553          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5554          m_cpt_inval++;
5555        }
5556
5557        break;
5558      }
5559
5560    case CC_SEND_CAS_IDLE:
5561      {
5562        // CLEANUP FSM has highest priority
5563        if(r_cleanup_to_cc_send_req.read())
5564        {
5565          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5566          break;
5567        }
5568
5569        if(m_write_to_cc_send_inst_fifo.rok() ||
5570            r_write_to_cc_send_multi_req.read())
5571        {
5572          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5573          m_cpt_update++;
5574          break;
5575        }
5576
5577        if(r_write_to_cc_send_brdcast_req.read())
5578        {
5579          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5580          m_cpt_inval++;
5581          break;
5582        }
5583
5584        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5585            r_xram_rsp_to_cc_send_multi_req.read())
5586        {
5587          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5588          m_cpt_inval++;
5589          break;
5590        }
5591
5592        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5593        {
5594          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5595          m_cpt_inval++;
5596          break;
5597        }
5598
5599        if(m_cas_to_cc_send_inst_fifo.rok() ||
5600            r_cas_to_cc_send_multi_req.read())
5601        {
5602          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5603          m_cpt_update++;
5604          break;
5605        }
5606
5607        if(r_cas_to_cc_send_brdcast_req.read())
5608        {
5609          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5610          m_cpt_inval++;
5611        }
5612        break;
5613      }
5614
5615    case CC_SEND_CLEANUP_IDLE:
5616      {
5617        // WRITE FSM has highest priority
5618        if(m_write_to_cc_send_inst_fifo.rok() ||
5619            r_write_to_cc_send_multi_req.read())
5620        {
5621          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5622          m_cpt_update++;
5623          break;
5624        }
5625
5626        if(r_write_to_cc_send_brdcast_req.read())
5627        {
5628          r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_HEADER;
5629          m_cpt_inval++;
5630          break;
5631        }
5632
5633        if(m_xram_rsp_to_cc_send_inst_fifo.rok() ||
5634            r_xram_rsp_to_cc_send_multi_req.read())
5635        {
5636          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5637          m_cpt_inval++;
5638          break;
5639        }
5640
5641        if(r_xram_rsp_to_cc_send_brdcast_req.read())
5642        {
5643          r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_HEADER;
5644          m_cpt_inval++;
5645          break;
5646        }
5647
5648        if(m_cas_to_cc_send_inst_fifo.rok() ||
5649            r_cas_to_cc_send_multi_req.read())
5650        {
5651          r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5652          m_cpt_update++;
5653          break;
5654        }
5655
5656        if(r_cas_to_cc_send_brdcast_req.read())
5657        {
5658          r_cc_send_fsm = CC_SEND_CAS_BRDCAST_HEADER;
5659          m_cpt_inval++;
5660          break;
5661        }
5662
5663        if(r_cleanup_to_cc_send_req.read())
5664        {
5665          r_cc_send_fsm = CC_SEND_CLEANUP_ACK;
5666        }
5667
5668        break;
5669      }
5670
5671    case CC_SEND_CLEANUP_ACK:
5672      {
5673        // send only flit for a cleanup acknowledgement (from CLEANUP FSM)
5674        if(not p_dspin_out.read) break;
5675
5676        r_cleanup_to_cc_send_req = false;
5677        r_cc_send_fsm = CC_SEND_CLEANUP_IDLE;
5678
5679#if DEBUG_MEMC_CC_SEND
5680        if(m_debug_cc_send_fsm)
5681        {
5682          std::cout
5683            << "  <MEMC " << name()
5684            << ".CC_SEND_CLEANUP_ACK> Cleanup Acknowledgement for srcid "
5685            << r_cleanup_to_cc_send_srcid.read()
5686            << std::endl;
5687        }
5688#endif
5689        break;
5690      }
5691
5692    case CC_SEND_XRAM_RSP_INVAL_HEADER:
5693      {
5694        // send first flit multi-inval (from XRAM_RSP FSM)
5695        if(m_xram_rsp_to_cc_send_inst_fifo.rok())
5696        {
5697          if(not p_dspin_out.read) break;
5698
5699          r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_NLINE;
5700          break;
5701        }
5702
5703        if(r_xram_rsp_to_cc_send_multi_req.read())
5704        {
5705          r_xram_rsp_to_cc_send_multi_req = false;
5706        }
5707
5708        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5709        break;
5710      }
5711
5712    case CC_SEND_XRAM_RSP_INVAL_NLINE:
5713      {
5714        // send second flit multi-inval (from XRAM_RSP FSM)
5715        if(not p_dspin_out.read) break;
5716
5717        m_cpt_inval_mult++;
5718
5719        r_cc_send_fsm = CC_SEND_XRAM_RSP_INVAL_HEADER;
5720
5721#if DEBUG_MEMC_CC_SEND
5722        if(m_debug_cc_send_fsm)
5723        {
5724          std::cout
5725            << "  <MEMC " << name()
5726            << ".CC_SEND_XRAM_RSP_INVAL_NLINE> Broadcast-Inval for line "
5727            << r_xram_rsp_to_cc_send_nline.read()
5728            << std::endl;
5729        }
5730#endif
5731        break;
5732      }
5733
5734    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
5735      {
5736        // send first flit broadcast-inval (from XRAM_RSP FSM)
5737        if(not p_dspin_out.read) break;
5738
5739        r_cc_send_fsm = CC_SEND_XRAM_RSP_BRDCAST_NLINE;
5740        break;
5741      }
5742
5743    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
5744      {
5745        // send second flit broadcast-inval (from XRAM_RSP FSM)
5746        if(not p_dspin_out.read) break;
5747
5748        m_cpt_inval_brdcast++;
5749
5750        r_xram_rsp_to_cc_send_brdcast_req = false;
5751        r_cc_send_fsm = CC_SEND_XRAM_RSP_IDLE;
5752
5753#if DEBUG_MEMC_CC_SEND
5754        if(m_debug_cc_send_fsm)
5755        {
5756          std::cout
5757            << "  <MEMC " << name()
5758            << ".CC_SEND_XRAM_RSP_BRDCAST_NLINE> Broadcast-Inval for line "
5759            << r_xram_rsp_to_cc_send_nline.read()
5760            << std::endl;
5761        }
5762#endif
5763        break;
5764      }
5765
5766    case CC_SEND_WRITE_BRDCAST_HEADER:
5767      {
5768        // send first flit broadcast-inval (from WRITE FSM)
5769        if(not p_dspin_out.read) break;
5770
5771        r_cc_send_fsm = CC_SEND_WRITE_BRDCAST_NLINE;
5772        break;
5773      }
5774
5775    case CC_SEND_WRITE_BRDCAST_NLINE:
5776      {
5777        // send second flit broadcast-inval (from WRITE FSM)
5778        if(not p_dspin_out.read) break;
5779
5780        m_cpt_inval_brdcast++;
5781
5782        r_write_to_cc_send_brdcast_req = false;
5783        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5784
5785#if DEBUG_MEMC_CC_SEND
5786        if(m_debug_cc_send_fsm)
5787        {
5788          std::cout
5789            << "  <MEMC " << name()
5790            << ".CC_SEND_WRITE_BRDCAST_NLINE> Broadcast-Inval for line "
5791            << r_write_to_cc_send_nline.read()
5792            << std::endl;
5793        }
5794#endif
5795        break;
5796      }
5797
5798    case CC_SEND_WRITE_UPDT_HEADER:
5799      {
5800        // send first flit for a multi-update (from WRITE FSM)
5801        if(m_write_to_cc_send_inst_fifo.rok())
5802        {
5803          if(not p_dspin_out.read) break;
5804
5805          r_cc_send_fsm = CC_SEND_WRITE_UPDT_NLINE;
5806          break;
5807        }
5808
5809        if(r_write_to_cc_send_multi_req.read())
5810        {
5811          r_write_to_cc_send_multi_req = false;
5812        }
5813
5814        r_cc_send_fsm = CC_SEND_WRITE_IDLE;
5815        break;
5816      }
5817
5818    case CC_SEND_WRITE_UPDT_NLINE:
5819      {
5820        // send second flit for a multi-update (from WRITE FSM)
5821        if(not p_dspin_out.read) break;
5822
5823        m_cpt_update_mult++;
5824
5825        r_cc_send_cpt = 0;
5826        r_cc_send_fsm = CC_SEND_WRITE_UPDT_DATA;
5827
5828#if DEBUG_MEMC_CC_SEND
5829        if(m_debug_cc_send_fsm)
5830        {
5831          std::cout
5832            << "  <MEMC " << name()
5833            << ".CC_SEND_WRITE_UPDT_NLINE> Multicast-Update for line "
5834            << r_write_to_cc_send_nline.read()
5835            << std::endl;
5836        }
5837#endif
5838        break;
5839      }
5840
5841    case CC_SEND_WRITE_UPDT_DATA:
5842      {
5843        // send N data flits for a multi-update (from WRITE FSM)
5844        if(not p_dspin_out.read) break;
5845
5846        if(r_cc_send_cpt.read() == (r_write_to_cc_send_count.read()-1))
5847        {
5848          write_to_cc_send_fifo_get = true;
5849          r_cc_send_fsm = CC_SEND_WRITE_UPDT_HEADER;
5850          break;
5851        }
5852
5853        r_cc_send_cpt = r_cc_send_cpt.read() + 1;
5854        break;
5855      }
5856
5857    case CC_SEND_CAS_BRDCAST_HEADER:
5858      {
5859        // send first flit for a broadcast-inval (from CAS FSM)
5860        if(not p_dspin_out.read) break;
5861
5862        r_cc_send_fsm = CC_SEND_CAS_BRDCAST_NLINE;
5863        break;
5864      }
5865
5866    case CC_SEND_CAS_BRDCAST_NLINE:
5867      {
5868        // send second flit broadcast-inval (from CAS FSM)
5869        if(not p_dspin_out.read) break;
5870
5871        m_cpt_inval_brdcast++;
5872
5873        r_cas_to_cc_send_brdcast_req = false;
5874        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5875
5876#if DEBUG_MEMC_CC_SEND
5877        if(m_debug_cc_send_fsm)
5878        {
5879          std::cout
5880            << "  <MEMC " << name()
5881            << ".CC_SEND_CAS_BRDCAST_NLINE> Broadcast-Inval for line "
5882            << r_cas_to_cc_send_nline.read()
5883            << std::endl;
5884        }
5885#endif
5886        break;
5887      }
5888
5889    case CC_SEND_CAS_UPDT_HEADER:
5890      {
5891        // send first flit for a multi-update (from CAS FSM)
5892        if(m_cas_to_cc_send_inst_fifo.rok())
5893        {
5894          if(not p_dspin_out.read) break;
5895
5896          r_cc_send_fsm = CC_SEND_CAS_UPDT_NLINE;
5897          break;
5898        }
5899
5900        // no more packets to send for the multi-update
5901        if(r_cas_to_cc_send_multi_req.read())
5902        {
5903          r_cas_to_cc_send_multi_req = false;
5904        }
5905
5906        r_cc_send_fsm = CC_SEND_CAS_IDLE;
5907        break;
5908      }
5909
5910    case CC_SEND_CAS_UPDT_NLINE:
5911      {
5912        // send second flit for a multi-update (from CAS FSM)
5913        if(not p_dspin_out.read) break;
5914
5915        m_cpt_update_mult++;
5916
5917        r_cc_send_cpt = 0;
5918        r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA;
5919
5920#if DEBUG_MEMC_CC_SEND
5921        if(m_debug_cc_send_fsm)
5922        {
5923          std::cout
5924            << "  <MEMC " << name()
5925            << ".CC_SEND_CAS_UPDT_NLINE> Multicast-Update for line "
5926            << r_cas_to_cc_send_nline.read()
5927            << std::endl;
5928        }
5929#endif
5930        break;
5931      }
5932
5933    case CC_SEND_CAS_UPDT_DATA:
5934      {
5935        // send first data for a multi-update (from CAS FSM)
5936        if(not p_dspin_out.read) break;
5937
5938        if(r_cas_to_cc_send_is_long.read())
5939        {
5940          r_cc_send_fsm = CC_SEND_CAS_UPDT_DATA_HIGH;
5941          break;
5942        }
5943
5944        cas_to_cc_send_fifo_get = true;
5945        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5946        break;
5947      }
5948
5949    case CC_SEND_CAS_UPDT_DATA_HIGH:
5950      {
5951        // send second data for a multi-update (from CAS FSM)
5952        if(not p_dspin_out.read) break;
5953
5954        cas_to_cc_send_fifo_get = true;
5955        r_cc_send_fsm = CC_SEND_CAS_UPDT_HEADER;
5956        break;
5957      }
5958  }
5959  // end switch r_cc_send_fsm
5960
5961  //////////////////////////////////////////////////////////////////////////////
5962  //    CC_RECEIVE FSM
5963  //////////////////////////////////////////////////////////////////////////////
5964  // The CC_RECEIVE fsm controls the DSPIN target port on the coherence
5965  // network.
5966  ///////////////////////////////////////////////////////////////////////////////
5967
5968  switch(r_cc_receive_fsm.read())
5969  {
5970    case CC_RECEIVE_IDLE:
5971      {
5972        if(not p_dspin_in.write) break;
5973
5974        uint8_t type =
5975          DspinDhccpParam::dspin_get(
5976              p_dspin_in.data.read(),
5977              DspinDhccpParam::FROM_L1_TYPE);
5978
5979        if((type == DspinDhccpParam::TYPE_CLEANUP_DATA) ||
5980           (type == DspinDhccpParam::TYPE_CLEANUP_INST) )
5981        { 
5982          r_cc_receive_fsm = CC_RECEIVE_CLEANUP;
5983          break;
5984        }
5985       
5986        if(type == DspinDhccpParam::TYPE_MULTI_ACK)
5987        {
5988          r_cc_receive_fsm = CC_RECEIVE_MULTI_ACK;
5989          break;
5990        }
5991
5992        assert(
5993            false && 
5994            "VCI_MEM_CACHE ERROR: Incorrect type in coherence request from "
5995            "L1 Cache");
5996       
5997        break;
5998      }
5999    case CC_RECEIVE_CLEANUP:
6000      {
6001        // wait for a valid cleanup flit
6002        // wait for a WOK in the CC_RECEIVE to CLEANUP fifo
6003        if(not p_dspin_in.write or not m_cc_receive_to_cleanup_fifo.wok()) break;
6004
6005        bool eop = (
6006            DspinDhccpParam::dspin_get(
6007              p_dspin_in.data.read(),
6008              DspinDhccpParam::FROM_L1_EOP)
6009            == 0x1);
6010
6011        cc_receive_to_cleanup_fifo_put = true;
6012        if(eop)
6013        {
6014          r_cc_receive_fsm = CC_RECEIVE_IDLE;
6015        }
6016
6017        break;
6018      }
6019    case CC_RECEIVE_MULTI_ACK:
6020      {
6021        // wait for a valid multicast acknowledgement flit
6022        // wait for a WOK in the CC_RECEIVE to MULTI_ACK fifo
6023        if(not p_dspin_in.write or not m_cc_receive_to_multi_ack_fifo.wok()) break;
6024
6025        bool eop = (
6026            DspinDhccpParam::dspin_get(
6027              p_dspin_in.data.read(),
6028              DspinDhccpParam::FROM_L1_EOP) 
6029            == 0x1);
6030
6031        cc_receive_to_multi_ack_fifo_put  = true;
6032        if(eop)
6033        {
6034          r_cc_receive_fsm = CC_RECEIVE_IDLE;
6035        }
6036
6037        break;
6038      }
6039    default:
6040      {
6041        assert(
6042            false &&
6043            "VCI_MEM_CACHE ERROR: Invalid state in CC_RECEIVE FSM");
6044      }
6045  }
6046  /////////////////////////////////////////////////////////////////////
6047  //    TGT_RSP FSM
6048  /////////////////////////////////////////////////////////////////////
6049  // The TGT_RSP fsm sends the responses on the VCI target port
6050  // with a round robin priority between six requests :
6051  // - r_read_to_tgt_rsp_req
6052  // - r_write_to_tgt_rsp_req
6053  // - r_cas_to_tgt_rsp_req
6054  // - r_cleanup_to_tgt_rsp_req
6055  // - r_xram_rsp_to_tgt_rsp_req
6056  // - r_multi_ack_to_tgt_rsp_req
6057  // The  ordering is :  read > write > cas > xram > init > cleanup
6058  /////////////////////////////////////////////////////////////////////
6059
6060  switch(r_tgt_rsp_fsm.read())
6061  {
6062    case TGT_RSP_READ_IDLE:
6063    { 
6064      // write requests have the highest priority
6065      if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6066      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6067      else if(r_xram_rsp_to_tgt_rsp_req)
6068      {
6069        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6070        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6071      }
6072      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6073      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6074      else if(r_read_to_tgt_rsp_req)
6075      {
6076        r_tgt_rsp_fsm = TGT_RSP_READ;
6077        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6078      }
6079      break;
6080    }
6081    ////////////////////////
6082    case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
6083    {
6084      if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS;
6085      else if(r_xram_rsp_to_tgt_rsp_req)
6086      {
6087        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6088        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6089      }
6090      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6091      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6092      else if(r_read_to_tgt_rsp_req)
6093      {
6094        r_tgt_rsp_fsm = TGT_RSP_READ;
6095        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6096      }
6097
6098      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6099      break;
6100    }
6101    ///////////////////////
6102    case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
6103    {
6104      if(r_xram_rsp_to_tgt_rsp_req)
6105      {
6106        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6107        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6108      }
6109      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6110      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6111      else if(r_read_to_tgt_rsp_req)
6112      {
6113        r_tgt_rsp_fsm = TGT_RSP_READ;
6114        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6115      }
6116      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6117      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6118      break;
6119    }
6120    ///////////////////////
6121    case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
6122    {
6123
6124      if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6125      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6126      else if(r_read_to_tgt_rsp_req)
6127      {
6128        r_tgt_rsp_fsm = TGT_RSP_READ;
6129        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6130      }
6131      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6132      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6133      else if(r_xram_rsp_to_tgt_rsp_req)
6134      {
6135        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6136        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6137      }
6138      break;
6139    }
6140    ///////////////////////
6141    case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
6142    {
6143      if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6144      else if(r_read_to_tgt_rsp_req)
6145      {
6146        r_tgt_rsp_fsm = TGT_RSP_READ;
6147        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6148      }
6149      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6150      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6151      else if(r_xram_rsp_to_tgt_rsp_req)
6152      {
6153        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6154        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6155      }
6156      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT;
6157      break;
6158    }
6159    ///////////////////////
6160    case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
6161    {
6162      if(r_read_to_tgt_rsp_req)
6163      {
6164        r_tgt_rsp_fsm = TGT_RSP_READ;
6165        r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
6166      }
6167      else if(r_write_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_WRITE;
6168      else if(r_cas_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
6169      else if(r_xram_rsp_to_tgt_rsp_req)
6170      {
6171        r_tgt_rsp_fsm = TGT_RSP_XRAM;
6172        r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
6173      }
6174      else if(r_multi_ack_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
6175      else if(r_cleanup_to_tgt_rsp_req) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
6176      break;
6177    }
6178    //////////////////
6179    case TGT_RSP_READ:    // send the response to a read
6180    {
6181      if(p_vci_tgt.rspack)
6182      {
6183
6184#if DEBUG_MEMC_TGT_RSP
6185        if(m_debug_tgt_rsp_fsm)
6186        {
6187          std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
6188                    << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
6189                    << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
6190                    << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
6191                    << " / rdata = " << std::hex << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6192                    << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6193        }
6194#endif
6195        if(r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read() +r_read_to_tgt_rsp_length-1))
6196        {
6197          r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
6198          r_read_to_tgt_rsp_req = false;
6199        }
6200        else
6201        {
6202          r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
6203        }
6204      }
6205      break;
6206    }
6207    ///////////////////
6208    case TGT_RSP_WRITE:   // send the write acknowledge
6209    {
6210      if(p_vci_tgt.rspack)
6211      {
6212
6213#if DEBUG_MEMC_TGT_RSP
6214        if(m_debug_tgt_rsp_fsm)
6215        {
6216          std::cout << "  <MEMC " << name() << ".TGT_RSP_WRITE> Write response"
6217                    << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
6218                    << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
6219                    << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
6220        }
6221#endif
6222        r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
6223        r_write_to_tgt_rsp_req = false;
6224      }
6225      break;
6226    }
6227    ///////////////////
6228    case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
6229    {
6230      if(p_vci_tgt.rspack)
6231      {
6232
6233#if DEBUG_MEMC_TGT_RSP
6234        if(m_debug_tgt_rsp_fsm)
6235        {
6236          std::cout << "  <MEMC " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
6237                    << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
6238                    << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
6239                    << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
6240        }
6241#endif
6242        r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
6243        r_cleanup_to_tgt_rsp_req = false;
6244      }
6245      break;
6246    }
6247    //////////////////
6248    case TGT_RSP_CAS:    // send one atomic word response
6249    {
6250      if(p_vci_tgt.rspack)
6251      {
6252
6253#if DEBUG_MEMC_TGT_RSP
6254        if(m_debug_tgt_rsp_fsm)
6255        {
6256          std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
6257                    << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
6258                    << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
6259                    << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
6260        }
6261#endif
6262        r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
6263        r_cas_to_tgt_rsp_req = false;
6264      }
6265      break;
6266    }
6267
6268    ///////////////////////
6269    case TGT_RSP_XRAM:    // send the response after XRAM access
6270    {
6271      if(p_vci_tgt.rspack)
6272      {
6273
6274#if DEBUG_MEMC_TGT_RSP
6275        if(m_debug_tgt_rsp_fsm)
6276        {
6277          std::cout << "  <MEMC " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
6278                    << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
6279                    << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
6280                    << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
6281                    << " / rdata = " << std::hex << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
6282                    << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
6283        }
6284#endif
6285        if((r_tgt_rsp_cpt.read() ==
6286            (r_xram_rsp_to_tgt_rsp_word.read() +r_xram_rsp_to_tgt_rsp_length.read()-1))
6287            || r_xram_rsp_to_tgt_rsp_rerror.read())
6288        {
6289          r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
6290          r_xram_rsp_to_tgt_rsp_req = false;
6291        }
6292        else
6293        {
6294          r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
6295        }
6296      }
6297      break;
6298    }
6299    //////////////////
6300    case TGT_RSP_INIT:    // send the write response after coherence transaction
6301    {
6302      if(p_vci_tgt.rspack)
6303      {
6304
6305#if DEBUG_MEMC_TGT_RSP
6306        if(m_debug_tgt_rsp_fsm)
6307        {
6308          std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
6309                    << " / rsrcid = " << std::dec << r_multi_ack_to_tgt_rsp_srcid.read()
6310                    << " / rtrdid = " << r_multi_ack_to_tgt_rsp_trdid.read()
6311                    << " / rpktid = " << r_multi_ack_to_tgt_rsp_pktid.read() << std::endl;
6312        }
6313#endif
6314        r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
6315        r_multi_ack_to_tgt_rsp_req = false;
6316      }
6317      break;
6318    }
6319  } // end switch tgt_rsp_fsm
6320
6321  ////////////////////////////////////////////////////////////////////////////////////
6322  //    ALLOC_UPT FSM
6323  ////////////////////////////////////////////////////////////////////////////////////
6324  // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
6325  // with a round robin priority between three FSMs : MULTI_ACK > WRITE > XRAM_RSP > CLEANUP
6326  // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
6327  // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
6328  // - The MULTI_ACK FSM complete those trasactions and erase the UPT entry.
6329  // - The CLEANUP  FSM decrement an entry in UPT.
6330  // The resource is always allocated.
6331  /////////////////////////////////////////////////////////////////////////////////////
6332
6333  switch(r_alloc_upt_fsm.read())
6334  {
6335
6336      ////////////////////////
6337    case ALLOC_UPT_MULTI_ACK:
6338      if((r_multi_ack_fsm.read() != MULTI_ACK_UPT_LOCK) &&
6339          (r_multi_ack_fsm.read() != MULTI_ACK_UPT_CLEAR))
6340      {
6341        if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
6342            (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
6343          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
6344
6345        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6346          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6347
6348        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6349          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6350
6351        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6352                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6353          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6354      }
6355      break;
6356
6357      /////////////////////
6358    case ALLOC_UPT_WRITE:
6359      if((r_write_fsm.read() != WRITE_UPT_LOCK) &&
6360          (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
6361      {
6362        if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6363          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6364
6365        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6366          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6367
6368        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6369                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6370          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6371
6372        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
6373          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
6374      }
6375      break;
6376
6377      ////////////////////////
6378    case ALLOC_UPT_XRAM_RSP:
6379      if(r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
6380      {
6381        if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6382          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6383
6384        else if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6385                (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6386          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6387
6388        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
6389          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
6390
6391        else if((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
6392                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
6393          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
6394      }
6395      break;
6396
6397      //////////////////////////
6398    case ALLOC_UPT_CLEANUP:
6399      if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK)
6400      {
6401        if((r_cas_fsm.read() == CAS_UPT_LOCK) ||
6402            (r_cas_fsm.read() == CAS_BC_UPT_LOCK))
6403          r_alloc_upt_fsm = ALLOC_UPT_CAS;
6404
6405        else if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
6406          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
6407
6408        else if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
6409                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
6410          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
6411
6412        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6413          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6414      }
6415      break;
6416
6417      //////////////////////////
6418    case ALLOC_UPT_CAS:
6419      if((r_cas_fsm.read() != CAS_UPT_LOCK) &&
6420          (r_cas_fsm.read() != CAS_BC_UPT_LOCK))
6421      {
6422        if(r_multi_ack_fsm.read() == MULTI_ACK_UPT_LOCK)
6423          r_alloc_upt_fsm = ALLOC_UPT_MULTI_ACK;
6424
6425        else if((r_write_fsm.read() == WRITE_UPT_LOCK) ||
6426                (r_write_fsm.read() == WRITE_BC_UPT_LOCK))
6427          r_alloc_upt_fsm = ALLOC_UPT_WRITE;
6428
6429        else if(r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)
6430          r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
6431
6432        else if(r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)
6433          r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
6434      }
6435      break;
6436
6437  } // end switch r_alloc_upt_fsm
6438
6439  ////////////////////////////////////////////////////////////////////////////////////
6440  //    ALLOC_DIR FSM
6441  ////////////////////////////////////////////////////////////////////////////////////
6442  // The ALLOC_DIR FSM allocates the access to the directory and
6443  // the data cache with a round robin priority between 5 user FSMs :
6444  // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
6445  // The ressource is always allocated.
6446  /////////////////////////////////////////////////////////////////////////////////////
6447
6448  switch(r_alloc_dir_fsm.read())
6449  {
6450    case ALLOC_DIR_RESET:
6451      // Initializes the directory one SET each cycle. All the WAYS of a SET are
6452      // initialize in parallel
6453
6454      r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
6455
6456      if(r_alloc_dir_reset_cpt.read() == (m_sets - 1))
6457      {
6458        m_cache_directory.init();
6459
6460        r_alloc_dir_fsm = ALLOC_DIR_READ;
6461      }
6462      break;
6463
6464      ////////////////////
6465    case ALLOC_DIR_READ:
6466      if(((r_read_fsm.read()        != READ_DIR_REQ)   &&
6467          (r_read_fsm.read()        != READ_DIR_LOCK)   &&
6468          (r_read_fsm.read()        != READ_TRT_LOCK)   &&
6469          (r_read_fsm.read()        != READ_HEAP_REQ))
6470          ||
6471          ((r_read_fsm.read()       == READ_TRT_LOCK)   &&
6472           (r_alloc_trt_fsm.read()  == ALLOC_TRT_READ)))
6473      {
6474        if(r_write_fsm.read() == WRITE_DIR_REQ)
6475          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
6476
6477        else if(r_cas_fsm.read() == CAS_DIR_REQ)
6478          r_alloc_dir_fsm = ALLOC_DIR_CAS;
6479
6480        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
6481          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
6482
6483        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
6484          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
6485      }
6486      break;
6487
6488      /////////////////////
6489    case ALLOC_DIR_WRITE:
6490      if(((r_write_fsm.read()       != WRITE_DIR_REQ)  &&
6491          (r_write_fsm.read()       != WRITE_DIR_LOCK)  &&
6492          (r_write_fsm.read()       != WRITE_DIR_READ)  &&
6493          (r_write_fsm.read()       != WRITE_DIR_HIT)  &&
6494          (r_write_fsm.read()       != WRITE_BC_TRT_LOCK)  &&
6495          (r_write_fsm.read()       != WRITE_BC_UPT_LOCK)  &&
6496          (r_write_fsm.read()       != WRITE_MISS_TRT_LOCK)  &&
6497          (r_write_fsm.read()       != WRITE_UPT_LOCK)  &&
6498          (r_write_fsm.read()       != WRITE_UPT_HEAP_LOCK))
6499          ||
6500          ((r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK)  &&
6501           (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE))
6502          ||
6503          ((r_write_fsm.read()      == WRITE_MISS_TRT_LOCK)  &&
6504           (r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE)))
6505      {
6506        if(r_cas_fsm.read() == CAS_DIR_REQ)
6507          r_alloc_dir_fsm = ALLOC_DIR_CAS;
6508
6509        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
6510          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
6511
6512        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
6513          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
6514
6515        else if(r_read_fsm.read() == READ_DIR_REQ)
6516          r_alloc_dir_fsm = ALLOC_DIR_READ;
6517      }
6518      break;
6519
6520      ////////////////////
6521    case ALLOC_DIR_CAS:
6522      if(((r_cas_fsm.read()         != CAS_DIR_REQ)  &&
6523          (r_cas_fsm.read()         != CAS_DIR_LOCK)  &&
6524          (r_cas_fsm.read()         != CAS_DIR_HIT_READ)  &&
6525          (r_cas_fsm.read()         != CAS_DIR_HIT_COMPARE)  &&
6526          (r_cas_fsm.read()         != CAS_DIR_HIT_WRITE)  &&
6527          (r_cas_fsm.read()         != CAS_BC_TRT_LOCK)  &&
6528          (r_cas_fsm.read()         != CAS_BC_UPT_LOCK)  &&
6529          (r_cas_fsm.read()         != CAS_MISS_TRT_LOCK)  &&
6530          (r_cas_fsm.read()         != CAS_UPT_LOCK)  &&
6531          (r_cas_fsm.read()         != CAS_UPT_HEAP_LOCK))
6532          ||
6533          ((r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK)  &&
6534           (r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS))
6535          ||
6536          ((r_cas_fsm.read()        == CAS_MISS_TRT_LOCK)  &&
6537           (r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS)))
6538      {
6539        if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
6540          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
6541
6542        else if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
6543          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
6544
6545        else if(r_read_fsm.read() == READ_DIR_REQ)
6546          r_alloc_dir_fsm = ALLOC_DIR_READ;
6547
6548        else if(r_write_fsm.read() == WRITE_DIR_REQ)
6549          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
6550      }
6551      break;
6552
6553      ///////////////////////
6554    case ALLOC_DIR_CLEANUP:
6555      if((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) &&
6556          (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
6557          (r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) &&
6558          (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK))
6559      {
6560        if(r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
6561          r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
6562
6563        else if(r_read_fsm.read() == READ_DIR_REQ)
6564          r_alloc_dir_fsm = ALLOC_DIR_READ;
6565
6566        else if(r_write_fsm.read() == WRITE_DIR_REQ)
6567          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
6568
6569        else if(r_cas_fsm.read() == CAS_DIR_REQ)
6570          r_alloc_dir_fsm = ALLOC_DIR_CAS;
6571      }
6572      break;
6573
6574      ////////////////////////
6575    case ALLOC_DIR_XRAM_RSP:
6576      if((r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK) &&
6577          (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY) &&
6578          (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
6579      {
6580        if(r_read_fsm.read() == READ_DIR_REQ)
6581          r_alloc_dir_fsm = ALLOC_DIR_READ;
6582
6583        else if(r_write_fsm.read() == WRITE_DIR_REQ)
6584          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
6585
6586        else if(r_cas_fsm.read() == CAS_DIR_REQ)
6587          r_alloc_dir_fsm = ALLOC_DIR_CAS;
6588
6589        else if(r_cleanup_fsm.read() == CLEANUP_DIR_REQ)
6590          r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
6591      }
6592      break;
6593
6594  } // end switch alloc_dir_fsm
6595
6596  ////////////////////////////////////////////////////////////////////////////////////
6597  //    ALLOC_TRT FSM
6598  ////////////////////////////////////////////////////////////////////////////////////
6599  // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
6600  // with a round robin priority between 4 user FSMs :
6601  // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
6602  // The ressource is always allocated.
6603  ///////////////////////////////////////////////////////////////////////////////////
6604
6605  switch(r_alloc_trt_fsm.read())
6606  {
6607      ////////////////////
6608    case ALLOC_TRT_READ:
6609      if(r_read_fsm.read() != READ_TRT_LOCK)
6610      {
6611        if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
6612            (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
6613          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6614
6615        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
6616                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
6617          r_alloc_trt_fsm = ALLOC_TRT_CAS;
6618
6619        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
6620                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
6621          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6622
6623        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
6624                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
6625          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6626      }
6627      break;
6628
6629      /////////////////////
6630    case ALLOC_TRT_WRITE:
6631      if((r_write_fsm.read() != WRITE_MISS_TRT_LOCK) &&
6632          (r_write_fsm.read() != WRITE_BC_TRT_LOCK) &&
6633          (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
6634      {
6635        if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
6636            (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
6637          r_alloc_trt_fsm = ALLOC_TRT_CAS;
6638
6639        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
6640                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
6641          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6642
6643        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
6644                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
6645          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6646
6647        else if(r_read_fsm.read() == READ_TRT_LOCK)
6648          r_alloc_trt_fsm = ALLOC_TRT_READ;
6649      }
6650      break;
6651
6652      ////////////////////
6653    case ALLOC_TRT_CAS:
6654      if((r_cas_fsm.read() != CAS_MISS_TRT_LOCK) &&
6655          (r_cas_fsm.read() != CAS_BC_TRT_LOCK) &&
6656          (r_cas_fsm.read() != CAS_BC_UPT_LOCK))
6657      {
6658        if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
6659            (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
6660          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6661
6662        else if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
6663                (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
6664          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6665
6666        else if(r_read_fsm.read() == READ_TRT_LOCK)
6667          r_alloc_trt_fsm = ALLOC_TRT_READ;
6668
6669        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
6670                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
6671          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6672      }
6673      break;
6674
6675      ////////////////////////
6676    case ALLOC_TRT_XRAM_RSP:
6677      if(((r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK)  ||
6678          (r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP)) &&
6679          (r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY)  &&
6680          (r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT)  &&
6681          (r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK))
6682      {
6683        if((r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
6684            (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))
6685          r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6686
6687        else if(r_read_fsm.read() == READ_TRT_LOCK)
6688          r_alloc_trt_fsm = ALLOC_TRT_READ;
6689
6690        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
6691                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
6692          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6693
6694        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
6695                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
6696          r_alloc_trt_fsm = ALLOC_TRT_CAS;
6697      }
6698      break;
6699
6700      ////////////////////////
6701    case ALLOC_TRT_IXR_RSP:
6702      if((r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
6703          (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ))
6704      {
6705        if(r_read_fsm.read() == READ_TRT_LOCK)
6706          r_alloc_trt_fsm = ALLOC_TRT_READ;
6707
6708        else if((r_write_fsm.read() == WRITE_MISS_TRT_LOCK) ||
6709                (r_write_fsm.read() == WRITE_BC_TRT_LOCK))
6710          r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6711
6712        else if((r_cas_fsm.read() == CAS_MISS_TRT_LOCK) ||
6713                (r_cas_fsm.read() == CAS_BC_TRT_LOCK))
6714          r_alloc_trt_fsm = ALLOC_TRT_CAS;
6715
6716        else if((r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK) &&
6717                (r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP))
6718          r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6719      }
6720      break;
6721
6722  } // end switch alloc_trt_fsm
6723
6724  ////////////////////////////////////////////////////////////////////////////////////
6725  //    ALLOC_HEAP FSM
6726  ////////////////////////////////////////////////////////////////////////////////////
6727  // The ALLOC_HEAP FSM allocates the access to the heap
6728  // with a round robin priority between 5 user FSMs :
6729  // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
6730  // The ressource is always allocated.
6731  /////////////////////////////////////////////////////////////////////////////////////
6732
6733  switch(r_alloc_heap_fsm.read())
6734  {
6735      ////////////////////
6736    case ALLOC_HEAP_RESET:
6737      // Initializes the heap one ENTRY each cycle.
6738
6739      r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
6740
6741      if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1))
6742      {
6743        m_heap.init();
6744
6745        r_alloc_heap_fsm = ALLOC_HEAP_READ;
6746      }
6747      break;
6748
6749      ////////////////////
6750    case ALLOC_HEAP_READ:
6751      if((r_read_fsm.read() != READ_HEAP_REQ) &&
6752          (r_read_fsm.read() != READ_HEAP_LOCK) &&
6753          (r_read_fsm.read() != READ_HEAP_ERASE))
6754      {
6755        if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
6756          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6757
6758        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
6759          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6760
6761        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
6762          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6763
6764        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
6765          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6766      }
6767      break;
6768
6769      /////////////////////
6770    case ALLOC_HEAP_WRITE:
6771      if((r_write_fsm.read() != WRITE_UPT_HEAP_LOCK) &&
6772          (r_write_fsm.read() != WRITE_UPT_REQ) &&
6773          (r_write_fsm.read() != WRITE_UPT_NEXT))
6774      {
6775        if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
6776          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6777
6778        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
6779          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6780
6781        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
6782          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6783
6784        else if(r_read_fsm.read() == READ_HEAP_REQ)
6785          r_alloc_heap_fsm = ALLOC_HEAP_READ;
6786      }
6787      break;
6788
6789      ////////////////////
6790    case ALLOC_HEAP_CAS:
6791      if((r_cas_fsm.read() != CAS_UPT_HEAP_LOCK) &&
6792          (r_cas_fsm.read() != CAS_UPT_REQ) &&
6793          (r_cas_fsm.read() != CAS_UPT_NEXT))
6794      {
6795        if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
6796          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6797
6798        else if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
6799          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6800
6801        else if(r_read_fsm.read() == READ_HEAP_REQ)
6802          r_alloc_heap_fsm = ALLOC_HEAP_READ;
6803
6804        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
6805          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6806      }
6807      break;
6808
6809      ///////////////////////
6810    case ALLOC_HEAP_CLEANUP:
6811      if((r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) &&
6812          (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
6813          (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH) &&
6814          (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN))
6815      {
6816        if(r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ)
6817          r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6818
6819        else if(r_read_fsm.read() == READ_HEAP_REQ)
6820          r_alloc_heap_fsm = ALLOC_HEAP_READ;
6821
6822        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
6823          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6824
6825        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
6826          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6827      }
6828      break;
6829
6830      ////////////////////////
6831    case ALLOC_HEAP_XRAM_RSP:
6832      if((r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ) &&
6833          (r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE))
6834      {
6835        if(r_read_fsm.read() == READ_HEAP_REQ)
6836          r_alloc_heap_fsm = ALLOC_HEAP_READ;
6837
6838        else if(r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)
6839          r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6840
6841        else if(r_cas_fsm.read() == CAS_UPT_HEAP_LOCK)
6842          r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6843
6844        else if(r_cleanup_fsm.read() == CLEANUP_HEAP_REQ)
6845          r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6846
6847      }
6848      break;
6849
6850  } // end switch alloc_heap_fsm
6851
6852
6853  ////////////////////////////////////////////////////////////////////////////////////
6854  //    TGT_CMD to READ FIFO
6855  ////////////////////////////////////////////////////////////////////////////////////
6856
6857  if(cmd_read_fifo_put)
6858  {
6859    if(cmd_read_fifo_get)
6860    {
6861      m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6862      m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read() >>2);
6863      m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6864      m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6865      m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6866    }
6867    else
6868    {
6869      m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6870      m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read() >>2);
6871      m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6872      m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6873      m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6874    }
6875  }
6876  else
6877  {
6878    if(cmd_read_fifo_get)
6879    {
6880      m_cmd_read_addr_fifo.simple_get();
6881      m_cmd_read_length_fifo.simple_get();
6882      m_cmd_read_srcid_fifo.simple_get();
6883      m_cmd_read_trdid_fifo.simple_get();
6884      m_cmd_read_pktid_fifo.simple_get();
6885    }
6886  }
6887  /////////////////////////////////////////////////////////////////////
6888  //    TGT_CMD to WRITE FIFO
6889  /////////////////////////////////////////////////////////////////////
6890
6891  if(cmd_write_fifo_put)
6892  {
6893    if(cmd_write_fifo_get)
6894    {
6895      m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6896      m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6897      m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6898      m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6899      m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6900      m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
6901      m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
6902    }
6903    else
6904    {
6905      m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6906      m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
6907      m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6908      m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6909      m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6910      m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
6911      m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
6912    }
6913  }
6914  else
6915  {
6916    if(cmd_write_fifo_get)
6917    {
6918      m_cmd_write_addr_fifo.simple_get();
6919      m_cmd_write_eop_fifo.simple_get();
6920      m_cmd_write_srcid_fifo.simple_get();
6921      m_cmd_write_trdid_fifo.simple_get();
6922      m_cmd_write_pktid_fifo.simple_get();
6923      m_cmd_write_data_fifo.simple_get();
6924      m_cmd_write_be_fifo.simple_get();
6925    }
6926  }
6927  ////////////////////////////////////////////////////////////////////////////////////
6928  //    TGT_CMD to CAS FIFO
6929  ////////////////////////////////////////////////////////////////////////////////////
6930
6931  if(cmd_cas_fifo_put)
6932  {
6933    if(cmd_cas_fifo_get)
6934    {
6935      m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6936      m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6937      m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6938      m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6939      m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6940      m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
6941    }
6942    else
6943    {
6944      m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6945      m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
6946      m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6947      m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6948      m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6949      m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
6950    }
6951  }
6952  else
6953  {
6954    if(cmd_cas_fifo_get)
6955    {
6956      m_cmd_cas_addr_fifo.simple_get();
6957      m_cmd_cas_eop_fifo.simple_get();
6958      m_cmd_cas_srcid_fifo.simple_get();
6959      m_cmd_cas_trdid_fifo.simple_get();
6960      m_cmd_cas_pktid_fifo.simple_get();
6961      m_cmd_cas_wdata_fifo.simple_get();
6962    }
6963  }
6964  ////////////////////////////////////////////////////////////////////////////////////
6965  //    CC_RECEIVE to CLEANUP FIFO
6966  ////////////////////////////////////////////////////////////////////////////////////
6967
6968  if(cc_receive_to_cleanup_fifo_put)
6969  {
6970    if(cc_receive_to_cleanup_fifo_get)
6971    {
6972      m_cc_receive_to_cleanup_fifo.put_and_get(p_dspin_in.data.read());
6973    }
6974    else
6975    {
6976      m_cc_receive_to_cleanup_fifo.simple_put(p_dspin_in.data.read());
6977    }
6978  }
6979  else
6980  {
6981    if(cc_receive_to_cleanup_fifo_get)
6982    {
6983      m_cc_receive_to_cleanup_fifo.simple_get();
6984    }
6985  }
6986
6987  ////////////////////////////////////////////////////////////////////////////////////
6988  //    CC_RECEIVE to MULTI_ACK FIFO
6989  ////////////////////////////////////////////////////////////////////////////////////
6990
6991  if(cc_receive_to_multi_ack_fifo_put)
6992  {
6993    if(cc_receive_to_multi_ack_fifo_get)
6994    {
6995      m_cc_receive_to_multi_ack_fifo.put_and_get(p_dspin_in.data.read());
6996    }
6997    else
6998    {
6999      m_cc_receive_to_multi_ack_fifo.simple_put(p_dspin_in.data.read());
7000    }
7001  }
7002  else
7003  {
7004    if(cc_receive_to_multi_ack_fifo_get)
7005    {
7006      m_cc_receive_to_multi_ack_fifo.simple_get();
7007    }
7008  }
7009
7010  ////////////////////////////////////////////////////////////////////////////////////
7011  //    WRITE to CC_SEND FIFO
7012  ////////////////////////////////////////////////////////////////////////////////////
7013
7014  if(write_to_cc_send_fifo_put)
7015  {
7016    if(write_to_cc_send_fifo_get)
7017    {
7018      m_write_to_cc_send_inst_fifo.put_and_get(write_to_cc_send_fifo_inst);
7019      m_write_to_cc_send_srcid_fifo.put_and_get(write_to_cc_send_fifo_srcid);
7020#if L1_MULTI_CACHE
7021      m_write_to_cc_send_cache_id_fifo.put_and_get(write_to_cc_send_fifo_cache_id);
7022#endif
7023    }
7024    else
7025    {
7026      m_write_to_cc_send_inst_fifo.simple_put(write_to_cc_send_fifo_inst);
7027      m_write_to_cc_send_srcid_fifo.simple_put(write_to_cc_send_fifo_srcid);
7028#if L1_MULTI_CACHE
7029      m_write_to_cc_send_cache_id_fifo.simple_put(write_to_cc_send_fifo_cache_id);
7030#endif
7031    }
7032  }
7033  else
7034  {
7035    if(write_to_cc_send_fifo_get)
7036    {
7037      m_write_to_cc_send_inst_fifo.simple_get();
7038      m_write_to_cc_send_srcid_fifo.simple_get();
7039#if L1_MULTI_CACHE
7040      m_write_to_cc_send_cache_id_fifo.simple_get();
7041#endif
7042    }
7043  }
7044  ////////////////////////////////////////////////////////////////////////////////////
7045  //    XRAM_RSP to CC_SEND FIFO
7046  ////////////////////////////////////////////////////////////////////////////////////
7047
7048  if(xram_rsp_to_cc_send_fifo_put)
7049  {
7050    if(xram_rsp_to_cc_send_fifo_get)
7051    {
7052      m_xram_rsp_to_cc_send_inst_fifo.put_and_get(xram_rsp_to_cc_send_fifo_inst);
7053      m_xram_rsp_to_cc_send_srcid_fifo.put_and_get(xram_rsp_to_cc_send_fifo_srcid);
7054#if L1_MULTI_CACHE
7055      m_xram_rsp_to_cc_send_cache_id_fifo.put_and_get(xram_rsp_to_cc_send_fifo_cache_id);
7056#endif
7057    }
7058    else
7059    {
7060      m_xram_rsp_to_cc_send_inst_fifo.simple_put(xram_rsp_to_cc_send_fifo_inst);
7061      m_xram_rsp_to_cc_send_srcid_fifo.simple_put(xram_rsp_to_cc_send_fifo_srcid);
7062#if L1_MULTI_CACHE
7063      m_xram_rsp_to_cc_send_cache_id_fifo.simple_put(xram_rsp_to_cc_send_fifo_cache_id);
7064#endif
7065    }
7066  }
7067  else
7068  {
7069    if(xram_rsp_to_cc_send_fifo_get)
7070    {
7071      m_xram_rsp_to_cc_send_inst_fifo.simple_get();
7072      m_xram_rsp_to_cc_send_srcid_fifo.simple_get();
7073#if L1_MULTI_CACHE
7074      m_xram_rsp_to_cc_send_cache_id_fifo.simple_get();
7075#endif
7076    }
7077  }
7078  ////////////////////////////////////////////////////////////////////////////////////
7079  //    CAS to CC_SEND FIFO
7080  ////////////////////////////////////////////////////////////////////////////////////
7081
7082  if(cas_to_cc_send_fifo_put)
7083  {
7084    if(cas_to_cc_send_fifo_get)
7085    {
7086      m_cas_to_cc_send_inst_fifo.put_and_get(cas_to_cc_send_fifo_inst);
7087      m_cas_to_cc_send_srcid_fifo.put_and_get(cas_to_cc_send_fifo_srcid);
7088#if L1_MULTI_CACHE
7089      m_cas_to_cc_send_cache_id_fifo.put_and_get(cas_to_cc_send_fifo_cache_id);
7090#endif
7091    }
7092    else
7093    {
7094      m_cas_to_cc_send_inst_fifo.simple_put(cas_to_cc_send_fifo_inst);
7095      m_cas_to_cc_send_srcid_fifo.simple_put(cas_to_cc_send_fifo_srcid);
7096#if L1_MULTI_CACHE
7097      m_cas_to_cc_send_cache_id_fifo.simple_put(cas_to_cc_send_fifo_cache_id);
7098#endif
7099    }
7100  }
7101  else
7102  {
7103    if(cas_to_cc_send_fifo_get)
7104    {
7105      m_cas_to_cc_send_inst_fifo.simple_get();
7106      m_cas_to_cc_send_srcid_fifo.simple_get();
7107#if L1_MULTI_CACHE
7108      m_cas_to_cc_send_cache_id_fifo.simple_get();
7109#endif
7110    }
7111  }
7112
7113  m_cpt_cycles++;
7114
7115} // end transition()
7116
7117/////////////////////////////
7118tmpl(void)::genMoore()
7119/////////////////////////////
7120{
7121  ////////////////////////////////////////////////////////////
7122  // Command signals on the p_vci_ixr port
7123  ////////////////////////////////////////////////////////////
7124
7125  p_vci_ixr.be      = 0xF;
7126  p_vci_ixr.pktid   = 0;
7127  p_vci_ixr.srcid   = m_srcid_ixr;
7128  p_vci_ixr.cons    = false;
7129  p_vci_ixr.wrap    = false;
7130  p_vci_ixr.contig  = true;
7131  p_vci_ixr.clen    = 0;
7132  p_vci_ixr.cfixed  = false;
7133
7134  if(r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE)
7135  {
7136    p_vci_ixr.cmd     = vci_param::CMD_READ;
7137    p_vci_ixr.cmdval  = true;
7138    p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read() *m_words*4);
7139    p_vci_ixr.plen    = m_words*4;
7140    p_vci_ixr.wdata   = 0x00000000;
7141    p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
7142    p_vci_ixr.eop     = true;
7143  }
7144  else if(r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE)
7145  {
7146    if(r_cas_to_ixr_cmd_write.read())
7147    {
7148      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
7149      p_vci_ixr.cmdval  = true;
7150      p_vci_ixr.address = (addr_t)((r_cas_to_ixr_cmd_nline.read() *m_words+r_ixr_cmd_cpt.read()) *4);
7151      p_vci_ixr.plen    = m_words*4;
7152      p_vci_ixr.wdata   = r_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
7153      p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
7154      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
7155    }
7156    else
7157    {
7158      p_vci_ixr.cmd     = vci_param::CMD_READ;
7159      p_vci_ixr.cmdval  = true;
7160      p_vci_ixr.address = (addr_t)(r_cas_to_ixr_cmd_nline.read() *m_words*4);
7161      p_vci_ixr.plen    = m_words*4;
7162      p_vci_ixr.wdata   = 0x00000000;
7163      p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
7164      p_vci_ixr.eop     = true;
7165    }
7166  }
7167  else if(r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE)
7168  {
7169    if(r_write_to_ixr_cmd_write.read())
7170    {
7171      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
7172      p_vci_ixr.cmdval  = true;
7173      p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read() *m_words+r_ixr_cmd_cpt.read()) *4);
7174      p_vci_ixr.plen    = m_words*4;
7175      p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
7176      p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
7177      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
7178    }
7179    else
7180    {
7181      p_vci_ixr.cmd     = vci_param::CMD_READ;
7182      p_vci_ixr.cmdval  = true;
7183      p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read() *m_words*4);
7184      p_vci_ixr.plen    = m_words*4;
7185      p_vci_ixr.wdata   = 0x00000000;
7186      p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
7187      p_vci_ixr.eop     = true;
7188    }
7189  }
7190  else if(r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA)
7191  {
7192    p_vci_ixr.cmd     = vci_param::CMD_WRITE;
7193    p_vci_ixr.cmdval  = true;
7194    p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read() *m_words+r_ixr_cmd_cpt.read()) *4);
7195    p_vci_ixr.plen    = m_words*4;
7196    p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
7197    p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
7198    p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
7199  }
7200  else
7201  {
7202    p_vci_ixr.cmdval  = false;
7203    p_vci_ixr.address = 0;
7204    p_vci_ixr.plen    = 0;
7205    p_vci_ixr.wdata   = 0;
7206    p_vci_ixr.trdid   = 0;
7207    p_vci_ixr.eop = false;
7208  }
7209
7210  ////////////////////////////////////////////////////
7211  // Response signals on the p_vci_ixr port
7212  ////////////////////////////////////////////////////
7213
7214  if(((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
7215      (r_ixr_rsp_fsm.read()   == IXR_RSP_TRT_READ)) ||
7216      (r_ixr_rsp_fsm.read()   == IXR_RSP_ACK))
7217   
7218    p_vci_ixr.rspack = true;
7219
7220  else
7221    p_vci_ixr.rspack = false;
7222
7223  ////////////////////////////////////////////////////
7224  // Command signals on the p_vci_tgt port
7225  ////////////////////////////////////////////////////
7226
7227  switch((tgt_cmd_fsm_state_e) r_tgt_cmd_fsm.read())
7228  {
7229    case TGT_CMD_IDLE:
7230      p_vci_tgt.cmdack  = false;
7231      break;
7232
7233    case TGT_CMD_READ:
7234      p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
7235      break;
7236
7237    case TGT_CMD_WRITE:
7238      p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
7239      break;
7240
7241    case TGT_CMD_CAS:
7242      p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
7243      break;
7244
7245    default:
7246      p_vci_tgt.cmdack  = false;
7247      break;
7248  }
7249
7250  ////////////////////////////////////////////////////
7251  // Response signals on the p_vci_tgt port
7252  ////////////////////////////////////////////////////
7253  switch(r_tgt_rsp_fsm.read())
7254  {
7255    case TGT_RSP_READ_IDLE:
7256    case TGT_RSP_WRITE_IDLE:
7257    case TGT_RSP_CAS_IDLE:
7258    case TGT_RSP_XRAM_IDLE:
7259    case TGT_RSP_INIT_IDLE:
7260    case TGT_RSP_CLEANUP_IDLE:
7261      p_vci_tgt.rspval  = false;
7262      p_vci_tgt.rsrcid  = 0;
7263      p_vci_tgt.rdata   = 0;
7264      p_vci_tgt.rpktid  = 0;
7265      p_vci_tgt.rtrdid  = 0;
7266      p_vci_tgt.rerror  = 0;
7267      p_vci_tgt.reop    = false;
7268      break;
7269
7270    case TGT_RSP_READ:
7271      p_vci_tgt.rspval   = true;
7272      if(((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
7273          && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read() +r_read_to_tgt_rsp_length-1)))
7274        p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
7275      else if((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
7276        p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
7277      else
7278        p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
7279      p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
7280      p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
7281      p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
7282      p_vci_tgt.rerror   = 0;
7283      p_vci_tgt.reop     = (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read() +r_read_to_tgt_rsp_length-1));
7284      break;
7285
7286    case TGT_RSP_WRITE:
7287      p_vci_tgt.rspval   = true;
7288      if(((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read())
7289        p_vci_tgt.rdata  = 1;
7290      else
7291        p_vci_tgt.rdata  = 0;
7292      p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
7293      p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
7294      p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
7295      p_vci_tgt.rerror   = 0;
7296      p_vci_tgt.reop     = true;
7297      break;
7298
7299    case TGT_RSP_CLEANUP:
7300      p_vci_tgt.rspval   = true;
7301      p_vci_tgt.rdata    = 0;
7302      p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
7303      p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
7304      p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
7305      p_vci_tgt.rerror   = 0; // Can be a CAS rsp
7306      p_vci_tgt.reop     = true;
7307      break;
7308
7309    case TGT_RSP_CAS:
7310      p_vci_tgt.rspval   = true;
7311      p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
7312      p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
7313      p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
7314      p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
7315      p_vci_tgt.rerror   = 0;
7316      p_vci_tgt.reop     = true;
7317      break;
7318
7319    case TGT_RSP_XRAM:
7320      p_vci_tgt.rspval   = true;
7321      if(((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
7322          && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read() +r_xram_rsp_to_tgt_rsp_length-1)))
7323        p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
7324      else
7325        p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
7326      p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
7327      p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
7328      p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
7329      p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
7330      p_vci_tgt.reop     = ((r_tgt_rsp_cpt.read()
7331                             == (r_xram_rsp_to_tgt_rsp_word.read() +r_xram_rsp_to_tgt_rsp_length.read()-1))
7332                            || r_xram_rsp_to_tgt_rsp_rerror.read());
7333      break;
7334
7335    case TGT_RSP_INIT:
7336      p_vci_tgt.rspval   = true;
7337      p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
7338      p_vci_tgt.rsrcid   = r_multi_ack_to_tgt_rsp_srcid.read();
7339      p_vci_tgt.rtrdid   = r_multi_ack_to_tgt_rsp_trdid.read();
7340      p_vci_tgt.rpktid   = r_multi_ack_to_tgt_rsp_pktid.read();
7341      p_vci_tgt.rerror   = 0;
7342      p_vci_tgt.reop     = true;
7343      break;
7344  } // end switch r_tgt_rsp_fsm
7345
7346  ////////////////////////////////////////////////////////////////////
7347  // Initiator command signals on the p_dspin_out port (CC_SEND FSM)
7348  ////////////////////////////////////////////////////////////////////
7349  p_dspin_out.write = false;
7350  p_dspin_out.data  = 0;
7351
7352  switch(r_cc_send_fsm.read())
7353  {
7354    case CC_SEND_XRAM_RSP_IDLE:
7355    case CC_SEND_WRITE_IDLE:
7356    case CC_SEND_CAS_IDLE:
7357    case CC_SEND_CLEANUP_IDLE:
7358        break;
7359
7360    case CC_SEND_CLEANUP_ACK:
7361      {
7362        uint64_t flit = 0;
7363 
7364        uint8_t cleanup_ack_type;
7365        if(r_cleanup_to_cc_send_inst.read())
7366        {
7367          cleanup_ack_type = DspinDhccpParam::TYPE_CLEANUP_ACK_INST;
7368        }
7369        else 
7370        {
7371          cleanup_ack_type = DspinDhccpParam::TYPE_CLEANUP_ACK_DATA;
7372        }
7373
7374        DspinDhccpParam::dspin_set(
7375            flit,
7376            1ULL,
7377            DspinDhccpParam::FROM_MC_EOP);
7378
7379        DspinDhccpParam::dspin_set(
7380            flit,
7381            r_cleanup_to_cc_send_srcid.read(),
7382            DspinDhccpParam::CLEANUP_ACK_DEST);
7383
7384        DspinDhccpParam::dspin_set(
7385            flit,
7386            r_cleanup_to_cc_send_set_index.read(),
7387            DspinDhccpParam::CLEANUP_ACK_SET);
7388
7389        DspinDhccpParam::dspin_set(
7390            flit,
7391            r_cleanup_to_cc_send_way_index.read(),
7392            DspinDhccpParam::CLEANUP_ACK_WAY);
7393
7394        DspinDhccpParam::dspin_set(
7395            flit,
7396            cleanup_ack_type,
7397            DspinDhccpParam::FROM_MC_TYPE);
7398
7399        p_dspin_out.write = true;
7400        p_dspin_out.data  = flit;
7401
7402        break;
7403      }
7404
7405    case CC_SEND_XRAM_RSP_INVAL_HEADER:
7406      {
7407        if(not m_xram_rsp_to_cc_send_inst_fifo.rok()) break;
7408
7409        uint8_t multi_inval_type;
7410        if(m_xram_rsp_to_cc_send_inst_fifo.read())
7411        {
7412          multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_INST;
7413        }
7414        else 
7415        {
7416          multi_inval_type = DspinDhccpParam::TYPE_MULTI_INVAL_DATA;
7417        }
7418
7419        uint64_t flit = 0;
7420
7421        DspinDhccpParam::dspin_set(
7422            flit,
7423            m_xram_rsp_to_cc_send_srcid_fifo.read(),
7424            DspinDhccpParam::MULTI_INVAL_DEST);
7425
7426        DspinDhccpParam::dspin_set(
7427            flit,
7428            m_srcid_ini,
7429            DspinDhccpParam::MULTI_INVAL_SRCID);
7430
7431        DspinDhccpParam::dspin_set(
7432            flit,
7433            r_xram_rsp_to_cc_send_trdid.read(),
7434            DspinDhccpParam::MULTI_INVAL_UPDT_INDEX);
7435
7436        DspinDhccpParam::dspin_set(
7437            flit,
7438            multi_inval_type,
7439            DspinDhccpParam::FROM_MC_TYPE);
7440
7441        p_dspin_out.write = true;
7442        p_dspin_out.data  = flit; 
7443
7444        break;
7445      }
7446
7447    case CC_SEND_XRAM_RSP_INVAL_NLINE:
7448      {
7449        uint64_t flit = 0;
7450
7451        DspinDhccpParam::dspin_set(
7452            flit,
7453            1ULL,
7454            DspinDhccpParam::FROM_MC_EOP);
7455
7456        DspinDhccpParam::dspin_set(
7457            flit,
7458            r_xram_rsp_to_cc_send_nline.read(),
7459            DspinDhccpParam::MULTI_INVAL_NLINE);
7460       
7461
7462        p_dspin_out.write = true;
7463        p_dspin_out.data  = flit;
7464
7465        break;
7466      }
7467
7468    case CC_SEND_XRAM_RSP_BRDCAST_HEADER:
7469    case CC_SEND_WRITE_BRDCAST_HEADER:
7470    case CC_SEND_CAS_BRDCAST_HEADER:
7471      {
7472        uint64_t flit = 0;
7473
7474        DspinDhccpParam::dspin_set(
7475            flit,
7476            m_broadcast_address,
7477            DspinDhccpParam::BROADCAST_BOX);
7478
7479        DspinDhccpParam::dspin_set(
7480            flit,
7481            m_srcid_ini,
7482            DspinDhccpParam::BROADCAST_SRCID);
7483
7484        DspinDhccpParam::dspin_set(
7485            flit,
7486            1ULL,
7487            DspinDhccpParam::FROM_MC_BC);
7488
7489        p_dspin_out.write = true;
7490        p_dspin_out.data  = flit;
7491
7492        break;
7493      }
7494
7495    case CC_SEND_XRAM_RSP_BRDCAST_NLINE:
7496      {
7497        uint64_t flit = 0;
7498
7499        DspinDhccpParam::dspin_set(
7500            flit,
7501            1ULL,
7502            DspinDhccpParam::FROM_MC_EOP);
7503
7504        DspinDhccpParam::dspin_set(
7505            flit,
7506            r_xram_rsp_to_cc_send_nline.read(),
7507            DspinDhccpParam::BROADCAST_NLINE);
7508
7509        p_dspin_out.write = true;
7510        p_dspin_out.data  = flit;
7511
7512        break;
7513      }
7514
7515    case CC_SEND_WRITE_BRDCAST_NLINE:
7516      {
7517        uint64_t flit = 0;
7518
7519        DspinDhccpParam::dspin_set(
7520            flit,
7521            1ULL,
7522            DspinDhccpParam::FROM_MC_EOP);
7523
7524        DspinDhccpParam::dspin_set(
7525            flit,
7526            r_write_to_cc_send_nline.read(),
7527            DspinDhccpParam::BROADCAST_NLINE);
7528
7529        p_dspin_out.write = true;
7530        p_dspin_out.data  = flit;
7531
7532        break;
7533      }
7534
7535    case CC_SEND_CAS_BRDCAST_NLINE:
7536      {
7537        uint64_t flit = 0;
7538
7539        DspinDhccpParam::dspin_set(
7540            flit,
7541            1ULL,
7542            DspinDhccpParam::FROM_MC_EOP);
7543
7544        DspinDhccpParam::dspin_set(
7545            flit,
7546            r_cas_to_cc_send_nline.read(),
7547            DspinDhccpParam::BROADCAST_NLINE);
7548
7549        p_dspin_out.write = true;
7550        p_dspin_out.data  = flit;
7551
7552        break;
7553      }
7554
7555    case CC_SEND_WRITE_UPDT_HEADER:
7556      {
7557        if(not m_write_to_cc_send_inst_fifo.rok()) break;
7558
7559        uint8_t multi_updt_type;
7560        if(m_write_to_cc_send_inst_fifo.read())
7561        {
7562          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_INST;
7563        }
7564        else 
7565        {
7566          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_DATA;
7567        }
7568
7569        uint64_t flit = 0;
7570
7571        DspinDhccpParam::dspin_set(
7572            flit,
7573            m_write_to_cc_send_srcid_fifo.read(),
7574            DspinDhccpParam::MULTI_UPDT_DEST);
7575
7576        DspinDhccpParam::dspin_set(
7577            flit,
7578            m_srcid_ini,
7579            DspinDhccpParam::MULTI_UPDT_SRCID);
7580
7581        DspinDhccpParam::dspin_set(
7582            flit,
7583            r_write_to_cc_send_trdid.read(),
7584            DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
7585
7586        DspinDhccpParam::dspin_set(
7587            flit,
7588            multi_updt_type,
7589            DspinDhccpParam::FROM_MC_TYPE);
7590
7591        p_dspin_out.write = true;
7592        p_dspin_out.data  = flit;
7593
7594        break;
7595      }
7596
7597    case CC_SEND_WRITE_UPDT_NLINE:
7598      {
7599        uint64_t flit = 0;
7600
7601        DspinDhccpParam::dspin_set(
7602            flit,
7603            r_write_to_cc_send_index.read(),
7604            DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
7605
7606        DspinDhccpParam::dspin_set(
7607            flit,
7608            r_write_to_cc_send_nline.read(),
7609            DspinDhccpParam::MULTI_UPDT_NLINE);
7610
7611        p_dspin_out.write = true;
7612        p_dspin_out.data  = flit;
7613
7614        break;
7615      }
7616
7617    case CC_SEND_WRITE_UPDT_DATA:
7618      {
7619        uint8_t multi_updt_eop;
7620        if(  r_cc_send_cpt.read() ==
7621            (r_write_to_cc_send_count.read()-1))
7622        {
7623          multi_updt_eop = 1;
7624        }
7625        else
7626        {
7627          multi_updt_eop = 0;
7628        }
7629
7630        uint8_t multi_updt_cpt  = 
7631          r_cc_send_cpt.read() + r_write_to_cc_send_index.read();
7632
7633        uint8_t  multi_updt_be   = r_write_to_cc_send_be[multi_updt_cpt].read();
7634        uint32_t multi_updt_data = r_write_to_cc_send_data[multi_updt_cpt].read();
7635
7636        uint64_t flit = 0;
7637
7638        DspinDhccpParam::dspin_set(
7639            flit,
7640            (uint64_t)multi_updt_eop,
7641            DspinDhccpParam::FROM_MC_EOP);
7642
7643        DspinDhccpParam::dspin_set(
7644            flit,
7645            multi_updt_be,
7646            DspinDhccpParam::MULTI_UPDT_BE);
7647
7648        DspinDhccpParam::dspin_set(
7649            flit,
7650            multi_updt_data,
7651            DspinDhccpParam::MULTI_UPDT_DATA);
7652
7653        p_dspin_out.write = true;
7654        p_dspin_out.data  = flit;
7655
7656        break;
7657      }
7658
7659    case CC_SEND_CAS_UPDT_HEADER:
7660      {
7661        if (not m_cas_to_cc_send_inst_fifo.rok()) break;
7662
7663        uint8_t multi_updt_type;
7664        if(m_cas_to_cc_send_inst_fifo.read())
7665        {
7666          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_INST;
7667        }
7668        else 
7669        {
7670          multi_updt_type = DspinDhccpParam::TYPE_MULTI_UPDT_DATA;
7671        }
7672
7673        uint64_t flit = 0;
7674
7675        DspinDhccpParam::dspin_set(
7676            flit,
7677            m_cas_to_cc_send_srcid_fifo.read(),
7678            DspinDhccpParam::MULTI_UPDT_DEST);
7679
7680        DspinDhccpParam::dspin_set(
7681            flit,
7682            m_srcid_ini,
7683            DspinDhccpParam::MULTI_UPDT_SRCID);
7684
7685        DspinDhccpParam::dspin_set(
7686            flit,
7687            r_cas_to_cc_send_trdid.read(),
7688            DspinDhccpParam::MULTI_UPDT_UPDT_INDEX);
7689
7690        DspinDhccpParam::dspin_set(
7691            flit,
7692            multi_updt_type,
7693            DspinDhccpParam::FROM_MC_TYPE);
7694
7695        p_dspin_out.write = true;
7696        p_dspin_out.data  = flit;
7697
7698        break;
7699      }
7700
7701    case CC_SEND_CAS_UPDT_NLINE:
7702      {
7703        uint64_t flit = 0;
7704
7705        DspinDhccpParam::dspin_set(
7706            flit,
7707            r_cas_to_cc_send_index.read(),
7708            DspinDhccpParam::MULTI_UPDT_WORD_INDEX);
7709
7710        DspinDhccpParam::dspin_set(
7711            flit,
7712            r_cas_to_cc_send_nline.read(),
7713            DspinDhccpParam::MULTI_UPDT_NLINE);
7714
7715        p_dspin_out.write = true;
7716        p_dspin_out.data  = flit;
7717
7718        break;
7719      }
7720
7721    case CC_SEND_CAS_UPDT_DATA:
7722      {
7723        uint8_t multi_updt_eop;
7724        if(not r_cas_to_cc_send_is_long.read())
7725        {
7726          multi_updt_eop = 1;
7727        }
7728        else
7729        {
7730          multi_updt_eop = 0;
7731        }
7732
7733        uint64_t flit = 0;
7734
7735        DspinDhccpParam::dspin_set(
7736            flit,
7737            (uint64_t)multi_updt_eop,
7738            DspinDhccpParam::FROM_MC_EOP);
7739
7740        DspinDhccpParam::dspin_set(
7741            flit,
7742            0xF,
7743            DspinDhccpParam::MULTI_UPDT_BE);
7744
7745        DspinDhccpParam::dspin_set(
7746            flit,
7747            r_cas_to_cc_send_wdata.read(),
7748            DspinDhccpParam::MULTI_UPDT_DATA);
7749
7750        p_dspin_out.write = true;
7751        p_dspin_out.data  = flit;
7752
7753        break;
7754      }
7755
7756    case CC_SEND_CAS_UPDT_DATA_HIGH:
7757      {
7758        uint64_t flit = 0;
7759
7760        DspinDhccpParam::dspin_set(
7761            flit,
7762            1ULL,
7763            DspinDhccpParam::FROM_MC_EOP);
7764
7765        DspinDhccpParam::dspin_set(
7766            flit,
7767            0xF,
7768            DspinDhccpParam::MULTI_UPDT_BE);
7769
7770        DspinDhccpParam::dspin_set(
7771            flit,
7772            r_cas_to_cc_send_wdata_high.read(),
7773            DspinDhccpParam::MULTI_UPDT_DATA);
7774
7775        p_dspin_out.write = true;
7776        p_dspin_out.data  = flit;
7777
7778        break;
7779      }
7780  }
7781
7782  ///////////////////////////////////////////////////////////////////
7783  // Target command signals from the p_dspin_in port (CC_RECEIVE FSM)
7784  ///////////////////////////////////////////////////////////////////
7785  p_dspin_in.read = false;
7786  switch(r_cc_receive_fsm.read())
7787  {
7788    case CC_RECEIVE_IDLE:
7789      {
7790        break;
7791      }
7792    case CC_RECEIVE_CLEANUP:
7793      {
7794        p_dspin_in.read = m_cc_receive_to_cleanup_fifo.wok();
7795        break;
7796      }
7797    case CC_RECEIVE_MULTI_ACK:
7798      {
7799        p_dspin_in.read = m_cc_receive_to_multi_ack_fifo.wok();
7800        break;
7801      }
7802  }
7803  // end switch r_cc_send_fsm
7804} // end genMoore()
7805
7806}
7807} // end name space
7808
7809// Local Variables:
7810// tab-width: 2
7811// c-basic-offset: 2
7812// c-file-offsets:((innamespace . 0)(inline-open . 0))
7813// indent-tabs-mode: nil
7814// End:
7815
7816// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
Note: See TracBrowser for help on using the repository browser.