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

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

Introducing new CLEANUP transaction address specification in the components:

  • vci_cc_vcache_wrapper_v4
  • vci_mem_cache_v4

The new specification uses the VCI WDATA and the VCI BE to send the cleanup
nline. The VCI ADDRESS is like follows:

  • NLINE MSb | Memory Cache local ID | 00....00

The platforms:

  • tsarv4_mono_mmu
  • tsarv4_generic_mmu

has been modified to use the modified components and the mapping table for the coherence
address space has been updated.

  • 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.6 KB
Line 
1 /* -*- c++ -*-
2 * File         : vci_mem_cache_v4.cpp
3 * Date         : 30/10/2008
4 * Copyright    : UPMC / LIP6
5 * Authors      : Alain Greiner / Eric Guthmuller
6 *
7 * SOCLIB_LGPL_HEADER_BEGIN
8 *
9 * This file is part of SoCLib, GNU LGPLv2.1.
10 *
11 * SoCLib is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published
13 * by the Free Software Foundation; version 2.1 of the License.
14 *
15 * SoCLib is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with SoCLib; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * 02110-1301 USA
24 *
25 * SOCLIB_LGPL_HEADER_END
26 *
27 * Maintainers: alain eric.guthmuller@polytechnique.edu
28 */
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_transaction_tab_lines(transaction_tab_lines),
276    m_transaction_tab( transaction_tab_lines, nwords ),
277    m_update_tab_lines( update_tab_lines),
278    m_update_tab( update_tab_lines ),
279    m_cache_directory( nways, nsets, nwords, vci_param::N ),
280    m_heap( m_heap_size ),
281
282#define L2 soclib::common::uint32_log2
283    m_x( L2(m_words), 2),
284    m_y( L2(m_sets), L2(m_words) + 2),
285    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
286    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
287#undef L2
288
289    //  FIFOs
290
291    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
292    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
293    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
294    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
295    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
296
297    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
298    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
299    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
300    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
301    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
302    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
303    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
304
305    m_cmd_sc_addr_fifo("m_cmd_sc_addr_fifo",4),
306    m_cmd_sc_eop_fifo("m_cmd_sc_eop_fifo",4),
307    m_cmd_sc_srcid_fifo("m_cmd_sc_srcid_fifo",4),
308    m_cmd_sc_trdid_fifo("m_cmd_sc_trdid_fifo",4),
309    m_cmd_sc_pktid_fifo("m_cmd_sc_pktid_fifo",4),
310    m_cmd_sc_wdata_fifo("m_cmd_sc_wdata_fifo",4),
311
312    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
313   
314    m_nseg(0), 
315    m_ncseg(0),
316
317    r_read_fsm("r_read_fsm"),
318
319    r_write_fsm("r_write_fsm"),
320
321    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
322    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
323#if L1_MULTI_CACHE
324    m_write_to_init_cmd_cache_id_fifo("m_write_to_init_cmd_cache_id_fifo",8),
325#endif
326
327    r_init_rsp_fsm("r_init_rsp_fsm"),
328    r_cleanup_fsm("r_cleanup_fsm"),
329
330    r_sc_fsm("r_sc_fsm"),
331
332    m_sc_to_init_cmd_inst_fifo("m_sc_to_init_cmd_inst_fifo",8),
333    m_sc_to_init_cmd_srcid_fifo("m_sc_to_init_cmd_srcid_fifo",8),
334#if L1_MULTI_CACHE
335    m_sc_to_init_cmd_cache_id_fifo("m_sc_to_init_cmd_cache_id_fifo",8),
336#endif
337
338    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
339    r_xram_rsp_fsm("r_xram_rsp_fsm"),
340
341    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
342    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
343#if L1_MULTI_CACHE
344    m_xram_rsp_to_init_cmd_cache_id_fifo("m_xram_rsp_to_init_cmd_cache_id_fifo",8),
345#endif
346
347    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
348
349    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
350
351    r_init_cmd_fsm("r_init_cmd_fsm"),
352
353    r_alloc_dir_fsm("r_alloc_dir_fsm"),
354    r_alloc_trt_fsm("r_alloc_trt_fsm"),
355    r_alloc_upt_fsm("r_alloc_upt_fsm"),
356    r_alloc_heap_fsm("r_alloc_heap_fsm")
357    {
358      assert(IS_POW_OF_2(nsets));
359      assert(IS_POW_OF_2(nwords));
360      assert(IS_POW_OF_2(nways));
361      assert(nsets);
362      assert(nwords);
363      assert(nways);
364
365      // check Transaction table size
366      assert( (uint32_log2(transaction_tab_lines) <= vci_param::T) and
367             "Need more bits for VCI TRDID field");
368
369      // Set the broadcast address with Xmin,Xmax,Ymin,Ymax set to maximum
370      m_broadcast_address = 0x3 | (0x7C1F << (vci_param::N-20));
371
372      // Get the segments associated to the MemCache
373      std::list<soclib::common::Segment>::iterator seg;
374      size_t i;
375
376      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
377        m_nseg++;
378      }
379      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
380        m_ncseg++;
381      }
382
383      m_seg = new soclib::common::Segment*[m_nseg];
384
385      i = 0;
386      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) {
387        m_seg[i] = &(*seg);
388        i++;
389      }
390
391      m_cseg = new soclib::common::Segment*[m_ncseg];
392
393      i = 0;
394      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) {
395          m_cseg[i] = &(*seg);
396          i++;
397      }
398
399      // Memory cache allocation & initialisation
400      m_cache_data = new data_t**[nways];
401      for ( size_t i=0 ; i<nways ; ++i ) {
402        m_cache_data[i] = new data_t*[nsets];
403      }
404      for ( size_t i=0; i<nways; ++i ) {
405        for ( size_t j=0; j<nsets; ++j ) {
406          m_cache_data[i][j] = new data_t[nwords];
407          for ( size_t k=0; k<nwords; k++){
408            m_cache_data[i][j][k]=0;
409          }     
410        }
411      }
412
413      // Allocation for IXR_RSP FSM
414      r_ixr_rsp_to_xram_rsp_rok     = new sc_signal<bool>[m_transaction_tab_lines];
415
416      // Allocation for XRAM_RSP FSM
417      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
418      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
419      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
420
421      // Allocation for READ FSM
422      r_read_data                               = new sc_signal<data_t>[nwords];
423      r_read_to_tgt_rsp_data            = new sc_signal<data_t>[nwords];
424
425      // Allocation for WRITE FSM
426      r_write_data                              = new sc_signal<data_t>[nwords];
427      r_write_be                                = new sc_signal<be_t>[nwords];
428      r_write_to_init_cmd_data          = new sc_signal<data_t>[nwords];
429      r_write_to_init_cmd_be            = new sc_signal<be_t>[nwords];
430      r_write_to_ixr_cmd_data       = new sc_signal<data_t>[nwords];
431
432      // Allocation for SC FSM
433      r_sc_to_ixr_cmd_data              = new sc_signal<data_t>[nwords];
434      r_sc_rdata                    = new sc_signal<data_t>[2];
435
436
437      // Simulation
438
439      SC_METHOD(transition);
440      dont_initialize();
441      sensitive << p_clk.pos();
442
443      SC_METHOD(genMoore);
444      dont_initialize();
445      sensitive << p_clk.neg();
446
447    } // end constructor
448
449///////////////////////////////////////////////////////////////////////
450tmpl(void)::start_monitor( vci_addr_t addr, vci_addr_t length )
451///////////////////////////////////////////////////////////////////////
452{
453    m_monitor_ok        = true;
454    m_monitor_base      = addr;
455    m_monitor_length    = length;
456}
457
458///////////////////////////////////////////////////////////////////////
459tmpl(void)::stop_monitor()
460///////////////////////////////////////////////////////////////////////
461{
462    m_monitor_ok        = false;
463}
464
465///////////////////////////////////////////////////////////////////////
466tmpl(void)::check_monitor( const char *buf, vci_addr_t addr, data_t data )
467///////////////////////////////////////////////////////////////////////
468{
469    if ( (addr >= m_monitor_base) and
470         (addr < m_monitor_base + m_monitor_length) )
471    {
472        std::cout << " MEMC Write Monitor : " << buf << " Address = " << std::hex << addr
473                  << " / Data = " << data << std::endl;
474    }
475}
476
477/////////////////////////////////////////////////////
478tmpl(void)::copies_monitor( vci_addr_t addr )
479/////////////////////////////////////////////////////
480{
481    DirectoryEntry entry = m_cache_directory.read_neutral(addr);
482    if ( (entry.count != m_debug_previous_count) or
483         (entry.valid != m_debug_previous_hit) )
484    {
485    std::cout << " MEMC " << name()
486              << " cache change at cycle " << std::dec << m_cpt_cycles
487              << " for address " << std::hex << addr
488              << " / HIT = " << entry.valid
489              << " / COUNT = " << std::dec << entry.count << std::endl;
490    }
491    m_debug_previous_count = entry.count;
492    m_debug_previous_hit = entry.valid;
493}
494
495//////////////////////////////////////////////////
496tmpl(void)::print_trace()
497//////////////////////////////////////////////////
498{
499    std::cout << "MEMC " << name() << std::endl;
500    std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm]
501              << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm]
502              << " | " << read_fsm_str[r_read_fsm]
503              << " | " << write_fsm_str[r_write_fsm]
504              << " | " << sc_fsm_str[r_sc_fsm]
505              << " | " << cleanup_fsm_str[r_cleanup_fsm] << std::endl;
506    std::cout << "  "  << init_cmd_fsm_str[r_init_cmd_fsm]
507              << " | " << init_rsp_fsm_str[r_init_rsp_fsm]
508              << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm]
509              << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm]
510              << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
511}
512
513/////////////////////////////////////////
514tmpl(void)::print_stats()
515/////////////////////////////////////////
516{
517    std::cout << "----------------------------------" << std::dec << std::endl;
518    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
519              << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
520              << "- READ TOTAL           = " << m_cpt_read << std::endl
521              << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
522              << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
523              << "- WRITE TOTAL          = " << m_cpt_write << std::endl
524              << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
525              << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
526              << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
527              << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
528              << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
529              << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
530              << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
531              << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
532              << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
533              << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
534              << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
535              << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
536              << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
537              << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
538}
539
540  /////////////////////////////////
541  tmpl(/**/)::~VciMemCacheV4()
542    /////////////////////////////////
543  {
544    for(size_t i=0; i<m_ways ; i++){
545      for(size_t j=0; j<m_sets ; j++){
546        delete [] m_cache_data[i][j];
547      }
548    }
549    for(size_t i=0; i<m_ways ; i++){
550      delete [] m_cache_data[i];
551    }
552    delete [] m_cache_data;
553
554    delete [] r_ixr_rsp_to_xram_rsp_rok;
555
556    delete [] r_xram_rsp_victim_data;
557    delete [] r_xram_rsp_to_tgt_rsp_data;
558    delete [] r_xram_rsp_to_ixr_cmd_data;
559
560    delete [] r_read_data;
561    delete [] r_read_to_tgt_rsp_data;
562
563    delete [] r_write_data;
564    delete [] r_write_be;
565    delete [] r_write_to_init_cmd_data;
566  }
567
568//////////////////////////////////
569tmpl(void)::transition()
570//////////////////////////////////
571{
572    using soclib::common::uint32_log2;
573
574    //  RESET         
575    if ( ! p_resetn.read() ) {
576
577      //     Initializing FSMs
578      r_tgt_cmd_fsm     = TGT_CMD_IDLE;
579      r_tgt_rsp_fsm     = TGT_RSP_READ_IDLE;
580      r_init_cmd_fsm    = INIT_CMD_INVAL_IDLE;
581      r_init_rsp_fsm    = INIT_RSP_IDLE;
582      r_read_fsm            = READ_IDLE;
583      r_write_fsm           = WRITE_IDLE;
584      r_sc_fsm          = SC_IDLE;
585      r_cleanup_fsm     = CLEANUP_IDLE;
586      r_alloc_dir_fsm   = ALLOC_DIR_READ;
587      r_alloc_heap_fsm  = ALLOC_HEAP_READ;
588      r_alloc_trt_fsm   = ALLOC_TRT_READ;
589      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
590      r_ixr_rsp_fsm     = IXR_RSP_IDLE;
591      r_xram_rsp_fsm    = XRAM_RSP_IDLE;
592      r_ixr_cmd_fsm     = IXR_CMD_READ_IDLE;
593
594      m_debug_global         = false;
595      m_debug_tgt_cmd_fsm    = false;
596      m_debug_tgt_rsp_fsm    = false;
597      m_debug_init_cmd_fsm   = false;
598      m_debug_init_rsp_fsm   = false;
599      m_debug_read_fsm       = false;
600      m_debug_write_fsm      = false;
601      m_debug_sc_fsm         = false;
602      m_debug_cleanup_fsm    = false;
603      m_debug_ixr_cmd_fsm    = false;
604      m_debug_ixr_rsp_fsm    = false;
605      m_debug_xram_rsp_fsm   = false;
606      m_debug_previous_hit   = false;
607      m_debug_previous_count = 0;
608
609      //  Initializing Tables
610      m_cache_directory.init();
611      m_transaction_tab.init();
612      m_heap.init();
613
614      // initializing FIFOs and communication Buffers
615
616      m_cmd_read_addr_fifo.init();
617      m_cmd_read_length_fifo.init();
618      m_cmd_read_srcid_fifo.init();
619      m_cmd_read_trdid_fifo.init();
620      m_cmd_read_pktid_fifo.init();
621
622      m_cmd_write_addr_fifo.init();
623      m_cmd_write_eop_fifo.init();
624      m_cmd_write_srcid_fifo.init();
625      m_cmd_write_trdid_fifo.init();
626      m_cmd_write_pktid_fifo.init();
627      m_cmd_write_data_fifo.init();
628
629      m_cmd_sc_addr_fifo.init();
630      m_cmd_sc_srcid_fifo.init();
631      m_cmd_sc_trdid_fifo.init();
632      m_cmd_sc_pktid_fifo.init();
633      m_cmd_sc_wdata_fifo.init();
634      m_cmd_sc_eop_fifo.init();
635
636      r_read_to_tgt_rsp_req                 = false;
637      r_read_to_ixr_cmd_req                 = false;
638
639      r_write_to_tgt_rsp_req            = false;
640      r_write_to_ixr_cmd_req            = false;
641      r_write_to_init_cmd_multi_req         = false;
642      r_write_to_init_cmd_brdcast_req   = false;
643      r_write_to_init_rsp_req           = false;
644      m_write_to_init_cmd_inst_fifo.init();
645      m_write_to_init_cmd_srcid_fifo.init();
646#if L1_MULTI_CACHE
647      m_write_to_init_cmd_cache_id_fifo.init();
648#endif
649
650      r_cleanup_to_tgt_rsp_req          = false;
651
652      r_init_rsp_to_tgt_rsp_req         = false;
653
654      r_sc_to_tgt_rsp_req                   = false;
655      r_sc_cpt                          = 0;
656      r_sc_lfsr                         = -1;
657      r_sc_to_ixr_cmd_req                   = false;
658      r_sc_to_init_cmd_multi_req            = false;
659      r_sc_to_init_cmd_brdcast_req          = false;
660      m_sc_to_init_cmd_inst_fifo.init();
661      m_sc_to_init_cmd_srcid_fifo.init();
662#if L1_MULTI_CACHE
663      m_sc_to_init_cmd_cache_id_fifo.init();
664#endif
665
666      for(size_t i=0; i<m_transaction_tab_lines ; i++){
667        r_ixr_rsp_to_xram_rsp_rok[i] = false;
668      }
669
670      r_xram_rsp_to_tgt_rsp_req             = false;
671      r_xram_rsp_to_init_cmd_multi_req      = false;
672      r_xram_rsp_to_init_cmd_brdcast_req    = false;
673      r_xram_rsp_to_ixr_cmd_req             = false;
674      r_xram_rsp_trt_index                      = 0;
675      m_xram_rsp_to_init_cmd_inst_fifo.init();
676      m_xram_rsp_to_init_cmd_srcid_fifo.init();
677#if L1_MULTI_CACHE
678      m_xram_rsp_to_init_cmd_cache_id_fifo.init();
679#endif
680
681      r_ixr_cmd_cpt         = 0;
682
683      r_copies_limit        = 3;
684
685      // Activity counters
686      m_cpt_cycles                  = 0;
687      m_cpt_read                    = 0;
688      m_cpt_read_miss       = 0;
689      m_cpt_write                   = 0;
690      m_cpt_write_miss      = 0;
691      m_cpt_write_cells     = 0;
692      m_cpt_write_dirty     = 0;
693      m_cpt_update                  = 0;
694      m_cpt_update_mult     = 0;
695      m_cpt_inval_brdcast       = 0;
696      m_cpt_inval                   = 0;
697      m_cpt_inval_mult          = 0;
698      m_cpt_cleanup                 = 0;
699      m_cpt_ll                      = 0;
700      m_cpt_sc                      = 0;
701      m_cpt_trt_full        = 0;
702      m_cpt_trt_rb          = 0;
703
704      return;
705    }
706
707    bool    cmd_read_fifo_put = false;
708    bool    cmd_read_fifo_get = false;
709
710    bool    cmd_write_fifo_put = false;
711    bool    cmd_write_fifo_get = false;
712
713    bool    cmd_sc_fifo_put = false;
714    bool    cmd_sc_fifo_get = false;
715
716    bool    write_to_init_cmd_fifo_put      = false;
717    bool    write_to_init_cmd_fifo_get      = false;
718    bool    write_to_init_cmd_fifo_inst     = false;
719    size_t  write_to_init_cmd_fifo_srcid    = 0;
720
721#if L1_MULTI_CACHE
722    size_t  write_to_init_cmd_fifo_cache_id = 0;
723#endif
724
725    bool    xram_rsp_to_init_cmd_fifo_put      = false;
726    bool    xram_rsp_to_init_cmd_fifo_get      = false;
727    bool    xram_rsp_to_init_cmd_fifo_inst     = false;
728    size_t  xram_rsp_to_init_cmd_fifo_srcid    = 0;
729
730#if L1_MULTI_CACHE
731    size_t  xram_rsp_to_init_cmd_fifo_cache_id = 0;
732#endif
733
734    bool    sc_to_init_cmd_fifo_put      = false;
735    bool    sc_to_init_cmd_fifo_get      = false;
736    bool    sc_to_init_cmd_fifo_inst     = false;
737    size_t  sc_to_init_cmd_fifo_srcid    = 0;
738
739#if L1_MULTI_CACHE
740    size_t  sc_to_init_cmd_fifo_cache_id = 0;
741#endif
742
743m_debug_global       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
744m_debug_tgt_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
745m_debug_tgt_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
746m_debug_init_cmd_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
747m_debug_init_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
748m_debug_read_fsm     = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
749m_debug_write_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
750m_debug_sc_fsm       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
751m_debug_cleanup_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
752m_debug_ixr_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
753m_debug_ixr_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
754m_debug_xram_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
755
756
757#if DEBUG_MEMC_GLOBAL   
758if( m_debug_global )
759{
760    std::cout << "---------------------------------------------" << std::dec << std::endl;
761    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
762      << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
763      << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
764      << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
765      << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
766      << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
767      << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
768      << " - SC FSM         = " << sc_fsm_str[r_sc_fsm] << std::endl
769      << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
770      << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
771      << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
772      << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
773      << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
774      << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
775      << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
776      << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
777}
778#endif
779
780    ////////////////////////////////////////////////////////////////////////////////////
781    //          TGT_CMD FSM
782    ////////////////////////////////////////////////////////////////////////////////////
783    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
784    //
785    // There is 3 types of accepted commands :
786    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word
787    //             or an entire cache line, depending on the PLEN value.
788    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
789    //             concern words in a same line.
790    // - SC      : The SC request has a length of 2 cells or 4 cells.
791    ////////////////////////////////////////////////////////////////////////////////////
792
793    switch ( r_tgt_cmd_fsm.read() )
794    {
795        //////////////////
796        case TGT_CMD_IDLE:
797        {
798            if ( p_vci_tgt.cmdval )
799            {
800
801#if DEBUG_MEMC_TGT_CMD
802if( m_debug_tgt_cmd_fsm )
803{
804    std::cout << "  <MEMC.TGT_CMD_IDLE> Receive command from srcid " << std::dec << p_vci_tgt.srcid.read()
805              << " / for address " << std::hex << p_vci_tgt.address.read() << std::endl;
806}
807#endif
808                // checking segmentation violation
809                vci_addr_t  address = p_vci_tgt.address.read();
810                uint32_t    plen    = p_vci_tgt.plen.read();
811                bool found = false;
812                for ( size_t seg_id = 0 ; seg_id < m_nseg ; seg_id++ )
813                {
814                    if ( m_seg[seg_id]->contains(address) &&
815                         m_seg[seg_id]->contains(address + plen - vci_param::B) )
816                    {
817                        found = true;
818                    }
819                }
820                if ( not found )
821                {
822                    std::cout << "VCI_MEM_CACHE ERROR " << name() << std::endl;
823                    std::cout << "Out of segment VCI address in TGT_CMD_IDLE state" << std::endl;
824                    exit(0);
825                }
826
827                if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ )
828                {
829                    r_tgt_cmd_fsm = TGT_CMD_READ;
830                }
831                else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
832                { 
833                    r_tgt_cmd_fsm = TGT_CMD_WRITE;
834                }
835                else if ( p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND )
836                {
837                    r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
838                }
839                else
840                {
841                    std::cout << "VCI_MEM_CACHE ERROR " << name()
842                              << " TGT_CMD_IDLE state" << std::endl;
843                    std::cout << " illegal VCI command type" << std::endl;
844                    exit(0);
845                }
846            }
847            break;
848        }
849        //////////////////
850        case TGT_CMD_READ:
851        {
852            if ((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16)
853            {
854                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
855                std::cout << " illegal address/plen combination for VCI read command" << std::endl;
856                exit(0);
857            }
858            if ( !p_vci_tgt.eop.read() )
859            {
860                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
861                std::cout << " read command packets must contain one single flit" << std::endl;
862                exit(0);
863            }
864
865            if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() )
866            {
867           
868#if DEBUG_MEMC_TGT_CMD
869if( m_debug_tgt_cmd_fsm )
870{
871    std::cout << "  <MEMC.TGT_CMD_READ> Push into read_fifo:"
872              << " address = " << std::hex << p_vci_tgt.address.read()
873              << " srcid = " << std::dec << p_vci_tgt.srcid.read()
874              << " trdid = " << p_vci_tgt.trdid.read()
875              << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
876}
877#endif
878                cmd_read_fifo_put = true;
879                m_cpt_read++;
880                r_tgt_cmd_fsm = TGT_CMD_IDLE;
881            }
882            break;
883        }
884        ///////////////////
885        case TGT_CMD_WRITE:
886        {
887            if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() )
888            {
889           
890#if DEBUG_MEMC_TGT_CMD
891if( m_debug_tgt_cmd_fsm )
892{
893    std::cout << "  <MEMC.TGT_CMD_WRITE> Push into write_fifo:"
894              << " address = " << std::hex << p_vci_tgt.address.read()
895              << " srcid = " << std::dec << p_vci_tgt.srcid.read()
896              << " trdid = " << p_vci_tgt.trdid.read()
897              << " wdata = " << std::hex << p_vci_tgt.wdata.read()
898              << " be = " << p_vci_tgt.be.read()
899              << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
900}
901#endif
902                cmd_write_fifo_put = true;
903                if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
904            }
905            break;
906        }
907        ////////////////////
908        case TGT_CMD_ATOMIC:
909        {
910            if ( (p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16) )
911            {
912                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_ATOMIC state" << std::endl;
913                std::cout << "illegal format for sc command " << std::endl;
914                exit(0);
915            }
916
917            if ( p_vci_tgt.cmdval && m_cmd_sc_addr_fifo.wok() )
918            {
919           
920#if DEBUG_MEMC_TGT_CMD
921if( m_debug_tgt_cmd_fsm )
922{
923    std::cout << "  <MEMC.TGT_CMD_ATOMIC> Pushing command into cmd_sc_fifo:"
924              << " address = " << std::hex << p_vci_tgt.address.read()
925              << " srcid = " << std::dec << p_vci_tgt.srcid.read()
926              << " trdid = " << p_vci_tgt.trdid.read()
927              << " wdata = " << std::hex << p_vci_tgt.wdata.read()
928              << " be = " << p_vci_tgt.be.read()
929              << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
930}
931#endif
932                cmd_sc_fifo_put = true;
933                if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
934            }
935            break;
936        }
937    } // end switch tgt_cmd_fsm
938
939    /////////////////////////////////////////////////////////////////////////
940    //          INIT_RSP FSM
941    /////////////////////////////////////////////////////////////////////////
942    // This FSM controls the response to the update or inval coherence
943    // requests sent by the memory cache to the L1 caches and update the UPT.
944    //
945    // It can be update or inval requests initiated by the WRITE FSM,
946    // or inval requests initiated by the XRAM_RSP FSM. 
947    // It can also be a direct request from the WRITE FSM.
948    //
949    // The FSM decrements the proper entry in UPT.
950    // It sends a request to the TGT_RSP FSM to complete the pending
951    // write transaction (acknowledge response to the writer processor),
952    // and clear the UPT entry when all responses have been received. 
953    //
954    // All those response packets are one word, compact
955    // packets complying with the VCI advanced format.
956    // The index in the Table is defined in the RTRDID field, and
957    // the transaction type is defined in the UPT entry.
958    /////////////////////////////////////////////////////////////////////
959
960    switch ( r_init_rsp_fsm.read() )
961    {
962        ///////////////////
963        case INIT_RSP_IDLE:   // wait a response for a coherence transaction
964        {
965            if ( p_vci_ini.rspval )
966            {
967
968#if DEBUG_MEMC_INIT_RSP
969if( m_debug_init_rsp_fsm )
970{
971    std::cout <<  "  <MEMC.INIT_RSP_IDLE> Response for UPT entry "
972              << p_vci_ini.rtrdid.read() << std::endl;
973}
974#endif
975                if ( p_vci_ini.rtrdid.read() >= m_update_tab.size() )
976                {
977                    std::cout << "VCI_MEM_CACHE ERROR " << name()
978                              << " INIT_RSP_IDLE state" << std::endl
979                              << "index too large for UPT: "
980                              << " / rtrdid = " << std::dec << p_vci_ini.rtrdid.read()
981                              << " / UPT size = " << std::dec << m_update_tab.size() << std::endl;
982                    exit(0);
983                }
984                if ( !p_vci_ini.reop.read() )
985                {
986                    std::cout << "VCI_MEM_CACHE ERROR " << name()
987                              << " INIT_RSP_IDLE state" << std::endl;
988                    std::cout << "all coherence response packets must be one flit" << std::endl;
989                    exit(0);
990                }
991
992                r_init_rsp_upt_index = p_vci_ini.rtrdid.read();
993                r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
994            }
995            else if( r_write_to_init_rsp_req.read() )
996            {
997                r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
998                r_write_to_init_rsp_req = false;
999                r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
1000            }
1001            break;
1002        }
1003        ///////////////////////
1004        case INIT_RSP_UPT_LOCK: // decrement the number of expected responses
1005        {
1006            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP )
1007            {
1008                size_t count = 0;
1009                bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
1010
1011#if DEBUG_MEMC_INIT_RSP
1012if( m_debug_init_rsp_fsm )
1013{
1014    std::cout << "  <MEMC.INIT_RSP_UPT_LOCK> Decrement the responses counter for UPT:"
1015              << " entry = " << r_init_rsp_upt_index.read()
1016              << " / rsp_count = " << std::dec << count << std::endl;
1017}
1018#endif
1019                if ( not valid )
1020                {
1021                    std::cout << "VCI_MEM_CACHE ERROR " << name()
1022                              << " INIT_RSP_UPT_LOCK state" << std::endl
1023                              << "unsuccessful access to decrement the UPT" << std::endl;
1024                    exit(0);
1025                }
1026
1027                if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
1028                else              r_init_rsp_fsm = INIT_RSP_IDLE;
1029            }
1030            break;
1031        }
1032        ////////////////////////
1033        case INIT_RSP_UPT_CLEAR:        // clear the UPT entry
1034        {
1035            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP )
1036            {
1037                r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
1038                r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
1039                r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
1040                r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
1041                bool need_rsp    = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
1042
1043                if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
1044                else            r_init_rsp_fsm = INIT_RSP_IDLE;
1045
1046                m_update_tab.clear(r_init_rsp_upt_index.read());
1047
1048#if DEBUG_MEMC_INIT_RSP
1049if ( m_debug_init_rsp_fsm )
1050{
1051    std::cout <<  "  <MEMC.INIT_RSP_UPT_CLEAR> Clear UPT entry "
1052              << r_init_rsp_upt_index.read() <<  std::endl;
1053}
1054#endif
1055            }
1056            break;
1057        }
1058        //////////////////
1059        case INIT_RSP_END:      // Post a request to TGT_RSP FSM
1060        {
1061            if ( !r_init_rsp_to_tgt_rsp_req )
1062            {
1063                r_init_rsp_to_tgt_rsp_req   = true;
1064                r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
1065                r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
1066                r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
1067                r_init_rsp_fsm = INIT_RSP_IDLE;
1068
1069#if DEBUG_MEMC_INIT_RSP
1070if ( m_debug_init_rsp_fsm )
1071{
1072    std::cout <<  "  <MEMC.INIT_RSP_END> Request TGT_RSP FSM to send a response to srcid "
1073              << r_init_rsp_srcid.read() <<  std::endl;
1074}
1075#endif
1076            }
1077            break;
1078        }
1079    } // end switch r_init_rsp_fsm
1080
1081    ////////////////////////////////////////////////////////////////////////////////////
1082    //          READ FSM
1083    ////////////////////////////////////////////////////////////////////////////////////
1084    // The READ FSM controls the VCI read requests.
1085    // It takes the lock protecting the cache directory to check the cache line status:
1086    // - In case of HIT
1087    //   The fsm copies the data (one line, or one single word)
1088    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
1089    //   The requesting initiator is registered in the cache directory.
1090    //   If the number of copy is larger than 1, the new copy is registered
1091    //   in the HEAP.
1092    //   If the number of copy is larger than the threshold, the HEAP is cleared,
1093    //   and the corresponding line switches to the counter mode.
1094    // - In case of MISS
1095    //   The READ fsm takes the lock protecting the transaction tab.
1096    //   If a read transaction to the XRAM for this line already exists,
1097    //   or if the transaction tab is full, the fsm is stalled.
1098    //   If a TRT entry is free, the READ request is registered in TRT,
1099    //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
1100    //   The READ FSM returns in the IDLE state as the read transaction will be
1101    //   completed when the missing line will be received.
1102    ////////////////////////////////////////////////////////////////////////////////////
1103
1104    switch ( r_read_fsm.read() )
1105    {
1106        ///////////////
1107        case READ_IDLE:         // waiting a read request
1108        {
1109            if (m_cmd_read_addr_fifo.rok())
1110            {
1111
1112#if DEBUG_MEMC_READ
1113if( m_debug_read_fsm )
1114{
1115    std::cout << "  <MEMC.READ_IDLE> Read request:"
1116              << " srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
1117              << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
1118              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1119}
1120#endif
1121                r_read_fsm = READ_DIR_LOCK;
1122            }
1123            break;
1124        }
1125        ///////////////////
1126        case READ_DIR_LOCK:     // check directory for hit / miss
1127        {
1128            if ( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
1129            {
1130                size_t way = 0;
1131                DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
1132
1133                r_read_is_cnt     = entry.is_cnt;
1134                r_read_dirty      = entry.dirty;
1135                r_read_lock           = entry.lock;
1136                r_read_tag            = entry.tag;
1137                r_read_way            = way;
1138                r_read_count      = entry.count;
1139                r_read_copy       = entry.owner.srcid;
1140
1141#if L1_MULTI_CACHE
1142                r_read_copy_cache = entry.owner.cache_id;
1143#endif
1144                r_read_copy_inst  = entry.owner.inst;
1145                r_read_ptr        = entry.ptr;              // pointer to the heap
1146
1147                bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
1148                if(  entry.valid )      // hit
1149                {
1150                    // test if we need to register a new copy in the heap
1151                    if ( entry.is_cnt || (entry.count == 0) || !cached_read )
1152                        r_read_fsm = READ_DIR_HIT;
1153                    else
1154                        r_read_fsm = READ_HEAP_LOCK;
1155                }
1156                else                    // miss
1157                {
1158                    r_read_fsm = READ_TRT_LOCK;
1159                }
1160
1161#if DEBUG_MEMC_READ
1162if( m_debug_read_fsm )
1163{
1164    std::cout << "  <MEMC.READ_DIR_LOCK> Accessing directory: "
1165              << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1166              << " / hit = " << std::dec << entry.valid
1167              << " / count = " <<std::dec << entry.count
1168              << " / is_cnt = " << entry.is_cnt << std::endl;
1169}
1170#endif
1171            }
1172            break;
1173        }
1174        //////////////////
1175        case READ_DIR_HIT:          //  read data in cache & update the directory
1176                                //  we enter this state in 3 cases:
1177                                //  - the read request is uncachable
1178                                //  - the cache line is in counter mode
1179                                //  - the cache line is valid but not replcated
1180        {
1181            if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
1182            {
1183                // signals generation
1184                bool inst_read    = (m_cmd_read_trdid_fifo.read() & 0x2);
1185                bool cached_read  = (m_cmd_read_trdid_fifo.read() & 0x1);
1186                bool is_cnt       = r_read_is_cnt.read();
1187
1188                // read data in the cache
1189                size_t set        = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1190                size_t way        = r_read_way.read();
1191                for ( size_t i=0 ; i<m_words ; i++ ) r_read_data[i] = m_cache_data[way][set][i];
1192
1193                // update the cache directory
1194                DirectoryEntry entry;
1195                entry.valid       = true;
1196                entry.is_cnt  = is_cnt;
1197                entry.dirty       = r_read_dirty.read();
1198                entry.tag         = r_read_tag.read();
1199                entry.lock        = r_read_lock.read();
1200                entry.ptr     = r_read_ptr.read();
1201                if (cached_read)  // Cached read => we must update the copies
1202                {
1203                    if (!is_cnt) // Not counter mode
1204                    {
1205                        entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1206#if L1_MULTI_CACHE
1207                        entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1208#endif
1209                        entry.owner.inst     = inst_read;
1210                        entry.count          = r_read_count.read() + 1;
1211                    }
1212                    else  // Counter mode
1213                    {
1214                        entry.owner.srcid    = 0;
1215#if L1_MULTI_CACHE
1216                        entry.owner.cache_id = 0;
1217#endif
1218                        entry.owner.inst     = false;
1219                        entry.count          = r_read_count.read() + 1;
1220                    }
1221                }
1222                else  // Uncached read
1223                {
1224                    entry.owner.srcid     = r_read_copy.read();
1225#if L1_MULTI_CACHE
1226                    entry.owner.cache_id  = r_read_copy_cache.read();
1227#endif
1228                    entry.owner.inst      = r_read_copy_inst.read();
1229                    entry.count           = r_read_count.read();
1230                }
1231
1232#if DEBUG_MEMC_READ
1233if( m_debug_read_fsm )
1234{
1235    std::cout << "  <MEMC.READ_DIR_HIT> Update directory entry:"
1236              << " set = " << std::dec << set
1237              << " / way = " << way
1238              << " / owner_id = " << entry.owner.srcid
1239              << " / owner_ins = " << entry.owner.inst
1240              << " / count = " << entry.count
1241              << " / is_cnt = " << entry.is_cnt << std::endl;
1242}
1243#endif
1244
1245                m_cache_directory.write(set, way, entry);
1246                r_read_fsm    = READ_RSP;
1247            }
1248            break;
1249        }
1250        ////////////////////
1251        case READ_HEAP_LOCK:    // read data in cache, update the directory
1252                                // and prepare the HEAP update       
1253        {
1254            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1255            {
1256                // enter counter mode when we reach the limit of copies or the heap is full
1257                bool go_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap.is_full();
1258
1259                // read data in the cache
1260                size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1261                size_t way = r_read_way.read();
1262                for ( size_t i=0 ; i<m_words ; i++ ) r_read_data[i] = m_cache_data[way][set][i];
1263
1264                // update the cache directory
1265                DirectoryEntry entry;
1266                entry.valid       = true;
1267                entry.is_cnt  = go_cnt;
1268                entry.dirty       = r_read_dirty.read();
1269                entry.tag         = r_read_tag.read();
1270                entry.lock        = r_read_lock.read();
1271                entry.count   = r_read_count.read() + 1;
1272
1273                if (not go_cnt)        // Not entering counter mode
1274                {
1275                    entry.owner.srcid   = r_read_copy.read();
1276#if L1_MULTI_CACHE
1277                    entry.owner.cache_id= r_read_copy_cache.read();
1278#endif
1279                    entry.owner.inst    = r_read_copy_inst.read();
1280                    entry.ptr           = m_heap.next_free_ptr();   // set pointer on the heap
1281                }
1282                else                // Entering Counter mode
1283                {
1284                    entry.owner.srcid   = 0;
1285#if L1_MULTI_CACHE
1286                    entry.owner.cache_id= 0;
1287#endif
1288                    entry.owner.inst    = false;
1289                    entry.ptr           = 0;
1290                }
1291
1292                m_cache_directory.write(set, way, entry);
1293
1294                // prepare the heap update (add an entry, or clear the linked list)
1295                if (not go_cnt)     // not switching to counter mode
1296                {
1297                    // We test if the next free entry in the heap is the last
1298                    HeapEntry heap_entry = m_heap.next_free_entry();
1299                    r_read_next_ptr      = heap_entry.next;
1300                    r_read_last_free     = ( heap_entry.next == m_heap.next_free_ptr() );
1301
1302                    r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
1303                }
1304                else                    // switching to counter mode
1305                {
1306                    if ( r_read_count.read()>1 )            // heap must be cleared
1307                    {
1308                        HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1309                        r_read_next_ptr      = m_heap.next_free_ptr();
1310                        m_heap.write_free_ptr(r_read_ptr.read());
1311
1312                        if( next_entry.next == r_read_ptr.read() )  // last entry
1313                        {
1314                            r_read_fsm = READ_HEAP_LAST;    // erase the entry
1315                        }
1316                        else                                        // not the last entry
1317                        {
1318                            r_read_ptr = next_entry.next;
1319                            r_read_fsm = READ_HEAP_ERASE;   // erase the list
1320                        }
1321                    }
1322                    else        // the heap is not used / nothing to do
1323                    {
1324                        r_read_fsm = READ_RSP;
1325                    }
1326                }
1327
1328#if DEBUG_MEMC_READ
1329if( m_debug_read_fsm )
1330{
1331    std::cout << "  <MEMC.READ_HEAP_LOCK> Update directory:"
1332              << " tag = " << std::hex << entry.tag
1333              << " set = " << std::dec << set
1334              << " way = " << way
1335              << " count = " << entry.count
1336              << " is_cnt = " << entry.is_cnt << std::endl;
1337}
1338#endif
1339            }
1340            break;
1341        }
1342        /////////////////////
1343        case READ_HEAP_WRITE:       // add a entry in the heap
1344        {
1345            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1346            {
1347                HeapEntry heap_entry;
1348                heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1349#if L1_MULTI_CACHE
1350                heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1351#endif
1352                heap_entry.owner.inst     = (m_cmd_read_trdid_fifo.read() & 0x2);
1353
1354                if(r_read_count.read() == 1)    // creation of a new linked list
1355                {
1356                    heap_entry.next         = m_heap.next_free_ptr();
1357                }
1358                else                            // head insertion in existing list
1359                {
1360                    heap_entry.next         = r_read_ptr.read();
1361                }
1362                m_heap.write_free_entry(heap_entry);
1363                m_heap.write_free_ptr(r_read_next_ptr.read());
1364                if(r_read_last_free.read())  m_heap.set_full();
1365
1366                r_read_fsm = READ_RSP;
1367
1368#if DEBUG_MEMC_READ
1369if( m_debug_read_fsm )
1370{
1371    std::cout << "  <MEMC.READ_HEAP_WRITE> Add an entry in the heap:"
1372              << " owner_id = " << heap_entry.owner.srcid
1373              << " owner_ins = " << heap_entry.owner.inst << std::endl;
1374}
1375#endif
1376            }
1377            else
1378            {
1379                std::cout << "VCI_MEM_CACHE ERROR " << name()
1380                          << " READ_HEAP_WRITE state" << std::endl;
1381                std::cout << "Bad HEAP allocation" << std::endl;
1382                exit(0);
1383            }
1384            break;
1385        }
1386        /////////////////////
1387        case READ_HEAP_ERASE:
1388        {
1389            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1390            {
1391                HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1392                if( next_entry.next == r_read_ptr.read() )
1393                {
1394                    r_read_fsm = READ_HEAP_LAST;
1395                }
1396                else
1397                {
1398                    r_read_ptr = next_entry.next;
1399                    r_read_fsm = READ_HEAP_ERASE;
1400                }
1401            }
1402            else
1403            {
1404                std::cout << "VCI_MEM_CACHE ERROR " << name()
1405                          << " READ_HEAP_ERASE state" << std::endl;
1406                std::cout << "Bad HEAP allocation" << std::endl;
1407                exit(0);
1408            }
1409            break;
1410        }
1411        ////////////////////
1412        case READ_HEAP_LAST:
1413        {
1414            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1415            {
1416                HeapEntry last_entry;
1417                last_entry.owner.srcid    = 0;
1418#if L1_MULTI_CACHE
1419                last_entry.owner.cache_id = 0;
1420#endif
1421                last_entry.owner.inst     = false;
1422
1423                if(m_heap.is_full())
1424                {
1425                    last_entry.next       = r_read_ptr.read();
1426                    m_heap.unset_full();
1427                }
1428                else
1429                {
1430                    last_entry.next       = r_read_next_ptr.read();
1431                }
1432                m_heap.write(r_read_ptr.read(),last_entry);
1433                r_read_fsm = READ_RSP;
1434            }
1435            else
1436            {
1437                std::cout << "VCI_MEM_CACHE ERROR " << name()
1438                          << " READ_HEAP_LAST state" << std::endl;
1439                std::cout << "Bad HEAP allocation" << std::endl;
1440                exit(0);
1441            }
1442            break;
1443        }
1444        //////////////
1445        case READ_RSP:          //  request the TGT_RSP FSM to return data
1446        {
1447            if( !r_read_to_tgt_rsp_req )
1448            {   
1449                for ( size_t i=0 ; i<m_words ; i++ )  r_read_to_tgt_rsp_data[i] = r_read_data[i];
1450                r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
1451                r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
1452                r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
1453                r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
1454                r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
1455                cmd_read_fifo_get        = true;
1456                r_read_to_tgt_rsp_req    = true;
1457                r_read_fsm               = READ_IDLE; 
1458
1459#if DEBUG_MEMC_READ
1460if( m_debug_read_fsm )
1461{
1462    std::cout << "  <MEMC.READ_RSP> Request the TGT_RSP FSM to return data:"
1463              << " rsrcid = " << std::dec << m_cmd_read_srcid_fifo.read()
1464              << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
1465              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1466}
1467#endif
1468            }
1469            break;
1470        }
1471        ///////////////////
1472        case READ_TRT_LOCK:     // read miss : check the Transaction Table
1473        {
1474            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ )
1475            {
1476                size_t      index     = 0;
1477                vci_addr_t  addr      = (vci_addr_t)m_cmd_read_addr_fifo.read();
1478                bool        hit_read  = m_transaction_tab.hit_read(m_nline[addr], index);
1479                bool        hit_write = m_transaction_tab.hit_write(m_nline[addr]);
1480                bool        wok       = !m_transaction_tab.full(index);
1481
1482                if( hit_read || !wok || hit_write )  // missing line already requested or no space
1483                {
1484                    if(!wok)                    m_cpt_trt_full++;
1485                    if(hit_read || hit_write)   m_cpt_trt_rb++;
1486                    r_read_fsm = READ_IDLE;
1487                }
1488                else                                // missing line is requested to the XRAM
1489                {
1490                    m_cpt_read_miss++;
1491                    r_read_trt_index = index;
1492                    r_read_fsm       = READ_TRT_SET;
1493                }
1494
1495#if DEBUG_MEMC_READ
1496if( m_debug_read_fsm )
1497{
1498    std::cout << "  <MEMC.READ_TRT_LOCK> Check TRT:"
1499              << " hit_read = " << hit_read
1500              << " / hit_write = " << hit_write
1501              << " / full = " << !wok << std::endl;
1502}
1503#endif
1504            }
1505            break;
1506        }
1507        //////////////////
1508        case READ_TRT_SET:      // register get transaction in TRT
1509        {
1510            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ )
1511            {
1512                m_transaction_tab.set(r_read_trt_index.read(),
1513                                      true,
1514                                      m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1515                                      m_cmd_read_srcid_fifo.read(),
1516                                      m_cmd_read_trdid_fifo.read(),
1517                                      m_cmd_read_pktid_fifo.read(),
1518                                      true,
1519                                      m_cmd_read_length_fifo.read(),
1520                                      m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1521                                      std::vector<be_t>(m_words,0),
1522                                      std::vector<data_t>(m_words,0));
1523#if DEBUG_MEMC_READ
1524if( m_debug_read_fsm )
1525{
1526    std::cout << "  <MEMC.READ_TRT_SET> Write in Transaction Table: " << std::hex
1527              << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1528              << " / srcid = " << std::dec << m_cmd_read_srcid_fifo.read()
1529              << std::endl;
1530}
1531#endif
1532                r_read_fsm = READ_TRT_REQ;
1533            }
1534            break;
1535        }
1536        //////////////////
1537        case READ_TRT_REQ:              // consume the read request in the FIFO,
1538                                                // and send it to the ixr_cmd_fsm
1539        {       
1540            if( not r_read_to_ixr_cmd_req )
1541            {
1542                cmd_read_fifo_get           = true;
1543                r_read_to_ixr_cmd_req   = true;
1544                r_read_to_ixr_cmd_nline = m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1545                r_read_to_ixr_cmd_trdid = r_read_trt_index.read();
1546                r_read_fsm                  = READ_IDLE;
1547
1548#if DEBUG_MEMC_READ
1549if( m_debug_read_fsm )
1550{
1551    std::cout << "  <MEMC.READ_TRT_REQ> Request GET transaction for address "
1552              << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
1553}
1554#endif
1555            }
1556            break;
1557        }
1558    } // end switch read_fsm
1559
1560    ///////////////////////////////////////////////////////////////////////////////////
1561    //          WRITE FSM
1562    ///////////////////////////////////////////////////////////////////////////////////
1563    // The WRITE FSM handles the write bursts sent by the processors.
1564    // All addresses in a burst must be in the same cache line.
1565    // A complete write burst is consumed in the FIFO & copied to a local buffer.
1566    // Then the FSM takes the lock protecting the cache directory, to check
1567    // if the line is in the cache.
1568    //
1569    // - In case of HIT, the cache is updated.
1570    //   If there is no other copy, an acknowledge response is immediately
1571    //   returned to the writing processor.
1572    //   If the data is cached by other processors, a coherence transaction must
1573    //   be launched:
1574    //   It is a multicast update if the line is not in counter mode, and the processor
1575    //   takes the lock protecting the Update Table (UPT) to register this transaction.
1576    //   It is a broadcast invalidate if the line is in counter mode.
1577    //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
1578    //   a multi-update request to all owners of the line (but the writer),
1579    //   through the INIT_CMD FSM. In case of coherence transaction, the WRITE FSM
1580    //   does not respond to the writing processor, as this response will be sent by
1581    //   the INIT_RSP FSM when all update responses have been received.
1582    //
1583    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
1584    //   table (TRT). If a read transaction to the XRAM for this line already exists,
1585    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
1586    //   the WRITE FSM register a new transaction in TRT, and sends a read line request
1587    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
1588    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
1589    /////////////////////////////////////////////////////////////////////////////////////
1590
1591    switch ( r_write_fsm.read() )
1592    {
1593        ////////////////
1594        case WRITE_IDLE:        // copy first word of a write burst in local buffer     
1595        {
1596            if ( m_cmd_write_addr_fifo.rok() )
1597            {
1598                m_cpt_write++;
1599                m_cpt_write_cells++;
1600
1601                // consume a word in the FIFO & write it in the local buffer
1602                cmd_write_fifo_get      = true;
1603                size_t index            = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
1604
1605                r_write_address         = (addr_t)(m_cmd_write_addr_fifo.read());
1606                r_write_word_index      = index;
1607                r_write_word_count      = 1;
1608                r_write_data[index]     = m_cmd_write_data_fifo.read();
1609                r_write_srcid           = m_cmd_write_srcid_fifo.read();
1610                r_write_trdid           = m_cmd_write_trdid_fifo.read();
1611                r_write_pktid           = m_cmd_write_pktid_fifo.read();
1612
1613                // initialize the be field for all words
1614                for ( size_t i=0 ; i<m_words ; i++ )
1615                {
1616                    if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
1617                    else              r_write_be[i] = 0x0;
1618                }
1619
1620                if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1621                    r_write_byte = true;
1622                else   
1623                    r_write_byte = false;
1624
1625                if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1626                else                               r_write_fsm = WRITE_NEXT;
1627
1628#if DEBUG_MEMC_WRITE
1629if( m_debug_write_fsm )
1630{
1631    std::cout << "  <MEMC.WRITE_IDLE> Write request "
1632              << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
1633              << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
1634              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
1635}
1636#endif
1637            }
1638            break;
1639        }
1640        ////////////////
1641        case WRITE_NEXT:        // copy next word of a write burst in local buffer
1642        {
1643            if ( m_cmd_write_addr_fifo.rok() )
1644            {
1645
1646#if DEBUG_MEMC_WRITE
1647if( m_debug_write_fsm )
1648{
1649    std::cout << "  <MEMC.WRITE_NEXT> Write another word in local buffer" << std::endl;
1650}
1651#endif
1652                m_cpt_write_cells++;
1653
1654                // check that the next word is in the same cache line
1655                if ( (m_nline[(vci_addr_t)(r_write_address.read())] !=
1656                      m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())]) )
1657                {
1658                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_NEXT state" << std::endl;
1659                    std::cout << "all words in a write burst must be in same cache line" << std::endl;
1660                    exit(0);
1661                }
1662
1663                // consume a word in the FIFO & write it in the local buffer
1664                cmd_write_fifo_get=true;
1665                size_t index            = r_write_word_index.read() + r_write_word_count.read();
1666
1667                r_write_be[index]       = m_cmd_write_be_fifo.read();
1668                r_write_data[index]     = m_cmd_write_data_fifo.read();
1669                r_write_word_count      = r_write_word_count.read() + 1;
1670
1671                if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1672                    r_write_byte = true;
1673
1674                if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1675            }
1676            break;
1677        }
1678        ////////////////////
1679        case WRITE_DIR_LOCK:    // access directory to check hit/miss
1680        {
1681            if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
1682            {
1683                size_t  way = 0;
1684                DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
1685
1686                if ( entry.valid ) // hit
1687                {       
1688                    // copy directory entry in local buffer in case of hit
1689                    r_write_is_cnt     = entry.is_cnt;
1690                    r_write_lock       = entry.lock;
1691                    r_write_tag        = entry.tag;
1692                    r_write_copy       = entry.owner.srcid;
1693#if L1_MULTI_CACHE
1694                    r_write_copy_cache = entry.owner.cache_id;
1695#endif
1696                    r_write_copy_inst  = entry.owner.inst;
1697                    r_write_count      = entry.count;
1698                    r_write_ptr        = entry.ptr;
1699                    r_write_way        = way;
1700
1701                    if( entry.is_cnt && entry.count )
1702                    {
1703                        r_write_fsm      = WRITE_DIR_READ;
1704                    }
1705                    else
1706                    {
1707                        if (r_write_byte.read())        r_write_fsm = WRITE_DIR_READ;
1708                        else                                    r_write_fsm = WRITE_DIR_HIT;
1709                    }
1710                }
1711                else    // miss
1712                {
1713                    r_write_fsm = WRITE_MISS_TRT_LOCK;
1714                }
1715
1716#if DEBUG_MEMC_WRITE
1717if( m_debug_write_fsm )
1718{
1719    std::cout << "  <MEMC.WRITE_DIR_LOCK> Check the directory: "
1720              << " address = " << std::hex << r_write_address.read()
1721              << " hit = " << std::dec << entry.valid
1722              << " count = " << entry.count
1723              << " is_cnt = " << entry.is_cnt << std::endl;
1724}
1725#endif
1726            }
1727            break;
1728        }
1729        ////////////////////
1730        case WRITE_DIR_READ:    // read the cache and complete the buffer when be!=0xF
1731        {
1732            // update local buffer
1733            size_t set  = m_y[(vci_addr_t)(r_write_address.read())];
1734            size_t way  = r_write_way.read();
1735            for(size_t i=0 ; i<m_words ; i++)
1736            {
1737                data_t mask = 0;
1738                if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
1739                if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
1740                if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
1741                if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
1742
1743                // complete only if mask is not null (for energy consumption)
1744                if ( r_write_be[i].read() || r_write_is_cnt.read() )
1745                {
1746                    r_write_data[i]  = (r_write_data[i].read() & mask) |
1747                                       (m_cache_data[way][set][i] & ~mask);
1748                }
1749            } // end for
1750
1751            // test if a coherence broadcast is required
1752            if( r_write_is_cnt.read() && r_write_count.read() ) r_write_fsm = WRITE_BC_TRT_LOCK;
1753            else                                                                        r_write_fsm = WRITE_DIR_HIT;
1754
1755#if DEBUG_MEMC_WRITE
1756if( m_debug_write_fsm )
1757{
1758    std::cout << "  <MEMC.WRITE_DIR_READ> Read the cache to complete local buffer" << std::endl;
1759}
1760#endif
1761            break;
1762        }
1763        ///////////////////
1764        case WRITE_DIR_HIT:        // update the cache directory
1765        {
1766            // update directory with Dirty bit
1767            DirectoryEntry entry;
1768            entry.valid          = true;
1769            entry.dirty          = true;
1770            entry.tag            = r_write_tag.read();
1771            entry.is_cnt         = r_write_is_cnt.read();
1772            entry.lock           = r_write_lock.read();
1773            entry.owner.srcid    = r_write_copy.read();
1774#if L1_MULTI_CACHE
1775            entry.owner.cache_id = r_write_copy_cache.read();
1776#endif
1777            entry.owner.inst     = r_write_copy_inst.read();
1778            entry.count          = r_write_count.read();
1779            entry.ptr            = r_write_ptr.read();
1780            size_t set           = m_y[(vci_addr_t)(r_write_address.read())];
1781            size_t way           = r_write_way.read();
1782
1783            // update directory
1784            m_cache_directory.write(set, way, entry);
1785
1786            // owner is true when the  the first registered copy is the writer itself
1787            bool owner = (((r_write_copy.read() == r_write_srcid.read())
1788#if L1_MULTI_CACHE
1789                         and (r_write_copy_cache.read()==r_write_pktid.read())
1790#endif
1791                         ) and not r_write_copy_inst.read());
1792
1793            // no_update is true when there is no need for coherence transaction
1794            bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
1795
1796            // write data in the cache if no coherence transaction
1797            if( no_update )
1798            {
1799                for(size_t i=0 ; i<m_words ; i++)
1800                {
1801                    if  ( r_write_be[i].read() )
1802                    {
1803                        m_cache_data[way][set][i]  = r_write_data[i].read();
1804                       
1805                        if ( m_monitor_ok )
1806                        {
1807                            vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | i<<2;
1808                            char buf[80];
1809                            snprintf(buf, 80, "WRITE_DIR_HIT srcid %d", r_write_srcid.read());
1810                            check_monitor( buf, address, r_write_data[i].read() );
1811                        }
1812                    }
1813                }
1814            }
1815
1816            if ( owner and not no_update )   r_write_count = r_write_count.read() - 1;
1817
1818            if ( no_update )      // Write transaction completed
1819            {
1820                r_write_fsm = WRITE_RSP;
1821            }
1822            else          // coherence update required       
1823            {
1824                if( !r_write_to_init_cmd_multi_req.read() &&
1825                   !r_write_to_init_cmd_brdcast_req.read()  )   r_write_fsm = WRITE_UPT_LOCK;
1826                else                                                                r_write_fsm = WRITE_WAIT;
1827            }
1828
1829#if DEBUG_MEMC_WRITE
1830if( m_debug_write_fsm )
1831{
1832    if ( no_update )
1833    {
1834        std::cout << "  <MEMC.WRITE_DIR_HIT> Write into cache / No coherence transaction"
1835                  << std::endl;
1836    }
1837    else
1838    {
1839        std::cout << "  <MEMC.WRITE_DIR_HIT> Coherence update required:"
1840                  << " is_cnt = " << r_write_is_cnt.read()
1841                  << " nb_copies = " << std::dec << r_write_count.read() << std::endl;
1842        if (owner)
1843        std::cout << "       ... but the first copy is the writer" << std::endl;
1844    }
1845}
1846#endif
1847            break;
1848        }
1849        ////////////////////
1850        case WRITE_UPT_LOCK:    // Try to register the update request in UPT
1851        {
1852            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
1853            {
1854                bool        wok        = false;
1855                size_t      index      = 0;
1856                size_t      srcid      = r_write_srcid.read();
1857                size_t      trdid      = r_write_trdid.read();
1858                size_t      pktid      = r_write_pktid.read();
1859                addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
1860                size_t      nb_copies  = r_write_count.read();
1861                size_t      set        = m_y[(vci_addr_t)(r_write_address.read())];
1862                size_t      way        = r_write_way.read();
1863
1864                wok = m_update_tab.set(true,    // it's an update transaction
1865                                      false,    // it's not a broadcast
1866                                      true,     // it needs a response
1867                                      srcid,
1868                                      trdid,
1869                                      pktid,
1870                                      nline,
1871                                      nb_copies,
1872                                      index);
1873                if ( wok )    // write data in cache
1874                {
1875                    for(size_t i=0 ; i<m_words ; i++)
1876                    {
1877                        if ( r_write_be[i].read() )
1878                        {
1879                            m_cache_data[way][set][i] = r_write_data[i].read();
1880
1881                            if ( m_monitor_ok )
1882                            {
1883                                vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | i<<2;
1884                                char buf[80];
1885                                snprintf(buf, 80, "WRITE_UPT_LOCK srcid %d", srcid);
1886                                check_monitor(buf, address, r_write_data[i].read() );
1887                            }
1888                        }
1889                    }
1890                }
1891
1892#if DEBUG_MEMC_WRITE
1893if( m_debug_write_fsm )
1894{
1895    if ( wok )
1896    {
1897        std::cout << "  <MEMC.WRITE_UPT_LOCK> Register the multicast update in UPT / "
1898                  << " nb_copies = " << r_write_count.read() << std::endl;
1899    }
1900}
1901#endif
1902                r_write_upt_index = index;
1903                //  releases the lock protecting UPT and the DIR if no entry...
1904                if ( wok ) r_write_fsm = WRITE_UPT_HEAP_LOCK;
1905                else       r_write_fsm = WRITE_WAIT;
1906            }
1907            break;
1908        }
1909        /////////////////////////
1910        case WRITE_UPT_HEAP_LOCK:   // get access to heap
1911        {
1912            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE )
1913            {
1914
1915#if DEBUG_MEMC_WRITE
1916if( m_debug_write_fsm )
1917{
1918    std::cout << "  <MEMC.WRITE_UPT_HEAP_LOCK> Get acces to the HEAP" << std::endl;
1919}
1920#endif
1921                r_write_fsm = WRITE_UPT_REQ;
1922            }
1923            break;
1924        }
1925        //////////////////
1926        case WRITE_UPT_REQ:     //  prepare the coherence ransaction for the INIT_CMD FSM
1927                                //  and write the first copy in the FIFO
1928                                //  send the request if only one copy
1929        {
1930            if( !r_write_to_init_cmd_multi_req.read() &&
1931                !r_write_to_init_cmd_brdcast_req.read()  )  // no pending coherence request
1932            {
1933                r_write_to_init_cmd_brdcast_req  = false;
1934                r_write_to_init_cmd_trdid        = r_write_upt_index.read();
1935                r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
1936                r_write_to_init_cmd_index        = r_write_word_index.read();
1937                r_write_to_init_cmd_count        = r_write_word_count.read();
1938
1939                for(size_t i=0; i<m_words ; i++) r_write_to_init_cmd_be[i]=r_write_be[i].read();
1940
1941                size_t min = r_write_word_index.read();
1942                size_t max = r_write_word_index.read() + r_write_word_count.read();
1943                for (size_t i=min ; i<max ; i++) r_write_to_init_cmd_data[i] = r_write_data[i];
1944           
1945                if( (r_write_copy.read() != r_write_srcid.read()) or
1946#if L1_MULTI_CACHE
1947                    (r_write_copy_cache.read() != r_write_pktid.read()) or
1948#endif
1949                    r_write_copy_inst.read() )
1950                {
1951                    // put the first srcid in the fifo
1952                    write_to_init_cmd_fifo_put     = true;
1953                    write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
1954                    write_to_init_cmd_fifo_srcid   = r_write_copy.read();
1955#if L1_MULTI_CACHE
1956                    write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
1957#endif
1958                    if(r_write_count.read() == 1)
1959                    {
1960                        r_write_fsm = WRITE_IDLE;
1961                        r_write_to_init_cmd_multi_req = true;
1962                    }
1963                    else
1964                    {
1965                        r_write_fsm = WRITE_UPT_NEXT;
1966                        r_write_to_dec = false;
1967
1968                    }
1969                }
1970                else
1971                {
1972                    r_write_fsm = WRITE_UPT_NEXT;
1973                    r_write_to_dec = false;
1974                }
1975
1976#if DEBUG_MEMC_WRITE
1977if( m_debug_write_fsm )
1978{
1979    std::cout << "  <MEMC.WRITE_UPT_REQ> Post first request to INIT_CMD FSM"
1980              << " / srcid = " << std::dec << r_write_copy.read()
1981              << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
1982    if ( r_write_count.read() == 1)
1983    std::cout << "         ... and this is the last" << std::endl;
1984}
1985#endif
1986            }
1987            break;
1988        }
1989        ///////////////////
1990        case WRITE_UPT_NEXT:    // continue the multi-update request to INIT_CMD fsm
1991                                // when there is copies in the heap.
1992                                // if one copy in the heap is the writer itself
1993                                // the corresponding SRCID should not be written in the fifo,
1994                                // but the UPT counter must be decremented.
1995                                // As this decrement is done in the WRITE_UPT_DEC state,
1996                                // after the last copy has been found, the decrement request
1997                                // must be  registered in the r_write_to_dec flip-flop.
1998        {
1999            HeapEntry entry = m_heap.read(r_write_ptr.read());
2000         
2001            bool dec_upt_counter;
2002
2003            if( (entry.owner.srcid != r_write_srcid.read()) or
2004#if L1_MULTI_CACHE
2005                (entry.owner.cache_id != r_write_pktid.read()) or
2006#endif
2007                entry.owner.inst)               // put te next srcid in the fifo
2008            {
2009                dec_upt_counter                 = false;
2010                write_to_init_cmd_fifo_put      = true;
2011                write_to_init_cmd_fifo_inst     = entry.owner.inst;
2012                write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
2013#if L1_MULTI_CACHE
2014                write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
2015#endif
2016
2017#if DEBUG_MEMC_WRITE
2018if( m_debug_write_fsm )
2019{
2020    std::cout << "  <MEMC.WRITE_UPT_NEXT> Post another request to INIT_CMD FSM"
2021              << " / heap_index = " << std::dec << r_write_ptr.read()
2022              << " / srcid = " << std::dec << r_write_copy.read()
2023              << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2024    if( entry.next == r_write_ptr.read() )
2025    std::cout << "        ... and this is the last" << std::endl;
2026}
2027#endif
2028            }
2029            else                                // the UPT counter must be decremented
2030            {
2031                dec_upt_counter = true;
2032
2033#if DEBUG_MEMC_WRITE
2034if( m_debug_write_fsm )
2035{
2036    std::cout << "  <MEMC.WRITE_UPT_NEXT> Skip one entry in heap matching the writer"
2037              << " / heap_index = " << std::dec << r_write_ptr.read()
2038              << " / srcid = " << std::dec << r_write_copy.read()
2039              << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2040    if( entry.next == r_write_ptr.read() )
2041    std::cout << "        ... and this is the last" << std::endl;
2042}
2043#endif
2044            }
2045
2046            // register the possible UPT decrement request
2047            r_write_to_dec = dec_upt_counter or r_write_to_dec.read();
2048
2049            if( not m_write_to_init_cmd_inst_fifo.wok() )
2050            {
2051                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_NEXT state" << std::endl
2052                          << "The write_to_init_cmd_fifo should not be full" << std::endl
2053                          << "as the depth should be larger than the max number of copies" << std::endl;
2054                exit(0);
2055            }
2056
2057            r_write_ptr = entry.next;
2058
2059            if( entry.next == r_write_ptr.read() )  // last copy
2060            {
2061                r_write_to_init_cmd_multi_req = true;
2062                if( r_write_to_dec.read() or dec_upt_counter)   r_write_fsm = WRITE_UPT_DEC;
2063                else                                                r_write_fsm = WRITE_IDLE;
2064            }
2065            break;
2066        }
2067        //////////////////
2068        case WRITE_UPT_DEC:     // If the initial writer has a copy, it should not
2069                                // receive an update request, but the counter in the
2070                                // update table must be decremented by the INIT_RSP FSM.
2071        {
2072            if ( !r_write_to_init_rsp_req.read() )
2073            {
2074                r_write_to_init_rsp_req = true;
2075                r_write_to_init_rsp_upt_index = r_write_upt_index.read();
2076                r_write_fsm = WRITE_IDLE;
2077            }
2078            break;
2079        }
2080        ///////////////
2081        case WRITE_RSP:         // Post a request to TGT_RSP FSM to acknowledge the write
2082                            // In order to increase the Write requests throughput,
2083                            // we don't wait to return in the IDLE state to consume
2084                            // a new request in the write FIFO
2085        {
2086            if ( !r_write_to_tgt_rsp_req.read() )
2087            {
2088                // post the request to TGT_RSP_FSM
2089                r_write_to_tgt_rsp_req   = true;
2090                r_write_to_tgt_rsp_srcid = r_write_srcid.read();
2091                r_write_to_tgt_rsp_trdid = r_write_trdid.read();
2092                r_write_to_tgt_rsp_pktid = r_write_pktid.read();
2093
2094                // try to get a new write request from the FIFO
2095                if ( m_cmd_write_addr_fifo.rok() )
2096                {
2097                    m_cpt_write++;
2098                    m_cpt_write_cells++;
2099
2100                    // consume a word in the FIFO & write it in the local buffer
2101                    cmd_write_fifo_get  = true;
2102                    size_t index                = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
2103
2104                    r_write_address             = (addr_t)(m_cmd_write_addr_fifo.read());
2105                    r_write_word_index  = index;
2106                    r_write_word_count  = 1;
2107                    r_write_data[index] = m_cmd_write_data_fifo.read();
2108                    r_write_srcid               = m_cmd_write_srcid_fifo.read();
2109                    r_write_trdid               = m_cmd_write_trdid_fifo.read();
2110                    r_write_pktid               = m_cmd_write_pktid_fifo.read();
2111
2112                    // initialize the be field for all words
2113                    for ( size_t i=0 ; i<m_words ; i++ )
2114                    {
2115                        if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
2116                        else              r_write_be[i] = 0x0;
2117                    }
2118
2119                    if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
2120                        r_write_byte = true;
2121                    else   
2122                        r_write_byte = false;
2123
2124                    if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
2125                    else                               r_write_fsm = WRITE_NEXT;
2126                }
2127                else
2128                {
2129                    r_write_fsm              = WRITE_IDLE;
2130                }
2131
2132#if DEBUG_MEMC_WRITE
2133if( m_debug_write_fsm )
2134{
2135    std::cout << "  <MEMC.WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
2136              << std::dec << r_write_srcid.read() << std::endl;
2137    if ( m_cmd_write_addr_fifo.rok() )
2138    {
2139        std::cout << "                    New Write request: "
2140              << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
2141              << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
2142              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
2143    }
2144}
2145#endif
2146            }
2147            break;
2148        }
2149        /////////////////////////
2150        case WRITE_MISS_TRT_LOCK:       // Miss : check Transaction Table
2151        {
2152            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2153            {
2154
2155#if DEBUG_MEMC_WRITE
2156if( m_debug_write_fsm )
2157{
2158    std::cout << "  <MEMC.WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
2159}
2160#endif
2161                size_t          hit_index = 0;
2162                size_t          wok_index = 0;
2163                vci_addr_t      addr      = (vci_addr_t)r_write_address.read();
2164                bool            hit_read  = m_transaction_tab.hit_read(m_nline[addr], hit_index);
2165                bool            hit_write = m_transaction_tab.hit_write(m_nline[addr]);
2166                bool            wok       = !m_transaction_tab.full(wok_index);
2167
2168                if ( hit_read )         // register the modified data in TRT
2169                {
2170                    r_write_trt_index = hit_index;
2171                    r_write_fsm       = WRITE_MISS_TRT_DATA;
2172                    m_cpt_write_miss++;
2173                }
2174                else if ( wok && !hit_write )   // set a new entry in TRT
2175                {
2176                    r_write_trt_index = wok_index;
2177                    r_write_fsm       = WRITE_MISS_TRT_SET;
2178                    m_cpt_write_miss++;
2179                }
2180                else            // wait an empty entry in TRT
2181                {
2182                    r_write_fsm       = WRITE_WAIT;
2183                    m_cpt_trt_full++;
2184                }
2185            }
2186            break;
2187        }
2188        ////////////////
2189        case WRITE_WAIT:        // release the locks protecting the shared ressources
2190        {
2191
2192#if DEBUG_MEMC_WRITE
2193if( m_debug_write_fsm )
2194{
2195    std::cout << "  <MEMC.WRITE_WAIT> Releases the locks before retry" << std::endl;
2196}
2197#endif
2198            r_write_fsm = WRITE_DIR_LOCK;
2199            break;
2200        }
2201        ////////////////////////
2202        case WRITE_MISS_TRT_SET:        // register a new transaction in TRT (Write Buffer)
2203        { 
2204            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2205            {
2206                std::vector<be_t>       be_vector;
2207                std::vector<data_t> data_vector;
2208                be_vector.clear();
2209                data_vector.clear();
2210                for ( size_t i=0; i<m_words; i++ )
2211                {
2212                    be_vector.push_back(r_write_be[i]);
2213                    data_vector.push_back(r_write_data[i]);
2214                }
2215                m_transaction_tab.set(r_write_trt_index.read(),
2216                                      true,                     // read request to XRAM
2217                                      m_nline[(vci_addr_t)(r_write_address.read())],
2218                                      r_write_srcid.read(),
2219                                      r_write_trdid.read(),
2220                                      r_write_pktid.read(),
2221                                      false,                    // not a processor read
2222                                      0,                        // not a single word
2223                                      0,                        // word index
2224                                      be_vector,
2225                                      data_vector);
2226                r_write_fsm = WRITE_MISS_XRAM_REQ;
2227
2228#if DEBUG_MEMC_WRITE
2229if( m_debug_write_fsm )
2230{
2231    std::cout << "  <MEMC.WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
2232}
2233#endif
2234            }
2235            break;
2236        } 
2237        /////////////////////////
2238        case WRITE_MISS_TRT_DATA:       // update an entry in TRT (used as a Write Buffer)
2239        {
2240            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2241            {
2242                std::vector<be_t> be_vector;
2243                std::vector<data_t> data_vector;
2244                be_vector.clear();
2245                data_vector.clear();
2246                for ( size_t i=0; i<m_words; i++ )
2247                {
2248                    be_vector.push_back(r_write_be[i]);
2249                    data_vector.push_back(r_write_data[i]);
2250                }
2251                m_transaction_tab.write_data_mask(r_write_trt_index.read(),
2252                                                  be_vector,
2253                                                  data_vector);
2254                r_write_fsm = WRITE_RSP;
2255
2256#if DEBUG_MEMC_WRITE
2257if( m_debug_write_fsm )
2258{
2259    std::cout << "  <MEMC.WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2260    m_transaction_tab.print( r_write_trt_index.read() );
2261}
2262#endif
2263            }
2264            break;
2265        }
2266        /////////////////////////
2267        case WRITE_MISS_XRAM_REQ:       // send a GET request to IXR_CMD FSM
2268        { 
2269            if ( !r_write_to_ixr_cmd_req )
2270            {
2271                r_write_to_ixr_cmd_req   = true;
2272                r_write_to_ixr_cmd_write = false;
2273                r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
2274                r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
2275                r_write_fsm              = WRITE_RSP;
2276
2277#if DEBUG_MEMC_WRITE
2278if( m_debug_write_fsm )
2279{
2280    std::cout << "  <MEMC.WRITE_MISS_XRAM_REQ> Post a GET request to the IXR_CMD FSM" << std::endl;
2281}
2282#endif
2283            }
2284            break;
2285        }
2286        ///////////////////////
2287        case WRITE_BC_TRT_LOCK:     // Check TRT not full
2288        {
2289            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2290            {
2291                size_t wok_index = 0;
2292                bool wok = !m_transaction_tab.full( wok_index );
2293                if ( wok )      // set a new entry in TRT
2294                {
2295                    r_write_trt_index = wok_index;
2296                    r_write_fsm       = WRITE_BC_UPT_LOCK;
2297                }
2298                else    // wait an empty entry in TRT
2299                {
2300                    r_write_fsm       = WRITE_WAIT;
2301                }
2302
2303#if DEBUG_MEMC_WRITE
2304if( m_debug_write_fsm )
2305{
2306    std::cout << "  <MEMC.WRITE_BC_TRT_LOCK> Check TRT : wok = "
2307              << wok << " / index = " << wok_index << std::endl;
2308}
2309#endif
2310            }
2311            break;
2312        }
2313        //////////////////////
2314        case WRITE_BC_UPT_LOCK:      // register BC transaction in UPT
2315        {
2316            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
2317            {
2318                bool        wok       = false;
2319                size_t      index     = 0;
2320                size_t      srcid     = r_write_srcid.read();
2321                size_t      trdid     = r_write_trdid.read();
2322                size_t      pktid     = r_write_pktid.read();
2323                addr_t      nline     = m_nline[(vci_addr_t)(r_write_address.read())];
2324                size_t      nb_copies = r_write_count.read();
2325
2326                wok =m_update_tab.set(false,    // it's an inval transaction
2327                                      true,     // it's a broadcast
2328                                      true,     // it needs a response
2329                                      srcid,
2330                                      trdid,
2331                                      pktid,
2332                                      nline,
2333                                      nb_copies,
2334                                      index);
2335
2336#if DEBUG_MEMC_WRITE
2337if( m_debug_write_fsm )
2338{
2339    if ( wok )
2340    {
2341        std::cout << "  <MEMC.WRITE_BC_UPT_LOCK> Register the broadcast inval in UPT / "
2342                  << " nb_copies = " << r_write_count.read() << std::endl;
2343    }
2344}
2345#endif
2346                r_write_upt_index = index;
2347
2348                if ( wok ) r_write_fsm = WRITE_BC_DIR_INVAL;
2349                else       r_write_fsm = WRITE_WAIT;
2350            }
2351            break;
2352        }
2353        ////////////////////////
2354        case WRITE_BC_DIR_INVAL:        // Register a put transaction to XRAM in TRT
2355                                // and invalidate the line in directory
2356        {
2357            if ( (r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE ) ||
2358                 (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE ) ||
2359                 (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE ) )
2360            {
2361                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_BC_DIR_INVAL state" << std::endl;
2362                std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
2363                exit(0);
2364            }
2365
2366            // register a write request to XRAM in TRT
2367            m_transaction_tab.set(r_write_trt_index.read(),
2368                                  false,                // write request to XRAM
2369                                  m_nline[(vci_addr_t)(r_write_address.read())],
2370                                  0,
2371                                  0,
2372                                  0,
2373                                  false,                // not a processor read
2374                                  0,                    // not a single word
2375                                  0,                    // word index
2376                                  std::vector<be_t>(m_words,0),
2377                                  std::vector<data_t>(m_words,0));
2378            // invalidate directory entry
2379            DirectoryEntry entry;
2380            entry.valid         = false;
2381            entry.dirty         = false;
2382            entry.tag           = 0;
2383            entry.is_cnt        = false;
2384            entry.lock          = false;
2385            entry.owner.srcid   = 0;
2386#if L1_MULTI_CACHE
2387            entry.owner.cache_id= 0;
2388#endif
2389            entry.owner.inst    = false;
2390            entry.ptr           = 0;
2391            entry.count         = 0;
2392            size_t set          = m_y[(vci_addr_t)(r_write_address.read())];
2393            size_t way          = r_write_way.read();
2394
2395            m_cache_directory.write(set, way, entry);
2396
2397#if DEBUG_MEMC_WRITE
2398if( m_debug_write_fsm )
2399{
2400    std::cout << "  <MEMC.WRITE_BC_DIR_INVAL> Invalidate the directory entry: @ = "
2401              << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
2402}
2403#endif
2404            r_write_fsm = WRITE_BC_CC_SEND;
2405            break;
2406        }
2407        //////////////////////
2408        case WRITE_BC_CC_SEND:    // Post a coherence broadcast request to INIT_CMD FSM
2409        {
2410            if ( !r_write_to_init_cmd_multi_req.read() && !r_write_to_init_cmd_brdcast_req.read() )
2411            {
2412                r_write_to_init_cmd_multi_req   = false;
2413                r_write_to_init_cmd_brdcast_req = true;
2414                r_write_to_init_cmd_trdid       = r_write_upt_index.read();
2415                r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
2416                r_write_to_init_cmd_index       = 0;
2417                r_write_to_init_cmd_count       = 0;
2418
2419                for(size_t i=0; i<m_words ; i++)
2420                {
2421                    r_write_to_init_cmd_be[i]=0;
2422                    r_write_to_init_cmd_data[i] = 0;
2423                }
2424                r_write_fsm = WRITE_BC_XRAM_REQ;
2425
2426#if DEBUG_MEMC_WRITE
2427if( m_debug_write_fsm )
2428{
2429    std::cout << "  <MEMC.WRITE_BC_CC_SEND> Post a broadcast request to INIT_CMD FSM" << std::endl;
2430}
2431#endif
2432            }
2433            break;
2434        }
2435        ///////////////////////
2436        case WRITE_BC_XRAM_REQ:   // Post a put request to IXR_CMD FSM
2437        {
2438            if ( !r_write_to_ixr_cmd_req )
2439            {
2440                r_write_to_ixr_cmd_req     = true;
2441                r_write_to_ixr_cmd_write   = true;
2442                r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
2443                r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
2444
2445                for(size_t i=0; i<m_words; i++) r_write_to_ixr_cmd_data[i] = r_write_data[i];
2446
2447                r_write_fsm = WRITE_IDLE;
2448
2449#if DEBUG_MEMC_WRITE
2450if( m_debug_write_fsm )
2451{
2452    std::cout << "  <MEMC.WRITE_BC_XRAM_REQ> Post a put request to IXR_CMD FSM" << std::endl;
2453}
2454#endif
2455            }
2456            break;
2457        }
2458    } // end switch r_write_fsm
2459
2460    ///////////////////////////////////////////////////////////////////////
2461    //          IXR_CMD FSM
2462    ///////////////////////////////////////////////////////////////////////
2463    // The IXR_CMD fsm controls the command packets to the XRAM :
2464    // - It sends a single cell VCI read request to the XRAM in case of MISS
2465    // posted by the READ, WRITE or SC FSMs : the TRDID field contains
2466    // the Transaction Tab index.
2467    // The VCI response is a multi-cell packet : the N cells contain
2468    // the N data words.
2469    // - It sends a multi-cell VCI write when the XRAM_RSP FSM, WRITE FSM
2470    // or SC FSM request to save a dirty line to the XRAM.
2471    // The VCI response is a single cell packet.
2472    // This FSM handles requests from the READ, WRITE, SC & XRAM_RSP FSMs
2473    // with a round-robin priority.
2474    ////////////////////////////////////////////////////////////////////////
2475
2476    switch ( r_ixr_cmd_fsm.read() )
2477    {
2478        ////////////////////////
2479        case IXR_CMD_READ_IDLE:
2480        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2481        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2482        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2483        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2484        break;
2485        ////////////////////////
2486        case IXR_CMD_WRITE_IDLE:
2487        if      ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2488        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2489        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2490        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2491        break;
2492        ////////////////////////
2493        case IXR_CMD_SC_IDLE:
2494        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2495        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2496        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2497        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2498        break;
2499        ////////////////////////
2500        case IXR_CMD_XRAM_IDLE:
2501        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2502        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2503        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2504        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2505        break;
2506        /////////////////////////       // send a get request to XRAM
2507        case IXR_CMD_READ_NLINE:
2508        if ( p_vci_ixr.cmdack )
2509        {
2510            r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;         
2511            r_read_to_ixr_cmd_req = false;
2512
2513#if DEBUG_MEMC_IXR_CMD
2514if( m_debug_ixr_cmd_fsm )
2515{
2516    std::cout << "  <MEMC.IXR_CMD_READ_NLINE> Send a get request to xram" << std::endl;
2517}
2518#endif
2519        }
2520        break;
2521        //////////////////////////
2522        case IXR_CMD_WRITE_NLINE:           // send a put or get command to XRAM
2523        if ( p_vci_ixr.cmdack )
2524        {
2525            if( r_write_to_ixr_cmd_write.read())
2526            {
2527                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2528                {
2529                    r_ixr_cmd_cpt = 0;
2530                    r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2531                    r_write_to_ixr_cmd_req = false;
2532                }
2533                else
2534                {
2535                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2536                }
2537
2538#if DEBUG_MEMC_IXR_CMD
2539if( m_debug_ixr_cmd_fsm )
2540{
2541    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a put request to xram" << std::endl;
2542}
2543#endif
2544            }
2545            else
2546            {
2547                r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;             
2548                r_write_to_ixr_cmd_req = false;
2549
2550#if DEBUG_MEMC_IXR_CMD
2551if( m_debug_ixr_cmd_fsm )
2552{
2553    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a get request to xram" << std::endl;
2554}
2555#endif
2556            }
2557        }
2558        break;
2559        //////////////////////
2560        case IXR_CMD_SC_NLINE:      // send a put or get command to XRAM
2561        if ( p_vci_ixr.cmdack )
2562        {
2563            if( r_sc_to_ixr_cmd_write.read())
2564            {
2565                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2566                {
2567                    r_ixr_cmd_cpt = 0;
2568                    r_ixr_cmd_fsm = IXR_CMD_SC_IDLE;
2569                    r_sc_to_ixr_cmd_req = false;
2570                }
2571                else
2572                {
2573                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2574                }
2575
2576#if DEBUG_MEMC_IXR_CMD
2577if( m_debug_ixr_cmd_fsm )
2578{
2579    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a put request to xram" << std::endl;
2580}
2581#endif
2582            }
2583            else
2584            {
2585                r_ixr_cmd_fsm = IXR_CMD_SC_IDLE;               
2586                r_sc_to_ixr_cmd_req = false;
2587
2588#if DEBUG_MEMC_IXR_CMD
2589if( m_debug_ixr_cmd_fsm )
2590{
2591    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a get request to xram" << std::endl;
2592}
2593#endif
2594            }
2595        }
2596        break;
2597        ////////////////////////
2598        case IXR_CMD_XRAM_DATA:     // send a put command to XRAM
2599        if ( p_vci_ixr.cmdack )
2600        {
2601            if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2602            {
2603                r_ixr_cmd_cpt = 0;
2604                r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
2605                r_xram_rsp_to_ixr_cmd_req = false;
2606            }
2607            else
2608            {
2609                r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2610            }
2611
2612#if DEBUG_MEMC_IXR_CMD
2613if( m_debug_ixr_cmd_fsm )
2614{
2615    std::cout << "  <MEMC.IXR_CMD_XRAM_DATA> Send a put request to xram" << std::endl;
2616}
2617#endif
2618        }
2619        break;
2620
2621    } // end switch r_ixr_cmd_fsm
2622
2623    ////////////////////////////////////////////////////////////////////////////
2624    //                IXR_RSP FSM
2625    ////////////////////////////////////////////////////////////////////////////
2626    // The IXR_RSP FSM receives the response packets from the XRAM,
2627    // for both put transaction, and get transaction.
2628    //
2629    // - A response to a put request is a single-cell VCI packet.
2630    // The Transaction Tab index is contained in the RTRDID field.
2631    // The FSM takes the lock protecting the TRT, and the corresponding
2632    // entry is erased.
2633    // 
2634    // - A response to a get request is a multi-cell VCI packet.
2635    // The Transaction Tab index is contained in the RTRDID field.
2636    // The N cells contain the N words of the cache line in the RDATA field.
2637    // The FSM takes the lock protecting the TRT to store the line in the TRT
2638    // (taking into account the write requests already stored in the TRT).
2639    // When the line is completely written, the corresponding rok signal is set.
2640    ///////////////////////////////////////////////////////////////////////////////
2641
2642    switch ( r_ixr_rsp_fsm.read() )
2643    {
2644        //////////////////
2645        case IXR_RSP_IDLE:      // test if it's a get or a put transaction
2646        {
2647            if ( p_vci_ixr.rspval.read() )
2648            {
2649                r_ixr_rsp_cpt   = 0;
2650                r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
2651                if ( p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read()&0x1))  // put transaction
2652                {
2653                    r_ixr_rsp_fsm = IXR_RSP_ACK;
2654
2655#if DEBUG_MEMC_IXR_RSP
2656if( m_debug_ixr_rsp_fsm )
2657{
2658    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
2659}
2660#endif
2661                }
2662                else                                                           // get transaction
2663                {
2664                    r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
2665
2666#if DEBUG_MEMC_IXR_RSP
2667if( m_debug_ixr_rsp_fsm )
2668{
2669    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
2670}
2671#endif
2672                }
2673            }
2674            break; 
2675        }
2676        ////////////////////////
2677        case IXR_RSP_ACK:        // Aknowledge the VCI response
2678        {
2679            if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
2680
2681#if DEBUG_MEMC_IXR_RSP
2682if( m_debug_ixr_rsp_fsm )
2683{
2684    std::cout << "  <MEMC.IXR_RSP_ACK>" << std::endl;
2685}
2686#endif
2687            break;
2688        }
2689        ////////////////////////
2690        case IXR_RSP_TRT_ERASE:         // erase the entry in the TRT
2691        {
2692            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP )
2693            {
2694                m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
2695                r_ixr_rsp_fsm = IXR_RSP_IDLE;
2696
2697#if DEBUG_MEMC_IXR_RSP
2698if( m_debug_ixr_rsp_fsm )
2699{
2700    std::cout << "  <MEMC.IXR_RSP_TRT_ERASE> Erase TRT entry "
2701              << r_ixr_rsp_trt_index.read() << std::endl;
2702}
2703#endif
2704            }
2705            break;
2706        }
2707        ///////////////////////
2708        case IXR_RSP_TRT_READ:          // write data in the TRT
2709        {
2710            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval )
2711            {
2712                size_t index    = r_ixr_rsp_trt_index.read();
2713                bool   eop      = p_vci_ixr.reop.read();
2714                data_t data     = p_vci_ixr.rdata.read();
2715                bool   error    = ((p_vci_ixr.rerror.read() & 0x1) == 1);
2716                assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) || p_vci_ixr.rerror.read())
2717                    and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
2718                m_transaction_tab.write_rsp(index,
2719                                            r_ixr_rsp_cpt.read(),
2720                                            data,
2721                                            error);
2722                r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
2723                if ( eop )
2724                {
2725                    r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
2726                    r_ixr_rsp_fsm = IXR_RSP_IDLE;
2727                }
2728
2729#if DEBUG_MEMC_IXR_RSP
2730if( m_debug_ixr_rsp_fsm )
2731{
2732    std::cout << "  <MEMC.IXR_RSP_TRT_READ> Writing a word in TRT : "
2733              << " index = " << std::dec << index
2734              << " / word = " << r_ixr_rsp_cpt.read()
2735              << " / data = " << std::hex << data << std::endl;
2736}
2737#endif
2738            }
2739            break;
2740        }
2741    } // end swich r_ixr_rsp_fsm
2742
2743    ////////////////////////////////////////////////////////////////////////////
2744    //                XRAM_RSP FSM
2745    ////////////////////////////////////////////////////////////////////////////
2746    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
2747    // The cache line has been written in the TRT by the IXR_CMD_FSM.
2748    // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
2749    // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
2750    // as the number of entries in the TRT, that are handled with
2751    // a round-robin priority...
2752    //
2753    // When a response is available, the corresponding TRT entry
2754    // must be copied in a local buffer to be written in the cache.
2755    // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
2756    // It selects a cache slot and writes the line in the cache.
2757    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
2758    // FSM to return the cache line to the registered processor.
2759    // If there is no empty slot, a victim line is evicted, and
2760    // invalidate requests are sent to the L1 caches containing copies.
2761    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
2762    // FSM to save the victim line to the XRAM, and register the write transaction
2763    // in the TRT (using the entry previously used by the read transaction).
2764    ///////////////////////////////////////////////////////////////////////////////
2765
2766    switch ( r_xram_rsp_fsm.read() )
2767    {
2768        ///////////////////
2769        case XRAM_RSP_IDLE:     // scan the XRAM responses to get the TRT index (round robin)
2770        {
2771            size_t ptr   = r_xram_rsp_trt_index.read();
2772            size_t lines = m_transaction_tab_lines;
2773            for( size_t i=0 ; i<lines ; i++)
2774            {
2775                size_t index=(i+ptr+1)%lines;
2776                if ( r_ixr_rsp_to_xram_rsp_rok[index] )
2777                {
2778                    r_xram_rsp_trt_index                = index;
2779                    r_ixr_rsp_to_xram_rsp_rok[index]    = false;
2780                    r_xram_rsp_fsm                      = XRAM_RSP_DIR_LOCK;
2781
2782#if DEBUG_MEMC_XRAM_RSP
2783if( m_debug_xram_rsp_fsm )
2784{       
2785    std::cout << "  <MEMC.XRAM_RSP_IDLE> Available cache line in TRT:"
2786              << " index = " << std::dec << index << std::endl;
2787}
2788#endif
2789                    break;
2790                }
2791            }
2792            break; 
2793        }
2794        ///////////////////////
2795        case XRAM_RSP_DIR_LOCK:         // Takes the lock on the directory
2796        {
2797            if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP )
2798            {
2799                r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
2800
2801#if DEBUG_MEMC_XRAM_RSP
2802if( m_debug_xram_rsp_fsm )
2803{       
2804    std::cout << "  <MEMC.XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
2805}
2806#endif
2807            }
2808            break;
2809        }
2810        ///////////////////////
2811        case XRAM_RSP_TRT_COPY:         // Takes the lock on TRT
2812                                    // Copy the TRT entry in a local buffer
2813                                    // and select a victim cache line
2814        {
2815            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) )
2816            {
2817                // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
2818                size_t  index = r_xram_rsp_trt_index.read();
2819                TransactionTabEntry    trt_entry(m_transaction_tab.read(index)); 
2820                r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
2821
2822                // selects & extracts a victim line from cache
2823                size_t way = 0;
2824                size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
2825                DirectoryEntry victim(m_cache_directory.select(set, way));
2826
2827                bool inval = (victim.count && victim.valid) ;
2828
2829                // copy the victim line in a local buffer
2830                for (size_t i=0 ; i<m_words ; i++)
2831                    r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
2832                r_xram_rsp_victim_copy      = victim.owner.srcid;
2833#if L1_MULTI_CACHE
2834                r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
2835#endif
2836                r_xram_rsp_victim_copy_inst = victim.owner.inst;
2837                r_xram_rsp_victim_count     = victim.count;
2838                r_xram_rsp_victim_ptr       = victim.ptr;
2839                r_xram_rsp_victim_way       = way;
2840                r_xram_rsp_victim_set       = set;
2841                r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
2842                r_xram_rsp_victim_is_cnt    = victim.is_cnt;
2843                r_xram_rsp_victim_inval     = inval ;
2844                r_xram_rsp_victim_dirty     = victim.dirty;
2845
2846                if(!trt_entry.rerror)   r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
2847                else                            r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;     
2848
2849#if DEBUG_MEMC_XRAM_RSP
2850if( m_debug_xram_rsp_fsm )
2851{
2852    std::cout << "  <MEMC.XRAM_RSP_TRT_COPY> Select a slot: "
2853              << " way = " << std::dec << way
2854              << " / set = " << set
2855              << " / inval_required = " << inval << std::endl;
2856}
2857#endif
2858            }
2859            break;
2860        }
2861        /////////////////////////
2862        case XRAM_RSP_INVAL_LOCK:       // check a possible pending inval
2863        {
2864            if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP )
2865            {
2866                size_t index;
2867                if (m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index))
2868                {
2869                    r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2870
2871#if DEBUG_MEMC_XRAM_RSP
2872if( m_debug_xram_rsp_fsm )
2873{
2874    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
2875              << " but an invalidation is already registered at this address" << std::endl;
2876    m_update_tab.print();
2877}
2878#endif
2879
2880                }
2881                    else if (m_update_tab.is_full() && r_xram_rsp_victim_inval.read())
2882                {
2883                        r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2884
2885#if DEBUG_MEMC_XRAM_RSP
2886if( m_debug_xram_rsp_fsm )
2887{
2888    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
2889              << " but the table is full" << std::endl;
2890    m_update_tab.print();
2891}
2892#endif
2893                    }
2894                else
2895                {
2896                    r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
2897
2898#if DEBUG_MEMC_XRAM_RSP
2899if( m_debug_xram_rsp_fsm )
2900{
2901    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT" << std::endl;
2902}
2903#endif
2904                }
2905            }
2906            break;
2907        }
2908        /////////////////////////
2909        case XRAM_RSP_INVAL_WAIT:       // returns to DIR_LOCK to retry
2910        {
2911            r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
2912            break;
2913        }
2914        ///////////////////////
2915        case XRAM_RSP_DIR_UPDT:         // updates the cache (both data & directory)
2916                                        // and possibly set an inval request in UPT
2917        {
2918            // signals generation
2919            bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read;
2920            bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read;
2921            // update data
2922            size_t set   = r_xram_rsp_victim_set.read();
2923            size_t way   = r_xram_rsp_victim_way.read();
2924            for(size_t i=0; i<m_words ; i++)
2925            {
2926                m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
2927
2928                if ( m_monitor_ok )
2929                {
2930                    vci_addr_t address = r_xram_rsp_trt_buf.nline<<6 | i<<2;
2931                    check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[i]);
2932                }
2933            }
2934            // compute dirty
2935            bool dirty = false;
2936            for(size_t i=0; i<m_words;i++) dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
2937            // update directory
2938            DirectoryEntry entry;
2939            entry.valid   = true;
2940            entry.is_cnt  = false;
2941            entry.lock    = false;
2942            entry.dirty   = dirty;
2943            entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
2944            entry.ptr     = 0;
2945            if(cached_read)
2946            {
2947                entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
2948#if L1_MULTI_CACHE
2949                entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
2950#endif
2951                entry.owner.inst    = inst_read;
2952                entry.count         = 1;
2953            }
2954            else
2955            {
2956                entry.owner.srcid    = 0;
2957#if L1_MULTI_CACHE
2958                entry.owner.cache_id = 0;
2959#endif
2960                entry.owner.inst     = 0;
2961                entry.count          = 0;
2962            }
2963            m_cache_directory.write(set, way, entry);
2964
2965            if (r_xram_rsp_victim_inval.read())
2966            {
2967                bool   brdcast          = r_xram_rsp_victim_is_cnt.read();
2968                size_t index            = 0;
2969                size_t count_copies     = r_xram_rsp_victim_count.read();
2970
2971                bool   wok = m_update_tab.set(  false,          // it's an inval transaction
2972                                                brdcast,        // set brdcast bit
2973                                                false,          // it does not need a response
2974                                                0,              // srcid
2975                                                0,              // trdid
2976                                                0,              // pktid
2977                                                r_xram_rsp_victim_nline.read(),
2978                                                count_copies,
2979                                                index);
2980                r_xram_rsp_upt_index = index;
2981
2982                if (!wok)
2983                {
2984                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
2985                    std::cout << "an update_tab entry was free but write is unsuccessful" << std::endl;
2986                    exit(0);
2987                }
2988            }
2989
2990#if DEBUG_MEMC_XRAM_RSP
2991if( m_debug_xram_rsp_fsm )
2992{
2993    std::cout << "  <MEMC.XRAM_RSP_DIR_UPDT> Directory update: "
2994              << " way = " << std::dec << way
2995              << " / set = " << set
2996              << " / count = " << entry.count
2997              << " / is_cnt = " << entry.is_cnt << std::endl;
2998    if (r_xram_rsp_victim_inval.read())
2999    std::cout << "                           Invalidation request for victim line "
3000              << std::hex << r_xram_rsp_victim_nline.read()
3001              << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
3002}
3003#endif
3004
3005            // If the victim is not dirty, we don't need another XRAM  put transaction,
3006            // and we canwe erase the TRT entry
3007            if (!r_xram_rsp_victim_dirty.read())  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
3008
3009            // Next state
3010            if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
3011            else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3012            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
3013            else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3014            break;
3015        }
3016        ////////////////////////
3017        case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (write to XRAM) if the victim is dirty
3018        {
3019            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP )
3020            {
3021                m_transaction_tab.set( r_xram_rsp_trt_index.read(),
3022                                       false,                           // write to XRAM
3023                                       r_xram_rsp_victim_nline.read(),  // line index
3024                                       0,
3025                                       0,
3026                                       0,
3027                                       false,
3028                                       0,
3029                                       0,
3030                                       std::vector<be_t>(m_words,0),
3031                                       std::vector<data_t>(m_words,0) );
3032
3033#if DEBUG_MEMC_XRAM_RSP
3034if( m_debug_xram_rsp_fsm )
3035{
3036    std::cout << "  <MEMC.XRAM_RSP_TRT_DIRTY> Set TRT entry for the put transaction:"
3037              << " dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3038}
3039#endif
3040                if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3041                else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
3042                else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3043            }
3044            break;
3045        }
3046        //////////////////////
3047        case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
3048        {
3049            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
3050            {
3051                r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
3052                r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
3053                r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
3054                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3055                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3056                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3057                r_xram_rsp_to_tgt_rsp_rerror = false;
3058                r_xram_rsp_to_tgt_rsp_req    = true;
3059
3060                if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
3061                else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3062                else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3063
3064
3065#if DEBUG_MEMC_XRAM_RSP
3066if( m_debug_xram_rsp_fsm )
3067{
3068    std::cout << "  <MEMC.XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:"
3069              << " rsrcid = " << std::dec << r_xram_rsp_trt_buf.srcid
3070              << " / address = " << std::hex << r_xram_rsp_trt_buf.nline*m_words*4
3071              << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
3072}
3073#endif
3074            }
3075            break;
3076        }
3077        ////////////////////
3078        case XRAM_RSP_INVAL:    // send invalidate request to INIT_CMD FSM
3079        {
3080            if(   !r_xram_rsp_to_init_cmd_multi_req.read() &&
3081                  !r_xram_rsp_to_init_cmd_brdcast_req.read() )
3082            {         
3083                bool multi_req = !r_xram_rsp_victim_is_cnt.read();
3084                bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
3085                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3086
3087                r_xram_rsp_to_init_cmd_multi_req    = last_multi_req;
3088                r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
3089                r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
3090                r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
3091                xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
3092                xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
3093#if L1_MULTI_CACHE
3094                xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
3095#endif
3096                xram_rsp_to_init_cmd_fifo_put       = multi_req;
3097                r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
3098
3099                if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3100                else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3101                else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3102
3103#if DEBUG_MEMC_XRAM_RSP
3104if( m_debug_xram_rsp_fsm )
3105{
3106    std::cout << "  <MEMC.XRAM_RSP_INVAL> Send an inval request to INIT_CMD FSM:"
3107              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3108}
3109#endif
3110          }
3111          break;
3112        }
3113        //////////////////////////
3114        case XRAM_RSP_WRITE_DIRTY:      // send a write request to IXR_CMD FSM
3115        {
3116            if ( !r_xram_rsp_to_ixr_cmd_req.read() )
3117            {
3118                r_xram_rsp_to_ixr_cmd_req = true;
3119                r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
3120                r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
3121                for(size_t i=0; i<m_words ; i++) r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
3122                m_cpt_write_dirty++;
3123
3124                bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
3125                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3126                if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3127                else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
3128
3129#if DEBUG_MEMC_XRAM_RSP
3130if( m_debug_xram_rsp_fsm )
3131{
3132    std::cout << "  <MEMC.XRAM_RSP_WRITE_DIRTY> Send the put request to IXR_CMD FSM:"
3133              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3134}
3135#endif
3136            }
3137            break;
3138        }
3139        /////////////////////////
3140        case XRAM_RSP_HEAP_ERASE:       // erase the list of copies and sent invalidations
3141        {
3142            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP )
3143            {
3144                HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
3145
3146                xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
3147#if L1_MULTI_CACHE
3148                xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
3149#endif
3150                xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
3151                xram_rsp_to_init_cmd_fifo_put   = true;
3152                if( m_xram_rsp_to_init_cmd_inst_fifo.wok() )
3153                {
3154                    r_xram_rsp_next_ptr = entry.next;
3155                    if( entry.next == r_xram_rsp_next_ptr.read() ) // last copy
3156                    {
3157                        r_xram_rsp_to_init_cmd_multi_req = true;
3158                        r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
3159                    }
3160                    else
3161                    {
3162                        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3163                    }
3164                }
3165                else
3166                {
3167                    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3168                }
3169
3170#if DEBUG_MEMC_XRAM_RSP
3171if( m_debug_xram_rsp_fsm )
3172{
3173    std::cout << "  <MEMC.XRAM_RSP_HEAP_ERASE> Erase the list of copies:"
3174              << " srcid = " << std::dec << entry.owner.srcid
3175              << " / inst = " << std::dec << entry.owner.inst << std::endl;
3176}
3177#endif
3178            }
3179            break;
3180        }
3181        /////////////////////////
3182        case XRAM_RSP_HEAP_LAST:        // last member of the list
3183        {
3184            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP )
3185            {
3186                std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
3187                std::cout << "bad HEAP allocation" << std::endl;
3188                exit(0);
3189            }
3190            size_t free_pointer = m_heap.next_free_ptr();
3191
3192            HeapEntry last_entry;
3193            last_entry.owner.srcid    = 0;
3194#if L1_MULTI_CACHE
3195            last_entry.owner.cache_id = 0;
3196#endif
3197            last_entry.owner.inst     = false;
3198            if(m_heap.is_full())
3199            {
3200                last_entry.next     = r_xram_rsp_next_ptr.read();
3201                m_heap.unset_full();
3202            }
3203            else
3204            {
3205                last_entry.next     = free_pointer;
3206            }
3207
3208            m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
3209            m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
3210
3211            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3212
3213#if DEBUG_MEMC_XRAM_RSP
3214if( m_debug_xram_rsp_fsm )
3215{
3216    std::cout << "  <MEMC.XRAM_RSP_HEAP_LAST> Heap housekeeping" << std::endl;
3217}
3218#endif
3219            break;
3220        }
3221        // ///////////////////////
3222        case XRAM_RSP_ERROR_ERASE:      // erase TRT entry in case of error
3223        {
3224            m_transaction_tab.erase(r_xram_rsp_trt_index.read());
3225
3226            // Next state
3227            if ( r_xram_rsp_trt_buf.proc_read  ) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3228            else                                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
3229
3230#if DEBUG_MEMC_XRAM_RSP
3231if( m_debug_xram_rsp_fsm )
3232{
3233    std::cout << "  <MEMC.XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << std::endl;
3234}
3235#endif
3236            break;
3237        }
3238        ////////////////////////
3239        case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3240        {
3241            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
3242            {
3243                r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3244                r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3245                r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3246                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3247                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3248                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3249                r_xram_rsp_to_tgt_rsp_rerror = true;
3250                r_xram_rsp_to_tgt_rsp_req    = true;
3251
3252                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3253
3254#if DEBUG_MEMC_XRAM_RSP
3255if( m_debug_xram_rsp_fsm )
3256{
3257    std::cout << "  <MEMC.XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3258              << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
3259}
3260#endif
3261            }
3262            break;
3263        }
3264    } // end swich r_xram_rsp_fsm
3265
3266    ////////////////////////////////////////////////////////////////////////////////////
3267    //          CLEANUP FSM
3268    ////////////////////////////////////////////////////////////////////////////////////
3269    // The CLEANUP FSM handles the cleanup request from L1 caches.
3270    // It accesses the cache directory and the heap to update the list of copies.
3271    ////////////////////////////////////////////////////////////////////////////////////
3272
3273
3274    switch ( r_cleanup_fsm.read() )
3275    {
3276        //////////////////
3277        case CLEANUP_IDLE:
3278        {
3279            if ( p_vci_tgt_cleanup.cmdval.read() )
3280            {
3281                if (p_vci_tgt_cleanup.srcid.read() >= m_initiators )
3282                {
3283                    std::cout << "VCI_MEM_CACHE ERROR " << name()
3284                              << " CLEANUP_IDLE state" << std::endl;
3285                    std::cout << "illegal srcid for  cleanup request" << std::endl;
3286                    exit(0);
3287                }
3288
3289                bool reached = false;
3290                for ( size_t index = 0 ; index < m_ncseg && !reached ; index++ )
3291                {
3292                    if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) )
3293                        reached = true;
3294                }
3295                // only write request to a mapped address that are not broadcast are handled
3296                if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
3297                     ((p_vci_tgt_cleanup.address.read() & 0x3) == 0) && reached)
3298                {
3299                    addr_t line =(((addr_t) p_vci_tgt_cleanup.be.read() << (vci_param::B*8))) |
3300                                 (((addr_t) p_vci_tgt_cleanup.wdata.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      case ALLOC_DIR_READ:
5257        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
5258              (r_read_fsm.read() != READ_TRT_LOCK)  &&
5259              (r_read_fsm.read() != READ_HEAP_LOCK))
5260            ||
5261            ( (r_read_fsm.read()        == READ_HEAP_LOCK) &&
5262              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_READ) )
5263            ||
5264            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
5265              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  )
5266        {
5267          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5268          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5269          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5270          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5271        }
5272        break;
5273
5274        /////////////////////
5275      case ALLOC_DIR_WRITE:
5276        if ( ((r_write_fsm.read() != WRITE_DIR_LOCK) &&
5277              (r_write_fsm.read() != WRITE_MISS_TRT_LOCK) &&
5278              (r_write_fsm.read() != WRITE_DIR_READ) &&
5279              (r_write_fsm.read() != WRITE_DIR_HIT) &&
5280              (r_write_fsm.read() != WRITE_BC_TRT_LOCK) &&
5281              (r_write_fsm.read() != WRITE_BC_UPT_LOCK) &&
5282              (r_write_fsm.read() != WRITE_UPT_LOCK) &&
5283              (r_write_fsm.read() != WRITE_UPT_HEAP_LOCK))
5284            ||
5285            ( (r_write_fsm.read()       == WRITE_UPT_HEAP_LOCK) &&
5286              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_WRITE) )
5287            ||
5288            ( (r_write_fsm.read()     == WRITE_MISS_TRT_LOCK) &&
5289              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
5290        {
5291          if        (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5292          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5293          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5294          else if   (r_read_fsm.read() == READ_DIR_LOCK)                r_alloc_dir_fsm = ALLOC_DIR_READ;
5295        }
5296        break;
5297
5298        ////////////////////
5299        case ALLOC_DIR_SC:
5300        if ( ((r_sc_fsm.read() != SC_DIR_LOCK)       &&
5301              (r_sc_fsm.read() != SC_DIR_HIT_READ )  &&
5302              (r_sc_fsm.read() != SC_DIR_HIT_WRITE ) &&
5303//              (r_sc_fsm.read() != SC_MISS_TRT_LOCK )    &&
5304              (r_sc_fsm.read() != SC_BC_TRT_LOCK)       &&
5305              (r_sc_fsm.read() != SC_BC_UPT_LOCK)     &&
5306              (r_sc_fsm.read() != SC_UPT_LOCK)       &&
5307              (r_sc_fsm.read() != SC_UPT_HEAP_LOCK))
5308            ||
5309            ( (r_sc_fsm.read()       == SC_UPT_HEAP_LOCK) &&
5310              (r_alloc_heap_fsm.read() == ALLOC_HEAP_SC) )
5311            ||
5312            ( (r_sc_fsm.read()      == SC_MISS_TRT_LOCK ) &&
5313              (r_alloc_trt_fsm.read() == ALLOC_TRT_SC)    ) )
5314        {
5315          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5316          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5317          else if (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
5318          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5319        }
5320        break;
5321
5322        ///////////////////////
5323        case ALLOC_DIR_CLEANUP:
5324        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
5325            (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
5326        {
5327          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5328          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
5329          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5330          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5331        }
5332        break;
5333        ////////////////////////
5334        case ALLOC_DIR_XRAM_RSP:
5335        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
5336            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   &&
5337            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
5338        {
5339          if      (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
5340          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5341          else if (r_sc_fsm.read() == SC_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_SC;
5342          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5343        }
5344        break;
5345
5346    } // end switch alloc_dir_fsm
5347
5348    ////////////////////////////////////////////////////////////////////////////////////
5349    //          ALLOC_TRT FSM
5350    ////////////////////////////////////////////////////////////////////////////////////
5351    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
5352    // with a round robin priority between 4 user FSMs :
5353    // The cyclic priority is READ > WRITE > SC > XRAM_RSP
5354    // The ressource is always allocated.
5355    ///////////////////////////////////////////////////////////////////////////////////
5356
5357    switch (r_alloc_trt_fsm)
5358    {
5359
5360      ////////////////////
5361      case ALLOC_TRT_READ:
5362        if ( r_read_fsm.read() != READ_TRT_LOCK )
5363        {
5364          if      ((r_write_fsm.read() == WRITE_MISS_TRT_LOCK)   ||
5365                   (r_write_fsm.read() == WRITE_BC_TRT_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5366          else if ((r_sc_fsm.read() == SC_MISS_TRT_LOCK) ||
5367                   (r_sc_fsm.read() == SC_BC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5368          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5369          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5370                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5371        }
5372        break;
5373        /////////////////////
5374      case ALLOC_TRT_WRITE:
5375        if ( (r_write_fsm.read() != WRITE_MISS_TRT_LOCK) &&
5376             (r_write_fsm.read() != WRITE_BC_TRT_LOCK) &&
5377             (r_write_fsm.read() != WRITE_BC_UPT_LOCK))
5378        {
5379          if      ((r_sc_fsm.read() == SC_MISS_TRT_LOCK) ||
5380                   (r_sc_fsm.read() == SC_BC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5381          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5382          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5383                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5384          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5385        }
5386        break;
5387        ////////////////////
5388      case ALLOC_TRT_SC:
5389        if ( (r_sc_fsm.read() != SC_MISS_TRT_LOCK) &&
5390             (r_sc_fsm.read() != SC_BC_TRT_LOCK) &&
5391             (r_sc_fsm.read() != SC_BC_UPT_LOCK))
5392        {
5393          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5394          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5395                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5396          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5397          else if ((r_write_fsm.read() == WRITE_MISS_TRT_LOCK)     ||
5398                   (r_write_fsm.read() == WRITE_BC_TRT_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5399        }
5400        break;
5401        ////////////////////////
5402      case ALLOC_TRT_XRAM_RSP:
5403        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
5404            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
5405            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
5406          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5407                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5408          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5409          else if ((r_write_fsm.read() == WRITE_MISS_TRT_LOCK)    ||
5410                   (r_write_fsm.read() == WRITE_BC_TRT_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5411          else if ((r_sc_fsm.read() == SC_MISS_TRT_LOCK) ||
5412                   (r_sc_fsm.read() == SC_BC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5413        }
5414        break;
5415        ////////////////////////
5416      case ALLOC_TRT_IXR_RSP:
5417        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
5418            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
5419          if      (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5420          else if ((r_write_fsm.read() == WRITE_MISS_TRT_LOCK)   ||
5421                   (r_write_fsm.read() == WRITE_BC_TRT_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5422          else if ((r_sc_fsm.read() == SC_MISS_TRT_LOCK) ||
5423                   (r_sc_fsm.read() == SC_BC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5424          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5425        }
5426        break;
5427
5428    } // end switch alloc_trt_fsm
5429
5430    ////////////////////////////////////////////////////////////////////////////////////
5431    //          ALLOC_HEAP FSM
5432    ////////////////////////////////////////////////////////////////////////////////////
5433    // The ALLOC_HEAP FSM allocates the access to the heap
5434    // with a round robin priority between 5 user FSMs :
5435    // The cyclic ordering is READ > WRITE > SC > CLEANUP > XRAM_RSP
5436    // The ressource is always allocated.
5437    /////////////////////////////////////////////////////////////////////////////////////
5438
5439    switch ( r_alloc_heap_fsm.read() )
5440    {
5441        ////////////////////
5442        case ALLOC_HEAP_READ:
5443        if (  (r_read_fsm.read() != READ_HEAP_LOCK) &&
5444              (r_read_fsm.read() != READ_HEAP_ERASE)     )
5445        {
5446          if      (r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5447          else if (r_sc_fsm.read() == SC_UPT_HEAP_LOCK)              r_alloc_heap_fsm = ALLOC_HEAP_SC;
5448          else if (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5449          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE) r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5450        }
5451        break;
5452
5453        /////////////////////
5454        case ALLOC_HEAP_WRITE:
5455        if (  (r_write_fsm.read() != WRITE_UPT_HEAP_LOCK)   &&
5456              (r_write_fsm.read() != WRITE_UPT_REQ)     &&
5457              (r_write_fsm.read() != WRITE_UPT_NEXT)  )
5458        {
5459          if      (r_sc_fsm.read() == SC_UPT_HEAP_LOCK)          r_alloc_heap_fsm = ALLOC_HEAP_SC;
5460          else if (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5461          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE) r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5462          else if (r_read_fsm.read() == READ_HEAP_LOCK)              r_alloc_heap_fsm = ALLOC_HEAP_READ;
5463        }
5464        break;
5465
5466        ////////////////////
5467        case ALLOC_HEAP_SC:
5468        if (  (r_sc_fsm.read() != SC_UPT_HEAP_LOCK)  &&
5469              (r_sc_fsm.read() != SC_UPT_REQ )    &&
5470              (r_sc_fsm.read() != SC_UPT_NEXT)  )
5471        {
5472          if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5473          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE) r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5474          else if (r_read_fsm.read() == READ_HEAP_LOCK)          r_alloc_heap_fsm = ALLOC_HEAP_READ;
5475          else if (r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5476        }
5477        break;
5478
5479        ///////////////////////
5480        case ALLOC_HEAP_CLEANUP:
5481        if ( (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
5482            (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH)&&
5483            (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN)    )
5484        {
5485          if      (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE) r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5486          else if (r_read_fsm.read() == READ_HEAP_LOCK)          r_alloc_heap_fsm = ALLOC_HEAP_READ;
5487          else if (r_write_fsm.read() == WRITE_UPT_HEAP_LOCK)    r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5488          else if (r_sc_fsm.read() == SC_UPT_HEAP_LOCK)          r_alloc_heap_fsm = ALLOC_HEAP_SC;
5489        }
5490        break;
5491        ////////////////////////
5492        case ALLOC_HEAP_XRAM_RSP:
5493        if ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE )
5494        {
5495          if        (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
5496          else if   (r_write_fsm.read() == WRITE_UPT_HEAP_LOCK) r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5497          else if   (r_sc_fsm.read() == SC_UPT_HEAP_LOCK)       r_alloc_heap_fsm = ALLOC_HEAP_SC;
5498          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK) r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5499        }
5500        break;
5501
5502    } // end switch alloc_heap_fsm
5503
5504
5505    ////////////////////////////////////////////////////////////////////////////////////
5506    //          TGT_CMD to READ FIFO
5507    ////////////////////////////////////////////////////////////////////////////////////
5508
5509    if ( cmd_read_fifo_put ) {
5510      if ( cmd_read_fifo_get ) {
5511        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5512        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
5513        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5514        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5515        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5516      } else {
5517        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5518        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
5519        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5520        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5521        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5522      }
5523    } else {
5524      if ( cmd_read_fifo_get ) {
5525        m_cmd_read_addr_fifo.simple_get();
5526        m_cmd_read_length_fifo.simple_get();
5527        m_cmd_read_srcid_fifo.simple_get();
5528        m_cmd_read_trdid_fifo.simple_get();
5529        m_cmd_read_pktid_fifo.simple_get();
5530      }
5531    }
5532    /////////////////////////////////////////////////////////////////////
5533    //          TGT_CMD to WRITE FIFO
5534    /////////////////////////////////////////////////////////////////////
5535
5536    if ( cmd_write_fifo_put ) {
5537      if ( cmd_write_fifo_get ) {
5538        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5539        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
5540        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5541        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5542        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5543        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
5544        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
5545      } else {
5546        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5547        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
5548        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5549        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5550        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5551        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
5552        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
5553      }
5554    } else {
5555      if ( cmd_write_fifo_get ) {
5556        m_cmd_write_addr_fifo.simple_get();
5557        m_cmd_write_eop_fifo.simple_get();
5558        m_cmd_write_srcid_fifo.simple_get();
5559        m_cmd_write_trdid_fifo.simple_get();
5560        m_cmd_write_pktid_fifo.simple_get();
5561        m_cmd_write_data_fifo.simple_get();
5562        m_cmd_write_be_fifo.simple_get();
5563      }
5564    }
5565    ////////////////////////////////////////////////////////////////////////////////////
5566    //          TGT_CMD to SC FIFO
5567    ////////////////////////////////////////////////////////////////////////////////////
5568
5569    if ( cmd_sc_fifo_put ) {
5570      if ( cmd_sc_fifo_get ) {
5571        m_cmd_sc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5572        m_cmd_sc_eop_fifo.put_and_get(p_vci_tgt.eop.read());
5573        m_cmd_sc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5574        m_cmd_sc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5575        m_cmd_sc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5576        m_cmd_sc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
5577      } else {
5578        m_cmd_sc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5579        m_cmd_sc_eop_fifo.simple_put(p_vci_tgt.eop.read());
5580        m_cmd_sc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5581        m_cmd_sc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5582        m_cmd_sc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5583        m_cmd_sc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
5584      }
5585    } else {
5586      if ( cmd_sc_fifo_get ) {
5587        m_cmd_sc_addr_fifo.simple_get();
5588        m_cmd_sc_eop_fifo.simple_get();
5589        m_cmd_sc_srcid_fifo.simple_get();
5590        m_cmd_sc_trdid_fifo.simple_get();
5591        m_cmd_sc_pktid_fifo.simple_get();
5592        m_cmd_sc_wdata_fifo.simple_get();
5593      }
5594    }
5595    ////////////////////////////////////////////////////////////////////////////////////
5596    //          WRITE to INIT_CMD FIFO
5597    ////////////////////////////////////////////////////////////////////////////////////
5598
5599    if ( write_to_init_cmd_fifo_put ) {
5600      if ( write_to_init_cmd_fifo_get ) {
5601        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
5602        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
5603#if L1_MULTI_CACHE
5604        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
5605#endif
5606      } else {
5607        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
5608        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
5609#if L1_MULTI_CACHE
5610        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
5611#endif
5612      }
5613    } else {
5614      if ( write_to_init_cmd_fifo_get ) {
5615        m_write_to_init_cmd_inst_fifo.simple_get();
5616        m_write_to_init_cmd_srcid_fifo.simple_get();
5617#if L1_MULTI_CACHE
5618        m_write_to_init_cmd_cache_id_fifo.simple_get();
5619#endif
5620      }
5621    }
5622    ////////////////////////////////////////////////////////////////////////////////////
5623    //          XRAM_RSP to INIT_CMD FIFO
5624    ////////////////////////////////////////////////////////////////////////////////////
5625
5626    if ( xram_rsp_to_init_cmd_fifo_put ) {
5627      if ( xram_rsp_to_init_cmd_fifo_get ) {
5628        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
5629        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
5630#if L1_MULTI_CACHE
5631        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
5632#endif
5633      } else {
5634        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
5635        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
5636#if L1_MULTI_CACHE
5637        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
5638#endif
5639      }
5640    } else {
5641      if ( xram_rsp_to_init_cmd_fifo_get ) {
5642        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
5643        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
5644#if L1_MULTI_CACHE
5645        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
5646#endif
5647      }
5648    }
5649    ////////////////////////////////////////////////////////////////////////////////////
5650    //          SC to INIT_CMD FIFO
5651    ////////////////////////////////////////////////////////////////////////////////////
5652
5653    if ( sc_to_init_cmd_fifo_put ) {
5654      if ( sc_to_init_cmd_fifo_get ) {
5655        m_sc_to_init_cmd_inst_fifo.put_and_get(sc_to_init_cmd_fifo_inst);
5656        m_sc_to_init_cmd_srcid_fifo.put_and_get(sc_to_init_cmd_fifo_srcid);
5657#if L1_MULTI_CACHE
5658        m_sc_to_init_cmd_cache_id_fifo.put_and_get(sc_to_init_cmd_fifo_cache_id);
5659#endif
5660      } else {
5661          m_sc_to_init_cmd_inst_fifo.simple_put(sc_to_init_cmd_fifo_inst);
5662          m_sc_to_init_cmd_srcid_fifo.simple_put(sc_to_init_cmd_fifo_srcid);
5663#if L1_MULTI_CACHE
5664          m_sc_to_init_cmd_cache_id_fifo.simple_put(sc_to_init_cmd_fifo_cache_id);
5665#endif
5666      }
5667    } else {
5668        if ( sc_to_init_cmd_fifo_get ) {
5669            m_sc_to_init_cmd_inst_fifo.simple_get();
5670            m_sc_to_init_cmd_srcid_fifo.simple_get();
5671#if L1_MULTI_CACHE
5672            m_sc_to_init_cmd_cache_id_fifo.simple_get();
5673#endif
5674      }
5675    }
5676
5677    m_cpt_cycles++;
5678
5679} // end transition()
5680
5681/////////////////////////////
5682tmpl(void)::genMoore()
5683/////////////////////////////
5684{
5685    ////////////////////////////////////////////////////////////
5686    // Command signals on the p_vci_ixr port
5687    ////////////////////////////////////////////////////////////
5688
5689    p_vci_ixr.be      = 0xF;
5690    p_vci_ixr.pktid   = 0;
5691    p_vci_ixr.srcid   = m_srcid_ixr;
5692    p_vci_ixr.cons    = false;
5693    p_vci_ixr.wrap    = false;
5694    p_vci_ixr.contig  = true;
5695    p_vci_ixr.clen    = 0;
5696    p_vci_ixr.cfixed  = false;
5697
5698    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
5699      p_vci_ixr.cmd     = vci_param::CMD_READ;
5700      p_vci_ixr.cmdval  = true;
5701      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
5702      p_vci_ixr.plen    = m_words*4;
5703      p_vci_ixr.wdata   = 0x00000000;
5704      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
5705      p_vci_ixr.eop     = true;
5706    }
5707    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_SC_NLINE ) {
5708      if(r_sc_to_ixr_cmd_write.read()){
5709        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5710        p_vci_ixr.cmdval  = true;
5711        p_vci_ixr.address = (addr_t)((r_sc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5712        p_vci_ixr.plen    = m_words*4;
5713        p_vci_ixr.wdata   = r_sc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5714        p_vci_ixr.trdid   = r_sc_to_ixr_cmd_trdid.read();
5715        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5716      } else {
5717        p_vci_ixr.cmd     = vci_param::CMD_READ;
5718        p_vci_ixr.cmdval  = true;
5719        p_vci_ixr.address = (addr_t)(r_sc_to_ixr_cmd_nline.read()*m_words*4);
5720        p_vci_ixr.plen    = m_words*4;
5721        p_vci_ixr.wdata   = 0x00000000;
5722        p_vci_ixr.trdid   = r_sc_to_ixr_cmd_trdid.read();
5723        p_vci_ixr.eop     = true;
5724      }
5725    }
5726    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
5727      if(r_write_to_ixr_cmd_write.read()){
5728        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5729        p_vci_ixr.cmdval  = true;
5730        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5731        p_vci_ixr.plen    = m_words*4;
5732        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5733        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
5734        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5735      } else {
5736        p_vci_ixr.cmd     = vci_param::CMD_READ;
5737        p_vci_ixr.cmdval  = true;
5738        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
5739        p_vci_ixr.plen    = m_words*4;
5740        p_vci_ixr.wdata   = 0x00000000;
5741        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
5742        p_vci_ixr.eop     = true;
5743      }
5744    }
5745    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
5746      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5747      p_vci_ixr.cmdval  = true;
5748      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5749      p_vci_ixr.plen    = m_words*4;
5750      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5751      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
5752      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5753    } else {
5754      p_vci_ixr.cmdval  = false;
5755      p_vci_ixr.address = 0;
5756      p_vci_ixr.plen    = 0;
5757      p_vci_ixr.wdata   = 0;
5758      p_vci_ixr.trdid   = 0;
5759      p_vci_ixr.eop     = false;
5760    }
5761
5762    ////////////////////////////////////////////////////
5763    // Response signals on the p_vci_ixr port
5764    ////////////////////////////////////////////////////
5765
5766    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
5767          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
5768        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
5769    else                                        p_vci_ixr.rspack = false;
5770
5771    ////////////////////////////////////////////////////
5772    // Command signals on the p_vci_tgt port
5773    ////////////////////////////////////////////////////
5774
5775    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
5776      case TGT_CMD_IDLE:
5777        p_vci_tgt.cmdack  = false;
5778        break;
5779      case TGT_CMD_READ:
5780        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
5781        break;
5782      case TGT_CMD_WRITE:
5783        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
5784        break;
5785      case TGT_CMD_ATOMIC:
5786        p_vci_tgt.cmdack  = m_cmd_sc_addr_fifo.wok();
5787        break;
5788      default:
5789        p_vci_tgt.cmdack = false;
5790        break;
5791    }
5792
5793    ////////////////////////////////////////////////////
5794    // Response signals on the p_vci_tgt port
5795    ////////////////////////////////////////////////////
5796    switch ( r_tgt_rsp_fsm.read() ) {
5797
5798      case TGT_RSP_READ_IDLE:
5799      case TGT_RSP_WRITE_IDLE:
5800      case TGT_RSP_SC_IDLE:
5801      case TGT_RSP_XRAM_IDLE:
5802      case TGT_RSP_INIT_IDLE:
5803      case TGT_RSP_CLEANUP_IDLE:
5804        p_vci_tgt.rspval  = false;
5805        p_vci_tgt.rsrcid  = 0;
5806        p_vci_tgt.rdata   = 0;
5807        p_vci_tgt.rpktid  = 0;
5808        p_vci_tgt.rtrdid  = 0;
5809        p_vci_tgt.rerror  = 0;
5810        p_vci_tgt.reop    = false;     
5811        break;
5812      case TGT_RSP_READ:
5813        p_vci_tgt.rspval   = true;
5814        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5815        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
5816        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
5817        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
5818        p_vci_tgt.rerror   = 0;
5819        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
5820        break;
5821      case TGT_RSP_WRITE:
5822        p_vci_tgt.rspval   = true;
5823        p_vci_tgt.rdata    = 0;
5824        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
5825        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
5826        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
5827        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
5828        p_vci_tgt.reop     = true;
5829        break;
5830      case TGT_RSP_CLEANUP:
5831        p_vci_tgt.rspval   = true;
5832        p_vci_tgt.rdata    = 0;
5833        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
5834        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
5835        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
5836        p_vci_tgt.rerror   = 0; // Can be a SC rsp
5837        p_vci_tgt.reop     = true;
5838        break;
5839      case TGT_RSP_SC:
5840        p_vci_tgt.rspval   = true;
5841        p_vci_tgt.rdata    = r_sc_to_tgt_rsp_data.read();
5842        p_vci_tgt.rsrcid   = r_sc_to_tgt_rsp_srcid.read();
5843        p_vci_tgt.rtrdid   = r_sc_to_tgt_rsp_trdid.read();
5844        p_vci_tgt.rpktid   = r_sc_to_tgt_rsp_pktid.read();
5845        p_vci_tgt.rerror   = 0;
5846        p_vci_tgt.reop     = true;
5847        break;
5848      case TGT_RSP_XRAM:
5849        p_vci_tgt.rspval   = true;
5850        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5851        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
5852        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
5853        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
5854        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
5855        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
5856                                == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
5857                              || r_xram_rsp_to_tgt_rsp_rerror.read());
5858        break;
5859      case TGT_RSP_INIT:
5860        p_vci_tgt.rspval   = true;
5861        p_vci_tgt.rdata    = 0;
5862        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
5863        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
5864        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
5865        p_vci_tgt.rerror   = 0; // Can be a SC rsp
5866        p_vci_tgt.reop     = true;     
5867        break;
5868    } // end switch r_tgt_rsp_fsm
5869
5870    ///////////////////////////////////////////////////
5871    // Command signals on the p_vci_ini port
5872    ///////////////////////////////////////////////////
5873
5874    p_vci_ini.cmd     = vci_param::CMD_WRITE;
5875    p_vci_ini.srcid   = m_srcid_ini;
5876    p_vci_ini.cons    = true;
5877    p_vci_ini.wrap    = false;
5878    p_vci_ini.contig  = false;
5879    p_vci_ini.clen    = 0;
5880    p_vci_ini.cfixed  = false;
5881
5882    vci_addr_t vci_ini_address = 0;
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        vci_ini_address = (vci_addr_t)
5900            m_xram_rsp_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
5901
5902        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
5903        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
5904          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
5905              p_vci_ini.address = (addr_t) (vci_ini_address+4);
5906          } else {
5907              p_vci_ini.address = (addr_t) (vci_ini_address);
5908          }
5909        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
5910        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
5911        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
5912        p_vci_ini.plen    = 4;
5913        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
5914        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
5915        p_vci_ini.eop     = true;
5916        break;
5917      }
5918      case INIT_CMD_XRAM_BRDCAST:
5919        p_vci_ini.cmdval  = true;
5920        p_vci_ini.address = m_broadcast_address;
5921        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
5922        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
5923        p_vci_ini.plen    = 4;
5924        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
5925        p_vci_ini.pktid   = 0;
5926        p_vci_ini.eop     = true;
5927        break;
5928
5929      case INIT_CMD_WRITE_BRDCAST:
5930        p_vci_ini.cmdval  = true;
5931        p_vci_ini.address = m_broadcast_address;
5932        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
5933        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
5934        p_vci_ini.plen    = 4 ;
5935        p_vci_ini.eop     = true;
5936        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5937        p_vci_ini.pktid   = 0;
5938        break;
5939      case INIT_CMD_UPDT_NLINE:
5940        vci_ini_address = (vci_addr_t)
5941            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
5942
5943        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
5944        if(m_write_to_init_cmd_inst_fifo.rok()){
5945          if(m_write_to_init_cmd_inst_fifo.read()) {
5946            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
5947          } else {
5948            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
5949          }
5950        } else {
5951          p_vci_ini.address = 0;
5952        }
5953        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
5954        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
5955        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5956        p_vci_ini.eop     = false;
5957        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5958        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5959        break;
5960      case INIT_CMD_UPDT_INDEX:
5961        vci_ini_address = (vci_addr_t)
5962            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
5963
5964        p_vci_ini.cmdval  = true;
5965        if(m_write_to_init_cmd_inst_fifo.read()) {
5966          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
5967        } else {
5968          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
5969        }
5970        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
5971        p_vci_ini.be      = 0xF;
5972        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5973        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5974        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5975        p_vci_ini.eop     = false;
5976        break;
5977      case INIT_CMD_UPDT_DATA:
5978        vci_ini_address = (vci_addr_t)
5979            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
5980
5981        p_vci_ini.cmdval  = true;
5982        if(m_write_to_init_cmd_inst_fifo.read()) {
5983          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
5984        } else {
5985          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
5986        }
5987        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
5988          r_write_to_init_cmd_index.read()].read();
5989        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
5990            r_write_to_init_cmd_index.read()].read()  ;
5991        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5992        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5993        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5994        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
5995        break;
5996
5997      case INIT_CMD_SC_BRDCAST:
5998        p_vci_ini.cmdval  = true;
5999        p_vci_ini.address = m_broadcast_address;
6000        p_vci_ini.wdata   = (addr_t)r_sc_to_init_cmd_nline.read();
6001        p_vci_ini.be      = ((r_sc_to_init_cmd_nline.read() >> 32) & 0x3);
6002        p_vci_ini.plen    = 4 ;
6003        p_vci_ini.eop     = true;
6004        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
6005        p_vci_ini.pktid   = 0;
6006        break;
6007      case INIT_CMD_SC_UPDT_NLINE:
6008        vci_ini_address = (vci_addr_t)
6009            m_sc_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6010
6011        p_vci_ini.cmdval  = m_sc_to_init_cmd_inst_fifo.rok();
6012        if(m_sc_to_init_cmd_inst_fifo.rok()){
6013          if( m_sc_to_init_cmd_inst_fifo.read() ) {
6014            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6015          } else {
6016            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6017          }
6018        } else {
6019          p_vci_ini.address = 0;
6020        }
6021        p_vci_ini.wdata   = (uint32_t)r_sc_to_init_cmd_nline.read();
6022        p_vci_ini.be      = ((r_sc_to_init_cmd_nline.read() >> 32 ) & 0x3);
6023        if(r_sc_to_init_cmd_is_long.read()){
6024            p_vci_ini.plen    = 4 * 4;
6025        } else {
6026            p_vci_ini.plen    = 4 * 3;
6027        }
6028        p_vci_ini.eop     = false;
6029        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
6030        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
6031        break;
6032      case INIT_CMD_SC_UPDT_INDEX:
6033        vci_ini_address = (vci_addr_t)
6034            m_sc_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6035
6036        p_vci_ini.cmdval  = true;
6037        if( m_sc_to_init_cmd_inst_fifo.read() ) {
6038          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6039        } else {
6040          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6041        }
6042        p_vci_ini.wdata   = r_sc_to_init_cmd_index.read();
6043        p_vci_ini.be      = 0xF;
6044        if(r_sc_to_init_cmd_is_long.read()){
6045            p_vci_ini.plen    = 4 * 4;
6046        } else {
6047            p_vci_ini.plen    = 4 * 3;
6048        }
6049        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
6050        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
6051        p_vci_ini.eop     = false;
6052        break;
6053      case INIT_CMD_SC_UPDT_DATA:
6054        vci_ini_address = (vci_addr_t)
6055            m_sc_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6056
6057        p_vci_ini.cmdval  = true;
6058        if( m_sc_to_init_cmd_inst_fifo.read() ) {
6059          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6060        } else {
6061          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6062        }
6063        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata.read();
6064        p_vci_ini.be      = 0xF;
6065        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
6066        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
6067        if(r_sc_to_init_cmd_is_long.read()){
6068            p_vci_ini.plen    = 4 * 4;
6069            p_vci_ini.eop     = false;
6070        } else {
6071            p_vci_ini.plen    = 4 * 3;
6072            p_vci_ini.eop     = true;
6073        }
6074        break;
6075      case INIT_CMD_SC_UPDT_DATA_HIGH:
6076        vci_ini_address = (vci_addr_t)
6077            m_sc_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6078
6079        p_vci_ini.cmdval  = true;
6080        if( m_sc_to_init_cmd_inst_fifo.read() ) {
6081          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6082        } else {
6083          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6084        }
6085        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata_high.read();
6086        p_vci_ini.be      = 0xF;
6087        p_vci_ini.plen    = 4 * 4;
6088        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
6089        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
6090        p_vci_ini.eop     = true;
6091        break;
6092
6093    } // end switch r_init_cmd_fsm
6094
6095    //////////////////////////////////////////////////////
6096    // Response signals on the p_vci_ini port
6097    //////////////////////////////////////////////////////
6098
6099    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
6100    else                                          p_vci_ini.rspack  = false;
6101
6102    //////////////////////////////////////////////////////
6103    // Response signals on the p_vci_tgt_cleanup port
6104    //////////////////////////////////////////////////////
6105    p_vci_tgt_cleanup.rspval = false;
6106    p_vci_tgt_cleanup.rsrcid = 0;
6107    p_vci_tgt_cleanup.rdata  = 0;
6108    p_vci_tgt_cleanup.rpktid = 0;
6109    p_vci_tgt_cleanup.rtrdid = 0;
6110    p_vci_tgt_cleanup.rerror = 0;
6111    p_vci_tgt_cleanup.reop   = false;
6112    p_vci_tgt_cleanup.cmdack = false ;
6113
6114    switch(r_cleanup_fsm.read()){
6115      case CLEANUP_IDLE:
6116        {
6117          p_vci_tgt_cleanup.cmdack = true ;
6118          break;
6119        }
6120      case CLEANUP_RSP:
6121        {
6122          p_vci_tgt_cleanup.rspval = true;
6123          p_vci_tgt_cleanup.rdata  = 0;
6124          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
6125          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
6126          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
6127          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
6128          p_vci_tgt_cleanup.reop   = 1;
6129          break;
6130        }
6131
6132    }
6133
6134} // end genMoore()
6135
6136}} // end name space
6137
6138// Local Variables:
6139// tab-width: 2
6140// c-basic-offset: 2
6141// c-file-offsets:((innamespace . 0)(inline-open . 0))
6142// indent-tabs-mode: nil
6143// End:
6144
6145// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
6146
Note: See TracBrowser for help on using the repository browser.