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

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

Including TYPE_CLEANUP_ACK_INST and TYPE_CLEANUP_ACK_DATA in the
dspin_dhccp_param class. These types will be decoded by the L1 cache to do the
request to the concerned FSM (DATA/INST).

Including a communication register between the CLEANUP FSM and the CC_SEND FSM
to signal if the CLEANUP_ACK to send concerns the DATA or the INSTRUCTION cache
of the L1.

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