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

Last change on this file since 2 was 2, checked in by nipo, 14 years ago

Import TSAR modules in TSAR's own svn

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