source: trunk/platforms/almos-tsarv3-platforms/common/vci_mem_cache_v3/caba/source/src/vci_mem_cache_v3.cpp @ 259

Last change on this file since 259 was 259, checked in by almaless, 12 years ago

Introduce ALMOS used platforms for TSAR.
See the package's README file for more information.

File size: 191.1 KB
Line 
1/* -*- c++ -*-
2 * File         : vci_mem_cache_v3.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#include "../include/vci_mem_cache_v3.h"
30
31//#define TDEBUG // Transaction tab debug
32//#define IDEBUG // Update tab debug
33//#define DDEBUG // Directory debug
34//#define DEBUG_VCI_MEM_CACHE 1
35
36#define MEMC_INI_ID  8196
37
38#define TRACE_MSG(...)                                                  \
39    do{                                                                 \
40        if((m_total_cycles > m_debug_start) || (current_waiting >= m_wait_threshold)) \
41            __VA_ARGS__;                                                \
42    }while(0)
43
44#define DUMP_UPDATE_TABLE                            \
45    do{                                         \
46        if((m_total_cycles > m_debug_start) || (current_waiting >= m_wait_threshold)) \
47            m_update_tab.print();                                       \
48    }while(0)
49
50
51#define DUMP_TRANSACTION_TABLE                            \
52    do{                                         \
53        if((m_total_cycles > m_debug_start) || (current_waiting >= m_wait_threshold)) { \
54            for(size_t i = 0 ; i < m_transaction_tab.size() ; i++)      \
55                m_transaction_tab.print(i, m_log);                      \
56        }                                                               \
57    }while(0)
58
59
60#define DUMP_ENTRY(x)  \
61    do {                                                                \
62        if((m_total_cycles > m_debug_start) || (current_waiting >= m_wait_threshold)) \
63            entry.print();                                              \
64    }while(0)
65
66namespace soclib { namespace caba {
67
68  const char *tgt_cmd_fsm_str[] = {
69    "TGT_CMD_IDLE",
70    "TGT_CMD_READ",
71    "TGT_CMD_READ_EOP",
72    "TGT_CMD_WRITE",
73    "TGT_CMD_ATOMIC",
74  };
75  const char *tgt_rsp_fsm_str[] = {
76    "TGT_RSP_READ_IDLE",
77    "TGT_RSP_WRITE_IDLE",
78    "TGT_RSP_LLSC_IDLE",
79    "TGT_RSP_XRAM_IDLE",
80    "TGT_RSP_INIT_IDLE",
81    "TGT_RSP_CLEANUP_IDLE",
82    "TGT_RSP_READ",
83    "TGT_RSP_WRITE",
84    "TGT_RSP_LLSC",
85    "TGT_RSP_XRAM",
86    "TGT_RSP_INIT",
87    "TGT_RSP_CLEANUP",
88  };
89  const char *init_cmd_fsm_str[] = {
90    "INIT_CMD_INVAL_IDLE",
91    "INIT_CMD_INVAL_NLINE",
92    "INIT_CMD_XRAM_BRDCAST",
93    "INIT_CMD_UPDT_IDLE",
94    "INIT_CMD_WRITE_BRDCAST",
95    "INIT_CMD_UPDT_NLINE",
96    "INIT_CMD_UPDT_INDEX",
97    "INIT_CMD_UPDT_DATA",
98    "INIT_CMD_SC_UPDT_IDLE",
99    "INIT_CMD_SC_BRDCAST",
100    "INIT_CMD_SC_UPDT_NLINE",
101    "INIT_CMD_SC_UPDT_INDEX",
102    "INIT_CMD_SC_UPDT_DATA",
103  };
104  const char *init_rsp_fsm_str[] = {
105    "INIT_RSP_IDLE",
106    "INIT_RSP_UPT_LOCK",
107    "INIT_RSP_UPT_CLEAR",
108    "INIT_RSP_END",
109  };
110  const char *read_fsm_str[] = {
111    "READ_IDLE",
112    "READ_DIR_LOCK",
113    "READ_DIR_HIT",
114    "READ_HEAP_LOCK",
115    "READ_HEAP_WRITE",
116    "READ_HEAP_ERASE",
117    "READ_HEAP_LAST",
118    "READ_RSP",
119    "READ_TRT_LOCK",
120    "READ_TRT_SET",
121    "READ_XRAM_REQ",
122  };
123  const char *write_fsm_str[] = {
124    "WRITE_IDLE",
125    "WRITE_NEXT",
126    "WRITE_DIR_LOCK",
127    "WRITE_DIR_HIT_READ",
128    "WRITE_DIR_HIT",
129    "WRITE_DIR_HIT_RSP",
130    "WRITE_UPT_LOCK",
131    "WRITE_HEAP_LOCK",
132    "WRITE_UPT_REQ",
133    "WRITE_UPDATE",
134    "WRITE_UPT_DEC",
135    "WRITE_RSP",
136    "WRITE_TRT_LOCK",
137    "WRITE_TRT_DATA",
138    "WRITE_TRT_SET",
139    "WRITE_WAIT",
140    "WRITE_XRAM_REQ",
141    "WRITE_TRT_WRITE_LOCK",
142    "WRITE_INVAL_LOCK",
143    "WRITE_DIR_INVAL",
144    "WRITE_INVAL",
145    "WRITE_XRAM_SEND",
146    "WRITE_HEAP_ERASE",
147    "WRITE_HEAP_LAST",
148  };
149  const char *ixr_rsp_fsm_str[] = {
150    "IXR_RSP_IDLE",
151    "IXR_RSP_ACK",
152    "IXR_RSP_TRT_ERASE",
153    "IXR_RSP_TRT_READ",
154  };
155  const char *xram_rsp_fsm_str[] = {
156    "XRAM_RSP_IDLE",
157    "XRAM_RSP_TRT_COPY",
158    "XRAM_RSP_TRT_DIRTY",
159    "XRAM_RSP_DIR_LOCK",
160    "XRAM_RSP_DIR_UPDT",
161    "XRAM_RSP_DIR_RSP",
162    "XRAM_RSP_INVAL_LOCK",
163    "XRAM_RSP_INVAL_WAIT",
164    "XRAM_RSP_INVAL",
165    "XRAM_RSP_WRITE_DIRTY",
166    "XRAM_RSP_HEAP_ERASE",
167    "XRAM_RSP_HEAP_LAST",
168  };
169  const char *ixr_cmd_fsm_str[] = {
170    "IXR_CMD_READ_IDLE",
171    "IXR_CMD_WRITE_IDLE",
172    "IXR_CMD_LLSC_IDLE",
173    "IXR_CMD_XRAM_IDLE",
174    "IXR_CMD_READ_NLINE",
175    "IXR_CMD_WRITE_NLINE",
176    "IXR_CMD_LLSC_NLINE",
177    "IXR_CMD_XRAM_DATA",
178  };
179  const char *llsc_fsm_str[] = {
180    "LLSC_IDLE",
181    "LL_DIR_LOCK",
182    "LL_DIR_HIT",
183    "LL_RSP",
184    "SC_DIR_LOCK",
185    "SC_DIR_HIT",
186    "SC_UPT_LOCK",
187    "SC_WAIT",
188    "SC_HEAP_LOCK",
189    "SC_UPT_REQ",
190    "SC_UPDATE",
191    "SC_TRT_LOCK",
192    "SC_INVAL_LOCK",
193    "SC_DIR_INVAL",
194    "SC_INVAL",
195    "SC_XRAM_SEND",
196    "SC_HEAP_ERASE",
197    "SC_HEAP_LAST",
198    "SC_RSP_FALSE",
199    "SC_RSP_TRUE",
200    "LLSC_TRT_LOCK",
201    "LLSC_TRT_SET",
202    "LLSC_XRAM_REQ",
203  };
204  const char *cleanup_fsm_str[] = {
205    "CLEANUP_IDLE",
206    "CLEANUP_DIR_LOCK",
207    "CLEANUP_DIR_WRITE",
208    "CLEANUP_HEAP_LOCK",
209    "CLEANUP_HEAP_SEARCH",
210    "CLEANUP_HEAP_CLEAN",
211    "CLEANUP_HEAP_FREE",
212    "CLEANUP_UPT_LOCK",
213    "CLEANUP_UPT_WRITE",
214    "CLEANUP_WRITE_RSP",
215    "CLEANUP_RSP",
216  };
217  const char *alloc_dir_fsm_str[] = {
218    "ALLOC_DIR_READ",
219    "ALLOC_DIR_WRITE",
220    "ALLOC_DIR_LLSC",
221    "ALLOC_DIR_CLEANUP",
222    "ALLOC_DIR_XRAM_RSP",
223  };
224  const char *alloc_trt_fsm_str[] = {
225    "ALLOC_TRT_READ",
226    "ALLOC_TRT_WRITE",
227    "ALLOC_TRT_LLSC",
228    "ALLOC_TRT_XRAM_RSP",
229    "ALLOC_TRT_IXR_RSP",
230  };
231  const char *alloc_upt_fsm_str[] = {
232    "ALLOC_UPT_WRITE",
233    "ALLOC_UPT_XRAM_RSP",
234    "ALLOC_UPT_INIT_RSP",
235    "ALLOC_UPT_CLEANUP",
236  };
237  const char *alloc_heap_fsm_str[] = {
238    "ALLOC_HEAP_READ",
239    "ALLOC_HEAP_WRITE",
240    "ALLOC_HEAP_LLSC",
241    "ALLOC_HEAP_CLEANUP",
242    "ALLOC_HEAP_XRAM_RSP",
243  };
244
245
246#define tmpl(x) template<typename vci_param> x VciMemCacheV3<vci_param>
247
248  using soclib::common::uint32_log2;
249
250  ////////////////////////////////
251  //    Constructor
252  ////////////////////////////////
253
254  tmpl(/**/)::VciMemCacheV3( 
255      sc_module_name name,
256      const soclib::common::MappingTable &mtp,
257      const soclib::common::MappingTable &mtc,
258      const soclib::common::MappingTable &mtx,
259      const soclib::common::IntTab &vci_ixr_index,
260      const soclib::common::IntTab &vci_ini_index,
261      const soclib::common::IntTab &vci_tgt_index,
262      const soclib::common::IntTab &vci_tgt_index_cleanup,
263      size_t nways,
264      size_t nsets,
265      size_t nwords,
266      size_t heap_size)
267
268    : soclib::caba::BaseModule(name),
269
270    p_clk("clk"),
271    p_resetn("resetn"),
272    p_vci_tgt("vci_tgt"),
273    p_vci_tgt_cleanup("vci_tgt_cleanup"),
274    p_vci_ini("vci_ini"),
275    p_vci_ixr("vci_ixr"),
276
277    m_initiators( 1 << vci_param::S ),
278    m_heap_size( heap_size ),
279    m_ways( nways ),
280    m_sets( nsets ),
281    m_words( nwords ),
282    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
283    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
284    m_seglist(mtp.getSegmentList(vci_tgt_index)),
285    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
286    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
287    m_atomic_tab( m_initiators ),
288    m_transaction_tab( TRANSACTION_TAB_LINES, nwords ),
289    m_update_tab( UPDATE_TAB_LINES ),
290    m_cache_directory( nways, nsets, nwords, vci_param::N ),
291    m_heap_directory( m_heap_size ),
292
293#define L2 soclib::common::uint32_log2
294    m_x( L2(m_words), 2),
295    m_y( L2(m_sets), L2(m_words) + 2),
296    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
297    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
298#undef L2
299
300    //  FIFOs
301    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
302    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
303    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
304    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
305    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
306
307    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
308    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
309    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
310    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
311    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
312    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
313    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
314
315    m_cmd_llsc_addr_fifo("m_cmd_llsc_addr_fifo",4),
316    m_cmd_llsc_sc_fifo("m_cmd_llsc_sc_fifo",4),
317    m_cmd_llsc_srcid_fifo("m_cmd_llsc_srcid_fifo",4),
318    m_cmd_llsc_trdid_fifo("m_cmd_llsc_trdid_fifo",4),
319    m_cmd_llsc_pktid_fifo("m_cmd_llsc_pktid_fifo",4),
320    m_cmd_llsc_wdata_fifo("m_cmd_llsc_wdata_fifo",4),
321
322    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
323   
324    nseg(0),   
325    ncseg(0),   
326
327    r_read_fsm("r_read_fsm"),
328    r_write_fsm("r_write_fsm"),
329    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
330    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
331    r_init_rsp_fsm("r_init_rsp_fsm"),
332    r_cleanup_fsm("r_cleanup_fsm"),
333    r_llsc_fsm("r_llsc_fsm"),
334    m_llsc_to_init_cmd_inst_fifo("m_llsc_to_init_cmd_inst_fifo",8),
335    m_llsc_to_init_cmd_srcid_fifo("m_llsc_to_init_cmd_srcid_fifo",8),
336    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
337    r_xram_rsp_fsm("r_xram_rsp_fsm"),
338    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
339    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
340    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
341    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
342    r_init_cmd_fsm("r_init_cmd_fsm"),
343    r_alloc_dir_fsm("r_alloc_dir_fsm"),
344    r_alloc_trt_fsm("r_alloc_trt_fsm"),
345    r_alloc_upt_fsm("r_alloc_upt_fsm")
346    {
347      assert(IS_POW_OF_2(nsets));
348      assert(IS_POW_OF_2(nwords));
349      assert(IS_POW_OF_2(nways));
350      assert(nsets);
351      assert(nwords);
352      assert(nways);
353      assert(nsets <= 1024);
354      assert(nwords <= 32);
355      assert(nways <= 32);
356
357      // Set the broadcast address with Xmin,Xmax,Ymin,Ymax set to maximum
358      broadcast_addr = 0x3 | (0x7C1F << (vci_param::N-20));
359
360      // Get the segments associated to the MemCache
361      std::list<soclib::common::Segment>::iterator seg;
362
363      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
364        nseg++;
365      }
366      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
367        ncseg++;
368      }
369
370      m_seg = new soclib::common::Segment*[nseg];
371      size_t i = 0;
372      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) { 
373        m_seg[i] = &(*seg);
374        i++;
375      }
376      m_cseg = new soclib::common::Segment*[ncseg];
377      i = 0;
378      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) { 
379          m_cseg[i] = &(*seg);
380          i++;
381      }
382
383      // Memory cache allocation & initialisation
384      m_cache_data = new data_t**[nways];
385      for ( size_t i=0 ; i<nways ; ++i ) {
386        m_cache_data[i] = new data_t*[nsets];
387      }
388      for ( size_t i=0; i<nways; ++i ) {
389        for ( size_t j=0; j<nsets; ++j ) {
390          m_cache_data[i][j] = new data_t[nwords];
391          for ( size_t k=0; k<nwords; k++){
392            m_cache_data[i][j][k]=0;
393          }     
394        }
395      }
396
397      // Allocation for IXR_RSP FSM
398      r_ixr_rsp_to_xram_rsp_rok     = new sc_signal<bool>[TRANSACTION_TAB_LINES];
399
400      // Allocation for XRAM_RSP FSM
401      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
402      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
403      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
404
405      // Allocation for READ FSM
406      r_read_data                               = new sc_signal<data_t>[nwords];
407      r_read_to_tgt_rsp_data            = new sc_signal<data_t>[nwords];
408
409      // Allocation for WRITE FSM
410      r_write_data                              = new sc_signal<data_t>[nwords];
411      r_write_be                                = new sc_signal<be_t>[nwords];
412      r_write_to_init_cmd_data          = new sc_signal<data_t>[nwords];
413      r_write_to_init_cmd_we            = new sc_signal<bool>[nwords];
414      r_write_to_ixr_cmd_data       = new sc_signal<data_t>[nwords];
415
416      // Allocation for LLSC FSM
417      r_llsc_to_ixr_cmd_data        = new sc_signal<data_t>[nwords];
418
419
420      m_tm_start = 0;
421      m_tm_end = 0;
422      m_period = 0;
423      m_debug_start = 499999999LL;
424
425      char *ptr;
426
427      ptr = getenv("TSAR_MEMC_COPY_THRESHOLD");
428
429      if(ptr != NULL)
430          m_copy_threshold = atol(ptr);
431      else
432          m_copy_threshold = 3;
433     
434      ptr = getenv("TSAR_MEMC_TM_START");
435
436      if(ptr != NULL)
437          m_tm_start = (size_t) atol(ptr);
438
439      ptr = getenv("TSAR_MEMC_TM_END");
440
441      if(ptr != NULL)
442          m_tm_end = (size_t) atol(ptr);
443
444      ptr = getenv("TSAR_MEMC_PERIOD");
445
446      if(ptr != NULL)
447          m_period = (size_t) atol(ptr);
448     
449      ptr = getenv("TSAR_MEMC_DEBUG_START");
450
451      if(ptr != NULL)
452          m_debug_start = (long long) atoll(ptr);
453
454      if(m_period != 0)
455          m_log.open(name, std::ios::out);
456
457      ptr = getenv("TSAR_MEMC_WAIT_THRESHOLD");
458
459      if(ptr != NULL)
460          m_wait_threshold = atof(ptr);
461      else
462          m_wait_threshold = 0.95;
463
464
465      //std::cout << name << " srcid " << m_srcid_ini << std::endl;
466
467      if(m_srcid_ini == 4)
468      {
469          std::cout << "TSAR_MEMC_TM_START    =" << m_tm_start << std::endl
470                    << "TSAR_MEMC_TM_END      =" << m_tm_end << std::endl
471                    << "TSAR_MEMC_PERIOD      =" << m_period << std::endl
472                    << "TSAR_MEMC_DEBUG_START =" << m_debug_start << std::endl
473                    << "CPY_TH                =" << m_copy_threshold << std::endl
474                    << "TRT_TBL               =" << TRANSACTION_TAB_LINES << std::endl
475                    << "UPD_TBL               =" << UPDATE_TAB_LINES << std::endl;
476      }
477 
478      // Simulation
479
480      SC_METHOD(transition);
481      dont_initialize();
482      sensitive << p_clk.pos();
483
484      SC_METHOD(genMoore);
485      dont_initialize();
486      sensitive << p_clk.neg();
487
488    } // end constructor
489
490  /////////////////////////////////////////
491  // This function prints the statistics
492  /////////////////////////////////////////
493
494  tmpl(void)::clear_stats()
495  {
496      // Activity counters
497      m_cpt_cycles                  = 0;
498      m_cpt_read                    = 0;
499      m_cpt_read_miss       = 0;
500      m_cpt_write                   = 0;
501      m_cpt_write_miss      = 0;
502      m_cpt_write_cells     = 0;
503      m_cpt_write_dirty     = 0;
504      m_cpt_update                  = 0;
505      m_cpt_update_mult     = 0;
506      m_cpt_inval_brdcast       = 0;
507      m_cpt_inval                   = 0;
508      m_cpt_inval_mult          = 0;
509      m_cpt_cleanup                 = 0;
510      m_cpt_ll                      = 0;
511      m_cpt_sc                      = 0;
512      m_waiting_cycles      = 0;
513  }
514
515  tmpl(void)::print_log()
516  {
517      m_log << "----------------------------------" << std::dec << std::endl;
518      m_log << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_total_cycles << std::endl
519            << "READ_RATE             = " << (double)m_cpt_read/m_cpt_cycles << std::endl
520            << "READ_MISS_RATE        = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
521            << "WRITE_RATE            = " << (double)m_cpt_write/m_cpt_cycles << std::endl
522            << "WRITE_MISS_RATE       = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
523            << "WRITE_BURST_LENGTH    = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
524            << "UPDATE_RATE           = " << (double)m_cpt_update/m_cpt_cycles << std::endl
525            << "UPDATE_ARITY          = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
526            << "INVAL_MULTICAST_RATE  = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
527            << "INVAL_MULTICAST_ARITY = " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
528            << "INVAL_BROADCAST_RATE  = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
529            << "SAVE_DIRTY_RATE       = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
530            << "CLEANUP_RATE          = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
531            << "LL_RATE               = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
532            << "SC_RATE               = " << (double)m_cpt_sc/m_cpt_cycles << std::endl
533            << "TGT_WAITING_%         = " << (double)m_waiting_cycles/m_cpt_cycles << std::endl;
534  }
535
536
537
538  tmpl(void)::print_stats()
539  {
540      std::cout << "----------------------------------" << std::dec << std::endl;
541      std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_total_cycles << std::endl
542                << "READ_RATE             = " << (double)m_cpt_read/m_cpt_cycles << std::endl
543                << "READ_MISS_RATE        = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
544                << "WRITE_RATE            = " << (double)m_cpt_write/m_cpt_cycles << std::endl
545                << "WRITE_MISS_RATE       = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
546                << "WRITE_BURST_LENGTH    = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
547                << "UPDATE_RATE           = " << (double)m_cpt_update/m_cpt_cycles << std::endl
548                << "UPDATE_ARITY          = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
549                << "INVAL_MULTICAST_RATE  = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
550                << "INVAL_MULTICAST_ARITY = " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
551                << "INVAL_BROADCAST_RATE  = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
552                << "SAVE_DIRTY_RATE       = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
553                << "CLEANUP_RATE          = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
554                << "LL_RATE               = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
555                << "SC_RATE               = " << (double)m_cpt_sc/m_cpt_cycles << std::endl
556                << "TGT_WAITING_%         = " << (double)m_waiting_cycles/m_cpt_cycles << std::endl;
557  }
558
559  tmpl(void)::print_trace_to_log_file()
560  {
561      m_log << "---------------------------------------------" << std::dec << std::endl;
562      m_log << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
563            << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
564            << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
565            << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
566            << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
567            << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
568            << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
569            << " - LLSC FSM       = " << llsc_fsm_str[r_llsc_fsm] << std::endl
570            << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
571            << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
572            << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
573            << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
574            << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
575            << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
576            << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
577            << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
578  }
579   
580  /////////////////////////////////
581  tmpl(/**/)::~VciMemCacheV3()
582    /////////////////////////////////
583  {
584    for(size_t i=0; i<m_ways ; i++){
585      for(size_t j=0; j<m_sets ; j++){
586        delete [] m_cache_data[i][j];
587      }
588    }
589    for(size_t i=0; i<m_ways ; i++){
590      delete [] m_cache_data[i];
591    }
592    delete [] m_cache_data;
593    delete [] m_coherence_table;
594
595    delete [] r_ixr_rsp_to_xram_rsp_rok;
596
597    delete [] r_xram_rsp_victim_data;
598    delete [] r_xram_rsp_to_tgt_rsp_data;
599    delete [] r_xram_rsp_to_ixr_cmd_data;
600
601    delete [] r_read_data;
602    delete [] r_read_to_tgt_rsp_data;
603
604    delete [] r_write_data;
605    delete [] r_write_be;
606    delete [] r_write_to_init_cmd_data;
607  }
608
609  //////////////////////////////////
610  tmpl(void)::transition()
611    //////////////////////////////////
612  {
613    using soclib::common::uint32_log2;
614    //  RESET         
615    if ( ! p_resetn.read() ) {
616
617      //     Initializing FSMs
618      r_tgt_cmd_fsm     = TGT_CMD_IDLE;
619      r_tgt_rsp_fsm     = TGT_RSP_READ_IDLE;
620      r_init_cmd_fsm    = INIT_CMD_INVAL_IDLE;
621      r_init_rsp_fsm    = INIT_RSP_IDLE;
622      r_read_fsm        = READ_IDLE;
623      r_write_fsm       = WRITE_IDLE;
624      r_llsc_fsm        = LLSC_IDLE;
625      r_cleanup_fsm     = CLEANUP_IDLE;
626      r_alloc_dir_fsm   = ALLOC_DIR_READ;
627      r_alloc_trt_fsm   = ALLOC_TRT_READ;
628      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
629      r_ixr_rsp_fsm     = IXR_RSP_IDLE;
630      r_xram_rsp_fsm    = XRAM_RSP_IDLE;
631      r_ixr_cmd_fsm     = IXR_CMD_READ_IDLE;
632
633      //  Initializing Tables
634      m_cache_directory.init();
635      m_atomic_tab.init();     
636      m_transaction_tab.init();
637      m_heap_directory.init();
638
639      // initializing FIFOs and communication Buffers
640
641      m_cmd_read_addr_fifo.init();
642      m_cmd_read_length_fifo.init();
643      m_cmd_read_srcid_fifo.init();
644      m_cmd_read_trdid_fifo.init();
645      m_cmd_read_pktid_fifo.init();
646
647      m_cmd_write_addr_fifo.init();
648      m_cmd_write_eop_fifo.init();
649      m_cmd_write_srcid_fifo.init();
650      m_cmd_write_trdid_fifo.init();
651      m_cmd_write_pktid_fifo.init();
652      m_cmd_write_data_fifo.init();
653
654      m_cmd_llsc_addr_fifo.init();
655      m_cmd_llsc_srcid_fifo.init();
656      m_cmd_llsc_trdid_fifo.init();
657      m_cmd_llsc_pktid_fifo.init();
658      m_cmd_llsc_wdata_fifo.init();
659      m_cmd_llsc_sc_fifo.init();
660
661      r_read_to_tgt_rsp_req         = false;
662      r_read_to_ixr_cmd_req         = false;
663
664      r_write_to_tgt_rsp_req            = false;
665      r_write_to_ixr_cmd_req            = false;
666      r_write_to_init_cmd_multi_req         = false;
667      r_write_to_init_cmd_brdcast_req   = false;
668      r_write_to_init_rsp_req           = false;
669      m_write_to_init_cmd_inst_fifo.init();
670      m_write_to_init_cmd_srcid_fifo.init();
671
672      r_cleanup_to_tgt_rsp_req  = false;
673
674      r_init_rsp_to_tgt_rsp_req = false;
675
676      r_llsc_to_tgt_rsp_req                 = false;
677      r_llsc_to_ixr_cmd_req                 = false;
678      r_llsc_to_init_cmd_multi_req          = false;
679      r_llsc_to_init_cmd_brdcast_req    = false;
680      m_llsc_to_init_cmd_inst_fifo.init();
681      m_llsc_to_init_cmd_srcid_fifo.init();
682
683      for(size_t i=0; i<TRANSACTION_TAB_LINES ; i++){
684        r_ixr_rsp_to_xram_rsp_rok[i] = false;
685      }
686
687      r_xram_rsp_to_tgt_rsp_req             = false;
688      r_xram_rsp_to_init_cmd_multi_req      = false;
689      r_xram_rsp_to_init_cmd_brdcast_req    = false;
690      r_xram_rsp_to_ixr_cmd_req             = false;
691      r_xram_rsp_trt_index                      = 0;
692      m_xram_rsp_to_init_cmd_inst_fifo.init();
693      m_xram_rsp_to_init_cmd_srcid_fifo.init();
694
695      r_ixr_cmd_cpt         = 0;
696
697      r_copies_limit        = m_copy_threshold;
698      m_total_cycles = 0;
699      clear_stats();
700      return;
701    }
702
703    double current_waiting = 0;
704
705    if(m_period != 0)
706    {
707        size_t current_period;
708
709        current_period  = (m_cpt_cycles == 0) ? 1 : m_cpt_cycles;
710        current_waiting = (double)(m_waiting_cycles / current_period);
711       
712        if(current_waiting > m_wait_threshold)
713            print_trace_to_log_file();
714    }
715
716    bool    cmd_read_fifo_put = false;
717    bool    cmd_read_fifo_get = false;
718
719    bool    cmd_write_fifo_put = false;
720    bool    cmd_write_fifo_get = false;
721
722    bool    cmd_llsc_fifo_put = false;
723    bool    cmd_llsc_fifo_get = false;
724
725    bool    write_to_init_cmd_fifo_put   = false;
726    bool    write_to_init_cmd_fifo_get   = false;
727    bool    write_to_init_cmd_fifo_inst  = false;
728    size_t  write_to_init_cmd_fifo_srcid = 0;
729
730    bool    xram_rsp_to_init_cmd_fifo_put   = false;
731    bool    xram_rsp_to_init_cmd_fifo_get   = false;
732    bool    xram_rsp_to_init_cmd_fifo_inst  = false;
733    size_t  xram_rsp_to_init_cmd_fifo_srcid = 0;
734
735    bool    llsc_to_init_cmd_fifo_put   = false;
736    bool    llsc_to_init_cmd_fifo_get   = false;
737    bool    llsc_to_init_cmd_fifo_inst  = false;
738    size_t  llsc_to_init_cmd_fifo_srcid = 0;
739
740
741    ////////////////////////////////////////////////////////////////////////////////////
742    //          TGT_CMD FSM
743    ////////////////////////////////////////////////////////////////////////////////////
744    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
745    //
746    // There is 4 types of packets for the m_mem_segment :
747    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word
748    //             or an entire cache line, depending on the PLEN value.
749    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
750    //             concern words in a same line.
751    // - LL      : The LL request has a length of 1 cell.
752    // - SC      : The SC request has a length of 1 cell.
753    //             The WDATA field contains the data to write.
754    //
755    ////////////////////////////////////////////////////////////////////////////////////
756
757    switch ( r_tgt_cmd_fsm.read() ) {
758
759      //////////////////
760      case TGT_CMD_IDLE:
761        {
762          if ( p_vci_tgt.cmdval ) 
763          {
764              m_waiting_cycles ++;
765
766              assert( (p_vci_tgt.srcid.read() < m_initiators)
767                      && "VCI_MEM_CACHE error in VCI_MEM_CACHE : The received SRCID is larger than the number of initiators");
768             
769              bool reached = false;
770              for ( size_t index = 0 ; index < nseg && !reached ; index++) 
771              {
772                  //              if ( m_seg[index]->contains((addr_t)(p_vci_tgt.address.read())) ) {
773                  if ( m_seg[index]->contains(p_vci_tgt.address.read()) ) {
774                      reached = true;
775                      r_index = index;
776                  }
777              }
778
779
780              if ( !reached ) 
781              { 
782                  std::cout << "VCI_MEM_CACHE Out of segment access in VCI_MEM_CACHE" << std::endl;
783                  std::cout << "Faulty address = " << std::hex << (addr_t)(p_vci_tgt.address.read()) << std::endl;
784                  std::cout << "Faulty initiator = " << std::dec << p_vci_tgt.srcid.read() << std::endl;
785                  exit(0);
786              } 
787              else if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ ) 
788              {
789                  r_tgt_cmd_fsm = TGT_CMD_READ;
790              } 
791              else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
792              { 
793                  r_tgt_cmd_fsm = TGT_CMD_WRITE;
794              } 
795              else if ((p_vci_tgt.cmd.read() == vci_param::CMD_LOCKED_READ) || 
796                       (p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND) ) 
797              {
798                  r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
799              } 
800          }
801          break;
802        }
803        //////////////////
804      case TGT_CMD_READ:
805
806        {
807          assert(((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2))<=16)
808              && "VCI_MEM_CACHE All read request to the MemCache must stay within a cache line"); 
809
810          m_waiting_cycles ++;
811
812          if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() ) {
813            cmd_read_fifo_put = true;
814            if ( p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
815            else                  r_tgt_cmd_fsm = TGT_CMD_READ_EOP;             
816          } 
817          break;
818        }
819        //////////////////////
820      case TGT_CMD_READ_EOP:
821        {
822            m_waiting_cycles ++;
823         
824            if ( p_vci_tgt.cmdval && p_vci_tgt.eop ){
825                r_tgt_cmd_fsm = TGT_CMD_IDLE;
826            }
827            break;
828        }
829        ///////////////////
830      case TGT_CMD_WRITE:
831        {
832
833            m_waiting_cycles ++;
834
835            if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() ) {
836                cmd_write_fifo_put = true;
837                if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
838               
839            }
840            break;
841        }
842        ////////////////////
843      case TGT_CMD_ATOMIC:
844        {
845          assert(p_vci_tgt.eop && "Memory Cache Error: LL or SC command with length > 1 ");
846
847          m_waiting_cycles ++;
848
849          if ( p_vci_tgt.cmdval && m_cmd_llsc_addr_fifo.wok() ) {
850              cmd_llsc_fifo_put = true;
851              r_tgt_cmd_fsm = TGT_CMD_IDLE;
852          }
853          break;
854        }
855    } // end switch tgt_cmd_fsm
856
857    /////////////////////////////////////////////////////////////////////////
858    //          INIT_RSP FSM
859    /////////////////////////////////////////////////////////////////////////
860    // This FSM controls the response to the update or invalidate requests
861    // sent by the memory cache to the L1 caches :
862    //
863    // - update request initiated by the WRITE FSM. 
864    //   The FSM decrements the proper entry in the Update/Inval Table.
865    //   It sends a request to the TGT_RSP FSM to complete the pending
866    //   write transaction (acknowledge response to the writer processor),
867    //   and clear the UPT entry when all responses have been received. 
868    // - invalidate request initiated by the XRAM_RSP FSM.
869    //   The FSM decrements the proper entry in the Update/Inval_Table,
870    //   and clear the entry when all responses have been received.
871    //
872    // All those response packets are one word, compact
873    // packets complying with the VCI advanced format.
874    // The index in the Table is defined in the RTRDID field, and
875    // the Transaction type is defined in the Update/Inval Table.
876    /////////////////////////////////////////////////////////////////////
877
878    switch ( r_init_rsp_fsm.read() ) {
879
880      ///////////////////
881      case INIT_RSP_IDLE:
882        {
883
884          if ( p_vci_ini.rspval ) {
885
886            assert ( ( p_vci_ini.rtrdid.read() < m_update_tab.size() )
887                && "VCI_MEM_CACHE UPT index too large in VCI response paquet received by memory cache" );
888            assert ( p_vci_ini.reop
889                && "VCI_MEM_CACHE All response packets to update/invalidate requests must be one cell" );
890            r_init_rsp_upt_index = p_vci_ini.rtrdid.read(); 
891            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
892          } else if( r_write_to_init_rsp_req.read() ){
893            r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
894            r_write_to_init_rsp_req = false;
895            r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
896          }
897          break;
898        }
899        ///////////////////////
900      case INIT_RSP_UPT_LOCK:   // decrement the number of expected responses
901        {
902
903          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) { 
904            size_t count = 0;
905            bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
906#ifdef IDEBUG
907            TRACE_MSG(m_log
908                      << m_total_cycles
909                      << " " << name() 
910                      << " INIT_RSP_UPT_LOCK update table : " << std::endl);
911           
912            DUMP_UPDATE_TABLE;
913#endif
914            assert ( valid
915                && "VCI_MEM_CACHE Invalid UPT entry in VCI response paquet received by memory cache" );
916
917            if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
918            else              r_init_rsp_fsm = INIT_RSP_IDLE;
919          }
920          break;
921        }
922        ////////////////////////
923      case INIT_RSP_UPT_CLEAR:  // clear the UPT entry
924        {
925          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP ) {
926            r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
927            r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
928            r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
929            r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
930            bool need_rsp = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
931            if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
932            else            r_init_rsp_fsm = INIT_RSP_IDLE;
933            m_update_tab.clear(r_init_rsp_upt_index.read());
934
935#ifdef IDEBUG
936            TRACE_MSG(std::cout << m_total_cycles << " " << name() << " INIT_RSP_UPT_CLEAR update table : " << std::endl);
937            DUMP_UPDATE_TABLE;
938#endif
939          }
940          break;
941        }
942        //////////////////
943      case INIT_RSP_END:
944        {
945
946          if ( !r_init_rsp_to_tgt_rsp_req ) {
947            r_init_rsp_to_tgt_rsp_req = true;
948            r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
949            r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
950            r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
951            r_init_rsp_fsm = INIT_RSP_IDLE;
952          }
953          break;
954        }
955    } // end switch r_init_rsp_fsm
956
957    ////////////////////////////////////////////////////////////////////////////////////
958    //          READ FSM
959    ////////////////////////////////////////////////////////////////////////////////////
960    // The READ FSM controls the read requests sent by processors.
961    // It takes the lock protecting the cache directory to check the cache line status:
962    // - In case of HIT, the fsm copies the data (one line, or one single word)
963    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
964    //   The requesting initiator is registered in the cache directory.
965    // - In case of MISS, the READ fsm takes the lock protecting the transaction tab.
966    //   If a read transaction to the XRAM for this line already exists,
967    //   or if the transaction tab is full, the fsm is stalled.
968    //   If a transaction entry is free, the READ fsm sends a request to the XRAM.
969    ////////////////////////////////////////////////////////////////////////////////////
970
971    switch ( r_read_fsm.read() ) {
972
973      ///////////////
974      case READ_IDLE:
975        {
976          if (m_cmd_read_addr_fifo.rok()) {
977            m_cpt_read++;
978            r_read_fsm = READ_DIR_LOCK;
979          }
980          break;
981        }
982        ///////////////////
983      case READ_DIR_LOCK:       // check directory for hit / miss
984        {
985          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
986            size_t way = 0;
987            DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
988#ifdef DDEBUG
989            TRACE_MSG(m_log << "In READ_DIR_LOCK printing the entry of address is : " 
990                      << std::hex << m_cmd_read_addr_fifo.read() 
991                      << std::endl);
992            DUMP_ENTRY(entry);
993            TRACE_MSG(m_log << "done" << std::endl);
994#endif
995
996            r_read_is_cnt   = entry.is_cnt;
997            r_read_dirty    = entry.dirty;
998            r_read_lock     = entry.lock;
999            r_read_inst     = entry.inst;
1000            r_read_tag      = entry.tag;
1001            r_read_way      = way;
1002            r_read_count    = entry.count;
1003            r_read_copy     = entry.owner.srcid; 
1004            r_read_copy_inst= entry.owner.inst;
1005            r_read_ptr      = entry.ptr;
1006
1007            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
1008            // In case of hit, the read acces must be registered in the copies bit-vector
1009            if( entry.valid ) 
1010            {
1011                if(entry.is_cnt || (entry.count == 0) || !cached_read)  { // No new entry in the heap
1012                    r_read_fsm = READ_DIR_HIT;
1013                } else {
1014                    r_read_fsm = READ_HEAP_LOCK;
1015                }
1016            } 
1017            else 
1018            {
1019                r_read_fsm = READ_TRT_LOCK;
1020                m_cpt_read_miss++;
1021            }
1022          }
1023          break;
1024        }
1025        //////////////////
1026      case READ_DIR_HIT:        // read hit : update the memory cache
1027        {
1028          if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ ) {
1029            // signals generation
1030            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
1031            bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
1032            bool is_cnt = r_read_is_cnt.read();
1033
1034            // read data in the cache
1035            size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1036            size_t way = r_read_way.read();
1037            for ( size_t i=0 ; i<m_words ; i++ ) {
1038              r_read_data[i] = m_cache_data[way][set][i];
1039            }
1040
1041            // update the cache directory (for the copies)
1042            DirectoryEntry entry;
1043            entry.valid   = true;
1044            entry.is_cnt  = is_cnt; 
1045            entry.dirty   = r_read_dirty.read();
1046            entry.tag     = r_read_tag.read();
1047            entry.lock    = r_read_lock.read();
1048            entry.ptr     = r_read_ptr.read();
1049            if(cached_read){  // Cached read, we update the copy
1050              if(!is_cnt){ // Not counter mode
1051                entry.owner.srcid   = m_cmd_read_srcid_fifo.read();
1052                entry.owner.inst    = inst_read;
1053                entry.inst          = r_read_inst.read() || inst_read;
1054                entry.count         = r_read_count.read() + 1;
1055              } else { // Counter mode
1056                entry.owner.srcid   = 0;
1057                entry.owner.inst    = false;
1058                entry.inst          = r_read_inst.read() || inst_read;
1059                entry.count         = r_read_count.read() + 1;
1060              } 
1061            } else { // Uncached read
1062              entry.owner.srcid     = r_read_copy.read();
1063              entry.owner.inst      = r_read_copy_inst.read();
1064              entry.inst            = r_read_inst.read();
1065              entry.count           = r_read_count.read();
1066            }
1067#ifdef DDEBUG
1068            TRACE_MSG(m_log << "In READ_DIR_HIT printing the entry of address is : " << std::endl);
1069            DUMP_ENTRY(entry);
1070            TRACE_MSG(m_log << "done" << std::endl);
1071#endif
1072
1073            m_cache_directory.write(set, way, entry);
1074            r_read_fsm    = READ_RSP;
1075          }
1076          break;
1077        }
1078        //////////////
1079      case READ_HEAP_LOCK:
1080        {
1081          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ ) 
1082          {
1083              size_t copies_count = r_read_count.read() + 1;
1084              bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
1085              //bool is_cnt    = (r_read_count.read() >= r_copies_limit.read()) || m_heap_directory.is_full();
1086              bool is_cnt    = (r_copies_limit.read() == 2) ? true : ((copies_count >= r_copies_limit.read()) || m_heap_directory.is_full());
1087
1088              // read data in the cache
1089              size_t set     = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1090              size_t way     = r_read_way.read();
1091
1092              for ( size_t i=0 ; i<m_words ; i++ ) {
1093                  r_read_data[i] = m_cache_data[way][set][i];
1094              }
1095
1096              // update the cache directory (for the copies)
1097              DirectoryEntry entry;
1098              entry.valid         = true;
1099              entry.is_cnt    = is_cnt; // when we reach the limit of copies or the heap is full
1100              entry.dirty         = r_read_dirty.read();
1101              entry.tag       = r_read_tag.read();
1102              entry.lock          = r_read_lock.read();
1103              if(!is_cnt){ // Not counter mode
1104                entry.owner.srcid   = r_read_copy.read();
1105                entry.owner.inst    = r_read_copy_inst.read();
1106                entry.inst          = r_read_inst.read() || inst_read;
1107                entry.count         = r_read_count.read() + 1;
1108                entry.ptr           = m_heap_directory.next_free_ptr();
1109              } else { // Counter mode
1110                entry.owner.srcid   = 0;
1111                entry.owner.inst    = false;
1112                entry.inst          = r_read_inst.read() || inst_read;
1113                entry.count         = r_read_count.read() + 1;
1114                entry.ptr           = 0;
1115              }
1116
1117#ifdef DDEBUG
1118              TRACE_MSG(m_log << "In READ_HEAP_LOCK printing the entry of address is : " << std::endl);
1119              DUMP_ENTRY(entry);
1120              TRACE_MSG(m_log << "done" << std::endl);
1121#endif
1122
1123              m_cache_directory.write(set, way, entry);
1124
1125              if(!is_cnt)
1126              {
1127                  HeapEntry free_heap_entry = m_heap_directory.next_free_entry();
1128                  r_read_next_ptr           = free_heap_entry.next;
1129
1130                  if( free_heap_entry.next == m_heap_directory.next_free_ptr() ) { // Last free heap entry
1131                      r_read_last_free = true;
1132                  } else {
1133                      r_read_last_free = false;
1134                  }
1135
1136                  r_read_fsm = READ_HEAP_WRITE; // we add an entry in the list of copies
1137              } 
1138              else 
1139              {
1140                  if(r_read_count.read()>1) 
1141                  { // else there is no list of copies...
1142                      HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
1143                      r_read_next_ptr = m_heap_directory.next_free_ptr();
1144                      m_heap_directory.write_free_ptr(r_read_ptr.read());
1145                      if( next_entry.next == r_read_ptr.read() ) { // The last list member
1146                          r_read_fsm = READ_HEAP_LAST; // we erase the list of copies (counter mode)
1147                      } else { // Not the end of the list
1148                          r_read_ptr = next_entry.next;
1149                          r_read_fsm = READ_HEAP_ERASE; // we erase the list of copies (counter mode)
1150                      }
1151                  } 
1152                  else 
1153                  {
1154                      r_read_fsm = READ_RSP;
1155                  }
1156              }
1157          }
1158          break;
1159        }
1160        //////////////
1161      case READ_HEAP_WRITE:
1162        {
1163          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
1164            bool inst_read = (m_cmd_read_trdid_fifo.read() & 0x2);
1165            HeapEntry new_heap_entry;
1166            new_heap_entry.owner.srcid  = m_cmd_read_srcid_fifo.read();
1167            new_heap_entry.owner.inst   = inst_read;
1168            if(r_read_count.read() == 1){ // creation of a new list
1169              new_heap_entry.next         = m_heap_directory.next_free_ptr(); 
1170            } else {                      // it is an insertion
1171              new_heap_entry.next         = r_read_ptr.read();
1172            }
1173            m_heap_directory.write_free_entry(new_heap_entry);
1174            m_heap_directory.write_free_ptr(r_read_next_ptr.read());
1175            if(r_read_last_free.read()) {
1176              m_heap_directory.set_full();
1177            }
1178
1179            r_read_fsm = READ_RSP;
1180          } else {
1181            assert(false && "MEMCACHE Error : Bad HEAP allocation");
1182          }
1183          break;
1184        }
1185        //////////////
1186      case READ_HEAP_ERASE:
1187        {
1188          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
1189            HeapEntry next_entry = m_heap_directory.read(r_read_ptr.read());
1190            if( next_entry.next == r_read_ptr.read() ){
1191              r_read_fsm = READ_HEAP_LAST;
1192            } else {
1193              r_read_ptr = next_entry.next;
1194              r_read_fsm = READ_HEAP_ERASE;
1195            }
1196          } else {
1197            assert(false && "MEMCACHE Error : Bad HEAP allocation");
1198          }
1199          break;
1200        }
1201        //////////////
1202      case READ_HEAP_LAST:
1203        {
1204          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ){
1205            HeapEntry last_entry;
1206            last_entry.owner.srcid = 0;
1207            last_entry.owner.inst  = false;
1208            if(m_heap_directory.is_full()){
1209              last_entry.next      = r_read_ptr.read();
1210              m_heap_directory.unset_full();
1211            } else {
1212              last_entry.next      = r_read_next_ptr.read();
1213            }
1214            m_heap_directory.write(r_read_ptr.read(),last_entry);
1215            r_read_fsm = READ_RSP;
1216          } else {
1217            assert(false && "MEMCACHE Error : Bad HEAP allocation");
1218          }
1219          break;
1220        }
1221        //////////////
1222      case READ_RSP:            //  request the TGT_RSP FSM to return data
1223        {
1224          if( !r_read_to_tgt_rsp_req ) {       
1225            for ( size_t i=0 ; i<m_words ; i++ ) {
1226              r_read_to_tgt_rsp_data[i] = r_read_data[i];
1227            }
1228            r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
1229            r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
1230            cmd_read_fifo_get            = true;
1231            r_read_to_tgt_rsp_req        = true;
1232            r_read_to_tgt_rsp_srcid      = m_cmd_read_srcid_fifo.read();
1233            r_read_to_tgt_rsp_trdid      = m_cmd_read_trdid_fifo.read();
1234            r_read_to_tgt_rsp_pktid      = m_cmd_read_pktid_fifo.read();
1235            r_read_fsm                       = READ_IDLE; 
1236          }
1237          break;
1238        }
1239        ///////////////////
1240      case READ_TRT_LOCK:       // read miss : check the Transaction Table
1241        {
1242          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
1243#ifdef TDEBUG
1244              TRACE_MSG(m_log << m_total_cycles << " " << name() << " READ_TRT_LOCK " << std::endl);
1245#endif
1246            size_t index     = 0;
1247            bool   hit_read  = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())], index);
1248            bool   hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())]);
1249            bool   wok       = !m_transaction_tab.full(index);
1250
1251            if( hit_read || !wok || hit_write )  // missing line already requested or no space
1252            { 
1253              r_read_fsm = READ_IDLE; 
1254             
1255              TRACE_MSG(m_log << m_total_cycles
1256                        << " " << name() 
1257                        << " READ_TRT_LOCK -> READ_IDLE"
1258                        << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1259                        << " read hit = " << hit_read
1260                        << ", write hit = " << hit_write
1261                        << std::endl);
1262            }
1263            else                                         // missing line is requested to the XRAM
1264            {   
1265              r_read_trt_index = index;
1266              r_read_fsm       = READ_TRT_SET;
1267            }
1268          }
1269          break;
1270        }
1271        //////////////////
1272      case READ_TRT_SET:
1273        {
1274          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ ) {
1275            m_transaction_tab.set(r_read_trt_index.read(),
1276                true,
1277                m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1278                m_cmd_read_srcid_fifo.read(),
1279                m_cmd_read_trdid_fifo.read(),
1280                m_cmd_read_pktid_fifo.read(),
1281                true,
1282                m_cmd_read_length_fifo.read(),
1283                m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1284                std::vector<be_t>(m_words,0),
1285                std::vector<data_t>(m_words,0));
1286#ifdef TDEBUG
1287            TRACE_MSG(m_log << m_total_cycles << " " << name() 
1288                      << " Address = " << std::hex << m_cmd_read_addr_fifo.read()
1289                      << " READ_TRT_SET transaction table : " << std::endl);
1290
1291            DUMP_TRANSACTION_TABLE;
1292#endif
1293
1294            r_read_fsm   = READ_XRAM_REQ;
1295          }
1296          break;
1297        }
1298        /////////////////////
1299      case READ_XRAM_REQ:
1300        {
1301          if( !r_read_to_ixr_cmd_req ) {
1302            cmd_read_fifo_get           = true;
1303            r_read_to_ixr_cmd_req       = true;
1304            r_read_to_ixr_cmd_nline     = m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1305            r_read_to_ixr_cmd_trdid     = r_read_trt_index.read();
1306            r_read_fsm                            = READ_IDLE;
1307          }
1308          break;
1309        }
1310    } // end switch read_fsm
1311
1312    ///////////////////////////////////////////////////////////////////////////////////
1313    //          WRITE FSM
1314    ///////////////////////////////////////////////////////////////////////////////////
1315    // The WRITE FSM handles the write bursts sent by the processors.
1316    // All addresses in a burst must be in the same cache line.
1317    // A complete write burst is consumed in the FIFO & copied to a local buffer.
1318    // Then the FSM takes the lock protecting the cache directory, to check
1319    // if the line is in the cache.
1320    //
1321    // - In case of HIT, the cache is updated.
1322    //   If there is no other copy, an acknowledge response is immediately
1323    //   returned to the writing processor.
1324    //   if the data is cached by other processoris, the FSM takes the lock
1325    //   protecting the Update Table (UPT) to register this update transaction.
1326    //   If the UPT is full, it releases the lock  and waits. Then, it sends
1327    //   a multi-update request to all owners of the line (but the writer),
1328    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM
1329    //   does not respond to the writing processor, as this response will be sent by
1330    //   the INIT_RSP FSM when all update responses have been received.
1331    //
1332    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
1333    //   table (TRT). If a read transaction to the XRAM for this line already exists,
1334    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
1335    //   the WRITE FSM register a new transaction in TRT, and sends a read line request
1336    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
1337    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
1338    /////////////////////////////////////////////////////////////////////////////////////
1339
1340    switch ( r_write_fsm.read() ) {
1341
1342      ////////////////
1343      case WRITE_IDLE:  // copy first word of a write burst in local buffer     
1344        {
1345          if ( m_cmd_write_addr_fifo.rok()) {
1346            m_cpt_write++;
1347            m_cpt_write_cells++;
1348            // consume a word in the FIFO & write it in the local buffer
1349            cmd_write_fifo_get  = true;
1350            size_t index            = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
1351            r_write_address         = (addr_t)(m_cmd_write_addr_fifo.read());
1352            r_write_word_index  = index;
1353            r_write_word_count  = 1;
1354            r_write_data[index] = m_cmd_write_data_fifo.read();
1355            r_write_srcid           = m_cmd_write_srcid_fifo.read();
1356            r_write_trdid           = m_cmd_write_trdid_fifo.read();
1357            r_write_pktid           = m_cmd_write_pktid_fifo.read();
1358
1359            // the be field must be set for all words
1360            for ( size_t i=0 ; i<m_words ; i++ ) {
1361              if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
1362              else                      r_write_be[i] = 0x0;
1363            }
1364            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1365                    r_write_byte=true;
1366            else    r_write_byte=false;
1367
1368            if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1369            else                               r_write_fsm = WRITE_NEXT;
1370          }
1371          break;
1372        }
1373        ////////////////
1374      case WRITE_NEXT:  // copy next word of a write burst in local buffer
1375        {
1376          if ( m_cmd_write_addr_fifo.rok() ) {
1377            m_cpt_write_cells++;
1378
1379            // check that the next word is in the same cache line
1380            assert( (m_nline[(vci_addr_t)(r_write_address.read())] == m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())]) 
1381                && "VCI_MEM_CACHE write error in vci_mem_cache : write burst over a line" );
1382            // consume a word in the FIFO & write it in the local buffer
1383            cmd_write_fifo_get=true;
1384            size_t index                = r_write_word_index.read() + r_write_word_count.read();
1385            r_write_be[index]       = m_cmd_write_be_fifo.read();
1386            r_write_data[index]     = m_cmd_write_data_fifo.read();
1387            r_write_word_count      = r_write_word_count.read() + 1;
1388            if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1389              r_write_byte=true;
1390            if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1391          }
1392          break;
1393        }
1394        ////////////////////
1395      case WRITE_DIR_LOCK:      // access directory to check hit/miss
1396        {
1397          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ) {
1398            size_t  way = 0;
1399            DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
1400
1401            // copy directory entry in local buffers in case of hit
1402            if ( entry.valid )  {       
1403              r_write_is_cnt    = entry.is_cnt;
1404              r_write_lock          = entry.lock;
1405              r_write_inst      = entry.inst;
1406              r_write_tag       = entry.tag;
1407              r_write_copy      = entry.owner.srcid;
1408              r_write_copy_inst = entry.owner.inst;
1409              r_write_count     = entry.count;
1410              r_write_ptr       = entry.ptr;
1411              r_write_way           = way;
1412             
1413              bool owner = (entry.owner.srcid==r_write_srcid.read()) && !entry.owner.inst;
1414              bool no_update = (entry.count==0) || ( owner && (entry.count==1));
1415
1416              if((entry.is_cnt && entry.count) || entry.inst)
1417              {
1418                  r_write_fsm      = WRITE_DIR_HIT_READ;
1419              } 
1420              else 
1421              {
1422                  if(r_write_byte.read())
1423                      r_write_fsm      = WRITE_DIR_HIT_READ;
1424                  else
1425                  { 
1426                      if( no_update) r_write_fsm  = WRITE_DIR_HIT_RSP;
1427                      else           r_write_fsm  = WRITE_DIR_HIT;
1428                  }
1429              }
1430            } 
1431            else 
1432            {
1433                r_write_fsm = WRITE_TRT_LOCK;
1434                m_cpt_write_miss++;
1435            }
1436          }
1437          break;
1438        }
1439        ///////////////////
1440      case WRITE_DIR_HIT_READ:  // read the cache and complete the buffer (data, when be!=0xF)
1441        {
1442          // update local buffer
1443          size_t set    = m_y[(vci_addr_t)(r_write_address.read())];
1444          size_t way    = r_write_way.read();
1445          for(size_t i=0 ; i<m_words ; i++) {
1446            data_t mask      = 0;
1447            if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
1448            if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
1449            if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
1450            if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
1451            if(r_write_be[i].read()||r_write_is_cnt.read()||r_write_inst.read()) { // complete only if mask is not null (for energy consumption)
1452              r_write_data[i]  = (r_write_data[i].read() & mask) | 
1453                (m_cache_data[way][set][i] & ~mask);
1454            }
1455          } // end for
1456
1457          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
1458          bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
1459          if((r_write_is_cnt.read() && r_write_count.read()) ||
1460              r_write_inst.read()){
1461            r_write_fsm            = WRITE_TRT_WRITE_LOCK;
1462          } else {
1463            if( no_update ) r_write_fsm = WRITE_DIR_HIT_RSP;
1464            else            r_write_fsm = WRITE_DIR_HIT;
1465          }
1466          break;
1467        }
1468        ///////////////////
1469      case WRITE_DIR_HIT:       // update the cache (data & dirty bit)
1470        {
1471          // update directory with Dirty bit
1472          DirectoryEntry entry;
1473          entry.valid       = true;
1474          entry.dirty       = true;
1475          entry.tag             = r_write_tag.read();
1476          entry.is_cnt      = r_write_is_cnt.read();
1477          entry.lock        = r_write_lock.read();
1478          entry.inst        = r_write_inst.read();
1479          entry.owner.srcid = r_write_copy.read();
1480          entry.owner.inst  = r_write_copy_inst.read();
1481          entry.count       = r_write_count.read();
1482          entry.ptr         = r_write_ptr.read();
1483          size_t set        = m_y[(vci_addr_t)(r_write_address.read())];
1484          size_t way        = r_write_way.read();
1485          m_cache_directory.write(set, way, entry);
1486
1487          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
1488
1489          size_t count_signal   = r_write_count.read();
1490          if(owner){
1491            count_signal        = count_signal - 1;
1492          }
1493          r_write_count         = count_signal;
1494          r_write_to_dec        = false;
1495
1496          if( !r_write_to_init_cmd_multi_req.read() && 
1497              !r_write_to_init_cmd_brdcast_req.read()  )
1498            r_write_fsm = WRITE_UPT_LOCK;
1499          else
1500            r_write_fsm = WRITE_WAIT;
1501          break;
1502        }
1503        ///////////////////
1504      case WRITE_DIR_HIT_RSP:   // update the cache (data & dirty bit) no update
1505        {
1506          // update directory with Dirty bit
1507          DirectoryEntry entry;
1508          entry.valid       = true;
1509          entry.dirty       = true;
1510          entry.tag             = r_write_tag.read();
1511          entry.is_cnt      = r_write_is_cnt.read();
1512          entry.lock        = r_write_lock.read();
1513          entry.inst        = r_write_inst.read();
1514          entry.owner.srcid = r_write_copy.read();
1515          entry.owner.inst  = r_write_copy_inst.read();
1516          entry.count       = r_write_count.read();
1517          entry.ptr         = r_write_ptr.read();
1518          size_t set        = m_y[(vci_addr_t)(r_write_address.read())];
1519          size_t way        = r_write_way.read();
1520          m_cache_directory.write(set, way, entry);
1521
1522          bool owner = (r_write_copy.read()==r_write_srcid.read()) && !r_write_copy_inst.read();
1523
1524          // write data in cache
1525          for(size_t i=0 ; i<m_words ; i++) {
1526              if  ( r_write_be[i].read() ) {
1527                  m_cache_data[way][set][i]  = r_write_data[i].read();
1528              }
1529          } // end for
1530
1531          if ( !r_write_to_tgt_rsp_req.read() ) {
1532            r_write_to_tgt_rsp_req          = true;
1533            r_write_to_tgt_rsp_srcid    = r_write_srcid.read();
1534            r_write_to_tgt_rsp_trdid    = r_write_trdid.read();
1535            r_write_to_tgt_rsp_pktid    = r_write_pktid.read();
1536            r_write_fsm                         = WRITE_IDLE;
1537          } else {
1538            r_write_fsm = WRITE_RSP;
1539          }
1540          break;
1541        }
1542        /////////////////////
1543      case WRITE_UPT_LOCK:      // Try to register the request in Update Table
1544        {
1545
1546          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
1547            bool        wok        = false;
1548            size_t      index      = 0;
1549            size_t      srcid      = r_write_srcid.read();
1550            size_t      trdid      = r_write_trdid.read();
1551            size_t      pktid      = r_write_pktid.read();
1552            addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
1553            size_t      nb_copies  = r_write_count.read();
1554            size_t set      = m_y[(vci_addr_t)(r_write_address.read())];
1555            size_t way      = r_write_way.read();
1556
1557            wok =m_update_tab.set(true, // it's an update transaction
1558                false,                  // it's not a broadcast
1559                true,                   // it needs a response
1560                srcid,
1561                trdid,
1562                pktid,
1563                nline,
1564                nb_copies,
1565                index);
1566            if(wok){
1567              // write data in cache
1568              for(size_t i=0 ; i<m_words ; i++) {
1569                if  ( r_write_be[i].read() ) {
1570                  m_cache_data[way][set][i]  = r_write_data[i].read();
1571                }
1572              } // end for
1573            }
1574#ifdef IDEBUG
1575            if((wok) && (m_total_cycles > m_debug_start) && (m_srcid_ini == MEMC_INI_ID)){
1576                TRACE_MSG(m_log << 
1577                          m_total_cycles
1578                          << " " << name() << " WRITE_UPT_LOCK update table : " 
1579                          << std::endl);
1580                m_update_tab.print();
1581            }
1582#endif
1583            r_write_upt_index = index;
1584            //  releases the lock protecting the Update Table and the Directory if no entry...
1585            if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
1586            else       r_write_fsm = WRITE_WAIT;
1587          }
1588          break;
1589        }
1590        //////////////////
1591      case WRITE_HEAP_LOCK:
1592        {
1593          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE ){
1594            r_write_fsm = WRITE_UPT_REQ;
1595          }
1596          break;
1597        }
1598        //////////////////
1599      case WRITE_UPT_REQ:
1600        {
1601          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
1602                    "MemCache ERROR : bad HEAP allocation");
1603          if( !r_write_to_init_cmd_multi_req.read() && 
1604              !r_write_to_init_cmd_brdcast_req.read()  ){
1605            r_write_to_init_cmd_brdcast_req  = false;
1606            r_write_to_init_cmd_trdid        = r_write_upt_index.read();
1607            r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
1608            r_write_to_init_cmd_index        = r_write_word_index.read();
1609            r_write_to_init_cmd_count        = r_write_word_count.read();
1610
1611            for(size_t i=0; i<m_words ; i++){
1612              if(r_write_be[i].read())  r_write_to_init_cmd_we[i]=true;
1613              else                      r_write_to_init_cmd_we[i]=false;
1614            }
1615
1616            size_t min = r_write_word_index.read();
1617            size_t max = r_write_word_index.read() + r_write_word_count.read();
1618            for (size_t i=min ; i<max ; i++) {
1619              r_write_to_init_cmd_data[i] = r_write_data[i];
1620            }
1621           
1622            if( r_write_copy.read() != r_write_srcid.read() ) {
1623              // We put the first copy in the fifo
1624              write_to_init_cmd_fifo_put     = true;
1625              write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
1626              write_to_init_cmd_fifo_srcid   = r_write_copy.read();
1627              if(r_write_count.read() == 1){
1628                r_write_fsm = WRITE_IDLE;
1629                r_write_to_init_cmd_multi_req = true;
1630              } else {
1631                r_write_fsm = WRITE_UPDATE;
1632              }
1633            } else {
1634              r_write_fsm = WRITE_UPDATE;
1635            }
1636          }
1637          break;
1638        }
1639        //////////////////
1640      case WRITE_UPDATE:        // send a multi-update request to INIT_CMD fsm
1641        {
1642          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
1643                    "MemCache ERROR : bad HEAP allocation");
1644          HeapEntry entry = m_heap_directory.read(r_write_ptr.read());
1645          write_to_init_cmd_fifo_inst  = entry.owner.inst;
1646          write_to_init_cmd_fifo_srcid = entry.owner.srcid;
1647          bool dec_upt_counter = r_write_to_dec.read();
1648          if( (entry.owner.srcid != r_write_srcid.read()) || entry.owner.inst ){
1649            write_to_init_cmd_fifo_put = true;
1650          } else {
1651            dec_upt_counter = true;
1652          }
1653          r_write_to_dec = dec_upt_counter;
1654
1655          if( m_write_to_init_cmd_inst_fifo.wok() ){
1656            r_write_ptr = entry.next;
1657            if( entry.next == r_write_ptr.read() ) { // last copy
1658              r_write_to_init_cmd_multi_req = true;
1659              if(dec_upt_counter){
1660                r_write_fsm = WRITE_UPT_DEC;
1661              } else {
1662                r_write_fsm = WRITE_IDLE;
1663              }
1664            } else {
1665              r_write_fsm = WRITE_UPDATE;
1666            }
1667          } else {
1668            r_write_fsm = WRITE_UPDATE;
1669          }
1670          break;
1671        }
1672        //////////////////
1673      case WRITE_UPT_DEC:
1674        {
1675          if(!r_write_to_init_rsp_req.read()){
1676            r_write_to_init_rsp_req = true;
1677            r_write_to_init_rsp_upt_index = r_write_upt_index.read();
1678            r_write_fsm = WRITE_IDLE;
1679          }
1680          break;
1681        }
1682        ///////////////
1683      case WRITE_RSP:           // send a request to TGT_RSP FSM to acknowledge the write
1684        {
1685          if ( !r_write_to_tgt_rsp_req.read() ) {
1686            r_write_to_tgt_rsp_req          = true;
1687            r_write_to_tgt_rsp_srcid    = r_write_srcid.read();
1688            r_write_to_tgt_rsp_trdid    = r_write_trdid.read();
1689            r_write_to_tgt_rsp_pktid    = r_write_pktid.read();
1690            r_write_fsm                         = WRITE_IDLE;
1691          }
1692          break;
1693        }
1694        ////////////////////
1695      case WRITE_TRT_LOCK:      // Miss : check Transaction Table
1696        {
1697          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
1698#ifdef TDEBUG
1699              TRACE_MSG(m_log << m_total_cycles << " " << name() << " READ_TRT_LOCK " << std::endl);
1700#endif
1701            size_t hit_index = 0;
1702            size_t wok_index = 0;
1703            bool hit_read    = m_transaction_tab.hit_read(m_nline[(vci_addr_t)(r_write_address.read())], hit_index);
1704            bool hit_write   = m_transaction_tab.hit_write(m_nline[(vci_addr_t)(r_write_address.read())]);
1705            bool wok         = !m_transaction_tab.full(wok_index);
1706
1707            if ( hit_read ) {   // register the modified data in TRT
1708              r_write_trt_index = hit_index;
1709              r_write_fsm       = WRITE_TRT_DATA;
1710            } else if ( wok && !hit_write ) {   // set a new entry in TRT
1711              r_write_trt_index = wok_index;
1712              r_write_fsm       = WRITE_TRT_SET;
1713            } else {                // wait an empty entry in TRT
1714              r_write_fsm       = WRITE_WAIT;
1715            }
1716          }
1717          break;
1718        }
1719        ////////////////////
1720      case WRITE_WAIT:  // release the lock protecting TRT
1721        { 
1722          r_write_fsm = WRITE_DIR_LOCK;
1723          break;
1724        }
1725        ///////////////////
1726      case WRITE_TRT_SET:       // register a new transaction in TRT (Write Buffer)
1727        { 
1728          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) 
1729          {
1730            std::vector<be_t> be_vector;
1731            std::vector<data_t> data_vector;
1732            be_vector.clear();
1733            data_vector.clear();
1734            for ( size_t i=0; i<m_words; i++ ) 
1735            {
1736              be_vector.push_back(r_write_be[i]);
1737              data_vector.push_back(r_write_data[i]);
1738            }
1739            m_transaction_tab.set(r_write_trt_index.read(),
1740                true,                           // read request to XRAM
1741                m_nline[(vci_addr_t)(r_write_address.read())],
1742                r_write_srcid.read(),
1743                r_write_trdid.read(),
1744                r_write_pktid.read(),
1745                false,                          // not a processor read
1746                0,                              // not a single word
1747                0,                              // word index
1748                be_vector,
1749                data_vector);
1750#ifdef TDEBUG
1751            TRACE_MSG(m_log << m_total_cycles << " " << name() << " WRITE_TRT_SET transaction table : " << std::endl);
1752            DUMP_TRANSACTION_TABLE;
1753#endif
1754
1755            r_write_fsm = WRITE_XRAM_REQ;
1756          }
1757          break;
1758        } 
1759        ///////////////////
1760      case WRITE_TRT_DATA:      // update an entry in TRT (Write Buffer)
1761        { 
1762          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
1763            std::vector<be_t> be_vector;
1764            std::vector<data_t> data_vector;
1765            be_vector.clear();
1766            data_vector.clear();
1767            for ( size_t i=0; i<m_words; i++ ) {
1768              be_vector.push_back(r_write_be[i]);
1769              data_vector.push_back(r_write_data[i]);
1770            }
1771            m_transaction_tab.write_data_mask(r_write_trt_index.read(),
1772                be_vector,
1773                data_vector);
1774            r_write_fsm = WRITE_RSP;
1775#ifdef TDEBUG
1776            TRACE_MSG(m_log << m_total_cycles << " " << name() << " WRITE_TRT_DATA transaction table : " << std::endl);
1777             
1778            DUMP_TRANSACTION_TABLE;
1779#endif
1780
1781          }
1782          break;
1783        }
1784        ////////////////////
1785      case WRITE_XRAM_REQ:      // send a request to IXR_CMD FSM
1786        { 
1787
1788          if ( !r_write_to_ixr_cmd_req ) {
1789            r_write_to_ixr_cmd_req   = true;
1790            r_write_to_ixr_cmd_write = false;
1791            r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
1792            r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
1793            r_write_fsm              = WRITE_RSP;
1794          }
1795          break;
1796        }
1797        ////////////////////
1798      case WRITE_TRT_WRITE_LOCK:
1799        {
1800          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) {
1801            size_t wok_index = 0;
1802            bool wok = !m_transaction_tab.full(wok_index);
1803            if ( wok ) {        // set a new entry in TRT
1804              r_write_trt_index = wok_index;
1805              r_write_fsm       = WRITE_INVAL_LOCK;
1806            } else {            // wait an empty entry in TRT
1807              r_write_fsm       = WRITE_WAIT;
1808            }
1809          }
1810
1811          break;
1812        }
1813        ////////////////////
1814      case WRITE_INVAL_LOCK:
1815        {
1816          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) {
1817            bool        wok       = false;
1818            size_t      index     = 0;
1819            size_t      srcid     = r_write_srcid.read();
1820            size_t      trdid     = r_write_trdid.read();
1821            size_t      pktid     = r_write_pktid.read();
1822            addr_t          nline     = m_nline[(vci_addr_t)(r_write_address.read())];
1823            size_t      nb_copies = r_write_count.read();
1824
1825            wok =m_update_tab.set(false,        // it's an inval transaction
1826                true,                       // it's a broadcast
1827                true,                       // it needs a response
1828                srcid,
1829                trdid,
1830                pktid,
1831                nline,
1832                nb_copies,
1833                index);
1834#ifdef IDEBUG
1835            if(wok){
1836       
1837                TRACE_MSG(m_log << 
1838                          m_total_cycles << " " << name() 
1839                          << " WRITE_INVAL_LOCK update table : " 
1840                          << std::endl);
1841
1842                DUMP_UPDATE_TABLE;   
1843            }
1844#endif
1845            r_write_upt_index = index;
1846            //  releases the lock protecting Update Table if no entry...
1847            if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
1848            else       r_write_fsm = WRITE_WAIT;
1849          }
1850
1851          break;
1852        }
1853        ////////////////////
1854      case WRITE_DIR_INVAL:
1855        {
1856            assert(((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE ) &&
1857                    (r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE ) &&
1858                    (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE ))&&
1859                    "MemCache ERROR : bad TRT,DIR or UPT allocation error");
1860            m_transaction_tab.set(r_write_trt_index.read(),
1861                false,                          // write request to XRAM
1862                m_nline[(vci_addr_t)(r_write_address.read())],
1863                0,
1864                0,
1865                0,
1866                false,                          // not a processor read
1867                0,                              // not a single word
1868                0,                              // word index
1869                std::vector<be_t>(m_words,0),
1870                std::vector<data_t>(m_words,0));
1871#ifdef TDEBUG
1872            TRACE_MSG(m_log << m_total_cycles
1873                      << " " << name() << " WRITE_DIR_INVAL transaction table : " << std::endl);
1874
1875            DUMP_TRANSACTION_TABLE;
1876#endif
1877
1878            // invalidate directory entry
1879            DirectoryEntry entry;
1880            entry.valid         = false;
1881            entry.dirty         = false;
1882            entry.tag           = 0;
1883            entry.is_cnt        = false;
1884            entry.lock          = false;
1885            entry.inst          = false;
1886            entry.owner.srcid   = 0;
1887            entry.owner.inst    = false;
1888            entry.ptr           = 0;
1889            entry.count         = 0;
1890            size_t set          = m_y[(vci_addr_t)(r_write_address.read())];
1891            size_t way          = r_write_way.read();
1892            m_cache_directory.write(set, way, entry);
1893
1894            r_write_fsm = WRITE_INVAL;
1895            break;
1896        }
1897        ////////////////////
1898      case WRITE_INVAL:
1899        {
1900          if (  !r_write_to_init_cmd_multi_req.read() &&
1901                !r_write_to_init_cmd_brdcast_req.read() ) {
1902            r_write_to_init_cmd_multi_req   = false;
1903            r_write_to_init_cmd_brdcast_req = true;
1904            r_write_to_init_cmd_trdid       = r_write_upt_index.read();
1905            r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
1906            r_write_to_init_cmd_index       = 0;
1907            r_write_to_init_cmd_count       = 0;
1908
1909            for(size_t i=0; i<m_words ; i++){
1910              r_write_to_init_cmd_we[i]=false;
1911              r_write_to_init_cmd_data[i] = 0;
1912            }
1913            r_write_fsm = WRITE_XRAM_SEND;
1914            // all inval responses
1915          }
1916
1917          break;
1918        }
1919        ////////////////////
1920      case WRITE_XRAM_SEND:
1921        {
1922          if ( !r_write_to_ixr_cmd_req ) {
1923            r_write_to_ixr_cmd_req     = true;
1924            r_write_to_ixr_cmd_write   = true;
1925            r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
1926            r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
1927            for(size_t i=0; i<m_words; i++){
1928              r_write_to_ixr_cmd_data[i] = r_write_data[i];
1929            }
1930            if(  r_write_is_cnt.read() ||
1931                ((!r_write_is_cnt.read()) && (r_write_count.read()==1)) ){
1932              r_write_fsm = WRITE_IDLE;
1933            } else {
1934              r_write_fsm = WRITE_HEAP_ERASE;
1935              r_write_next_ptr = r_write_ptr.read();
1936            }
1937          }
1938          break;
1939        }
1940        ////////////////////
1941      case WRITE_HEAP_ERASE:
1942        {
1943          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE){
1944            HeapEntry next_entry = m_heap_directory.read(r_write_next_ptr.read());
1945            if( next_entry.next == r_write_next_ptr.read()){
1946              r_write_fsm = WRITE_HEAP_LAST;
1947            } else {
1948              r_write_next_ptr = next_entry.next;
1949              r_write_fsm = WRITE_HEAP_ERASE;
1950            }
1951          }
1952          break;
1953        }
1954        ////////////////////
1955      case WRITE_HEAP_LAST:
1956        {
1957          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE) &&
1958                  "MemCache ERROR : bad HEAP allocation");
1959          size_t free_pointer = m_heap_directory.next_free_ptr();
1960
1961          HeapEntry last_entry;
1962          last_entry.owner.srcid = 0;
1963          last_entry.owner.inst  = false;
1964          if(m_heap_directory.is_full()){
1965            last_entry.next     = r_write_next_ptr.read();
1966            m_heap_directory.unset_full();
1967          } else {
1968            last_entry.next     = free_pointer;
1969          }
1970
1971          m_heap_directory.write_free_ptr(r_write_ptr.read());
1972          m_heap_directory.write(r_write_next_ptr.read(),last_entry);
1973
1974          r_write_fsm = WRITE_IDLE;
1975          break;
1976        }
1977    } // end switch r_write_fsm
1978
1979    ///////////////////////////////////////////////////////////////////////
1980    //          IXR_CMD FSM
1981    ///////////////////////////////////////////////////////////////////////
1982    // The IXR_CMD fsm controls the command packets to the XRAM :
1983    // - It sends a single cell VCI read to the XRAM in case of MISS request
1984    // posted by the READ, WRITE or LLSC FSMs : the TRDID field contains
1985    // the Transaction Tab index.
1986    // The VCI response is a multi-cell packet : the N cells contain
1987    // the N data words.
1988    // - It sends a multi-cell VCI write when the XRAM_RSP FSM request
1989    // to save a dirty line to the XRAM.
1990    // The VCI response is a single cell packet.
1991    // This FSM handles requests from the READ, WRITE, LLSC & XRAM_RSP FSMs
1992    // with a round-robin priority.
1993    ////////////////////////////////////////////////////////////////////////
1994
1995    switch ( r_ixr_cmd_fsm.read() ) {
1996      ////////////////////////
1997      case IXR_CMD_READ_IDLE:
1998        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
1999        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
2000        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2001        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2002        break;
2003        ////////////////////////
2004      case IXR_CMD_WRITE_IDLE:
2005        if      ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
2006        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2007        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2008        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2009        break;
2010        ////////////////////////
2011      case IXR_CMD_LLSC_IDLE:
2012        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2013        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2014        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2015        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
2016        break;
2017        ////////////////////////
2018      case IXR_CMD_XRAM_IDLE:
2019        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2020        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2021        else if ( r_llsc_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_LLSC_NLINE;
2022        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2023        break;
2024        /////////////////////////
2025      case IXR_CMD_READ_NLINE:
2026        if ( p_vci_ixr.cmdack ) {
2027          r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;           
2028          r_read_to_ixr_cmd_req = false;
2029        }
2030        break;
2031        //////////////////////////
2032      case IXR_CMD_WRITE_NLINE:
2033        if ( p_vci_ixr.cmdack ) {
2034          if( r_write_to_ixr_cmd_write.read()){
2035            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
2036              r_ixr_cmd_cpt = 0;
2037              r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2038              r_write_to_ixr_cmd_req = false;
2039            } else {
2040              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2041            }
2042          } else {
2043            r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;         
2044            r_write_to_ixr_cmd_req = false;
2045          }
2046        }
2047        break;
2048        /////////////////////////
2049      case IXR_CMD_LLSC_NLINE:
2050        if ( p_vci_ixr.cmdack ) {
2051          if( r_llsc_to_ixr_cmd_write.read()){
2052            if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
2053              r_ixr_cmd_cpt = 0;
2054              r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;
2055              r_llsc_to_ixr_cmd_req = false;
2056            } else {
2057              r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2058            }
2059          } else {
2060            r_ixr_cmd_fsm = IXR_CMD_LLSC_IDLE;         
2061            r_llsc_to_ixr_cmd_req = false;
2062          }
2063        }
2064        break;
2065        ////////////////////////
2066      case IXR_CMD_XRAM_DATA:
2067        if ( p_vci_ixr.cmdack ) {
2068          if ( r_ixr_cmd_cpt.read() == (m_words - 1) ) {
2069            r_ixr_cmd_cpt = 0;
2070            r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
2071            r_xram_rsp_to_ixr_cmd_req = false;
2072          } else {
2073            r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2074          }
2075        }
2076        break;
2077
2078    } // end switch r_ixr_cmd_fsm
2079
2080    ////////////////////////////////////////////////////////////////////////////
2081    //                IXR_RSP FSM
2082    ////////////////////////////////////////////////////////////////////////////
2083    // The IXR_RSP FSM receives the response packets from the XRAM,
2084    // for both write transaction, and read transaction.
2085    //
2086    // - A response to a write request is a single-cell VCI packet.
2087    // The Transaction Tab index is contained in the RTRDID field.
2088    // The FSM takes the lock protecting the TRT, and the corresponding
2089    // entry is erased.
2090    // 
2091    // - A response to a read request is a multi-cell VCI packet.
2092    // The Transaction Tab index is contained in the RTRDID field.
2093    // The N cells contain the N words of the cache line in the RDATA field.
2094    // The FSM takes the lock protecting the TRT to store the line in the TRT
2095    // (taking into account the write requests already stored in the TRT).
2096    // When the line is completely written, the corresponding rok signal is set.
2097    ///////////////////////////////////////////////////////////////////////////////
2098
2099    switch ( r_ixr_rsp_fsm.read() ) {
2100
2101      ///////////////////
2102      case IXR_RSP_IDLE:        // test if it's a read or a write transaction
2103        {
2104          if ( p_vci_ixr.rspval ) {
2105            r_ixr_rsp_cpt   = 0;
2106            r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
2107            if ( p_vci_ixr.reop )  r_ixr_rsp_fsm = IXR_RSP_ACK;
2108            else                   r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
2109          }
2110          break; 
2111        }
2112        ////////////////////////
2113      case IXR_RSP_ACK:        // Acknowledge the vci response
2114        r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
2115        break;
2116        ////////////////////////
2117      case IXR_RSP_TRT_ERASE:   // erase the entry in the TRT
2118        {
2119          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP ) {
2120            m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
2121            r_ixr_rsp_fsm = IXR_RSP_IDLE;
2122
2123#ifdef TDEBUG           
2124            TRACE_MSG(m_log << m_total_cycles << " " << name() << " IXR_RSP_TRT_ERASE transaction table : " << std::endl);
2125            DUMP_TRANSACTION_TABLE;
2126#endif
2127
2128          }
2129          break;
2130        }
2131        ///////////////////////
2132      case IXR_RSP_TRT_READ:            // write data in the TRT
2133        {
2134          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval ) {
2135            bool   eop          = p_vci_ixr.reop.read();
2136            data_t data         = p_vci_ixr.rdata.read();
2137            size_t index        = r_ixr_rsp_trt_index.read();
2138            assert( eop == (r_ixr_rsp_cpt.read() == (m_words-1)) 
2139                && "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
2140
2141
2142            if(m_total_cycles > m_debug_start)
2143            {
2144                m_log << "[ " << std::dec << m_total_cycles << " ]"
2145                      << " " << name() << " m_srcid_ini " << m_srcid_ini
2146                      << " IXR_RSP_TRT_READ: calling write_rsp with [i:" 
2147                      << index
2148                      << ",cntr:"
2149                      << r_ixr_rsp_cpt.read()
2150                      << ",data:" << std::hex
2151                      << data << "]" << std::dec << std::endl;
2152            }
2153
2154            m_transaction_tab.write_rsp(index, r_ixr_rsp_cpt.read(), data);
2155
2156            if(m_total_cycles > m_debug_start)
2157            {
2158                m_log << std::dec << m_total_cycles
2159                      << " " << name()
2160                      << " Done" << std::endl;
2161            }
2162
2163            r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
2164
2165            if ( eop ) {
2166#ifdef TDEBUG
2167                TRACE_MSG(m_log << m_total_cycles << " " << name() << " IXR_RSP_TRT_READ transaction table : " << std::endl);
2168                DUMP_TRANSACTION_TABLE;
2169#endif
2170
2171              r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
2172              r_ixr_rsp_fsm = IXR_RSP_IDLE;
2173            }
2174          }
2175          break;
2176        }
2177    } // end swich r_ixr_rsp_fsm
2178
2179
2180    ////////////////////////////////////////////////////////////////////////////
2181    //                XRAM_RSP FSM
2182    ////////////////////////////////////////////////////////////////////////////
2183    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
2184    // The cache line has been written in the TRT buffer by the IXR_FSM.
2185    //
2186    // When a response is available, the corresponding TRT entry
2187    // is copied in a local buffer to be written in the cache.
2188    // Then, the FSM releases the lock protecting the TRT, and takes the lock
2189    // protecting the cache directory.
2190    // It selects a cache slot and writes the line in the cache.
2191    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
2192    // FSM to return the cache line to the registered processor.
2193    // If there is no empty slot, a victim line is evicted, and
2194    // invalidate requests are sent to the L1 caches containing copies.
2195    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
2196    // FSM to save the victim line to the XRAM, and register the write transaction
2197    // in the TRT (using the entry previously used by the read transaction).
2198    ///////////////////////////////////////////////////////////////////////////////
2199
2200    switch ( r_xram_rsp_fsm.read() ) {
2201
2202      ///////////////////
2203      case XRAM_RSP_IDLE:       // test if there is a response with a round robin priority
2204        {
2205          size_t ptr   = r_xram_rsp_trt_index.read();
2206          size_t lines = TRANSACTION_TAB_LINES;
2207          for(size_t i=0; i<lines; i++){
2208            size_t index=(i+ptr+1)%lines;
2209            if(r_ixr_rsp_to_xram_rsp_rok[index]){
2210              r_xram_rsp_trt_index=index;
2211              r_ixr_rsp_to_xram_rsp_rok[index]=false;
2212              r_xram_rsp_fsm           = XRAM_RSP_DIR_LOCK;
2213              break;
2214
2215#ifdef TDEBUG
2216              TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_IDLE state" << std::endl);
2217#endif
2218            }
2219          }
2220          break; 
2221        }
2222        ///////////////////////
2223      case XRAM_RSP_DIR_LOCK:   // Take the lock on the directory
2224        {
2225          if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) {
2226            r_xram_rsp_fsm           = XRAM_RSP_TRT_COPY;
2227#ifdef TDEBUG
2228            TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_DIR_LOCK state" << std::endl);
2229#endif
2230          }
2231          break;
2232        }
2233        ///////////////////////
2234      case XRAM_RSP_TRT_COPY:           // Copy the TRT entry in the local buffer and eviction of a cache line
2235        {
2236          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) ) {
2237            size_t index = r_xram_rsp_trt_index.read();
2238            TransactionTabEntry    trt_entry(m_transaction_tab.read(index));   
2239
2240            r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
2241
2242            // selects & extracts a victim line from cache
2243            size_t way = 0;
2244            size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
2245            DirectoryEntry victim(m_cache_directory.select(set, way));
2246
2247            for (size_t i=0 ; i<m_words ; i++) r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
2248
2249            bool inval = (victim.count && victim.valid) ;
2250
2251            r_xram_rsp_victim_copy      = victim.owner.srcid;
2252            r_xram_rsp_victim_copy_inst = victim.owner.inst;
2253            r_xram_rsp_victim_count     = victim.count;
2254            r_xram_rsp_victim_ptr       = victim.ptr;
2255            r_xram_rsp_victim_way       = way;
2256            r_xram_rsp_victim_set       = set;
2257            r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
2258            r_xram_rsp_victim_is_cnt    = victim.is_cnt;
2259            r_xram_rsp_victim_inval     = inval ;
2260            r_xram_rsp_victim_dirty     = victim.dirty;
2261
2262            r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
2263
2264#ifdef TDEBUG
2265            TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_TRT_COPY state" << std::endl);
2266            TRACE_MSG(m_log << "Victim way : " << std::hex << way << " set " << std::hex << set << std::endl);
2267            DUMP_ENTRY(victim);
2268#endif
2269          }
2270          break;
2271        }
2272        ///////////////////////
2273      case XRAM_RSP_INVAL_LOCK:
2274        {
2275          if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP ) 
2276          {
2277
2278#ifdef IDEBUG
2279              TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state, line = " 
2280                        << std::hex << r_xram_rsp_trt_buf.nline
2281                        << std::endl);
2282#endif
2283              size_t index;
2284             
2285              if(m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index))
2286              {
2287                  r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2288                 
2289#ifdef IDEBUG
2290                  TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl);
2291                  TRACE_MSG(m_log << "A invalidation is already registered at this address" << std::endl);
2292                 
2293                  DUMP_UPDATE_TABLE;
2294#endif
2295              }
2296              else if(m_update_tab.is_full() && r_xram_rsp_victim_inval.read())
2297              {
2298                  r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2299                 
2300#ifdef IDEBUG
2301                  TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_INVAL_WAIT state" << std::endl);
2302                  TRACE_MSG(m_log << "The inval tab is full" << std::endl);
2303
2304                  DUMP_UPDATE_TABLE;
2305#endif
2306              }
2307              else 
2308              {
2309                  r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
2310#ifdef IDEBUG
2311                  TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL_LOCK state to XRAM_RSP_DIR_UPDT state" << std::endl);
2312                  DUMP_UPDATE_TABLE;
2313#endif
2314              }
2315          }
2316          break;
2317        }
2318        ///////////////////////
2319      case XRAM_RSP_INVAL_WAIT:
2320        {
2321          r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
2322#ifdef IDEBUG
2323          TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL_WAIT state" << std::endl);
2324#endif
2325          break;
2326        }
2327        ///////////////////////
2328      case XRAM_RSP_DIR_UPDT:           // updates the cache (both data & directory)
2329        {
2330          // signals generation
2331          bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read; // It is an instruction read
2332          bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read ;
2333          // update data
2334          size_t set   = r_xram_rsp_victim_set.read();
2335          size_t way   = r_xram_rsp_victim_way.read();
2336          for(size_t i=0; i<m_words ; i++){
2337            m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
2338          }
2339          // compute dirty
2340          bool dirty = false;
2341          for(size_t i=0; i<m_words;i++){
2342            dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
2343          }
2344
2345          // update directory
2346          DirectoryEntry entry;
2347          entry.valid     = true;
2348          entry.is_cnt    = false;
2349          entry.lock      = false;
2350          entry.dirty     = dirty;
2351          entry.tag           = r_xram_rsp_trt_buf.nline / m_sets;
2352          entry.ptr       = 0;
2353          if(cached_read) {
2354            if(inst_read) {
2355              entry.inst        = true;
2356              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
2357              entry.owner.inst  = true;
2358              entry.count       = 1;
2359            } else {
2360              entry.inst        = false;
2361              entry.owner.srcid = r_xram_rsp_trt_buf.srcid;
2362              entry.owner.inst  = false;
2363              entry.count       = 1;
2364            }
2365          } else {
2366            entry.owner.srcid = 0;
2367            entry.owner.inst  = 0;
2368            entry.inst        = false;
2369            entry.count       = 0;
2370          }
2371          m_cache_directory.write(set, way, entry);
2372#ifdef DDEBUG
2373          TRACE_MSG(m_log << "printing the entry : " << std::endl);
2374          DUMP_ENTRY(entry);
2375          TRACE_MSG(m_log << "done" << std::endl);
2376#endif
2377
2378#ifdef TDEBUG
2379          TRACE_MSG(m_log << m_total_cycles << " " << name() << " XRAM_RSP_DIR_UPDT transaction table : " << std::endl);
2380          DUMP_TRANSACTION_TABLE;
2381#endif
2382
2383          if(r_xram_rsp_victim_inval.read()){
2384            bool    brdcast = r_xram_rsp_victim_is_cnt.read();
2385            size_t index;
2386            size_t count_copies = r_xram_rsp_victim_count.read();
2387
2388            bool         wok = m_update_tab.set(false,  // it's an inval transaction
2389                                            brdcast,                          // set brdcast bit
2390                                            false,  // it does not need a response
2391                                            0,
2392                                            0,
2393                                            0,
2394                                            r_xram_rsp_victim_nline.read(),
2395                                            count_copies,
2396                                            index);
2397
2398#ifdef IDEBUG
2399            TRACE_MSG(m_log << "xram_rsp : record invalidation, time = " << std::dec << m_cpt_cycles << std::endl);
2400           
2401            DUMP_UPDATE_TABLE;
2402#endif
2403            r_xram_rsp_upt_index = index;
2404            if(!wok) {
2405              assert(false && "mem_cache error : xram_rsp_dir_upt, an update_tab entry was free but write unsuccessful");
2406            }
2407          }
2408          // If the victim is not dirty, we erase the entry in the TRT
2409          if      (!r_xram_rsp_victim_dirty.read()){
2410              m_transaction_tab.erase(r_xram_rsp_trt_index.read());
2411
2412          }
2413          // Next state
2414          if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
2415          else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
2416          else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
2417          else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
2418          break;
2419        }
2420        ////////////////////////
2421      case XRAM_RSP_TRT_DIRTY:          // set the TRT entry (write line to XRAM) if the victim is dirty
2422        {
2423          if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ) {
2424            m_transaction_tab.set(r_xram_rsp_trt_index.read(),
2425                false,                          // write to XRAM
2426                r_xram_rsp_victim_nline.read(), // line index
2427                0,
2428                0,
2429                0,
2430                false,
2431                0,
2432                0,
2433                std::vector<be_t>(m_words,0),
2434                std::vector<data_t>(m_words,0) );
2435#ifdef TDEBUG
2436            TRACE_MSG(m_log << m_total_cycles << " " << name() << " XRAM_RSP_TRT_DIRTY transaction table : " << std::endl);
2437            DUMP_TRANSACTION_TABLE;
2438#endif
2439
2440            if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
2441            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
2442            else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
2443          }
2444          break;
2445        }
2446        //////////////////////
2447      case XRAM_RSP_DIR_RSP:     // send a request to TGT_RSP FSM in case of read
2448        {
2449          if ( !r_xram_rsp_to_tgt_rsp_req.read() ) {
2450            r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
2451            r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
2452            r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
2453            for (size_t i=0; i < m_words; i++) {
2454              r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
2455            } 
2456            r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
2457            r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
2458            r_xram_rsp_to_tgt_rsp_req    = true;
2459
2460            if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
2461            else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY; 
2462            else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
2463
2464#ifdef DDEBUG
2465            TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_DIR_RSP state" << std::endl);
2466#endif
2467          }
2468          break;
2469        }
2470        ////////////////////
2471      case XRAM_RSP_INVAL:      // send invalidate request to INIT_CMD FSM
2472        {
2473          if(   !r_xram_rsp_to_init_cmd_multi_req.read() && 
2474                !r_xram_rsp_to_init_cmd_brdcast_req.read() ) {       
2475           
2476            bool multi_req = !r_xram_rsp_victim_is_cnt.read();
2477            bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
2478            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
2479
2480            r_xram_rsp_to_init_cmd_multi_req    = last_multi_req; 
2481            r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
2482            r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
2483            r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
2484            xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
2485            xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
2486            xram_rsp_to_init_cmd_fifo_put       = multi_req;
2487           
2488            r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
2489
2490            if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
2491            else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2492            else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
2493#ifdef IDEBUG
2494            TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_INVAL state" << std::endl);
2495#endif
2496          }
2497          break;
2498        }
2499        //////////////////////////
2500      case XRAM_RSP_WRITE_DIRTY:        // send a write request to IXR_CMD FSM
2501        {
2502          if ( !r_xram_rsp_to_ixr_cmd_req.read() ) {
2503            r_xram_rsp_to_ixr_cmd_req = true;
2504            r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
2505            r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
2506            for(size_t i=0; i<m_words ; i++) {
2507              r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
2508            }
2509            m_cpt_write_dirty++;
2510            bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
2511            bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
2512            if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2513            else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
2514#ifdef TDEBUG
2515            TRACE_MSG(m_log << "XRAM_RSP FSM in XRAM_RSP_WRITE_DIRTY state" << std::endl);
2516#endif
2517          }
2518          break;
2519        }
2520        //////////////////////////
2521      case XRAM_RSP_HEAP_ERASE: // erase the list of copies and sent invalidations
2522        {
2523          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP ) {
2524            HeapEntry entry = m_heap_directory.read(r_xram_rsp_next_ptr.read());
2525            xram_rsp_to_init_cmd_fifo_srcid = entry.owner.srcid;
2526            xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
2527            xram_rsp_to_init_cmd_fifo_put   = true;
2528            if( m_xram_rsp_to_init_cmd_inst_fifo.wok() ){
2529              r_xram_rsp_next_ptr = entry.next;
2530              if( entry.next == r_xram_rsp_next_ptr.read() ){ // last copy
2531                r_xram_rsp_to_init_cmd_multi_req = true;
2532                r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
2533              } else {
2534                r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2535              }
2536            } else {
2537              r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2538            }
2539          }
2540          break;
2541        }
2542        //////////////////////////
2543      case XRAM_RSP_HEAP_LAST:  // last member of the list
2544        {
2545          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP) &&
2546                  "MemCache ERROR : bad HEAP allocation");
2547          size_t free_pointer = m_heap_directory.next_free_ptr();
2548
2549          HeapEntry last_entry;
2550          last_entry.owner.srcid = 0;
2551          last_entry.owner.inst  = false;
2552          if(m_heap_directory.is_full()){
2553            last_entry.next     = r_xram_rsp_next_ptr.read();
2554            m_heap_directory.unset_full();
2555          } else {
2556            last_entry.next     = free_pointer;
2557          }
2558
2559          m_heap_directory.write_free_ptr(r_xram_rsp_victim_ptr.read());
2560          m_heap_directory.write(r_xram_rsp_next_ptr.read(),last_entry);
2561
2562          r_xram_rsp_fsm = XRAM_RSP_IDLE;
2563
2564          break;
2565        }
2566    } // end swich r_xram_rsp_fsm
2567
2568    ////////////////////////////////////////////////////////////////////////////////////
2569    //          CLEANUP FSM
2570    ////////////////////////////////////////////////////////////////////////////////////
2571    // The CLEANUP FSM handles the cleanup request from L1 caches.
2572    // It accesses the cache directory to update the list of copies.
2573    //
2574    ////////////////////////////////////////////////////////////////////////////////////
2575    switch ( r_cleanup_fsm.read() ) {
2576
2577      ///////////////////
2578      case CLEANUP_IDLE:
2579        {
2580
2581          if ( p_vci_tgt_cleanup.cmdval.read() ) {
2582            assert( (p_vci_tgt_cleanup.srcid.read() < m_initiators) &&
2583                "VCI_MEM_CACHE error in VCI_MEM_CACHE in the CLEANUP network : The received SRCID is larger than the number of initiators");
2584            bool reached = false;
2585            for ( size_t index = 0 ; index < ncseg && !reached ; index++ ){
2586              if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) ){
2587                reached = true;
2588              }
2589            }
2590            if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
2591                (((addr_t)(p_vci_tgt_cleanup.address.read())&0x3) != 0x3) &&
2592                reached) {
2593
2594              m_cpt_cleanup++;
2595
2596              r_cleanup_nline      = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]) ;
2597              r_cleanup_srcid      = p_vci_tgt_cleanup.srcid.read();
2598              r_cleanup_trdid      = p_vci_tgt_cleanup.trdid.read();
2599              r_cleanup_pktid      = p_vci_tgt_cleanup.pktid.read();
2600
2601              r_cleanup_fsm        = CLEANUP_DIR_LOCK;
2602            }
2603          }
2604          break;
2605        }
2606        //////////////////////
2607      case CLEANUP_DIR_LOCK:
2608        {
2609          if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) {
2610
2611            // Read the directory
2612            size_t way = 0;
2613           addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
2614           DirectoryEntry entry = m_cache_directory.read(cleanup_address , way);
2615#ifdef DDEBUG
2616           TRACE_MSG(m_log << "In CLEANUP_DIR_LOCK printing the entry of address is : " << std::hex << cleanup_address << std::endl);
2617           DUMP_ENTRY(entry);
2618           TRACE_MSG(m_log << "done" << std::endl);
2619#endif
2620            r_cleanup_is_cnt    = entry.is_cnt;
2621            r_cleanup_dirty         = entry.dirty;
2622            r_cleanup_tag           = entry.tag;
2623            r_cleanup_lock          = entry.lock;
2624            r_cleanup_inst      = entry.inst;
2625            r_cleanup_way           = way;
2626            r_cleanup_copy      = entry.owner.srcid;
2627            r_cleanup_copy_inst = entry.owner.inst;
2628            r_cleanup_count     = entry.count;
2629            r_cleanup_ptr       = entry.ptr;
2630
2631
2632            // In case of hit, the copy must be cleaned in the copies bit-vector
2633            if( entry.valid){
2634              if ( (entry.count==1) || (entry.is_cnt) )  { // no access to the heap
2635                r_cleanup_fsm = CLEANUP_DIR_WRITE;
2636              } else {
2637                r_cleanup_fsm = CLEANUP_HEAP_LOCK;
2638              }
2639            } else {
2640              r_cleanup_fsm = CLEANUP_UPT_LOCK;
2641            }
2642          }
2643          break;
2644        }
2645        ///////////////////////
2646      case CLEANUP_DIR_WRITE:
2647        {
2648          assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP ) && 
2649                "MemCache ERROR : Bad DIR allocation");
2650          size_t way      = r_cleanup_way.read();
2651#define L2 soclib::common::uint32_log2
2652          size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
2653#undef L2
2654          bool cleanup_inst  = r_cleanup_trdid.read() & 0x1; 
2655          bool match_srcid   = (r_cleanup_copy.read() == r_cleanup_srcid.read());
2656          bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
2657          bool match         = match_srcid && match_inst;
2658
2659          // update the cache directory (for the copies)
2660          DirectoryEntry entry;
2661          entry.valid   = true;
2662          entry.is_cnt  = r_cleanup_is_cnt.read();
2663          entry.dirty   = r_cleanup_dirty.read();
2664          entry.tag         = r_cleanup_tag.read();
2665          entry.lock    = r_cleanup_lock.read();
2666          entry.ptr     = r_cleanup_ptr.read();
2667          if(r_cleanup_is_cnt.read()) { // Directory is a counter
2668            entry.count  = r_cleanup_count.read() -1;
2669            if((r_cleanup_count.read()-1) == 0){
2670              entry.inst    = false;
2671            } else {
2672              entry.inst    = r_cleanup_inst.read();
2673            }
2674            entry.owner.srcid = 0;
2675            entry.owner.inst  = 0;
2676            // response to the cache
2677            r_cleanup_fsm = CLEANUP_RSP;
2678          }
2679          else{                         // Directory is a list
2680            if(match) { // hit
2681              entry.count       = 0; // no more copy
2682              entry.owner.srcid = 0;
2683              entry.owner.inst  = 0;
2684              entry.inst        = false;
2685              r_cleanup_fsm     = CLEANUP_RSP; 
2686            } else { // miss
2687              entry.count       = r_cleanup_count.read();
2688              entry.owner.srcid = r_cleanup_copy.read();
2689              entry.owner.inst  = r_cleanup_copy_inst.read();
2690              entry.inst        = r_cleanup_inst.read();
2691              r_cleanup_fsm     = CLEANUP_UPT_LOCK;
2692            }
2693          }
2694          m_cache_directory.write(set, way, entry); 
2695
2696          break;
2697        }
2698        /////////////////
2699      case CLEANUP_HEAP_LOCK:
2700        {
2701          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP){
2702            size_t way      = r_cleanup_way.read();
2703#define L2 soclib::common::uint32_log2
2704            size_t set      = m_y[(vci_addr_t)(r_cleanup_nline.read() << (L2(m_words) +2))];
2705#undef L2
2706            HeapEntry heap_entry = m_heap_directory.read(r_cleanup_ptr.read());
2707            bool last = (heap_entry.next == r_cleanup_ptr.read());
2708            bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
2709            bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
2710            bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
2711            bool match_dir          = match_dir_srcid && match_dir_inst;
2712            bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
2713            bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
2714            bool match_heap         = match_heap_srcid && match_heap_inst;
2715
2716            r_cleanup_prev_ptr = r_cleanup_ptr.read();
2717            r_cleanup_prev_srcid = heap_entry.owner.srcid;
2718            r_cleanup_prev_inst  = heap_entry.owner.inst;
2719
2720            if(match_dir){
2721              DirectoryEntry dir_entry;
2722              dir_entry.valid       = true;
2723              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
2724              dir_entry.dirty       = r_cleanup_dirty.read();
2725              dir_entry.tag             = r_cleanup_tag.read();
2726              dir_entry.lock        = r_cleanup_lock.read();
2727              dir_entry.ptr         = heap_entry.next;
2728              dir_entry.count       = r_cleanup_count.read()-1;
2729              dir_entry.owner.srcid = heap_entry.owner.srcid;
2730              dir_entry.owner.inst  = heap_entry.owner.inst;
2731              dir_entry.inst        = r_cleanup_inst.read();
2732              m_cache_directory.write(set,way,dir_entry);
2733              r_cleanup_next_ptr    = r_cleanup_ptr.read();
2734              r_cleanup_fsm         = CLEANUP_HEAP_FREE;
2735            }
2736            else if(match_heap){
2737              DirectoryEntry dir_entry;
2738              dir_entry.valid       = true;
2739              dir_entry.is_cnt      = r_cleanup_is_cnt.read();
2740              dir_entry.dirty       = r_cleanup_dirty.read();
2741              dir_entry.tag             = r_cleanup_tag.read();
2742              dir_entry.lock        = r_cleanup_lock.read();
2743              dir_entry.ptr         = heap_entry.next;
2744              dir_entry.count       = r_cleanup_count.read()-1;
2745              dir_entry.owner.srcid = r_cleanup_copy.read();
2746              dir_entry.owner.inst  = r_cleanup_copy_inst.read();
2747              dir_entry.inst        = r_cleanup_inst.read();
2748              m_cache_directory.write(set,way,dir_entry);
2749              r_cleanup_next_ptr    = r_cleanup_ptr.read();
2750              r_cleanup_fsm         = CLEANUP_HEAP_FREE; 
2751            }
2752            else{
2753              if(!last){
2754                DirectoryEntry dir_entry;
2755                dir_entry.valid         = true;
2756                dir_entry.is_cnt        = r_cleanup_is_cnt.read();
2757                dir_entry.dirty         = r_cleanup_dirty.read();
2758                dir_entry.tag           = r_cleanup_tag.read();
2759                dir_entry.lock          = r_cleanup_lock.read();
2760                dir_entry.ptr           = r_cleanup_ptr.read();
2761                dir_entry.count         = r_cleanup_count.read()-1;
2762                dir_entry.owner.srcid   = r_cleanup_copy.read();
2763                dir_entry.owner.inst    = r_cleanup_copy_inst.read();
2764                dir_entry.inst          = r_cleanup_inst.read();
2765                m_cache_directory.write(set,way,dir_entry);
2766
2767                r_cleanup_next_ptr = heap_entry.next;
2768                r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
2769
2770              } else{
2771                assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
2772              }
2773            }
2774          }
2775          break;
2776        }
2777        /////////////////
2778      case CLEANUP_HEAP_SEARCH:
2779        {
2780          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
2781                    "MemCache ERROR : bad HEAP allocation");
2782          HeapEntry heap_entry = m_heap_directory.read(r_cleanup_next_ptr.read());
2783          bool last = (heap_entry.next == r_cleanup_next_ptr.read());
2784          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1; 
2785          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
2786          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
2787          bool match_heap         = match_heap_srcid && match_heap_inst;
2788
2789          if(match_heap){
2790            r_cleanup_ptr           = heap_entry.next; // reuse ressources
2791            r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
2792          }
2793          else{
2794            if(last) {
2795              assert(false && "MemCache ERROR : CLEANUP hit but line not shared");
2796            } else {
2797              r_cleanup_prev_ptr = r_cleanup_next_ptr.read();
2798              r_cleanup_prev_srcid = heap_entry.owner.srcid;
2799              r_cleanup_prev_inst  = heap_entry.owner.inst;
2800              r_cleanup_next_ptr = heap_entry.next;
2801              r_cleanup_fsm      = CLEANUP_HEAP_SEARCH;
2802            }
2803          }
2804
2805          break;
2806        }
2807        /////////////////
2808      case CLEANUP_HEAP_CLEAN:
2809        {
2810          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
2811                    "MemCache ERROR : bad HEAP allocation");
2812          bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
2813          HeapEntry heap_entry; 
2814          heap_entry.owner.srcid = r_cleanup_prev_srcid.read();
2815          heap_entry.owner.inst  = r_cleanup_prev_inst.read();
2816          if(last){ // this is the last entry of the list of copies
2817            heap_entry.next     = r_cleanup_prev_ptr.read();
2818          } else { // this is not the last entry
2819            heap_entry.next     = r_cleanup_ptr.read();
2820          }
2821          m_heap_directory.write(r_cleanup_prev_ptr.read(),heap_entry);
2822          r_cleanup_fsm = CLEANUP_HEAP_FREE;
2823          break;
2824        }
2825        /////////////////
2826      case CLEANUP_HEAP_FREE:
2827        {
2828          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP) &&
2829                    "MemCache ERROR : bad HEAP allocation");
2830          HeapEntry heap_entry;
2831          heap_entry.owner.srcid = 0;
2832          heap_entry.owner.inst  = false;
2833          if(m_heap_directory.is_full()){
2834            heap_entry.next     = r_cleanup_next_ptr.read();
2835          } else {
2836            heap_entry.next     = m_heap_directory.next_free_ptr();
2837          }
2838          m_heap_directory.write(r_cleanup_next_ptr.read(),heap_entry);
2839          m_heap_directory.write_free_ptr(r_cleanup_next_ptr.read());
2840          m_heap_directory.unset_full();
2841          r_cleanup_fsm = CLEANUP_RSP;
2842          break;
2843        }
2844        /////////////////
2845      case CLEANUP_UPT_LOCK:
2846        {
2847          if( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
2848          {
2849            size_t index;
2850            bool hit_inval;
2851            hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
2852            if(!hit_inval) {
2853#ifdef DEBUG_VCI_MEM_CACHE
2854                TRACE_MSG(m_log << "MEM_CACHE WARNING: cleanup with no corresponding entry at address : " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::dec << std::endl);
2855#endif
2856              r_cleanup_fsm = CLEANUP_RSP;
2857            } else {
2858              r_cleanup_write_srcid = m_update_tab.srcid(index);
2859              r_cleanup_write_trdid = m_update_tab.trdid(index);
2860              r_cleanup_write_pktid = m_update_tab.pktid(index);
2861              r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
2862              r_cleanup_fsm = CLEANUP_UPT_WRITE;
2863            }
2864            r_cleanup_index.write(index) ; 
2865          }
2866          break;
2867        }
2868        /////////////////
2869      case CLEANUP_UPT_WRITE:
2870        {
2871          size_t count = 0;
2872          m_update_tab.decrement(r_cleanup_index.read(), count); // &count
2873          if(count == 0){
2874            m_update_tab.clear(r_cleanup_index.read());
2875#ifdef IDEBUG
2876            TRACE_MSG(m_log << m_total_cycles << " " << name() << " CLEANUP_UPT_WRITE update table : " << std::endl);
2877            DUMP_UPDATE_TABLE;
2878#endif
2879
2880            if(r_cleanup_need_rsp.read()){
2881              r_cleanup_fsm = CLEANUP_WRITE_RSP ;
2882            } else {
2883              r_cleanup_fsm = CLEANUP_RSP;
2884            }
2885          } else {
2886            r_cleanup_fsm = CLEANUP_RSP ;
2887          }
2888          break;
2889        }
2890        /////////////////
2891      case CLEANUP_WRITE_RSP:
2892        {
2893          if( !r_cleanup_to_tgt_rsp_req.read()) {
2894            r_cleanup_to_tgt_rsp_req     = true;
2895            r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
2896            r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
2897            r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
2898            r_cleanup_fsm = CLEANUP_RSP;
2899          }
2900          break;
2901        }
2902        /////////////////
2903      case CLEANUP_RSP:
2904        {
2905          if(p_vci_tgt_cleanup.rspack)
2906            r_cleanup_fsm = CLEANUP_IDLE;
2907          break;
2908        }
2909    } // end switch cleanup fsm
2910
2911
2912    ////////////////////////////////////////////////////////////////////////////////////
2913    //          LLSC FSM
2914    ////////////////////////////////////////////////////////////////////////////////////
2915    // The LLSC FSM handles the LL & SC atomic access.
2916    //
2917    // For a LL :
2918    // It access the directory to check hit / miss.
2919    // - In case of hit, the LL request is registered in the Atomic Table and the
2920    // response is sent to the requesting processor.
2921    // - In case of miss, the LLSC FSM accesses the transaction table.
2922    // If a read transaction to the XRAM for this line already exists,
2923    // or if the transaction table is full, it returns to IDLE state.
2924    // Otherwise, a new transaction to the XRAM is initiated.
2925    // In both cases, the LL request is not consumed in the FIFO.
2926    //
2927    // For a SC :
2928    // It access the directory to check hit / miss.
2929    // - In case of hit, the Atomic Table is checked and the proper response
2930    // (true or false is sent to the requesting processor.
2931    // - In case of miss, the LLSC FSM accesses the transaction table.
2932    // If a read transaction to the XRAM for this line already exists,
2933    // or if the transaction table is full, it returns to IDLE state.
2934    // Otherwise, a new transaction to the XRAM is initiated.
2935    // In both cases, the SC request is not consumed in the FIFO.
2936    /////////////////////////////////////////////////////////////////////
2937
2938    switch ( r_llsc_fsm.read() ) {
2939
2940      ///////////////
2941      case LLSC_IDLE:           // test LL / SC
2942        {
2943          if( m_cmd_llsc_addr_fifo.rok() ) {
2944            if(m_cmd_llsc_sc_fifo.read()){
2945              m_cpt_sc++;
2946              r_llsc_fsm = SC_DIR_LOCK;
2947            }
2948            else{
2949              m_cpt_ll++;
2950              r_llsc_fsm = LL_DIR_LOCK;
2951            }
2952          }     
2953          break;
2954        }
2955        /////////////////
2956      case LL_DIR_LOCK:         // check directory for hit / miss
2957        {
2958          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
2959            size_t way = 0;
2960            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
2961            r_llsc_is_cnt     = entry.is_cnt;
2962            r_llsc_dirty      = entry.dirty;
2963            r_llsc_inst       = entry.inst;
2964            r_llsc_tag        = entry.tag;
2965            r_llsc_way        = way;
2966            r_llsc_copy       = entry.owner.srcid;
2967            r_llsc_copy_inst  = entry.owner.inst;
2968            r_llsc_count      = entry.count;
2969            r_llsc_ptr        = entry.ptr;
2970
2971            // set Atomic Table
2972            m_atomic_tab.set(m_cmd_llsc_srcid_fifo.read(), m_cmd_llsc_addr_fifo.read());
2973
2974            if ( entry.valid )  r_llsc_fsm = LL_DIR_HIT;
2975            else                r_llsc_fsm = LLSC_TRT_LOCK;
2976          }
2977          break;
2978        }
2979        ////////////////
2980      case LL_DIR_HIT:          // read hit : update the memory cache
2981        {
2982          size_t way    = r_llsc_way.read();
2983          size_t set    = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
2984          size_t word   = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
2985
2986          // update directory (lock bit & copies)
2987          DirectoryEntry entry;
2988          entry.valid       = true;
2989          entry.is_cnt      = r_llsc_is_cnt.read();
2990          entry.dirty       = r_llsc_dirty.read();
2991          entry.lock        = true;
2992          entry.inst        = r_llsc_inst.read();
2993          entry.tag             = r_llsc_tag.read();
2994          entry.owner.srcid = r_llsc_copy.read();
2995          entry.owner.inst  = r_llsc_copy_inst.read();
2996          entry.count       = r_llsc_count.read();
2997          entry.ptr         = r_llsc_ptr.read();
2998          m_cache_directory.write(set, way, entry);
2999
3000          // read data in cache
3001          r_llsc_data   = m_cache_data[way][set][word];
3002
3003          r_llsc_fsm    = LL_RSP;
3004          break;
3005        }
3006        ////////////
3007      case LL_RSP:              // request the TGT_RSP FSM to return data
3008        {
3009          if ( !r_llsc_to_tgt_rsp_req ) {
3010            cmd_llsc_fifo_get           = true;
3011            r_llsc_to_tgt_rsp_data      = r_llsc_data.read();
3012            r_llsc_to_tgt_rsp_srcid     = m_cmd_llsc_srcid_fifo.read();
3013            r_llsc_to_tgt_rsp_trdid     = m_cmd_llsc_trdid_fifo.read();
3014            r_llsc_to_tgt_rsp_pktid     = m_cmd_llsc_pktid_fifo.read();
3015            r_llsc_to_tgt_rsp_req       = true;
3016            r_llsc_fsm = LLSC_IDLE;
3017          }
3018          break;
3019        }
3020        /////////////////
3021      case SC_DIR_LOCK:
3022        {
3023          if( r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ) {
3024            size_t way = 0;
3025            DirectoryEntry entry(m_cache_directory.read(m_cmd_llsc_addr_fifo.read(), way));
3026            bool ok = m_atomic_tab.isatomic(m_cmd_llsc_srcid_fifo.read(),m_cmd_llsc_addr_fifo.read());
3027            if( ok ) {
3028              r_llsc_is_cnt   = entry.is_cnt;
3029              r_llsc_dirty    = entry.dirty;
3030              r_llsc_tag      = entry.tag;
3031              r_llsc_way      = way;
3032              r_llsc_copy     = entry.owner.srcid;
3033              r_llsc_copy_inst= entry.owner.inst;
3034              r_llsc_inst     = entry.inst;
3035              r_llsc_ptr      = entry.ptr;
3036              r_llsc_count    = entry.count;
3037              if ( entry.valid ){
3038                if((entry.is_cnt && entry.count) || entry.inst) {
3039                  r_llsc_fsm = SC_TRT_LOCK;
3040                } else {
3041                  r_llsc_fsm = SC_DIR_HIT;
3042                }
3043              }
3044              else r_llsc_fsm = LLSC_TRT_LOCK;
3045            } else {
3046              r_llsc_fsm = SC_RSP_FALSE;
3047            }
3048          }
3049          break;
3050        }
3051        ////////////////
3052      case SC_DIR_HIT:
3053        {
3054          size_t way    = r_llsc_way.read();
3055          size_t set    = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
3056          size_t word   = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
3057
3058          // update directory (lock & dirty bits
3059          DirectoryEntry entry;
3060          entry.valid       = true;
3061          entry.is_cnt      = r_llsc_is_cnt.read();
3062          entry.dirty       = true;
3063          entry.lock        = true;
3064          entry.inst        = r_llsc_inst.read();
3065          entry.tag             = r_llsc_tag.read();
3066          entry.owner.srcid = r_llsc_copy.read();
3067          entry.owner.inst  = r_llsc_copy_inst.read();
3068          entry.count       = r_llsc_count.read();
3069          entry.ptr         = r_llsc_ptr.read();
3070          m_cache_directory.write(set, way, entry);
3071
3072          if(!r_llsc_count.read()){ // no update
3073            // write data in cache
3074            m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
3075            // reset Atomic Table
3076            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
3077          }
3078         
3079          if(r_llsc_count.read()) {  // Shared line
3080              if( !r_llsc_to_init_cmd_multi_req.read() && 
3081                  !r_llsc_to_init_cmd_brdcast_req.read()  )
3082                  r_llsc_fsm = SC_UPT_LOCK;
3083              else
3084                  r_llsc_fsm = SC_WAIT;
3085          } else {
3086            r_llsc_fsm = SC_RSP_TRUE;
3087          }
3088          break;
3089        }
3090        /////////////////////
3091      case SC_UPT_LOCK:         // Try to register the request in Update Table
3092        {
3093
3094          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
3095            size_t way  = r_llsc_way.read();
3096            size_t set  = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
3097            size_t word = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
3098            bool        wok        = false;
3099            size_t      index      = 0;
3100            size_t      srcid      = m_cmd_llsc_srcid_fifo.read();
3101            size_t      trdid      = m_cmd_llsc_trdid_fifo.read();
3102            size_t      pktid      = m_cmd_llsc_pktid_fifo.read();
3103            addr_t          nline      = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3104            size_t      nb_copies  = r_llsc_count.read();
3105
3106            wok =m_update_tab.set(true, // it's an update transaction
3107                false,                  // it's not a broadcast
3108                true,                   // it needs a response
3109                srcid,
3110                trdid,
3111                pktid,
3112                nline,
3113                nb_copies,
3114                index);
3115            if(wok){
3116              // write data in cache
3117              m_cache_data[way][set][word] = m_cmd_llsc_wdata_fifo.read();
3118              // reset Atomic Table
3119              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
3120            }
3121#ifdef IDEBUG
3122            if(wok){
3123                TRACE_MSG(m_log << m_total_cycles << " " << name() << " SC_UPT_LOCK update table : " << std::endl);
3124                DUMP_UPDATE_TABLE;
3125            }
3126#endif
3127            r_llsc_upt_index = index;
3128            //  releases the lock protecting the Update Table and the Directory if no entry...
3129            if ( wok ) r_llsc_fsm = SC_HEAP_LOCK;
3130            else       r_llsc_fsm = SC_WAIT;
3131          }
3132          break;
3133        }
3134        ////////////////////
3135      case SC_WAIT:     // release all locks
3136        {
3137          r_llsc_fsm = SC_DIR_LOCK;
3138          break;
3139        }
3140        ////////////////////
3141      case SC_HEAP_LOCK:        // lock the heap
3142        {
3143          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC ){
3144            r_llsc_fsm = SC_UPT_REQ;
3145          }
3146          break;
3147        }
3148        ////////////////////
3149      case SC_UPT_REQ:  // Request the update
3150        {
3151          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
3152                    "MemCache ERROR : bad HEAP allocation");
3153          if( !r_llsc_to_init_cmd_multi_req.read() && 
3154              !r_llsc_to_init_cmd_brdcast_req.read()  ){
3155            r_llsc_to_init_cmd_brdcast_req  = false;
3156            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
3157            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3158            r_llsc_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3159            r_llsc_to_init_cmd_wdata        = m_cmd_llsc_wdata_fifo.read();
3160
3161            // We put the first copy in the fifo
3162            llsc_to_init_cmd_fifo_put     = true;
3163            llsc_to_init_cmd_fifo_inst    = r_llsc_copy_inst.read();
3164            llsc_to_init_cmd_fifo_srcid   = r_llsc_copy.read();
3165            if(r_llsc_count.read() == 1){
3166              r_llsc_fsm = LLSC_IDLE;
3167              cmd_llsc_fifo_get            = true;
3168              r_llsc_to_init_cmd_multi_req = true;
3169            } else {
3170              r_llsc_fsm = SC_UPDATE;
3171            }
3172          }
3173          break;
3174        }
3175        //////////////////
3176      case SC_UPDATE:           // send a multi-update request to INIT_CMD fsm
3177        {
3178          assert( (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
3179                    "MemCache ERROR : bad HEAP allocation");
3180          HeapEntry entry = m_heap_directory.read(r_llsc_ptr.read());
3181          llsc_to_init_cmd_fifo_inst  = entry.owner.inst;
3182          llsc_to_init_cmd_fifo_srcid = entry.owner.srcid;
3183          llsc_to_init_cmd_fifo_put = true;
3184
3185          if( m_llsc_to_init_cmd_inst_fifo.wok() ){
3186            r_llsc_ptr = entry.next;
3187            if( entry.next == r_llsc_ptr.read() ) { // last copy
3188              r_llsc_to_init_cmd_multi_req = true;
3189              r_llsc_fsm = LLSC_IDLE; // Response will be sent after receiving
3190                                      // all update responses
3191              cmd_llsc_fifo_get         = true;
3192            } else {
3193              r_llsc_fsm = SC_UPDATE;
3194            }
3195          } else {
3196            r_llsc_fsm = SC_UPDATE;
3197          }
3198         
3199          break;
3200        }
3201        //////////////////
3202      case SC_TRT_LOCK:
3203        {
3204          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
3205            if( !r_llsc_to_ixr_cmd_req ) { // we can transfer the data to the buffer
3206              size_t way        = r_llsc_way.read();
3207              size_t set        = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3208              for(size_t i = 0; i<m_words; i++){
3209                if(i==m_x[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]) {
3210                  r_llsc_to_ixr_cmd_data[i] = m_cmd_llsc_wdata_fifo.read();
3211                } else {
3212                  r_llsc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
3213                }
3214              }
3215              size_t wok_index = 0;
3216              bool wok = !m_transaction_tab.full(wok_index);
3217              if ( wok ) { // set a new entry in TRT
3218                r_llsc_trt_index = wok_index;
3219                r_llsc_fsm       = SC_INVAL_LOCK; 
3220              } else {
3221                r_llsc_fsm       = SC_WAIT;
3222              }
3223            } else {
3224              r_llsc_fsm = SC_WAIT;
3225            }
3226          }
3227          break;
3228        }
3229        //////////////////
3230      case SC_INVAL_LOCK:
3231        {
3232          if ( r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC ) {
3233            bool        wok       = false;
3234            size_t      index     = 0;
3235            size_t      srcid     = m_cmd_llsc_srcid_fifo.read();
3236            size_t      trdid     = m_cmd_llsc_trdid_fifo.read();
3237            size_t      pktid     = m_cmd_llsc_pktid_fifo.read();
3238            addr_t          nline     = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3239            size_t      nb_copies = r_llsc_count.read();
3240
3241            wok =m_update_tab.set(false,        // it's an inval transaction
3242                true,                       // it's a broadcast
3243                true,                       // it needs a response
3244                srcid,
3245                trdid,
3246                pktid,
3247                nline,
3248                nb_copies,
3249                index);
3250#ifdef IDEBUG
3251            if(wok){
3252                TRACE_MSG(m_log << m_total_cycles << " " << name() << " LLSC_INVAL_LOCK update table : " << std::endl);
3253                DUMP_UPDATE_TABLE;
3254            }
3255#endif
3256            r_llsc_upt_index = index;
3257            //  releases the lock protecting Update Table if no entry...
3258            if ( wok ) r_llsc_fsm = SC_DIR_INVAL;
3259            else       r_llsc_fsm = SC_WAIT;
3260          }
3261          break;
3262        }
3263        //////////////////
3264      case SC_DIR_INVAL:
3265        {
3266          if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) &&
3267              (r_alloc_upt_fsm.read() == ALLOC_UPT_LLSC )  &&
3268              (r_alloc_dir_fsm.read() == ALLOC_DIR_LLSC ))
3269          {
3270            m_transaction_tab.set(r_llsc_trt_index.read(),
3271                false,                          // write request to XRAM
3272                m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())],
3273                0,
3274                0,
3275                0,
3276                false,                          // not a processor read
3277                0,                              // not a single word
3278                0,                              // word index
3279                std::vector<be_t>(m_words,0),
3280                std::vector<data_t>(m_words,0));
3281#ifdef TDEBUG
3282            TRACE_MSG(m_log << m_total_cycles << " " << name() << " SC_DIR_INVAL transaction table : " << std::endl);
3283            DUMP_TRANSACTION_TABLE;
3284#endif
3285            // reset Atomic Table
3286            m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
3287
3288            // invalidate directory entry
3289            DirectoryEntry entry;
3290            entry.valid    = false;
3291            entry.dirty    = false;
3292            entry.tag      = 0;
3293            entry.is_cnt   = false;
3294            entry.lock     = false;
3295//            entry.d_copies = 0;
3296//            entry.i_copies = 0;
3297            entry.count    = 0;
3298            size_t set     = m_y[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3299            size_t way     = r_llsc_way.read();
3300            m_cache_directory.write(set, way, entry);
3301
3302            r_llsc_fsm = SC_INVAL;
3303          } else {
3304            assert(false && "LOCK ERROR in LLSC_FSM, STATE = LLSC_DIR_INVAL");
3305          }
3306
3307          break;
3308
3309        }
3310        //////////////////
3311      case SC_INVAL:
3312        {
3313          if ( !r_llsc_to_init_cmd_multi_req.read() &&
3314               !r_llsc_to_init_cmd_brdcast_req.read()) {
3315            r_llsc_to_init_cmd_multi_req    = false;
3316            r_llsc_to_init_cmd_brdcast_req  = true;
3317            r_llsc_to_init_cmd_trdid        = r_llsc_upt_index.read();
3318            r_llsc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3319            r_llsc_to_init_cmd_index        = 0;
3320            r_llsc_to_init_cmd_wdata        = 0;
3321
3322            r_llsc_fsm = SC_XRAM_SEND;
3323            // all update responses
3324          }
3325
3326          break;
3327        }
3328        //////////////////
3329      case SC_XRAM_SEND:
3330        {
3331          if ( !r_llsc_to_ixr_cmd_req ) {
3332            r_llsc_to_ixr_cmd_req     = true;
3333            r_llsc_to_ixr_cmd_write   = true;
3334            r_llsc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())];
3335            r_llsc_to_ixr_cmd_trdid   = r_llsc_trt_index.read();
3336            if(  r_llsc_is_cnt.read() ||
3337                ((!r_llsc_is_cnt.read()) && (r_llsc_count.read()==1)) ){
3338              r_llsc_fsm        = LLSC_IDLE;
3339              cmd_llsc_fifo_get = true;
3340            } else {
3341              r_llsc_fsm        = SC_HEAP_ERASE;
3342              r_llsc_next_ptr   = r_llsc_ptr.read();
3343            }
3344          } else {
3345            assert( false && "MEM_CACHE, LLSC FSM : SC_XRAM_SEND state : the request should not have been previously set");
3346          }
3347          break;
3348        }
3349        //////////////////
3350      case SC_HEAP_ERASE:
3351        {
3352          if(r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC){
3353            HeapEntry next_entry = m_heap_directory.read(r_llsc_next_ptr.read());
3354            if( next_entry.next == r_llsc_next_ptr.read()){
3355                //r_write_fsm = SC_HEAP_LAST;
3356                r_llsc_fsm = SC_HEAP_LAST; // As suggest by Alexendre J.
3357            } else {
3358              r_llsc_next_ptr = next_entry.next;
3359              r_llsc_fsm = SC_HEAP_ERASE;
3360            }
3361          }
3362          break;
3363        }
3364        //////////////////
3365      case SC_HEAP_LAST:
3366        {
3367          assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) &&
3368                  "MemCache ERROR : bad HEAP allocation");
3369          size_t free_pointer = m_heap_directory.next_free_ptr();
3370
3371          HeapEntry last_entry;
3372          last_entry.owner.srcid = 0;
3373          last_entry.owner.inst  = false;
3374          if(m_heap_directory.is_full()){
3375            last_entry.next     = r_llsc_next_ptr.read();
3376            m_heap_directory.unset_full();
3377          } else {
3378            last_entry.next     = free_pointer;
3379          }
3380
3381          m_heap_directory.write_free_ptr(r_llsc_ptr.read());
3382          m_heap_directory.write(r_llsc_next_ptr.read(),last_entry);
3383
3384          cmd_llsc_fifo_get             = true;
3385          r_llsc_fsm = LLSC_IDLE;
3386          break;
3387        }
3388        //////////////////
3389      case SC_RSP_FALSE:
3390        {
3391          if( !r_llsc_to_tgt_rsp_req ) {
3392            cmd_llsc_fifo_get           = true;
3393            r_llsc_to_tgt_rsp_req       = true;
3394            r_llsc_to_tgt_rsp_data      = 1;
3395            r_llsc_to_tgt_rsp_srcid     = m_cmd_llsc_srcid_fifo.read();
3396            r_llsc_to_tgt_rsp_trdid     = m_cmd_llsc_trdid_fifo.read();
3397            r_llsc_to_tgt_rsp_pktid     = m_cmd_llsc_pktid_fifo.read();
3398            r_llsc_fsm                      = LLSC_IDLE;
3399          }
3400          break;
3401        }
3402        /////////////////
3403      case SC_RSP_TRUE:
3404        {
3405          if( !r_llsc_to_tgt_rsp_req ) {
3406            cmd_llsc_fifo_get       = true;
3407            r_llsc_to_tgt_rsp_req       = true;
3408            r_llsc_to_tgt_rsp_data      = 0;
3409            r_llsc_to_tgt_rsp_srcid     = m_cmd_llsc_srcid_fifo.read();
3410            r_llsc_to_tgt_rsp_trdid     = m_cmd_llsc_trdid_fifo.read();
3411            r_llsc_to_tgt_rsp_pktid     = m_cmd_llsc_pktid_fifo.read();
3412            r_llsc_fsm                      = LLSC_IDLE;
3413          }
3414          break;
3415        }
3416        ///////////////////
3417      case LLSC_TRT_LOCK:         // read or write miss : check the Transaction Table
3418        {
3419          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
3420            size_t   index = 0;
3421            bool hit_read = m_transaction_tab.hit_read(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],index);
3422            bool hit_write = m_transaction_tab.hit_write(m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()]);
3423            bool wok = !m_transaction_tab.full(index);
3424
3425            if ( hit_read || !wok || hit_write ) {  // missing line already requested or no space in TRT
3426              r_llsc_fsm = LLSC_IDLE;
3427            } else {
3428              r_llsc_trt_index = index;
3429              r_llsc_fsm       = LLSC_TRT_SET;
3430            }
3431          }
3432          break;
3433        }
3434        //////////////////
3435      case LLSC_TRT_SET:        // register the XRAM transaction in Transaction Table
3436        {
3437          if( r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC ) {
3438            size_t word = m_x[(vci_addr_t)(m_cmd_llsc_addr_fifo.read())]; 
3439            bool proc_read = !m_cmd_llsc_sc_fifo.read();
3440            if(proc_read){
3441              m_transaction_tab.set(r_llsc_trt_index.read(),
3442                  true,
3443                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
3444                  m_cmd_llsc_srcid_fifo.read(),
3445                  m_cmd_llsc_trdid_fifo.read(),
3446                  m_cmd_llsc_pktid_fifo.read(),
3447                  true,
3448                  1,
3449                  word,
3450                  std::vector<be_t>(m_words,0),
3451                  std::vector<data_t>(m_words,0));
3452            }else{
3453              std::vector<be_t> be_vector;
3454              std::vector<data_t> data_vector;
3455              be_vector.clear();
3456              data_vector.clear();
3457              // reset Atomic Table
3458              m_atomic_tab.reset(m_cmd_llsc_addr_fifo.read());
3459              for ( size_t i=0; i<m_words; i++ ) 
3460              {   
3461                if(i == word){
3462                  be_vector.push_back(0xF);
3463                  data_vector.push_back(m_cmd_llsc_wdata_fifo.read());
3464                } else {
3465                  be_vector.push_back(0);
3466                  data_vector.push_back(0);
3467                }
3468              }
3469 
3470              m_transaction_tab.set(r_llsc_trt_index.read(),
3471                  true,
3472                  m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()],
3473                  m_cmd_llsc_srcid_fifo.read(),
3474                  m_cmd_llsc_trdid_fifo.read(),
3475                  m_cmd_llsc_pktid_fifo.read(),
3476                  false,
3477                  0,
3478                  0,
3479                  be_vector,
3480                  data_vector);
3481            }
3482#ifdef TDEBUG
3483            TRACE_MSG(m_log << m_total_cycles << " " << name() << " LLSC_TRT_SET transaction table : " << std::endl);
3484            DUMP_TRANSACTION_TABLE;
3485#endif
3486
3487            r_llsc_fsm = LLSC_XRAM_REQ;
3488          }
3489          break;
3490        }
3491        ///////////////////
3492      case LLSC_XRAM_REQ:       // request the IXR_CMD FSM to fetch the missing line
3493        {
3494          if ( !r_llsc_to_ixr_cmd_req ) {
3495            r_llsc_to_ixr_cmd_req        = true;
3496            r_llsc_to_ixr_cmd_write      = false;
3497            r_llsc_to_ixr_cmd_trdid      = r_llsc_trt_index.read();
3498            r_llsc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_llsc_addr_fifo.read()];
3499            if( m_cmd_llsc_sc_fifo.read() ) {
3500              r_llsc_fsm                 = SC_RSP_TRUE;
3501            } else {
3502              cmd_llsc_fifo_get          = true;
3503              r_llsc_fsm                 = LLSC_IDLE;
3504            }
3505          }
3506          break;
3507        }
3508    } // end switch r_llsc_fsm
3509
3510
3511    //////////////////////////////////////////////////////////////////////////////
3512    //          INIT_CMD FSM
3513    //////////////////////////////////////////////////////////////////////////////
3514    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
3515    // or invalidate cache lines in L1 caches.
3516    // It implements a round-robin priority between the two following requests:
3517    // - r_write_to_init_cmd_req : update request from WRITE FSM
3518    // - r_xram_rsp_to_init_cmd_req : invalidate request from XRAM_RSP FSM
3519    // The inval request is a single cell VCI write command containing the
3520    // index of the line to be invalidated.
3521    // The update request is a multi-cells VCI write command : The first cell
3522    // contains the index of the cache line to be updated. The second cell contains
3523    // the index of the first modified word in the line. The following cells
3524    // contain the data.
3525    ///////////////////////////////////////////////////////////////////////////////
3526
3527    switch ( r_init_cmd_fsm.read() ) {
3528
3529      ////////////////////////
3530      case INIT_CMD_UPDT_IDLE:  // Invalidate requests have highest priority
3531        {
3532
3533          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
3534               r_xram_rsp_to_init_cmd_multi_req.read()  ) {
3535            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
3536            m_cpt_inval++;
3537          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
3538            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
3539            m_cpt_inval++;
3540          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
3541                      r_write_to_init_cmd_multi_req.read() ) {
3542            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
3543            m_cpt_update++;
3544          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
3545            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
3546            m_cpt_inval++;
3547          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
3548                      r_llsc_to_init_cmd_multi_req.read()  ) {
3549            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
3550            m_cpt_update++;
3551          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
3552            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
3553            m_cpt_inval++;
3554          }
3555          break;
3556        }
3557        /////////////////////////
3558      case INIT_CMD_INVAL_IDLE: // Update requests have highest priority
3559        {
3560          if ( m_write_to_init_cmd_inst_fifo.rok() ||
3561               r_write_to_init_cmd_multi_req.read() ) {
3562            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
3563            m_cpt_update++;
3564          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
3565            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
3566            m_cpt_inval++;
3567          } else if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
3568                      r_llsc_to_init_cmd_multi_req.read()  ) {
3569            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
3570            m_cpt_update++;
3571          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
3572            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
3573            m_cpt_inval++;
3574          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
3575                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
3576            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
3577            m_cpt_inval++;
3578          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
3579            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
3580            m_cpt_inval++;
3581          }
3582          break;
3583        }
3584        /////////////////////////
3585      case INIT_CMD_SC_UPDT_IDLE:       // Update requests for SCs have highest priority
3586        {
3587          if ( m_llsc_to_init_cmd_inst_fifo.rok() ||
3588               r_llsc_to_init_cmd_multi_req.read()  ) {
3589            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
3590            m_cpt_update++;
3591          } else if( r_llsc_to_init_cmd_brdcast_req.read() ){
3592            r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
3593            m_cpt_inval++;
3594          } else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
3595                      r_xram_rsp_to_init_cmd_multi_req.read()  ) {
3596            r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
3597            m_cpt_inval++;
3598          } else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() ) {
3599            r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
3600            m_cpt_inval++;
3601          } else if ( m_write_to_init_cmd_inst_fifo.rok() ||
3602                      r_write_to_init_cmd_multi_req.read() ) {
3603            r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
3604            m_cpt_update++;
3605          } else if ( r_write_to_init_cmd_brdcast_req.read() ){
3606            r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
3607            m_cpt_inval++;
3608          }
3609          break;
3610        }
3611        ////////////////////////
3612      case INIT_CMD_INVAL_NLINE:        // send the cache line index
3613        {
3614          if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ){
3615            if ( p_vci_ini.cmdack ) {
3616              m_cpt_inval_mult++;
3617              r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
3618              xram_rsp_to_init_cmd_fifo_get = true;
3619            }
3620          } else {
3621            if( r_xram_rsp_to_init_cmd_multi_req.read() ){
3622              r_xram_rsp_to_init_cmd_multi_req = false;
3623            } 
3624            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
3625          }
3626          break;
3627        }
3628        ////////////////////////
3629      case INIT_CMD_XRAM_BRDCAST:       // send the cache line index
3630        {
3631          if ( p_vci_ini.cmdack ) {
3632            m_cpt_inval_brdcast++;
3633            r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
3634            r_xram_rsp_to_init_cmd_brdcast_req = false;
3635          }
3636          break;
3637        }
3638        /////////////////////////
3639      case INIT_CMD_WRITE_BRDCAST:
3640        {
3641          if( p_vci_ini.cmdack ) {
3642            m_cpt_inval_brdcast++;
3643            r_write_to_init_cmd_brdcast_req = false;
3644            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
3645          }
3646          break;
3647        }
3648        /////////////////////////
3649      case INIT_CMD_UPDT_NLINE: // send the cache line index
3650        {
3651          if ( m_write_to_init_cmd_inst_fifo.rok() ) {
3652            if ( p_vci_ini.cmdack ){
3653              m_cpt_update_mult++;
3654              r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
3655            }
3656          } else {
3657            if ( r_write_to_init_cmd_multi_req.read() ){
3658              r_write_to_init_cmd_multi_req = false;
3659            }
3660            r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
3661          }
3662          break;
3663        }
3664        /////////////////////////
3665      case INIT_CMD_UPDT_INDEX: // send the first word index
3666        {
3667          r_init_cmd_cpt    = 0;
3668          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
3669          break;
3670        }
3671        ////////////////////////
3672      case INIT_CMD_UPDT_DATA:  // send the data
3673        {
3674          if ( p_vci_ini.cmdack ) {
3675            if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) ) {
3676              r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
3677              write_to_init_cmd_fifo_get = true;
3678            } else {
3679              r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
3680            }
3681          }
3682          break;
3683        }
3684        /////////////////////////
3685      case INIT_CMD_SC_BRDCAST:
3686        {
3687          if( p_vci_ini.cmdack ) {
3688            m_cpt_inval_brdcast++;
3689            r_llsc_to_init_cmd_brdcast_req = false;
3690            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
3691          }
3692          break;
3693        }
3694        /////////////////////////
3695      case INIT_CMD_SC_UPDT_NLINE:      // send the cache line index
3696        {
3697          if ( m_llsc_to_init_cmd_inst_fifo.rok() ){
3698            if ( p_vci_ini.cmdack ){
3699              m_cpt_update_mult++;
3700              r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
3701            }
3702          } else {
3703            if( r_llsc_to_init_cmd_multi_req.read() ){
3704              r_llsc_to_init_cmd_multi_req = false;
3705            }
3706            r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
3707          }
3708          break;
3709        }
3710        /////////////////////////
3711      case INIT_CMD_SC_UPDT_INDEX:      // send the first word index
3712        {
3713          if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
3714          break;
3715        }
3716        ////////////////////////
3717      case INIT_CMD_SC_UPDT_DATA:       // send the data
3718        {
3719          if ( p_vci_ini.cmdack ) {
3720            llsc_to_init_cmd_fifo_get = true;
3721            r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
3722          }
3723          break;
3724        }
3725
3726    } // end switch r_init_cmd_fsm
3727
3728    /////////////////////////////////////////////////////////////////////
3729    //          TGT_RSP FSM
3730    /////////////////////////////////////////////////////////////////////
3731    // The TGT_RSP fsm sends the responses on the VCI target port
3732    // with a round robin priority between six requests :
3733    // - r_read_to_tgt_rsp_req
3734    // - r_write_to_tgt_rsp_req
3735    // - r_llsc_to_tgt_rsp_req
3736    // - r_cleanup_to_tgt_rsp_req
3737    // - r_init_rsp_to_tgt_rsp_req
3738    // - r_xram_rsp_to_tgt_rsp_req
3739    // The  ordering is :  read > write > llsc > cleanup > xram > init
3740    /////////////////////////////////////////////////////////////////////
3741
3742    switch ( r_tgt_rsp_fsm.read() ) {
3743
3744      ///////////////////////
3745      case TGT_RSP_READ_IDLE:           // write requests have the highest priority
3746        {
3747          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3748          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3749          else if ( r_xram_rsp_to_tgt_rsp_req ) {
3750            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3751            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3752          }
3753          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3754          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3755          else if ( r_read_to_tgt_rsp_req     ) {
3756            r_tgt_rsp_fsm = TGT_RSP_READ;
3757            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3758          }
3759          break;
3760        }
3761        ////////////////////////
3762      case TGT_RSP_WRITE_IDLE:          // llsc requests have the highest priority
3763        {
3764          if      ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3765          else if ( r_xram_rsp_to_tgt_rsp_req ) {
3766            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3767            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3768          }
3769          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3770          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3771          else if ( r_read_to_tgt_rsp_req     ) {
3772            r_tgt_rsp_fsm = TGT_RSP_READ;
3773            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3774          }
3775
3776          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3777          break;
3778        }
3779        ///////////////////////
3780      case TGT_RSP_LLSC_IDLE:           // cleanup requests have the highest priority
3781        {
3782          if ( r_xram_rsp_to_tgt_rsp_req )  {
3783            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3784            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3785          }
3786          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3787          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3788          else if ( r_read_to_tgt_rsp_req     ) {
3789            r_tgt_rsp_fsm = TGT_RSP_READ;
3790            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3791          }
3792          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3793          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3794          break;
3795        }
3796      case TGT_RSP_XRAM_IDLE:           // init requests have the highest priority
3797        {
3798
3799          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3800          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3801          else if ( r_read_to_tgt_rsp_req     ) {
3802            r_tgt_rsp_fsm = TGT_RSP_READ;
3803            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3804          }
3805          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3806          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3807          else if ( r_xram_rsp_to_tgt_rsp_req )  {
3808            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3809            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3810          }
3811          break;
3812        }
3813        ///////////////////////
3814      case TGT_RSP_INIT_IDLE:           // cleanup requests have the highest priority
3815        {
3816          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3817          else if ( r_read_to_tgt_rsp_req     ) {
3818            r_tgt_rsp_fsm = TGT_RSP_READ;
3819            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3820          }
3821          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3822          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3823          else if ( r_xram_rsp_to_tgt_rsp_req ) {
3824            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3825            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3826          }
3827          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3828          break;
3829        }
3830        ///////////////////////
3831      case TGT_RSP_CLEANUP_IDLE:                // read requests have the highest priority
3832        {
3833          if      ( r_read_to_tgt_rsp_req     ) {
3834            r_tgt_rsp_fsm = TGT_RSP_READ;
3835            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
3836          }
3837          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
3838          else if ( r_llsc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_LLSC;
3839          else if ( r_xram_rsp_to_tgt_rsp_req ) {
3840            r_tgt_rsp_fsm = TGT_RSP_XRAM;
3841            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
3842          }
3843          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
3844          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
3845          break;
3846        }
3847        ///////////////////////
3848      case TGT_RSP_READ:                // send the response
3849        {
3850          if ( p_vci_tgt.rspack ) {
3851            if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) ) {
3852              r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
3853              r_read_to_tgt_rsp_req = false;
3854            } else {
3855              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
3856            }
3857          }
3858          break;
3859        }
3860        ///////////////////
3861      case TGT_RSP_WRITE:               // send the write acknowledge
3862        {
3863          if ( p_vci_tgt.rspack ) {
3864            r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
3865            r_write_to_tgt_rsp_req = false;
3866          }
3867          break;
3868        }
3869        ///////////////////
3870      case TGT_RSP_CLEANUP:             // send the write acknowledge
3871        {
3872          if ( p_vci_tgt.rspack ) {
3873            r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
3874            r_cleanup_to_tgt_rsp_req = false;
3875          }
3876          break;
3877        }
3878        //////////////////
3879      case TGT_RSP_LLSC:                // send one atomic word response
3880        {
3881          if ( p_vci_tgt.rspack ) {
3882            r_tgt_rsp_fsm = TGT_RSP_LLSC_IDLE;
3883            r_llsc_to_tgt_rsp_req = false;
3884          }
3885          break;
3886        }
3887
3888        ///////////////////////
3889      case TGT_RSP_XRAM:                // send the response
3890        {
3891          if ( p_vci_tgt.rspack ) {
3892            if ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1)) {
3893              r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
3894              r_xram_rsp_to_tgt_rsp_req = false;
3895            } else {
3896              r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
3897            }
3898          }
3899          break;
3900        }
3901        ///////////////////
3902      case TGT_RSP_INIT:                // send the pending write acknowledge
3903        {
3904          if ( p_vci_tgt.rspack ) {
3905            r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
3906            r_init_rsp_to_tgt_rsp_req = false;
3907          }
3908          break;
3909        }
3910    } // end switch tgt_rsp_fsm
3911    ////////////////////////////////////////////////////////////////////////////////////
3912    //          NEW ALLOC_UPT FSM
3913    ////////////////////////////////////////////////////////////////////////////////////
3914    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
3915    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
3916    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
3917    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
3918    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
3919    // - The CLEANUP  FSM decrement an entry in UPT.
3920    // The resource is always allocated.
3921    /////////////////////////////////////////////////////////////////////////////////////
3922
3923    switch ( r_alloc_upt_fsm.read() ) {
3924
3925      ////////////////////////
3926      case ALLOC_UPT_INIT_RSP:
3927        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) && 
3928             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) ) 
3929        {
3930          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
3931                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
3932          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
3933          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
3934          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
3935                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
3936        }
3937        break;
3938
3939        /////////////////////
3940      case ALLOC_UPT_WRITE:
3941        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
3942             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
3943        {
3944          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
3945          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
3946          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
3947                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
3948          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
3949        }
3950        break;
3951
3952        ////////////////////////
3953      case ALLOC_UPT_XRAM_RSP:
3954        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK) 
3955        { 
3956          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
3957          else if ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
3958                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
3959          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
3960          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
3961                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
3962        }
3963        break;
3964
3965        //////////////////////////
3966      case ALLOC_UPT_CLEANUP:
3967        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
3968        {
3969          if      ((r_llsc_fsm.read() == SC_UPT_LOCK) ||
3970                   (r_llsc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_LLSC;
3971          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
3972          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
3973                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
3974          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
3975        }
3976        break;
3977       
3978        //////////////////////////
3979      case ALLOC_UPT_LLSC:
3980        if( (r_llsc_fsm.read() != SC_UPT_LOCK) && 
3981            (r_llsc_fsm.read() != SC_INVAL_LOCK))
3982        {
3983          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
3984          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
3985                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
3986          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
3987          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
3988        }
3989        break;
3990
3991    } // end switch r_alloc_upt_fsm
3992
3993    ////////////////////////////////////////////////////////////////////////////////////
3994    //          ALLOC_DIR FSM
3995    ////////////////////////////////////////////////////////////////////////////////////
3996    // The ALLOC_DIR FSM allocates the access to the directory and
3997    // the data cache with a round robin priority between 5 user FSMs :
3998    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
3999    // The ressource is always allocated.
4000    /////////////////////////////////////////////////////////////////////////////////////
4001
4002    switch ( r_alloc_dir_fsm.read() ) {
4003
4004      ////////////////////
4005      case ALLOC_DIR_READ:
4006        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
4007              (r_read_fsm.read() != READ_TRT_LOCK)  &&
4008              (r_read_fsm.read() != READ_HEAP_LOCK))
4009            ||
4010            ( (r_read_fsm.read()        == READ_HEAP_LOCK) &&
4011              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_READ) )
4012            ||
4013            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
4014              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  ) 
4015        {
4016          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4017          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
4018                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
4019          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
4020          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4021        }
4022        break;
4023
4024        /////////////////////
4025      case ALLOC_DIR_WRITE:
4026        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
4027              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
4028              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
4029              (r_write_fsm.read() != WRITE_DIR_HIT) &&
4030              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
4031              (r_write_fsm.read() != WRITE_INVAL_LOCK) &&
4032              (r_write_fsm.read() != WRITE_UPT_LOCK) &&
4033              (r_write_fsm.read() != WRITE_HEAP_LOCK))
4034            ||
4035            ( (r_write_fsm.read()       == WRITE_HEAP_LOCK) &&
4036              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_WRITE) )
4037            ||
4038            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
4039              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
4040        {
4041          if        ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
4042                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
4043          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
4044          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4045          else if   (r_read_fsm.read() == READ_DIR_LOCK)                r_alloc_dir_fsm = ALLOC_DIR_READ;
4046        }
4047        break;
4048
4049        ////////////////////
4050      case ALLOC_DIR_LLSC:
4051        if ( ( (r_llsc_fsm.read() != LL_DIR_LOCK)    &&
4052              (r_llsc_fsm.read() != LL_DIR_HIT )    &&
4053              (r_llsc_fsm.read() != SC_DIR_LOCK)    &&
4054              (r_llsc_fsm.read() != SC_DIR_HIT )    &&
4055              (r_llsc_fsm.read() != LLSC_TRT_LOCK ) &&
4056              (r_llsc_fsm.read() != SC_TRT_LOCK)    &&
4057              (r_llsc_fsm.read() != SC_INVAL_LOCK)  &&
4058              (r_llsc_fsm.read() != SC_UPT_LOCK)    &&
4059              (r_llsc_fsm.read() != SC_HEAP_LOCK))
4060            ||
4061            ( (r_llsc_fsm.read()       == SC_HEAP_LOCK) &&
4062              (r_alloc_heap_fsm.read() == ALLOC_HEAP_LLSC) )
4063            ||
4064            ( (r_llsc_fsm.read()      == LLSC_TRT_LOCK ) &&
4065              (r_alloc_trt_fsm.read() == ALLOC_TRT_LLSC)    ) )
4066        {
4067          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
4068          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4069          else if (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
4070          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4071        }
4072        break;
4073
4074        ///////////////////////
4075      case ALLOC_DIR_CLEANUP:
4076        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
4077            (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
4078        {
4079          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
4080          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
4081          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4082          else if   ((r_llsc_fsm.read() == LL_DIR_LOCK) || 
4083                    (r_llsc_fsm.read() == SC_DIR_LOCK))             r_alloc_dir_fsm = ALLOC_DIR_LLSC;
4084        }
4085        break;
4086        ////////////////////////
4087      case ALLOC_DIR_XRAM_RSP:
4088        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
4089            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   && 
4090            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
4091        {
4092          if      (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
4093          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
4094          else if ( (r_llsc_fsm.read() == LL_DIR_LOCK) || 
4095                    (r_llsc_fsm.read() == SC_DIR_LOCK))         r_alloc_dir_fsm = ALLOC_DIR_LLSC;
4096          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
4097        }
4098        break;
4099
4100    } // end switch alloc_dir_fsm
4101
4102    ////////////////////////////////////////////////////////////////////////////////////
4103    //          ALLOC_TRT FSM
4104    ////////////////////////////////////////////////////////////////////////////////////
4105    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
4106    // with a round robin priority between 4 user FSMs :
4107    // The cyclic priority is READ > WRITE > LLSC > XRAM_RSP
4108    // The ressource is always allocated.
4109    ///////////////////////////////////////////////////////////////////////////////////
4110
4111    switch (r_alloc_trt_fsm) {
4112
4113      ////////////////////
4114      case ALLOC_TRT_READ:
4115        if ( r_read_fsm.read() != READ_TRT_LOCK ) 
4116        {
4117          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
4118                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4119          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
4120                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
4121          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4122          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
4123                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4124        }
4125        break;
4126        /////////////////////
4127      case ALLOC_TRT_WRITE:
4128        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
4129             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
4130             (r_write_fsm.read() != WRITE_INVAL_LOCK)) 
4131        {
4132          if      ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
4133                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
4134          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4135          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
4136                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4137          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
4138        }
4139        break;
4140        ////////////////////
4141      case ALLOC_TRT_LLSC:
4142        if ( (r_llsc_fsm.read() != LLSC_TRT_LOCK) &&
4143             (r_llsc_fsm.read() != SC_TRT_LOCK) &&
4144             (r_llsc_fsm.read() != SC_INVAL_LOCK))
4145        { 
4146          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4147          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
4148                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4149          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
4150          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
4151                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4152        }
4153        break;
4154        ////////////////////////
4155      case ALLOC_TRT_XRAM_RSP:
4156        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
4157            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
4158            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
4159          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
4160                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
4161          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
4162          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
4163                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4164          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
4165                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
4166        }
4167        break;
4168        ////////////////////////
4169      case ALLOC_TRT_IXR_RSP:
4170        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
4171            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
4172          if      (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
4173          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
4174                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
4175          else if ((r_llsc_fsm.read() == LLSC_TRT_LOCK) ||
4176                   (r_llsc_fsm.read() == SC_TRT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_LLSC;
4177          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
4178        }
4179        break;
4180
4181    } // end switch alloc_trt_fsm
4182
4183    ////////////////////////////////////////////////////////////////////////////////////
4184    //          ALLOC_HEAP FSM
4185    ////////////////////////////////////////////////////////////////////////////////////
4186    // The ALLOC_HEAP FSM allocates the access to the heap
4187    // with a round robin priority between 5 user FSMs :
4188    // The cyclic ordering is READ > WRITE > LLSC > CLEANUP > XRAM_RSP
4189    // The ressource is always allocated.
4190    /////////////////////////////////////////////////////////////////////////////////////
4191
4192    switch ( r_alloc_heap_fsm.read() ) {
4193
4194      ////////////////////
4195      case ALLOC_HEAP_READ:
4196        if (  (r_read_fsm.read() != READ_HEAP_LOCK) &&
4197              (r_read_fsm.read() != READ_HEAP_ERASE)     ) 
4198        {
4199          if        ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||         
4200                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
4201          else if  ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
4202                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
4203          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
4204          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
4205        }
4206        break;
4207
4208        /////////////////////
4209      case ALLOC_HEAP_WRITE:
4210        if (  (r_write_fsm.read() != WRITE_HEAP_LOCK)   &&
4211              (r_write_fsm.read() != WRITE_UPT_REQ)     &&
4212              (r_write_fsm.read() != WRITE_UPDATE)      &&
4213              (r_write_fsm.read() != WRITE_HEAP_ERASE))
4214        {
4215          if       ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
4216                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
4217          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
4218          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
4219          else if   (r_read_fsm.read() == READ_HEAP_LOCK)               r_alloc_heap_fsm = ALLOC_HEAP_READ;
4220        }
4221        break;
4222
4223        ////////////////////
4224      case ALLOC_HEAP_LLSC:
4225        if (  (r_llsc_fsm.read() != SC_HEAP_LOCK)  &&
4226              (r_llsc_fsm.read() != SC_UPT_REQ )    &&
4227              (r_llsc_fsm.read() != SC_UPDATE)      &&
4228              (r_llsc_fsm.read() != SC_HEAP_ERASE ) )
4229        {
4230          if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
4231          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
4232          else if (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
4233          else if ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||       
4234                   (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
4235        }
4236        break;
4237
4238        ///////////////////////
4239      case ALLOC_HEAP_CLEANUP:
4240        if ( (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
4241            (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH)&&
4242            (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN)    )
4243        {
4244          if        (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
4245          else if   (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
4246          else if   ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||       
4247                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
4248          else if   ((r_llsc_fsm.read() == SC_HEAP_LOCK) || 
4249                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
4250        }
4251        break;
4252        ////////////////////////
4253      case ALLOC_HEAP_XRAM_RSP:
4254        if ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE )
4255        {
4256          if        (r_read_fsm.read() == READ_HEAP_LOCK)               r_alloc_heap_fsm = ALLOC_HEAP_READ;
4257          else if   ((r_write_fsm.read() == WRITE_HEAP_LOCK) ||       
4258                     (r_write_fsm.read() == WRITE_HEAP_ERASE))      r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
4259          else if   ( (r_llsc_fsm.read() == SC_HEAP_LOCK) || 
4260                    (r_llsc_fsm.read() == SC_HEAP_ERASE))           r_alloc_heap_fsm = ALLOC_HEAP_LLSC;
4261          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
4262        }
4263        break;
4264
4265    } // end switch alloc_heap_fsm
4266
4267
4268    ////////////////////////////////////////////////////////////////////////////////////
4269    //          TGT_CMD to READ FIFO
4270    ////////////////////////////////////////////////////////////////////////////////////
4271
4272    if ( cmd_read_fifo_put ) {
4273      if ( cmd_read_fifo_get ) {
4274        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
4275        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
4276        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
4277        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
4278        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
4279      } else {
4280        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
4281        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
4282        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
4283        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
4284        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
4285      }
4286    } else {
4287      if ( cmd_read_fifo_get ) {
4288        m_cmd_read_addr_fifo.simple_get();
4289        m_cmd_read_length_fifo.simple_get();
4290        m_cmd_read_srcid_fifo.simple_get();
4291        m_cmd_read_trdid_fifo.simple_get();
4292        m_cmd_read_pktid_fifo.simple_get();
4293      }
4294    }
4295    /////////////////////////////////////////////////////////////////////
4296    //          TGT_CMD to WRITE FIFO
4297    /////////////////////////////////////////////////////////////////////
4298
4299    if ( cmd_write_fifo_put ) {
4300      if ( cmd_write_fifo_get ) {
4301        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
4302        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
4303        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
4304        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
4305        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
4306        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
4307        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
4308      } else {
4309        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
4310        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
4311        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
4312        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
4313        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
4314        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
4315        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
4316      }
4317    } else {
4318      if ( cmd_write_fifo_get ) {
4319        m_cmd_write_addr_fifo.simple_get();
4320        m_cmd_write_eop_fifo.simple_get();
4321        m_cmd_write_srcid_fifo.simple_get();
4322        m_cmd_write_trdid_fifo.simple_get();
4323        m_cmd_write_pktid_fifo.simple_get();
4324        m_cmd_write_data_fifo.simple_get();
4325        m_cmd_write_be_fifo.simple_get();
4326      }
4327    }
4328    ////////////////////////////////////////////////////////////////////////////////////
4329    //          TGT_CMD to LLSC FIFO
4330    ////////////////////////////////////////////////////////////////////////////////////
4331
4332    if ( cmd_llsc_fifo_put ) {
4333      if ( cmd_llsc_fifo_get ) {
4334        m_cmd_llsc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
4335        m_cmd_llsc_sc_fifo.put_and_get(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
4336        m_cmd_llsc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
4337        m_cmd_llsc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
4338        m_cmd_llsc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
4339        m_cmd_llsc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
4340      } else {
4341        m_cmd_llsc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
4342        m_cmd_llsc_sc_fifo.simple_put(p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND); 
4343        m_cmd_llsc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
4344        m_cmd_llsc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
4345        m_cmd_llsc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
4346        m_cmd_llsc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
4347      }
4348    } else {
4349      if ( cmd_llsc_fifo_get ) {
4350        m_cmd_llsc_addr_fifo.simple_get();
4351        m_cmd_llsc_sc_fifo.simple_get();
4352        m_cmd_llsc_srcid_fifo.simple_get();
4353        m_cmd_llsc_trdid_fifo.simple_get();
4354        m_cmd_llsc_pktid_fifo.simple_get();
4355        m_cmd_llsc_wdata_fifo.simple_get();
4356      }
4357    }
4358    ////////////////////////////////////////////////////////////////////////////////////
4359    //          WRITE to INIT_CMD FIFO
4360    ////////////////////////////////////////////////////////////////////////////////////
4361
4362    if ( write_to_init_cmd_fifo_put ) {
4363      if ( write_to_init_cmd_fifo_get ) {
4364        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
4365        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
4366      } else {
4367        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
4368        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
4369      }
4370    } else {
4371      if ( write_to_init_cmd_fifo_get ) {
4372        m_write_to_init_cmd_inst_fifo.simple_get();
4373        m_write_to_init_cmd_srcid_fifo.simple_get();
4374      }
4375    }
4376    ////////////////////////////////////////////////////////////////////////////////////
4377    //          XRAM_RSP to INIT_CMD FIFO
4378    ////////////////////////////////////////////////////////////////////////////////////
4379
4380    if ( xram_rsp_to_init_cmd_fifo_put ) {
4381      if ( xram_rsp_to_init_cmd_fifo_get ) {
4382        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
4383        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
4384      } else {
4385        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
4386        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
4387      }
4388    } else {
4389      if ( xram_rsp_to_init_cmd_fifo_get ) {
4390        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
4391        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
4392      }
4393    }
4394    ////////////////////////////////////////////////////////////////////////////////////
4395    //          LLSC to INIT_CMD FIFO
4396    ////////////////////////////////////////////////////////////////////////////////////
4397
4398    if ( llsc_to_init_cmd_fifo_put ) {
4399      if ( llsc_to_init_cmd_fifo_get ) {
4400        m_llsc_to_init_cmd_inst_fifo.put_and_get(llsc_to_init_cmd_fifo_inst);
4401        m_llsc_to_init_cmd_srcid_fifo.put_and_get(llsc_to_init_cmd_fifo_srcid);
4402      } else {
4403        m_llsc_to_init_cmd_inst_fifo.simple_put(llsc_to_init_cmd_fifo_inst);
4404        m_llsc_to_init_cmd_srcid_fifo.simple_put(llsc_to_init_cmd_fifo_srcid);
4405      }
4406    } else {
4407      if ( llsc_to_init_cmd_fifo_get ) {
4408        m_llsc_to_init_cmd_inst_fifo.simple_get();
4409        m_llsc_to_init_cmd_srcid_fifo.simple_get();
4410      }
4411    }
4412
4413
4414  //////////////////////////////////////////////////////////////
4415    m_cpt_cycles++;
4416    m_total_cycles++;
4417
4418    if((m_period != 0) && ((m_cpt_cycles % m_period) == 0))
4419    {
4420        print_log();
4421        clear_stats();
4422    }
4423
4424  } // end transition()
4425
4426  /////////////////////////////
4427  tmpl(void)::genMoore()
4428    /////////////////////////////
4429  {
4430    ////////////////////////////////////////////////////////////
4431    // Command signals on the p_vci_ixr port
4432    ////////////////////////////////////////////////////////////
4433
4434
4435    p_vci_ixr.be      = 0xF;
4436    p_vci_ixr.pktid   = 0;
4437    p_vci_ixr.srcid   = m_srcid_ixr;
4438    p_vci_ixr.cons    = false;
4439    p_vci_ixr.wrap    = false;
4440    p_vci_ixr.contig  = true;
4441    p_vci_ixr.clen    = 0;
4442    p_vci_ixr.cfixed  = false;
4443
4444    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
4445      p_vci_ixr.cmd     = vci_param::CMD_READ;
4446      p_vci_ixr.cmdval  = true;
4447      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
4448      p_vci_ixr.plen    = m_words*4;
4449      p_vci_ixr.wdata   = 0x00000000;
4450      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
4451      p_vci_ixr.eop     = true;
4452    } 
4453    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_LLSC_NLINE ) {
4454      if(r_llsc_to_ixr_cmd_write.read()){
4455        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
4456        p_vci_ixr.cmdval  = true;
4457        p_vci_ixr.address = (addr_t)((r_llsc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
4458        p_vci_ixr.plen    = m_words*4;
4459        p_vci_ixr.wdata   = r_llsc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
4460        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
4461        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
4462      } else {
4463        p_vci_ixr.cmd     = vci_param::CMD_READ;
4464        p_vci_ixr.cmdval  = true;
4465        p_vci_ixr.address = (addr_t)(r_llsc_to_ixr_cmd_nline.read()*m_words*4);
4466        p_vci_ixr.plen    = m_words*4;
4467        p_vci_ixr.wdata   = 0x00000000;
4468        p_vci_ixr.trdid   = r_llsc_to_ixr_cmd_trdid.read();
4469        p_vci_ixr.eop     = true;
4470      }
4471    } 
4472    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
4473      if(r_write_to_ixr_cmd_write.read()){
4474        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
4475        p_vci_ixr.cmdval  = true;
4476        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
4477        p_vci_ixr.plen    = m_words*4;
4478        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
4479        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
4480        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
4481      } else {
4482        p_vci_ixr.cmd     = vci_param::CMD_READ;
4483        p_vci_ixr.cmdval  = true;
4484        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
4485        p_vci_ixr.plen    = m_words*4;
4486        p_vci_ixr.wdata   = 0x00000000;
4487        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
4488        p_vci_ixr.eop     = true;
4489      }
4490    } 
4491    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
4492      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
4493      p_vci_ixr.cmdval  = true;
4494      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
4495      p_vci_ixr.plen    = m_words*4;
4496      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
4497      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
4498      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
4499    } else {
4500      p_vci_ixr.cmdval  = false;
4501      p_vci_ixr.address = 0;
4502      p_vci_ixr.plen    = 0;
4503      p_vci_ixr.wdata   = 0;
4504      p_vci_ixr.trdid   = 0;
4505      p_vci_ixr.eop     = false;
4506    }
4507
4508    ////////////////////////////////////////////////////
4509    // Response signals on the p_vci_ixr port
4510    ////////////////////////////////////////////////////
4511
4512    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
4513          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) || 
4514        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
4515    else                                        p_vci_ixr.rspack = false;
4516
4517    ////////////////////////////////////////////////////
4518    // Command signals on the p_vci_tgt port
4519    ////////////////////////////////////////////////////
4520
4521    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
4522      case TGT_CMD_IDLE:
4523        p_vci_tgt.cmdack  = false;
4524        break;
4525      case TGT_CMD_READ:
4526        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
4527        break;
4528      case TGT_CMD_READ_EOP:
4529        p_vci_tgt.cmdack  = true;
4530        break;
4531      case TGT_CMD_WRITE:
4532        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
4533        break;
4534      case TGT_CMD_ATOMIC:
4535        p_vci_tgt.cmdack  = m_cmd_llsc_addr_fifo.wok();
4536        break;
4537      default:
4538        p_vci_tgt.cmdack = false;
4539        break;
4540    }
4541
4542    ////////////////////////////////////////////////////
4543    // Response signals on the p_vci_tgt port
4544    ////////////////////////////////////////////////////
4545    switch ( r_tgt_rsp_fsm.read() ) {
4546
4547      case TGT_RSP_READ_IDLE:
4548      case TGT_RSP_WRITE_IDLE:
4549      case TGT_RSP_LLSC_IDLE:
4550      case TGT_RSP_XRAM_IDLE:
4551      case TGT_RSP_INIT_IDLE:
4552      case TGT_RSP_CLEANUP_IDLE:
4553        p_vci_tgt.rspval  = false;
4554        p_vci_tgt.rsrcid  = 0;
4555        p_vci_tgt.rdata   = 0;
4556        p_vci_tgt.rpktid  = 0;
4557        p_vci_tgt.rtrdid  = 0;
4558        p_vci_tgt.rerror  = 0;
4559        p_vci_tgt.reop    = false;     
4560        break;
4561      case TGT_RSP_READ:
4562        p_vci_tgt.rspval   = true;
4563        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
4564        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
4565        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
4566        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
4567        p_vci_tgt.rerror   = 0;
4568        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
4569        break;
4570      case TGT_RSP_WRITE:
4571        p_vci_tgt.rspval   = true;
4572        p_vci_tgt.rdata    = 0;
4573        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
4574        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
4575        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
4576        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
4577        p_vci_tgt.reop     = true;
4578        break;
4579      case TGT_RSP_CLEANUP:
4580        p_vci_tgt.rspval   = true;
4581        p_vci_tgt.rdata    = 0;
4582        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
4583        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
4584        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
4585        p_vci_tgt.rerror   = 0;
4586        p_vci_tgt.reop     = true;
4587        break;
4588      case TGT_RSP_LLSC:
4589        p_vci_tgt.rspval   = true;
4590        p_vci_tgt.rdata    = r_llsc_to_tgt_rsp_data.read();
4591        p_vci_tgt.rsrcid   = r_llsc_to_tgt_rsp_srcid.read();
4592        p_vci_tgt.rtrdid   = r_llsc_to_tgt_rsp_trdid.read();
4593        p_vci_tgt.rpktid   = r_llsc_to_tgt_rsp_pktid.read();
4594        p_vci_tgt.rerror   = 0;
4595        p_vci_tgt.reop     = true;
4596        break;
4597      case TGT_RSP_XRAM:
4598        p_vci_tgt.rspval   = true;
4599        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
4600        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
4601        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
4602        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
4603        p_vci_tgt.rerror   = 0;
4604        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1));
4605        break;
4606      case TGT_RSP_INIT:
4607        p_vci_tgt.rspval   = true;
4608        p_vci_tgt.rdata    = 0;
4609        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
4610        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
4611        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
4612        p_vci_tgt.rerror   = 0;
4613        p_vci_tgt.reop     = true;     
4614        break;
4615    } // end switch r_tgt_rsp_fsm
4616
4617    ///////////////////////////////////////////////////
4618    // Command signals on the p_vci_ini port
4619    ///////////////////////////////////////////////////
4620
4621    p_vci_ini.cmd     = vci_param::CMD_WRITE;
4622    p_vci_ini.srcid   = m_srcid_ini;
4623    p_vci_ini.pktid   = 0;
4624    p_vci_ini.cons    = true;
4625    p_vci_ini.wrap    = false;
4626    p_vci_ini.contig  = false;
4627    p_vci_ini.clen    = 0;
4628    p_vci_ini.cfixed  = false;
4629
4630    switch ( r_init_cmd_fsm.read() ) {
4631
4632      case INIT_CMD_UPDT_IDLE:
4633      case INIT_CMD_INVAL_IDLE:
4634      case INIT_CMD_SC_UPDT_IDLE:
4635        p_vci_ini.cmdval  = false;
4636        p_vci_ini.address = 0;
4637        p_vci_ini.wdata   = 0;
4638        p_vci_ini.be      = 0;
4639        p_vci_ini.plen    = 0;
4640        p_vci_ini.trdid   = 0;
4641        p_vci_ini.eop     = false;
4642        break;
4643      case INIT_CMD_INVAL_NLINE:
4644        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
4645        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
4646          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
4647            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]+8);
4648          } else {
4649            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]);
4650          }
4651        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
4652        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
4653        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
4654        p_vci_ini.plen    = 4;
4655        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
4656        p_vci_ini.eop     = true;
4657        break;
4658      case INIT_CMD_XRAM_BRDCAST:
4659        p_vci_ini.cmdval  = true;
4660        p_vci_ini.address = broadcast_addr;
4661        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
4662        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
4663        p_vci_ini.plen    = 4;
4664        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
4665        p_vci_ini.eop     = true;
4666        break;
4667
4668      case INIT_CMD_WRITE_BRDCAST:
4669        p_vci_ini.cmdval  = true;
4670        p_vci_ini.address = broadcast_addr;
4671        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
4672        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
4673        p_vci_ini.plen    = 4 ;
4674        p_vci_ini.eop     = true;
4675        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
4676        break;
4677      case INIT_CMD_UPDT_NLINE:
4678        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
4679        if(m_write_to_init_cmd_inst_fifo.rok()){
4680          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
4681        } else {
4682          p_vci_ini.address = 0;
4683        }
4684        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
4685        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
4686        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
4687        p_vci_ini.eop     = false;
4688        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
4689        break;
4690      case INIT_CMD_UPDT_INDEX:
4691        p_vci_ini.cmdval  = true;
4692        p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
4693        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
4694        p_vci_ini.be      = 0xF;
4695        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
4696        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
4697        p_vci_ini.eop     = false;
4698        break;
4699      case INIT_CMD_UPDT_DATA:
4700        p_vci_ini.cmdval  = true;
4701        p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 4);
4702        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
4703          r_write_to_init_cmd_index.read()].read();
4704        if(r_write_to_init_cmd_we[r_init_cmd_cpt.read() +
4705            r_write_to_init_cmd_index.read()].read()) 
4706          p_vci_ini.be      = 0xF;
4707        else                    p_vci_ini.be      = 0x0;
4708        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
4709        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
4710        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
4711        break;
4712
4713      case INIT_CMD_SC_BRDCAST:
4714        p_vci_ini.cmdval  = true;
4715        p_vci_ini.address = broadcast_addr;
4716        p_vci_ini.wdata   = (addr_t)r_llsc_to_init_cmd_nline.read();
4717        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32) & 0x3);
4718        p_vci_ini.plen    = 4 ;
4719        p_vci_ini.eop     = true;
4720        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
4721        break;
4722      case INIT_CMD_SC_UPDT_NLINE:
4723        p_vci_ini.cmdval  = m_llsc_to_init_cmd_inst_fifo.rok();
4724        if(m_llsc_to_init_cmd_inst_fifo.rok()){
4725          p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
4726        } else {
4727          p_vci_ini.address = 0;
4728        }
4729        p_vci_ini.wdata   = (uint32_t)r_llsc_to_init_cmd_nline.read();
4730        p_vci_ini.be      = ((r_llsc_to_init_cmd_nline.read() >> 32 ) & 0x3);
4731        p_vci_ini.plen    = 4 * 3;
4732        p_vci_ini.eop     = false;
4733        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
4734        break;
4735      case INIT_CMD_SC_UPDT_INDEX:
4736        p_vci_ini.cmdval  = true;
4737        p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
4738        p_vci_ini.wdata   = r_llsc_to_init_cmd_index.read();
4739        p_vci_ini.be      = 0xF;
4740        p_vci_ini.plen    = 4 * 3;
4741        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
4742        p_vci_ini.eop     = false;
4743        break;
4744      case INIT_CMD_SC_UPDT_DATA:
4745        p_vci_ini.cmdval  = true;
4746        p_vci_ini.address = (addr_t)(m_coherence_table[m_llsc_to_init_cmd_srcid_fifo.read()] + 4);
4747        p_vci_ini.wdata   = r_llsc_to_init_cmd_wdata.read();
4748        p_vci_ini.be      = 0xF;
4749        p_vci_ini.plen    = 4 * 3;
4750        p_vci_ini.trdid   = r_llsc_to_init_cmd_trdid.read();
4751        p_vci_ini.eop     = true;
4752        break;
4753
4754    } // end switch r_init_cmd_fsm
4755
4756    //////////////////////////////////////////////////////
4757    // Response signals on the p_vci_ini port
4758    //////////////////////////////////////////////////////
4759
4760    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
4761    else                                          p_vci_ini.rspack  = false;
4762
4763    //////////////////////////////////////////////////////
4764    // Response signals on the p_vci_tgt_cleanup port
4765    //////////////////////////////////////////////////////
4766    p_vci_tgt_cleanup.rspval = false;
4767    p_vci_tgt_cleanup.rsrcid = 0;
4768    p_vci_tgt_cleanup.rdata  = 0;
4769    p_vci_tgt_cleanup.rpktid = 0;
4770    p_vci_tgt_cleanup.rtrdid = 0;
4771    p_vci_tgt_cleanup.rerror = 0;
4772    p_vci_tgt_cleanup.reop   = false;
4773    p_vci_tgt_cleanup.cmdack = false ;
4774
4775    switch(r_cleanup_fsm.read()){
4776      case CLEANUP_IDLE:
4777        {
4778          p_vci_tgt_cleanup.cmdack = true ;
4779          break;
4780        }
4781      case CLEANUP_RSP:
4782        {
4783          p_vci_tgt_cleanup.rspval = true;
4784          p_vci_tgt_cleanup.rdata  = 0;
4785          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
4786          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
4787          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
4788          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
4789          p_vci_tgt_cleanup.reop   = 1;
4790          break;
4791        }
4792
4793    }
4794
4795  } // end genMoore()
4796
4797}} // end name space
4798
4799// Local Variables:
4800// tab-width: 4
4801// c-basic-offset: 4
4802// c-file-offsets:((innamespace . 0)(inline-open . 0))
4803// indent-tabs-mode: nil
4804// End:
4805
4806// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
4807
Note: See TracBrowser for help on using the repository browser.