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

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

Erasing useless template parameters for the communication/dspin_dhccp_param class.

Modifying consequently the vci_mem_cache_dspin_coherence class to use the
dspin_dhccp_param class without templates.

Introducing in the vci_mem_cache and the vci_mem_cache_dspin_coherence modules
the state CAS_DIR_HIT_COMPARE.

Before this modification, the comparison between the expected data and the actual
data was done directly in the CAS_DIR_HIT_READ state using the data obtained in the
same cycle from the cache.

Now, the data obtained from the cache is stored in a buffer and the next cycle,
in the CAS_DIR_HIT_COMPARE state, the comparison is made using the data from the
buffer.

This modifications allows to eliminate a critical path obtained in the ASIC
synthesis of the memory cache.

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