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

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

make the cache monitor function print the FSM state which does the update,
and print the srcid if it makes sense.
In the XRAM_RSP_DIR_UPDT, print the right data.

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