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

Last change on this file since 305 was 305, checked in by joannou, 11 years ago

In vci_mem_cache component:
Adding an assert for cleanup commands received with no copy in the directory
(such a cleanup should not be received by the vci_mem_cache)

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