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

Last change on this file since 212 was 212, checked in by bouyer, 12 years ago

Introduce read_neutral(), which returns a directory entry without updating
the LRU bit.
Use read_neutral() in cache_monitor(), so that it doesn't affect the
cache state

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