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

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

Bugfix in vci_mem_cache_v4:

In function "copy()" of the xram_transaction table the LL key was not
copied into register. Hence, the key coming from the XRAM_RSP to the
TGT_RSP FSM was never correct.

In TGT_RSP FSM, in case of LL response, the two response flits were
inverted. We must send first the key and then the data.

Add:

Add the COMPARE_HIT_COMPARE state in the CAS FSM to optimize timing.
(This modification has been already done in the vci_mem_cache v5).

Add output ports for debug. This ports are used only if the
MONITOR_MEMCACHE_FSM compilation directive is gave.

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