source: branches/v4/modules/vci_mem_cache_v1/caba/source/src/vci_mem_cache_v1.cpp @ 775

Last change on this file since 775 was 192, checked in by cfuguet, 12 years ago

Cleanup transaction modification

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