source: trunk/modules/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp @ 184

Last change on this file since 184 was 184, checked in by alain, 12 years ago

mproving the debug mechanisms

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Author Date Id Rev URL Revision"
  • Property svn:mime-type set to text/plain
File size: 228.1 KB
Line 
1 /* -*- c++ -*-
2 * File         : vci_mem_cache_v4.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
30#include "../include/vci_mem_cache_v4.h"
31
32//////   debug services   ///////////////////////////////////////////////////////
33// All debug messages are conditionned by two variables:
34// - compile time : DEBUG_MEMC_*** : defined below
35// - execution time : m_debug_***  : defined by constructor arguments
36//    m_debug_* = (m_debug_ok) and (m_cpt_cycle > m_debug_start_cycle)
37/////////////////////////////////////////////////////////////////////////////////
38
39#define DEBUG_MEMC_GLOBAL       0       // synthetic trace of all FSMs
40#define DEBUG_MEMC_READ         1       // detailed trace of READ FSM
41#define DEBUG_MEMC_WRITE        1       // detailed trace of WRITE FSM 
42#define DEBUG_MEMC_SC           0       // detailed trace of SC FSM     
43#define DEBUG_MEMC_IXR_CMD      1       // detailed trace of IXR_RSP FSM
44#define DEBUG_MEMC_IXR_RSP      1       // detailed trace of IXR_RSP FSM
45#define DEBUG_MEMC_XRAM_RSP     1       // detailed trace of XRAM_RSP FSM       
46#define DEBUG_MEMC_INIT_CMD     0       // detailed trace of INIT_CMD FSM       
47#define DEBUG_MEMC_INIT_RSP     0       // detailed trace of INIT_RSP FSM       
48#define DEBUG_MEMC_TGT_CMD      0       // detailed trace of TGT_CMD FSM       
49#define DEBUG_MEMC_TGT_RSP      0       // detailed trace of TGT_RSP FSM       
50#define DEBUG_MEMC_CLEANUP      0       // detailed trace of CLEANUP FSM       
51
52#define RANDOMIZE_SC            1
53
54namespace soclib { namespace caba {
55
56  const char *tgt_cmd_fsm_str[] = {
57    "TGT_CMD_IDLE",
58    "TGT_CMD_READ",
59    "TGT_CMD_WRITE",
60    "TGT_CMD_ATOMIC",
61  };
62  const char *tgt_rsp_fsm_str[] = {
63    "TGT_RSP_READ_IDLE",
64    "TGT_RSP_WRITE_IDLE",
65    "TGT_RSP_SC_IDLE",
66    "TGT_RSP_XRAM_IDLE",
67    "TGT_RSP_INIT_IDLE",
68    "TGT_RSP_CLEANUP_IDLE",
69    "TGT_RSP_READ",
70    "TGT_RSP_WRITE",
71    "TGT_RSP_SC",
72    "TGT_RSP_XRAM",
73    "TGT_RSP_INIT",
74    "TGT_RSP_CLEANUP",
75  };
76  const char *init_cmd_fsm_str[] = {
77    "INIT_CMD_INVAL_IDLE",
78    "INIT_CMD_INVAL_NLINE",
79    "INIT_CMD_XRAM_BRDCAST",
80    "INIT_CMD_UPDT_IDLE",
81    "INIT_CMD_WRITE_BRDCAST",
82    "INIT_CMD_UPDT_NLINE",
83    "INIT_CMD_UPDT_INDEX",
84    "INIT_CMD_UPDT_DATA",
85    "INIT_CMD_SC_UPDT_IDLE",
86    "INIT_CMD_SC_BRDCAST",
87    "INIT_CMD_SC_UPDT_NLINE",
88    "INIT_CMD_SC_UPDT_INDEX",
89    "INIT_CMD_SC_UPDT_DATA",
90    "INIT_CMD_SC_UPDT_DATA_HIGH",
91  };
92  const char *init_rsp_fsm_str[] = {
93    "INIT_RSP_IDLE",
94    "INIT_RSP_UPT_LOCK",
95    "INIT_RSP_UPT_CLEAR",
96    "INIT_RSP_END",
97  };
98  const char *read_fsm_str[] = {
99    "READ_IDLE",
100    "READ_DIR_LOCK",
101    "READ_DIR_HIT",
102    "READ_HEAP_LOCK",
103    "READ_HEAP_WRITE",
104    "READ_HEAP_ERASE",
105    "READ_HEAP_LAST",
106    "READ_RSP",
107    "READ_TRT_LOCK",
108    "READ_TRT_SET",
109    "READ_TRT_REQ",
110  };
111  const char *write_fsm_str[] = {
112    "WRITE_IDLE",
113    "WRITE_NEXT",
114    "WRITE_DIR_LOCK",
115    "WRITE_DIR_HIT_READ",
116    "WRITE_DIR_HIT",
117    "WRITE_UPT_LOCK",
118    "WRITE_HEAP_LOCK",
119    "WRITE_UPT_REQ",
120    "WRITE_UPDATE",
121    "WRITE_UPT_DEC",
122    "WRITE_RSP",
123    "WRITE_TRT_LOCK",
124    "WRITE_TRT_DATA",
125    "WRITE_TRT_SET",
126    "WRITE_WAIT",
127    "WRITE_XRAM_REQ",
128    "WRITE_TRT_WRITE_LOCK",
129    "WRITE_INVAL_LOCK",
130    "WRITE_DIR_INVAL",
131    "WRITE_INVAL",
132    "WRITE_XRAM_SEND",
133  };
134  const char *ixr_rsp_fsm_str[] = {
135    "IXR_RSP_IDLE",
136    "IXR_RSP_ACK",
137    "IXR_RSP_TRT_ERASE",
138    "IXR_RSP_TRT_READ",
139  };
140  const char *xram_rsp_fsm_str[] = {
141    "XRAM_RSP_IDLE",
142    "XRAM_RSP_TRT_COPY",
143    "XRAM_RSP_TRT_DIRTY",
144    "XRAM_RSP_DIR_LOCK",
145    "XRAM_RSP_DIR_UPDT",
146    "XRAM_RSP_DIR_RSP",
147    "XRAM_RSP_INVAL_LOCK",
148    "XRAM_RSP_INVAL_WAIT",
149    "XRAM_RSP_INVAL",
150    "XRAM_RSP_WRITE_DIRTY",
151    "XRAM_RSP_HEAP_ERASE",
152    "XRAM_RSP_HEAP_LAST",
153    "XRAM_RSP_ERROR_ERASE",
154    "XRAM_RSP_ERROR_RSP",
155  };
156  const char *ixr_cmd_fsm_str[] = {
157    "IXR_CMD_READ_IDLE",
158    "IXR_CMD_WRITE_IDLE",
159    "IXR_CMD_SC_IDLE",
160    "IXR_CMD_XRAM_IDLE",
161    "IXR_CMD_READ_NLINE",
162    "IXR_CMD_WRITE_NLINE",
163    "IXR_CMD_SC_NLINE",
164    "IXR_CMD_XRAM_DATA",
165  };
166  const char *sc_fsm_str[] = {
167    "SC_IDLE",
168    "SC_DIR_LOCK",
169    "SC_DIR_HIT_READ",
170    "SC_DIR_HIT_WRITE",
171    "SC_UPT_LOCK",
172    "SC_WAIT",
173    "SC_HEAP_LOCK",
174    "SC_UPT_REQ",
175    "SC_UPT_NEXT",
176    "SC_TRT_PUT_LOCK",
177    "SC_INVAL_LOCK",
178    "SC_DIR_INVAL",
179    "SC_INVAL",
180    "SC_TRT_PUT_REQ",
181    "SC_RSP_FAIL",
182    "SC_RSP_SUCCESS",
183    "SC_TRT_GET_LOCK",
184    "SC_TRT_GET_SET",
185    "SC_TRT_GET_REQ",
186  };
187  const char *cleanup_fsm_str[] = {
188    "CLEANUP_IDLE",
189    "CLEANUP_DIR_LOCK",
190    "CLEANUP_DIR_WRITE",
191    "CLEANUP_HEAP_LOCK",
192    "CLEANUP_HEAP_SEARCH",
193    "CLEANUP_HEAP_CLEAN",
194    "CLEANUP_HEAP_FREE",
195    "CLEANUP_UPT_LOCK",
196    "CLEANUP_UPT_WRITE",
197    "CLEANUP_WRITE_RSP",
198    "CLEANUP_RSP",
199  };
200  const char *alloc_dir_fsm_str[] = {
201    "ALLOC_DIR_READ",
202    "ALLOC_DIR_WRITE",
203    "ALLOC_DIR_SC",
204    "ALLOC_DIR_CLEANUP",
205    "ALLOC_DIR_XRAM_RSP",
206  };
207  const char *alloc_trt_fsm_str[] = {
208    "ALLOC_TRT_READ",
209    "ALLOC_TRT_WRITE",
210    "ALLOC_TRT_SC",
211    "ALLOC_TRT_XRAM_RSP",
212    "ALLOC_TRT_IXR_RSP",
213  };
214  const char *alloc_upt_fsm_str[] = {
215    "ALLOC_UPT_WRITE",
216    "ALLOC_UPT_XRAM_RSP",
217    "ALLOC_UPT_INIT_RSP",
218    "ALLOC_UPT_CLEANUP",
219  };
220  const char *alloc_heap_fsm_str[] = {
221    "ALLOC_HEAP_READ",
222    "ALLOC_HEAP_WRITE",
223    "ALLOC_HEAP_SC",
224    "ALLOC_HEAP_CLEANUP",
225    "ALLOC_HEAP_XRAM_RSP",
226  };
227
228#define tmpl(x) template<typename vci_param> x VciMemCacheV4<vci_param>
229
230  using soclib::common::uint32_log2;
231
232  ////////////////////////////////
233  //    Constructor
234  ////////////////////////////////
235
236  tmpl(/**/)::VciMemCacheV4(
237      sc_module_name name,
238      const soclib::common::MappingTable &mtp,
239      const soclib::common::MappingTable &mtc,
240      const soclib::common::MappingTable &mtx,
241      const soclib::common::IntTab &vci_ixr_index,
242      const soclib::common::IntTab &vci_ini_index,
243      const soclib::common::IntTab &vci_tgt_index,
244      const soclib::common::IntTab &vci_tgt_index_cleanup,
245      size_t nways,                                         // number of ways per set
246      size_t nsets,                                         // number of cache sets
247      size_t nwords,                                        // number of words in cache line
248      size_t heap_size,                                     // number of heap entries
249      size_t transaction_tab_lines,                         // number of TRT entries
250      size_t update_tab_lines,                              // number of UPT entries
251      size_t debug_start_cycle,
252      bool   debug_ok)
253
254    : soclib::caba::BaseModule(name),
255
256    m_debug_start_cycle( debug_start_cycle),
257    m_debug_ok ( debug_ok ),
258
259    p_clk("clk"),
260    p_resetn("resetn"),
261    p_vci_tgt("vci_tgt"),
262    p_vci_tgt_cleanup("vci_tgt_cleanup"),
263    p_vci_ini("vci_ini"),
264    p_vci_ixr("vci_ixr"),
265
266    m_initiators( 1 << vci_param::S ),
267    m_heap_size( heap_size ),
268    m_ways( nways ),
269    m_sets( nsets ),
270    m_words( nwords ),
271    m_srcid_ixr( mtx.indexForId(vci_ixr_index) ),
272    m_srcid_ini( mtc.indexForId(vci_ini_index) ),
273    m_seglist(mtp.getSegmentList(vci_tgt_index)),
274    m_cseglist(mtc.getSegmentList(vci_tgt_index_cleanup)),
275    m_coherence_table( mtc.getCoherenceTable<vci_addr_t>() ),
276    m_transaction_tab_lines(transaction_tab_lines),
277    m_transaction_tab( transaction_tab_lines, nwords ),
278    m_update_tab_lines( update_tab_lines),
279    m_update_tab( update_tab_lines ),
280    m_cache_directory( nways, nsets, nwords, vci_param::N ),
281    m_heap( m_heap_size ),
282
283#define L2 soclib::common::uint32_log2
284    m_x( L2(m_words), 2),
285    m_y( L2(m_sets), L2(m_words) + 2),
286    m_z( vci_param::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
287    m_nline( vci_param::N - L2(m_words) - 2, L2(m_words) + 2),
288#undef L2
289
290    //  FIFOs
291    m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
292    m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
293    m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
294    m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
295    m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
296
297    m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
298    m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
299    m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
300    m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
301    m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
302    m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
303    m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
304
305    m_cmd_sc_addr_fifo("m_cmd_sc_addr_fifo",4),
306    m_cmd_sc_eop_fifo("m_cmd_sc_eop_fifo",4),
307    m_cmd_sc_srcid_fifo("m_cmd_sc_srcid_fifo",4),
308    m_cmd_sc_trdid_fifo("m_cmd_sc_trdid_fifo",4),
309    m_cmd_sc_pktid_fifo("m_cmd_sc_pktid_fifo",4),
310    m_cmd_sc_wdata_fifo("m_cmd_sc_wdata_fifo",4),
311
312    r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
313   
314    nseg(0),   
315    ncseg(0),   
316
317    r_read_fsm("r_read_fsm"),
318    r_write_fsm("r_write_fsm"),
319    m_write_to_init_cmd_inst_fifo("m_write_to_init_cmd_inst_fifo",8),
320    m_write_to_init_cmd_srcid_fifo("m_write_to_init_cmd_srcid_fifo",8),
321#if L1_MULTI_CACHE
322    m_write_to_init_cmd_cache_id_fifo("m_write_to_init_cmd_cache_id_fifo",8),
323#endif
324    r_init_rsp_fsm("r_init_rsp_fsm"),
325    r_cleanup_fsm("r_cleanup_fsm"),
326    r_sc_fsm("r_sc_fsm"),
327    m_sc_to_init_cmd_inst_fifo("m_sc_to_init_cmd_inst_fifo",8),
328    m_sc_to_init_cmd_srcid_fifo("m_sc_to_init_cmd_srcid_fifo",8),
329#if L1_MULTI_CACHE
330    m_sc_to_init_cmd_cache_id_fifo("m_sc_to_init_cmd_cache_id_fifo",8),
331#endif
332    r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
333    r_xram_rsp_fsm("r_xram_rsp_fsm"),
334    m_xram_rsp_to_init_cmd_inst_fifo("m_xram_rsp_to_init_cmd_inst_fifo",8),
335    m_xram_rsp_to_init_cmd_srcid_fifo("m_xram_rsp_to_init_cmd_srcid_fifo",8),
336#if L1_MULTI_CACHE
337    m_xram_rsp_to_init_cmd_cache_id_fifo("m_xram_rsp_to_init_cmd_cache_id_fifo",8),
338#endif
339    r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
340    r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
341    r_init_cmd_fsm("r_init_cmd_fsm"),
342    r_alloc_dir_fsm("r_alloc_dir_fsm"),
343    r_alloc_trt_fsm("r_alloc_trt_fsm"),
344    r_alloc_upt_fsm("r_alloc_upt_fsm")
345    {
346      assert(IS_POW_OF_2(nsets));
347      assert(IS_POW_OF_2(nwords));
348      assert(IS_POW_OF_2(nways));
349      assert(nsets);
350      assert(nwords);
351      assert(nways);
352
353      // check Transaction table size
354      assert( (uint32_log2(transaction_tab_lines) <= vci_param::T) and
355             "Need more bits for VCI TRDID field");
356
357      // Set the broadcast address with Xmin,Xmax,Ymin,Ymax set to maximum
358      m_broadcast_address = 0x3 | (0x7C1F << (vci_param::N-20));
359
360      // Get the segments associated to the MemCache
361      std::list<soclib::common::Segment>::iterator seg;
362
363      for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++) {
364        nseg++;
365      }
366      for(seg = m_cseglist.begin(); seg != m_cseglist.end() ; seg++) {
367        ncseg++;
368      }
369
370      m_seg = new soclib::common::Segment*[nseg];
371      size_t i = 0;
372      for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) {
373        m_seg[i] = &(*seg);
374        i++;
375      }
376      m_cseg = new soclib::common::Segment*[ncseg];
377      i = 0;
378      for ( seg = m_cseglist.begin() ; seg != m_cseglist.end() ; seg++ ) {
379          m_cseg[i] = &(*seg);
380          i++;
381      }
382
383      // Memory cache allocation & initialisation
384      m_cache_data = new data_t**[nways];
385      for ( size_t i=0 ; i<nways ; ++i ) {
386        m_cache_data[i] = new data_t*[nsets];
387      }
388      for ( size_t i=0; i<nways; ++i ) {
389        for ( size_t j=0; j<nsets; ++j ) {
390          m_cache_data[i][j] = new data_t[nwords];
391          for ( size_t k=0; k<nwords; k++){
392            m_cache_data[i][j][k]=0;
393          }     
394        }
395      }
396
397      // Allocation for IXR_RSP FSM
398      r_ixr_rsp_to_xram_rsp_rok     = new sc_signal<bool>[m_transaction_tab_lines];
399
400      // Allocation for XRAM_RSP FSM
401      r_xram_rsp_victim_data        = new sc_signal<data_t>[nwords];
402      r_xram_rsp_to_tgt_rsp_data    = new sc_signal<data_t>[nwords];
403      r_xram_rsp_to_ixr_cmd_data    = new sc_signal<data_t>[nwords];
404
405      // Allocation for READ FSM
406      r_read_data                               = new sc_signal<data_t>[nwords];
407      r_read_to_tgt_rsp_data            = new sc_signal<data_t>[nwords];
408
409      // Allocation for WRITE FSM
410      r_write_data                              = new sc_signal<data_t>[nwords];
411      r_write_be                                = new sc_signal<be_t>[nwords];
412      r_write_to_init_cmd_data          = new sc_signal<data_t>[nwords];
413      r_write_to_init_cmd_be            = new sc_signal<be_t>[nwords];
414      r_write_to_ixr_cmd_data       = new sc_signal<data_t>[nwords];
415
416      // Allocation for SC FSM
417      r_sc_to_ixr_cmd_data              = new sc_signal<data_t>[nwords];
418      r_sc_rdata                    = new sc_signal<data_t>[2];
419
420
421      // Simulation
422
423      SC_METHOD(transition);
424      dont_initialize();
425      sensitive << p_clk.pos();
426
427      SC_METHOD(genMoore);
428      dont_initialize();
429      sensitive << p_clk.neg();
430
431    } // end constructor
432
433/////////////////////////////////////////////////////
434tmpl(void)::cache_monitor( vci_addr_t addr )
435/////////////////////////////////////////////////////
436{
437    size_t way = 0;
438    DirectoryEntry entry = m_cache_directory.read(addr, way);
439    if ( (entry.count != m_debug_previous_count) or
440         (entry.valid != m_debug_previous_hit) )
441    {
442    std::cout << " MEMC " << name()
443              << " cache change at cycle " << std::dec << m_cpt_cycles
444              << " for address " << std::hex << addr
445              << " / HIT = " << entry.valid
446              << " / COUNT = " << std::dec << entry.count << std::endl;
447    }
448    m_debug_previous_count = entry.count;
449    m_debug_previous_hit = entry.valid;
450}
451
452//////////////////////////////////////////////////
453tmpl(void)::print_trace()
454//////////////////////////////////////////////////
455{
456    std::cout << "MEMC " << name() << std::endl;
457    std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm]
458              << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm]
459              << " | " << read_fsm_str[r_read_fsm]
460              << " | " << write_fsm_str[r_write_fsm]
461              << " | " << sc_fsm_str[r_sc_fsm]
462              << " | " << cleanup_fsm_str[r_cleanup_fsm] << std::endl;
463    std::cout << "  "  << init_cmd_fsm_str[r_init_cmd_fsm]
464              << " | " << init_rsp_fsm_str[r_init_rsp_fsm]
465              << " | " << ixr_cmd_fsm_str[r_ixr_cmd_fsm]
466              << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm]
467              << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl;
468}
469
470/////////////////////////////////////////
471tmpl(void)::print_stats()
472/////////////////////////////////////////
473{
474    std::cout << "----------------------------------" << std::dec << std::endl;
475    std::cout << "MEM_CACHE " << m_srcid_ini << " / Time = " << m_cpt_cycles << std::endl
476              << "- READ RATE            = " << (double)m_cpt_read/m_cpt_cycles << std::endl
477              << "- READ TOTAL           = " << m_cpt_read << std::endl
478              << "- READ MISS RATE       = " << (double)m_cpt_read_miss/m_cpt_read << std::endl
479              << "- WRITE RATE           = " << (double)m_cpt_write/m_cpt_cycles << std::endl
480              << "- WRITE TOTAL          = " << m_cpt_write << std::endl
481              << "- WRITE MISS RATE      = " << (double)m_cpt_write_miss/m_cpt_write << std::endl
482              << "- WRITE BURST LENGTH   = " << (double)m_cpt_write_cells/m_cpt_write << std::endl
483              << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
484              << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
485              << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
486              << "- UPDATE RATE          = " << (double)m_cpt_update/m_cpt_cycles << std::endl
487              << "- UPDATE ARITY         = " << (double)m_cpt_update_mult/m_cpt_update << std::endl
488              << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast)/m_cpt_cycles << std::endl
489              << "- INVAL MULTICAST ARITY= " << (double)m_cpt_inval_mult/(m_cpt_inval-m_cpt_inval_brdcast) << std::endl
490              << "- INVAL BROADCAST RATE = " << (double)m_cpt_inval_brdcast/m_cpt_cycles << std::endl
491              << "- SAVE DIRTY RATE      = " << (double)m_cpt_write_dirty/m_cpt_cycles << std::endl
492              << "- CLEANUP RATE         = " << (double)m_cpt_cleanup/m_cpt_cycles << std::endl
493              << "- LL RATE              = " << (double)m_cpt_ll/m_cpt_cycles << std::endl
494              << "- SC RATE              = " << (double)m_cpt_sc/m_cpt_cycles << std::endl;
495}
496
497  /////////////////////////////////
498  tmpl(/**/)::~VciMemCacheV4()
499    /////////////////////////////////
500  {
501    for(size_t i=0; i<m_ways ; i++){
502      for(size_t j=0; j<m_sets ; j++){
503        delete [] m_cache_data[i][j];
504      }
505    }
506    for(size_t i=0; i<m_ways ; i++){
507      delete [] m_cache_data[i];
508    }
509    delete [] m_cache_data;
510    delete [] m_coherence_table;
511
512    delete [] r_ixr_rsp_to_xram_rsp_rok;
513
514    delete [] r_xram_rsp_victim_data;
515    delete [] r_xram_rsp_to_tgt_rsp_data;
516    delete [] r_xram_rsp_to_ixr_cmd_data;
517
518    delete [] r_read_data;
519    delete [] r_read_to_tgt_rsp_data;
520
521    delete [] r_write_data;
522    delete [] r_write_be;
523    delete [] r_write_to_init_cmd_data;
524  }
525
526//////////////////////////////////
527tmpl(void)::transition()
528//////////////////////////////////
529{
530    using soclib::common::uint32_log2;
531
532    //  RESET         
533    if ( ! p_resetn.read() ) {
534
535      //     Initializing FSMs
536      r_tgt_cmd_fsm     = TGT_CMD_IDLE;
537      r_tgt_rsp_fsm     = TGT_RSP_READ_IDLE;
538      r_init_cmd_fsm    = INIT_CMD_INVAL_IDLE;
539      r_init_rsp_fsm    = INIT_RSP_IDLE;
540      r_read_fsm            = READ_IDLE;
541      r_write_fsm           = WRITE_IDLE;
542      r_sc_fsm          = SC_IDLE;
543      r_cleanup_fsm     = CLEANUP_IDLE;
544      r_alloc_dir_fsm   = ALLOC_DIR_READ;
545      r_alloc_trt_fsm   = ALLOC_TRT_READ;
546      r_alloc_upt_fsm   = ALLOC_UPT_WRITE;
547      r_ixr_rsp_fsm     = IXR_RSP_IDLE;
548      r_xram_rsp_fsm    = XRAM_RSP_IDLE;
549      r_ixr_cmd_fsm     = IXR_CMD_READ_IDLE;
550
551      m_debug_global         = false;
552      m_debug_tgt_cmd_fsm    = false;
553      m_debug_tgt_rsp_fsm    = false;
554      m_debug_init_cmd_fsm   = false;
555      m_debug_init_rsp_fsm   = false;
556      m_debug_read_fsm       = false;
557      m_debug_write_fsm      = false;
558      m_debug_sc_fsm         = false;
559      m_debug_cleanup_fsm    = false;
560      m_debug_ixr_cmd_fsm    = false;
561      m_debug_ixr_rsp_fsm    = false;
562      m_debug_xram_rsp_fsm   = false;
563      m_debug_previous_hit   = false;
564      m_debug_previous_count = 0;
565
566      //  Initializing Tables
567      m_cache_directory.init();
568      m_transaction_tab.init();
569      m_heap.init();
570
571      // initializing FIFOs and communication Buffers
572
573      m_cmd_read_addr_fifo.init();
574      m_cmd_read_length_fifo.init();
575      m_cmd_read_srcid_fifo.init();
576      m_cmd_read_trdid_fifo.init();
577      m_cmd_read_pktid_fifo.init();
578
579      m_cmd_write_addr_fifo.init();
580      m_cmd_write_eop_fifo.init();
581      m_cmd_write_srcid_fifo.init();
582      m_cmd_write_trdid_fifo.init();
583      m_cmd_write_pktid_fifo.init();
584      m_cmd_write_data_fifo.init();
585
586      m_cmd_sc_addr_fifo.init();
587      m_cmd_sc_srcid_fifo.init();
588      m_cmd_sc_trdid_fifo.init();
589      m_cmd_sc_pktid_fifo.init();
590      m_cmd_sc_wdata_fifo.init();
591      m_cmd_sc_eop_fifo.init();
592
593      r_read_to_tgt_rsp_req                 = false;
594      r_read_to_ixr_cmd_req                 = false;
595
596      r_write_to_tgt_rsp_req            = false;
597      r_write_to_ixr_cmd_req            = false;
598      r_write_to_init_cmd_multi_req         = false;
599      r_write_to_init_cmd_brdcast_req   = false;
600      r_write_to_init_rsp_req           = false;
601      m_write_to_init_cmd_inst_fifo.init();
602      m_write_to_init_cmd_srcid_fifo.init();
603#if L1_MULTI_CACHE
604      m_write_to_init_cmd_cache_id_fifo.init();
605#endif
606
607      r_cleanup_to_tgt_rsp_req          = false;
608
609      r_init_rsp_to_tgt_rsp_req         = false;
610
611      r_sc_to_tgt_rsp_req                   = false;
612      r_sc_cpt                          = 0;
613      r_sc_lfsr                         = -1;
614      r_sc_to_ixr_cmd_req                   = false;
615      r_sc_to_init_cmd_multi_req            = false;
616      r_sc_to_init_cmd_brdcast_req          = false;
617      m_sc_to_init_cmd_inst_fifo.init();
618      m_sc_to_init_cmd_srcid_fifo.init();
619#if L1_MULTI_CACHE
620      m_sc_to_init_cmd_cache_id_fifo.init();
621#endif
622
623      for(size_t i=0; i<m_transaction_tab_lines ; i++){
624        r_ixr_rsp_to_xram_rsp_rok[i] = false;
625      }
626
627      r_xram_rsp_to_tgt_rsp_req             = false;
628      r_xram_rsp_to_init_cmd_multi_req      = false;
629      r_xram_rsp_to_init_cmd_brdcast_req    = false;
630      r_xram_rsp_to_ixr_cmd_req             = false;
631      r_xram_rsp_trt_index                      = 0;
632      m_xram_rsp_to_init_cmd_inst_fifo.init();
633      m_xram_rsp_to_init_cmd_srcid_fifo.init();
634#if L1_MULTI_CACHE
635      m_xram_rsp_to_init_cmd_cache_id_fifo.init();
636#endif
637
638      r_ixr_cmd_cpt         = 0;
639
640      r_copies_limit        = 3;
641
642      // Activity counters
643      m_cpt_cycles                  = 0;
644      m_cpt_read                    = 0;
645      m_cpt_read_miss       = 0;
646      m_cpt_write                   = 0;
647      m_cpt_write_miss      = 0;
648      m_cpt_write_cells     = 0;
649      m_cpt_write_dirty     = 0;
650      m_cpt_update                  = 0;
651      m_cpt_update_mult     = 0;
652      m_cpt_inval_brdcast       = 0;
653      m_cpt_inval                   = 0;
654      m_cpt_inval_mult          = 0;
655      m_cpt_cleanup                 = 0;
656      m_cpt_ll                      = 0;
657      m_cpt_sc                      = 0;
658      m_cpt_trt_full        = 0;
659      m_cpt_trt_rb          = 0;
660
661      return;
662    }
663
664    bool    cmd_read_fifo_put = false;
665    bool    cmd_read_fifo_get = false;
666
667    bool    cmd_write_fifo_put = false;
668    bool    cmd_write_fifo_get = false;
669
670    bool    cmd_sc_fifo_put = false;
671    bool    cmd_sc_fifo_get = false;
672
673    bool    write_to_init_cmd_fifo_put      = false;
674    bool    write_to_init_cmd_fifo_get      = false;
675    bool    write_to_init_cmd_fifo_inst     = false;
676    size_t  write_to_init_cmd_fifo_srcid    = 0;
677
678#if L1_MULTI_CACHE
679    size_t  write_to_init_cmd_fifo_cache_id = 0;
680#endif
681
682    bool    xram_rsp_to_init_cmd_fifo_put      = false;
683    bool    xram_rsp_to_init_cmd_fifo_get      = false;
684    bool    xram_rsp_to_init_cmd_fifo_inst     = false;
685    size_t  xram_rsp_to_init_cmd_fifo_srcid    = 0;
686
687#if L1_MULTI_CACHE
688    size_t  xram_rsp_to_init_cmd_fifo_cache_id = 0;
689#endif
690
691    bool    sc_to_init_cmd_fifo_put      = false;
692    bool    sc_to_init_cmd_fifo_get      = false;
693    bool    sc_to_init_cmd_fifo_inst     = false;
694    size_t  sc_to_init_cmd_fifo_srcid    = 0;
695
696#if L1_MULTI_CACHE
697    size_t  sc_to_init_cmd_fifo_cache_id = 0;
698#endif
699
700m_debug_global       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
701m_debug_tgt_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
702m_debug_tgt_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
703m_debug_init_cmd_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
704m_debug_init_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
705m_debug_read_fsm     = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
706m_debug_write_fsm    = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
707m_debug_sc_fsm       = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
708m_debug_cleanup_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
709m_debug_ixr_cmd_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
710m_debug_ixr_rsp_fsm  = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
711m_debug_xram_rsp_fsm = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
712
713
714#if DEBUG_MEMC_GLOBAL   
715if( m_debug_global )
716{
717    std::cout << "---------------------------------------------" << std::dec << std::endl;
718    std::cout << "MEM_CACHE " << m_srcid_ini << " ; Time = " << m_cpt_cycles << std::endl
719      << " - TGT_CMD FSM    = " << tgt_cmd_fsm_str[r_tgt_cmd_fsm] << std::endl
720      << " - TGT_RSP FSM    = " << tgt_rsp_fsm_str[r_tgt_rsp_fsm] << std::endl
721      << " - INIT_CMD FSM   = " << init_cmd_fsm_str[r_init_cmd_fsm] << std::endl
722      << " - INIT_RSP FSM   = " << init_rsp_fsm_str[r_init_rsp_fsm] << std::endl
723      << " - READ FSM       = " << read_fsm_str[r_read_fsm] << std::endl
724      << " - WRITE FSM      = " << write_fsm_str[r_write_fsm] << std::endl
725      << " - SC FSM         = " << sc_fsm_str[r_sc_fsm] << std::endl
726      << " - CLEANUP FSM    = " << cleanup_fsm_str[r_cleanup_fsm] << std::endl
727      << " - IXR_CMD FSM    = " << ixr_cmd_fsm_str[r_ixr_cmd_fsm] << std::endl
728      << " - IXR_RSP FSM    = " << ixr_rsp_fsm_str[r_ixr_rsp_fsm] << std::endl
729      << " - XRAM_RSP FSM   = " << xram_rsp_fsm_str[r_xram_rsp_fsm] << std::endl
730      << " - ALLOC_DIR FSM  = " << alloc_dir_fsm_str[r_alloc_dir_fsm] << std::endl
731      << " - ALLOC_TRT FSM  = " << alloc_trt_fsm_str[r_alloc_trt_fsm] << std::endl
732      << " - ALLOC_UPT FSM  = " << alloc_upt_fsm_str[r_alloc_upt_fsm] << std::endl
733      << " - ALLOC_HEAP FSM = " << alloc_heap_fsm_str[r_alloc_heap_fsm] << std::endl;
734}
735#endif
736
737    ////////////////////////////////////////////////////////////////////////////////////
738    //          TGT_CMD FSM
739    ////////////////////////////////////////////////////////////////////////////////////
740    // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors
741    //
742    // There is 3 types of accepted commands :
743    // - READ    : a READ request has a length of 1 VCI cell. It can be a single word
744    //             or an entire cache line, depending on the PLEN value.
745    // - WRITE   : a WRITE request has a maximum length of 16 cells, and can only
746    //             concern words in a same line.
747    // - SC      : The SC request has a length of 2 cells or 4 cells.
748    ////////////////////////////////////////////////////////////////////////////////////
749
750    switch ( r_tgt_cmd_fsm.read() )
751    {
752        //////////////////
753        case TGT_CMD_IDLE:
754        {
755            if ( p_vci_tgt.cmdval )
756            {
757
758#if DEBUG_MEMC_TGT_CMD
759if( m_debug_tgt_cmd_fsm )
760{
761    std::cout << "  <MEMC.TGT_CMD_IDLE> Receive command from srcid " << p_vci_tgt.srcid.read()
762              << " / for address " << p_vci_tgt.address.read() << std::endl;
763}
764#endif
765                if ( p_vci_tgt.cmd.read() == vci_param::CMD_READ )
766                {
767                    r_tgt_cmd_fsm = TGT_CMD_READ;
768                }
769                else if ( p_vci_tgt.cmd.read() == vci_param::CMD_WRITE )
770                { 
771                    r_tgt_cmd_fsm = TGT_CMD_WRITE;
772                }
773                else if ( p_vci_tgt.cmd.read() == vci_param::CMD_STORE_COND )
774                {
775                    r_tgt_cmd_fsm = TGT_CMD_ATOMIC;
776                }
777                else
778                {
779                    std::cout << "VCI_MEM_CACHE ERROR " << name()
780                              << " TGT_CMD_IDLE state" << std::endl;
781                    std::cout << " illegal VCI command type" << std::endl;
782                    exit(0);
783                }
784            }
785            break;
786        }
787        //////////////////
788        case TGT_CMD_READ:
789        {
790            if ((m_x[(vci_addr_t)p_vci_tgt.address.read()]+(p_vci_tgt.plen.read()>>2)) > 16)
791            {
792                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
793                std::cout << " illegal address/plen combination for VCI read command" << std::endl;
794                exit(0);
795            }
796            if ( !p_vci_tgt.eop.read() )
797            {
798                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state" << std::endl;
799                std::cout << " read command packets must contain one single flit" << std::endl;
800                exit(0);
801            }
802
803            if ( p_vci_tgt.cmdval && m_cmd_read_addr_fifo.wok() )
804            {
805           
806#if DEBUG_MEMC_TGT_CMD
807if( m_debug_tgt_cmd_fsm )
808{
809    std::cout << "  <MEMC.TGT_CMD_READ> Push into read_fifo:"
810              << " address = " << std::hex << p_vci_tgt.address.read()
811              << " srcid = " << p_vci_tgt.srcid.read()
812              << " trdid = " << p_vci_tgt.trdid.read()
813              << " plen = " << p_vci_tgt.plen.read() << std::endl;
814}
815#endif
816                cmd_read_fifo_put = true;
817                m_cpt_read++;
818                r_tgt_cmd_fsm = TGT_CMD_IDLE;
819            }
820            break;
821        }
822        ///////////////////
823        case TGT_CMD_WRITE:
824        {
825            if ( p_vci_tgt.cmdval && m_cmd_write_addr_fifo.wok() )
826            {
827           
828#if DEBUG_MEMC_TGT_CMD
829if( m_debug_tgt_cmd_fsm )
830{
831    std::cout << "  <MEMC.TGT_CMD_WRITE> Push into write_fifo:"
832              << " address = " << std::hex << p_vci_tgt.address.read()
833              << " srcid = " << p_vci_tgt.srcid.read()
834              << " trdid = " << p_vci_tgt.trdid.read()
835              << " wdata = " << p_vci_tgt.wdata.read()
836              << " be = " << p_vci_tgt.be.read()
837              << " plen = " << p_vci_tgt.plen.read() << std::endl;
838}
839#endif
840                cmd_write_fifo_put = true;
841                if(  p_vci_tgt.eop )  r_tgt_cmd_fsm = TGT_CMD_IDLE;
842            }
843            break;
844        }
845        ////////////////////
846        case TGT_CMD_ATOMIC:
847        {
848            if ( (p_vci_tgt.plen.read() != 8) && (p_vci_tgt.plen.read() != 16) )
849            {
850                std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_ATOMIC state" << std::endl;
851                std::cout << "illegal format for sc command " << std::endl;
852                exit(0);
853            }
854
855            if ( p_vci_tgt.cmdval && m_cmd_sc_addr_fifo.wok() )
856            {
857           
858#if DEBUG_MEMC_TGT_CMD
859if( m_debug_tgt_cmd_fsm )
860{
861    std::cout << "  <MEMC.TGT_CMD_ATOMIC> Pushing command into cmd_sc_fifo:"
862              << " address = " << std::hex << p_vci_tgt.address.read()
863              << " srcid = " << p_vci_tgt.srcid.read()
864              << " trdid = " << p_vci_tgt.trdid.read()
865              << " wdata = " << p_vci_tgt.wdata.read()
866              << " be = " << p_vci_tgt.be.read()
867              << " plen = " << p_vci_tgt.plen.read() << std::endl;
868}
869#endif
870                cmd_sc_fifo_put = true;
871                if( p_vci_tgt.eop ) r_tgt_cmd_fsm = TGT_CMD_IDLE;
872            }
873            break;
874        }
875    } // end switch tgt_cmd_fsm
876
877    /////////////////////////////////////////////////////////////////////////
878    //          INIT_RSP FSM
879    /////////////////////////////////////////////////////////////////////////
880    // This FSM controls the response to the update or inval coherence
881    // requests sent by the memory cache to the L1 caches :
882    //
883    // It can be update or inval requests initiated by the WRITE FSM,
884    // or inval requests initiated by the XRAM_RSP FSM. 
885    // The FSM decrements the proper entry in UPT.
886    // It sends a request to the TGT_RSP FSM to complete the pending
887    // write transaction (acknowledge response to the writer processor),
888    // and clear the UPT entry when all responses have been received. 
889    //
890    // All those response packets are one word, compact
891    // packets complying with the VCI advanced format.
892    // The index in the Table is defined in the RTRDID field, and
893    // the transaction type is defined in the UPT entry.
894    /////////////////////////////////////////////////////////////////////
895
896    switch ( r_init_rsp_fsm.read() )
897    {
898        ///////////////////
899        case INIT_RSP_IDLE:   // wait a response for a coherence transaction
900        {
901            if ( p_vci_ini.rspval )
902            {
903
904#if DEBUG_MEMC_INIT_RSP
905if( m_debug_init_rsp_fsm )
906{
907    std::cout <<  "  <MEMC.INIT_RSP_IDLE> Response for UPT entry "
908              << p_vci_ini.rtrdid.read() << std::endl;
909}
910#endif
911                if ( p_vci_ini.rtrdid.read() >= m_update_tab.size() )
912                {
913                    std::cout << "VCI_MEM_CACHE ERROR " << name()
914                              << " INIT_RSP_IDLE state" << std::endl;
915                    std::cout << "index too large for UPT: "
916                              << " / rtrdid = " << p_vci_ini.rtrdid.read()
917                              << " / UPT size = " << m_update_tab.size() << std::endl;
918                    exit(0);
919                }
920                if ( !p_vci_ini.reop.read() )
921                {
922                    std::cout << "VCI_MEM_CACHE ERROR " << name()
923                              << " INIT_RSP_IDLE state" << std::endl;
924                    std::cout << "all coherence response packets must be one flit" << std::endl;
925                    exit(0);
926                }
927
928                r_init_rsp_upt_index = p_vci_ini.rtrdid.read();
929                r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
930            }
931            else if( r_write_to_init_rsp_req.read() )
932            {
933                r_init_rsp_upt_index = r_write_to_init_rsp_upt_index.read();
934                r_write_to_init_rsp_req = false;
935                r_init_rsp_fsm = INIT_RSP_UPT_LOCK;
936            }
937            break;
938        }
939        ///////////////////////
940        case INIT_RSP_UPT_LOCK: // decrement the number of expected responses
941        {
942            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP )
943            {
944                size_t count = 0;
945                bool valid  = m_update_tab.decrement(r_init_rsp_upt_index.read(), count);
946
947#if DEBUG_MEMC_INIT_RSP
948if( m_debug_init_rsp_fsm )
949{
950    std::cout << "  <MEMC.INIT_RSP_UPT_LOCK> Decrement the responses counter for UPT:"
951              << " entry = " << r_init_rsp_upt_index.read()
952              << " / rsp_count = " << std::dec << count << std::endl;
953}
954#endif
955                if ( not valid )
956                {
957                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " INIT_RSP_UPT_LOCK state" << std::endl;
958                    std::cout << "unsuccessful access to decrement the UPT" << std::endl;
959                    exit(0);
960                }
961
962                if ( count == 0 ) r_init_rsp_fsm = INIT_RSP_UPT_CLEAR;
963                else              r_init_rsp_fsm = INIT_RSP_IDLE;
964            }
965            break;
966        }
967        ////////////////////////
968        case INIT_RSP_UPT_CLEAR:        // clear the UPT entry
969        {
970            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_INIT_RSP )
971            {
972                r_init_rsp_srcid = m_update_tab.srcid(r_init_rsp_upt_index.read());
973                r_init_rsp_trdid = m_update_tab.trdid(r_init_rsp_upt_index.read());
974                r_init_rsp_pktid = m_update_tab.pktid(r_init_rsp_upt_index.read());
975                r_init_rsp_nline = m_update_tab.nline(r_init_rsp_upt_index.read());
976                bool need_rsp    = m_update_tab.need_rsp(r_init_rsp_upt_index.read());
977
978                if ( need_rsp ) r_init_rsp_fsm = INIT_RSP_END;
979                else            r_init_rsp_fsm = INIT_RSP_IDLE;
980
981                m_update_tab.clear(r_init_rsp_upt_index.read());
982
983#if DEBUG_MEMC_INIT_RSP
984if ( m_debug_init_rsp_fsm )
985{
986    std::cout <<  "  <MEMC.INIT_RSP_UPT_CLEAR> Clear UPT entry "
987              << r_init_rsp_upt_index.read() <<  std::endl;
988}
989#endif
990            }
991            break;
992        }
993        //////////////////
994        case INIT_RSP_END:      // Post a request to TGT_RSP FSM
995        {
996            if ( !r_init_rsp_to_tgt_rsp_req )
997            {
998                r_init_rsp_to_tgt_rsp_req   = true;
999                r_init_rsp_to_tgt_rsp_srcid = r_init_rsp_srcid.read();
1000                r_init_rsp_to_tgt_rsp_trdid = r_init_rsp_trdid.read();
1001                r_init_rsp_to_tgt_rsp_pktid = r_init_rsp_pktid.read();
1002                r_init_rsp_fsm = INIT_RSP_IDLE;
1003
1004#if DEBUG_MEMC_INIT_RSP
1005if ( m_debug_init_rsp_fsm )
1006{
1007    std::cout <<  "  <MEMC.INIT_RSP_END> Request TGT_RSP FSM to send a response to srcid "
1008              << r_init_rsp_srcid.read() <<  std::endl;
1009}
1010#endif
1011            }
1012            break;
1013        }
1014    } // end switch r_init_rsp_fsm
1015
1016    ////////////////////////////////////////////////////////////////////////////////////
1017    //          READ FSM
1018    ////////////////////////////////////////////////////////////////////////////////////
1019    // The READ FSM controls the VCI read requests.
1020    // It takes the lock protecting the cache directory to check the cache line status:
1021    // - In case of HIT
1022    //   The fsm copies the data (one line, or one single word)
1023    //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
1024    //   The requesting initiator is registered in the cache directory.
1025    //   If the number of copy is larger than 1, the new copy is registered
1026    //   in the HEAP.
1027    //   If the number of copy is larger than the threshold, the HEAP is cleared,
1028    //   and the corresponding line switches to the counter mode.
1029    // - In case of MISS
1030    //   The READ fsm takes the lock protecting the transaction tab.
1031    //   If a read transaction to the XRAM for this line already exists,
1032    //   or if the transaction tab is full, the fsm is stalled.
1033    //   If a TRT entry is free, the READ request is registered in TRT,
1034    //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
1035    //   The READ FSM returns in the IDLE state as the read transaction will be
1036    //   completed when the missing line will be received.
1037    ////////////////////////////////////////////////////////////////////////////////////
1038
1039    switch ( r_read_fsm.read() )
1040    {
1041        ///////////////
1042        case READ_IDLE:         // waiting a read request
1043        {
1044            if (m_cmd_read_addr_fifo.rok())
1045            {
1046
1047#if DEBUG_MEMC_READ
1048if( m_debug_read_fsm )
1049{
1050    std::cout << "  <MEMC.READ_IDLE> Read request:"
1051              << " srcid = " << std::hex << m_cmd_read_srcid_fifo.read()
1052              << " / address = " << m_cmd_read_addr_fifo.read()
1053              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1054}
1055#endif
1056                r_read_fsm = READ_DIR_LOCK;
1057            }
1058            break;
1059        }
1060        ///////////////////
1061        case READ_DIR_LOCK:     // check directory for hit / miss
1062        {
1063            if ( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
1064            {
1065                size_t way = 0;
1066                DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
1067
1068                r_read_is_cnt     = entry.is_cnt;
1069                r_read_dirty      = entry.dirty;
1070                r_read_lock           = entry.lock;
1071                r_read_tag            = entry.tag;
1072                r_read_way            = way;
1073                r_read_count      = entry.count;
1074                r_read_copy       = entry.owner.srcid;
1075
1076#if L1_MULTI_CACHE
1077                r_read_copy_cache = entry.owner.cache_id;
1078#endif
1079                r_read_copy_inst  = entry.owner.inst;
1080                r_read_ptr        = entry.ptr;              // pointer to the heap
1081
1082                bool cached_read = (m_cmd_read_trdid_fifo.read() & 0x1);
1083                if(  entry.valid )      // hit
1084                {
1085                    // test if we need to register a new copy in the heap
1086                    if ( entry.is_cnt || (entry.count == 0) || !cached_read )
1087                        r_read_fsm = READ_DIR_HIT;
1088                    else
1089                        r_read_fsm = READ_HEAP_LOCK;
1090                }
1091                else                    // miss
1092                {
1093                    r_read_fsm = READ_TRT_LOCK;
1094                }
1095
1096#if DEBUG_MEMC_READ
1097if( m_debug_read_fsm )
1098{
1099    std::cout << "  <MEMC.READ_DIR_LOCK> Accessing directory: "
1100              << " address = " << std::hex << m_cmd_read_addr_fifo.read()
1101              << " / hit = " << entry.valid
1102              << " / count = " <<std::dec << entry.count
1103              << " / is_cnt = " << entry.is_cnt << std::endl;
1104}
1105#endif
1106            }
1107            break;
1108        }
1109        //////////////////
1110        case READ_DIR_HIT:          //  read data in cache & update the directory
1111                                //  we enter this state in 3 cases:
1112                                //  - the read request is uncachable
1113                                //  - the cache line is in counter mode
1114                                //  - the cache line is valid but not replcated
1115        {
1116            if( r_alloc_dir_fsm.read() == ALLOC_DIR_READ )
1117            {
1118                // signals generation
1119                bool inst_read    = (m_cmd_read_trdid_fifo.read() & 0x2);
1120                bool cached_read  = (m_cmd_read_trdid_fifo.read() & 0x1);
1121                bool is_cnt       = r_read_is_cnt.read();
1122
1123                // read data in the cache
1124                size_t set        = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1125                size_t way        = r_read_way.read();
1126                for ( size_t i=0 ; i<m_words ; i++ ) r_read_data[i] = m_cache_data[way][set][i];
1127
1128                // update the cache directory
1129                DirectoryEntry entry;
1130                entry.valid       = true;
1131                entry.is_cnt  = is_cnt;
1132                entry.dirty       = r_read_dirty.read();
1133                entry.tag         = r_read_tag.read();
1134                entry.lock        = r_read_lock.read();
1135                entry.ptr     = r_read_ptr.read();
1136                if (cached_read)  // Cached read => we must update the copies
1137                {
1138                    if (!is_cnt) // Not counter mode
1139                    {
1140                        entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1141#if L1_MULTI_CACHE
1142                        entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1143#endif
1144                        entry.owner.inst     = inst_read;
1145                        entry.count          = r_read_count.read() + 1;
1146                    }
1147                    else  // Counter mode
1148                    {
1149                        entry.owner.srcid    = 0;
1150#if L1_MULTI_CACHE
1151                        entry.owner.cache_id = 0;
1152#endif
1153                        entry.owner.inst     = false;
1154                        entry.count          = r_read_count.read() + 1;
1155                    }
1156                }
1157                else  // Uncached read
1158                {
1159                    entry.owner.srcid     = r_read_copy.read();
1160#if L1_MULTI_CACHE
1161                    entry.owner.cache_id  = r_read_copy_cache.read();
1162#endif
1163                    entry.owner.inst      = r_read_copy_inst.read();
1164                    entry.count           = r_read_count.read();
1165                }
1166
1167#if DEBUG_MEMC_READ
1168if( m_debug_read_fsm )
1169{
1170    std::cout << "  <MEMC.READ_DIR_HIT> Update directory entry:"
1171              << " set = " << std::dec << set
1172              << " / way = " << way
1173              << " / owner_id = " << entry.owner.srcid
1174              << " / owner_ins = " << entry.owner.inst
1175              << " / count = " << entry.count
1176              << " / is_cnt = " << entry.is_cnt << std::endl;
1177}
1178#endif
1179
1180                m_cache_directory.write(set, way, entry);
1181                r_read_fsm    = READ_RSP;
1182            }
1183            break;
1184        }
1185        ////////////////////
1186        case READ_HEAP_LOCK:    // read data in cache, update the directory
1187                                // and prepare the HEAP update       
1188        {
1189            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1190            {
1191                // enter counter mode when we reach the limit of copies or the heap is full
1192                bool go_cnt = (r_read_count.read() >= r_copies_limit.read()) || m_heap.is_full();
1193
1194                // read data in the cache
1195                size_t set = m_y[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1196                size_t way = r_read_way.read();
1197                for ( size_t i=0 ; i<m_words ; i++ ) r_read_data[i] = m_cache_data[way][set][i];
1198
1199                // update the cache directory
1200                DirectoryEntry entry;
1201                entry.valid       = true;
1202                entry.is_cnt  = go_cnt;
1203                entry.dirty       = r_read_dirty.read();
1204                entry.tag         = r_read_tag.read();
1205                entry.lock        = r_read_lock.read();
1206                entry.count   = r_read_count.read() + 1;
1207
1208                if (not go_cnt)        // Not entering counter mode
1209                {
1210                    entry.owner.srcid   = r_read_copy.read();
1211#if L1_MULTI_CACHE
1212                    entry.owner.cache_id= r_read_copy_cache.read();
1213#endif
1214                    entry.owner.inst    = r_read_copy_inst.read();
1215                    entry.ptr           = m_heap.next_free_ptr();   // set pointer on the heap
1216                }
1217                else                // Entering Counter mode
1218                {
1219                    entry.owner.srcid   = 0;
1220#if L1_MULTI_CACHE
1221                    entry.owner.cache_id= 0;
1222#endif
1223                    entry.owner.inst    = false;
1224                    entry.ptr           = 0;
1225                }
1226
1227                m_cache_directory.write(set, way, entry);
1228
1229                // prepare the heap update (add an entry, or clear the linked list)
1230                if (not go_cnt)     // not switching to counter mode
1231                {
1232                    // We test if the next free entry in the heap is the last
1233                    HeapEntry heap_entry = m_heap.next_free_entry();
1234                    r_read_next_ptr      = heap_entry.next;
1235                    r_read_last_free     = ( heap_entry.next == m_heap.next_free_ptr() );
1236
1237                    r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
1238                }
1239                else                    // switching to counter mode
1240                {
1241                    if ( r_read_count.read()>1 )            // heap must be cleared
1242                    {
1243                        HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1244                        r_read_next_ptr      = m_heap.next_free_ptr();
1245                        m_heap.write_free_ptr(r_read_ptr.read());
1246
1247                        if( next_entry.next == r_read_ptr.read() )  // last entry
1248                        {
1249                            r_read_fsm = READ_HEAP_LAST;    // erase the entry
1250                        }
1251                        else                                        // not the last entry
1252                        {
1253                            r_read_ptr = next_entry.next;
1254                            r_read_fsm = READ_HEAP_ERASE;   // erase the list
1255                        }
1256                    }
1257                    else        // the heap is not used / nothing to do
1258                    {
1259                        r_read_fsm = READ_RSP;
1260                    }
1261                }
1262
1263#if DEBUG_MEMC_READ
1264if( m_debug_read_fsm )
1265{
1266    std::cout << "  <MEMC.READ_HEAP_LOCK> Update directory:"
1267              << " tag = " << std::hex << entry.tag
1268              << " set = " << std::dec << set
1269              << " way = " << way
1270              << " count = " << entry.count
1271              << " is_cnt = " << entry.is_cnt << std::endl;
1272}
1273#endif
1274            }
1275            break;
1276        }
1277        /////////////////////
1278        case READ_HEAP_WRITE:       // add a entry in the heap
1279        {
1280            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1281            {
1282                HeapEntry heap_entry;
1283                heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
1284#if L1_MULTI_CACHE
1285                heap_entry.owner.cache_id = m_cmd_read_pktid_fifo.read();
1286#endif
1287                heap_entry.owner.inst     = (m_cmd_read_trdid_fifo.read() & 0x2);
1288
1289                if(r_read_count.read() == 1)    // creation of a new linked list
1290                {
1291                    heap_entry.next         = m_heap.next_free_ptr();
1292                }
1293                else                            // head insertion in existing list
1294                {
1295                    heap_entry.next         = r_read_ptr.read();
1296                }
1297                m_heap.write_free_entry(heap_entry);
1298                m_heap.write_free_ptr(r_read_next_ptr.read());
1299                if(r_read_last_free.read())  m_heap.set_full();
1300
1301                r_read_fsm = READ_RSP;
1302
1303#if DEBUG_MEMC_READ
1304if( m_debug_read_fsm )
1305{
1306    std::cout << "  <MEMC.READ_HEAP_WRITE> Add an entry in the heap:"
1307              << " owner_id = " << heap_entry.owner.srcid
1308              << " owner_ins = " << heap_entry.owner.inst << std::endl;
1309}
1310#endif
1311            }
1312            else
1313            {
1314                std::cout << "VCI_MEM_CACHE ERROR " << name()
1315                          << " READ_HEAP_WRITE state" << std::endl;
1316                std::cout << "Bad HEAP allocation" << std::endl;
1317                exit(0);
1318            }
1319            break;
1320        }
1321        /////////////////////
1322        case READ_HEAP_ERASE:
1323        {
1324            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1325            {
1326                HeapEntry next_entry = m_heap.read(r_read_ptr.read());
1327                if( next_entry.next == r_read_ptr.read() )
1328                {
1329                    r_read_fsm = READ_HEAP_LAST;
1330                }
1331                else
1332                {
1333                    r_read_ptr = next_entry.next;
1334                    r_read_fsm = READ_HEAP_ERASE;
1335                }
1336            }
1337            else
1338            {
1339                std::cout << "VCI_MEM_CACHE ERROR " << name()
1340                          << " READ_HEAP_ERASE state" << std::endl;
1341                std::cout << "Bad HEAP allocation" << std::endl;
1342                exit(0);
1343            }
1344            break;
1345        }
1346        ////////////////////
1347        case READ_HEAP_LAST:
1348        {
1349            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_READ )
1350            {
1351                HeapEntry last_entry;
1352                last_entry.owner.srcid    = 0;
1353#if L1_MULTI_CACHE
1354                last_entry.owner.cache_id = 0;
1355#endif
1356                last_entry.owner.inst     = false;
1357
1358                if(m_heap.is_full())
1359                {
1360                    last_entry.next       = r_read_ptr.read();
1361                    m_heap.unset_full();
1362                }
1363                else
1364                {
1365                    last_entry.next       = r_read_next_ptr.read();
1366                }
1367                m_heap.write(r_read_ptr.read(),last_entry);
1368                r_read_fsm = READ_RSP;
1369            }
1370            else
1371            {
1372                std::cout << "VCI_MEM_CACHE ERROR " << name()
1373                          << " READ_HEAP_LAST state" << std::endl;
1374                std::cout << "Bad HEAP allocation" << std::endl;
1375                exit(0);
1376            }
1377            break;
1378        }
1379        //////////////
1380        case READ_RSP:          //  request the TGT_RSP FSM to return data
1381        {
1382            if( !r_read_to_tgt_rsp_req )
1383            {   
1384                for ( size_t i=0 ; i<m_words ; i++ )  r_read_to_tgt_rsp_data[i] = r_read_data[i];
1385                r_read_to_tgt_rsp_word   = m_x[(vci_addr_t)m_cmd_read_addr_fifo.read()];
1386                r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
1387                r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
1388                r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
1389                r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
1390                cmd_read_fifo_get        = true;
1391                r_read_to_tgt_rsp_req    = true;
1392                r_read_fsm               = READ_IDLE; 
1393
1394#if DEBUG_MEMC_READ
1395if( m_debug_read_fsm )
1396{
1397    std::cout << "  <MEMC.READ_RSP> Request the TGT_RSP FSM to return data:"
1398              << " rsrcid = " << std::hex << m_cmd_read_srcid_fifo.read()
1399              << " / address = " << m_cmd_read_addr_fifo.read()
1400              << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
1401}
1402#endif
1403            }
1404            break;
1405        }
1406        ///////////////////
1407        case READ_TRT_LOCK:     // read miss : check the Transaction Table
1408        {
1409            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ )
1410            {
1411                size_t      index     = 0;
1412                vci_addr_t  addr      = (vci_addr_t)m_cmd_read_addr_fifo.read();
1413                bool        hit_read  = m_transaction_tab.hit_read(m_nline[addr], index);
1414                bool        hit_write = m_transaction_tab.hit_write(m_nline[addr]);
1415                bool        wok       = !m_transaction_tab.full(index);
1416
1417                if( hit_read || !wok || hit_write )  // missing line already requested or no space
1418                {
1419                    if(!wok)                    m_cpt_trt_full++;
1420                    if(hit_read || hit_write)   m_cpt_trt_rb++;
1421                    r_read_fsm = READ_IDLE;
1422                }
1423                else                                // missing line is requested to the XRAM
1424                {
1425                    m_cpt_read_miss++;
1426                    r_read_trt_index = index;
1427                    r_read_fsm       = READ_TRT_SET;
1428                }
1429
1430#if DEBUG_MEMC_READ
1431if( m_debug_read_fsm )
1432{
1433    std::cout << "  <MEMC.READ_TRT_LOCK> Check TRT:"
1434              << " hit_read = " << hit_read
1435              << " / hit_write = " << hit_write
1436              << " / full = " << !wok << std::endl;
1437}
1438#endif
1439            }
1440            break;
1441        }
1442        //////////////////
1443        case READ_TRT_SET:      // register get transaction in TRT
1444        {
1445            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_READ )
1446            {
1447                m_transaction_tab.set(r_read_trt_index.read(),
1448                                      true,
1449                                      m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1450                                      m_cmd_read_srcid_fifo.read(),
1451                                      m_cmd_read_trdid_fifo.read(),
1452                                      m_cmd_read_pktid_fifo.read(),
1453                                      true,
1454                                      m_cmd_read_length_fifo.read(),
1455                                      m_x[(vci_addr_t)(m_cmd_read_addr_fifo.read())],
1456                                      std::vector<be_t>(m_words,0),
1457                                      std::vector<data_t>(m_words,0));
1458#if DEBUG_MEMC_READ
1459if( m_debug_read_fsm )
1460{
1461    std::cout << "  <MEMC.READ_TRT_SET> Write in Transaction Table: " << std::hex
1462              << " address = " << m_cmd_read_addr_fifo.read()
1463              << " / srcid = " << m_cmd_read_srcid_fifo.read() << std::endl;
1464}
1465#endif
1466                r_read_fsm = READ_TRT_REQ;
1467            }
1468            break;
1469        }
1470        //////////////////
1471        case READ_TRT_REQ:              // consume the read request in the FIFO,
1472                                                // and send it to the ixr_cmd_fsm
1473        {       
1474            if( not r_read_to_ixr_cmd_req )
1475            {
1476                cmd_read_fifo_get           = true;
1477                r_read_to_ixr_cmd_req   = true;
1478                r_read_to_ixr_cmd_nline = m_nline[(vci_addr_t)(m_cmd_read_addr_fifo.read())];
1479                r_read_to_ixr_cmd_trdid = r_read_trt_index.read();
1480                r_read_fsm                  = READ_IDLE;
1481
1482#if DEBUG_MEMC_READ
1483if( m_debug_read_fsm )
1484{
1485    std::cout << "  <MEMC.READ_TRT_REQ> Request GET transaction for address "
1486              << m_cmd_read_addr_fifo.read() << std::endl;
1487}
1488#endif
1489            }
1490            break;
1491        }
1492    } // end switch read_fsm
1493
1494    ///////////////////////////////////////////////////////////////////////////////////
1495    //          WRITE FSM
1496    ///////////////////////////////////////////////////////////////////////////////////
1497    // The WRITE FSM handles the write bursts sent by the processors.
1498    // All addresses in a burst must be in the same cache line.
1499    // A complete write burst is consumed in the FIFO & copied to a local buffer.
1500    // Then the FSM takes the lock protecting the cache directory, to check
1501    // if the line is in the cache.
1502    //
1503    // - In case of HIT, the cache is updated.
1504    //   If there is no other copy, an acknowledge response is immediately
1505    //   returned to the writing processor.
1506    //   If the data is cached by other processors, a coherence transaction must
1507    //   be launched:
1508    //   It is a multicast update if the line is not in counter mode, and the processor
1509    //   takes the lock protecting the Update Table (UPT) to register this transaction.
1510    //   It is a broadcast invalidate if the line is in counter mode.
1511    //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
1512    //   a multi-update request to all owners of the line (but the writer),
1513    //   through the INIT_CMD FSM. In case of multi-update transaction, the WRITE FSM
1514    //   does not respond to the writing processor, as this response will be sent by
1515    //   the INIT_RSP FSM when all update responses have been received.
1516    //
1517    // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
1518    //   table (TRT). If a read transaction to the XRAM for this line already exists,
1519    //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
1520    //   the WRITE FSM register a new transaction in TRT, and sends a read line request
1521    //   to the XRAM. If the TRT is full, it releases the lock, and waits.
1522    //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
1523    /////////////////////////////////////////////////////////////////////////////////////
1524
1525    switch ( r_write_fsm.read() )
1526    {
1527        ////////////////
1528        case WRITE_IDLE:        // copy first word of a write burst in local buffer     
1529        {
1530            if ( m_cmd_write_addr_fifo.rok() )
1531            {
1532                m_cpt_write++;
1533                m_cpt_write_cells++;
1534
1535                // consume a word in the FIFO & write it in the local buffer
1536                cmd_write_fifo_get      = true;
1537                size_t index            = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
1538
1539                r_write_address         = (addr_t)(m_cmd_write_addr_fifo.read());
1540                r_write_word_index      = index;
1541                r_write_word_count      = 1;
1542                r_write_data[index]     = m_cmd_write_data_fifo.read();
1543                r_write_srcid           = m_cmd_write_srcid_fifo.read();
1544                r_write_trdid           = m_cmd_write_trdid_fifo.read();
1545                r_write_pktid           = m_cmd_write_pktid_fifo.read();
1546
1547                // initialize the be field for all words
1548                for ( size_t i=0 ; i<m_words ; i++ )
1549                {
1550                    if ( i == index ) r_write_be[i] = m_cmd_write_be_fifo.read();
1551                    else              r_write_be[i] = 0x0;
1552                }
1553
1554                if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1555                    r_write_byte = true;
1556                else   
1557                    r_write_byte = false;
1558
1559                if( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1560                else                               r_write_fsm = WRITE_NEXT;
1561
1562#if DEBUG_MEMC_WRITE
1563if( m_debug_write_fsm )
1564{
1565    std::cout << "  <MEMC.WRITE_IDLE> Write request "
1566              << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
1567              << " / address = " << m_cmd_write_addr_fifo.read()
1568              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
1569}
1570#endif
1571            }
1572            break;
1573        }
1574        ////////////////
1575        case WRITE_NEXT:        // copy next word of a write burst in local buffer
1576        {
1577            if ( m_cmd_write_addr_fifo.rok() )
1578            {
1579
1580#if DEBUG_MEMC_WRITE
1581if( m_debug_write_fsm )
1582{
1583    std::cout << "  <MEMC.WRITE_NEXT> Write another word in local buffer" << std::endl;
1584}
1585#endif
1586                m_cpt_write_cells++;
1587
1588                // check that the next word is in the same cache line
1589                if ( (m_nline[(vci_addr_t)(r_write_address.read())] !=
1590                      m_nline[(vci_addr_t)(m_cmd_write_addr_fifo.read())]) )
1591                {
1592                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_NEXT state" << std::endl;
1593                    std::cout << "all words in a write burst must be in same cache line" << std::endl;
1594                    exit(0);
1595                }
1596
1597                // consume a word in the FIFO & write it in the local buffer
1598                cmd_write_fifo_get=true;
1599                size_t index            = r_write_word_index.read() + r_write_word_count.read();
1600
1601                r_write_be[index]       = m_cmd_write_be_fifo.read();
1602                r_write_data[index]     = m_cmd_write_data_fifo.read();
1603                r_write_word_count      = r_write_word_count.read() + 1;
1604
1605                if( !((m_cmd_write_be_fifo.read() == 0x0)||(m_cmd_write_be_fifo.read() == 0xF)) )
1606                    r_write_byte = true;
1607
1608                if ( m_cmd_write_eop_fifo.read() )  r_write_fsm = WRITE_DIR_LOCK;
1609            }
1610            break;
1611        }
1612        ////////////////////
1613        case WRITE_DIR_LOCK:    // access directory to check hit/miss
1614        {
1615            if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
1616            {
1617                size_t  way = 0;
1618                DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
1619
1620                if ( entry.valid ) // hit
1621                {       
1622                    // copy directory entry in local buffer in case of hit
1623                    r_write_is_cnt     = entry.is_cnt;
1624                    r_write_lock       = entry.lock;
1625                    r_write_tag        = entry.tag;
1626                    r_write_copy       = entry.owner.srcid;
1627#if L1_MULTI_CACHE
1628                    r_write_copy_cache = entry.owner.cache_id;
1629#endif
1630                    r_write_copy_inst  = entry.owner.inst;
1631                    r_write_count      = entry.count;
1632                    r_write_ptr        = entry.ptr;
1633                    r_write_way        = way;
1634
1635                    if( entry.is_cnt && entry.count )
1636                    {
1637                        r_write_fsm      = WRITE_DIR_HIT_READ;
1638                    }
1639                    else
1640                    {
1641                        if (r_write_byte.read())        r_write_fsm = WRITE_DIR_HIT_READ;
1642                        else                                    r_write_fsm = WRITE_DIR_HIT;
1643                    }
1644                }
1645                else    // miss
1646                {
1647                    r_write_fsm = WRITE_TRT_LOCK;
1648                }
1649
1650#if DEBUG_MEMC_WRITE
1651if( m_debug_write_fsm )
1652{
1653    std::cout << "  <MEMC.WRITE_DIR_LOCK> Check the directory: "
1654              << " address = " << r_write_address.read()
1655              << " hit = " << entry.valid
1656              << " count = " << std::dec << entry.count
1657              << " is_cnt = " << entry.is_cnt << std::endl;
1658}
1659#endif
1660            }
1661            break;
1662        }
1663        ////////////////////////
1664        case WRITE_DIR_HIT_READ:        // read the cache and complete the buffer when be!=0xF
1665        {
1666            // update local buffer
1667            size_t set  = m_y[(vci_addr_t)(r_write_address.read())];
1668            size_t way  = r_write_way.read();
1669            for(size_t i=0 ; i<m_words ; i++)
1670            {
1671                data_t mask = 0;
1672                if  (r_write_be[i].read() & 0x1) mask = mask | 0x000000FF;
1673                if  (r_write_be[i].read() & 0x2) mask = mask | 0x0000FF00;
1674                if  (r_write_be[i].read() & 0x4) mask = mask | 0x00FF0000;
1675                if  (r_write_be[i].read() & 0x8) mask = mask | 0xFF000000;
1676
1677                // complete only if mask is not null (for energy consumption)
1678                if ( r_write_be[i].read() || r_write_is_cnt.read() )
1679                {
1680                    r_write_data[i]  = (r_write_data[i].read() & mask) |
1681                                           (m_cache_data[way][set][i] & ~mask);
1682                }
1683            } // end for
1684
1685            // test if a coherence broadcast is required
1686            if( r_write_is_cnt.read() && r_write_count.read() ) r_write_fsm = WRITE_TRT_WRITE_LOCK;
1687            else                                                r_write_fsm = WRITE_DIR_HIT;
1688
1689#if DEBUG_MEMC_WRITE
1690if( m_debug_write_fsm )
1691{
1692    if( r_write_is_cnt.read() && r_write_count.read() )
1693    {
1694        std::cout << "  <MEMC.WRITE_DIR_HIT_READ> Read the cache to complete local buffer /"
1695                  << " coherence broadcast required" << std::endl;
1696    }
1697    else
1698    {
1699        std::cout << "  <MEMC.WRITE_DIR_HIT_READ> Read the cache to complete local buffer"
1700                  << std::endl;
1701    }
1702}
1703#endif
1704            break;
1705        }
1706        ///////////////////
1707        case WRITE_DIR_HIT:        // update the cache (data & directory)
1708        {
1709            // update directory with Dirty bit
1710            DirectoryEntry entry;
1711            entry.valid          = true;
1712            entry.dirty          = true;
1713            entry.tag            = r_write_tag.read();
1714            entry.is_cnt         = r_write_is_cnt.read();
1715            entry.lock           = r_write_lock.read();
1716            entry.owner.srcid    = r_write_copy.read();
1717#if L1_MULTI_CACHE
1718            entry.owner.cache_id = r_write_copy_cache.read();
1719#endif
1720            entry.owner.inst     = r_write_copy_inst.read();
1721            entry.count          = r_write_count.read();
1722            entry.ptr            = r_write_ptr.read();
1723            size_t set           = m_y[(vci_addr_t)(r_write_address.read())];
1724            size_t way           = r_write_way.read();
1725
1726            // update directory
1727            m_cache_directory.write(set, way, entry);
1728
1729            // owner is true when the writer is the owner
1730            bool owner = (((r_write_copy.read() == r_write_srcid.read())
1731#if L1_MULTI_CACHE
1732                         and (r_write_copy_cache.read()==r_write_pktid.read())
1733#endif
1734                         ) and not r_write_copy_inst.read());
1735
1736            // no_update is true when there is no need for coherence transaction
1737            bool no_update = (r_write_count.read()==0) || ( owner && (r_write_count.read()==1));
1738
1739            // write data in the cache if no transaction on the coherence network
1740            if( no_update )
1741            {
1742                for(size_t i=0 ; i<m_words ; i++)
1743                {
1744                    if  ( r_write_be[i].read() ) m_cache_data[way][set][i]  = r_write_data[i].read();
1745                }
1746            }
1747
1748            if ( owner )   r_write_count = r_write_count.read() - 1;
1749            r_write_to_dec = false;
1750
1751            if ( no_update )      // Write transaction completed
1752            {
1753                r_write_fsm = WRITE_RSP;
1754            }
1755            else          // coherence update required       
1756            {
1757                if( !r_write_to_init_cmd_multi_req.read() &&
1758                   !r_write_to_init_cmd_brdcast_req.read()  )   r_write_fsm = WRITE_UPT_LOCK;
1759                else                                            r_write_fsm = WRITE_WAIT;
1760            }
1761
1762#if DEBUG_MEMC_WRITE
1763if( m_debug_write_fsm )
1764{
1765    if ( no_update )
1766    {
1767        std::cout << "  <MEMC.WRITE_DIR_HIT> Write into cache / No coherence transaction"
1768                  << std::endl;
1769    }
1770    else
1771    {
1772        std::cout << "  <MEMC.WRITE_DIR_HIT> Coherence update required:"
1773                  << " is_cnt = " << r_write_is_cnt.read()
1774                  << " count = " << std::dec << r_write_count.read()
1775                  << std::endl;
1776    }
1777}
1778#endif
1779            break;
1780        }
1781        /////////////////////
1782        case WRITE_UPT_LOCK:    // Try to register the update request in UPT
1783        {
1784            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
1785            {
1786                bool        wok        = false;
1787                size_t      index      = 0;
1788                size_t      srcid      = r_write_srcid.read();
1789                size_t      trdid      = r_write_trdid.read();
1790                size_t      pktid      = r_write_pktid.read();
1791                addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
1792                size_t      nb_copies  = r_write_count.read();
1793                size_t      set        = m_y[(vci_addr_t)(r_write_address.read())];
1794                size_t      way        = r_write_way.read();
1795
1796                wok = m_update_tab.set(true,    // it's an update transaction
1797                                      false,    // it's not a broadcast
1798                                      true,     // it needs a response
1799                                      srcid,
1800                                      trdid,
1801                                      pktid,
1802                                      nline,
1803                                      nb_copies,
1804                                      index);
1805                if ( wok )    // write data in cache
1806                {
1807                    for(size_t i=0 ; i<m_words ; i++)
1808                    {
1809                        if ( r_write_be[i].read() ) m_cache_data[way][set][i] = r_write_data[i].read();
1810                    }
1811                }
1812
1813#if DEBUG_MEMC_WRITE
1814if( m_debug_write_fsm )
1815{
1816    if ( wok )
1817    {
1818        std::cout << "  <MEMC.WRITE_UPT_LOCK> Register the multicast update in UPT / "
1819                  << " nb_copies = " << r_write_count.read() << std::endl;
1820        //m_update_tab.print();
1821    }
1822}
1823#endif
1824                r_write_upt_index = index;
1825                //  releases the lock protecting the Update Table and the Directory if no entry...
1826                if ( wok ) r_write_fsm = WRITE_HEAP_LOCK;
1827                else       r_write_fsm = WRITE_WAIT;
1828            }
1829            break;
1830        }
1831        /////////////////////
1832        case WRITE_HEAP_LOCK:
1833        {
1834            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE )
1835            {
1836
1837#if DEBUG_MEMC_WRITE
1838if( m_debug_write_fsm )
1839{
1840    std::cout << "  <MEMC.WRITE_HEAP_LOCK> Get acces to the HEAP" << std::endl;
1841}
1842#endif
1843                r_write_fsm = WRITE_UPT_REQ;
1844            }
1845            break;
1846        }
1847        //////////////////
1848        case WRITE_UPT_REQ:
1849        {
1850            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_WRITE )
1851            {
1852                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_REQ state" << std::endl;
1853                std::cout << "bad HEAP allocation" << std::endl;
1854                exit(0);
1855            }
1856
1857            if( !r_write_to_init_cmd_multi_req.read() &&
1858                !r_write_to_init_cmd_brdcast_req.read()  )
1859            {
1860                r_write_to_init_cmd_brdcast_req  = false;
1861                r_write_to_init_cmd_trdid        = r_write_upt_index.read();
1862                r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
1863                r_write_to_init_cmd_index        = r_write_word_index.read();
1864                r_write_to_init_cmd_count        = r_write_word_count.read();
1865
1866                for(size_t i=0; i<m_words ; i++)
1867                {
1868                    r_write_to_init_cmd_be[i]=r_write_be[i].read();
1869                }
1870
1871                size_t min = r_write_word_index.read();
1872                size_t max = r_write_word_index.read() + r_write_word_count.read();
1873                for (size_t i=min ; i<max ; i++)  r_write_to_init_cmd_data[i] = r_write_data[i];
1874           
1875                if( (r_write_copy.read() != r_write_srcid.read()) or
1876#if L1_MULTI_CACHE
1877                    (r_write_copy_cache.read() != r_write_pktid.read()) or
1878#endif
1879                    r_write_copy_inst.read() )
1880                {
1881                    // We put the first copy in the fifo
1882                    write_to_init_cmd_fifo_put     = true;
1883                    write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
1884                    write_to_init_cmd_fifo_srcid   = r_write_copy.read();
1885#if L1_MULTI_CACHE
1886                    write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
1887#endif
1888                    if(r_write_count.read() == 1)
1889                    {
1890                        r_write_fsm = WRITE_IDLE;
1891                        r_write_to_init_cmd_multi_req = true;
1892                    }
1893                    else
1894                    {
1895                        r_write_fsm = WRITE_UPDATE;
1896                    }
1897                }
1898                else
1899                {
1900                    r_write_fsm = WRITE_UPDATE;
1901                }
1902            }
1903            break;
1904        }
1905        //////////////////
1906        case WRITE_UPDATE:      // send a multi-update request to INIT_CMD fsm
1907        {
1908            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_WRITE )
1909            {
1910                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPDATE state" << std::endl;
1911                std::cout << "bad HEAP allocation" << std::endl;
1912                exit(0);
1913            }
1914
1915            HeapEntry entry = m_heap.read(r_write_ptr.read());
1916            write_to_init_cmd_fifo_inst     = entry.owner.inst;
1917            write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
1918#if L1_MULTI_CACHE
1919            write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
1920#endif
1921         
1922            bool dec_upt_counter = r_write_to_dec.read();
1923            if( (entry.owner.srcid != r_write_srcid.read()) or
1924#if L1_MULTI_CACHE
1925                (entry.owner.cache_id != r_write_pktid.read()) or
1926#endif
1927                entry.owner.inst)
1928            {
1929                write_to_init_cmd_fifo_put = true;
1930            }
1931            else
1932            {
1933                dec_upt_counter = true;
1934            }
1935            r_write_to_dec = dec_upt_counter;
1936
1937            if( m_write_to_init_cmd_inst_fifo.wok() )
1938            {
1939                r_write_ptr = entry.next;
1940                if( entry.next == r_write_ptr.read() )  // last copy
1941                {
1942                    r_write_to_init_cmd_multi_req = true;
1943                    if(dec_upt_counter) r_write_fsm = WRITE_UPT_DEC;
1944                    else                r_write_fsm = WRITE_IDLE;
1945                }
1946                else
1947                {
1948                    r_write_fsm = WRITE_UPDATE;
1949                }
1950            }
1951            else
1952            {
1953                r_write_fsm = WRITE_UPDATE;
1954            }
1955            break;
1956        }
1957        //////////////////
1958        case WRITE_UPT_DEC:     // Post another coherence update request
1959        {
1960            if ( !r_write_to_init_rsp_req.read() )
1961            {
1962                r_write_to_init_rsp_req = true;
1963                r_write_to_init_rsp_upt_index = r_write_upt_index.read();
1964                r_write_fsm = WRITE_IDLE;
1965            }
1966            break;
1967        }
1968        ///////////////
1969        case WRITE_RSP:         // Post a request to TGT_RSP FSM to acknowledge the write
1970        {
1971            if ( !r_write_to_tgt_rsp_req.read() )
1972            {
1973
1974#if DEBUG_MEMC_WRITE
1975if( m_debug_write_fsm )
1976{
1977    std::cout << "  <MEMC.WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
1978              << std::hex << r_write_srcid.read() << std:: endl;
1979}
1980#endif
1981                r_write_to_tgt_rsp_req   = true;
1982                r_write_to_tgt_rsp_srcid = r_write_srcid.read();
1983                r_write_to_tgt_rsp_trdid = r_write_trdid.read();
1984                r_write_to_tgt_rsp_pktid = r_write_pktid.read();
1985                r_write_fsm              = WRITE_IDLE;
1986            }
1987            break;
1988        }
1989        ////////////////////
1990        case WRITE_TRT_LOCK:    // Miss : check Transaction Table
1991        {
1992            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
1993            {
1994
1995#if DEBUG_MEMC_WRITE
1996if( m_debug_write_fsm )
1997{
1998    std::cout << "  <MEMC.WRITE_TRT_LOCK> Check the TRT" << std::endl;
1999}
2000#endif
2001                size_t          hit_index = 0;
2002                size_t          wok_index = 0;
2003                vci_addr_t      addr      = (vci_addr_t)r_write_address.read();
2004                bool            hit_read  = m_transaction_tab.hit_read(m_nline[addr], hit_index);
2005                bool            hit_write = m_transaction_tab.hit_write(m_nline[addr]);
2006                bool            wok       = !m_transaction_tab.full(wok_index);
2007
2008                if ( hit_read )         // register the modified data in TRT
2009                {
2010                    r_write_trt_index = hit_index;
2011                    r_write_fsm       = WRITE_TRT_DATA;
2012                    m_cpt_write_miss++;
2013                }
2014                else if ( wok && !hit_write )   // set a new entry in TRT
2015                {
2016                    r_write_trt_index = wok_index;
2017                    r_write_fsm       = WRITE_TRT_SET;
2018                    m_cpt_write_miss++;
2019                }
2020                else            // wait an empty entry in TRT
2021                {
2022                    r_write_fsm       = WRITE_WAIT;
2023                    m_cpt_trt_full++;
2024                }
2025            }
2026            break;
2027        }
2028        ////////////////
2029        case WRITE_WAIT:        // release the locks protecting the shared ressources
2030        {
2031
2032#if DEBUG_MEMC_WRITE
2033if( m_debug_write_fsm )
2034{
2035    std::cout << "  <MEMC.WRITE_WAIT> Releases the locks before retry" << std::endl;
2036}
2037#endif
2038            r_write_fsm = WRITE_DIR_LOCK;
2039            break;
2040        }
2041        ///////////////////
2042        case WRITE_TRT_SET:     // register a new transaction in TRT (Write Buffer)
2043        { 
2044            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2045            {
2046                std::vector<be_t>       be_vector;
2047                std::vector<data_t> data_vector;
2048                be_vector.clear();
2049                data_vector.clear();
2050                for ( size_t i=0; i<m_words; i++ )
2051                {
2052                    be_vector.push_back(r_write_be[i]);
2053                    data_vector.push_back(r_write_data[i]);
2054                }
2055                m_transaction_tab.set(r_write_trt_index.read(),
2056                                      true,                     // read request to XRAM
2057                                      m_nline[(vci_addr_t)(r_write_address.read())],
2058                                      r_write_srcid.read(),
2059                                      r_write_trdid.read(),
2060                                      r_write_pktid.read(),
2061                                      false,                    // not a processor read
2062                                      0,                        // not a single word
2063                                      0,                        // word index
2064                                      be_vector,
2065                                      data_vector);
2066                r_write_fsm = WRITE_XRAM_REQ;
2067
2068#if DEBUG_MEMC_WRITE
2069if( m_debug_write_fsm )
2070{
2071    std::cout << "  <MEMC.WRITE_TRT_SET> Set a new entry in TRT" << std::endl;
2072}
2073#endif
2074            }
2075            break;
2076        } 
2077        ////////////////////
2078        case WRITE_TRT_DATA:    // update an entry in TRT (Write Buffer)
2079        {
2080            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2081            {
2082                std::vector<be_t> be_vector;
2083                std::vector<data_t> data_vector;
2084                be_vector.clear();
2085                data_vector.clear();
2086                for ( size_t i=0; i<m_words; i++ )
2087                {
2088                    be_vector.push_back(r_write_be[i]);
2089                    data_vector.push_back(r_write_data[i]);
2090                }
2091                m_transaction_tab.write_data_mask(r_write_trt_index.read(),
2092                                                  be_vector,
2093                                                  data_vector);
2094                r_write_fsm = WRITE_RSP;
2095
2096#if DEBUG_MEMC_WRITE
2097if( m_debug_write_fsm )
2098{
2099    std::cout << "  <MEMC.WRITE_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2100    m_transaction_tab.print( r_write_trt_index.read() );
2101}
2102#endif
2103            }
2104            break;
2105        }
2106        ////////////////////
2107        case WRITE_XRAM_REQ:    // send a request to IXR_CMD FSM
2108        { 
2109            if ( !r_write_to_ixr_cmd_req )
2110            {
2111                r_write_to_ixr_cmd_req   = true;
2112                r_write_to_ixr_cmd_write = false;
2113                r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
2114                r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
2115                r_write_fsm              = WRITE_RSP;
2116
2117#if DEBUG_MEMC_WRITE
2118if( m_debug_write_fsm )
2119{
2120    std::cout << "  <MEMC.WRITE_XRAM_REQ> Post a request to the IXR_CMD FSM" << std::endl;
2121}
2122#endif
2123            }
2124            break;
2125        }
2126        //////////////////////////
2127        case WRITE_TRT_WRITE_LOCK:      // Check TRT not full
2128        {
2129            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2130            {
2131                size_t wok_index = 0;
2132                bool wok = !m_transaction_tab.full( wok_index );
2133                if ( wok )      // set a new entry in TRT
2134                {
2135                    r_write_trt_index = wok_index;
2136                    r_write_fsm       = WRITE_INVAL_LOCK;
2137                }
2138                else    // wait an empty entry in TRT
2139                {
2140                    r_write_fsm       = WRITE_WAIT;
2141                }
2142
2143#if DEBUG_MEMC_WRITE
2144if( m_debug_write_fsm )
2145{
2146    std::cout << "  <MEMC.WRITE_TRT_WRITE_LOCK> Check TRT : wok = "
2147              << wok << " index = " << wok_index << std::endl;
2148}
2149#endif
2150            }
2151            break;
2152        }
2153        //////////////////////
2154        case WRITE_INVAL_LOCK:
2155        {
2156            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
2157            {
2158                bool        wok       = false;
2159                size_t      index     = 0;
2160                size_t      srcid     = r_write_srcid.read();
2161                size_t      trdid     = r_write_trdid.read();
2162                size_t      pktid     = r_write_pktid.read();
2163                addr_t      nline     = m_nline[(vci_addr_t)(r_write_address.read())];
2164                size_t      nb_copies = r_write_count.read();
2165
2166                wok =m_update_tab.set(false,    // it's an inval transaction
2167                                      true,     // it's a broadcast
2168                                      true,     // it needs a response
2169                                      srcid,
2170                                      trdid,
2171                                      pktid,
2172                                      nline,
2173                                      nb_copies,
2174                                      index);
2175
2176#if DEBUG_MEMC_WRITE
2177if( m_debug_write_fsm )
2178{
2179    if ( wok )
2180    {
2181        std::cout << "  <MEMC.WRITE_INVAL_LOCK> Register the broadcast inval in UPT / "
2182                  << " nb_copies = " << r_write_count.read() << std::endl;
2183        //m_update_tab.print();
2184    }
2185}
2186#endif
2187                r_write_upt_index = index;
2188
2189                if ( wok ) r_write_fsm = WRITE_DIR_INVAL;
2190                else       r_write_fsm = WRITE_WAIT;
2191            }
2192            break;
2193        }
2194        /////////////////////
2195        case WRITE_DIR_INVAL:   // Register a put transaction to XRAM in TRT
2196                                // and invalidate the line in directory
2197        {
2198            if ( (r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE ) ||
2199                 (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE ) ||
2200                 (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE ) )
2201            {
2202                std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_DIR_INVAL state" << std::endl;
2203                std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
2204                exit(0);
2205            }
2206
2207            // register a write request to XRAM in TRT
2208            m_transaction_tab.set(r_write_trt_index.read(),
2209                                  false,                // write request to XRAM
2210                                  m_nline[(vci_addr_t)(r_write_address.read())],
2211                                  0,
2212                                  0,
2213                                  0,
2214                                  false,                // not a processor read
2215                                  0,                    // not a single word
2216                                  0,                    // word index
2217                                  std::vector<be_t>(m_words,0),
2218                                  std::vector<data_t>(m_words,0));
2219            // invalidate directory entry
2220            DirectoryEntry entry;
2221            entry.valid         = false;
2222            entry.dirty         = false;
2223            entry.tag           = 0;
2224            entry.is_cnt        = false;
2225            entry.lock          = false;
2226            entry.owner.srcid   = 0;
2227#if L1_MULTI_CACHE
2228            entry.owner.cache_id= 0;
2229#endif
2230            entry.owner.inst    = false;
2231            entry.ptr           = 0;
2232            entry.count         = 0;
2233            size_t set          = m_y[(vci_addr_t)(r_write_address.read())];
2234            size_t way          = r_write_way.read();
2235
2236            m_cache_directory.write(set, way, entry);
2237
2238#if DEBUG_MEMC_WRITE
2239if( m_debug_write_fsm )
2240{
2241    std::cout << "  <MEMC.WRITE_DIR_INVAL> Invalidate the directory entry: @ = "
2242              << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
2243}
2244#endif
2245            r_write_fsm = WRITE_INVAL;
2246            break;
2247        }
2248        /////////////////
2249        case WRITE_INVAL:    // Post a coherence broadcast request to INIT_CMD FSM
2250        {
2251            if ( !r_write_to_init_cmd_multi_req.read() && !r_write_to_init_cmd_brdcast_req.read() )
2252            {
2253                r_write_to_init_cmd_multi_req   = false;
2254                r_write_to_init_cmd_brdcast_req = true;
2255                r_write_to_init_cmd_trdid       = r_write_upt_index.read();
2256                r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
2257                r_write_to_init_cmd_index       = 0;
2258                r_write_to_init_cmd_count       = 0;
2259
2260                for(size_t i=0; i<m_words ; i++)
2261                {
2262                    r_write_to_init_cmd_be[i]=0;
2263                    r_write_to_init_cmd_data[i] = 0;
2264                }
2265                r_write_fsm = WRITE_XRAM_SEND;
2266
2267#if DEBUG_MEMC_WRITE
2268if( m_debug_write_fsm )
2269{
2270    std::cout << "  <MEMC.WRITE_INVAL> Post a broadcast request to INIT_CMD FSM" << std::endl;
2271}
2272#endif
2273            }
2274            break;
2275        }
2276        /////////////////////
2277        case WRITE_XRAM_SEND:   // Post a put request to IXR_CMD FSM
2278        {
2279            if ( !r_write_to_ixr_cmd_req )
2280            {
2281                r_write_to_ixr_cmd_req     = true;
2282                r_write_to_ixr_cmd_write   = true;
2283                r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
2284                r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
2285
2286                for(size_t i=0; i<m_words; i++) r_write_to_ixr_cmd_data[i] = r_write_data[i];
2287
2288                r_write_fsm = WRITE_IDLE;
2289
2290#if DEBUG_MEMC_WRITE
2291if( m_debug_write_fsm )
2292{
2293    std::cout << "  <MEMC.WRITE_XRAM_SEND> Post a put request to IXR_CMD FSM" << std::endl;
2294}
2295#endif
2296            }
2297            break;
2298        }
2299    } // end switch r_write_fsm
2300
2301    ///////////////////////////////////////////////////////////////////////
2302    //          IXR_CMD FSM
2303    ///////////////////////////////////////////////////////////////////////
2304    // The IXR_CMD fsm controls the command packets to the XRAM :
2305    // - It sends a single cell VCI get request to the XRAM in case of MISS
2306    // posted by the READ, WRITE or SC FSMs : the TRDID field contains
2307    // the Transaction Tab index.
2308    // The VCI response is a multi-cell packet : the N cells contain
2309    // the N data words.
2310    // - It sends a multi-cell VCI write when the XRAM_RSP FSM, WRITE FSM
2311    // or SC FSM request to save a dirty line to the XRAM.
2312    // The VCI response is a single cell packet.
2313    // This FSM handles requests from the READ, WRITE, SC & XRAM_RSP FSMs
2314    // with a round-robin priority.
2315    ////////////////////////////////////////////////////////////////////////
2316
2317    switch ( r_ixr_cmd_fsm.read() )
2318    {
2319        ////////////////////////
2320        case IXR_CMD_READ_IDLE:
2321        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2322        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2323        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2324        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2325        break;
2326        ////////////////////////
2327        case IXR_CMD_WRITE_IDLE:
2328        if      ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2329        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2330        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2331        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2332        break;
2333        ////////////////////////
2334        case IXR_CMD_SC_IDLE:
2335        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2336        else if ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2337        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2338        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2339        break;
2340        ////////////////////////
2341        case IXR_CMD_XRAM_IDLE:
2342        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2343        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2344        else if ( r_sc_to_ixr_cmd_req  )       r_ixr_cmd_fsm = IXR_CMD_SC_NLINE;
2345        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2346        break;
2347        /////////////////////////
2348        case IXR_CMD_READ_NLINE:
2349        if ( p_vci_ixr.cmdack )
2350        {
2351            r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;         
2352            r_read_to_ixr_cmd_req = false;
2353
2354#if DEBUG_MEMC_IXR_CMD
2355if( m_debug_ixr_cmd_fsm )
2356{
2357    std::cout << "  <MEMC.IXR_CMD_READ_NLINE> Send a get request to xram" ;
2358}
2359#endif
2360        }
2361        break;
2362        //////////////////////////
2363        case IXR_CMD_WRITE_NLINE:       
2364        if ( p_vci_ixr.cmdack )
2365        {
2366            if( r_write_to_ixr_cmd_write.read())
2367            {
2368                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2369                {
2370                    r_ixr_cmd_cpt = 0;
2371                    r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2372                    r_write_to_ixr_cmd_req = false;
2373                }
2374                else
2375                {
2376                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2377                }
2378
2379#if DEBUG_MEMC_IXR_CMD
2380if( m_debug_ixr_cmd_fsm )
2381{
2382    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a put request to xram" ;
2383}
2384#endif
2385            }
2386            else
2387            {
2388                r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;             
2389                r_write_to_ixr_cmd_req = false;
2390
2391#if DEBUG_MEMC_IXR_CMD
2392if( m_debug_ixr_cmd_fsm )
2393{
2394    std::cout << "  <MEMC.IXR_CMD_WRITE_NLINE> Send a get request to xram" ;
2395}
2396#endif
2397            }
2398        }
2399        break;
2400        //////////////////////
2401        case IXR_CMD_SC_NLINE:
2402        if ( p_vci_ixr.cmdack )
2403        {
2404            if( r_sc_to_ixr_cmd_write.read())
2405            {
2406                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2407                {
2408                    r_ixr_cmd_cpt = 0;
2409                    r_ixr_cmd_fsm = IXR_CMD_SC_IDLE;
2410                    r_sc_to_ixr_cmd_req = false;
2411                }
2412                else
2413                {
2414                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2415                }
2416
2417#if DEBUG_MEMC_IXR_CMD
2418if( m_debug_ixr_cmd_fsm )
2419{
2420    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a put request to xram" ;
2421}
2422#endif
2423            }
2424            else
2425            {
2426                r_ixr_cmd_fsm = IXR_CMD_SC_IDLE;               
2427                r_sc_to_ixr_cmd_req = false;
2428
2429#if DEBUG_MEMC_IXR_CMD
2430if( m_debug_ixr_cmd_fsm )
2431{
2432    std::cout << "  <MEMC.IXR_CMD_SC_NLINE> Send a get request to xram" ;
2433}
2434#endif
2435            }
2436        }
2437        break;
2438        ////////////////////////
2439        case IXR_CMD_XRAM_DATA:
2440        if ( p_vci_ixr.cmdack )
2441        {
2442            if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2443            {
2444                r_ixr_cmd_cpt = 0;
2445                r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
2446                r_xram_rsp_to_ixr_cmd_req = false;
2447            }
2448            else
2449            {
2450                r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2451            }
2452
2453#if DEBUG_MEMC_IXR_CMD
2454if( m_debug_ixr_cmd_fsm )
2455{
2456    std::cout << "  <MEMC.IXR_CMD_XRAM_DATA> Send a put request to xram" ;
2457}
2458#endif
2459        }
2460        break;
2461
2462    } // end switch r_ixr_cmd_fsm
2463
2464    ////////////////////////////////////////////////////////////////////////////
2465    //                IXR_RSP FSM
2466    ////////////////////////////////////////////////////////////////////////////
2467    // The IXR_RSP FSM receives the response packets from the XRAM,
2468    // for both put transaction, and get transaction.
2469    //
2470    // - A response to a put request is a single-cell VCI packet.
2471    // The Transaction Tab index is contained in the RTRDID field.
2472    // The FSM takes the lock protecting the TRT, and the corresponding
2473    // entry is erased.
2474    // 
2475    // - A response to a get request is a multi-cell VCI packet.
2476    // The Transaction Tab index is contained in the RTRDID field.
2477    // The N cells contain the N words of the cache line in the RDATA field.
2478    // The FSM takes the lock protecting the TRT to store the line in the TRT
2479    // (taking into account the write requests already stored in the TRT).
2480    // When the line is completely written, the corresponding rok signal is set.
2481    ///////////////////////////////////////////////////////////////////////////////
2482
2483    switch ( r_ixr_rsp_fsm.read() )
2484    {
2485        ///////////////////
2486        case IXR_RSP_IDLE:      // test if it's a get or a put transaction
2487        {
2488            if ( p_vci_ixr.rspval.read() )
2489            {
2490                r_ixr_rsp_cpt   = 0;
2491                r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
2492                if ( p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read()&0x1))  // put transaction
2493                {
2494                    r_ixr_rsp_fsm = IXR_RSP_ACK;
2495
2496#if DEBUG_MEMC_IXR_RSP
2497if( m_debug_ixr_rsp_fsm )
2498{
2499    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
2500}
2501#endif
2502                }
2503                else                                                           // get transaction
2504                {
2505                    r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
2506
2507#if DEBUG_MEMC_IXR_RSP
2508if( m_debug_ixr_rsp_fsm )
2509{
2510    std::cout << "  <MEMC.IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
2511}
2512#endif
2513                }
2514            }
2515            break; 
2516        }
2517        ////////////////////////
2518        case IXR_RSP_ACK:        // Aknowledge the VCI response
2519        {
2520            if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
2521
2522#if DEBUG_MEMC_IXR_RSP
2523if( m_debug_ixr_rsp_fsm )
2524{
2525    std::cout << "  <MEMC.IXR_RSP_ACK>" << std::endl;
2526}
2527#endif
2528            break;
2529        }
2530        ////////////////////////
2531        case IXR_RSP_TRT_ERASE:         // erase the entry in the TRT
2532        {
2533            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP )
2534            {
2535                m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
2536                r_ixr_rsp_fsm = IXR_RSP_IDLE;
2537
2538#if DEBUG_MEMC_IXR_RSP
2539if( m_debug_ixr_rsp_fsm )
2540{
2541    std::cout << "  <MEMC.IXR_RSP_TRT_ERASE> Erase TRT entry "
2542              << r_ixr_rsp_trt_index.read() << std::endl;
2543}
2544#endif
2545            }
2546            break;
2547        }
2548        ///////////////////////
2549        case IXR_RSP_TRT_READ:          // write data in the TRT
2550        {
2551            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval )
2552            {
2553                size_t index    = r_ixr_rsp_trt_index.read();
2554                bool   eop      = p_vci_ixr.reop.read();
2555                data_t data     = p_vci_ixr.rdata.read();
2556                bool   error    = (p_vci_ixr.rerror.read()&0x1 == 0);
2557                assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) || p_vci_ixr.rerror.read())
2558                    and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
2559                m_transaction_tab.write_rsp(index,
2560                                            r_ixr_rsp_cpt.read(),
2561                                            data,
2562                                            error);
2563                r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
2564                if ( eop )
2565                {
2566                    r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
2567                    r_ixr_rsp_fsm = IXR_RSP_IDLE;
2568                }
2569
2570#if DEBUG_MEMC_IXR_RSP
2571if( m_debug_ixr_rsp_fsm )
2572{
2573    std::cout << "  <MEMC.IXR_RSP_TRT_READ> Writing a word in TRT : "
2574              << " index = " << std::dec << index
2575              << " / word = " << r_ixr_rsp_cpt.read()
2576              << " / data = " << std::hex << data << std::endl;
2577}
2578#endif
2579            }
2580            break;
2581        }
2582    } // end swich r_ixr_rsp_fsm
2583
2584    ////////////////////////////////////////////////////////////////////////////
2585    //                XRAM_RSP FSM
2586    ////////////////////////////////////////////////////////////////////////////
2587    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
2588    // The cache line has been written in the TRT by the IXR_CMD_FSM.
2589    // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
2590    // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
2591    // as the number of entries in the TRT, that are handled with
2592    // a round-robin priority...
2593    //
2594    // When a response is available, the corresponding TRT entry
2595    // must be copied in a local buffer to be written in the cache.
2596    // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
2597    // It selects a cache slot and writes the line in the cache.
2598    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
2599    // FSM to return the cache line to the registered processor.
2600    // If there is no empty slot, a victim line is evicted, and
2601    // invalidate requests are sent to the L1 caches containing copies.
2602    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
2603    // FSM to save the victim line to the XRAM, and register the write transaction
2604    // in the TRT (using the entry previously used by the read transaction).
2605    ///////////////////////////////////////////////////////////////////////////////
2606
2607    switch ( r_xram_rsp_fsm.read() )
2608    {
2609        ///////////////////
2610        case XRAM_RSP_IDLE:     // scan the XRAM responses to get the TRT index (round robin)
2611        {
2612            size_t ptr   = r_xram_rsp_trt_index.read();
2613            size_t lines = m_transaction_tab_lines;
2614            for( size_t i=0 ; i<lines ; i++)
2615            {
2616                size_t index=(i+ptr+1)%lines;
2617                if ( r_ixr_rsp_to_xram_rsp_rok[index] )
2618                {
2619                    r_xram_rsp_trt_index                = index;
2620                    r_ixr_rsp_to_xram_rsp_rok[index]    = false;
2621                    r_xram_rsp_fsm                      = XRAM_RSP_DIR_LOCK;
2622
2623#if DEBUG_MEMC_XRAM_RSP
2624if( m_debug_xram_rsp_fsm )
2625{       
2626    std::cout << "  <MEMC.XRAM_RSP_IDLE> Available cache line in TRT:"
2627              << " index = " << std::dec << index << std::endl;
2628}
2629#endif
2630                    break;
2631                }
2632            }
2633            break; 
2634        }
2635        ///////////////////////
2636        case XRAM_RSP_DIR_LOCK:         // Takes the lock on the directory
2637        {
2638            if( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP )
2639            {
2640                r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
2641
2642#if DEBUG_MEMC_XRAM_RSP
2643if( m_debug_xram_rsp_fsm )
2644{       
2645    std::cout << "  <MEMC.XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
2646}
2647#endif
2648            }
2649            break;
2650        }
2651        ///////////////////////
2652        case XRAM_RSP_TRT_COPY:         // Takes the lock on TRT
2653                                    // Copy the TRT entry in a local buffer
2654                                    // and select a victim cache line
2655        {
2656            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) )
2657            {
2658                // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
2659                size_t  index = r_xram_rsp_trt_index.read();
2660                TransactionTabEntry    trt_entry(m_transaction_tab.read(index)); 
2661                r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
2662
2663                // selects & extracts a victim line from cache
2664                size_t way = 0;
2665                size_t set = m_y[(vci_addr_t)(trt_entry.nline * m_words * 4)];
2666                DirectoryEntry victim(m_cache_directory.select(set, way));
2667
2668                bool inval = (victim.count && victim.valid) ;
2669
2670                // copy the victim line in a local buffer
2671                for (size_t i=0 ; i<m_words ; i++)
2672                    r_xram_rsp_victim_data[i] = m_cache_data[way][set][i];
2673                r_xram_rsp_victim_copy      = victim.owner.srcid;
2674#if L1_MULTI_CACHE
2675                r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
2676#endif
2677                r_xram_rsp_victim_copy_inst = victim.owner.inst;
2678                r_xram_rsp_victim_count     = victim.count;
2679                r_xram_rsp_victim_ptr       = victim.ptr;
2680                r_xram_rsp_victim_way       = way;
2681                r_xram_rsp_victim_set       = set;
2682                r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
2683                r_xram_rsp_victim_is_cnt    = victim.is_cnt;
2684                r_xram_rsp_victim_inval     = inval ;
2685                r_xram_rsp_victim_dirty     = victim.dirty;
2686
2687                if(!trt_entry.rerror)   r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
2688                else                            r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;     
2689
2690#if DEBUG_MEMC_XRAM_RSP
2691if( m_debug_xram_rsp_fsm )
2692{
2693    std::cout << "  <MEMC.XRAM_RSP_TRT_COPY> Select a slot: "
2694              << " way = " << std::dec << way
2695              << " / set = " << set
2696              << " / inval_required = " << inval << std::endl;
2697}
2698#endif
2699            }
2700            break;
2701        }
2702        /////////////////////////
2703        case XRAM_RSP_INVAL_LOCK:       // check a possible pending inval
2704        {
2705            if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP )
2706            {
2707                size_t index;
2708                if (m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index))
2709                {
2710                    r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2711
2712#if DEBUG_MEMC_XRAM_RSP
2713if( m_debug_xram_rsp_fsm )
2714{
2715    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
2716              << " but an invalidation is already registered at this address" << std::endl;
2717    m_update_tab.print();
2718}
2719#endif
2720
2721                }
2722                else if (m_update_tab.is_full() && r_xram_rsp_victim_inval.read())
2723                {
2724                    r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
2725
2726#if DEBUG_MEMC_XRAM_RSP
2727if( m_debug_xram_rsp_fsm )
2728{
2729    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
2730              << " but the table is full" << std::endl;
2731    m_update_tab.print();
2732}
2733#endif
2734                }
2735                else
2736                {
2737                    r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
2738
2739#if DEBUG_MEMC_XRAM_RSP
2740if( m_debug_xram_rsp_fsm )
2741{
2742    std::cout << "  <MEMC.XRAM_RSP_INVAL_LOCK> Get acces to UPT" << std::endl;
2743}
2744#endif
2745                }
2746            }
2747            break;
2748        }
2749        /////////////////////////
2750        case XRAM_RSP_INVAL_WAIT:       // returns to DIR_LOCK to retry
2751        {
2752            r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
2753            break;
2754        }
2755        ///////////////////////
2756        case XRAM_RSP_DIR_UPDT:         // updates the cache (both data & directory)
2757                                        // and possibly set an inval request in UPT
2758        {
2759            // signals generation
2760            bool inst_read = (r_xram_rsp_trt_buf.trdid & 0x2) && r_xram_rsp_trt_buf.proc_read;
2761            bool cached_read = (r_xram_rsp_trt_buf.trdid & 0x1) && r_xram_rsp_trt_buf.proc_read;
2762            // update data
2763            size_t set   = r_xram_rsp_victim_set.read();
2764            size_t way   = r_xram_rsp_victim_way.read();
2765            for(size_t i=0; i<m_words ; i++) m_cache_data[way][set][i] = r_xram_rsp_trt_buf.wdata[i];
2766            // compute dirty
2767            bool dirty = false;
2768            for(size_t i=0; i<m_words;i++) dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
2769            // update directory
2770            DirectoryEntry entry;
2771            entry.valid   = true;
2772            entry.is_cnt  = false;
2773            entry.lock    = false;
2774            entry.dirty   = dirty;
2775            entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
2776            entry.ptr     = 0;
2777            if(cached_read)
2778            {
2779                entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
2780#if L1_MULTI_CACHE
2781                entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
2782#endif
2783                entry.owner.inst    = inst_read;
2784                entry.count         = 1;
2785            }
2786            else
2787            {
2788                entry.owner.srcid    = 0;
2789#if L1_MULTI_CACHE
2790                entry.owner.cache_id = 0;
2791#endif
2792                entry.owner.inst     = 0;
2793                entry.count          = 0;
2794            }
2795            m_cache_directory.write(set, way, entry);
2796
2797            if (r_xram_rsp_victim_inval.read())
2798            {
2799                bool   brdcast          = r_xram_rsp_victim_is_cnt.read();
2800                size_t index            = 0;
2801                size_t count_copies     = r_xram_rsp_victim_count.read();
2802
2803                bool   wok = m_update_tab.set(  false,          // it's an inval transaction
2804                                                brdcast,        // set brdcast bit
2805                                                false,          // it does not need a response
2806                                                0,              // srcid
2807                                                0,              // trdid
2808                                                0,              // pktid
2809                                                r_xram_rsp_victim_nline.read(),
2810                                                count_copies,
2811                                                index);
2812                r_xram_rsp_upt_index = index;
2813
2814                if (!wok)
2815                {
2816                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
2817                    std::cout << "an update_tab entry was free but write is unsuccessful" << std::endl;
2818                    exit(0);
2819                }
2820            }
2821
2822#if DEBUG_MEMC_XRAM_RSP
2823if( m_debug_xram_rsp_fsm )
2824{
2825    std::cout << "  <MEMC.XRAM_RSP_DIR_UPDT> Directory update: "
2826              << " way = " << std::dec << way
2827              << " / set = " << set
2828              << " / count = " << entry.count
2829              << " / is_cnt = " << entry.is_cnt << std::endl;
2830    if (r_xram_rsp_victim_inval.read())
2831    std::cout << "                           Invalidation request for victim line "
2832              << std::hex << r_xram_rsp_victim_nline.read()
2833              << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
2834}
2835#endif
2836
2837            // If the victim is not dirty, we don't need another XRAM  put transaction,
2838            // and we canwe erase the TRT entry
2839            if (!r_xram_rsp_victim_dirty.read())  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
2840
2841            // Next state
2842            if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
2843            else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
2844            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
2845            else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
2846            break;
2847        }
2848        ////////////////////////
2849        case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (write to XRAM) if the victim is dirty
2850        {
2851            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP )
2852            {
2853                m_transaction_tab.set( r_xram_rsp_trt_index.read(),
2854                                       false,                           // write to XRAM
2855                                       r_xram_rsp_victim_nline.read(),  // line index
2856                                       0,
2857                                       0,
2858                                       0,
2859                                       false,
2860                                       0,
2861                                       0,
2862                                       std::vector<be_t>(m_words,0),
2863                                       std::vector<data_t>(m_words,0) );
2864
2865#if DEBUG_MEMC_XRAM_RSP
2866if( m_debug_xram_rsp_fsm )
2867{
2868    std::cout << "  <MEMC.XRAM_RSP_TRT_DIRTY> Set TRT entry for the put transaction:"
2869              << " dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
2870}
2871#endif
2872                if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
2873                else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
2874                else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
2875            }
2876            break;
2877        }
2878        //////////////////////
2879        case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
2880        {
2881            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
2882            {
2883                r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
2884                r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
2885                r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
2886                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
2887                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
2888                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
2889                r_xram_rsp_to_tgt_rsp_rerror = false;
2890                r_xram_rsp_to_tgt_rsp_req    = true;
2891
2892                if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
2893                else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
2894                else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
2895
2896
2897#if DEBUG_MEMC_XRAM_RSP
2898if( m_debug_xram_rsp_fsm )
2899{
2900    std::cout << "  <MEMC.XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:"
2901              << " rsrcid = " << std::hex << r_xram_rsp_trt_buf.srcid
2902              << " / address = " << r_xram_rsp_trt_buf.nline*m_words*4
2903              << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
2904}
2905#endif
2906            }
2907            break;
2908        }
2909        ////////////////////
2910        case XRAM_RSP_INVAL:    // send invalidate request to INIT_CMD FSM
2911        {
2912            if(   !r_xram_rsp_to_init_cmd_multi_req.read() &&
2913                  !r_xram_rsp_to_init_cmd_brdcast_req.read() )
2914            {         
2915                bool multi_req = !r_xram_rsp_victim_is_cnt.read();
2916                bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
2917                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
2918
2919                r_xram_rsp_to_init_cmd_multi_req    = last_multi_req;
2920                r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
2921                r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
2922                r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
2923                xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
2924                xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
2925#if L1_MULTI_CACHE
2926                xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
2927#endif
2928                xram_rsp_to_init_cmd_fifo_put       = multi_req;
2929                r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
2930
2931                if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
2932                else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2933                else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
2934
2935#if DEBUG_MEMC_XRAM_RSP
2936if( m_debug_xram_rsp_fsm )
2937{
2938    std::cout << "  <MEMC.XRAM_RSP_INVAL> Send an inval request to INIT_CMD FSM:"
2939              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
2940}
2941#endif
2942          }
2943          break;
2944        }
2945        //////////////////////////
2946        case XRAM_RSP_WRITE_DIRTY:      // send a write request to IXR_CMD FSM
2947        {
2948            if ( !r_xram_rsp_to_ixr_cmd_req.read() )
2949            {
2950                r_xram_rsp_to_ixr_cmd_req = true;
2951                r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
2952                r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
2953                for(size_t i=0; i<m_words ; i++) r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
2954                m_cpt_write_dirty++;
2955
2956                bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
2957                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
2958                if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2959                else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
2960
2961#if DEBUG_MEMC_XRAM_RSP
2962if( m_debug_xram_rsp_fsm )
2963{
2964    std::cout << "  <MEMC.XRAM_RSP_WRITE_DIRTY> Send the put request to IXR_CMD FSM:"
2965              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
2966}
2967#endif
2968            }
2969            break;
2970        }
2971        /////////////////////////
2972        case XRAM_RSP_HEAP_ERASE:       // erase the list of copies and sent invalidations
2973        {
2974            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP )
2975            {
2976                HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
2977
2978                xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
2979#if L1_MULTI_CACHE
2980                xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
2981#endif
2982                xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
2983                xram_rsp_to_init_cmd_fifo_put   = true;
2984                if( m_xram_rsp_to_init_cmd_inst_fifo.wok() )
2985                {
2986                    r_xram_rsp_next_ptr = entry.next;
2987                    if( entry.next == r_xram_rsp_next_ptr.read() ) // last copy
2988                    {
2989                        r_xram_rsp_to_init_cmd_multi_req = true;
2990                        r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
2991                    }
2992                    else
2993                    {
2994                        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
2995                    }
2996                }
2997                else
2998                {
2999                    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3000                }
3001
3002#if DEBUG_MEMC_XRAM_RSP
3003if( m_debug_xram_rsp_fsm )
3004{
3005    std::cout << "  <MEMC.XRAM_RSP_HEAP_ERASE> Erase the list of copies:"
3006              << " srcid = " << entry.owner.srcid
3007              << " / inst = " << entry.owner.inst << std::endl;
3008}
3009#endif
3010            }
3011            break;
3012        }
3013        /////////////////////////
3014        case XRAM_RSP_HEAP_LAST:        // last member of the list
3015        {
3016            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP )
3017            {
3018                std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
3019                std::cout << "bad HEAP allocation" << std::endl;
3020                exit(0);
3021            }
3022            size_t free_pointer = m_heap.next_free_ptr();
3023
3024            HeapEntry last_entry;
3025            last_entry.owner.srcid    = 0;
3026#if L1_MULTI_CACHE
3027            last_entry.owner.cache_id = 0;
3028#endif
3029            last_entry.owner.inst     = false;
3030            if(m_heap.is_full())
3031            {
3032                last_entry.next     = r_xram_rsp_next_ptr.read();
3033                m_heap.unset_full();
3034            }
3035            else
3036            {
3037                last_entry.next     = free_pointer;
3038            }
3039
3040            m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
3041            m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
3042
3043            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3044
3045#if DEBUG_MEMC_XRAM_RSP
3046if( m_debug_xram_rsp_fsm )
3047{
3048    std::cout << "  <MEMC.XRAM_RSP_HEAP_LAST> Heap housekeeping" << std::endl;
3049}
3050#endif
3051            break;
3052        }
3053        // ///////////////////////
3054        case XRAM_RSP_ERROR_ERASE:      // erase TRT entry in case of error
3055        {
3056            m_transaction_tab.erase(r_xram_rsp_trt_index.read());
3057
3058            // Next state
3059            if ( r_xram_rsp_trt_buf.proc_read  ) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3060            else                                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
3061
3062#if DEBUG_MEMC_XRAM_RSP
3063if( m_debug_xram_rsp_fsm )
3064{
3065    std::cout << "  <MEMC.XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << std::endl;
3066}
3067#endif
3068            break;
3069        }
3070        ////////////////////////
3071        case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3072        {
3073            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
3074            {
3075                r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3076                r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3077                r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3078                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3079                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3080                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3081                r_xram_rsp_to_tgt_rsp_rerror = true;
3082                r_xram_rsp_to_tgt_rsp_req    = true;
3083
3084                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3085
3086#if DEBUG_MEMC_XRAM_RSP
3087if( m_debug_xram_rsp_fsm )
3088{
3089    std::cout << "  <MEMC.XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3090              << " srcid = " << r_xram_rsp_trt_buf.srcid << std::endl;
3091}
3092#endif
3093            }
3094            break;
3095        }
3096    } // end swich r_xram_rsp_fsm
3097
3098    ////////////////////////////////////////////////////////////////////////////////////
3099    //          CLEANUP FSM
3100    ////////////////////////////////////////////////////////////////////////////////////
3101    // The CLEANUP FSM handles the cleanup request from L1 caches.
3102    // It accesses the cache directory and the heap to update the list of copies.
3103    ////////////////////////////////////////////////////////////////////////////////////
3104
3105
3106    switch ( r_cleanup_fsm.read() )
3107    {
3108        //////////////////
3109        case CLEANUP_IDLE:
3110        {
3111            if ( p_vci_tgt_cleanup.cmdval.read() )
3112            {
3113                if (p_vci_tgt_cleanup.srcid.read() >= m_initiators )
3114                {
3115                    std::cout << "VCI_MEM_CACHE ERROR " << name()
3116                              << " CLEANUP_IDLE state" << std::endl;
3117                    std::cout << "illegal srcid for  cleanup request" << std::endl;
3118                    exit(0);
3119                }
3120
3121                bool reached = false;
3122                for ( size_t index = 0 ; index < ncseg && !reached ; index++ )
3123                {
3124                    if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) )
3125                        reached = true;
3126                }
3127                // only write request to a mapped address that are not broadcast are handled
3128                if ( (p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE) &&
3129                     ((p_vci_tgt_cleanup.address.read() & 0x3) == 0) && reached)
3130                {
3131                    addr_t line = (addr_t)(m_nline[(vci_addr_t)(p_vci_tgt_cleanup.address.read())]);
3132
3133                    r_cleanup_nline = line;
3134                    r_cleanup_srcid = p_vci_tgt_cleanup.srcid.read();
3135                    r_cleanup_trdid = p_vci_tgt_cleanup.trdid.read();
3136                    r_cleanup_pktid = p_vci_tgt_cleanup.pktid.read();
3137                    r_cleanup_fsm   = CLEANUP_DIR_LOCK;
3138
3139#if DEBUG_MEMC_CLEANUP
3140if( m_debug_cleanup_fsm )
3141{
3142    std::cout << "  <MEMC.CLEANUP_IDLE> Cleanup request:" << std::hex
3143              << " line = " << line * m_words * 4
3144              << " / owner_id = " << p_vci_tgt_cleanup.srcid.read()
3145              << " / owner_ins = " << (p_vci_tgt_cleanup.trdid.read()&0x1)
3146              << std::endl;
3147}
3148#endif
3149                    m_cpt_cleanup++;
3150                }
3151            }
3152            break;
3153        }
3154        //////////////////////
3155        case CLEANUP_DIR_LOCK:  // test directory status
3156        {
3157            if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP )
3158            {
3159                // Read the directory
3160                size_t way = 0;
3161                    addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
3162                DirectoryEntry entry   = m_cache_directory.read(cleanup_address , way);
3163                r_cleanup_is_cnt       = entry.is_cnt;
3164                r_cleanup_dirty        = entry.dirty;
3165                r_cleanup_tag          = entry.tag;
3166                r_cleanup_lock         = entry.lock;
3167                r_cleanup_way          = way;
3168                r_cleanup_copy         = entry.owner.srcid;
3169#if L1_MULTI_CACHE
3170                r_cleanup_copy_cache= entry.owner.cache_id;
3171#endif
3172                r_cleanup_copy_inst    = entry.owner.inst;
3173                r_cleanup_count        = entry.count;
3174                r_cleanup_ptr          = entry.ptr;
3175
3176                if( entry.valid) //  hit : the copy must be cleared 
3177                {
3178                    if ( (entry.count==1) || (entry.is_cnt) )  // no access to the heap
3179                    {
3180                        r_cleanup_fsm = CLEANUP_DIR_WRITE;
3181                    }
3182                    else                                        // access to the heap
3183                    {
3184                        r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3185                    }
3186                }
3187                else            // miss : we must check the update table
3188                {
3189                    r_cleanup_fsm = CLEANUP_UPT_LOCK;
3190                }
3191
3192#if DEBUG_MEMC_CLEANUP
3193if( m_debug_cleanup_fsm )
3194{
3195    std::cout << "  <MEMC.CLEANUP_DIR_LOCK> Test directory status: " << std::hex
3196              << " line = " << r_cleanup_nline.read() * m_words * 4
3197              << " / hit = " << entry.valid
3198              << " / dir_id = " << entry.owner.srcid
3199              << " / dir_ins = " << entry.owner.inst
3200              << " / search_id = " << r_cleanup_srcid.read()
3201              << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
3202              << " / count = " << entry.count
3203              << " / is_cnt = " << entry.is_cnt << std::endl;
3204}
3205#endif
3206            }
3207            break;
3208        }
3209        ///////////////////////
3210        case CLEANUP_DIR_WRITE:  //  update the directory entry without heap access
3211        {
3212            if ( r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP )
3213            {
3214                std::cout << "VCI_MEM_CACHE ERROR " << name()
3215                          << " CLEANUP_DIR_WRITE state"
3216                          << " bad DIR allocation" << std::endl;
3217                exit(0);
3218            }
3219
3220            size_t way         = r_cleanup_way.read();
3221            size_t set         = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3222            bool cleanup_inst  = r_cleanup_trdid.read() & 0x1;
3223            bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
3224#if L1_MULTI_CACHE
3225                                and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read())
3226#endif
3227                                );
3228            bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
3229            bool match         = match_srcid && match_inst;
3230
3231            // update the cache directory (for the copies)
3232            DirectoryEntry entry;
3233            entry.valid   = true;
3234            entry.is_cnt  = r_cleanup_is_cnt.read();
3235            entry.dirty   = r_cleanup_dirty.read();
3236            entry.tag     = r_cleanup_tag.read();
3237            entry.lock    = r_cleanup_lock.read();
3238            entry.ptr     = r_cleanup_ptr.read();
3239
3240            if ( r_cleanup_is_cnt.read() )      // counter mode
3241            {
3242                entry.count  = r_cleanup_count.read() -1;
3243                entry.owner.srcid   = 0;
3244#if L1_MULTI_CACHE
3245                entry.owner.cache_id= 0;
3246#endif
3247                entry.owner.inst    = 0;
3248                // response to the cache
3249                r_cleanup_fsm = CLEANUP_RSP;
3250            }
3251            else                                            // linked_list mode
3252            {                       
3253                if ( match )  // hit
3254                {
3255                    entry.count         = 0; // no more copy
3256                    entry.owner.srcid   = 0;
3257#if L1_MULTI_CACHE
3258                    entry.owner.cache_id=0;
3259#endif
3260                    entry.owner.inst    = 0;
3261                    r_cleanup_fsm       = CLEANUP_RSP;
3262                }
3263                else         // miss
3264                {
3265                    entry.count          = r_cleanup_count.read();
3266                    entry.owner.srcid    = r_cleanup_copy.read();
3267#if L1_MULTI_CACHE
3268                    entry.owner.cache_id = r_cleanup_copy_cache.read();
3269#endif
3270                    entry.owner.inst     = r_cleanup_copy_inst.read();
3271                    r_cleanup_fsm        = CLEANUP_UPT_LOCK;
3272                }
3273            }
3274            m_cache_directory.write(set, way, entry); 
3275
3276#if DEBUG_MEMC_CLEANUP
3277if( m_debug_cleanup_fsm )
3278{
3279    std::cout << "  <MEMC.CLEANUP_DIR_WRITE> Update directory:" << std::hex
3280              << " line = " << r_cleanup_nline.read() * m_words * 4
3281              << " / dir_id = " << entry.owner.srcid
3282              << " / dir_ins = " << entry.owner.inst
3283              << " / count = " << entry.count
3284              << " / is_cnt = " << entry.is_cnt << std::endl;
3285}
3286#endif
3287
3288            break;
3289        }
3290        ///////////////////////
3291        case CLEANUP_HEAP_LOCK:  // two cases are handled in this state:
3292                                 // - the matching copy is directly in the directory
3293                                 // - the matching copy is the first copy in the heap
3294        {
3295            if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3296            {
3297                size_t way              = r_cleanup_way.read();
3298                size_t set              = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3299                HeapEntry heap_entry    = m_heap.read(r_cleanup_ptr.read());
3300                bool last               = (heap_entry.next == r_cleanup_ptr.read());
3301                bool cleanup_inst       = r_cleanup_trdid.read() & 0x1;
3302
3303                // match_dir computation
3304                bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3305                bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
3306                bool match_dir          = match_dir_srcid and match_dir_inst;
3307#if L1_MULTI_CACHE
3308                match_dir = match_dir and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3309#endif
3310
3311                // match_heap computation
3312                bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3313                bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
3314                bool match_heap         = match_heap_srcid and match_heap_inst;
3315#if L1_MULTI_CACHE
3316                match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3317#endif
3318
3319                r_cleanup_prev_ptr      = r_cleanup_ptr.read();
3320                r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3321#if L1_MULTI_CACHE
3322                r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3323#endif
3324                r_cleanup_prev_inst     = heap_entry.owner.inst;
3325
3326                if (match_dir) // the matching copy is registered in the directory
3327                {       
3328                    // the copy registered in the directory must be replaced
3329                    // by the first copy registered in the heap
3330                    // and the corresponding entry must be freed
3331                    DirectoryEntry dir_entry;
3332                    dir_entry.valid             = true;
3333                    dir_entry.is_cnt        = r_cleanup_is_cnt.read();
3334                    dir_entry.dirty             = r_cleanup_dirty.read();
3335                    dir_entry.tag               = r_cleanup_tag.read();
3336                    dir_entry.lock              = r_cleanup_lock.read();
3337                    dir_entry.ptr           = heap_entry.next;
3338                    dir_entry.count         = r_cleanup_count.read()-1;
3339                    dir_entry.owner.srcid   = heap_entry.owner.srcid;
3340#if L1_MULTI_CACHE
3341                    dir_entry.owner.cache_id = heap_entry.owner.cache_id;
3342#endif
3343                    dir_entry.owner.inst    = heap_entry.owner.inst;
3344                    m_cache_directory.write(set,way,dir_entry);
3345                    r_cleanup_next_ptr      = r_cleanup_ptr.read();
3346                    r_cleanup_fsm           = CLEANUP_HEAP_FREE;
3347                }
3348                else if (match_heap) // the matching copy is the first copy in the heap
3349                {
3350                    // The first copy in heap must be freed
3351                    // and the copy registered in directory must point to the next copy in heap
3352                    DirectoryEntry dir_entry;
3353                    dir_entry.valid             = true;
3354                    dir_entry.is_cnt        = r_cleanup_is_cnt.read();
3355                    dir_entry.dirty             = r_cleanup_dirty.read();
3356                    dir_entry.tag               = r_cleanup_tag.read();
3357                    dir_entry.lock              = r_cleanup_lock.read();
3358                    dir_entry.ptr           = heap_entry.next;
3359                    dir_entry.count         = r_cleanup_count.read()-1;
3360                    dir_entry.owner.srcid   = r_cleanup_copy.read();
3361#if L1_MULTI_CACHE
3362                    dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3363#endif
3364                    dir_entry.owner.inst    = r_cleanup_copy_inst.read();
3365                    m_cache_directory.write(set,way,dir_entry);
3366                    r_cleanup_next_ptr      = r_cleanup_ptr.read();
3367                    r_cleanup_fsm           = CLEANUP_HEAP_FREE;
3368                }
3369                else if(!last) // The matching copy is in the heap, but is not the first copy
3370                {
3371                    // The directory entry must be modified to decrement count
3372                    DirectoryEntry  dir_entry;
3373                    dir_entry.valid           = true;
3374                    dir_entry.is_cnt      = r_cleanup_is_cnt.read();
3375                    dir_entry.dirty           = r_cleanup_dirty.read();
3376                    dir_entry.tag             = r_cleanup_tag.read();
3377                    dir_entry.lock        = r_cleanup_lock.read();
3378                    dir_entry.ptr         = r_cleanup_ptr.read();
3379                    dir_entry.count       = r_cleanup_count.read()-1;
3380                    dir_entry.owner.srcid = r_cleanup_copy.read();
3381#if L1_MULTI_CACHE
3382                    dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3383#endif
3384                    dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3385                    m_cache_directory.write(set,way,dir_entry);
3386                    r_cleanup_next_ptr       = heap_entry.next;
3387                    r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
3388                }
3389                else
3390                {
3391                    std::cout << "VCI_MEM_CACHE ERROR " << name()
3392                              << " CLEANUP_HEAP_LOCK state"
3393                              << " hit but copy not found" << std::endl;
3394                    exit(0);
3395                }
3396
3397#if DEBUG_MEMC_CLEANUP
3398if( m_debug_cleanup_fsm )
3399{
3400    std::cout << "  <MEMC.CLEANUP_HEAP_LOCK> Checks matching:"
3401              << " line = " << r_cleanup_nline.read() * m_words * 4
3402              << " / dir_id = " << r_cleanup_copy.read()
3403              << " / dir_ins = " << r_cleanup_copy_inst.read()
3404              << " / heap_id = " << heap_entry.owner.srcid
3405              << " / heap_ins = " << heap_entry.owner.inst
3406              << " / search_id = " << r_cleanup_srcid.read()
3407              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3408}
3409#endif
3410            }
3411            break;
3412        }
3413        /////////////////////////
3414        case CLEANUP_HEAP_SEARCH:  // This state is handling the case where the copy
3415                                   // is in the heap, but is not the first in the linked list
3416        {
3417            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3418            {
3419                std::cout << "VCI_MEM_CACHE ERROR " << name()
3420                          << " CLEANUP_HEAP_SEARCH state"
3421                          << " bad HEAP allocation" << std::endl;
3422                exit(0);
3423            }
3424
3425            HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
3426            bool last             = (heap_entry.next == r_cleanup_next_ptr.read());
3427            bool cleanup_inst     = r_cleanup_trdid.read() & 0x1;
3428            bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3429            bool match_heap_inst  = (heap_entry.owner.inst  == cleanup_inst);
3430            bool match_heap       = match_heap_srcid && match_heap_inst;
3431#if L1_MULTI_CACHE
3432            match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3433#endif
3434
3435#if DEBUG_MEMC_CLEANUP
3436if( m_debug_cleanup_fsm )
3437{
3438    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Cheks matching:"
3439              << " line = " << r_cleanup_nline.read() * m_words * 4
3440              << " / heap_id = " << heap_entry.owner.srcid
3441              << " / heap_ins = " << heap_entry.owner.inst
3442              << " / search_id = " << r_cleanup_srcid.read()
3443              << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
3444              << " / last = " << last << std::endl;
3445}
3446#endif
3447            if(match_heap) // the matching copy must be removed
3448            {
3449                r_cleanup_ptr = heap_entry.next; // reuse ressources
3450                r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
3451            }
3452            else
3453            {
3454                if ( last )
3455                {
3456                    std::cout << "VCI_MEM_CACHE_ERROR " << name()
3457                              << " CLEANUP_HEAP_SEARCH state"
3458                              << " cleanup hit but copy not found" << std::endl;
3459                    exit(0);
3460                }
3461                else // test the next in the linked list
3462                {
3463                    r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
3464                    r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3465#if L1_MULTI_CACHE
3466                    r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3467#endif
3468                    r_cleanup_prev_inst     = heap_entry.owner.inst;
3469                    r_cleanup_next_ptr      = heap_entry.next;
3470                    r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
3471
3472#if DEBUG_MEMC_CLEANUP
3473if( m_debug_cleanup_fsm )
3474{
3475    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
3476              << " line = " << r_cleanup_nline.read() * m_words * 4
3477              << " / heap_id = " << heap_entry.owner.srcid
3478              << " / heap_ins = " << heap_entry.owner.inst
3479              << " / search_id = " << r_cleanup_srcid.read()
3480              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3481}
3482#endif
3483                }
3484            }
3485            break;
3486        }
3487        ////////////////////////
3488        case CLEANUP_HEAP_CLEAN:  // remove a copy in the linked list
3489        {
3490            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3491            {
3492                std::cout << "VCI_MEM_CACHE ERROR " << name()
3493                          << " CLEANUP_HEAP_CLEAN state"
3494                          << "Bad HEAP allocation" << std::endl;
3495                exit(0);
3496            }
3497
3498            bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
3499            HeapEntry heap_entry;
3500            heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
3501#if L1_MULTI_CACHE
3502            heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
3503#endif
3504            heap_entry.owner.inst     = r_cleanup_prev_inst.read();
3505            if(last) // this is the last entry of the list of copies
3506            {
3507                heap_entry.next     = r_cleanup_prev_ptr.read();
3508            }
3509            else  // this is not the last entry
3510            {
3511                heap_entry.next     = r_cleanup_ptr.read();
3512            }
3513            m_heap.write(r_cleanup_prev_ptr.read(),heap_entry);
3514            r_cleanup_fsm = CLEANUP_HEAP_FREE;
3515
3516#if DEBUG_MEMC_CLEANUP
3517if( m_debug_cleanup_fsm )
3518{
3519    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Remove the copy in the linked list" << std::endl;
3520}
3521#endif
3522            break;
3523        }
3524        ///////////////////////
3525        case CLEANUP_HEAP_FREE:  // The heap entry pointed by r_cleanup_next_ptr is freed
3526                                 // and becomes the head of the list of free entries
3527        {
3528            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3529            {
3530                std::cout << "VCI_MEM_CACHE ERROR " << name() << " CLEANUP_HEAP_CLEAN state" << std::endl;
3531                std::cout << "Bad HEAP allocation" << std::endl;
3532                exit(0);
3533            }
3534
3535            HeapEntry heap_entry;
3536            heap_entry.owner.srcid    = 0;
3537#if L1_MULTI_CACHE
3538            heap_entry.owner.cache_id = 0;
3539#endif
3540            heap_entry.owner.inst     = false;
3541
3542            if(m_heap.is_full()) heap_entry.next     = r_cleanup_next_ptr.read();
3543            else                           heap_entry.next     = m_heap.next_free_ptr();
3544            m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
3545            m_heap.write_free_ptr(r_cleanup_next_ptr.read());
3546            m_heap.unset_full();
3547            r_cleanup_fsm = CLEANUP_RSP;
3548
3549#if DEBUG_MEMC_CLEANUP
3550if( m_debug_cleanup_fsm )
3551{
3552    std::cout << "  <MEMC.CLEANUP_HEAP_SEARCH> Update the list of free entries" << std::endl;
3553}
3554#endif
3555            break;
3556        }
3557        //////////////////////
3558        case CLEANUP_UPT_LOCK:
3559        {
3560            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
3561            {
3562                size_t index = 0;
3563                bool hit_inval;
3564                hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
3565
3566                if ( !hit_inval ) // no pending inval
3567                {
3568
3569#if DEBUG_MEMC_CLEANUP
3570if( m_debug_cleanup_fsm )
3571{
3572    std::cout << "  <MEMC.CLEANUP_UPT_LOCK> Unexpected cleanup with no corresponding UPT entry:"
3573              << " address = " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::endl;
3574}
3575#endif
3576                    r_cleanup_fsm = CLEANUP_RSP;
3577                }
3578                else            // pending inval
3579                {
3580                    r_cleanup_write_srcid = m_update_tab.srcid(index);
3581                    r_cleanup_write_trdid = m_update_tab.trdid(index);
3582                    r_cleanup_write_pktid = m_update_tab.pktid(index);
3583                    r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
3584                    r_cleanup_fsm = CLEANUP_UPT_WRITE;
3585                }
3586                r_cleanup_index.write(index) ;
3587            }
3588            break;
3589        }
3590        ///////////////////////
3591        case CLEANUP_UPT_WRITE:  // decrement response counter
3592        {
3593            size_t count = 0;
3594            m_update_tab.decrement(r_cleanup_index.read(), count);
3595            if ( count == 0 )
3596            {
3597                m_update_tab.clear(r_cleanup_index.read());
3598
3599#if DEBUG_MEMC_CLEANUP
3600if( m_debug_cleanup_fsm )
3601{
3602    std::cout << "  <MEMC.CLEANUP_UPT_WRITE> Decrement response counter in UPT:"
3603              << " UPT_index = " << r_cleanup_index.read()
3604              << " rsp_count = " << count << std::endl;
3605}
3606#endif
3607                if( r_cleanup_need_rsp.read() ) r_cleanup_fsm = CLEANUP_WRITE_RSP ; 
3608                else                                        r_cleanup_fsm = CLEANUP_RSP;
3609            }
3610            else
3611            {
3612                r_cleanup_fsm = CLEANUP_RSP ;
3613            }
3614            break;
3615        }
3616        ///////////////////////
3617        case CLEANUP_WRITE_RSP: // Response to a previous write on the direct network
3618        {
3619            if( !r_cleanup_to_tgt_rsp_req.read() )
3620            {
3621                r_cleanup_to_tgt_rsp_req     = true;
3622                r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
3623                r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
3624                r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
3625                r_cleanup_fsm                = CLEANUP_RSP;
3626
3627#if DEBUG_MEMC_CLEANUP
3628if( m_debug_cleanup_fsm )
3629{
3630    std::cout << "  <MEMC.CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
3631              << " rsrcid = " << r_cleanup_write_srcid.read()
3632              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
3633}
3634#endif
3635            }
3636            break;
3637        }
3638        /////////////////
3639        case CLEANUP_RSP:       // Response to a cleanup on the coherence network
3640        {
3641            if ( p_vci_tgt_cleanup.rspack.read() )
3642            {
3643                r_cleanup_fsm = CLEANUP_IDLE;
3644
3645#if DEBUG_MEMC_CLEANUP
3646if( m_debug_cleanup_fsm )
3647{
3648    std::cout << "  <MEMC.CLEANUP_RSP> Send the response to a cleanup request:"
3649              << " rsrcid = " << r_cleanup_write_srcid.read()
3650              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
3651}
3652#endif
3653            }
3654            break;
3655        }
3656    } // end switch cleanup fsm
3657
3658    ////////////////////////////////////////////////////////////////////////////////////
3659    //          SC FSM
3660    ////////////////////////////////////////////////////////////////////////////////////
3661    // The SC FSM handles the SC (Store Conditionnal) atomic commands,
3662    // that are handled as "compare-and-swap instructions.
3663    //
3664    // This command contains two or four flits:
3665    // - In case of 32 bits atomic access, the first flit contains the value read
3666    // by a previous LL instruction, the second flit contains the value to be writen.
3667    // - In case of 64 bits atomic access, the 2 first flits contains the value read
3668    // by a previous LL instruction, the 2 next flits contains the value to be writen.
3669    //
3670    // The target address is cachable. If it is replicated in other L1 caches
3671    // than the writer, a coherence operation is done.
3672    //
3673    // It access the directory to check hit / miss.
3674    // - In case of miss, the SC FSM must register a GET transaction in TRT.
3675    // If a read transaction to the XRAM for this line already exists,
3676    // or if the transaction table is full, it goes to the WAIT state
3677    // to release the locks and try again. When the GET transaction has been
3678    // launched, it goes to the WAIT state and try again.
3679    // The SC request is not consumed in the FIFO until a HIT is obtained.
3680    // - In case of hit...
3681    ///////////////////////////////////////////////////////////////////////////////////
3682
3683    switch ( r_sc_fsm.read() )
3684    {
3685        /////////////
3686        case SC_IDLE:       // fill the local rdata buffers
3687        {
3688            if( m_cmd_sc_addr_fifo.rok() )
3689            {
3690
3691#if DEBUG_MEMC_SC
3692if( m_debug_sc_fsm )
3693{
3694    std::cout << "  <MEMC.SC_IDLE> SC command: " << std::hex
3695              << " srcid = " <<  m_cmd_sc_srcid_fifo.read()
3696              << " addr = " <<  m_cmd_sc_addr_fifo.read()
3697              << " wdata = " << m_cmd_sc_wdata_fifo.read()
3698              << " eop = " << m_cmd_sc_eop_fifo.read()
3699              << " cpt  = " << std::dec << r_sc_cpt.read() << std::endl;
3700}
3701#endif
3702                if( m_cmd_sc_eop_fifo.read() )
3703                {
3704                    m_cpt_sc++;
3705                    r_sc_fsm = SC_DIR_LOCK;
3706                }
3707                else  // we keep the last word in the FIFO
3708                {
3709                    cmd_sc_fifo_get = true;
3710                }
3711                // We fill the two buffers
3712                if ( r_sc_cpt.read() < 2 ) // 32 bits access
3713                    r_sc_rdata[r_sc_cpt.read()] = m_cmd_sc_wdata_fifo.read();
3714
3715                if((r_sc_cpt.read() == 1) && m_cmd_sc_eop_fifo.read())
3716                    r_sc_wdata = m_cmd_sc_wdata_fifo.read();
3717
3718                if( r_sc_cpt.read()>3 ) // more than 4 flits...
3719                {
3720                    std::cout << "VCI_MEM_CACHE ERROR in SC_IDLE state : illegal SC command"
3721                              << std::endl;
3722                    exit(0);
3723                }
3724
3725                if ( r_sc_cpt.read()==2 )
3726                    r_sc_wdata = m_cmd_sc_wdata_fifo.read();
3727
3728                r_sc_cpt = r_sc_cpt.read()+1;
3729            }   
3730            break;
3731        }
3732        /////////////////
3733        case SC_DIR_LOCK:  // Read the directory
3734        {
3735            if( r_alloc_dir_fsm.read() == ALLOC_DIR_SC )
3736            {
3737                size_t way = 0;
3738                DirectoryEntry entry(m_cache_directory.read(m_cmd_sc_addr_fifo.read(), way));
3739
3740                r_sc_is_cnt     = entry.is_cnt;
3741                r_sc_dirty      = entry.dirty;
3742                r_sc_tag        = entry.tag;
3743                r_sc_way        = way;
3744                r_sc_copy       = entry.owner.srcid;
3745#if L1_MULTI_CACHE
3746                r_sc_copy_cache = entry.owner.cache_id;
3747#endif
3748                r_sc_copy_inst  = entry.owner.inst;
3749                r_sc_ptr        = entry.ptr;
3750                r_sc_count      = entry.count;
3751
3752                if ( entry.valid )      r_sc_fsm = SC_DIR_HIT_READ;
3753                else                    r_sc_fsm = SC_TRT_GET_LOCK;
3754
3755#if DEBUG_MEMC_SC
3756if( m_debug_sc_fsm )
3757{
3758    std::cout << "  <MEMC.SC_DIR_LOCK> Directory acces"
3759              << " / address = " << m_cmd_sc_addr_fifo.read()
3760              << " / hit = " << entry.valid
3761              << " / count = " << entry.count
3762              << " / is_cnt = " << entry.is_cnt << std::endl;
3763}
3764#endif
3765            }
3766            break;
3767        }
3768        /////////////////////
3769        case SC_DIR_HIT_READ:  // update directory for lock and dirty bit
3770                               // and check data change in cache
3771        {
3772            size_t way  = r_sc_way.read();
3773            size_t set  = m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3774            size_t word = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3775
3776            // update directory (lock & dirty bits)
3777            DirectoryEntry entry;
3778            entry.valid          = true;
3779            entry.is_cnt         = r_sc_is_cnt.read();
3780            entry.dirty          = true;
3781            entry.lock           = true;
3782            entry.tag            = r_sc_tag.read();
3783            entry.owner.srcid    = r_sc_copy.read();
3784#if L1_MULTI_CACHE
3785            entry.owner.cache_id = r_sc_copy_cache.read();
3786#endif
3787            entry.owner.inst     = r_sc_copy_inst.read();
3788            entry.count          = r_sc_count.read();
3789            entry.ptr            = r_sc_ptr.read();
3790
3791            m_cache_directory.write(set, way, entry);
3792
3793            // read data in cache & check data change
3794            bool ok = ( r_sc_rdata[0].read() == m_cache_data[way][set][word] );
3795            if ( r_sc_cpt.read()==4 )  // 64 bits SC
3796                ok &= ( r_sc_rdata[1] == m_cache_data[way][set][word+1] );
3797
3798            // to avoid livelock, force the atomic access to fail pseudo-randomly
3799            bool forced_fail = ( (r_sc_lfsr % (64) == 0) && RANDOMIZE_SC );
3800            r_sc_lfsr = (r_sc_lfsr >> 1) ^ ((-(r_sc_lfsr & 1)) & 0xd0000001);
3801
3802            if( ok and not forced_fail )        // no data change
3803            {
3804                r_sc_fsm = SC_DIR_HIT_WRITE;
3805            }
3806            else                            // return failure
3807            {
3808                r_sc_fsm = SC_RSP_FAIL;
3809            }
3810
3811#if DEBUG_MEMC_SC
3812if( m_debug_sc_fsm )
3813{
3814    std::cout << "  <MEMC.SC_DIR_HIT_READ> Test if SC success:"
3815              << " / expected value = " << r_sc_rdata[0].read()
3816              << " / actual value = " << m_cache_data[way][set][word]
3817              << " / forced_fail = " << forced_fail << std::endl;
3818}
3819#endif
3820            break;
3821        }
3822        ///// ////////////////
3823        case SC_DIR_HIT_WRITE:          // write data in the cache
3824                                    // and test if a coherence request is required
3825        {
3826            size_t way  = r_sc_way.read();
3827            size_t set  = m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3828            size_t word = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3829
3830            // cache update
3831            m_cache_data[way][set][word] = r_sc_wdata.read();
3832            if(r_sc_cpt.read()==4)
3833                m_cache_data[way][set][word+1] = m_cmd_sc_wdata_fifo.read();
3834         
3835            // test coherence request
3836            if(r_sc_count.read())   // replicated line
3837            {
3838                if ( r_sc_is_cnt.read() )
3839                {
3840                    r_sc_fsm = SC_TRT_PUT_LOCK;                 // broadcast invalidate required
3841                }
3842                else if( !r_sc_to_init_cmd_multi_req.read() &&
3843                         !r_sc_to_init_cmd_brdcast_req.read()  )
3844                {
3845                    r_sc_fsm = SC_UPT_LOCK;                     // multi update required
3846                }
3847                else
3848                {
3849                    r_sc_fsm = SC_WAIT;
3850                }
3851            }
3852            else                    // no copies
3853            {
3854                r_sc_fsm = SC_RSP_SUCCESS;
3855            }
3856
3857#if DEBUG_MEMC_SC
3858if( m_debug_sc_fsm )
3859{
3860    std::cout << "  <MEMC.SC_DIR_HIT_WRITE> Update cache:"
3861              << " way = " << std::dec << way
3862              << " / set = " << set
3863              << " / word = " << word
3864              << " / value = " << r_sc_wdata.read()
3865              << " / count = " << r_sc_count.read() << std::endl;
3866}
3867#endif
3868            break;
3869        }
3870        /////////////////
3871        case SC_UPT_LOCK:  //  register the transaction in UPT
3872        {
3873            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_SC )
3874            {
3875                bool        wok        = false;
3876                size_t      index      = 0;
3877                size_t      srcid      = m_cmd_sc_srcid_fifo.read();
3878                size_t      trdid      = m_cmd_sc_trdid_fifo.read();
3879                size_t      pktid      = m_cmd_sc_pktid_fifo.read();
3880                addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3881                size_t      nb_copies  = r_sc_count.read();
3882
3883                wok = m_update_tab.set(true,    // it's an update transaction
3884                                       false,   // it's not a broadcast
3885                                       true,    // it needs a response
3886                                       srcid,
3887                                       trdid,
3888                                       pktid,
3889                                       nline,
3890                                       nb_copies,
3891                                       index);
3892                if (wok)  // coherence transaction registered in UPT
3893                {
3894                    r_sc_upt_index = index;
3895                    r_sc_fsm = SC_HEAP_LOCK;
3896                }
3897                else       //  releases the locks protecting UPT and DIR if no entry
3898                {
3899                    r_sc_fsm = SC_WAIT;
3900                }
3901
3902#if DEBUG_MEMC_SC
3903if( m_debug_sc_fsm )
3904{
3905    std::cout << "  <MEMC.SC_UPT_LOCK> Register multi-update transaction in UPT" 
3906              << " / wok = " << wok
3907              << " / nline  = " << std::hex << nline
3908              << " / count = " << nb_copies << std::endl;
3909}
3910#endif
3911            }
3912            break;
3913        }
3914        /////////////
3915        case SC_WAIT:   // release all locks and retry from beginning
3916        {
3917
3918#if DEBUG_MEMC_SC
3919if( m_debug_sc_fsm )
3920{
3921    std::cout << "  <MEMC.SC_WAIT> Release all locks" << std::endl;
3922}
3923#endif
3924            r_sc_fsm = SC_DIR_LOCK;
3925            break;
3926        }
3927        //////////////////
3928        case SC_HEAP_LOCK:      // lock the heap
3929        {
3930            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_SC )
3931            {
3932
3933#if DEBUG_MEMC_SC
3934if( m_debug_sc_fsm )
3935{
3936    std::cout << "  <MEMC.SC_HEAP_LOCK> Get access to the heap" << std::endl;
3937}
3938#endif
3939                r_sc_fsm = SC_UPT_REQ;
3940            }
3941            break;
3942        }
3943        ////////////////
3944        case SC_UPT_REQ:        // send a first update request to INIT_CMD FSM
3945        {
3946            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_SC) and
3947                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
3948
3949            if( !r_sc_to_init_cmd_multi_req.read() && !r_sc_to_init_cmd_brdcast_req.read() )
3950            {
3951                r_sc_to_init_cmd_brdcast_req  = false;
3952                r_sc_to_init_cmd_trdid        = r_sc_upt_index.read();
3953                r_sc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3954                r_sc_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
3955                r_sc_to_init_cmd_wdata        = r_sc_wdata.read();
3956
3957                if(r_sc_cpt.read() == 4)
3958                {
3959                    r_sc_to_init_cmd_is_long    = true;
3960                    r_sc_to_init_cmd_wdata_high = m_cmd_sc_wdata_fifo.read();
3961                }
3962                else
3963                {
3964                    r_sc_to_init_cmd_is_long    = false;
3965                    r_sc_to_init_cmd_wdata_high = 0;
3966                }
3967
3968                // We put the first copy in the fifo
3969                sc_to_init_cmd_fifo_put     = true;
3970                sc_to_init_cmd_fifo_inst    = r_sc_copy_inst.read();
3971                sc_to_init_cmd_fifo_srcid   = r_sc_copy.read();
3972#if L1_MULTI_CACHE
3973                sc_to_init_cmd_fifo_cache_id= r_sc_copy_cache.read();
3974#endif
3975                if(r_sc_count.read() == 1) // one single copy
3976                {
3977                    r_sc_fsm = SC_IDLE;   // Response will be sent after receiving
3978                                            // update responses
3979                    cmd_sc_fifo_get            = true;
3980                    r_sc_to_init_cmd_multi_req = true;
3981                    r_sc_cpt = 0;
3982                }
3983                else                    // several copies
3984                {
3985                    r_sc_fsm = SC_UPT_NEXT;
3986                }
3987
3988#if DEBUG_MEMC_SC
3989if( m_debug_sc_fsm )
3990{
3991    std::cout << "  <MEMC.SC_UPT_REQ> Send the first update request to INIT_CMD FSM "
3992              << " / address = " << std::hex << m_cmd_sc_addr_fifo.read()
3993              << " / wdata = " << std::hex << r_sc_wdata.read()
3994              << " / srcid = " << std::hex << r_sc_copy.read()
3995              << " / inst = " << r_sc_copy_inst.read() << std::endl;
3996}
3997#endif
3998            }
3999            break;
4000        }
4001        /////////////////
4002        case SC_UPT_NEXT:       // send a multi-update request to INIT_CMD FSM
4003        {
4004            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_SC)
4005                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4006
4007            HeapEntry entry = m_heap.read(r_sc_ptr.read());
4008            sc_to_init_cmd_fifo_srcid    = entry.owner.srcid;
4009#if L1_MULTI_CACHE
4010            sc_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
4011#endif
4012            sc_to_init_cmd_fifo_inst     = entry.owner.inst;
4013            sc_to_init_cmd_fifo_put = true;
4014
4015            if( m_sc_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
4016            {
4017                r_sc_ptr = entry.next;
4018                if( entry.next == r_sc_ptr.read() )  // last copy
4019                {
4020                    r_sc_to_init_cmd_multi_req = true;
4021                    r_sc_fsm = SC_IDLE;   // Response will be sent after receiving
4022                                            // all update responses
4023                    cmd_sc_fifo_get = true;
4024                    r_sc_cpt        = 0;
4025                }
4026            }
4027
4028#if DEBUG_MEMC_SC
4029if( m_debug_sc_fsm )
4030{
4031    std::cout << "  <MEMC.SC_UPT_NEXT> Send the next update request to INIT_CMD FSM "
4032              << " / address = " << std::hex << m_cmd_sc_addr_fifo.read()
4033              << " / wdata = " << std::hex << r_sc_wdata.read()
4034              << " / srcid = " << std::hex << entry.owner.srcid
4035              << " / inst = " << entry.owner.inst << std::endl;
4036}
4037#endif
4038            break;
4039        }
4040        /////////////////////
4041        case SC_TRT_PUT_LOCK:           // check the TRT to register a PUT transaction     
4042        {
4043            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC )
4044            {
4045                if( !r_sc_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
4046                {
4047                    // fill the data buffer
4048                    size_t way  = r_sc_way.read();
4049                    size_t set  = m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4050                        size_t word = m_x[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4051                    for(size_t i = 0; i<m_words; i++)
4052                    {
4053                        if (i == word)
4054                        {
4055                            r_sc_to_ixr_cmd_data[i] = r_sc_wdata.read();
4056                        }
4057                        else if ( (i == word+1) && (r_sc_cpt.read()==4) ) // 64 bit SC
4058                        {
4059                            r_sc_to_ixr_cmd_data[i] = m_cmd_sc_wdata_fifo.read();
4060                        }
4061                        else
4062                        {
4063                            r_sc_to_ixr_cmd_data[i] = m_cache_data[way][set][i];
4064                        }
4065                    }
4066                    size_t wok_index = 0;
4067                    bool   wok       = !m_transaction_tab.full(wok_index);
4068                    if ( wok ) 
4069                    {
4070                        r_sc_trt_index = wok_index;
4071                        r_sc_fsm       = SC_INVAL_LOCK;
4072                    }
4073                    else
4074                    {
4075                        r_sc_fsm       = SC_WAIT;
4076                    }
4077                }
4078                else
4079                {
4080                    r_sc_fsm = SC_WAIT;
4081                }
4082            }
4083            break;
4084        }
4085        ///////////////////
4086        case SC_INVAL_LOCK:  // Register a broadcast inval transaction in UPT
4087        {
4088            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_SC )
4089            {
4090                bool        wok       = false;
4091                size_t      index     = 0;
4092                size_t      srcid     = m_cmd_sc_srcid_fifo.read();
4093                size_t      trdid     = m_cmd_sc_trdid_fifo.read();
4094                size_t      pktid     = m_cmd_sc_pktid_fifo.read();
4095                addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4096                size_t      nb_copies = r_sc_count.read();
4097
4098                // register a broadcast inval transaction in UPT
4099                wok = m_update_tab.set(false,   // it's an inval transaction
4100                                       true,    // it's a broadcast
4101                                       true,    // it needs a response
4102                                       srcid,
4103                                       trdid,
4104                                       pktid,
4105                                       nline,
4106                                       nb_copies,
4107                                       index);
4108               
4109                if ( wok )      // UPT not full
4110                {
4111                    r_sc_upt_index = index;
4112                    r_sc_fsm = SC_DIR_INVAL;
4113#if DEBUG_MEMC_SC
4114if( m_debug_sc_fsm )
4115{
4116    std::cout << "  <MEMC.SC_INVAL_LOCK> Register a broadcast inval transaction in UPT"
4117              << " / nline = " << nline
4118              << " / count = " << nb_copies
4119              << " / upt_index = " << index << std::endl;
4120}
4121#endif
4122                }
4123                else      //  releases the lock protecting UPT
4124                {
4125                     r_sc_fsm = SC_WAIT;
4126                }
4127            }
4128            break;
4129        }
4130        //////////////////
4131        case SC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
4132        {
4133            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_SC ) &&
4134                 (r_alloc_upt_fsm.read() == ALLOC_UPT_SC ) &&
4135                 (r_alloc_dir_fsm.read() == ALLOC_DIR_SC ))
4136            {
4137                // set TRT
4138                m_transaction_tab.set(r_sc_trt_index.read(),
4139                                      false,            // PUT request to XRAM
4140                                      m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())],
4141                                      0,
4142                                      0,
4143                                      0,
4144                                      false,            // not a processor read
4145                                      0,               
4146                                      0,
4147                                      std::vector<be_t>(m_words,0),
4148                                      std::vector<data_t>(m_words,0));
4149
4150                // invalidate directory entry
4151                DirectoryEntry entry;
4152                entry.valid             = false;
4153                entry.dirty             = false;
4154                entry.tag               = 0;
4155                entry.is_cnt        = false;
4156                entry.lock              = false;
4157                entry.count         = 0;
4158                entry.owner.srcid   = 0;
4159#if L1_MULTI_CACHE
4160                entry.owner.cache_id= 0;
4161#endif
4162                entry.owner.inst    = false;
4163                entry.ptr           = 0;
4164                size_t set              = m_y[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4165                size_t way              = r_sc_way.read();
4166                m_cache_directory.write(set, way, entry);
4167
4168                r_sc_fsm = SC_INVAL;
4169
4170#if DEBUG_MEMC_SC
4171if( m_debug_sc_fsm )
4172{
4173    std::cout << "  <MEMC.SC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
4174              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())]
4175              << " / set = " << std::dec << set << " / way = " << way << std::endl;
4176}
4177#endif
4178            }
4179            else
4180            {
4181                assert(false and "LOCK ERROR in SC_FSM, STATE = SC_DIR_INVAL");
4182            }
4183            break;
4184        }
4185        //////////////
4186        case SC_INVAL:  // Request the broadcast inval to INIT_CMD FSM
4187        {
4188            if ( !r_sc_to_init_cmd_multi_req.read() &&
4189                 !r_sc_to_init_cmd_brdcast_req.read())
4190            {
4191                r_sc_to_init_cmd_multi_req    = false;
4192                r_sc_to_init_cmd_brdcast_req  = true;
4193                r_sc_to_init_cmd_trdid        = r_sc_upt_index.read();
4194                r_sc_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4195                r_sc_to_init_cmd_index        = 0;
4196                r_sc_to_init_cmd_wdata        = 0;
4197
4198                r_sc_fsm = SC_TRT_PUT_REQ;
4199            }
4200            break;
4201        }
4202        ////////////////////
4203        case SC_TRT_PUT_REQ: // request the IXR FSM to start a put transaction
4204        {
4205            if ( !r_sc_to_ixr_cmd_req )
4206            {
4207                r_sc_to_ixr_cmd_req     = true;
4208                r_sc_to_ixr_cmd_write   = true;
4209                r_sc_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_sc_addr_fifo.read())];
4210                r_sc_to_ixr_cmd_trdid   = r_sc_trt_index.read();
4211                r_sc_fsm                = SC_IDLE;
4212                cmd_sc_fifo_get         = true;
4213                r_sc_cpt                = 0;
4214
4215#if DEBUG_MEMC_SC
4216if( m_debug_sc_fsm )
4217{
4218    std::cout << "  <MEMC.SC_TRT_PUT_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
4219              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]
4220              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
4221}
4222#endif
4223            }
4224            else
4225            {
4226               std::cout << "MEM_CACHE, SC_TRT_PUT_REQ state : request should not have been previously set"
4227                         << std::endl;
4228            }
4229            break;
4230        }
4231        /////////////////
4232        case SC_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
4233        {
4234            if( !r_sc_to_tgt_rsp_req )
4235            {
4236                cmd_sc_fifo_get     = true;
4237                r_sc_cpt              = 0;
4238                r_sc_to_tgt_rsp_req     = true;
4239                r_sc_to_tgt_rsp_data    = 1;
4240                r_sc_to_tgt_rsp_srcid   = m_cmd_sc_srcid_fifo.read();
4241                r_sc_to_tgt_rsp_trdid   = m_cmd_sc_trdid_fifo.read();
4242                r_sc_to_tgt_rsp_pktid   = m_cmd_sc_pktid_fifo.read();
4243                r_sc_fsm              = SC_IDLE;
4244
4245#if DEBUG_MEMC_SC
4246if( m_debug_sc_fsm )
4247{
4248    std::cout << "  <MEMC.SC_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
4249}
4250#endif
4251            }
4252            break;
4253        }
4254        ////////////////////
4255        case SC_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
4256        {
4257            if( !r_sc_to_tgt_rsp_req )
4258            {
4259                cmd_sc_fifo_get       = true;
4260                r_sc_cpt              = 0;
4261                r_sc_to_tgt_rsp_req     = true;
4262                r_sc_to_tgt_rsp_data    = 0;
4263                r_sc_to_tgt_rsp_srcid   = m_cmd_sc_srcid_fifo.read();
4264                r_sc_to_tgt_rsp_trdid   = m_cmd_sc_trdid_fifo.read();
4265                r_sc_to_tgt_rsp_pktid   = m_cmd_sc_pktid_fifo.read();
4266                r_sc_fsm              = SC_IDLE;
4267
4268#if DEBUG_MEMC_SC
4269if( m_debug_sc_fsm )
4270{
4271    std::cout << "  <MEMC.SC_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
4272}
4273#endif
4274            }
4275            break;
4276        }
4277        /////////////////////
4278        case SC_TRT_GET_LOCK:         // cache miss : request access to transaction Table
4279        {
4280            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC )
4281            {
4282                size_t   index = 0;
4283                bool hit_read = m_transaction_tab.hit_read(
4284                                  m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()],index);
4285                bool hit_write = m_transaction_tab.hit_write(
4286                                   m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]);
4287                bool wok = !m_transaction_tab.full(index);
4288
4289#if DEBUG_MEMC_SC
4290if( m_debug_sc_fsm )
4291{
4292    std::cout << "  <MEMC.SC_TRT_GET_LOCK> Check TRT state"
4293              << " / hit_read = "  << hit_read
4294              << " / hit_write = " << hit_write
4295              << " / wok = " << wok 
4296              << " / index = " << index << std::endl;
4297}
4298#endif
4299
4300                if ( hit_read || !wok || hit_write ) // missing line already requested or no space in TRT
4301                {
4302                    r_sc_fsm = SC_WAIT;
4303                }
4304                else
4305                {
4306                    r_sc_trt_index = index;
4307                    r_sc_fsm       = SC_TRT_GET_SET;
4308                }
4309            }
4310            break;
4311        }
4312        ////////////////////
4313        case SC_TRT_GET_SET:    // register the GET transaction in TRT
4314        {
4315            if( r_alloc_trt_fsm.read() == ALLOC_TRT_SC )
4316            {
4317                std::vector<be_t> be_vector;
4318                std::vector<data_t> data_vector;
4319                be_vector.clear();
4320                data_vector.clear();
4321                for ( size_t i=0; i<m_words; i++ )
4322                {   
4323                    be_vector.push_back(0);
4324                    data_vector.push_back(0);
4325                }
4326
4327                m_transaction_tab.set(r_sc_trt_index.read(),
4328                                      true,             // read request         
4329                                      m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()],
4330                                      m_cmd_sc_srcid_fifo.read(),
4331                                      m_cmd_sc_trdid_fifo.read(),
4332                                      m_cmd_sc_pktid_fifo.read(),
4333                                      false,            // write request from processor
4334                                      0,
4335                                      0,
4336                                      be_vector,
4337                                      data_vector);
4338                r_sc_fsm = SC_TRT_GET_REQ;       
4339
4340#if DEBUG_MEMC_SC
4341if( m_debug_sc_fsm )
4342{
4343    std::cout << "  <MEMC.SC_TRT_GET_SET> Register a GET transaction in TRT" << std::hex
4344              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]
4345              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
4346}
4347#endif
4348            }
4349            break;
4350        }
4351        ////////////////////
4352        case SC_TRT_GET_REQ:    // request the IXR_CMD FSM to fetch the missing line
4353        {
4354            if ( !r_sc_to_ixr_cmd_req )
4355            {
4356                r_sc_to_ixr_cmd_req        = true;
4357                r_sc_to_ixr_cmd_write      = false;
4358                r_sc_to_ixr_cmd_trdid      = r_sc_trt_index.read();
4359                r_sc_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()];
4360                r_sc_fsm                   = SC_WAIT;
4361
4362#if DEBUG_MEMC_SC
4363if( m_debug_sc_fsm )
4364{
4365    std::cout << "  <MEMC.SC_TRT_GET_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
4366              << " / nline = " << m_nline[(vci_addr_t)m_cmd_sc_addr_fifo.read()]
4367              << " / trt_index = " << r_sc_trt_index.read() << std::endl;
4368}
4369#endif
4370            }
4371            break;
4372        }
4373    } // end switch r_sc_fsm
4374
4375
4376    //////////////////////////////////////////////////////////////////////////////
4377    //          INIT_CMD FSM
4378    //////////////////////////////////////////////////////////////////////////////
4379    // The INIT_CMD fsm controls the VCI CMD initiator port, used to update
4380    // or invalidate cache lines in L1 caches.
4381    //
4382    // It implements a round-robin priority between the three possible client FSMs
4383    // XRAM_RSP, WRITE and SC. Each FSM can request two types of services:
4384    // - r_xram_rsp_to_init_cmd_multi_req : multi-inval 
4385    //   r_xram_rsp_to_init_cmd_brdcast_req : broadcast-inval 
4386    // - r_write_to_init_cmd_multi_req : multi-update 
4387    //   r_write_to_init_cmd_brdcast_req : broadcast-inval
4388    // - r_sc_to_init_cmd_multi_req : multi-update 
4389    //   r_sc_to_init_cmd_brdcast_req : broadcast-inval
4390    //
4391    // An inval request is a single cell VCI write command containing the
4392    // index of the line to be invalidated.
4393    // An update request is a multi-cells VCI write command : The first cell
4394    // contains the index of the cache line to be updated. The second cell contains
4395    // the index of the first modified word in the line. The following cells
4396    // contain the data.
4397    ///////////////////////////////////////////////////////////////////////////////
4398
4399    switch ( r_init_cmd_fsm.read() )
4400    {
4401        ////////////////////////
4402        case INIT_CMD_UPDT_IDLE:        // XRAM_RSP FSM has highest priority
4403        {
4404            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
4405                 r_xram_rsp_to_init_cmd_multi_req.read()  )
4406            {
4407                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
4408                m_cpt_inval++;
4409            }
4410            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
4411            {
4412                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
4413                m_cpt_inval++;
4414            }
4415            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
4416                      r_write_to_init_cmd_multi_req.read() )
4417            {
4418                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
4419                m_cpt_update++;
4420            }
4421            else if ( r_write_to_init_cmd_brdcast_req.read() )
4422            {
4423                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
4424                m_cpt_inval++;
4425            }
4426            else if ( m_sc_to_init_cmd_inst_fifo.rok() ||
4427                      r_sc_to_init_cmd_multi_req.read()  )
4428            {
4429                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
4430                m_cpt_update++;
4431            }
4432            else if( r_sc_to_init_cmd_brdcast_req.read() )
4433            {
4434                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
4435                m_cpt_inval++;
4436            }
4437            break;
4438        }
4439        /////////////////////////
4440        case INIT_CMD_INVAL_IDLE:       // WRITE FSM has highest priority
4441        {
4442            if ( m_write_to_init_cmd_inst_fifo.rok() ||
4443                 r_write_to_init_cmd_multi_req.read() )
4444            {
4445                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
4446                m_cpt_update++;
4447            }
4448            else if ( r_write_to_init_cmd_brdcast_req.read() )
4449            {
4450                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
4451                m_cpt_inval++;
4452            }
4453            else if ( m_sc_to_init_cmd_inst_fifo.rok() ||
4454                      r_sc_to_init_cmd_multi_req.read()  )
4455            {
4456                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
4457                m_cpt_update++;
4458            }
4459            else if( r_sc_to_init_cmd_brdcast_req.read() )
4460            {
4461                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
4462                m_cpt_inval++;
4463            }
4464            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
4465                      r_xram_rsp_to_init_cmd_multi_req.read()  )
4466            {
4467                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
4468                m_cpt_inval++;
4469            }
4470            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
4471            {
4472                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
4473                m_cpt_inval++;
4474            }
4475            break;
4476        }
4477        //////////////////////////
4478        case INIT_CMD_SC_UPDT_IDLE:     // SC FSM has highest priority
4479        {
4480            if ( m_sc_to_init_cmd_inst_fifo.rok() ||
4481                 r_sc_to_init_cmd_multi_req.read()  )
4482            {
4483                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
4484                m_cpt_update++;
4485            }
4486            else if( r_sc_to_init_cmd_brdcast_req.read() )
4487            {
4488                r_init_cmd_fsm = INIT_CMD_SC_BRDCAST;
4489                m_cpt_inval++;
4490            }
4491            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
4492                      r_xram_rsp_to_init_cmd_multi_req.read()  )
4493            {
4494                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
4495                m_cpt_inval++;
4496            }
4497            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
4498            {
4499                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
4500                m_cpt_inval++;
4501            }
4502            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
4503                      r_write_to_init_cmd_multi_req.read() )
4504            {
4505                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
4506                m_cpt_update++;
4507            }
4508            else if ( r_write_to_init_cmd_brdcast_req.read() )
4509            {
4510                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
4511                m_cpt_inval++;
4512            }
4513            break;
4514        }
4515        //////////////////////////
4516        case INIT_CMD_INVAL_NLINE:      // send a multi-inval (from XRAM_RSP)
4517        {
4518            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() )
4519            {
4520                if ( p_vci_ini.cmdack )
4521                {
4522                    m_cpt_inval_mult++;
4523                    r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
4524                    xram_rsp_to_init_cmd_fifo_get = true;
4525                }
4526            }
4527            else
4528            {
4529                if( r_xram_rsp_to_init_cmd_multi_req.read() ) r_xram_rsp_to_init_cmd_multi_req = false;
4530                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
4531            }
4532            break;
4533        }
4534        ///////////////////////////
4535        case INIT_CMD_XRAM_BRDCAST:     // send a broadcast-inval (from XRAM_RSP)
4536        {
4537            if ( p_vci_ini.cmdack )
4538            {
4539                m_cpt_inval_brdcast++;
4540                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
4541                r_xram_rsp_to_init_cmd_brdcast_req = false;
4542            }
4543            break;
4544        }
4545        ////////////////////////////
4546        case INIT_CMD_WRITE_BRDCAST:    // send a broadcast-inval (from WRITE FSM)
4547        {
4548            if( p_vci_ini.cmdack )
4549            {
4550
4551#if DEBUG_MEMC_INIT_CMD
4552if( m_debug_init_cmd_fsm )
4553{
4554    std::cout << "  <MEMC.INIT_CMD_WRITE_BRDCAST> Broadcast-Inval for line "
4555              << r_write_to_init_cmd_nline.read() << std::endl;
4556}
4557#endif
4558                m_cpt_inval_brdcast++;
4559                r_write_to_init_cmd_brdcast_req = false;
4560                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
4561            }
4562            break;
4563        }
4564        /////////////////////////
4565        case INIT_CMD_UPDT_NLINE:  // send nline for a multi-update (from WRITE FSM)
4566        {
4567            if ( m_write_to_init_cmd_inst_fifo.rok() )
4568            {
4569                if ( p_vci_ini.cmdack )
4570                {
4571                    m_cpt_update_mult++;
4572                    r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
4573                    // write_to_init_cmd_fifo_get = true;
4574                }
4575            }
4576            else
4577            {
4578                if ( r_write_to_init_cmd_multi_req.read() ) r_write_to_init_cmd_multi_req = false;
4579                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
4580            }
4581            break;
4582        }
4583        /////////////////////////
4584        case INIT_CMD_UPDT_INDEX:  // send word index for a multi-update (from WRITE FSM)
4585        {
4586            r_init_cmd_cpt    = 0;
4587            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
4588            break;
4589        }
4590        ////////////////////////
4591        case INIT_CMD_UPDT_DATA:  // send the data for a multi-update (from WRITE FSM)
4592        {
4593            if ( p_vci_ini.cmdack )
4594            {
4595                if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) )
4596                {
4597                    r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
4598                    write_to_init_cmd_fifo_get = true;
4599                }
4600                else
4601                {
4602                    r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
4603                }
4604            }
4605            break;
4606        }
4607        /////////////////////////
4608        case INIT_CMD_SC_BRDCAST:       // send a broadcast-inval (from SC FSM)
4609        {
4610            if( p_vci_ini.cmdack )
4611            {
4612                m_cpt_inval_brdcast++;
4613                r_sc_to_init_cmd_brdcast_req = false;
4614                r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
4615            }
4616            break;
4617        }
4618        ////////////////////////////
4619        case INIT_CMD_SC_UPDT_NLINE:   // send nline for a multi-update (from SC FSM)
4620        {
4621            if ( m_sc_to_init_cmd_inst_fifo.rok() )
4622            {
4623                if ( p_vci_ini.cmdack )
4624                {
4625                    m_cpt_update_mult++;
4626                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_INDEX;
4627                }
4628            }
4629            else
4630            {
4631                if( r_sc_to_init_cmd_multi_req.read() ) r_sc_to_init_cmd_multi_req = false;
4632                r_init_cmd_fsm = INIT_CMD_SC_UPDT_IDLE;
4633            }
4634            break;
4635        }
4636        ////////////////////////////
4637        case INIT_CMD_SC_UPDT_INDEX:  // send word index for a multi-update (from SC FSM)
4638        {
4639            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA;
4640            break;
4641        }
4642        ///////////////////////////
4643        case INIT_CMD_SC_UPDT_DATA:  // send first data for a multi-update (from SC FSM)
4644        {
4645            if ( p_vci_ini.cmdack )
4646            {
4647                if ( r_sc_to_init_cmd_is_long.read() )
4648                {
4649                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_DATA_HIGH;
4650                }
4651                else
4652                {
4653                    sc_to_init_cmd_fifo_get = true;
4654                    r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
4655                }
4656            }
4657            break;
4658        }
4659        ////////////////////////
4660        case INIT_CMD_SC_UPDT_DATA_HIGH:  // send second data for a multi-update (from SC FSM)
4661        {
4662            if ( p_vci_ini.cmdack )
4663            {
4664                sc_to_init_cmd_fifo_get = true;
4665                r_init_cmd_fsm = INIT_CMD_SC_UPDT_NLINE;
4666            }
4667            break;
4668        }
4669    } // end switch r_init_cmd_fsm
4670
4671    /////////////////////////////////////////////////////////////////////
4672    //          TGT_RSP FSM
4673    /////////////////////////////////////////////////////////////////////
4674    // The TGT_RSP fsm sends the responses on the VCI target port
4675    // with a round robin priority between six requests :
4676    // - r_read_to_tgt_rsp_req
4677    // - r_write_to_tgt_rsp_req
4678    // - r_sc_to_tgt_rsp_req
4679    // - r_cleanup_to_tgt_rsp_req
4680    // - r_xram_rsp_to_tgt_rsp_req
4681    // - r_init_rsp_to_tgt_rsp_req
4682    // The  ordering is :  read > write > sc > xram > init > cleanup
4683    /////////////////////////////////////////////////////////////////////
4684
4685    switch ( r_tgt_rsp_fsm.read() )
4686    {
4687        ///////////////////////
4688        case TGT_RSP_READ_IDLE:         // write requests have the highest priority
4689        {
4690          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4691          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4692          else if ( r_xram_rsp_to_tgt_rsp_req )
4693          {
4694            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4695            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4696          }
4697          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4698          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4699          else if ( r_read_to_tgt_rsp_req     )
4700          {
4701            r_tgt_rsp_fsm = TGT_RSP_READ;
4702            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4703          }
4704          break;
4705        }
4706        ////////////////////////
4707        case TGT_RSP_WRITE_IDLE:        // sc requests have the highest priority
4708        {
4709          if      ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4710          else if ( r_xram_rsp_to_tgt_rsp_req )
4711          {
4712            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4713            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4714          }
4715          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4716          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4717          else if ( r_read_to_tgt_rsp_req     )
4718          {
4719            r_tgt_rsp_fsm = TGT_RSP_READ;
4720            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4721          }
4722
4723          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4724          break;
4725        }
4726        ///////////////////////
4727        case TGT_RSP_SC_IDLE:           // xram_rsp requests have the highest priority
4728        {
4729          if ( r_xram_rsp_to_tgt_rsp_req ) 
4730          {
4731            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4732            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4733          }
4734          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4735          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4736          else if ( r_read_to_tgt_rsp_req     )
4737          {
4738            r_tgt_rsp_fsm = TGT_RSP_READ;
4739            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4740          }
4741          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4742          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4743          break;
4744        }
4745        ///////////////////////
4746        case TGT_RSP_XRAM_IDLE:         // init requests have the highest priority
4747        {
4748
4749          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4750          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4751          else if ( r_read_to_tgt_rsp_req     )
4752          {
4753            r_tgt_rsp_fsm = TGT_RSP_READ;
4754            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4755          }
4756          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4757          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4758          else if ( r_xram_rsp_to_tgt_rsp_req ) 
4759          {
4760            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4761            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4762          }
4763          break;
4764        }
4765        ///////////////////////
4766        case TGT_RSP_INIT_IDLE:         // cleanup requests have the highest priority
4767        {
4768          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4769          else if ( r_read_to_tgt_rsp_req     )
4770          {
4771            r_tgt_rsp_fsm = TGT_RSP_READ;
4772            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4773          }
4774          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4775          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4776          else if ( r_xram_rsp_to_tgt_rsp_req )
4777          {
4778            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4779            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4780          }
4781          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4782          break;
4783        }
4784        ///////////////////////
4785        case TGT_RSP_CLEANUP_IDLE:              // read requests have the highest priority
4786        {
4787          if      ( r_read_to_tgt_rsp_req     )
4788          {
4789            r_tgt_rsp_fsm = TGT_RSP_READ;
4790            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
4791          }
4792          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
4793          else if ( r_sc_to_tgt_rsp_req     ) r_tgt_rsp_fsm = TGT_RSP_SC;
4794          else if ( r_xram_rsp_to_tgt_rsp_req )
4795          {
4796            r_tgt_rsp_fsm = TGT_RSP_XRAM;
4797            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
4798          }
4799          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
4800          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
4801          break;
4802        }
4803        //////////////////
4804        case TGT_RSP_READ:              // send the response to a read
4805        {
4806            if ( p_vci_tgt.rspack )
4807            {
4808
4809#if DEBUG_MEMC_TGT_RSP
4810if( m_debug_tgt_rsp_fsm )
4811{
4812    std::cout << "  <MEMC.TGT_RSP_READ> Read response"
4813              << " / rsrcid = " << std::hex << r_read_to_tgt_rsp_srcid.read()
4814              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
4815              << " / rdata = " << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
4816              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
4817}
4818#endif
4819                if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) )
4820                {
4821                    r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
4822                    r_read_to_tgt_rsp_req = false;
4823                }
4824                else
4825                {
4826                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
4827                }
4828            }
4829            break;
4830        }
4831        ///////////////////
4832        case TGT_RSP_WRITE:             // send the write acknowledge
4833        {
4834            if ( p_vci_tgt.rspack )
4835            {
4836
4837#if DEBUG_MEMC_TGT_RSP
4838if( m_debug_tgt_rsp_fsm )
4839{
4840    std::cout << "  <MEMC.TGT_RSP_WRITE> Write response"
4841              << " / rsrcid = " << r_write_to_tgt_rsp_srcid.read()
4842              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read() << std::endl;
4843}
4844#endif
4845                r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
4846                r_write_to_tgt_rsp_req = false;
4847            }
4848            break;
4849        }
4850        ///////////////////
4851        case TGT_RSP_CLEANUP:           // pas clair pour moi (AG)   
4852        {
4853            if ( p_vci_tgt.rspack )
4854            {
4855
4856#if DEBUG_MEMC_TGT_RSP
4857if( m_debug_tgt_rsp_fsm )
4858{
4859    std::cout << "  <MEMC.TGT_RSP_CLEANUP> Cleanup response"
4860              << " / rsrcid = " << r_cleanup_to_tgt_rsp_srcid.read()
4861              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read() << std::endl;
4862}
4863#endif
4864                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
4865                r_cleanup_to_tgt_rsp_req = false;
4866            }
4867            break;
4868        }
4869        //////////////////
4870        case TGT_RSP_SC:                // send one atomic word response
4871        {
4872            if ( p_vci_tgt.rspack )
4873            {
4874
4875#if DEBUG_MEMC_TGT_RSP
4876if( m_debug_tgt_rsp_fsm )
4877{
4878    std::cout << "  <MEMC.TGT_RSP_SC> SC response"
4879              << " / rsrcid = " << r_sc_to_tgt_rsp_srcid.read()
4880              << " / rtrdid = " << r_sc_to_tgt_rsp_trdid.read() << std::endl;
4881}
4882#endif
4883                r_tgt_rsp_fsm = TGT_RSP_SC_IDLE;
4884                r_sc_to_tgt_rsp_req = false;
4885            }
4886            break;
4887        }
4888
4889        ///////////////////////
4890        case TGT_RSP_XRAM:              // send the response after XRAM access
4891        {
4892            if ( p_vci_tgt.rspack )
4893            {
4894
4895#if DEBUG_MEMC_TGT_RSP
4896if( m_debug_tgt_rsp_fsm )
4897{
4898    std::cout << "  <MEMC.TGT_RSP_XRAM> Response following XRAM access"
4899              << " / rsrcid = " << r_xram_rsp_to_tgt_rsp_srcid.read()
4900              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
4901              << " / rdata = " << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
4902              << " / cpt = " << r_tgt_rsp_cpt.read() << std::endl;
4903}
4904#endif
4905                if ( (r_tgt_rsp_cpt.read() ==
4906                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
4907                   || r_xram_rsp_to_tgt_rsp_rerror.read() )
4908                {
4909                    r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
4910                    r_xram_rsp_to_tgt_rsp_req = false;
4911                }
4912                else
4913                {
4914                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
4915                }
4916            }
4917            break;
4918        }
4919        //////////////////
4920        case TGT_RSP_INIT:              // send the write response after coherence transaction
4921        {
4922            if ( p_vci_tgt.rspack )
4923            {
4924
4925#if DEBUG_MEMC_TGT_RSP
4926if( m_debug_tgt_rsp_fsm )
4927{
4928    std::cout << "  <MEMC.TGT_RSP_INIT> Write response after coherence transaction"
4929              << " / rsrcid = " << r_init_rsp_to_tgt_rsp_srcid.read()
4930              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read() << std::endl;
4931}
4932#endif
4933                r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
4934                r_init_rsp_to_tgt_rsp_req = false;
4935            }
4936            break;
4937        }
4938    } // end switch tgt_rsp_fsm
4939
4940    ////////////////////////////////////////////////////////////////////////////////////
4941    //          ALLOC_UPT FSM
4942    ////////////////////////////////////////////////////////////////////////////////////
4943    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
4944    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
4945    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
4946    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
4947    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
4948    // - The CLEANUP  FSM decrement an entry in UPT.
4949    // The resource is always allocated.
4950    /////////////////////////////////////////////////////////////////////////////////////
4951
4952    switch ( r_alloc_upt_fsm.read() )
4953    {
4954
4955      ////////////////////////
4956      case ALLOC_UPT_INIT_RSP:
4957        if ( (r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK) &&
4958             (r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR) )
4959        {
4960          if      ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
4961                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
4962          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
4963          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
4964          else if ((r_sc_fsm.read() == SC_UPT_LOCK) ||
4965                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
4966        }
4967        break;
4968
4969        /////////////////////
4970      case ALLOC_UPT_WRITE:
4971        if ( (r_write_fsm.read() != WRITE_UPT_LOCK) &&
4972             (r_write_fsm.read() != WRITE_INVAL_LOCK))
4973        {
4974          if      (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
4975          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
4976          else if ((r_sc_fsm.read() == SC_UPT_LOCK) ||
4977                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
4978          else if (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
4979        }
4980        break;
4981
4982        ////////////////////////
4983      case ALLOC_UPT_XRAM_RSP:
4984        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
4985        {
4986          if       (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)       r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
4987          else if ((r_sc_fsm.read() == SC_UPT_LOCK) ||
4988                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
4989          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
4990          else if ((r_write_fsm.read() == WRITE_UPT_LOCK)   ||
4991                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
4992        }
4993        break;
4994
4995        //////////////////////////
4996      case ALLOC_UPT_CLEANUP:
4997        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
4998        {
4999          if      ((r_sc_fsm.read() == SC_UPT_LOCK) ||
5000                   (r_sc_fsm.read() == SC_INVAL_LOCK))            r_alloc_upt_fsm = ALLOC_UPT_SC;
5001          else if  (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)     r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5002          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
5003                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5004          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5005        }
5006        break;
5007       
5008        //////////////////////////
5009      case ALLOC_UPT_SC:
5010        if( (r_sc_fsm.read() != SC_UPT_LOCK) &&
5011            (r_sc_fsm.read() != SC_INVAL_LOCK))
5012        {
5013          if      (r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK)      r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5014          else if ((r_write_fsm.read() == WRITE_UPT_LOCK) ||
5015                   (r_write_fsm.read() == WRITE_INVAL_LOCK))        r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5016          else if (r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK)    r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5017          else if (r_cleanup_fsm.read() == CLEANUP_UPT_LOCK)        r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5018        }
5019        break;
5020
5021    } // end switch r_alloc_upt_fsm
5022
5023    ////////////////////////////////////////////////////////////////////////////////////
5024    //          ALLOC_DIR FSM
5025    ////////////////////////////////////////////////////////////////////////////////////
5026    // The ALLOC_DIR FSM allocates the access to the directory and
5027    // the data cache with a round robin priority between 5 user FSMs :
5028    // The cyclic ordering is READ > WRITE > SC > CLEANUP > XRAM_RSP
5029    // The ressource is always allocated.
5030    /////////////////////////////////////////////////////////////////////////////////////
5031
5032    switch ( r_alloc_dir_fsm.read() )
5033    {
5034
5035      ////////////////////
5036      case ALLOC_DIR_READ:
5037        if ( ( (r_read_fsm.read() != READ_DIR_LOCK) &&
5038              (r_read_fsm.read() != READ_TRT_LOCK)  &&
5039              (r_read_fsm.read() != READ_HEAP_LOCK))
5040            ||
5041            ( (r_read_fsm.read()        == READ_HEAP_LOCK) &&
5042              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_READ) )
5043            ||
5044            ( (r_read_fsm.read()      == READ_TRT_LOCK)  &&
5045              (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)    )  )
5046        {
5047          if        (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5048          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5049          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5050          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5051        }
5052        break;
5053
5054        /////////////////////
5055      case ALLOC_DIR_WRITE:
5056        if ( ( (r_write_fsm.read() != WRITE_DIR_LOCK)     &&
5057              (r_write_fsm.read() != WRITE_TRT_LOCK)     &&
5058              (r_write_fsm.read() != WRITE_DIR_HIT_READ) &&
5059              (r_write_fsm.read() != WRITE_DIR_HIT) &&
5060              (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
5061              (r_write_fsm.read() != WRITE_INVAL_LOCK) &&
5062              (r_write_fsm.read() != WRITE_UPT_LOCK) &&
5063              (r_write_fsm.read() != WRITE_HEAP_LOCK))
5064            ||
5065            ( (r_write_fsm.read()       == WRITE_HEAP_LOCK) &&
5066              (r_alloc_heap_fsm.read()  == ALLOC_HEAP_WRITE) )
5067            ||
5068            ( (r_write_fsm.read()     == WRITE_TRT_LOCK) &&
5069              (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)   )   )
5070        {
5071          if        (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5072          else if   (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)      r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5073          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5074          else if   (r_read_fsm.read() == READ_DIR_LOCK)                r_alloc_dir_fsm = ALLOC_DIR_READ;
5075        }
5076        break;
5077
5078        ////////////////////
5079        case ALLOC_DIR_SC:
5080        if ( ((r_sc_fsm.read() != SC_DIR_LOCK)       &&
5081              (r_sc_fsm.read() != SC_DIR_HIT_READ )  &&
5082              (r_sc_fsm.read() != SC_DIR_HIT_WRITE ) &&
5083//              (r_sc_fsm.read() != SC_TRT_GET_LOCK )    &&
5084              (r_sc_fsm.read() != SC_TRT_PUT_LOCK)       &&
5085              (r_sc_fsm.read() != SC_INVAL_LOCK)     &&
5086              (r_sc_fsm.read() != SC_UPT_LOCK)       &&
5087              (r_sc_fsm.read() != SC_HEAP_LOCK))
5088            ||
5089            ( (r_sc_fsm.read()       == SC_HEAP_LOCK) &&
5090              (r_alloc_heap_fsm.read() == ALLOC_HEAP_SC) )
5091            ||
5092            ( (r_sc_fsm.read()      == SC_TRT_GET_LOCK ) &&
5093              (r_alloc_trt_fsm.read() == ALLOC_TRT_SC)    ) )
5094        {
5095          if      (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5096          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)  r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5097          else if (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
5098          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5099        }
5100        break;
5101
5102        ///////////////////////
5103        case ALLOC_DIR_CLEANUP:
5104        if ( (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) &&
5105            (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) )
5106        {
5107          if        (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5108          else if   (r_read_fsm.read() == READ_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_READ;
5109          else if   (r_write_fsm.read() == WRITE_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5110          else if   (r_sc_fsm.read() == SC_DIR_LOCK)              r_alloc_dir_fsm = ALLOC_DIR_SC;
5111        }
5112        break;
5113        ////////////////////////
5114        case ALLOC_DIR_XRAM_RSP:
5115        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK)  &&
5116            (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)   &&
5117            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK))
5118        {
5119          if      (r_read_fsm.read() == READ_DIR_LOCK)          r_alloc_dir_fsm = ALLOC_DIR_READ;
5120          else if (r_write_fsm.read() == WRITE_DIR_LOCK)        r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5121          else if (r_sc_fsm.read() == SC_DIR_LOCK)            r_alloc_dir_fsm = ALLOC_DIR_SC;
5122          else if (r_cleanup_fsm.read() == CLEANUP_DIR_LOCK)    r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5123        }
5124        break;
5125
5126    } // end switch alloc_dir_fsm
5127
5128    ////////////////////////////////////////////////////////////////////////////////////
5129    //          ALLOC_TRT FSM
5130    ////////////////////////////////////////////////////////////////////////////////////
5131    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
5132    // with a round robin priority between 4 user FSMs :
5133    // The cyclic priority is READ > WRITE > SC > XRAM_RSP
5134    // The ressource is always allocated.
5135    ///////////////////////////////////////////////////////////////////////////////////
5136
5137    switch (r_alloc_trt_fsm)
5138    {
5139
5140      ////////////////////
5141      case ALLOC_TRT_READ:
5142        if ( r_read_fsm.read() != READ_TRT_LOCK )
5143        {
5144          if      ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
5145                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5146          else if ((r_sc_fsm.read() == SC_TRT_GET_LOCK) ||
5147                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5148          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5149          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5150                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ) )    r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5151        }
5152        break;
5153        /////////////////////
5154      case ALLOC_TRT_WRITE:
5155        if ( (r_write_fsm.read() != WRITE_TRT_LOCK) &&
5156             (r_write_fsm.read() != WRITE_TRT_WRITE_LOCK) &&
5157             (r_write_fsm.read() != WRITE_INVAL_LOCK))
5158        {
5159          if      ((r_sc_fsm.read() == SC_TRT_GET_LOCK) ||
5160                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5161          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5162          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5163                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5164          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5165        }
5166        break;
5167        ////////////////////
5168      case ALLOC_TRT_SC:
5169        if ( (r_sc_fsm.read() != SC_TRT_GET_LOCK) &&
5170             (r_sc_fsm.read() != SC_TRT_PUT_LOCK) &&
5171             (r_sc_fsm.read() != SC_INVAL_LOCK))
5172        {
5173          if      (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5174          else if ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5175                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5176          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5177          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)     ||
5178                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5179        }
5180        break;
5181        ////////////////////////
5182      case ALLOC_TRT_XRAM_RSP:
5183        if ( (r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY)  &&
5184            (r_xram_rsp_fsm.read() != XRAM_RSP_DIR_UPDT)   &&
5185            (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)) {
5186          if      ( (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE) ||
5187                    (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ))     r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5188          else if (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5189          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)    ||
5190                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5191          else if ((r_sc_fsm.read() == SC_TRT_GET_LOCK) ||
5192                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5193        }
5194        break;
5195        ////////////////////////
5196      case ALLOC_TRT_IXR_RSP:
5197        if ( (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE) &&
5198            (r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ) ) {
5199          if      (r_read_fsm.read() == READ_TRT_LOCK)              r_alloc_trt_fsm = ALLOC_TRT_READ;
5200          else if ((r_write_fsm.read() == WRITE_TRT_LOCK)   ||
5201                   (r_write_fsm.read() == WRITE_TRT_WRITE_LOCK))    r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5202          else if ((r_sc_fsm.read() == SC_TRT_GET_LOCK) ||
5203                   (r_sc_fsm.read() == SC_TRT_PUT_LOCK))              r_alloc_trt_fsm = ALLOC_TRT_SC;
5204          else if (r_xram_rsp_fsm.read() == XRAM_RSP_TRT_COPY)      r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5205        }
5206        break;
5207
5208    } // end switch alloc_trt_fsm
5209
5210    ////////////////////////////////////////////////////////////////////////////////////
5211    //          ALLOC_HEAP FSM
5212    ////////////////////////////////////////////////////////////////////////////////////
5213    // The ALLOC_HEAP FSM allocates the access to the heap
5214    // with a round robin priority between 5 user FSMs :
5215    // The cyclic ordering is READ > WRITE > SC > CLEANUP > XRAM_RSP
5216    // The ressource is always allocated.
5217    /////////////////////////////////////////////////////////////////////////////////////
5218
5219    switch ( r_alloc_heap_fsm.read() )
5220    {
5221
5222      ////////////////////
5223      case ALLOC_HEAP_READ:
5224        if (  (r_read_fsm.read() != READ_HEAP_LOCK) &&
5225              (r_read_fsm.read() != READ_HEAP_ERASE)     )
5226        {
5227          if        (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5228          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
5229          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5230          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5231        }
5232        break;
5233
5234        /////////////////////
5235      case ALLOC_HEAP_WRITE:
5236        if (  (r_write_fsm.read() != WRITE_HEAP_LOCK)   &&
5237              (r_write_fsm.read() != WRITE_UPT_REQ)     &&
5238              (r_write_fsm.read() != WRITE_UPDATE)  )
5239        {
5240          if        (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
5241          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5242          else if   (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5243          else if   (r_read_fsm.read() == READ_HEAP_LOCK)               r_alloc_heap_fsm = ALLOC_HEAP_READ;
5244        }
5245        break;
5246
5247        ////////////////////
5248      case ALLOC_HEAP_SC:
5249        if (  (r_sc_fsm.read() != SC_HEAP_LOCK)  &&
5250              (r_sc_fsm.read() != SC_UPT_REQ )    &&
5251              (r_sc_fsm.read() != SC_UPT_NEXT)  )
5252        {
5253          if      (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5254          else if (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5255          else if (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
5256          else if (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5257        }
5258        break;
5259
5260        ///////////////////////
5261      case ALLOC_HEAP_CLEANUP:
5262        if ( (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK) &&
5263            (r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH)&&
5264            (r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN)    )
5265        {
5266          if        (r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_ERASE)  r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5267          else if   (r_read_fsm.read() == READ_HEAP_LOCK)           r_alloc_heap_fsm = ALLOC_HEAP_READ;
5268          else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5269          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
5270        }
5271        break;
5272        ////////////////////////
5273      case ALLOC_HEAP_XRAM_RSP:
5274        if ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE )
5275        {
5276          if        (r_read_fsm.read() == READ_HEAP_LOCK)               r_alloc_heap_fsm = ALLOC_HEAP_READ;
5277          else if   (r_write_fsm.read() == WRITE_HEAP_LOCK)         r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5278          else if   (r_sc_fsm.read() == SC_HEAP_LOCK)             r_alloc_heap_fsm = ALLOC_HEAP_SC;
5279          else if   (r_cleanup_fsm.read() == CLEANUP_HEAP_LOCK)     r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5280        }
5281        break;
5282
5283    } // end switch alloc_heap_fsm
5284
5285
5286    ////////////////////////////////////////////////////////////////////////////////////
5287    //          TGT_CMD to READ FIFO
5288    ////////////////////////////////////////////////////////////////////////////////////
5289
5290    if ( cmd_read_fifo_put ) {
5291      if ( cmd_read_fifo_get ) {
5292        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5293        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
5294        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5295        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5296        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5297      } else {
5298        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5299        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
5300        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5301        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5302        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5303      }
5304    } else {
5305      if ( cmd_read_fifo_get ) {
5306        m_cmd_read_addr_fifo.simple_get();
5307        m_cmd_read_length_fifo.simple_get();
5308        m_cmd_read_srcid_fifo.simple_get();
5309        m_cmd_read_trdid_fifo.simple_get();
5310        m_cmd_read_pktid_fifo.simple_get();
5311      }
5312    }
5313    /////////////////////////////////////////////////////////////////////
5314    //          TGT_CMD to WRITE FIFO
5315    /////////////////////////////////////////////////////////////////////
5316
5317    if ( cmd_write_fifo_put ) {
5318      if ( cmd_write_fifo_get ) {
5319        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5320        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
5321        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5322        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5323        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5324        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
5325        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
5326      } else {
5327        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5328        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
5329        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5330        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5331        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5332        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
5333        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
5334      }
5335    } else {
5336      if ( cmd_write_fifo_get ) {
5337        m_cmd_write_addr_fifo.simple_get();
5338        m_cmd_write_eop_fifo.simple_get();
5339        m_cmd_write_srcid_fifo.simple_get();
5340        m_cmd_write_trdid_fifo.simple_get();
5341        m_cmd_write_pktid_fifo.simple_get();
5342        m_cmd_write_data_fifo.simple_get();
5343        m_cmd_write_be_fifo.simple_get();
5344      }
5345    }
5346    ////////////////////////////////////////////////////////////////////////////////////
5347    //          TGT_CMD to SC FIFO
5348    ////////////////////////////////////////////////////////////////////////////////////
5349
5350    if ( cmd_sc_fifo_put ) {
5351      if ( cmd_sc_fifo_get ) {
5352        m_cmd_sc_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
5353        m_cmd_sc_eop_fifo.put_and_get(p_vci_tgt.eop.read());
5354        m_cmd_sc_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
5355        m_cmd_sc_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
5356        m_cmd_sc_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
5357        m_cmd_sc_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
5358      } else {
5359        m_cmd_sc_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
5360        m_cmd_sc_eop_fifo.simple_put(p_vci_tgt.eop.read());
5361        m_cmd_sc_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
5362        m_cmd_sc_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
5363        m_cmd_sc_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
5364        m_cmd_sc_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
5365      }
5366    } else {
5367      if ( cmd_sc_fifo_get ) {
5368        m_cmd_sc_addr_fifo.simple_get();
5369        m_cmd_sc_eop_fifo.simple_get();
5370        m_cmd_sc_srcid_fifo.simple_get();
5371        m_cmd_sc_trdid_fifo.simple_get();
5372        m_cmd_sc_pktid_fifo.simple_get();
5373        m_cmd_sc_wdata_fifo.simple_get();
5374      }
5375    }
5376    ////////////////////////////////////////////////////////////////////////////////////
5377    //          WRITE to INIT_CMD FIFO
5378    ////////////////////////////////////////////////////////////////////////////////////
5379
5380    if ( write_to_init_cmd_fifo_put ) {
5381      if ( write_to_init_cmd_fifo_get ) {
5382        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
5383        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
5384#if L1_MULTI_CACHE
5385        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
5386#endif
5387      } else {
5388        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
5389        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
5390#if L1_MULTI_CACHE
5391        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
5392#endif
5393      }
5394    } else {
5395      if ( write_to_init_cmd_fifo_get ) {
5396        m_write_to_init_cmd_inst_fifo.simple_get();
5397        m_write_to_init_cmd_srcid_fifo.simple_get();
5398#if L1_MULTI_CACHE
5399        m_write_to_init_cmd_cache_id_fifo.simple_get();
5400#endif
5401      }
5402    }
5403    ////////////////////////////////////////////////////////////////////////////////////
5404    //          XRAM_RSP to INIT_CMD FIFO
5405    ////////////////////////////////////////////////////////////////////////////////////
5406
5407    if ( xram_rsp_to_init_cmd_fifo_put ) {
5408      if ( xram_rsp_to_init_cmd_fifo_get ) {
5409        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
5410        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
5411#if L1_MULTI_CACHE
5412        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
5413#endif
5414      } else {
5415        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
5416        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
5417#if L1_MULTI_CACHE
5418        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
5419#endif
5420      }
5421    } else {
5422      if ( xram_rsp_to_init_cmd_fifo_get ) {
5423        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
5424        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
5425#if L1_MULTI_CACHE
5426        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
5427#endif
5428      }
5429    }
5430    ////////////////////////////////////////////////////////////////////////////////////
5431    //          SC to INIT_CMD FIFO
5432    ////////////////////////////////////////////////////////////////////////////////////
5433
5434    if ( sc_to_init_cmd_fifo_put ) {
5435      if ( sc_to_init_cmd_fifo_get ) {
5436        m_sc_to_init_cmd_inst_fifo.put_and_get(sc_to_init_cmd_fifo_inst);
5437        m_sc_to_init_cmd_srcid_fifo.put_and_get(sc_to_init_cmd_fifo_srcid);
5438#if L1_MULTI_CACHE
5439        m_sc_to_init_cmd_cache_id_fifo.put_and_get(sc_to_init_cmd_fifo_cache_id);
5440#endif
5441      } else {
5442          m_sc_to_init_cmd_inst_fifo.simple_put(sc_to_init_cmd_fifo_inst);
5443          m_sc_to_init_cmd_srcid_fifo.simple_put(sc_to_init_cmd_fifo_srcid);
5444#if L1_MULTI_CACHE
5445          m_sc_to_init_cmd_cache_id_fifo.simple_put(sc_to_init_cmd_fifo_cache_id);
5446#endif
5447      }
5448    } else {
5449        if ( sc_to_init_cmd_fifo_get ) {
5450            m_sc_to_init_cmd_inst_fifo.simple_get();
5451            m_sc_to_init_cmd_srcid_fifo.simple_get();
5452#if L1_MULTI_CACHE
5453            m_sc_to_init_cmd_cache_id_fifo.simple_get();
5454#endif
5455      }
5456    }
5457
5458    m_cpt_cycles++;
5459
5460} // end transition()
5461
5462/////////////////////////////
5463tmpl(void)::genMoore()
5464/////////////////////////////
5465{
5466    ////////////////////////////////////////////////////////////
5467    // Command signals on the p_vci_ixr port
5468    ////////////////////////////////////////////////////////////
5469
5470    p_vci_ixr.be      = 0xF;
5471    p_vci_ixr.pktid   = 0;
5472    p_vci_ixr.srcid   = m_srcid_ixr;
5473    p_vci_ixr.cons    = false;
5474    p_vci_ixr.wrap    = false;
5475    p_vci_ixr.contig  = true;
5476    p_vci_ixr.clen    = 0;
5477    p_vci_ixr.cfixed  = false;
5478
5479    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
5480      p_vci_ixr.cmd     = vci_param::CMD_READ;
5481      p_vci_ixr.cmdval  = true;
5482      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
5483      p_vci_ixr.plen    = m_words*4;
5484      p_vci_ixr.wdata   = 0x00000000;
5485      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
5486      p_vci_ixr.eop     = true;
5487    }
5488    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_SC_NLINE ) {
5489      if(r_sc_to_ixr_cmd_write.read()){
5490        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5491        p_vci_ixr.cmdval  = true;
5492        p_vci_ixr.address = (addr_t)((r_sc_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5493        p_vci_ixr.plen    = m_words*4;
5494        p_vci_ixr.wdata   = r_sc_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5495        p_vci_ixr.trdid   = r_sc_to_ixr_cmd_trdid.read();
5496        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5497      } else {
5498        p_vci_ixr.cmd     = vci_param::CMD_READ;
5499        p_vci_ixr.cmdval  = true;
5500        p_vci_ixr.address = (addr_t)(r_sc_to_ixr_cmd_nline.read()*m_words*4);
5501        p_vci_ixr.plen    = m_words*4;
5502        p_vci_ixr.wdata   = 0x00000000;
5503        p_vci_ixr.trdid   = r_sc_to_ixr_cmd_trdid.read();
5504        p_vci_ixr.eop     = true;
5505      }
5506    }
5507    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
5508      if(r_write_to_ixr_cmd_write.read()){
5509        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5510        p_vci_ixr.cmdval  = true;
5511        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5512        p_vci_ixr.plen    = m_words*4;
5513        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5514        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
5515        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5516      } else {
5517        p_vci_ixr.cmd     = vci_param::CMD_READ;
5518        p_vci_ixr.cmdval  = true;
5519        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
5520        p_vci_ixr.plen    = m_words*4;
5521        p_vci_ixr.wdata   = 0x00000000;
5522        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
5523        p_vci_ixr.eop     = true;
5524      }
5525    }
5526    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
5527      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
5528      p_vci_ixr.cmdval  = true;
5529      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
5530      p_vci_ixr.plen    = m_words*4;
5531      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
5532      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
5533      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
5534    } else {
5535      p_vci_ixr.cmdval  = false;
5536      p_vci_ixr.address = 0;
5537      p_vci_ixr.plen    = 0;
5538      p_vci_ixr.wdata   = 0;
5539      p_vci_ixr.trdid   = 0;
5540      p_vci_ixr.eop     = false;
5541    }
5542
5543    ////////////////////////////////////////////////////
5544    // Response signals on the p_vci_ixr port
5545    ////////////////////////////////////////////////////
5546
5547    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
5548          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
5549        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
5550    else                                        p_vci_ixr.rspack = false;
5551
5552    ////////////////////////////////////////////////////
5553    // Command signals on the p_vci_tgt port
5554    ////////////////////////////////////////////////////
5555
5556    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
5557      case TGT_CMD_IDLE:
5558        p_vci_tgt.cmdack  = false;
5559        break;
5560      case TGT_CMD_READ:
5561        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
5562        break;
5563      case TGT_CMD_WRITE:
5564        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
5565        break;
5566      case TGT_CMD_ATOMIC:
5567        p_vci_tgt.cmdack  = m_cmd_sc_addr_fifo.wok();
5568        break;
5569      default:
5570        p_vci_tgt.cmdack = false;
5571        break;
5572    }
5573
5574    ////////////////////////////////////////////////////
5575    // Response signals on the p_vci_tgt port
5576    ////////////////////////////////////////////////////
5577    switch ( r_tgt_rsp_fsm.read() ) {
5578
5579      case TGT_RSP_READ_IDLE:
5580      case TGT_RSP_WRITE_IDLE:
5581      case TGT_RSP_SC_IDLE:
5582      case TGT_RSP_XRAM_IDLE:
5583      case TGT_RSP_INIT_IDLE:
5584      case TGT_RSP_CLEANUP_IDLE:
5585        p_vci_tgt.rspval  = false;
5586        p_vci_tgt.rsrcid  = 0;
5587        p_vci_tgt.rdata   = 0;
5588        p_vci_tgt.rpktid  = 0;
5589        p_vci_tgt.rtrdid  = 0;
5590        p_vci_tgt.rerror  = 0;
5591        p_vci_tgt.reop    = false;     
5592        break;
5593      case TGT_RSP_READ:
5594        p_vci_tgt.rspval   = true;
5595        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5596        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
5597        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
5598        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
5599        p_vci_tgt.rerror   = 0;
5600        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
5601        break;
5602      case TGT_RSP_WRITE:
5603        p_vci_tgt.rspval   = true;
5604        p_vci_tgt.rdata    = 0;
5605        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
5606        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
5607        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
5608        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
5609        p_vci_tgt.reop     = true;
5610        break;
5611      case TGT_RSP_CLEANUP:
5612        p_vci_tgt.rspval   = true;
5613        p_vci_tgt.rdata    = 0;
5614        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
5615        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
5616        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
5617        p_vci_tgt.rerror   = 0; // Can be a SC rsp
5618        p_vci_tgt.reop     = true;
5619        break;
5620      case TGT_RSP_SC:
5621        p_vci_tgt.rspval   = true;
5622        p_vci_tgt.rdata    = r_sc_to_tgt_rsp_data.read();
5623        p_vci_tgt.rsrcid   = r_sc_to_tgt_rsp_srcid.read();
5624        p_vci_tgt.rtrdid   = r_sc_to_tgt_rsp_trdid.read();
5625        p_vci_tgt.rpktid   = r_sc_to_tgt_rsp_pktid.read();
5626        p_vci_tgt.rerror   = 0;
5627        p_vci_tgt.reop     = true;
5628        break;
5629      case TGT_RSP_XRAM:
5630        p_vci_tgt.rspval   = true;
5631        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
5632        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
5633        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
5634        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
5635        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
5636        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
5637                                == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
5638                              || r_xram_rsp_to_tgt_rsp_rerror.read());
5639        break;
5640      case TGT_RSP_INIT:
5641        p_vci_tgt.rspval   = true;
5642        p_vci_tgt.rdata    = 0;
5643        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
5644        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
5645        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
5646        p_vci_tgt.rerror   = 0; // Can be a SC rsp
5647        p_vci_tgt.reop     = true;     
5648        break;
5649    } // end switch r_tgt_rsp_fsm
5650
5651    ///////////////////////////////////////////////////
5652    // Command signals on the p_vci_ini port
5653    ///////////////////////////////////////////////////
5654
5655    p_vci_ini.cmd     = vci_param::CMD_WRITE;
5656    p_vci_ini.srcid   = m_srcid_ini;
5657    p_vci_ini.cons    = true;
5658    p_vci_ini.wrap    = false;
5659    p_vci_ini.contig  = false;
5660    p_vci_ini.clen    = 0;
5661    p_vci_ini.cfixed  = false;
5662
5663    switch ( r_init_cmd_fsm.read() ) {
5664
5665      case INIT_CMD_UPDT_IDLE:
5666      case INIT_CMD_INVAL_IDLE:
5667      case INIT_CMD_SC_UPDT_IDLE:
5668        p_vci_ini.cmdval  = false;
5669        p_vci_ini.address = 0;
5670        p_vci_ini.wdata   = 0;
5671        p_vci_ini.be      = 0;
5672        p_vci_ini.plen    = 0;
5673        p_vci_ini.trdid   = 0;
5674        p_vci_ini.pktid   = 0;
5675        p_vci_ini.eop     = false;
5676        break;
5677      case INIT_CMD_INVAL_NLINE:
5678      {
5679        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
5680        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
5681          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
5682            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]+4);
5683          } else {
5684            p_vci_ini.address = (addr_t)(m_coherence_table[m_xram_rsp_to_init_cmd_srcid_fifo.read()]);
5685          }
5686        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
5687        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
5688        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
5689        p_vci_ini.plen    = 4;
5690        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
5691        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
5692        p_vci_ini.eop     = true;
5693        break;
5694      }
5695      case INIT_CMD_XRAM_BRDCAST:
5696        p_vci_ini.cmdval  = true;
5697        p_vci_ini.address = m_broadcast_address;
5698        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
5699        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
5700        p_vci_ini.plen    = 4;
5701        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
5702        p_vci_ini.pktid   = 0;
5703        p_vci_ini.eop     = true;
5704        break;
5705
5706      case INIT_CMD_WRITE_BRDCAST:
5707        p_vci_ini.cmdval  = true;
5708        p_vci_ini.address = m_broadcast_address;
5709        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
5710        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
5711        p_vci_ini.plen    = 4 ;
5712        p_vci_ini.eop     = true;
5713        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5714        p_vci_ini.pktid   = 0;
5715        break;
5716      case INIT_CMD_UPDT_NLINE:
5717        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
5718        if(m_write_to_init_cmd_inst_fifo.rok()){
5719          if(m_write_to_init_cmd_inst_fifo.read()) {
5720            p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
5721          } else {
5722            p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
5723          }
5724        } else {
5725          p_vci_ini.address = 0;
5726        }
5727        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
5728        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
5729        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5730        p_vci_ini.eop     = false;
5731        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5732        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5733        break;
5734      case INIT_CMD_UPDT_INDEX:
5735        p_vci_ini.cmdval  = true;
5736        if(m_write_to_init_cmd_inst_fifo.read()) {
5737          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
5738        } else {
5739          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
5740        }
5741        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
5742        p_vci_ini.be      = 0xF;
5743        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5744        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5745        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5746        p_vci_ini.eop     = false;
5747        break;
5748      case INIT_CMD_UPDT_DATA:
5749        p_vci_ini.cmdval  = true;
5750        if(m_write_to_init_cmd_inst_fifo.read()) {
5751          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 12);
5752        } else {
5753          p_vci_ini.address = (addr_t)(m_coherence_table[m_write_to_init_cmd_srcid_fifo.read()] + 8);
5754        }
5755        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
5756          r_write_to_init_cmd_index.read()].read();
5757        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
5758            r_write_to_init_cmd_index.read()].read()  ;
5759        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
5760        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
5761        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
5762        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
5763        break;
5764
5765      case INIT_CMD_SC_BRDCAST:
5766        p_vci_ini.cmdval  = true;
5767        p_vci_ini.address = m_broadcast_address;
5768        p_vci_ini.wdata   = (addr_t)r_sc_to_init_cmd_nline.read();
5769        p_vci_ini.be      = ((r_sc_to_init_cmd_nline.read() >> 32) & 0x3);
5770        p_vci_ini.plen    = 4 ;
5771        p_vci_ini.eop     = true;
5772        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
5773        p_vci_ini.pktid   = 0;
5774        break;
5775      case INIT_CMD_SC_UPDT_NLINE:
5776        p_vci_ini.cmdval  = m_sc_to_init_cmd_inst_fifo.rok();
5777        if(m_sc_to_init_cmd_inst_fifo.rok()){
5778          if( m_sc_to_init_cmd_inst_fifo.read() ) {
5779            p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
5780          } else {
5781            p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
5782          }
5783        } else {
5784          p_vci_ini.address = 0;
5785        }
5786        p_vci_ini.wdata   = (uint32_t)r_sc_to_init_cmd_nline.read();
5787        p_vci_ini.be      = ((r_sc_to_init_cmd_nline.read() >> 32 ) & 0x3);
5788        if(r_sc_to_init_cmd_is_long.read()){
5789            p_vci_ini.plen    = 4 * 4;
5790        } else {
5791            p_vci_ini.plen    = 4 * 3;
5792        }
5793        p_vci_ini.eop     = false;
5794        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
5795        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
5796        break;
5797      case INIT_CMD_SC_UPDT_INDEX:
5798        p_vci_ini.cmdval  = true;
5799        if( m_sc_to_init_cmd_inst_fifo.read() ) {
5800          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
5801        } else {
5802          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
5803        }
5804        p_vci_ini.wdata   = r_sc_to_init_cmd_index.read();
5805        p_vci_ini.be      = 0xF;
5806        if(r_sc_to_init_cmd_is_long.read()){
5807            p_vci_ini.plen    = 4 * 4;
5808        } else {
5809            p_vci_ini.plen    = 4 * 3;
5810        }
5811        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
5812        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
5813        p_vci_ini.eop     = false;
5814        break;
5815      case INIT_CMD_SC_UPDT_DATA:
5816        p_vci_ini.cmdval  = true;
5817        if( m_sc_to_init_cmd_inst_fifo.read() ) {
5818          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
5819        } else {
5820          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
5821        }
5822        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata.read();
5823        p_vci_ini.be      = 0xF;
5824        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
5825        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
5826        if(r_sc_to_init_cmd_is_long.read()){
5827            p_vci_ini.plen    = 4 * 4;
5828            p_vci_ini.eop     = false;
5829        } else {
5830            p_vci_ini.plen    = 4 * 3;
5831            p_vci_ini.eop     = true;
5832        }
5833        break;
5834      case INIT_CMD_SC_UPDT_DATA_HIGH:
5835        p_vci_ini.cmdval  = true;
5836        if( m_sc_to_init_cmd_inst_fifo.read() ) {
5837          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 12);
5838        } else {
5839          p_vci_ini.address = (addr_t)(m_coherence_table[m_sc_to_init_cmd_srcid_fifo.read()] + 8);
5840        }
5841        p_vci_ini.wdata   = r_sc_to_init_cmd_wdata_high.read();
5842        p_vci_ini.be      = 0xF;
5843        p_vci_ini.plen    = 4 * 4;
5844        p_vci_ini.trdid   = r_sc_to_init_cmd_trdid.read();
5845        p_vci_ini.pktid   = m_sc_to_init_cmd_cache_id_fifo.read();
5846        p_vci_ini.eop     = true;
5847        break;
5848
5849    } // end switch r_init_cmd_fsm
5850
5851    //////////////////////////////////////////////////////
5852    // Response signals on the p_vci_ini port
5853    //////////////////////////////////////////////////////
5854
5855    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
5856    else                                          p_vci_ini.rspack  = false;
5857
5858    //////////////////////////////////////////////////////
5859    // Response signals on the p_vci_tgt_cleanup port
5860    //////////////////////////////////////////////////////
5861    p_vci_tgt_cleanup.rspval = false;
5862    p_vci_tgt_cleanup.rsrcid = 0;
5863    p_vci_tgt_cleanup.rdata  = 0;
5864    p_vci_tgt_cleanup.rpktid = 0;
5865    p_vci_tgt_cleanup.rtrdid = 0;
5866    p_vci_tgt_cleanup.rerror = 0;
5867    p_vci_tgt_cleanup.reop   = false;
5868    p_vci_tgt_cleanup.cmdack = false ;
5869
5870    switch(r_cleanup_fsm.read()){
5871      case CLEANUP_IDLE:
5872        {
5873          p_vci_tgt_cleanup.cmdack = true ;
5874          break;
5875        }
5876      case CLEANUP_RSP:
5877        {
5878          p_vci_tgt_cleanup.rspval = true;
5879          p_vci_tgt_cleanup.rdata  = 0;
5880          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
5881          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
5882          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
5883          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
5884          p_vci_tgt_cleanup.reop   = 1;
5885          break;
5886        }
5887
5888    }
5889
5890} // end genMoore()
5891
5892}} // end name space
5893
5894// Local Variables:
5895// tab-width: 2
5896// c-basic-offset: 2
5897// c-file-offsets:((innamespace . 0)(inline-open . 0))
5898// indent-tabs-mode: nil
5899// End:
5900
5901// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
5902
Note: See TracBrowser for help on using the repository browser.