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

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

Erasing useless template parameters for the communication/dspin_dhccp_param class.

Modifying consequently the vci_mem_cache_dspin_coherence class to use the
dspin_dhccp_param class without templates.

Introducing in the vci_mem_cache and the vci_mem_cache_dspin_coherence modules
the state CAS_DIR_HIT_COMPARE.

Before this modification, the comparison between the expected data and the actual
data was done directly in the CAS_DIR_HIT_READ state using the data obtained in the
same cycle from the cache.

Now, the data obtained from the cache is stored in a buffer and the next cycle,
in the CAS_DIR_HIT_COMPARE state, the comparison is made using the data from the
buffer.

This modifications allows to eliminate a critical path obtained in the ASIC
synthesis of the memory cache.

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