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

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