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

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