source: trunk/modules/vci_mem_cache_v2s/caba/source/src/vci_mem_cache_v2s.cpp @ 365

Last change on this file since 365 was 41, checked in by gao, 14 years ago

Special for cc_vcache and cc_vcache_multi

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