source: trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp @ 340

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

Erasing always false condition in the if statement of the
WRITE_UPT_REQ state.

In this state the r_write_count register, is always bigger than 0.

  • 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.5 KB
Line 
1 /* -*- c++ -*-
2 * File       : vci_mem_cache_v4.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_v4.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 VciMemCacheV4<vci_param>
241
242  using soclib::common::uint32_log2;
243
244  ////////////////////////////////
245  //  Constructor
246  ////////////////////////////////
247
248  tmpl(/**/)::VciMemCacheV4(
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(/**/)::~VciMemCacheV4()
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)
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            if ( (entry.count==1) || (entry.is_cnt) )  // no access to the heap
3709            {
3710              r_cleanup_fsm = CLEANUP_DIR_WRITE;
3711            }
3712            else          // access to the heap
3713            {
3714              r_cleanup_fsm = CLEANUP_HEAP_REQ;
3715            }
3716          }
3717          else    // miss : we must check the update table
3718          {
3719            r_cleanup_fsm = CLEANUP_UPT_LOCK;
3720          }
3721
3722#if DEBUG_MEMC_CLEANUP
3723          if( m_debug_cleanup_fsm )
3724          {
3725            std::cout
3726              << "  <MEMC " << name()
3727              << ".CLEANUP_DIR_LOCK> Test directory status: " << std::hex
3728              << " line = " << r_cleanup_nline.read() * m_words * 4
3729              << " / hit = " << entry.valid
3730              << " / dir_id = " << entry.owner.srcid
3731              << " / dir_ins = " << entry.owner.inst
3732              << " / search_id = " << r_cleanup_srcid.read()
3733              << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
3734              << " / count = " << entry.count
3735              << " / is_cnt = " << entry.is_cnt << std::endl;
3736          }
3737#endif
3738        }
3739        else
3740        {
3741          std::cout << "VCI_MEM_CACHE ERROR " << name()
3742            << " CLEANUP_DIR_LOCK state"
3743            << " bad DIR allocation" << std::endl;
3744
3745          exit(0);
3746        }
3747        break;
3748      }
3749
3750      ///////////////////////
3751      case CLEANUP_DIR_WRITE:
3752      // Update the directory entry without heap access
3753      {
3754        if ( r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP )
3755        {
3756          std::cout << "VCI_MEM_CACHE ERROR " << name()
3757            << " CLEANUP_DIR_WRITE state"
3758            << " bad DIR allocation" << std::endl;
3759          exit(0);
3760        }
3761
3762        size_t way         = r_cleanup_way.read();
3763        size_t set         = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3764        bool cleanup_inst  = r_cleanup_trdid.read() & 0x1;
3765        bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
3766#if L1_MULTI_CACHE
3767            and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read())
3768#endif
3769            );
3770        bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
3771        bool match         = match_srcid && match_inst;
3772
3773        if (not r_cleanup_is_cnt.read() and not match) {
3774            std::cout
3775              << "VCI_MEM_CACHE ERROR : Cleanup request on a valid"
3776              << "entry using linked list mode with no corresponding"
3777              << "directory or heap entry"
3778              << std::endl;
3779
3780            exit(1);
3781        }
3782
3783        // update the cache directory (for the copies)
3784        DirectoryEntry entry;
3785        entry.valid       = true;
3786        entry.is_cnt      = r_cleanup_is_cnt.read();
3787        entry.dirty       = r_cleanup_dirty.read();
3788        entry.tag         = r_cleanup_tag.read();
3789        entry.lock        = r_cleanup_lock.read();
3790        entry.ptr         = r_cleanup_ptr.read();
3791        entry.count       = r_cleanup_count.read() - 1;
3792        entry.owner.srcid = 0;
3793        entry.owner.inst  = 0;
3794#if L1_MULTI_CACHE
3795        entry.owner.cache_id = 0;
3796#endif
3797
3798        m_cache_directory.write(set, way, entry);
3799
3800        r_cleanup_fsm = CLEANUP_RSP;
3801
3802#if DEBUG_MEMC_CLEANUP
3803        if( m_debug_cleanup_fsm )
3804        {
3805          std::cout
3806            << "  <MEMC " << name()
3807            << ".CLEANUP_DIR_WRITE> Update directory:" << std::hex
3808            << " line = " << r_cleanup_nline.read() * m_words * 4
3809            << " / dir_id = " << entry.owner.srcid
3810            << " / dir_ins = " << entry.owner.inst
3811            << " / count = " << entry.count
3812            << " / is_cnt = " << entry.is_cnt << std::endl;
3813        }
3814#endif
3815
3816        break;
3817      }
3818     
3819      ///////////////////////
3820      case CLEANUP_HEAP_REQ:
3821      // Get the lock to the HEAP directory
3822      {
3823        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3824        {
3825          r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3826        }
3827
3828#if DEBUG_MEMC_CLEANUP
3829        if( m_debug_cleanup_fsm )
3830        {
3831          std::cout
3832            << "  <MEMC " << name() << ".CLEANUP_HEAP_REQ> Requesting HEAP lock "
3833            << std::endl;
3834        }
3835#endif
3836        break;
3837      }
3838
3839      ///////////////////////
3840      case CLEANUP_HEAP_LOCK:
3841      // two cases are handled in this state:
3842      // - the matching copy is directly in the directory
3843      // - the matching copy is the first copy in the heap
3844      {
3845        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3846        {
3847          size_t way              = r_cleanup_way.read();
3848          size_t set              = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3849          HeapEntry heap_entry    = m_heap.read(r_cleanup_ptr.read());
3850          bool last               = (heap_entry.next == r_cleanup_ptr.read());
3851          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1;
3852
3853          // match_dir computation
3854          bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3855          bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
3856          bool match_dir          = match_dir_srcid and match_dir_inst;
3857#if L1_MULTI_CACHE
3858          match_dir = match_dir and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3859#endif
3860
3861          // match_heap computation
3862          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3863          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
3864          bool match_heap         = match_heap_srcid and match_heap_inst;
3865#if L1_MULTI_CACHE
3866          match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3867#endif
3868
3869          r_cleanup_prev_ptr      = r_cleanup_ptr.read();
3870          r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3871#if L1_MULTI_CACHE
3872          r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3873#endif
3874          r_cleanup_prev_inst     = heap_entry.owner.inst;
3875
3876          if (match_dir)
3877          // the matching copy is registered in the directory
3878          {
3879            // the copy registered in the directory must be replaced
3880            // by the first copy registered in the heap
3881            // and the corresponding entry must be freed
3882            DirectoryEntry dir_entry;
3883            dir_entry.valid          = true;
3884            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3885            dir_entry.dirty          = r_cleanup_dirty.read();
3886            dir_entry.tag            = r_cleanup_tag.read();
3887            dir_entry.lock           = r_cleanup_lock.read();
3888            dir_entry.ptr            = heap_entry.next;
3889            dir_entry.count          = r_cleanup_count.read()-1;
3890            dir_entry.owner.srcid    = heap_entry.owner.srcid;
3891#if L1_MULTI_CACHE
3892            dir_entry.owner.cache_id = heap_entry.owner.cache_id;
3893#endif
3894            dir_entry.owner.inst     = heap_entry.owner.inst;
3895
3896            m_cache_directory.write(set,way,dir_entry);
3897
3898            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3899            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3900          }
3901          else if (match_heap)
3902          // the matching copy is the first copy in the heap
3903          {
3904            // The first copy in heap must be freed
3905            // and the copy registered in directory must point to the next copy in heap
3906            DirectoryEntry dir_entry;
3907            dir_entry.valid          = true;
3908            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3909            dir_entry.dirty          = r_cleanup_dirty.read();
3910            dir_entry.tag            = r_cleanup_tag.read();
3911            dir_entry.lock           = r_cleanup_lock.read();
3912            dir_entry.ptr            = heap_entry.next;
3913            dir_entry.count          = r_cleanup_count.read()-1;
3914            dir_entry.owner.srcid    = r_cleanup_copy.read();
3915#if L1_MULTI_CACHE
3916            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3917#endif
3918            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3919
3920            m_cache_directory.write(set,way,dir_entry);
3921
3922            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3923            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3924          }
3925          else if(!last)
3926          // The matching copy is in the heap, but is not the first copy
3927          {
3928            // The directory entry must be modified to decrement count
3929            DirectoryEntry  dir_entry;
3930            dir_entry.valid          = true;
3931            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3932            dir_entry.dirty          = r_cleanup_dirty.read();
3933            dir_entry.tag            = r_cleanup_tag.read();
3934            dir_entry.lock           = r_cleanup_lock.read();
3935            dir_entry.ptr            = r_cleanup_ptr.read();
3936            dir_entry.count          = r_cleanup_count.read()-1;
3937            dir_entry.owner.srcid    = r_cleanup_copy.read();
3938#if L1_MULTI_CACHE
3939            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3940#endif
3941            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3942
3943            m_cache_directory.write(set,way,dir_entry);
3944
3945            r_cleanup_next_ptr       = heap_entry.next;
3946            r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
3947          }
3948          else
3949          {
3950            std::cout << "VCI_MEM_CACHE ERROR " << name()
3951              << " CLEANUP_HEAP_LOCK state"
3952              << " hit but copy not found" << std::endl;
3953            exit(0);
3954          }
3955
3956#if DEBUG_MEMC_CLEANUP
3957          if( m_debug_cleanup_fsm )
3958          {
3959            std::cout
3960              << "  <MEMC " << name() << ".CLEANUP_HEAP_LOCK> Checks matching:"
3961              << " line = " << r_cleanup_nline.read() * m_words * 4
3962              << " / dir_id = " << r_cleanup_copy.read()
3963              << " / dir_ins = " << r_cleanup_copy_inst.read()
3964              << " / heap_id = " << heap_entry.owner.srcid
3965              << " / heap_ins = " << heap_entry.owner.inst
3966              << " / search_id = " << r_cleanup_srcid.read()
3967              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3968          }
3969#endif
3970        }
3971        else
3972        {
3973          std::cout << "VCI_MEM_CACHE ERROR " << name()
3974            << " CLEANUP_HEAP_LOCK state"
3975            << " bad HEAP allocation" << std::endl;
3976
3977          exit(0);
3978        }
3979        break;
3980      }
3981
3982      /////////////////////////
3983      case CLEANUP_HEAP_SEARCH:  // This state is handling the case where the copy
3984      // is in the heap, but is not the first in the linked list
3985      {
3986        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3987        {
3988          std::cout << "VCI_MEM_CACHE ERROR " << name()
3989            << " CLEANUP_HEAP_SEARCH state"
3990            << " bad HEAP allocation" << std::endl;
3991          exit(0);
3992        }
3993
3994        HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
3995        bool last             = (heap_entry.next == r_cleanup_next_ptr.read());
3996        bool cleanup_inst     = r_cleanup_trdid.read() & 0x1;
3997        bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3998        bool match_heap_inst  = (heap_entry.owner.inst  == cleanup_inst);
3999        bool match_heap       = match_heap_srcid && match_heap_inst;
4000#if L1_MULTI_CACHE
4001        match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
4002#endif
4003
4004#if DEBUG_MEMC_CLEANUP
4005        if( m_debug_cleanup_fsm )
4006        {
4007          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Cheks matching:"
4008            << " line = " << r_cleanup_nline.read() * m_words * 4
4009            << " / heap_id = " << heap_entry.owner.srcid
4010            << " / heap_ins = " << heap_entry.owner.inst
4011            << " / search_id = " << r_cleanup_srcid.read()
4012            << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
4013            << " / last = " << last << std::endl;
4014        }
4015#endif
4016        if(match_heap) // the matching copy must be removed
4017        {
4018          r_cleanup_ptr = heap_entry.next; // reuse ressources
4019          r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
4020        }
4021        else
4022        {
4023          if ( last )
4024          {
4025            std::cout << "VCI_MEM_CACHE_ERROR " << name()
4026              << " CLEANUP_HEAP_SEARCH state"
4027              << " cleanup hit but copy not found" << std::endl;
4028            exit(0);
4029          }
4030          else // test the next in the linked list
4031          {
4032            r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
4033            r_cleanup_prev_srcid    = heap_entry.owner.srcid;
4034#if L1_MULTI_CACHE
4035            r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4036#endif
4037            r_cleanup_prev_inst     = heap_entry.owner.inst;
4038            r_cleanup_next_ptr      = heap_entry.next;
4039            r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
4040
4041#if DEBUG_MEMC_CLEANUP
4042            if( m_debug_cleanup_fsm )
4043            {
4044              std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
4045                << " line = " << r_cleanup_nline.read() * m_words * 4
4046                << " / heap_id = " << heap_entry.owner.srcid
4047                << " / heap_ins = " << heap_entry.owner.inst
4048                << " / search_id = " << r_cleanup_srcid.read()
4049                << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
4050            }
4051#endif
4052          }
4053        }
4054        break;
4055      }
4056
4057      ////////////////////////
4058      case CLEANUP_HEAP_CLEAN:  // remove a copy in the linked list
4059      {
4060        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4061        {
4062          std::cout << "VCI_MEM_CACHE ERROR " << name()
4063            << " CLEANUP_HEAP_CLEAN state"
4064            << "Bad HEAP allocation" << std::endl;
4065          exit(0);
4066        }
4067
4068        bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
4069        HeapEntry heap_entry;
4070        heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4071#if L1_MULTI_CACHE
4072        heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4073#endif
4074        heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4075       
4076        if(last) // this is the last entry of the list of copies
4077        {
4078          heap_entry.next     = r_cleanup_prev_ptr.read();
4079        }
4080        else  // this is not the last entry
4081        {
4082          heap_entry.next     = r_cleanup_ptr.read();
4083        }
4084
4085        m_heap.write(r_cleanup_prev_ptr.read(),heap_entry);
4086        r_cleanup_fsm = CLEANUP_HEAP_FREE;
4087
4088#if DEBUG_MEMC_CLEANUP
4089        if( m_debug_cleanup_fsm )
4090        {
4091          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Remove the copy in the linked list" << std::endl;
4092        }
4093#endif
4094        break;
4095      }
4096
4097      ///////////////////////
4098      case CLEANUP_HEAP_FREE:
4099      // The heap entry pointed by r_cleanup_next_ptr is freed
4100      // and becomes the head of the list of free entries
4101      {
4102        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4103        {
4104          std::cout
4105            << "VCI_MEM_CACHE ERROR " << name()
4106            << " CLEANUP_HEAP_CLEAN state" << std::endl
4107            << "Bad HEAP allocation" << std::endl;
4108
4109          exit(0);
4110        }
4111
4112        HeapEntry heap_entry;
4113        heap_entry.owner.srcid    = 0;
4114#if L1_MULTI_CACHE
4115        heap_entry.owner.cache_id = 0;
4116#endif
4117        heap_entry.owner.inst     = false;
4118
4119        if(m_heap.is_full())
4120        {
4121          heap_entry.next = r_cleanup_next_ptr.read();
4122        }
4123        else
4124        {
4125          heap_entry.next = m_heap.next_free_ptr();
4126        }
4127
4128        m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4129        m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4130        m_heap.unset_full();
4131
4132        r_cleanup_fsm = CLEANUP_RSP;
4133
4134#if DEBUG_MEMC_CLEANUP
4135        if( m_debug_cleanup_fsm )
4136        {
4137          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Update the list of free entries" << std::endl;
4138        }
4139#endif
4140        break;
4141      }
4142
4143      //////////////////////
4144      case CLEANUP_UPT_LOCK:
4145      {
4146        if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
4147        {
4148          size_t index = 0;
4149          bool hit_inval;
4150          hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
4151
4152          if ( !hit_inval ) // no pending inval
4153          {
4154
4155#if DEBUG_MEMC_CLEANUP
4156            if( m_debug_cleanup_fsm )
4157            {
4158              std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_LOCK> Unexpected cleanup with no corresponding UPT entry:"
4159                << " address = " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::endl;
4160            }
4161#endif
4162            r_cleanup_fsm = CLEANUP_RSP;
4163          }
4164          else    // pending inval
4165          {
4166            r_cleanup_write_srcid = m_update_tab.srcid(index);
4167            r_cleanup_write_trdid = m_update_tab.trdid(index);
4168            r_cleanup_write_pktid = m_update_tab.pktid(index);
4169            r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
4170            r_cleanup_fsm = CLEANUP_UPT_WRITE;
4171          }
4172          r_cleanup_index.write(index) ;
4173        }
4174        break;
4175      }
4176
4177      ///////////////////////
4178      case CLEANUP_UPT_WRITE:  // decrement response counter
4179      {
4180        size_t count = 0;
4181        m_update_tab.decrement(r_cleanup_index.read(), count);
4182        if ( count == 0 )
4183        {
4184          m_update_tab.clear(r_cleanup_index.read());
4185
4186#if DEBUG_MEMC_CLEANUP
4187          if( m_debug_cleanup_fsm )
4188          {
4189            std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_WRITE> Decrement response counter in UPT:"
4190              << " UPT_index = " << r_cleanup_index.read()
4191              << " rsp_count = " << count << std::endl;
4192          }
4193#endif
4194          if( r_cleanup_need_rsp.read() ) r_cleanup_fsm = CLEANUP_WRITE_RSP ;
4195          else                      r_cleanup_fsm = CLEANUP_RSP;
4196        }
4197        else
4198        {
4199          r_cleanup_fsm = CLEANUP_RSP ;
4200        }
4201        break;
4202      }
4203
4204      ///////////////////////
4205      case CLEANUP_WRITE_RSP: // Response to a previous write on the direct network
4206      {
4207        if( !r_cleanup_to_tgt_rsp_req.read() )
4208        {
4209          r_cleanup_to_tgt_rsp_req     = true;
4210          r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4211          r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4212          r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4213          r_cleanup_fsm                = CLEANUP_RSP;
4214
4215#if DEBUG_MEMC_CLEANUP
4216          if( m_debug_cleanup_fsm )
4217          {
4218            std::cout << "  <MEMC " << name() << ".CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
4219              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4220              << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read() << std::endl;
4221          }
4222#endif
4223        }
4224        break;
4225      }
4226
4227      /////////////////
4228      case CLEANUP_RSP: // Response to a cleanup on the coherence network
4229      {
4230        if ( p_vci_tgt_cleanup.rspack.read() )
4231        {
4232          r_cleanup_fsm = CLEANUP_IDLE;
4233
4234#if DEBUG_MEMC_CLEANUP
4235          if( m_debug_cleanup_fsm )
4236          {
4237            std::cout << "  <MEMC " << name() << ".CLEANUP_RSP> Send the response to a cleanup request:"
4238              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4239              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
4240          }
4241#endif
4242        }
4243        break;
4244      }
4245    } // end switch cleanup fsm
4246
4247    ////////////////////////////////////////////////////////////////////////////////////
4248    //    CAS FSM
4249    ////////////////////////////////////////////////////////////////////////////////////
4250    // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4251    // that are handled as "compare-and-swap instructions.
4252    //
4253    // This command contains two or four flits:
4254    // - In case of 32 bits atomic access, the first flit contains the value read
4255    // by a previous LL instruction, the second flit contains the value to be writen.
4256    // - In case of 64 bits atomic access, the 2 first flits contains the value read
4257    // by a previous LL instruction, the 2 next flits contains the value to be writen.
4258    //
4259    // The target address is cachable. If it is replicated in other L1 caches
4260    // than the writer, a coherence operation is done.
4261    //
4262    // It access the directory to check hit / miss.
4263    // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4264    // If a read transaction to the XRAM for this line already exists,
4265    // or if the transaction table is full, it goes to the WAIT state
4266    // to release the locks and try again. When the GET transaction has been
4267    // launched, it goes to the WAIT state and try again.
4268    // The CAS request is not consumed in the FIFO until a HIT is obtained.
4269    // - In case of hit...
4270    ///////////////////////////////////////////////////////////////////////////////////
4271
4272    switch ( r_cas_fsm.read() )
4273    {
4274        /////////////
4275        case CAS_IDLE:     // fill the local rdata buffers
4276        {
4277            if( m_cmd_cas_addr_fifo.rok() )
4278            {
4279
4280#if DEBUG_MEMC_CAS
4281if( m_debug_cas_fsm )
4282{
4283    std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
4284              << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4285              << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4286              << " wdata = " << m_cmd_cas_wdata_fifo.read()
4287              << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4288              << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4289}
4290#endif
4291                if( m_cmd_cas_eop_fifo.read() )
4292                {
4293                    m_cpt_cas++;
4294                    r_cas_fsm = CAS_DIR_REQ;
4295                }
4296                else  // we keep the last word in the FIFO
4297                {
4298                    cmd_cas_fifo_get = true;
4299                }
4300                // We fill the two buffers
4301                if ( r_cas_cpt.read() < 2 ) // 32 bits access
4302                    r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4303
4304                if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4305                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4306
4307                if( r_cas_cpt.read()>3 ) // more than 4 flits...
4308                {
4309                    std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4310                              << std::endl;
4311                    exit(0);
4312                }
4313
4314                if ( r_cas_cpt.read()==2 )
4315                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4316
4317                r_cas_cpt = r_cas_cpt.read()+1;
4318            }
4319            break;
4320        }
4321       
4322        /////////////////
4323        case CAS_DIR_REQ:
4324        {
4325            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4326            {
4327              r_cas_fsm = CAS_DIR_LOCK;
4328            }
4329
4330#if DEBUG_MEMC_CAS
4331            if( m_debug_cas_fsm )
4332            {
4333              std::cout
4334                << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
4335                << std::endl;
4336            }
4337#endif
4338            break;
4339        }
4340
4341        /////////////////
4342        case CAS_DIR_LOCK:  // Read the directory
4343        {
4344            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4345            {
4346                size_t way = 0;
4347                DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4348
4349                r_cas_is_cnt     = entry.is_cnt;
4350                r_cas_dirty      = entry.dirty;
4351                r_cas_tag        = entry.tag;
4352                r_cas_way        = way;
4353                r_cas_copy       = entry.owner.srcid;
4354#if L1_MULTI_CACHE
4355                r_cas_copy_cache = entry.owner.cache_id;
4356#endif
4357                r_cas_copy_inst  = entry.owner.inst;
4358                r_cas_ptr        = entry.ptr;
4359                r_cas_count      = entry.count;
4360
4361                if ( entry.valid )  r_cas_fsm = CAS_DIR_HIT_READ;
4362                else          r_cas_fsm = CAS_MISS_TRT_LOCK;
4363
4364#if DEBUG_MEMC_CAS
4365if( m_debug_cas_fsm )
4366{
4367    std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
4368              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4369              << " / hit = " << std::dec << entry.valid
4370              << " / count = " << entry.count
4371              << " / is_cnt = " << entry.is_cnt << std::endl;
4372}
4373#endif
4374            }
4375            else
4376            {
4377              std::cout
4378                << "VCI_MEM_CACHE ERROR " << name()
4379                << " CAS_DIR_LOCK state" << std::endl
4380                << "Bad DIR allocation"   << std::endl;
4381
4382              exit(0);
4383            }
4384
4385            break;
4386        }
4387        /////////////////////
4388        case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4389                               // and check data change in cache
4390        {
4391            size_t way  = r_cas_way.read();
4392            size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4393            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4394
4395            // update directory (lock & dirty bits)
4396            DirectoryEntry entry;
4397            entry.valid          = true;
4398            entry.is_cnt         = r_cas_is_cnt.read();
4399            entry.dirty          = true;
4400            entry.lock           = true;
4401            entry.tag          = r_cas_tag.read();
4402            entry.owner.srcid    = r_cas_copy.read();
4403#if L1_MULTI_CACHE
4404            entry.owner.cache_id = r_cas_copy_cache.read();
4405#endif
4406            entry.owner.inst     = r_cas_copy_inst.read();
4407            entry.count          = r_cas_count.read();
4408            entry.ptr            = r_cas_ptr.read();
4409
4410            m_cache_directory.write(set, way, entry);
4411
4412            // read data in cache & check data change
4413            bool ok = ( r_cas_rdata[0].read() == m_cache_data.read(way, set, word) );
4414            if ( r_cas_cpt.read()==4 )  // 64 bits CAS
4415                ok &= ( r_cas_rdata[1] == m_cache_data.read(way, set, word+1));
4416
4417            // to avoid livelock, force the atomic access to fail pseudo-randomly
4418            bool forced_fail = ( (r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS );
4419            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((-(r_cas_lfsr & 1)) & 0xd0000001);
4420
4421            if( ok and not forced_fail )  // no data change
4422            {
4423                r_cas_fsm = CAS_DIR_HIT_WRITE;
4424            }
4425            else                            // return failure
4426            {
4427                r_cas_fsm = CAS_RSP_FAIL;
4428            }
4429
4430#if DEBUG_MEMC_CAS
4431if( m_debug_cas_fsm )
4432{
4433    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Test if CAS success:"
4434              << " / expected value = " << r_cas_rdata[0].read()
4435              << " / actual value = " << m_cache_data.read(way, set, word)
4436              << " / forced_fail = " << forced_fail << std::endl;
4437}
4438#endif
4439            break;
4440        }
4441        //////////////////////
4442        case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4443                                   // write data in cache if no CC request
4444        {
4445            // The CAS is a success => sw access to the llsc_global_table
4446            m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
4447
4448            // test coherence request
4449            if(r_cas_count.read())   // replicated line
4450            {
4451                if ( r_cas_is_cnt.read() )
4452                {
4453                    r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4454                }
4455                else if( !r_cas_to_init_cmd_multi_req.read() &&
4456                         !r_cas_to_init_cmd_brdcast_req.read()  )
4457                {
4458                    r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4459                }
4460                else
4461                {
4462                    r_cas_fsm = CAS_WAIT;
4463                }
4464            }
4465            else                    // no copies
4466            {
4467                size_t way  = r_cas_way.read();
4468                size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4469                size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4470
4471                // cache update
4472                m_cache_data.write(way, set, word, r_cas_wdata.read());
4473                if(r_cas_cpt.read()==4)
4474                    m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4475
4476                // monitor
4477                if ( m_monitor_ok )
4478                {
4479                    vci_addr_t address = m_cmd_cas_addr_fifo.read();
4480                char buf[80];
4481                snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4482                    check_monitor( buf, address, r_cas_wdata.read() );
4483                    if ( r_cas_cpt.read()==4 )
4484                    check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4485                }
4486                r_cas_fsm = CAS_RSP_SUCCESS;
4487
4488#if DEBUG_MEMC_CAS
4489if( m_debug_cas_fsm )
4490{
4491    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
4492              << " way = " << std::dec << way
4493              << " / set = " << set
4494              << " / word = " << word
4495              << " / value = " << r_cas_wdata.read()
4496              << " / count = " << r_cas_count.read() << std::endl;
4497    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
4498}
4499#endif
4500            }
4501            break;
4502        }
4503        /////////////////
4504        case CAS_UPT_LOCK:  // try to register the transaction in UPT
4505                           // and write data in cache if successful registration
4506                           // releases locks to retry later if UPT full
4507        {
4508            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4509            {
4510                bool        wok        = false;
4511                size_t      index      = 0;
4512                size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4513                size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4514                size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4515                addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4516                size_t      nb_copies  = r_cas_count.read();
4517
4518                wok = m_update_tab.set(true,  // it's an update transaction
4519                                       false,   // it's not a broadcast
4520                                       true,    // it needs a response
4521                                       srcid,
4522                                       trdid,
4523                                       pktid,
4524                                       nline,
4525                                       nb_copies,
4526                                       index);
4527                if (wok)  // coherence transaction registered in UPT
4528                {
4529                    // cache update
4530                    size_t way  = r_cas_way.read();
4531                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4532                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4533
4534                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4535                    if(r_cas_cpt.read()==4)
4536                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4537
4538                    // monitor
4539                    if ( m_monitor_ok )
4540                    {
4541                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4542                    char buf[80];
4543                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4544                        check_monitor( buf, address, r_cas_wdata.read() );
4545                        if ( r_cas_cpt.read()==4 )
4546                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4547                    }
4548
4549                    r_cas_upt_index = index;
4550                    r_cas_fsm = CAS_UPT_HEAP_LOCK;
4551                }
4552                else       //  releases the locks protecting UPT and DIR UPT full
4553                {
4554                    r_cas_fsm = CAS_WAIT;
4555                }
4556
4557#if DEBUG_MEMC_CAS
4558if( m_debug_cas_fsm )
4559{
4560    std::cout << "  <MEMC " << name() << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
4561              << " / wok = " << wok
4562              << " / nline  = " << std::hex << nline
4563              << " / count = " << nb_copies << std::endl;
4564}
4565#endif
4566            }
4567            break;
4568        }
4569        /////////////
4570        case CAS_WAIT:   // release all locks and retry from beginning
4571        {
4572
4573#if DEBUG_MEMC_CAS
4574if( m_debug_cas_fsm )
4575{
4576    std::cout << "  <MEMC " << name() << ".CAS_WAIT> Release all locks" << std::endl;
4577}
4578#endif
4579            r_cas_fsm = CAS_DIR_REQ;
4580            break;
4581        }
4582        //////////////////
4583        case CAS_UPT_HEAP_LOCK:  // lock the heap
4584        {
4585            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS )
4586            {
4587
4588#if DEBUG_MEMC_CAS
4589if( m_debug_cas_fsm )
4590{
4591    std::cout << "  <MEMC " << name() << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4592}
4593#endif
4594                r_cas_fsm = CAS_UPT_REQ;
4595            }
4596            break;
4597        }
4598        ////////////////
4599        case CAS_UPT_REQ:  // send a first update request to INIT_CMD FSM
4600        {
4601            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4602                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4603
4604            if( !r_cas_to_init_cmd_multi_req.read() && !r_cas_to_init_cmd_brdcast_req.read() )
4605            {
4606                r_cas_to_init_cmd_brdcast_req  = false;
4607                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4608                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4609                r_cas_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4610                r_cas_to_init_cmd_wdata        = r_cas_wdata.read();
4611
4612                if(r_cas_cpt.read() == 4)
4613                {
4614                    r_cas_to_init_cmd_is_long    = true;
4615                    r_cas_to_init_cmd_wdata_high = m_cmd_cas_wdata_fifo.read();
4616                }
4617                else
4618                {
4619                    r_cas_to_init_cmd_is_long    = false;
4620                    r_cas_to_init_cmd_wdata_high = 0;
4621                }
4622
4623                // We put the first copy in the fifo
4624                cas_to_init_cmd_fifo_put     = true;
4625                cas_to_init_cmd_fifo_inst    = r_cas_copy_inst.read();
4626                cas_to_init_cmd_fifo_srcid   = r_cas_copy.read();
4627#if L1_MULTI_CACHE
4628                cas_to_init_cmd_fifo_cache_id= r_cas_copy_cache.read();
4629#endif
4630                if(r_cas_count.read() == 1) // one single copy
4631                {
4632                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4633                                            // update responses
4634                    cmd_cas_fifo_get            = true;
4635                    r_cas_to_init_cmd_multi_req = true;
4636                    r_cas_cpt = 0;
4637                }
4638                else      // several copies
4639                {
4640                    r_cas_fsm = CAS_UPT_NEXT;
4641                }
4642
4643#if DEBUG_MEMC_CAS
4644if( m_debug_cas_fsm )
4645{
4646    std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to INIT_CMD FSM "
4647              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4648              << " / wdata = " << std::hex << r_cas_wdata.read()
4649              << " / srcid = " << std::dec << r_cas_copy.read()
4650              << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
4651}
4652#endif
4653            }
4654            break;
4655        }
4656        /////////////////
4657        case CAS_UPT_NEXT:     // send a multi-update request to INIT_CMD FSM
4658        {
4659            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4660                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4661
4662            HeapEntry entry = m_heap.read(r_cas_ptr.read());
4663            cas_to_init_cmd_fifo_srcid    = entry.owner.srcid;
4664#if L1_MULTI_CACHE
4665            cas_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
4666#endif
4667            cas_to_init_cmd_fifo_inst     = entry.owner.inst;
4668            cas_to_init_cmd_fifo_put = true;
4669
4670            if( m_cas_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
4671            {
4672                r_cas_ptr = entry.next;
4673                if( entry.next == r_cas_ptr.read() )  // last copy
4674                {
4675                    r_cas_to_init_cmd_multi_req = true;
4676                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4677                                            // all update responses
4678                    cmd_cas_fifo_get = true;
4679                    r_cas_cpt        = 0;
4680                }
4681            }
4682
4683#if DEBUG_MEMC_CAS
4684if( m_debug_cas_fsm )
4685{
4686    std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to INIT_CMD FSM "
4687              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4688              << " / wdata = " << std::hex << r_cas_wdata.read()
4689              << " / srcid = " << std::dec << entry.owner.srcid
4690              << " / inst = " << std::dec << entry.owner.inst << std::endl;
4691}
4692#endif
4693            break;
4694        }
4695        /////////////////////
4696        case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
4697        {
4698            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4699            {
4700                if( !r_cas_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
4701                {
4702                    // fill the data buffer
4703                    size_t way  = r_cas_way.read();
4704                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4705                        size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4706                    for(size_t i = 0; i<m_words; i++)
4707                    {
4708                        if (i == word)
4709                        {
4710                            r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
4711                        }
4712                        else if ( (i == word+1) && (r_cas_cpt.read()==4) ) // 64 bit CAS
4713                        {
4714                            r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
4715                        }
4716                        else
4717                        {
4718                            r_cas_to_ixr_cmd_data[i] = m_cache_data.read(way, set, i);
4719                        }
4720                    }
4721                    size_t wok_index = 0;
4722                    bool   wok       = !m_transaction_tab.full(wok_index);
4723                    if ( wok )
4724                    {
4725                        r_cas_trt_index = wok_index;
4726                        r_cas_fsm       = CAS_BC_UPT_LOCK;
4727                    }
4728                    else
4729                    {
4730                        r_cas_fsm       = CAS_WAIT;
4731                    }
4732                }
4733                else
4734                {
4735                    r_cas_fsm = CAS_WAIT;
4736                }
4737            }
4738            break;
4739        }
4740        ///////////////////
4741        case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
4742                              // write data in cache in case of successful registration
4743        {
4744            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4745            {
4746                bool        wok       = false;
4747                size_t      index     = 0;
4748                size_t      srcid     = m_cmd_cas_srcid_fifo.read();
4749                size_t      trdid     = m_cmd_cas_trdid_fifo.read();
4750                size_t      pktid     = m_cmd_cas_pktid_fifo.read();
4751                addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4752                size_t      nb_copies = r_cas_count.read();
4753
4754                // register a broadcast inval transaction in UPT
4755                wok = m_update_tab.set(false, // it's an inval transaction
4756                                       true,    // it's a broadcast
4757                                       true,    // it needs a response
4758                                       srcid,
4759                                       trdid,
4760                                       pktid,
4761                                       nline,
4762                                       nb_copies,
4763                                       index);
4764
4765                if ( wok )  // UPT not full
4766                {
4767                    // cache update
4768                    size_t way  = r_cas_way.read();
4769                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4770                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4771
4772                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4773                    if(r_cas_cpt.read()==4)
4774                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4775
4776                    // monitor
4777                    if ( m_monitor_ok )
4778                    {
4779                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4780                    char buf[80];
4781                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4782                        check_monitor( buf, address, r_cas_wdata.read() );
4783                        if ( r_cas_cpt.read()==4 )
4784                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4785                    }
4786                    r_cas_upt_index = index;
4787                    r_cas_fsm = CAS_BC_DIR_INVAL;
4788#if DEBUG_MEMC_CAS
4789if( m_debug_cas_fsm )
4790{
4791    std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
4792              << " / nline = " << nline
4793              << " / count = " << nb_copies
4794              << " / upt_index = " << index << std::endl;
4795}
4796#endif
4797                }
4798                else      //  releases the lock protecting UPT
4799                {
4800                     r_cas_fsm = CAS_WAIT;
4801                }
4802            }
4803            break;
4804        }
4805        //////////////////
4806        case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
4807        {
4808            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS ) &&
4809                 (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS ) &&
4810                 (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS ))
4811            {
4812                // set TRT
4813                m_transaction_tab.set(r_cas_trt_index.read(),
4814                                      false,    // PUT request to XRAM
4815                                      m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())],
4816                                      0,
4817                                      0,
4818                                      0,
4819                                      false,    // not a processor read
4820                                      0,
4821                                      0,
4822                                      std::vector<be_t>(m_words,0),
4823                                      std::vector<data_t>(m_words,0));
4824
4825                // invalidate directory entry
4826                DirectoryEntry entry;
4827                entry.valid         = false;
4828                entry.dirty         = false;
4829                entry.tag         = 0;
4830                entry.is_cnt        = false;
4831                entry.lock          = false;
4832                entry.count         = 0;
4833                entry.owner.srcid   = 0;
4834#if L1_MULTI_CACHE
4835                entry.owner.cache_id= 0;
4836#endif
4837                entry.owner.inst    = false;
4838                entry.ptr           = 0;
4839                size_t set          = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4840                size_t way          = r_cas_way.read();
4841                m_cache_directory.write(set, way, entry);
4842
4843                r_cas_fsm = CAS_BC_CC_SEND;
4844
4845#if DEBUG_MEMC_CAS
4846if( m_debug_cas_fsm )
4847{
4848    std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
4849              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
4850              << " / set = " << std::dec << set << " / way = " << way << std::endl;
4851}
4852#endif
4853            }
4854            else
4855            {
4856                assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
4857            }
4858            break;
4859        }
4860        ///////////////////
4861        case CAS_BC_CC_SEND:  // Request the broadcast inval to INIT_CMD FSM
4862        {
4863            if ( !r_cas_to_init_cmd_multi_req.read() &&
4864                 !r_cas_to_init_cmd_brdcast_req.read())
4865            {
4866                r_cas_to_init_cmd_multi_req    = false;
4867                r_cas_to_init_cmd_brdcast_req  = true;
4868                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4869                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4870                r_cas_to_init_cmd_index        = 0;
4871                r_cas_to_init_cmd_wdata        = 0;
4872
4873                r_cas_fsm = CAS_BC_XRAM_REQ;
4874            }
4875            break;
4876        }
4877        ////////////////////
4878        case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
4879        {
4880            if ( !r_cas_to_ixr_cmd_req )
4881            {
4882                r_cas_to_ixr_cmd_req     = true;
4883                r_cas_to_ixr_cmd_write   = true;
4884                r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4885                r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
4886                r_cas_fsm                = CAS_IDLE;
4887                cmd_cas_fifo_get         = true;
4888                r_cas_cpt                = 0;
4889
4890#if DEBUG_MEMC_CAS
4891if( m_debug_cas_fsm )
4892{
4893    std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
4894              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
4895              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
4896}
4897#endif
4898            }
4899            else
4900            {
4901               std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
4902                         << std::endl;
4903            }
4904            break;
4905        }
4906        /////////////////
4907        case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
4908        {
4909            if( !r_cas_to_tgt_rsp_req )
4910            {
4911                cmd_cas_fifo_get     = true;
4912                r_cas_cpt              = 0;
4913                r_cas_to_tgt_rsp_req = true;
4914                r_cas_to_tgt_rsp_data  = 1;
4915                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4916                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4917                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4918                r_cas_fsm              = CAS_IDLE;
4919
4920#if DEBUG_MEMC_CAS
4921if( m_debug_cas_fsm )
4922{
4923    std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
4924}
4925#endif
4926            }
4927            break;
4928        }
4929        ////////////////////
4930        case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
4931        {
4932            if( !r_cas_to_tgt_rsp_req )
4933            {
4934                cmd_cas_fifo_get       = true;
4935                r_cas_cpt              = 0;
4936                r_cas_to_tgt_rsp_req = true;
4937                r_cas_to_tgt_rsp_data  = 0;
4938                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4939                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4940                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4941                r_cas_fsm              = CAS_IDLE;
4942
4943#if DEBUG_MEMC_CAS
4944if( m_debug_cas_fsm )
4945{
4946    std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
4947}
4948#endif
4949            }
4950            break;
4951        }
4952        /////////////////////
4953        case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
4954        {
4955            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4956            {
4957                size_t   index = 0;
4958                bool hit_read = m_transaction_tab.hit_read(
4959                                  m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],index);
4960                bool hit_write = m_transaction_tab.hit_write(
4961                                   m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]);
4962                bool wok = !m_transaction_tab.full(index);
4963
4964#if DEBUG_MEMC_CAS
4965if( m_debug_cas_fsm )
4966{
4967    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_LOCK> Check TRT state"
4968              << " / hit_read = "  << hit_read
4969              << " / hit_write = " << hit_write
4970              << " / wok = " << wok
4971              << " / index = " << index << std::endl;
4972}
4973#endif
4974
4975                if ( hit_read || !wok || hit_write ) // missing line already requested or no space in TRT
4976                {
4977                    r_cas_fsm = CAS_WAIT;
4978                }
4979                else
4980                {
4981                    r_cas_trt_index = index;
4982                    r_cas_fsm       = CAS_MISS_TRT_SET;
4983                }
4984            }
4985            break;
4986        }
4987        ////////////////////
4988        case CAS_MISS_TRT_SET: // register the GET transaction in TRT
4989        {
4990            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4991            {
4992                std::vector<be_t> be_vector;
4993                std::vector<data_t> data_vector;
4994                be_vector.clear();
4995                data_vector.clear();
4996                for ( size_t i=0; i<m_words; i++ )
4997                {
4998                    be_vector.push_back(0);
4999                    data_vector.push_back(0);
5000                }
5001
5002                m_transaction_tab.set(r_cas_trt_index.read(),
5003                                      true,   // read request
5004                                      m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],
5005                                      m_cmd_cas_srcid_fifo.read(),
5006                                      m_cmd_cas_trdid_fifo.read(),
5007                                      m_cmd_cas_pktid_fifo.read(),
5008                                      false,    // write request from processor
5009                                      0,
5010                                      0,
5011                                      be_vector,
5012                                      data_vector);
5013                r_cas_fsm = CAS_MISS_XRAM_REQ;
5014
5015#if DEBUG_MEMC_CAS
5016if( m_debug_cas_fsm )
5017{
5018    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
5019              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
5020              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5021}
5022#endif
5023            }
5024            break;
5025        }
5026        //////////////////////
5027        case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
5028        {
5029            if ( !r_cas_to_ixr_cmd_req )
5030            {
5031                r_cas_to_ixr_cmd_req        = true;
5032                r_cas_to_ixr_cmd_write      = false;
5033                r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
5034                r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()];
5035                r_cas_fsm                   = CAS_WAIT;
5036
5037#if DEBUG_MEMC_CAS
5038if( m_debug_cas_fsm )
5039{
5040    std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
5041              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
5042              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5043}
5044#endif
5045            }
5046            break;
5047        }
5048    } // end switch r_cas_fsm
5049
5050
5051    //////////////////////////////////////////////////////////////////////////////
5052    //    INIT_CMD FSM
5053    //////////////////////////////////////////////////////////////////////////////
5054    // The INIT_CMD fsm controls the VCI CMD initiator port on the coherence
5055    // network, used to update or invalidate cache lines in L1 caches.
5056    //
5057    // It implements a round-robin priority between the three possible client FSMs
5058    // XRAM_RSP, WRITE and CAS. Each FSM can request two types of services:
5059    // - r_xram_rsp_to_init_cmd_multi_req : multi-inval
5060    //   r_xram_rsp_to_init_cmd_brdcast_req : broadcast-inval
5061    // - r_write_to_init_cmd_multi_req : multi-update
5062    //   r_write_to_init_cmd_brdcast_req : broadcast-inval
5063    // - r_cas_to_init_cmd_multi_req : multi-update
5064    //   r_cas_to_init_cmd_brdcast_req : broadcast-inval
5065    //
5066    // An inval request is a single cell VCI write command containing the
5067    // index of the line to be invalidated.
5068    // An update request is a multi-cells VCI write command : The first cell
5069    // contains the index of the cache line to be updated. The second cell contains
5070    // the index of the first modified word in the line. The following cells
5071    // contain the data.
5072    ///////////////////////////////////////////////////////////////////////////////
5073
5074    switch ( r_init_cmd_fsm.read() )
5075    {
5076        ////////////////////////
5077        case INIT_CMD_UPDT_IDLE:  // XRAM_RSP FSM has highest priority
5078        {
5079            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5080                 r_xram_rsp_to_init_cmd_multi_req.read()  )
5081            {
5082                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5083                m_cpt_inval++;
5084            }
5085            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5086            {
5087                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5088                m_cpt_inval++;
5089            }
5090            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5091                      r_write_to_init_cmd_multi_req.read() )
5092            {
5093                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5094                m_cpt_update++;
5095            }
5096            else if ( r_write_to_init_cmd_brdcast_req.read() )
5097            {
5098                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5099                m_cpt_inval++;
5100            }
5101            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5102                      r_cas_to_init_cmd_multi_req.read()  )
5103            {
5104                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5105                m_cpt_update++;
5106            }
5107            else if( r_cas_to_init_cmd_brdcast_req.read() )
5108            {
5109                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5110                m_cpt_inval++;
5111            }
5112            break;
5113        }
5114        /////////////////////////
5115        case INIT_CMD_INVAL_IDLE: // WRITE FSM has highest priority
5116        {
5117            if ( m_write_to_init_cmd_inst_fifo.rok() ||
5118                 r_write_to_init_cmd_multi_req.read() )
5119            {
5120                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5121                m_cpt_update++;
5122            }
5123            else if ( r_write_to_init_cmd_brdcast_req.read() )
5124            {
5125                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5126                m_cpt_inval++;
5127            }
5128            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5129                      r_cas_to_init_cmd_multi_req.read()  )
5130            {
5131                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5132                m_cpt_update++;
5133            }
5134            else if( r_cas_to_init_cmd_brdcast_req.read() )
5135            {
5136                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5137                m_cpt_inval++;
5138            }
5139            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5140                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5141            {
5142                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5143                m_cpt_inval++;
5144            }
5145            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5146            {
5147                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5148                m_cpt_inval++;
5149            }
5150            break;
5151        }
5152        //////////////////////////
5153        case INIT_CMD_CAS_UPDT_IDLE: // CAS FSM has highest priority
5154        {
5155            if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5156                 r_cas_to_init_cmd_multi_req.read()  )
5157            {
5158                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5159                m_cpt_update++;
5160            }
5161            else if( r_cas_to_init_cmd_brdcast_req.read() )
5162            {
5163                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5164                m_cpt_inval++;
5165            }
5166            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5167                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5168            {
5169                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5170                m_cpt_inval++;
5171            }
5172            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5173            {
5174                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5175                m_cpt_inval++;
5176            }
5177            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5178                      r_write_to_init_cmd_multi_req.read() )
5179            {
5180                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5181                m_cpt_update++;
5182            }
5183            else if ( r_write_to_init_cmd_brdcast_req.read() )
5184            {
5185                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5186                m_cpt_inval++;
5187            }
5188            break;
5189        }
5190        //////////////////////////
5191        case INIT_CMD_INVAL_NLINE:  // send a multi-inval (from XRAM_RSP)
5192        {
5193            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() )
5194            {
5195                if ( p_vci_ini.cmdack )
5196                {
5197                    m_cpt_inval_mult++;
5198                    r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5199                    xram_rsp_to_init_cmd_fifo_get = true;
5200                }
5201            }
5202            else
5203            {
5204                if( r_xram_rsp_to_init_cmd_multi_req.read() ) r_xram_rsp_to_init_cmd_multi_req = false;
5205                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5206            }
5207            break;
5208        }
5209        ///////////////////////////
5210        case INIT_CMD_XRAM_BRDCAST: // send a broadcast-inval (from XRAM_RSP)
5211        {
5212            if ( p_vci_ini.cmdack )
5213            {
5214                m_cpt_inval_brdcast++;
5215                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5216                r_xram_rsp_to_init_cmd_brdcast_req = false;
5217            }
5218            break;
5219        }
5220        ////////////////////////////
5221        case INIT_CMD_WRITE_BRDCAST:  // send a broadcast-inval (from WRITE FSM)
5222        {
5223            if( p_vci_ini.cmdack )
5224            {
5225
5226#if DEBUG_MEMC_INIT_CMD
5227if( m_debug_init_cmd_fsm )
5228{
5229    std::cout << "  <MEMC " << name() << ".INIT_CMD_WRITE_BRDCAST> Broadcast-Inval for line "
5230              << r_write_to_init_cmd_nline.read() << std::endl;
5231}
5232#endif
5233                m_cpt_inval_brdcast++;
5234                r_write_to_init_cmd_brdcast_req = false;
5235                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5236            }
5237            break;
5238        }
5239        /////////////////////////
5240        case INIT_CMD_UPDT_NLINE:  // send nline for a multi-update (from WRITE FSM)
5241        {
5242            if ( m_write_to_init_cmd_inst_fifo.rok() )
5243            {
5244                if ( p_vci_ini.cmdack )
5245                {
5246                    m_cpt_update_mult++;
5247                    r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
5248                    // write_to_init_cmd_fifo_get = true;
5249                }
5250            }
5251            else
5252            {
5253                if ( r_write_to_init_cmd_multi_req.read() ) r_write_to_init_cmd_multi_req = false;
5254                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5255            }
5256            break;
5257        }
5258        /////////////////////////
5259        case INIT_CMD_UPDT_INDEX:  // send word index for a multi-update (from WRITE FSM)
5260        {
5261            r_init_cmd_cpt    = 0;
5262            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
5263            break;
5264        }
5265        ////////////////////////
5266        case INIT_CMD_UPDT_DATA:  // send the data for a multi-update (from WRITE FSM)
5267        {
5268            if ( p_vci_ini.cmdack )
5269            {
5270                if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) )
5271                {
5272                    r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5273                    write_to_init_cmd_fifo_get = true;
5274                }
5275                else
5276                {
5277                    r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
5278                }
5279            }
5280            break;
5281        }
5282        /////////////////////////
5283        case INIT_CMD_CAS_BRDCAST: // send a broadcast-inval (from CAS FSM)
5284        {
5285            if( p_vci_ini.cmdack )
5286            {
5287                m_cpt_inval_brdcast++;
5288                r_cas_to_init_cmd_brdcast_req = false;
5289                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5290            }
5291            break;
5292        }
5293        ////////////////////////////
5294        case INIT_CMD_CAS_UPDT_NLINE:   // send nline for a multi-update (from CAS FSM)
5295        {
5296            if ( m_cas_to_init_cmd_inst_fifo.rok() )
5297            {
5298                if ( p_vci_ini.cmdack )
5299                {
5300                    m_cpt_update_mult++;
5301                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_INDEX;
5302                }
5303            }
5304            else
5305            {
5306                if( r_cas_to_init_cmd_multi_req.read() ) r_cas_to_init_cmd_multi_req = false;
5307                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5308            }
5309            break;
5310        }
5311        ////////////////////////////
5312        case INIT_CMD_CAS_UPDT_INDEX:  // send word index for a multi-update (from CAS FSM)
5313        {
5314            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA;
5315            break;
5316        }
5317        ///////////////////////////
5318        case INIT_CMD_CAS_UPDT_DATA:  // send first data for a multi-update (from CAS FSM)
5319        {
5320            if ( p_vci_ini.cmdack )
5321            {
5322                if ( r_cas_to_init_cmd_is_long.read() )
5323                {
5324                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA_HIGH;
5325                }
5326                else
5327                {
5328                    cas_to_init_cmd_fifo_get = true;
5329                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5330                }
5331            }
5332            break;
5333        }
5334        ////////////////////////
5335        case INIT_CMD_CAS_UPDT_DATA_HIGH:  // send second data for a multi-update (from CAS FSM)
5336        {
5337            if ( p_vci_ini.cmdack )
5338            {
5339                cas_to_init_cmd_fifo_get = true;
5340                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5341            }
5342            break;
5343        }
5344    } // end switch r_init_cmd_fsm
5345
5346    /////////////////////////////////////////////////////////////////////
5347    //    TGT_RSP FSM
5348    /////////////////////////////////////////////////////////////////////
5349    // The TGT_RSP fsm sends the responses on the VCI target port
5350    // with a round robin priority between six requests :
5351    // - r_read_to_tgt_rsp_req
5352    // - r_write_to_tgt_rsp_req
5353    // - r_cas_to_tgt_rsp_req
5354    // - r_cleanup_to_tgt_rsp_req
5355    // - r_xram_rsp_to_tgt_rsp_req
5356    // - r_init_rsp_to_tgt_rsp_req
5357    // The  ordering is :  read > write > cas > xram > init > cleanup
5358    /////////////////////////////////////////////////////////////////////
5359
5360    switch ( r_tgt_rsp_fsm.read() )
5361    {
5362        ///////////////////////
5363        case TGT_RSP_READ_IDLE:   // write requests have the highest priority
5364        {
5365          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5366          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5367          else if ( r_xram_rsp_to_tgt_rsp_req )
5368          {
5369            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5370            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5371          }
5372          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5373          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5374          else if ( r_read_to_tgt_rsp_req     )
5375          {
5376            r_tgt_rsp_fsm = TGT_RSP_READ;
5377            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5378          }
5379          break;
5380        }
5381        ////////////////////////
5382        case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
5383        {
5384          if      ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS;
5385          else if ( r_xram_rsp_to_tgt_rsp_req )
5386          {
5387            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5388            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5389          }
5390          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5391          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5392          else if ( r_read_to_tgt_rsp_req     )
5393          {
5394            r_tgt_rsp_fsm = TGT_RSP_READ;
5395            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5396          }
5397
5398          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5399          break;
5400        }
5401        ///////////////////////
5402        case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
5403        {
5404          if ( r_xram_rsp_to_tgt_rsp_req )
5405          {
5406            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5407            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5408          }
5409          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5410          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5411          else if ( r_read_to_tgt_rsp_req     )
5412          {
5413            r_tgt_rsp_fsm = TGT_RSP_READ;
5414            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5415          }
5416          else if ( r_write_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5417          else if ( r_cas_to_tgt_rsp_req   ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5418          break;
5419        }
5420        ///////////////////////
5421        case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
5422        {
5423
5424          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5425          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5426          else if ( r_read_to_tgt_rsp_req     )
5427          {
5428            r_tgt_rsp_fsm = TGT_RSP_READ;
5429            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5430          }
5431          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5432          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5433          else if ( r_xram_rsp_to_tgt_rsp_req )
5434          {
5435            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5436            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5437          }
5438          break;
5439        }
5440        ///////////////////////
5441        case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
5442        {
5443          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5444          else if ( r_read_to_tgt_rsp_req     )
5445          {
5446            r_tgt_rsp_fsm = TGT_RSP_READ;
5447            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5448          }
5449          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5450          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5451          else if ( r_xram_rsp_to_tgt_rsp_req )
5452          {
5453            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5454            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5455          }
5456          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
5457          break;
5458        }
5459        ///////////////////////
5460        case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
5461        {
5462          if      ( r_read_to_tgt_rsp_req     )
5463          {
5464            r_tgt_rsp_fsm = TGT_RSP_READ;
5465            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5466          }
5467          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5468          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5469          else if ( r_xram_rsp_to_tgt_rsp_req )
5470          {
5471            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5472            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5473          }
5474          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5475          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5476          break;
5477        }
5478        //////////////////
5479        case TGT_RSP_READ:    // send the response to a read
5480        {
5481            if ( p_vci_tgt.rspack )
5482            {
5483
5484#if DEBUG_MEMC_TGT_RSP
5485if( m_debug_tgt_rsp_fsm )
5486{
5487    std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
5488              << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
5489              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
5490              << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
5491              << " / rdata = " << std::hex << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5492              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5493}
5494#endif
5495                if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) )
5496                {
5497                    r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
5498                    r_read_to_tgt_rsp_req = false;
5499                }
5500                else
5501                {
5502                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5503                }
5504            }
5505            break;
5506        }
5507        ///////////////////
5508        case TGT_RSP_WRITE:   // send the write acknowledge
5509        {
5510            if ( p_vci_tgt.rspack )
5511            {
5512
5513#if DEBUG_MEMC_TGT_RSP
5514if( m_debug_tgt_rsp_fsm )
5515{
5516    std::cout << "  <MEMC " << name() << ".TGT_RSP_WRITE> Write response"
5517              << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
5518              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
5519              << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
5520}
5521#endif
5522                r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
5523                r_write_to_tgt_rsp_req = false;
5524            }
5525            break;
5526        }
5527        ///////////////////
5528        case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
5529        {
5530            if ( p_vci_tgt.rspack )
5531            {
5532
5533#if DEBUG_MEMC_TGT_RSP
5534if( m_debug_tgt_rsp_fsm )
5535{
5536    std::cout << "  <MEMC " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
5537              << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
5538              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
5539              << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
5540}
5541#endif
5542                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
5543                r_cleanup_to_tgt_rsp_req = false;
5544            }
5545            break;
5546        }
5547        //////////////////
5548        case TGT_RSP_CAS:    // send one atomic word response
5549        {
5550            if ( p_vci_tgt.rspack )
5551            {
5552
5553#if DEBUG_MEMC_TGT_RSP
5554if( m_debug_tgt_rsp_fsm )
5555{
5556    std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
5557              << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
5558              << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
5559              << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
5560}
5561#endif
5562                r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
5563                r_cas_to_tgt_rsp_req = false;
5564            }
5565            break;
5566        }
5567
5568        ///////////////////////
5569        case TGT_RSP_XRAM:    // send the response after XRAM access
5570        {
5571            if ( p_vci_tgt.rspack )
5572            {
5573
5574#if DEBUG_MEMC_TGT_RSP
5575if( m_debug_tgt_rsp_fsm )
5576{
5577    std::cout << "  <MEMC " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
5578              << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
5579              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
5580              << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
5581              << " / rdata = " << std::hex << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5582              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5583}
5584#endif
5585                if ( (r_tgt_rsp_cpt.read() ==
5586                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
5587                   || r_xram_rsp_to_tgt_rsp_rerror.read() )
5588                {
5589                    r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
5590                    r_xram_rsp_to_tgt_rsp_req = false;
5591                }
5592                else
5593                {
5594                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5595                }
5596            }
5597            break;
5598        }
5599        //////////////////
5600        case TGT_RSP_INIT:    // send the write response after coherence transaction
5601        {
5602            if ( p_vci_tgt.rspack )
5603            {
5604
5605#if DEBUG_MEMC_TGT_RSP
5606if( m_debug_tgt_rsp_fsm )
5607{
5608    std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
5609              << " / rsrcid = " << std::dec << r_init_rsp_to_tgt_rsp_srcid.read()
5610              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read()
5611              << " / rpktid = " << r_init_rsp_to_tgt_rsp_pktid.read() << std::endl;
5612}
5613#endif
5614                r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
5615                r_init_rsp_to_tgt_rsp_req = false;
5616            }
5617            break;
5618        }
5619    } // end switch tgt_rsp_fsm
5620
5621    ////////////////////////////////////////////////////////////////////////////////////
5622    //    ALLOC_UPT FSM
5623    ////////////////////////////////////////////////////////////////////////////////////
5624    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
5625    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
5626    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
5627    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
5628    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
5629    // - The CLEANUP  FSM decrement an entry in UPT.
5630    // The resource is always allocated.
5631    /////////////////////////////////////////////////////////////////////////////////////
5632
5633    switch ( r_alloc_upt_fsm.read() )
5634    {
5635
5636      ////////////////////////
5637      case ALLOC_UPT_INIT_RSP:
5638        if (( r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK  ) &&
5639            ( r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR ))
5640        {
5641          if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5642              ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5643            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5644
5645          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5646            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5647
5648          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5649            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5650
5651          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5652                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5653            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5654        }
5655        break;
5656
5657        /////////////////////
5658      case ALLOC_UPT_WRITE:
5659        if (( r_write_fsm.read() != WRITE_UPT_LOCK    ) &&
5660            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK ))
5661        {
5662          if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5663            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5664
5665          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5666            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5667
5668          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5669                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5670            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5671
5672          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5673            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5674        }
5675        break;
5676
5677        ////////////////////////
5678      case ALLOC_UPT_XRAM_RSP:
5679        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
5680        {
5681          if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5682            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5683
5684          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5685                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5686            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5687
5688          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5689            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5690
5691          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    )   ||
5692                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5693            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5694        }
5695        break;
5696
5697        //////////////////////////
5698      case ALLOC_UPT_CLEANUP:
5699        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
5700        {
5701          if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5702              ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5703            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5704
5705          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5706            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5707
5708          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5709                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5710            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5711
5712          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5713            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5714        }
5715        break;
5716
5717        //////////////////////////
5718      case ALLOC_UPT_CAS:
5719        if (( r_cas_fsm.read() != CAS_UPT_LOCK    ) &&
5720            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK ))
5721        {
5722          if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5723            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5724
5725          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5726                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5727            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5728
5729          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5730            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5731
5732          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5733            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5734        }
5735        break;
5736
5737    } // end switch r_alloc_upt_fsm
5738
5739    ////////////////////////////////////////////////////////////////////////////////////
5740    //    ALLOC_DIR FSM
5741    ////////////////////////////////////////////////////////////////////////////////////
5742    // The ALLOC_DIR FSM allocates the access to the directory and
5743    // the data cache with a round robin priority between 5 user FSMs :
5744    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
5745    // The ressource is always allocated.
5746    /////////////////////////////////////////////////////////////////////////////////////
5747
5748    switch ( r_alloc_dir_fsm.read() )
5749    {
5750      case ALLOC_DIR_RESET:
5751        // Initializes the directory one SET each cycle. All the WAYS of a SET are
5752        // initialize in parallel
5753
5754        r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
5755
5756        if (r_alloc_dir_reset_cpt.read() == (m_sets - 1)) {
5757          m_cache_directory.init();
5758
5759          r_alloc_dir_fsm = ALLOC_DIR_READ;
5760        }
5761        break;
5762
5763      ////////////////////
5764      case ALLOC_DIR_READ:
5765        if ((( r_read_fsm.read()       != READ_DIR_REQ    )   &&
5766             ( r_read_fsm.read()       != READ_DIR_LOCK   )   &&
5767             ( r_read_fsm.read()       != READ_TRT_LOCK   )   &&
5768             ( r_read_fsm.read()       != READ_HEAP_REQ   ))
5769            ||
5770            (( r_read_fsm.read()       == READ_TRT_LOCK   )   &&
5771             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_READ  )))
5772        {
5773          if (r_write_fsm.read() == WRITE_DIR_REQ)
5774            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5775
5776          else if (r_cas_fsm.read() == CAS_DIR_REQ)
5777            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5778
5779          else if (r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5780            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5781
5782          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
5783            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5784        }
5785        break;
5786
5787        /////////////////////
5788      case ALLOC_DIR_WRITE:
5789        if ((( r_write_fsm.read()      != WRITE_DIR_REQ       )  &&
5790             ( r_write_fsm.read()      != WRITE_DIR_LOCK      )  &&
5791             ( r_write_fsm.read()      != WRITE_DIR_READ      )  &&
5792             ( r_write_fsm.read()      != WRITE_DIR_HIT       )  &&
5793             ( r_write_fsm.read()      != WRITE_BC_TRT_LOCK   )  &&
5794             ( r_write_fsm.read()      != WRITE_BC_UPT_LOCK   )  &&
5795             ( r_write_fsm.read()      != WRITE_MISS_TRT_LOCK )  &&
5796             ( r_write_fsm.read()      != WRITE_UPT_LOCK      )  &&
5797             ( r_write_fsm.read()      != WRITE_UPT_HEAP_LOCK ))
5798            ||
5799            (( r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK )  &&
5800             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE    ))
5801            ||
5802            (( r_write_fsm.read()      == WRITE_MISS_TRT_LOCK )  &&
5803             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE     )))
5804        {
5805          if ( r_cas_fsm.read() == CAS_DIR_REQ )
5806            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5807
5808          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5809            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5810
5811          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5812            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5813
5814          else if ( r_read_fsm.read() == READ_DIR_REQ )
5815            r_alloc_dir_fsm = ALLOC_DIR_READ;
5816        }
5817        break;
5818
5819        ////////////////////
5820        case ALLOC_DIR_CAS:
5821        if ((( r_cas_fsm.read()        != CAS_DIR_REQ       )  &&
5822             ( r_cas_fsm.read()        != CAS_DIR_LOCK      )  &&
5823             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ  )  &&
5824             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE )  &&
5825             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK   )  &&
5826             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK   )  &&
5827             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK )  &&
5828             ( r_cas_fsm.read()        != CAS_UPT_LOCK      )  &&
5829             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK ))
5830            ||
5831            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK )  &&
5832             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS    ))
5833            ||
5834            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK )  &&
5835             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS     )))
5836        {
5837          if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5838            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5839
5840          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5841            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5842
5843          else if ( r_read_fsm.read() == READ_DIR_REQ )
5844            r_alloc_dir_fsm = ALLOC_DIR_READ;
5845
5846          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5847            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5848        }
5849        break;
5850
5851        ///////////////////////
5852        case ALLOC_DIR_CLEANUP:
5853        if (( r_cleanup_fsm.read() != CLEANUP_DIR_REQ   ) &&
5854            ( r_cleanup_fsm.read() != CLEANUP_DIR_LOCK  ) &&
5855            ( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ  ) &&
5856            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK ))
5857        {
5858          if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5859            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5860
5861          else if ( r_read_fsm.read() == READ_DIR_REQ )
5862            r_alloc_dir_fsm = ALLOC_DIR_READ;
5863
5864          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5865            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5866
5867          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5868            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5869        }
5870        break;
5871
5872        ////////////////////////
5873        case ALLOC_DIR_XRAM_RSP:
5874        if (( r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK   ) &&
5875            ( r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY   ) &&
5876            ( r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK ))
5877        {
5878          if ( r_read_fsm.read() == READ_DIR_REQ )
5879            r_alloc_dir_fsm = ALLOC_DIR_READ;
5880
5881          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5882            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5883
5884          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5885            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5886
5887          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5888            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5889        }
5890        break;
5891
5892    } // end switch alloc_dir_fsm
5893
5894    ////////////////////////////////////////////////////////////////////////////////////
5895    //    ALLOC_TRT FSM
5896    ////////////////////////////////////////////////////////////////////////////////////
5897    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
5898    // with a round robin priority between 4 user FSMs :
5899    // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
5900    // The ressource is always allocated.
5901    ///////////////////////////////////////////////////////////////////////////////////
5902
5903    switch ( r_alloc_trt_fsm.read() )
5904    {
5905      ////////////////////
5906      case ALLOC_TRT_READ:
5907        if ( r_read_fsm.read() != READ_TRT_LOCK )
5908        {
5909          if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5910              ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5911            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5912
5913          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5914                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5915            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5916
5917          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5918                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5919            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5920
5921          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5922                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5923            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5924        }
5925        break;
5926
5927      /////////////////////
5928      case ALLOC_TRT_WRITE:
5929        if (( r_write_fsm.read() != WRITE_MISS_TRT_LOCK ) &&
5930            ( r_write_fsm.read() != WRITE_BC_TRT_LOCK   ) &&
5931            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK   ))
5932        {
5933          if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5934              ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5935            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5936
5937          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5938                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5939            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5940
5941          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5942                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5943            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5944
5945          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5946            r_alloc_trt_fsm = ALLOC_TRT_READ;
5947        }
5948        break;
5949
5950      ////////////////////
5951      case ALLOC_TRT_CAS:
5952        if (( r_cas_fsm.read() != CAS_MISS_TRT_LOCK ) &&
5953            ( r_cas_fsm.read() != CAS_BC_TRT_LOCK   ) &&
5954            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK   ))
5955        {
5956          if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5957              ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5958            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5959
5960          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5961                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5962            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5963
5964          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5965            r_alloc_trt_fsm = ALLOC_TRT_READ;
5966
5967          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5968                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5969            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5970        }
5971        break;
5972
5973      ////////////////////////
5974      case ALLOC_TRT_XRAM_RSP:
5975        if ((( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK   )  ||
5976             ( r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP  )) &&
5977             ( r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY   )  &&
5978             ( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT   )  &&
5979             ( r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK ))
5980        {
5981          if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5982              ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5983            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5984
5985          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5986            r_alloc_trt_fsm = ALLOC_TRT_READ;
5987
5988          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5989                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5990            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5991
5992          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5993                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5994            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5995        }
5996        break;
5997
5998      ////////////////////////
5999      case ALLOC_TRT_IXR_RSP:
6000        if (( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE ) &&
6001            ( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ  ))
6002        {
6003          if ( r_read_fsm.read() == READ_TRT_LOCK )
6004            r_alloc_trt_fsm = ALLOC_TRT_READ;
6005
6006          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
6007                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
6008            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6009
6010          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
6011                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
6012            r_alloc_trt_fsm = ALLOC_TRT_CAS;
6013
6014          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
6015                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
6016            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6017        }
6018        break;
6019
6020    } // end switch alloc_trt_fsm
6021
6022    ////////////////////////////////////////////////////////////////////////////////////
6023    //    ALLOC_HEAP FSM
6024    ////////////////////////////////////////////////////////////////////////////////////
6025    // The ALLOC_HEAP FSM allocates the access to the heap
6026    // with a round robin priority between 5 user FSMs :
6027    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
6028    // The ressource is always allocated.
6029    /////////////////////////////////////////////////////////////////////////////////////
6030
6031    switch ( r_alloc_heap_fsm.read() )
6032    {
6033        ////////////////////
6034        case ALLOC_HEAP_RESET:
6035          // Initializes the heap one ENTRY each cycle.
6036
6037          r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
6038
6039          if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1)) {
6040            m_heap.init();
6041
6042            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6043          }
6044          break;
6045
6046        ////////////////////
6047        case ALLOC_HEAP_READ:
6048        if (( r_read_fsm.read() != READ_HEAP_REQ   ) &&
6049            ( r_read_fsm.read() != READ_HEAP_LOCK  ) &&
6050            ( r_read_fsm.read() != READ_HEAP_ERASE ))
6051        {
6052          if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6053            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6054
6055          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6056            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6057
6058          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6059            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6060
6061          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6062            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6063        }
6064        break;
6065
6066        /////////////////////
6067        case ALLOC_HEAP_WRITE:
6068        if (( r_write_fsm.read() != WRITE_UPT_HEAP_LOCK ) &&
6069            ( r_write_fsm.read() != WRITE_UPT_REQ       ) &&
6070            ( r_write_fsm.read() != WRITE_UPT_NEXT      ))
6071        {
6072          if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6073            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6074
6075          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6076            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6077
6078          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6079            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6080
6081          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6082            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6083        }
6084        break;
6085
6086        ////////////////////
6087        case ALLOC_HEAP_CAS:
6088        if (( r_cas_fsm.read() != CAS_UPT_HEAP_LOCK ) &&
6089            ( r_cas_fsm.read() != CAS_UPT_REQ       ) &&
6090            ( r_cas_fsm.read() != CAS_UPT_NEXT      ))
6091        {
6092          if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6093            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6094
6095          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6096            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6097
6098          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6099            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6100
6101          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6102            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6103        }
6104        break;
6105
6106        ///////////////////////
6107        case ALLOC_HEAP_CLEANUP:
6108        if (( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ    ) &&
6109            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK   ) &&
6110            ( r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH ) &&
6111            ( r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN  ))
6112        {
6113          if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6114            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6115
6116          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6117            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6118
6119          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6120            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6121
6122          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6123            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6124        }
6125        break;
6126
6127        ////////////////////////
6128        case ALLOC_HEAP_XRAM_RSP:
6129        if (( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ   ) &&
6130            ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE ))
6131        {
6132          if  ( r_read_fsm.read() == READ_HEAP_REQ )
6133            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6134
6135          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6136            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6137
6138          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6139            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6140
6141          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6142            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6143
6144        }
6145        break;
6146
6147    } // end switch alloc_heap_fsm
6148
6149
6150    ////////////////////////////////////////////////////////////////////////////////////
6151    //    TGT_CMD to READ FIFO
6152    ////////////////////////////////////////////////////////////////////////////////////
6153
6154    if ( cmd_read_fifo_put ) {
6155      if ( cmd_read_fifo_get ) {
6156        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6157        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
6158        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6159        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6160        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6161      } else {
6162        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6163        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
6164        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6165        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6166        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6167      }
6168    } else {
6169      if ( cmd_read_fifo_get ) {
6170        m_cmd_read_addr_fifo.simple_get();
6171        m_cmd_read_length_fifo.simple_get();
6172        m_cmd_read_srcid_fifo.simple_get();
6173        m_cmd_read_trdid_fifo.simple_get();
6174        m_cmd_read_pktid_fifo.simple_get();
6175      }
6176    }
6177    /////////////////////////////////////////////////////////////////////
6178    //    TGT_CMD to WRITE FIFO
6179    /////////////////////////////////////////////////////////////////////
6180
6181    if ( cmd_write_fifo_put ) {
6182      if ( cmd_write_fifo_get ) {
6183        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6184        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6185        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6186        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6187        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6188        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
6189        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
6190      } else {
6191        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6192        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
6193        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6194        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6195        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6196        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
6197        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
6198      }
6199    } else {
6200      if ( cmd_write_fifo_get ) {
6201        m_cmd_write_addr_fifo.simple_get();
6202        m_cmd_write_eop_fifo.simple_get();
6203        m_cmd_write_srcid_fifo.simple_get();
6204        m_cmd_write_trdid_fifo.simple_get();
6205        m_cmd_write_pktid_fifo.simple_get();
6206        m_cmd_write_data_fifo.simple_get();
6207        m_cmd_write_be_fifo.simple_get();
6208      }
6209    }
6210    ////////////////////////////////////////////////////////////////////////////////////
6211    //    TGT_CMD to CAS FIFO
6212    ////////////////////////////////////////////////////////////////////////////////////
6213
6214    if ( cmd_cas_fifo_put ) {
6215      if ( cmd_cas_fifo_get ) {
6216        m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6217        m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6218        m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6219        m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6220        m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6221        m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
6222      } else {
6223        m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6224        m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
6225        m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6226        m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6227        m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6228        m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
6229      }
6230    } else {
6231      if ( cmd_cas_fifo_get ) {
6232        m_cmd_cas_addr_fifo.simple_get();
6233        m_cmd_cas_eop_fifo.simple_get();
6234        m_cmd_cas_srcid_fifo.simple_get();
6235        m_cmd_cas_trdid_fifo.simple_get();
6236        m_cmd_cas_pktid_fifo.simple_get();
6237        m_cmd_cas_wdata_fifo.simple_get();
6238      }
6239    }
6240    ////////////////////////////////////////////////////////////////////////////////////
6241    //    WRITE to INIT_CMD FIFO
6242    ////////////////////////////////////////////////////////////////////////////////////
6243
6244    if ( write_to_init_cmd_fifo_put ) {
6245      if ( write_to_init_cmd_fifo_get ) {
6246        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
6247        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
6248#if L1_MULTI_CACHE
6249        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
6250#endif
6251      } else {
6252        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
6253        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
6254#if L1_MULTI_CACHE
6255        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
6256#endif
6257      }
6258    } else {
6259      if ( write_to_init_cmd_fifo_get ) {
6260        m_write_to_init_cmd_inst_fifo.simple_get();
6261        m_write_to_init_cmd_srcid_fifo.simple_get();
6262#if L1_MULTI_CACHE
6263        m_write_to_init_cmd_cache_id_fifo.simple_get();
6264#endif
6265      }
6266    }
6267    ////////////////////////////////////////////////////////////////////////////////////
6268    //    XRAM_RSP to INIT_CMD FIFO
6269    ////////////////////////////////////////////////////////////////////////////////////
6270
6271    if ( xram_rsp_to_init_cmd_fifo_put ) {
6272      if ( xram_rsp_to_init_cmd_fifo_get ) {
6273        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
6274        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
6275#if L1_MULTI_CACHE
6276        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
6277#endif
6278      } else {
6279        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
6280        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
6281#if L1_MULTI_CACHE
6282        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
6283#endif
6284      }
6285    } else {
6286      if ( xram_rsp_to_init_cmd_fifo_get ) {
6287        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
6288        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
6289#if L1_MULTI_CACHE
6290        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
6291#endif
6292      }
6293    }
6294    ////////////////////////////////////////////////////////////////////////////////////
6295    //    CAS to INIT_CMD FIFO
6296    ////////////////////////////////////////////////////////////////////////////////////
6297
6298    if ( cas_to_init_cmd_fifo_put ) {
6299      if ( cas_to_init_cmd_fifo_get ) {
6300        m_cas_to_init_cmd_inst_fifo.put_and_get(cas_to_init_cmd_fifo_inst);
6301        m_cas_to_init_cmd_srcid_fifo.put_and_get(cas_to_init_cmd_fifo_srcid);
6302#if L1_MULTI_CACHE
6303        m_cas_to_init_cmd_cache_id_fifo.put_and_get(cas_to_init_cmd_fifo_cache_id);
6304#endif
6305      } else {
6306          m_cas_to_init_cmd_inst_fifo.simple_put(cas_to_init_cmd_fifo_inst);
6307          m_cas_to_init_cmd_srcid_fifo.simple_put(cas_to_init_cmd_fifo_srcid);
6308#if L1_MULTI_CACHE
6309          m_cas_to_init_cmd_cache_id_fifo.simple_put(cas_to_init_cmd_fifo_cache_id);
6310#endif
6311      }
6312    } else {
6313        if ( cas_to_init_cmd_fifo_get ) {
6314            m_cas_to_init_cmd_inst_fifo.simple_get();
6315            m_cas_to_init_cmd_srcid_fifo.simple_get();
6316#if L1_MULTI_CACHE
6317            m_cas_to_init_cmd_cache_id_fifo.simple_get();
6318#endif
6319      }
6320    }
6321
6322    m_cpt_cycles++;
6323
6324} // end transition()
6325
6326/////////////////////////////
6327tmpl(void)::genMoore()
6328/////////////////////////////
6329{
6330    ////////////////////////////////////////////////////////////
6331    // Command signals on the p_vci_ixr port
6332    ////////////////////////////////////////////////////////////
6333
6334    p_vci_ixr.be      = 0xF;
6335    p_vci_ixr.pktid   = 0;
6336    p_vci_ixr.srcid   = m_srcid_ixr;
6337    p_vci_ixr.cons    = false;
6338    p_vci_ixr.wrap    = false;
6339    p_vci_ixr.contig  = true;
6340    p_vci_ixr.clen    = 0;
6341    p_vci_ixr.cfixed  = false;
6342
6343    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
6344      p_vci_ixr.cmd     = vci_param::CMD_READ;
6345      p_vci_ixr.cmdval  = true;
6346      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
6347      p_vci_ixr.plen    = m_words*4;
6348      p_vci_ixr.wdata   = 0x00000000;
6349      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
6350      p_vci_ixr.eop     = true;
6351    }
6352    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE ) {
6353      if(r_cas_to_ixr_cmd_write.read()){
6354        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6355        p_vci_ixr.cmdval  = true;
6356        p_vci_ixr.address = (addr_t)((r_cas_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6357        p_vci_ixr.plen    = m_words*4;
6358        p_vci_ixr.wdata   = r_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6359        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6360        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6361      } else {
6362        p_vci_ixr.cmd     = vci_param::CMD_READ;
6363        p_vci_ixr.cmdval  = true;
6364        p_vci_ixr.address = (addr_t)(r_cas_to_ixr_cmd_nline.read()*m_words*4);
6365        p_vci_ixr.plen    = m_words*4;
6366        p_vci_ixr.wdata   = 0x00000000;
6367        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6368        p_vci_ixr.eop     = true;
6369      }
6370    }
6371    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
6372      if(r_write_to_ixr_cmd_write.read()){
6373        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6374        p_vci_ixr.cmdval  = true;
6375        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6376        p_vci_ixr.plen    = m_words*4;
6377        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6378        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6379        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6380      } else {
6381        p_vci_ixr.cmd     = vci_param::CMD_READ;
6382        p_vci_ixr.cmdval  = true;
6383        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
6384        p_vci_ixr.plen    = m_words*4;
6385        p_vci_ixr.wdata   = 0x00000000;
6386        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6387        p_vci_ixr.eop     = true;
6388      }
6389    }
6390    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
6391      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6392      p_vci_ixr.cmdval  = true;
6393      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6394      p_vci_ixr.plen    = m_words*4;
6395      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6396      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
6397      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6398    } else {
6399      p_vci_ixr.cmdval  = false;
6400      p_vci_ixr.address = 0;
6401      p_vci_ixr.plen    = 0;
6402      p_vci_ixr.wdata   = 0;
6403      p_vci_ixr.trdid   = 0;
6404      p_vci_ixr.eop = false;
6405    }
6406
6407    ////////////////////////////////////////////////////
6408    // Response signals on the p_vci_ixr port
6409    ////////////////////////////////////////////////////
6410
6411    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
6412          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
6413        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
6414    else                                        p_vci_ixr.rspack = false;
6415
6416    ////////////////////////////////////////////////////
6417    // Command signals on the p_vci_tgt port
6418    ////////////////////////////////////////////////////
6419
6420    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
6421      case TGT_CMD_IDLE:
6422        p_vci_tgt.cmdack  = false;
6423        break;
6424      case TGT_CMD_READ:
6425        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
6426        break;
6427      case TGT_CMD_WRITE:
6428        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
6429        break;
6430      case TGT_CMD_CAS:
6431        p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
6432        break;
6433      default:
6434        p_vci_tgt.cmdack  = false;
6435        break;
6436    }
6437
6438    ////////////////////////////////////////////////////
6439    // Response signals on the p_vci_tgt port
6440    ////////////////////////////////////////////////////
6441    switch ( r_tgt_rsp_fsm.read() ) {
6442
6443      case TGT_RSP_READ_IDLE:
6444      case TGT_RSP_WRITE_IDLE:
6445      case TGT_RSP_CAS_IDLE:
6446      case TGT_RSP_XRAM_IDLE:
6447      case TGT_RSP_INIT_IDLE:
6448      case TGT_RSP_CLEANUP_IDLE:
6449        p_vci_tgt.rspval  = false;
6450        p_vci_tgt.rsrcid  = 0;
6451        p_vci_tgt.rdata   = 0;
6452        p_vci_tgt.rpktid  = 0;
6453        p_vci_tgt.rtrdid  = 0;
6454        p_vci_tgt.rerror  = 0;
6455        p_vci_tgt.reop    = false;
6456        break;
6457      case TGT_RSP_READ:
6458        p_vci_tgt.rspval   = true;
6459        if( ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6460            && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1)) )
6461          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
6462        else if ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6463          p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
6464        else
6465          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6466        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
6467        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
6468        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
6469        p_vci_tgt.rerror   = 0;
6470        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
6471        break;
6472      case TGT_RSP_WRITE:
6473        /*if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) )
6474            {
6475              std::cout << "SC RSP / rsrcid = " << r_write_to_tgt_rsp_srcid.read() << " / rdata = " << r_write_to_tgt_rsp_sc_fail.read() << std::endl;
6476            }*/
6477        p_vci_tgt.rspval   = true;
6478        if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read() )
6479          p_vci_tgt.rdata  = 1;
6480        else
6481          p_vci_tgt.rdata  = 0;
6482        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
6483        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
6484        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
6485        //p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
6486        p_vci_tgt.rerror   = 0;
6487        p_vci_tgt.reop     = true;
6488        break;
6489      case TGT_RSP_CLEANUP:
6490        p_vci_tgt.rspval   = true;
6491        p_vci_tgt.rdata    = 0;
6492        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
6493        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
6494        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
6495        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
6496        p_vci_tgt.reop     = true;
6497        break;
6498      case TGT_RSP_CAS:
6499        p_vci_tgt.rspval   = true;
6500        p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
6501        p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
6502        p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
6503        p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
6504        p_vci_tgt.rerror   = 0;
6505        p_vci_tgt.reop     = true;
6506        break;
6507      case TGT_RSP_XRAM:
6508        p_vci_tgt.rspval   = true;
6509        if( ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6510            && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length-1)) )
6511          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
6512        else
6513          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6514        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
6515        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
6516        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
6517        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
6518        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
6519              == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
6520            || r_xram_rsp_to_tgt_rsp_rerror.read());
6521        break;
6522      case TGT_RSP_INIT:
6523        p_vci_tgt.rspval   = true;
6524        p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
6525        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
6526        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
6527        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
6528        p_vci_tgt.rerror   = 0;
6529        p_vci_tgt.reop     = true;
6530        break;
6531    } // end switch r_tgt_rsp_fsm
6532
6533    ///////////////////////////////////////////////////
6534    // Command signals on the p_vci_ini port
6535    ///////////////////////////////////////////////////
6536
6537    p_vci_ini.cmd     = vci_param::CMD_WRITE;
6538    p_vci_ini.srcid   = m_srcid_ini;
6539    p_vci_ini.cons    = true;
6540    p_vci_ini.wrap    = false;
6541    p_vci_ini.contig  = false;
6542    p_vci_ini.clen    = 0;
6543    p_vci_ini.cfixed  = false;
6544
6545    vci_addr_t vci_ini_address = 0;
6546    switch ( r_init_cmd_fsm.read() ) {
6547
6548      case INIT_CMD_UPDT_IDLE:
6549      case INIT_CMD_INVAL_IDLE:
6550      case INIT_CMD_CAS_UPDT_IDLE:
6551        p_vci_ini.cmdval  = false;
6552        p_vci_ini.address = 0;
6553        p_vci_ini.wdata   = 0;
6554        p_vci_ini.be      = 0;
6555        p_vci_ini.plen    = 0;
6556        p_vci_ini.trdid   = 0;
6557        p_vci_ini.pktid   = 0;
6558        p_vci_ini.eop     = false;
6559        break;
6560      case INIT_CMD_INVAL_NLINE:
6561      {
6562        vci_ini_address = (vci_addr_t)
6563            m_xram_rsp_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6564
6565        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
6566        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
6567          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
6568              p_vci_ini.address = (addr_t) (vci_ini_address+4);
6569          } else {
6570              p_vci_ini.address = (addr_t) (vci_ini_address);
6571          }
6572        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
6573        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6574        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6575        p_vci_ini.plen    = 4;
6576        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6577#if L1_MULTI_CACHE
6578        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
6579#endif
6580        p_vci_ini.eop     = true;
6581        break;
6582      }
6583      case INIT_CMD_XRAM_BRDCAST:
6584        p_vci_ini.cmdval  = true;
6585        p_vci_ini.address = m_broadcast_address;
6586        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6587        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6588        p_vci_ini.plen    = 4;
6589        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6590        p_vci_ini.pktid   = 0;
6591        p_vci_ini.eop     = true;
6592        break;
6593
6594      case INIT_CMD_WRITE_BRDCAST:
6595        p_vci_ini.cmdval  = true;
6596        p_vci_ini.address = m_broadcast_address;
6597        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
6598        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
6599        p_vci_ini.plen    = 4 ;
6600        p_vci_ini.eop     = true;
6601        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6602        p_vci_ini.pktid   = 0;
6603        break;
6604      case INIT_CMD_UPDT_NLINE:
6605        vci_ini_address = (vci_addr_t)
6606            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6607
6608        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
6609        if(m_write_to_init_cmd_inst_fifo.rok()){
6610          if(m_write_to_init_cmd_inst_fifo.read()) {
6611            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6612          } else {
6613            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6614          }
6615        } else {
6616          p_vci_ini.address = 0;
6617        }
6618        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
6619        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
6620        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6621        p_vci_ini.eop     = false;
6622        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6623#if L1_MULTI_CACHE
6624        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6625#endif
6626        break;
6627      case INIT_CMD_UPDT_INDEX:
6628        vci_ini_address = (vci_addr_t)
6629            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6630
6631        p_vci_ini.cmdval  = true;
6632        if(m_write_to_init_cmd_inst_fifo.read()) {
6633          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6634        } else {
6635          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6636        }
6637        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
6638        p_vci_ini.be      = 0xF;
6639        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6640        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6641#if L1_MULTI_CACHE
6642        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6643#endif
6644        p_vci_ini.eop     = false;
6645        break;
6646      case INIT_CMD_UPDT_DATA:
6647        vci_ini_address = (vci_addr_t)
6648            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6649
6650        p_vci_ini.cmdval  = true;
6651        if(m_write_to_init_cmd_inst_fifo.read()) {
6652          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6653        } else {
6654          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6655        }
6656        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
6657          r_write_to_init_cmd_index.read()].read();
6658        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
6659            r_write_to_init_cmd_index.read()].read()  ;
6660        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6661        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6662#if L1_MULTI_CACHE
6663        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6664#endif
6665        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
6666        break;
6667
6668      case INIT_CMD_CAS_BRDCAST:
6669        p_vci_ini.cmdval  = true;
6670        p_vci_ini.address = m_broadcast_address;
6671        p_vci_ini.wdata   = (addr_t)r_cas_to_init_cmd_nline.read();
6672        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32) & 0x3);
6673        p_vci_ini.plen    = 4 ;
6674        p_vci_ini.eop     = true;
6675        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6676        p_vci_ini.pktid   = 0;
6677        break;
6678      case INIT_CMD_CAS_UPDT_NLINE:
6679        vci_ini_address = (vci_addr_t)
6680            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6681
6682        p_vci_ini.cmdval  = m_cas_to_init_cmd_inst_fifo.rok();
6683        if(m_cas_to_init_cmd_inst_fifo.rok()){
6684          if( m_cas_to_init_cmd_inst_fifo.read() ) {
6685            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6686          } else {
6687            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6688          }
6689        } else {
6690          p_vci_ini.address = 0;
6691        }
6692        p_vci_ini.wdata   = (uint32_t)r_cas_to_init_cmd_nline.read();
6693        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32 ) & 0x3);
6694        if(r_cas_to_init_cmd_is_long.read()){
6695            p_vci_ini.plen    = 4 * 4;
6696        } else {
6697            p_vci_ini.plen    = 4 * 3;
6698        }
6699        p_vci_ini.eop     = false;
6700        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6701#if L1_MULTI_CACHE
6702        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6703#endif
6704        break;
6705      case INIT_CMD_CAS_UPDT_INDEX:
6706        vci_ini_address = (vci_addr_t)
6707            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6708
6709        p_vci_ini.cmdval  = true;
6710        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6711          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6712        } else {
6713          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6714        }
6715        p_vci_ini.wdata   = r_cas_to_init_cmd_index.read();
6716        p_vci_ini.be      = 0xF;
6717        if(r_cas_to_init_cmd_is_long.read()){
6718            p_vci_ini.plen    = 4 * 4;
6719        } else {
6720            p_vci_ini.plen    = 4 * 3;
6721        }
6722        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6723#if L1_MULTI_CACHE
6724        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6725#endif
6726        p_vci_ini.eop     = false;
6727        break;
6728      case INIT_CMD_CAS_UPDT_DATA:
6729        vci_ini_address = (vci_addr_t)
6730            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6731
6732        p_vci_ini.cmdval  = true;
6733        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6734          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6735        } else {
6736          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6737        }
6738        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata.read();
6739        p_vci_ini.be      = 0xF;
6740        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6741#if L1_MULTI_CACHE
6742        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6743#endif
6744        if(r_cas_to_init_cmd_is_long.read()){
6745            p_vci_ini.plen    = 4 * 4;
6746            p_vci_ini.eop     = false;
6747        } else {
6748            p_vci_ini.plen    = 4 * 3;
6749            p_vci_ini.eop     = true;
6750        }
6751        break;
6752      case INIT_CMD_CAS_UPDT_DATA_HIGH:
6753        vci_ini_address = (vci_addr_t)
6754            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6755
6756        p_vci_ini.cmdval  = true;
6757        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6758          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6759        } else {
6760          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6761        }
6762        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata_high.read();
6763        p_vci_ini.be      = 0xF;
6764        p_vci_ini.plen    = 4 * 4;
6765        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6766#if L1_MULTI_CACHE
6767        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6768#endif
6769        p_vci_ini.eop     = true;
6770        break;
6771
6772    } // end switch r_init_cmd_fsm
6773
6774    //////////////////////////////////////////////////////
6775    // Response signals on the p_vci_ini port
6776    //////////////////////////////////////////////////////
6777
6778    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
6779    else                                          p_vci_ini.rspack  = false;
6780
6781    //////////////////////////////////////////////////////
6782    // Response signals on the p_vci_tgt_cleanup port
6783    //////////////////////////////////////////////////////
6784    p_vci_tgt_cleanup.rspval = false;
6785    p_vci_tgt_cleanup.rsrcid = 0;
6786    p_vci_tgt_cleanup.rdata  = 0;
6787    p_vci_tgt_cleanup.rpktid = 0;
6788    p_vci_tgt_cleanup.rtrdid = 0;
6789    p_vci_tgt_cleanup.rerror = 0;
6790    p_vci_tgt_cleanup.reop   = false;
6791    p_vci_tgt_cleanup.cmdack = false ;
6792
6793    switch(r_cleanup_fsm.read()){
6794      case CLEANUP_IDLE:
6795        {
6796          p_vci_tgt_cleanup.cmdack = true ;
6797          break;
6798        }
6799      case CLEANUP_RSP:
6800        {
6801          p_vci_tgt_cleanup.rspval = true;
6802          p_vci_tgt_cleanup.rdata  = 0;
6803          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
6804          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
6805          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
6806          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
6807          p_vci_tgt_cleanup.reop   = 1;
6808          break;
6809        }
6810
6811    }
6812
6813} // end genMoore()
6814
6815}} // end name space
6816
6817// Local Variables:
6818// tab-width: 2
6819// c-basic-offset: 2
6820// c-file-offsets:((innamespace . 0)(inline-open . 0))
6821// indent-tabs-mode: nil
6822// End:
6823
6824// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
Note: See TracBrowser for help on using the repository browser.