source: branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 335

Last change on this file since 335 was 335, checked in by joannou, 11 years ago

Added llsc table initialization in both vci_mem_cache and vci_mem_cache_dspin_coherence components'reset

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