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

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

Modification in v5/vci_mem_cache

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

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