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

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

Fixing a bub in SC_FSM: The write was done too sytematically in the SC_DIR_HIT_WRITE
state: The actual cache update is done now in three states: DIR_HIT_WRITE (if no CC transactions)
in SC_UPT_LOCK in case of CC_UPDATE, and in SC_BC_UPT_LOCK states in case of SC_BROADCAST.
Because we want to be sur that the SC will be completed (no retry in WAITstate) before updating the cache

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