source: trunk/modules/vci_mem_cache_v2/caba/source/src/vci_mem_cache_v2.cpp @ 83

Last change on this file since 83 was 83, checked in by guthmull, 14 years ago

Fix the masking of RERROR field

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