source: trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 377

Last change on this file since 377 was 367, checked in by cfuguet, 12 years ago

Modification in v5/vci_mem_cache

Aligning to left the SRCID into the DEST field in case of
coherence command coming from the Memory Cache.

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