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

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

Bugfix of previous commit in vci_mem_cache:

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