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

Last change on this file since 215 was 215, checked in by alain, 12 years ago

Introducing start_monitor() & stop_monitor() methods in vci_mem_cache_v4

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