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

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

Modification in vci_mem_cache:

  • Replacing "if" by "assert" in the WRITE_UPT_REQ state. The "if" condition must always be true as it has been verified in the previous WRITE_DIR_HIT

state.

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