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

Last change on this file since 246 was 246, checked in by cfuguet, 12 years ago

Bug fix in IXR_RSP FSM. Erroneous condition for the error verification

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