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

Last change on this file since 224 was 224, checked in by bouyer, 13 years ago

Normalize trace message: address, data and byte enable in hex, everything else
(or almost) in dec.

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