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

Last change on this file since 339 was 339, checked in by cfuguet, 11 years ago

Erasing always false condition in the if statement of the
WRITE_UPT_REQ state.

In this state the r_write_count register, is always bigger than 0.

  • 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: 247.2 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        size_t index        = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
1796
1797        r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
1798        r_write_word_index  = index;
1799        r_write_word_count  = 1;
1800        r_write_data[index] = m_cmd_write_data_fifo.read();
1801        r_write_srcid       = m_cmd_write_srcid_fifo.read();
1802        r_write_trdid       = m_cmd_write_trdid_fifo.read();
1803        r_write_pktid       = m_cmd_write_pktid_fifo.read();
1804        r_write_pending_sc  = false;
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        size_t index        = r_write_word_index.read() + r_write_word_count.read();
1863
1864        r_write_be[index]   = m_cmd_write_be_fifo.read();
1865        r_write_data[index] = m_cmd_write_data_fifo.read();
1866        r_write_word_count  = r_write_word_count.read() + 1;
1867
1868        if ( m_cmd_write_eop_fifo.read() )
1869        {
1870          r_write_fsm = WRITE_DIR_REQ;
1871        }
1872      }
1873      break;
1874    }
1875
1876    ////////////////////
1877    case WRITE_DIR_REQ:
1878    {
1879      // Get the lock to the directory
1880      // and access the llsc_global_table
1881      if(r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE)
1882      {
1883        ///////////////////////////////////////////////////////////////////////
1884        // SC command treatment
1885        // We test the r_write_pending_sc register to know if we are returning
1886        // from the WAIT state.
1887        // In this case, the SC has already succeed and we cannot consume
1888        // another time from the FIFO. Also, we don't have to test another
1889        // time if the SC has succeed
1890        if(((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
1891        {
1892          if(not m_cmd_write_addr_fifo.rok()) break;
1893
1894          assert(m_cmd_write_eop_fifo.read() &&
1895                 "Error in VCI_MEM_CACHE : "
1896                 "invalid packet format for SC command");
1897
1898          size_t index    = r_write_word_index.read();
1899          bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
1900                                            r_write_data[index].read());
1901
1902          // consume a word in the FIFO & write it in the local buffer
1903          cmd_write_fifo_get  = true;
1904          r_write_data[index] = m_cmd_write_data_fifo.read();
1905          r_write_sc_fail     = not sc_success;
1906          r_write_pending_sc  = true;
1907
1908          if(not sc_success) r_write_fsm = WRITE_RSP;
1909          else               r_write_fsm = WRITE_DIR_LOCK;
1910
1911          break;
1912        }
1913
1914        ///////////////////////////////////////////////////////////////////////
1915        // WRITE command or SC command treatment returning from the WAIT state
1916        // In the second case, we must access the LL/SC global table to
1917        // erase any possible new reservation when we release the lock on the
1918        // directory
1919        m_llsc_table.sw(r_write_address.read());
1920
1921        r_write_fsm = WRITE_DIR_LOCK;
1922      }
1923
1924#if DEBUG_MEMC_WRITE
1925      if(m_debug_write_fsm)
1926      {
1927        std::cout
1928            << "  <MEMC " << name() << ".WRITE_DIR_REQ> Requesting DIR lock "
1929            << std::endl;
1930      }
1931#endif
1932
1933      break;
1934    }
1935
1936    ////////////////////
1937    case WRITE_DIR_LOCK:
1938    // access directory to check hit/miss
1939    {
1940      if ( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
1941      {
1942        size_t  way = 0;
1943        DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
1944
1945        if ( entry.valid ) // hit
1946        {
1947          // copy directory entry in local buffer in case of hit
1948          r_write_is_cnt     = entry.is_cnt;
1949          r_write_lock       = entry.lock;
1950          r_write_tag        = entry.tag;
1951          r_write_copy       = entry.owner.srcid;
1952#if L1_MULTI_CACHE
1953          r_write_copy_cache = entry.owner.cache_id;
1954#endif
1955          r_write_copy_inst  = entry.owner.inst;
1956          r_write_count      = entry.count;
1957          r_write_ptr        = entry.ptr;
1958          r_write_way        = way;
1959
1960          if( entry.is_cnt && entry.count )
1961          {
1962            r_write_fsm = WRITE_DIR_READ;
1963          }
1964          else
1965          {
1966            r_write_fsm = WRITE_DIR_HIT;
1967          }
1968        }
1969        else  // miss
1970        {
1971          r_write_fsm = WRITE_MISS_TRT_LOCK;
1972        }
1973
1974#if DEBUG_MEMC_WRITE
1975        if( m_debug_write_fsm )
1976        {
1977          std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> Check the directory: "
1978            << " address = " << std::hex << r_write_address.read()
1979            << " hit = " << std::dec << entry.valid
1980            << " count = " << entry.count
1981            << " is_cnt = " << entry.is_cnt << std::endl;
1982          if((r_write_pktid.read() & 0x7) == TYPE_SC)
1983            std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> global_llsc_table SC access" << std::endl;
1984          else
1985            std::cout << "  <MEMC " << name() << ".WRITE_DIR_LOCK> global_llsc_table SW access" << std::endl;
1986        }
1987#endif
1988      }
1989      else
1990      {
1991        std::cout << "VCI_MEM_CACHE ERROR " << name()
1992          << " WRITE_DIR_LOCK state"        << std::endl
1993          << "bad DIR allocation"           << std::endl;
1994
1995        exit(0);
1996      }
1997
1998      break;
1999    }
2000
2001    ////////////////////
2002    case WRITE_DIR_READ:  // read the cache and complete the buffer when be!=0xF
2003    {
2004      // update local buffer
2005      size_t set  = m_y[(vci_addr_t)(r_write_address.read())];
2006      size_t way  = r_write_way.read();
2007      for(size_t word=0 ; word<m_words ; word++)
2008      {
2009        data_t mask = 0;
2010        if  (r_write_be[word].read() & 0x1) mask = mask | 0x000000FF;
2011        if  (r_write_be[word].read() & 0x2) mask = mask | 0x0000FF00;
2012        if  (r_write_be[word].read() & 0x4) mask = mask | 0x00FF0000;
2013        if  (r_write_be[word].read() & 0x8) mask = mask | 0xFF000000;
2014
2015        // complete only if mask is not null (for energy consumption)
2016        r_write_data[word]  = (r_write_data[word].read() & mask) |
2017          (m_cache_data.read(way, set, word) & ~mask);
2018
2019      } // end for
2020
2021      // test if a coherence broadcast is required
2022      r_write_fsm = WRITE_BC_TRT_LOCK;
2023
2024#if DEBUG_MEMC_WRITE
2025      if( m_debug_write_fsm )
2026      {
2027        std::cout << "  <MEMC " << name() << ".WRITE_DIR_READ> Read the cache to complete local buffer" << std::endl;
2028      }
2029#endif
2030      break;
2031    }
2032
2033    ///////////////////
2034    case WRITE_DIR_HIT:
2035    {
2036      // update the cache directory
2037      // update directory with Dirty bit
2038      DirectoryEntry entry;
2039      entry.valid          = true;
2040      entry.dirty          = true;
2041      entry.tag          = r_write_tag.read();
2042      entry.is_cnt         = r_write_is_cnt.read();
2043      entry.lock           = r_write_lock.read();
2044      entry.owner.srcid    = r_write_copy.read();
2045#if L1_MULTI_CACHE
2046      entry.owner.cache_id = r_write_copy_cache.read();
2047#endif
2048      entry.owner.inst     = r_write_copy_inst.read();
2049      entry.count          = r_write_count.read();
2050      entry.ptr            = r_write_ptr.read();
2051
2052      size_t set           = m_y[(vci_addr_t)(r_write_address.read())];
2053      size_t way           = r_write_way.read();
2054
2055      // update directory
2056      m_cache_directory.write(set, way, entry);
2057
2058      // owner is true when the  the first registered copy is the writer itself
2059      bool owner = (((r_write_copy.read() == r_write_srcid.read())
2060#if L1_MULTI_CACHE
2061            and (r_write_copy_cache.read()==r_write_pktid.read())
2062#endif
2063            ) and not r_write_copy_inst.read());
2064
2065      // no_update is true when there is no need for coherence transaction
2066      // (tests for sc requests)
2067      bool no_update = ((r_write_count.read()==0) || ( owner && (r_write_count.read()==1) && (r_write_pktid.read() != TYPE_SC)));
2068
2069      // write data in the cache if no coherence transaction
2070      if( no_update )
2071      {
2072        for(size_t word=0 ; word<m_words ; word++)
2073        {
2074          m_cache_data.write(way, set, word, r_write_data[word].read(), r_write_be[word].read());
2075
2076          if ( m_monitor_ok )
2077          {
2078            vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | word<<2;
2079            char buf[80];
2080            snprintf(buf, 80, "WRITE_DIR_HIT srcid %d", r_write_srcid.read());
2081            check_monitor( buf, address, r_write_data[word].read() );
2082          }
2083        }
2084      }
2085
2086      if ( owner and not no_update and (r_write_pktid.read() != TYPE_SC))
2087      {
2088        r_write_count = r_write_count.read() - 1;
2089      }
2090
2091      if ( no_update )
2092      // Write transaction completed
2093      {
2094        r_write_fsm = WRITE_RSP;
2095      }
2096      else
2097      // coherence update required
2098      {
2099        if( !r_write_to_init_cmd_multi_req.read()   &&
2100            !r_write_to_init_cmd_brdcast_req.read() )
2101        {
2102          r_write_fsm = WRITE_UPT_LOCK;
2103        }
2104        else
2105        {
2106          r_write_fsm = WRITE_WAIT;
2107        }
2108      }
2109
2110#if DEBUG_MEMC_WRITE
2111      if( m_debug_write_fsm )
2112      {
2113        if ( no_update )
2114        {
2115          std::cout << "  <MEMC " << name() << ".WRITE_DIR_HIT> Write into cache / No coherence transaction"
2116            << std::endl;
2117        }
2118        else
2119        {
2120          std::cout << "  <MEMC " << name() << ".WRITE_DIR_HIT> Coherence update required:"
2121            << " is_cnt = " << r_write_is_cnt.read()
2122            << " nb_copies = " << std::dec << r_write_count.read() << std::endl;
2123          if (owner)
2124            std::cout << "       ... but the first copy is the writer" << std::endl;
2125        }
2126      }
2127#endif
2128      break;
2129    }
2130
2131      ////////////////////
2132    case WRITE_UPT_LOCK:  // Try to register the update request in UPT
2133    {
2134      if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
2135      {
2136        bool        wok        = false;
2137        size_t      index      = 0;
2138        size_t      srcid      = r_write_srcid.read();
2139        size_t      trdid      = r_write_trdid.read();
2140        size_t      pktid      = r_write_pktid.read();
2141        addr_t      nline      = m_nline[(vci_addr_t)(r_write_address.read())];
2142        size_t      nb_copies  = r_write_count.read();
2143        size_t      set        = m_y[(vci_addr_t)(r_write_address.read())];
2144        size_t      way        = r_write_way.read();
2145
2146        wok = m_update_tab.set(true,  // it's an update transaction
2147            false,    // it's not a broadcast
2148            true,     // it needs a response
2149            srcid,
2150            trdid,
2151            pktid,
2152            nline,
2153            nb_copies,
2154            index);
2155        if ( wok )    // write data in cache
2156        {
2157          for(size_t word=0 ; word<m_words ; word++)
2158          {
2159            m_cache_data.write(way, set, word, r_write_data[word].read(), r_write_be[word].read());
2160
2161            if ( m_monitor_ok )
2162            {
2163              vci_addr_t address = (r_write_address.read() & ~(vci_addr_t)0x3F) | word<<2;
2164              char buf[80];
2165              snprintf(buf, 80, "WRITE_UPT_LOCK srcid %d", srcid);
2166              check_monitor(buf, address, r_write_data[word].read() );
2167            }
2168          }
2169        }
2170
2171#if DEBUG_MEMC_WRITE
2172        if( m_debug_write_fsm )
2173        {
2174          if ( wok )
2175          {
2176            std::cout << "  <MEMC " << name() << ".WRITE_UPT_LOCK> Register the multicast update in UPT / "
2177              << " nb_copies = " << r_write_count.read() << std::endl;
2178          }
2179        }
2180#endif
2181        r_write_upt_index = index;
2182        //  releases the lock protecting UPT and the DIR if no entry...
2183        if ( wok ) r_write_fsm = WRITE_UPT_HEAP_LOCK;
2184        else       r_write_fsm = WRITE_WAIT;
2185      }
2186      break;
2187    }
2188
2189      /////////////////////////
2190    case WRITE_UPT_HEAP_LOCK:   // get access to heap
2191    {
2192      if( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE )
2193      {
2194
2195#if DEBUG_MEMC_WRITE
2196        if( m_debug_write_fsm )
2197        {
2198          std::cout << "  <MEMC " << name() << ".WRITE_UPT_HEAP_LOCK> Get acces to the HEAP" << std::endl;
2199        }
2200#endif
2201        r_write_fsm = WRITE_UPT_REQ;
2202      }
2203      break;
2204    }
2205
2206    //////////////////
2207    case WRITE_UPT_REQ:
2208    {
2209      // prepare the coherence transaction for the INIT_CMD FSM
2210      // and write the first copy in the FIFO
2211      // send the request if only one copy
2212
2213      if( !r_write_to_init_cmd_multi_req.read() &&
2214          !r_write_to_init_cmd_brdcast_req.read()  )  // no pending coherence request
2215      {
2216        r_write_to_init_cmd_brdcast_req  = false;
2217        r_write_to_init_cmd_trdid        = r_write_upt_index.read();
2218        r_write_to_init_cmd_nline        = m_nline[(vci_addr_t)(r_write_address.read())];
2219        r_write_to_init_cmd_index        = r_write_word_index.read();
2220        r_write_to_init_cmd_count        = r_write_word_count.read();
2221
2222        for(size_t i=0; i<m_words ; i++) r_write_to_init_cmd_be[i]=r_write_be[i].read();
2223
2224        size_t min = r_write_word_index.read();
2225        size_t max = r_write_word_index.read() + r_write_word_count.read();
2226        for (size_t i=min ; i<max ; i++) r_write_to_init_cmd_data[i] = r_write_data[i];
2227
2228        if( (r_write_copy.read() != r_write_srcid.read()) or (r_write_pktid.read() == TYPE_SC) or
2229#if L1_MULTI_CACHE
2230            (r_write_copy_cache.read() != r_write_pktid.read()) or
2231#endif
2232            r_write_copy_inst.read() )
2233        {
2234          // put the first srcid in the fifo
2235          write_to_init_cmd_fifo_put     = true;
2236          write_to_init_cmd_fifo_inst    = r_write_copy_inst.read();
2237          write_to_init_cmd_fifo_srcid   = r_write_copy.read();
2238#if L1_MULTI_CACHE
2239          write_to_init_cmd_fifo_cache_id= r_write_copy_cache.read();
2240#endif
2241          if(r_write_count.read() == 1)
2242          {
2243            r_write_fsm = WRITE_IDLE;
2244            r_write_to_init_cmd_multi_req = true;
2245          }
2246          else
2247          {
2248            r_write_fsm = WRITE_UPT_NEXT;
2249            r_write_to_dec = false;
2250
2251          }
2252        }
2253        else
2254        {
2255          r_write_fsm = WRITE_UPT_NEXT;
2256          r_write_to_dec = false;
2257        }
2258
2259#if DEBUG_MEMC_WRITE
2260        if( m_debug_write_fsm )
2261        {
2262          std::cout << "  <MEMC " << name() << ".WRITE_UPT_REQ> Post first request to INIT_CMD FSM"
2263            << " / srcid = " << std::dec << r_write_copy.read()
2264            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2265          if ( r_write_count.read() == 1)
2266            std::cout << "         ... and this is the last" << std::endl;
2267        }
2268#endif
2269      }
2270      break;
2271    }
2272
2273    ///////////////////
2274    case WRITE_UPT_NEXT:
2275    {
2276      // continue the multi-update request to INIT_CMD fsm
2277      // when there is copies in the heap.
2278      // if one copy in the heap is the writer itself
2279      // the corresponding SRCID should not be written in the fifo,
2280      // but the UPT counter must be decremented.
2281      // As this decrement is done in the WRITE_UPT_DEC state,
2282      // after the last copy has been found, the decrement request
2283      // must be  registered in the r_write_to_dec flip-flop.
2284
2285      HeapEntry entry = m_heap.read(r_write_ptr.read());
2286
2287      bool dec_upt_counter;
2288
2289      if(((entry.owner.srcid != r_write_srcid.read()) || (r_write_pktid.read() == TYPE_SC)) or
2290#if L1_MULTI_CACHE
2291          (entry.owner.cache_id != r_write_pktid.read()) or
2292#endif
2293          entry.owner.inst)             // put the next srcid in the fifo
2294      {
2295        dec_upt_counter                 = false;
2296        write_to_init_cmd_fifo_put      = true;
2297        write_to_init_cmd_fifo_inst     = entry.owner.inst;
2298        write_to_init_cmd_fifo_srcid    = entry.owner.srcid;
2299#if L1_MULTI_CACHE
2300        write_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
2301#endif
2302
2303#if DEBUG_MEMC_WRITE
2304        if( m_debug_write_fsm )
2305        {
2306          std::cout << "  <MEMC " << name() << ".WRITE_UPT_NEXT> Post another request to INIT_CMD FSM"
2307            << " / heap_index = " << std::dec << r_write_ptr.read()
2308            << " / srcid = " << std::dec << r_write_copy.read()
2309            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2310          if( entry.next == r_write_ptr.read() )
2311            std::cout << "        ... and this is the last" << std::endl;
2312        }
2313#endif
2314      }
2315      else                                // the UPT counter must be decremented
2316      {
2317        dec_upt_counter = true;
2318
2319#if DEBUG_MEMC_WRITE
2320        if( m_debug_write_fsm )
2321        {
2322          std::cout << "  <MEMC " << name() << ".WRITE_UPT_NEXT> Skip one entry in heap matching the writer"
2323            << " / heap_index = " << std::dec << r_write_ptr.read()
2324            << " / srcid = " << std::dec << r_write_copy.read()
2325            << " / inst = "  << std::dec << r_write_copy_inst.read() << std::endl;
2326          if( entry.next == r_write_ptr.read() )
2327            std::cout << "        ... and this is the last" << std::endl;
2328        }
2329#endif
2330      }
2331
2332      // register the possible UPT decrement request
2333      r_write_to_dec = dec_upt_counter or r_write_to_dec.read();
2334
2335      if( not m_write_to_init_cmd_inst_fifo.wok() )
2336      {
2337        std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_UPT_NEXT state" << std::endl
2338          << "The write_to_init_cmd_fifo should not be full" << std::endl
2339          << "as the depth should be larger than the max number of copies" << std::endl;
2340        exit(0);
2341      }
2342
2343      r_write_ptr = entry.next;
2344
2345      if( entry.next == r_write_ptr.read() )  // last copy
2346      {
2347        r_write_to_init_cmd_multi_req = true;
2348        if( r_write_to_dec.read() or dec_upt_counter)   r_write_fsm = WRITE_UPT_DEC;
2349        else                                          r_write_fsm = WRITE_IDLE;
2350      }
2351      break;
2352    }
2353
2354    //////////////////
2355    case WRITE_UPT_DEC:
2356    {
2357      // If the initial writer has a copy, it should not
2358      // receive an update request, but the counter in the
2359      // update table must be decremented by the INIT_RSP FSM.
2360
2361      if ( !r_write_to_init_rsp_req.read() )
2362      {
2363        r_write_to_init_rsp_req = true;
2364        r_write_to_init_rsp_upt_index = r_write_upt_index.read();
2365        r_write_fsm = WRITE_IDLE;
2366      }
2367      break;
2368    }
2369   
2370    ///////////////
2371    case WRITE_RSP:
2372    {
2373      // Post a request to TGT_RSP FSM to acknowledge the write
2374      // In order to increase the Write requests throughput,
2375      // we don't wait to return in the IDLE state to consume
2376      // a new request in the write FIFO
2377
2378      if ( !r_write_to_tgt_rsp_req.read() )
2379      {
2380        // post the request to TGT_RSP_FSM
2381        r_write_to_tgt_rsp_req     = true;
2382        r_write_to_tgt_rsp_srcid   = r_write_srcid.read();
2383        r_write_to_tgt_rsp_trdid   = r_write_trdid.read();
2384        r_write_to_tgt_rsp_pktid   = r_write_pktid.read();
2385        r_write_to_tgt_rsp_sc_fail = r_write_sc_fail.read();
2386
2387        // try to get a new write request from the FIFO
2388        if ( m_cmd_write_addr_fifo.rok() )
2389        {
2390          if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
2391            m_cpt_sc++;
2392          else
2393          {
2394            m_cpt_write++;
2395            m_cpt_write_cells++;
2396          }
2397
2398          // consume a word in the FIFO & write it in the local buffer
2399          cmd_write_fifo_get  = true;
2400          size_t index        = m_x[(vci_addr_t)(m_cmd_write_addr_fifo.read())];
2401
2402          r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
2403          r_write_word_index  = index;
2404          r_write_word_count  = 1;
2405          r_write_data[index] = m_cmd_write_data_fifo.read();
2406          r_write_srcid       = m_cmd_write_srcid_fifo.read();
2407          r_write_trdid       = m_cmd_write_trdid_fifo.read();
2408          r_write_pktid       = m_cmd_write_pktid_fifo.read();
2409          r_write_pending_sc  = false;
2410
2411          // initialize the be field for all words
2412          for ( size_t word=0 ; word<m_words ; word++ )
2413          {
2414            if ( word == index ) r_write_be[word] = m_cmd_write_be_fifo.read();
2415            else                 r_write_be[word] = 0x0;
2416          }
2417
2418          if( m_cmd_write_eop_fifo.read() || ((m_cmd_write_pktid_fifo.read() & 0x7)  == TYPE_SC) )
2419          {
2420            r_write_fsm = WRITE_DIR_REQ;
2421          }
2422          else
2423          {
2424            r_write_fsm = WRITE_NEXT;
2425          }
2426        }
2427        else
2428        {
2429          r_write_fsm = WRITE_IDLE;
2430        }
2431
2432#if DEBUG_MEMC_WRITE
2433        if( m_debug_write_fsm )
2434        {
2435          std::cout << "  <MEMC " << name() << ".WRITE_RSP> Post a request to TGT_RSP FSM: rsrcid = "
2436            << std::dec << r_write_srcid.read() << std::endl;
2437          if ( m_cmd_write_addr_fifo.rok() )
2438          {
2439            std::cout << "                    New Write request: "
2440              << " srcid = " << std::dec << m_cmd_write_srcid_fifo.read()
2441              << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
2442              << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
2443          }
2444        }
2445#endif
2446      }
2447      break;
2448    }
2449
2450    /////////////////////////
2451    case WRITE_MISS_TRT_LOCK: // Miss : check Transaction Table
2452    {
2453      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2454      {
2455
2456#if DEBUG_MEMC_WRITE
2457        if( m_debug_write_fsm )
2458        {
2459          std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_LOCK> Check the TRT" << std::endl;
2460        }
2461#endif
2462        size_t  hit_index = 0;
2463        size_t  wok_index = 0;
2464        vci_addr_t  addr  = (vci_addr_t)r_write_address.read();
2465        bool    hit_read  = m_transaction_tab.hit_read(m_nline[addr], hit_index);
2466        bool    hit_write = m_transaction_tab.hit_write(m_nline[addr]);
2467        bool    wok       = !m_transaction_tab.full(wok_index);
2468
2469        if ( hit_read )   // register the modified data in TRT
2470        {
2471          r_write_trt_index = hit_index;
2472          r_write_fsm       = WRITE_MISS_TRT_DATA;
2473          m_cpt_write_miss++;
2474        }
2475        else if ( wok && !hit_write )   // set a new entry in TRT
2476        {
2477          r_write_trt_index = wok_index;
2478          r_write_fsm       = WRITE_MISS_TRT_SET;
2479          m_cpt_write_miss++;
2480        }
2481        else    // wait an empty entry in TRT
2482        {
2483          r_write_fsm       = WRITE_WAIT;
2484          m_cpt_trt_full++;
2485        }
2486      }
2487      break;
2488    }
2489
2490    ////////////////
2491    case WRITE_WAIT:  // release the locks protecting the shared ressources
2492    {
2493#if DEBUG_MEMC_WRITE
2494      if( m_debug_write_fsm )
2495      {
2496        std::cout << "  <MEMC " << name() << ".WRITE_WAIT> Releases the locks before retry" << std::endl;
2497      }
2498#endif
2499      r_write_fsm = WRITE_DIR_REQ;
2500      break;
2501    }
2502
2503    ////////////////////////
2504    case WRITE_MISS_TRT_SET:  // register a new transaction in TRT (Write Buffer)
2505    {
2506      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2507      {
2508        std::vector<be_t>   be_vector;
2509        std::vector<data_t> data_vector;
2510        be_vector.clear();
2511        data_vector.clear();
2512        for ( size_t i=0; i<m_words; i++ )
2513        {
2514          be_vector.push_back(r_write_be[i]);
2515          data_vector.push_back(r_write_data[i]);
2516        }
2517        m_transaction_tab.set(r_write_trt_index.read(),
2518            true,     // read request to XRAM
2519            m_nline[(vci_addr_t)(r_write_address.read())],
2520            r_write_srcid.read(),
2521            r_write_trdid.read(),
2522            r_write_pktid.read(),
2523            false,      // not a processor read
2524            0,        // not a single word
2525            0,            // word index
2526            be_vector,
2527            data_vector);
2528        r_write_fsm = WRITE_MISS_XRAM_REQ;
2529
2530#if DEBUG_MEMC_WRITE
2531        if( m_debug_write_fsm )
2532        {
2533          std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_SET> Set a new entry in TRT" << std::endl;
2534        }
2535#endif
2536      }
2537      break;
2538    }
2539
2540      /////////////////////////
2541    case WRITE_MISS_TRT_DATA: // update an entry in TRT (used as a Write Buffer)
2542    {
2543      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2544      {
2545        std::vector<be_t> be_vector;
2546        std::vector<data_t> data_vector;
2547        be_vector.clear();
2548        data_vector.clear();
2549        for ( size_t i=0; i<m_words; i++ )
2550        {
2551          be_vector.push_back(r_write_be[i]);
2552          data_vector.push_back(r_write_data[i]);
2553        }
2554        m_transaction_tab.write_data_mask(r_write_trt_index.read(),
2555            be_vector,
2556            data_vector);
2557        r_write_fsm = WRITE_RSP;
2558
2559#if DEBUG_MEMC_WRITE
2560        if( m_debug_write_fsm )
2561        {
2562          std::cout << "  <MEMC " << name() << ".WRITE_MISS_TRT_DATA> Modify an existing entry in TRT" << std::endl;
2563          m_transaction_tab.print( r_write_trt_index.read() );
2564        }
2565#endif
2566      }
2567      break;
2568    }
2569
2570    /////////////////////////
2571    case WRITE_MISS_XRAM_REQ: // send a GET request to IXR_CMD FSM
2572    {
2573      if ( !r_write_to_ixr_cmd_req )
2574      {
2575        r_write_to_ixr_cmd_req   = true;
2576        r_write_to_ixr_cmd_write = false;
2577        r_write_to_ixr_cmd_nline = m_nline[(vci_addr_t)(r_write_address.read())];
2578        r_write_to_ixr_cmd_trdid = r_write_trt_index.read();
2579        r_write_fsm              = WRITE_RSP;
2580
2581#if DEBUG_MEMC_WRITE
2582        if( m_debug_write_fsm )
2583        {
2584          std::cout << "  <MEMC " << name() << ".WRITE_MISS_XRAM_REQ> Post a GET request to the IXR_CMD FSM" << std::endl;
2585        }
2586#endif
2587      }
2588      break;
2589    }
2590
2591    ///////////////////////
2592    case WRITE_BC_TRT_LOCK:     // Check TRT not full
2593    {
2594      if ( r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE )
2595      {
2596        size_t wok_index = 0;
2597        bool wok = !m_transaction_tab.full( wok_index );
2598        if ( wok )    // set a new entry in TRT
2599        {
2600          r_write_trt_index = wok_index;
2601          r_write_fsm       = WRITE_BC_UPT_LOCK;
2602        }
2603        else  // wait an empty entry in TRT
2604        {
2605          r_write_fsm       = WRITE_WAIT;
2606        }
2607
2608#if DEBUG_MEMC_WRITE
2609        if( m_debug_write_fsm )
2610        {
2611          std::cout << "  <MEMC " << name() << ".WRITE_BC_TRT_LOCK> Check TRT : wok = "
2612            << wok << " / index = " << wok_index << std::endl;
2613        }
2614#endif
2615      }
2616      break;
2617    }
2618
2619    //////////////////////
2620    case WRITE_BC_UPT_LOCK:      // register BC transaction in UPT
2621    {
2622      if ( r_alloc_upt_fsm.read() == ALLOC_UPT_WRITE )
2623      {
2624        bool        wok       = false;
2625        size_t      index     = 0;
2626        size_t      srcid     = r_write_srcid.read();
2627        size_t      trdid     = r_write_trdid.read();
2628        size_t      pktid     = r_write_pktid.read();
2629        addr_t      nline     = m_nline[(vci_addr_t)(r_write_address.read())];
2630        size_t      nb_copies = r_write_count.read();
2631
2632        wok =m_update_tab.set(false,  // it's an inval transaction
2633            true,     // it's a broadcast
2634            true,     // it needs a response
2635            srcid,
2636            trdid,
2637            pktid,
2638            nline,
2639            nb_copies,
2640            index);
2641
2642#if DEBUG_MEMC_WRITE
2643        if( m_debug_write_fsm )
2644        {
2645          if ( wok )
2646          {
2647            std::cout << "  <MEMC " << name() << ".WRITE_BC_UPT_LOCK> Register the broadcast inval in UPT / "
2648              << " nb_copies = " << r_write_count.read() << std::endl;
2649          }
2650        }
2651#endif
2652        r_write_upt_index = index;
2653
2654        if ( wok ) r_write_fsm = WRITE_BC_DIR_INVAL;
2655        else       r_write_fsm = WRITE_WAIT;
2656      }
2657      break;
2658    }
2659
2660    ////////////////////////
2661    case WRITE_BC_DIR_INVAL:
2662    {
2663      // Register a put transaction to XRAM in TRT
2664      // and invalidate the line in directory
2665      if ( (r_alloc_trt_fsm.read() != ALLOC_TRT_WRITE ) ||
2666          (r_alloc_upt_fsm.read() != ALLOC_UPT_WRITE ) ||
2667          (r_alloc_dir_fsm.read() != ALLOC_DIR_WRITE ) )
2668      {
2669        std::cout << "VCI_MEM_CACHE ERROR " << name() << " WRITE_BC_DIR_INVAL state" << std::endl;
2670        std::cout << "bad TRT, DIR, or UPT allocation" << std::endl;
2671        exit(0);
2672      }
2673
2674      // register a write request to XRAM in TRT
2675      m_transaction_tab.set(r_write_trt_index.read(),
2676          false,    // write request to XRAM
2677          m_nline[(vci_addr_t)(r_write_address.read())],
2678          0,
2679          0,
2680          0,
2681          false,    // not a processor read
2682          0,        // not a single word
2683          0,            // word index
2684          std::vector<be_t>(m_words,0),
2685          std::vector<data_t>(m_words,0));
2686
2687      // invalidate directory entry
2688      DirectoryEntry entry;
2689      entry.valid         = false;
2690      entry.dirty         = false;
2691      entry.tag         = 0;
2692      entry.is_cnt        = false;
2693      entry.lock          = false;
2694      entry.owner.srcid   = 0;
2695#if L1_MULTI_CACHE
2696      entry.owner.cache_id= 0;
2697#endif
2698      entry.owner.inst    = false;
2699      entry.ptr           = 0;
2700      entry.count         = 0;
2701      size_t set          = m_y[(vci_addr_t)(r_write_address.read())];
2702      size_t way          = r_write_way.read();
2703
2704      m_cache_directory.write(set, way, entry);
2705
2706#if DEBUG_MEMC_WRITE
2707      if( m_debug_write_fsm )
2708      {
2709        std::cout << "  <MEMC " << name() << ".WRITE_BC_DIR_INVAL> Invalidate the directory entry: @ = "
2710          << r_write_address.read() << " / register the put transaction in TRT:" << std::endl;
2711      }
2712#endif
2713      r_write_fsm = WRITE_BC_CC_SEND;
2714      break;
2715    }
2716
2717    //////////////////////
2718    case WRITE_BC_CC_SEND:    // Post a coherence broadcast request to INIT_CMD FSM
2719    {
2720      if ( !r_write_to_init_cmd_multi_req.read() && !r_write_to_init_cmd_brdcast_req.read() )
2721      {
2722        r_write_to_init_cmd_multi_req   = false;
2723        r_write_to_init_cmd_brdcast_req = true;
2724        r_write_to_init_cmd_trdid       = r_write_upt_index.read();
2725        r_write_to_init_cmd_nline       = m_nline[(vci_addr_t)(r_write_address.read())];
2726        r_write_to_init_cmd_index       = 0;
2727        r_write_to_init_cmd_count       = 0;
2728
2729        for(size_t i=0; i<m_words ; i++)
2730        {
2731          r_write_to_init_cmd_be[i]=0;
2732          r_write_to_init_cmd_data[i] = 0;
2733        }
2734        r_write_fsm = WRITE_BC_XRAM_REQ;
2735
2736#if DEBUG_MEMC_WRITE
2737        if( m_debug_write_fsm )
2738        {
2739          std::cout << "  <MEMC " << name() << ".WRITE_BC_CC_SEND> Post a broadcast request to INIT_CMD FSM" << std::endl;
2740        }
2741#endif
2742      }
2743      break;
2744    }
2745
2746    ///////////////////////
2747    case WRITE_BC_XRAM_REQ:   // Post a put request to IXR_CMD FSM
2748    {
2749      if ( !r_write_to_ixr_cmd_req )
2750      {
2751        r_write_to_ixr_cmd_req     = true;
2752        r_write_to_ixr_cmd_write   = true;
2753        r_write_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(r_write_address.read())];
2754        r_write_to_ixr_cmd_trdid   = r_write_trt_index.read();
2755
2756        for(size_t i=0; i<m_words; i++) r_write_to_ixr_cmd_data[i] = r_write_data[i];
2757
2758        r_write_fsm = WRITE_IDLE;
2759
2760#if DEBUG_MEMC_WRITE
2761        if( m_debug_write_fsm )
2762        {
2763          std::cout << "  <MEMC " << name() << ".WRITE_BC_XRAM_REQ> Post a put request to IXR_CMD FSM" << std::endl;
2764        }
2765#endif
2766      }
2767      break;
2768    }
2769  } // end switch r_write_fsm
2770
2771    ///////////////////////////////////////////////////////////////////////
2772    //    IXR_CMD FSM
2773    ///////////////////////////////////////////////////////////////////////
2774    // The IXR_CMD fsm controls the command packets to the XRAM :
2775    // - It sends a single cell VCI read request to the XRAM in case of MISS
2776    // posted by the READ, WRITE or CAS FSMs : the TRDID field contains
2777    // the Transaction Tab index.
2778    // The VCI response is a multi-cell packet : the N cells contain
2779    // the N data words.
2780    // - It sends a multi-cell VCI write when the XRAM_RSP FSM, WRITE FSM
2781    // or CAS FSM request to save a dirty line to the XRAM.
2782    // The VCI response is a single cell packet.
2783    // This FSM handles requests from the READ, WRITE, CAS & XRAM_RSP FSMs
2784    // with a round-robin priority.
2785    ////////////////////////////////////////////////////////////////////////
2786
2787    switch ( r_ixr_cmd_fsm.read() )
2788    {
2789        ////////////////////////
2790        case IXR_CMD_READ_IDLE:
2791        if      ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2792        else 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        break;
2796        ////////////////////////
2797        case IXR_CMD_WRITE_IDLE:
2798        if      ( r_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
2799        else 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        break;
2803        ////////////////////////
2804        case IXR_CMD_CAS_IDLE:
2805        if      ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2806        else 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        break;
2810        ////////////////////////
2811        case IXR_CMD_XRAM_IDLE:
2812        if      ( r_read_to_ixr_cmd_req  )     r_ixr_cmd_fsm = IXR_CMD_READ_NLINE;
2813        else if ( r_write_to_ixr_cmd_req )     r_ixr_cmd_fsm = IXR_CMD_WRITE_NLINE;
2814        else if ( r_cas_to_ixr_cmd_req  )      r_ixr_cmd_fsm = IXR_CMD_CAS_NLINE;
2815        else if ( r_xram_rsp_to_ixr_cmd_req  ) r_ixr_cmd_fsm = IXR_CMD_XRAM_DATA;
2816        break;
2817        /////////////////////////       // send a get request to XRAM
2818        case IXR_CMD_READ_NLINE:
2819        if ( p_vci_ixr.cmdack )
2820        {
2821            r_ixr_cmd_fsm = IXR_CMD_READ_IDLE;
2822            r_read_to_ixr_cmd_req = false;
2823
2824#if DEBUG_MEMC_IXR_CMD
2825if( m_debug_ixr_cmd_fsm )
2826{
2827    std::cout << "  <MEMC " << name() << ".IXR_CMD_READ_NLINE> Send a get request to xram" << std::endl;
2828}
2829#endif
2830        }
2831        break;
2832        //////////////////////////
2833        case IXR_CMD_WRITE_NLINE:     // send a put or get command to XRAM
2834        if ( p_vci_ixr.cmdack )
2835        {
2836            if( r_write_to_ixr_cmd_write.read())
2837            {
2838                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2839                {
2840                    r_ixr_cmd_cpt = 0;
2841                    r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2842                    r_write_to_ixr_cmd_req = false;
2843                }
2844                else
2845                {
2846                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2847                }
2848
2849#if DEBUG_MEMC_IXR_CMD
2850if( m_debug_ixr_cmd_fsm )
2851{
2852    std::cout << "  <MEMC " << name() << ".IXR_CMD_WRITE_NLINE> Send a put request to xram" << std::endl;
2853}
2854#endif
2855            }
2856            else
2857            {
2858                r_ixr_cmd_fsm = IXR_CMD_WRITE_IDLE;
2859                r_write_to_ixr_cmd_req = false;
2860
2861#if DEBUG_MEMC_IXR_CMD
2862if( m_debug_ixr_cmd_fsm )
2863{
2864    std::cout << "  <MEMC " << name() << ".IXR_CMD_WRITE_NLINE> Send a get request to xram" << std::endl;
2865}
2866#endif
2867            }
2868        }
2869        break;
2870        //////////////////////
2871        case IXR_CMD_CAS_NLINE:      // send a put or get command to XRAM
2872        if ( p_vci_ixr.cmdack )
2873        {
2874            if( r_cas_to_ixr_cmd_write.read())
2875            {
2876                if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2877                {
2878                    r_ixr_cmd_cpt = 0;
2879                    r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2880                    r_cas_to_ixr_cmd_req = false;
2881                }
2882                else
2883                {
2884                    r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2885                }
2886
2887#if DEBUG_MEMC_IXR_CMD
2888if( m_debug_ixr_cmd_fsm )
2889{
2890    std::cout << "  <MEMC " << name() << ".IXR_CMD_CAS_NLINE> Send a put request to xram" << std::endl;
2891}
2892#endif
2893            }
2894            else
2895            {
2896                r_ixr_cmd_fsm = IXR_CMD_CAS_IDLE;
2897                r_cas_to_ixr_cmd_req = false;
2898
2899#if DEBUG_MEMC_IXR_CMD
2900if( m_debug_ixr_cmd_fsm )
2901{
2902    std::cout << "  <MEMC " << name() << ".IXR_CMD_CAS_NLINE> Send a get request to xram" << std::endl;
2903}
2904#endif
2905            }
2906        }
2907        break;
2908        ////////////////////////
2909        case IXR_CMD_XRAM_DATA:     // send a put command to XRAM
2910        if ( p_vci_ixr.cmdack )
2911        {
2912            if ( r_ixr_cmd_cpt.read() == (m_words - 1) )
2913            {
2914                r_ixr_cmd_cpt = 0;
2915                r_ixr_cmd_fsm = IXR_CMD_XRAM_IDLE;
2916                r_xram_rsp_to_ixr_cmd_req = false;
2917            }
2918            else
2919            {
2920                r_ixr_cmd_cpt = r_ixr_cmd_cpt + 1;
2921            }
2922
2923#if DEBUG_MEMC_IXR_CMD
2924if( m_debug_ixr_cmd_fsm )
2925{
2926    std::cout << "  <MEMC " << name() << ".IXR_CMD_XRAM_DATA> Send a put request to xram" << std::endl;
2927}
2928#endif
2929        }
2930        break;
2931
2932    } // end switch r_ixr_cmd_fsm
2933
2934    ////////////////////////////////////////////////////////////////////////////
2935    //                IXR_RSP FSM
2936    ////////////////////////////////////////////////////////////////////////////
2937    // The IXR_RSP FSM receives the response packets from the XRAM,
2938    // for both put transaction, and get transaction.
2939    //
2940    // - A response to a put request is a single-cell VCI packet.
2941    // The Transaction Tab index is contained in the RTRDID field.
2942    // The FSM takes the lock protecting the TRT, and the corresponding
2943    // entry is erased.
2944    //
2945    // - A response to a get request is a multi-cell VCI packet.
2946    // The Transaction Tab index is contained in the RTRDID field.
2947    // The N cells contain the N words of the cache line in the RDATA field.
2948    // The FSM takes the lock protecting the TRT to store the line in the TRT
2949    // (taking into account the write requests already stored in the TRT).
2950    // When the line is completely written, the corresponding rok signal is set.
2951    ///////////////////////////////////////////////////////////////////////////////
2952
2953    switch ( r_ixr_rsp_fsm.read() )
2954    {
2955        //////////////////
2956        case IXR_RSP_IDLE:  // test if it's a get or a put transaction
2957        {
2958            if ( p_vci_ixr.rspval.read() )
2959            {
2960                r_ixr_rsp_cpt   = 0;
2961                r_ixr_rsp_trt_index = p_vci_ixr.rtrdid.read();
2962                if ( p_vci_ixr.reop.read() && !(p_vci_ixr.rerror.read()&0x1))  // put transaction
2963                {
2964                    r_ixr_rsp_fsm = IXR_RSP_ACK;
2965
2966#if DEBUG_MEMC_IXR_RSP
2967if( m_debug_ixr_rsp_fsm )
2968{
2969    std::cout << "  <MEMC " << name() << ".IXR_RSP_IDLE> Response from XRAM to a put transaction" << std::endl;
2970}
2971#endif
2972                }
2973                else                     // get transaction
2974                {
2975          r_ixr_rsp_fsm = IXR_RSP_TRT_READ;
2976
2977#if DEBUG_MEMC_IXR_RSP
2978if( m_debug_ixr_rsp_fsm )
2979{
2980    std::cout << "  <MEMC " << name() << ".IXR_RSP_IDLE> Response from XRAM to a get transaction" << std::endl;
2981}
2982#endif
2983                }
2984            }
2985            break;
2986        }
2987        ////////////////////////
2988        case IXR_RSP_ACK:        // Aknowledge the VCI response
2989        {
2990            if(p_vci_ixr.rspval.read()) r_ixr_rsp_fsm = IXR_RSP_TRT_ERASE;
2991
2992#if DEBUG_MEMC_IXR_RSP
2993if( m_debug_ixr_rsp_fsm )
2994{
2995    std::cout << "  <MEMC " << name() << ".IXR_RSP_ACK>" << std::endl;
2996}
2997#endif
2998            break;
2999        }
3000        ////////////////////////
3001        case IXR_RSP_TRT_ERASE:   // erase the entry in the TRT
3002        {
3003            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP )
3004            {
3005                m_transaction_tab.erase(r_ixr_rsp_trt_index.read());
3006                r_ixr_rsp_fsm = IXR_RSP_IDLE;
3007
3008#if DEBUG_MEMC_IXR_RSP
3009if( m_debug_ixr_rsp_fsm )
3010{
3011    std::cout << "  <MEMC " << name() << ".IXR_RSP_TRT_ERASE> Erase TRT entry "
3012              << r_ixr_rsp_trt_index.read() << std::endl;
3013}
3014#endif
3015            }
3016            break;
3017        }
3018        ///////////////////////
3019        case IXR_RSP_TRT_READ:    // write data in the TRT
3020        {
3021            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&  p_vci_ixr.rspval )
3022            {
3023                size_t index    = r_ixr_rsp_trt_index.read();
3024                bool   eop    = p_vci_ixr.reop.read();
3025                data_t data   = p_vci_ixr.rdata.read();
3026                bool   error    = ((p_vci_ixr.rerror.read() & 0x1) == 1);
3027                assert(((eop == (r_ixr_rsp_cpt.read() == (m_words-1))) || p_vci_ixr.rerror.read())
3028                    and "Error in VCI_MEM_CACHE : invalid length for a response from XRAM");
3029                m_transaction_tab.write_rsp(index,
3030                                            r_ixr_rsp_cpt.read(),
3031                                            data,
3032                                            error);
3033                r_ixr_rsp_cpt = r_ixr_rsp_cpt.read() + 1;
3034                if ( eop )
3035                {
3036                    r_ixr_rsp_to_xram_rsp_rok[r_ixr_rsp_trt_index.read()]=true;
3037                    r_ixr_rsp_fsm = IXR_RSP_IDLE;
3038                }
3039
3040#if DEBUG_MEMC_IXR_RSP
3041if( m_debug_ixr_rsp_fsm )
3042{
3043    std::cout << "  <MEMC " << name() << ".IXR_RSP_TRT_READ> Writing a word in TRT : "
3044              << " index = " << std::dec << index
3045              << " / word = " << r_ixr_rsp_cpt.read()
3046              << " / data = " << std::hex << data << std::endl;
3047}
3048#endif
3049            }
3050            break;
3051        }
3052    } // end swich r_ixr_rsp_fsm
3053
3054    ////////////////////////////////////////////////////////////////////////////
3055    //                XRAM_RSP FSM
3056    ////////////////////////////////////////////////////////////////////////////
3057    // The XRAM_RSP FSM handles the incoming cache lines from the XRAM.
3058    // The cache line has been written in the TRT by the IXR_CMD_FSM.
3059    // As the IXR_RSP FSM and the XRAM_RSP FSM are running in parallel,
3060    // there is as many flip-flops r_ixr_rsp_to_xram_rsp_rok[i]
3061    // as the number of entries in the TRT, that are handled with
3062    // a round-robin priority...
3063    //
3064    // When a response is available, the corresponding TRT entry
3065    // must be copied in a local buffer to be written in the cache.
3066    // The FSM takes the lock protecting the TRT, and the lock protecting the DIR.
3067    // It selects a cache slot and writes the line in the cache.
3068    // If it was a read MISS, the XRAM_RSP FSM send a request to the TGT_RSP
3069    // FSM to return the cache line to the registered processor.
3070    // If there is no empty slot, a victim line is evicted, and
3071    // invalidate requests are sent to the L1 caches containing copies.
3072    // If this line is dirty, the XRAM_RSP FSM send a request to the IXR_CMD
3073    // FSM to save the victim line to the XRAM, and register the write transaction
3074    // in the TRT (using the entry previously used by the read transaction).
3075    ///////////////////////////////////////////////////////////////////////////////
3076
3077    switch ( r_xram_rsp_fsm.read() )
3078    {
3079        ///////////////////
3080        case XRAM_RSP_IDLE: // scan the XRAM responses to get the TRT index (round robin)
3081        {
3082            size_t ptr   = r_xram_rsp_trt_index.read();
3083            size_t lines = m_transaction_tab_lines;
3084            for( size_t i=0 ; i<lines ; i++)
3085            {
3086                size_t index=(i+ptr+1)%lines;
3087                if ( r_ixr_rsp_to_xram_rsp_rok[index] )
3088                {
3089                    r_xram_rsp_trt_index             = index;
3090                    r_ixr_rsp_to_xram_rsp_rok[index] = false;
3091                    r_xram_rsp_fsm                   = XRAM_RSP_DIR_LOCK;
3092
3093#if DEBUG_MEMC_XRAM_RSP
3094if( m_debug_xram_rsp_fsm )
3095{
3096    std::cout << "  <MEMC " << name() << ".XRAM_RSP_IDLE> Available cache line in TRT:"
3097              << " index = " << std::dec << index << std::endl;
3098}
3099#endif
3100                    break;
3101                }
3102            }
3103            break;
3104        }
3105        ///////////////////////
3106        case XRAM_RSP_DIR_LOCK:
3107        // Takes the lock on the directory
3108        // Takes the lock on TRT
3109        // Copy the TRT entry in a local buffer
3110        {
3111            if (( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ) &&
3112                ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP ))
3113            {
3114                // copy the TRT entry in the r_xram_rsp_trt_buf local buffer
3115                size_t  index = r_xram_rsp_trt_index.read();
3116
3117                TransactionTabEntry trt_entry(m_transaction_tab.read(index));
3118                r_xram_rsp_trt_buf.copy(trt_entry);  // TRT entry local buffer
3119
3120                r_xram_rsp_fsm = XRAM_RSP_TRT_COPY;
3121
3122#if DEBUG_MEMC_XRAM_RSP
3123if( m_debug_xram_rsp_fsm )
3124{
3125    std::cout << "  <MEMC " << name() << ".XRAM_RSP_DIR_LOCK> Get access to directory" << std::endl;
3126}
3127#endif
3128            }
3129            break;
3130        }
3131        ///////////////////////
3132        case XRAM_RSP_TRT_COPY:
3133        // Select a victim cache line
3134        {
3135            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP) )
3136            {
3137                // selects & extracts a victim line from cache
3138                size_t way = 0;
3139                size_t set = m_y[(vci_addr_t)(r_xram_rsp_trt_buf.nline * m_words * 4)];
3140
3141                DirectoryEntry victim(m_cache_directory.select(set, way));
3142
3143                bool inval = (victim.count && victim.valid) ;
3144
3145                // copy the victim line in a local buffer
3146                m_cache_data.read_line(way, set, r_xram_rsp_victim_data);
3147
3148                r_xram_rsp_victim_copy      = victim.owner.srcid;
3149#if L1_MULTI_CACHE
3150                r_xram_rsp_victim_copy_cache= victim.owner.cache_id;
3151#endif
3152                r_xram_rsp_victim_copy_inst = victim.owner.inst;
3153                r_xram_rsp_victim_count     = victim.count;
3154                r_xram_rsp_victim_ptr       = victim.ptr;
3155                r_xram_rsp_victim_way       = way;
3156                r_xram_rsp_victim_set       = set;
3157                r_xram_rsp_victim_nline     = victim.tag*m_sets + set;
3158                r_xram_rsp_victim_is_cnt    = victim.is_cnt;
3159                r_xram_rsp_victim_inval     = inval ;
3160                r_xram_rsp_victim_dirty     = victim.dirty;
3161
3162                if(!r_xram_rsp_trt_buf.rerror)
3163                {
3164                  r_xram_rsp_fsm = XRAM_RSP_INVAL_LOCK;
3165                }
3166                else
3167                {
3168                  r_xram_rsp_fsm = XRAM_RSP_ERROR_ERASE;
3169                }
3170
3171#if DEBUG_MEMC_XRAM_RSP
3172if( m_debug_xram_rsp_fsm )
3173{
3174    std::cout << "  <MEMC " << name() << ".XRAM_RSP_TRT_COPY> Select a slot: "
3175              << " way = " << std::dec << way
3176              << " / set = " << set
3177              << " / inval_required = " << inval << std::endl;
3178}
3179#endif
3180            }
3181            else
3182            {
3183                std::cout << "VCI_MEM_CACHE ERROR "     << name()
3184                          << " XRAM_RSP_TRT_COPY state" << std::endl
3185                          << "bad TRT allocation"       << std::endl;
3186
3187                exit(0);
3188            }
3189            break;
3190        }
3191        /////////////////////////
3192        case XRAM_RSP_INVAL_LOCK: // check a possible pending inval
3193        {
3194            if ( r_alloc_upt_fsm == ALLOC_UPT_XRAM_RSP )
3195            {
3196                size_t index;
3197                if (m_update_tab.search_inval(r_xram_rsp_trt_buf.nline, index))
3198                {
3199                    r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3200
3201#if DEBUG_MEMC_XRAM_RSP
3202if( m_debug_xram_rsp_fsm )
3203{
3204    std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
3205              << " but an invalidation is already registered at this address" << std::endl;
3206    m_update_tab.print();
3207}
3208#endif
3209
3210                }
3211              else if (m_update_tab.is_full() && r_xram_rsp_victim_inval.read())
3212                {
3213                  r_xram_rsp_fsm = XRAM_RSP_INVAL_WAIT;
3214
3215#if DEBUG_MEMC_XRAM_RSP
3216if( m_debug_xram_rsp_fsm )
3217{
3218    std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL_LOCK> Get acces to UPT,"
3219              << " but the table is full" << std::endl;
3220    m_update_tab.print();
3221}
3222#endif
3223              }
3224                else
3225                {
3226                    r_xram_rsp_fsm = XRAM_RSP_DIR_UPDT;
3227
3228#if DEBUG_MEMC_XRAM_RSP
3229if( m_debug_xram_rsp_fsm )
3230{
3231    std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL_LOCK> Get acces to UPT" << std::endl;
3232}
3233#endif
3234                }
3235            }
3236            break;
3237        }
3238        /////////////////////////
3239        case XRAM_RSP_INVAL_WAIT: // returns to DIR_LOCK to retry
3240        {
3241            r_xram_rsp_fsm = XRAM_RSP_DIR_LOCK;
3242            break;
3243        }
3244        ///////////////////////
3245        case XRAM_RSP_DIR_UPDT:   // updates the cache (both data & directory)
3246                                        // and possibly set an inval request in UPT
3247        {
3248            // signals generation
3249            // check if this is an instruction read, this means pktid is either
3250            // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
3251            // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3252            bool inst_read = (r_xram_rsp_trt_buf.pktid & 0x2) && r_xram_rsp_trt_buf.proc_read;
3253            // check if this is a cached read, this means pktid is either
3254            // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
3255            // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
3256            bool cached_read = (r_xram_rsp_trt_buf.pktid & 0x1) && r_xram_rsp_trt_buf.proc_read;
3257
3258            // update data
3259            size_t set   = r_xram_rsp_victim_set.read();
3260            size_t way   = r_xram_rsp_victim_way.read();
3261            for(size_t word=0; word<m_words ; word++)
3262            {
3263                m_cache_data.write(way, set, word, r_xram_rsp_trt_buf.wdata[word]);
3264
3265                if ( m_monitor_ok )
3266                {
3267                    vci_addr_t address = r_xram_rsp_trt_buf.nline<<6 | word<<2;
3268                    check_monitor("XRAM_RSP_DIR_UPDT", address, r_xram_rsp_trt_buf.wdata[word]);
3269                }
3270            }
3271            // compute dirty
3272            bool dirty = false;
3273            for(size_t i=0; i<m_words;i++) dirty = dirty || (r_xram_rsp_trt_buf.wdata_be[i] != 0);
3274            // update directory
3275            DirectoryEntry entry;
3276            entry.valid   = true;
3277            entry.is_cnt  = false;
3278            entry.lock    = false;
3279            entry.dirty   = dirty;
3280            entry.tag     = r_xram_rsp_trt_buf.nline / m_sets;
3281            entry.ptr     = 0;
3282            if(cached_read)
3283            {
3284                entry.owner.srcid   = r_xram_rsp_trt_buf.srcid;
3285#if L1_MULTI_CACHE
3286                entry.owner.cache_id= r_xram_rsp_trt_buf.pktid;
3287#endif
3288                entry.owner.inst    = inst_read;
3289                entry.count         = 1;
3290            }
3291            else
3292            {
3293                entry.owner.srcid    = 0;
3294#if L1_MULTI_CACHE
3295                entry.owner.cache_id = 0;
3296#endif
3297                entry.owner.inst     = 0;
3298                entry.count          = 0;
3299            }
3300            m_cache_directory.write(set, way, entry);
3301
3302            if (r_xram_rsp_victim_inval.read())
3303            {
3304                bool   brdcast    = r_xram_rsp_victim_is_cnt.read();
3305                size_t index    = 0;
3306                size_t count_copies   = r_xram_rsp_victim_count.read();
3307
3308                bool   wok = m_update_tab.set(  false,    // it's an inval transaction
3309                        brdcast,  // set brdcast bit
3310                        false,    // it does not need a response
3311                        0,    // srcid
3312                        0,    // trdid
3313                        0,    // pktid
3314                        r_xram_rsp_victim_nline.read(),
3315                        count_copies,
3316                        index);
3317                r_xram_rsp_upt_index = index;
3318
3319                if (!wok)
3320                {
3321                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
3322                    std::cout << "an update_tab entry was free but write is unsuccessful" << std::endl;
3323                    exit(0);
3324                }
3325            }
3326
3327#if DEBUG_MEMC_XRAM_RSP
3328if( m_debug_xram_rsp_fsm )
3329{
3330    std::cout << "  <MEMC " << name() << ".XRAM_RSP_DIR_UPDT> Directory update: "
3331              << " way = " << std::dec << way
3332              << " / set = " << set
3333              << " / count = " << entry.count
3334              << " / is_cnt = " << entry.is_cnt << std::endl;
3335    if (r_xram_rsp_victim_inval.read())
3336    std::cout << "                           Invalidation request for victim line "
3337              << std::hex << r_xram_rsp_victim_nline.read()
3338              << " / broadcast = " << r_xram_rsp_victim_is_cnt.read() << std::endl;
3339}
3340#endif
3341
3342            // If the victim is not dirty, we don't need another XRAM  put transaction,
3343            // and we canwe erase the TRT entry
3344            if (!r_xram_rsp_victim_dirty.read())  m_transaction_tab.erase(r_xram_rsp_trt_index.read());
3345
3346            // Next state
3347            if      ( r_xram_rsp_victim_dirty.read())       r_xram_rsp_fsm = XRAM_RSP_TRT_DIRTY;
3348            else if ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3349            else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
3350            else                                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3351            break;
3352        }
3353        ////////////////////////
3354        case XRAM_RSP_TRT_DIRTY:  // set the TRT entry (write to XRAM) if the victim is dirty
3355        {
3356            if ( r_alloc_trt_fsm.read() == ALLOC_TRT_XRAM_RSP )
3357            {
3358                m_transaction_tab.set( r_xram_rsp_trt_index.read(),
3359                                       false,       // write to XRAM
3360                                       r_xram_rsp_victim_nline.read(),  // line index
3361                                       0,
3362                                       0,
3363                                       0,
3364                                       false,
3365                                       0,
3366                                       0,
3367                                       std::vector<be_t>(m_words,0),
3368                                       std::vector<data_t>(m_words,0) );
3369
3370#if DEBUG_MEMC_XRAM_RSP
3371if( m_debug_xram_rsp_fsm )
3372{
3373    std::cout << "  <MEMC " << name() << ".XRAM_RSP_TRT_DIRTY> Set TRT entry for the put transaction:"
3374        << " dirty victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3375}
3376#endif
3377                if      ( r_xram_rsp_trt_buf.proc_read  )       r_xram_rsp_fsm = XRAM_RSP_DIR_RSP;
3378                else if ( r_xram_rsp_victim_inval.read())       r_xram_rsp_fsm = XRAM_RSP_INVAL;
3379                else                                            r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3380            }
3381            break;
3382        }
3383        //////////////////////
3384        case XRAM_RSP_DIR_RSP:     // Request a response to TGT_RSP FSM
3385        {
3386            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
3387            {
3388                r_xram_rsp_to_tgt_rsp_srcid = r_xram_rsp_trt_buf.srcid;
3389                r_xram_rsp_to_tgt_rsp_trdid = r_xram_rsp_trt_buf.trdid;
3390                r_xram_rsp_to_tgt_rsp_pktid = r_xram_rsp_trt_buf.pktid;
3391                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3392                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3393                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3394                r_xram_rsp_to_tgt_rsp_ll_key = r_xram_rsp_trt_buf.ll_key;
3395                r_xram_rsp_to_tgt_rsp_rerror = false;
3396                r_xram_rsp_to_tgt_rsp_req    = true;
3397
3398                if      ( r_xram_rsp_victim_inval ) r_xram_rsp_fsm = XRAM_RSP_INVAL;
3399                else if ( r_xram_rsp_victim_dirty ) r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3400                else                                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3401
3402
3403#if DEBUG_MEMC_XRAM_RSP
3404if( m_debug_xram_rsp_fsm )
3405{
3406    std::cout << "  <MEMC " << name() << ".XRAM_RSP_DIR_RSP> Request the TGT_RSP FSM to return data:"
3407              << " rsrcid = " << std::dec << r_xram_rsp_trt_buf.srcid
3408              << " / address = " << std::hex << r_xram_rsp_trt_buf.nline*m_words*4
3409              << " / nwords = " << std::dec << r_xram_rsp_trt_buf.read_length << std::endl;
3410}
3411#endif
3412            }
3413            break;
3414        }
3415        ////////////////////
3416        case XRAM_RSP_INVAL:  // send invalidate request to INIT_CMD FSM
3417        {
3418            if(   !r_xram_rsp_to_init_cmd_multi_req.read() &&
3419                  !r_xram_rsp_to_init_cmd_brdcast_req.read() )
3420            {
3421                bool multi_req = !r_xram_rsp_victim_is_cnt.read();
3422                bool last_multi_req  = multi_req && (r_xram_rsp_victim_count.read() == 1);
3423                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3424
3425                r_xram_rsp_to_init_cmd_multi_req    = last_multi_req;
3426                r_xram_rsp_to_init_cmd_brdcast_req  = r_xram_rsp_victim_is_cnt.read();
3427                r_xram_rsp_to_init_cmd_nline        = r_xram_rsp_victim_nline.read();
3428                r_xram_rsp_to_init_cmd_trdid        = r_xram_rsp_upt_index;
3429                xram_rsp_to_init_cmd_fifo_srcid     = r_xram_rsp_victim_copy.read();
3430                xram_rsp_to_init_cmd_fifo_inst      = r_xram_rsp_victim_copy_inst.read();
3431#if L1_MULTI_CACHE
3432                xram_rsp_to_init_cmd_fifo_cache_id  = r_xram_rsp_victim_copy_cache.read();
3433#endif
3434                xram_rsp_to_init_cmd_fifo_put       = multi_req;
3435                r_xram_rsp_next_ptr                 = r_xram_rsp_victim_ptr.read();
3436
3437                if ( r_xram_rsp_victim_dirty )  r_xram_rsp_fsm = XRAM_RSP_WRITE_DIRTY;
3438                else if (not_last_multi_req)    r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3439                else                            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3440
3441#if DEBUG_MEMC_XRAM_RSP
3442if( m_debug_xram_rsp_fsm )
3443{
3444    std::cout << "  <MEMC " << name() << ".XRAM_RSP_INVAL> Send an inval request to INIT_CMD FSM:"
3445              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3446}
3447#endif
3448          }
3449          break;
3450        }
3451        //////////////////////////
3452        case XRAM_RSP_WRITE_DIRTY:  // send a write request to IXR_CMD FSM
3453        {
3454            if ( !r_xram_rsp_to_ixr_cmd_req.read() )
3455            {
3456                r_xram_rsp_to_ixr_cmd_req = true;
3457                r_xram_rsp_to_ixr_cmd_nline = r_xram_rsp_victim_nline.read();
3458                r_xram_rsp_to_ixr_cmd_trdid = r_xram_rsp_trt_index.read();
3459                for(size_t i=0; i<m_words ; i++) r_xram_rsp_to_ixr_cmd_data[i] = r_xram_rsp_victim_data[i];
3460                m_cpt_write_dirty++;
3461
3462                bool multi_req = !r_xram_rsp_victim_is_cnt.read() && r_xram_rsp_victim_inval.read();
3463                bool not_last_multi_req = multi_req && (r_xram_rsp_victim_count.read() != 1);
3464                if ( not_last_multi_req )   r_xram_rsp_fsm = XRAM_RSP_HEAP_REQ;
3465                else                        r_xram_rsp_fsm = XRAM_RSP_IDLE;
3466
3467#if DEBUG_MEMC_XRAM_RSP
3468if( m_debug_xram_rsp_fsm )
3469{
3470    std::cout << "  <MEMC " << name() << ".XRAM_RSP_WRITE_DIRTY> Send the put request to IXR_CMD FSM:"
3471              << " victim line = " << r_xram_rsp_victim_nline.read() << std::endl;
3472}
3473#endif
3474            }
3475            break;
3476        }
3477
3478        /////////////////////////
3479        case XRAM_RSP_HEAP_REQ:
3480        // Get the lock to the HEAP directory
3481        {
3482          if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP )
3483          {
3484            r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3485          }
3486
3487#if DEBUG_MEMC_XRAM_RSP
3488          if( m_debug_xram_rsp_fsm )
3489          {
3490            std::cout
3491              << "  <MEMC " << name() << ".XRAM_RSP_HEAP_REQ> Requesting HEAP lock "
3492              << std::endl;
3493          }
3494#endif
3495          break;
3496        }
3497
3498        /////////////////////////
3499        case XRAM_RSP_HEAP_ERASE: // erase the list of copies and sent invalidations
3500        {
3501            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_XRAM_RSP )
3502            {
3503                HeapEntry entry = m_heap.read(r_xram_rsp_next_ptr.read());
3504
3505                xram_rsp_to_init_cmd_fifo_srcid    = entry.owner.srcid;
3506#if L1_MULTI_CACHE
3507                xram_rsp_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
3508#endif
3509                xram_rsp_to_init_cmd_fifo_inst  = entry.owner.inst;
3510                xram_rsp_to_init_cmd_fifo_put   = true;
3511                if( m_xram_rsp_to_init_cmd_inst_fifo.wok() )
3512                {
3513                    r_xram_rsp_next_ptr = entry.next;
3514                    if( entry.next == r_xram_rsp_next_ptr.read() ) // last copy
3515                    {
3516                        r_xram_rsp_to_init_cmd_multi_req = true;
3517                        r_xram_rsp_fsm = XRAM_RSP_HEAP_LAST;
3518                    }
3519                    else
3520                    {
3521                        r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3522                    }
3523                }
3524                else
3525                {
3526                    r_xram_rsp_fsm = XRAM_RSP_HEAP_ERASE;
3527                }
3528
3529#if DEBUG_MEMC_XRAM_RSP
3530if( m_debug_xram_rsp_fsm )
3531{
3532    std::cout << "  <MEMC " << name() << ".XRAM_RSP_HEAP_ERASE> Erase the list of copies:"
3533              << " srcid = " << std::dec << entry.owner.srcid
3534              << " / inst = " << std::dec << entry.owner.inst << std::endl;
3535}
3536#endif
3537            }
3538            break;
3539        }
3540        /////////////////////////
3541        case XRAM_RSP_HEAP_LAST:  // last member of the list
3542        {
3543            if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_XRAM_RSP )
3544            {
3545                std::cout << "VCI_MEM_CACHE ERROR " << name() << " XRAM_RSP_HEAP_LAST state" << std::endl;
3546                std::cout << "bad HEAP allocation" << std::endl;
3547                exit(0);
3548            }
3549            size_t free_pointer = m_heap.next_free_ptr();
3550
3551            HeapEntry last_entry;
3552            last_entry.owner.srcid    = 0;
3553#if L1_MULTI_CACHE
3554            last_entry.owner.cache_id = 0;
3555#endif
3556            last_entry.owner.inst     = false;
3557            if(m_heap.is_full())
3558            {
3559                last_entry.next     = r_xram_rsp_next_ptr.read();
3560                m_heap.unset_full();
3561            }
3562            else
3563            {
3564                last_entry.next     = free_pointer;
3565            }
3566
3567            m_heap.write_free_ptr(r_xram_rsp_victim_ptr.read());
3568            m_heap.write(r_xram_rsp_next_ptr.read(),last_entry);
3569
3570            r_xram_rsp_fsm = XRAM_RSP_IDLE;
3571
3572#if DEBUG_MEMC_XRAM_RSP
3573if( m_debug_xram_rsp_fsm )
3574{
3575    std::cout << "  <MEMC " << name() << ".XRAM_RSP_HEAP_LAST> Heap housekeeping" << std::endl;
3576}
3577#endif
3578            break;
3579        }
3580        // ///////////////////////
3581        case XRAM_RSP_ERROR_ERASE:  // erase TRT entry in case of error
3582        {
3583            m_transaction_tab.erase(r_xram_rsp_trt_index.read());
3584
3585            // Next state
3586            if ( r_xram_rsp_trt_buf.proc_read  ) r_xram_rsp_fsm = XRAM_RSP_ERROR_RSP;
3587            else                                 r_xram_rsp_fsm = XRAM_RSP_IDLE;
3588
3589#if DEBUG_MEMC_XRAM_RSP
3590if( m_debug_xram_rsp_fsm )
3591{
3592    std::cout << "  <MEMC " << name() << ".XRAM_RSP_ERROR_ERASE> Error reported by XRAM / erase the TRT entry" << std::endl;
3593}
3594#endif
3595            break;
3596        }
3597        ////////////////////////
3598        case XRAM_RSP_ERROR_RSP:     // Request an error response to TGT_RSP FSM
3599        {
3600            if ( !r_xram_rsp_to_tgt_rsp_req.read() )
3601            {
3602                r_xram_rsp_to_tgt_rsp_srcid  = r_xram_rsp_trt_buf.srcid;
3603                r_xram_rsp_to_tgt_rsp_trdid  = r_xram_rsp_trt_buf.trdid;
3604                r_xram_rsp_to_tgt_rsp_pktid  = r_xram_rsp_trt_buf.pktid;
3605                for (size_t i=0; i < m_words; i++) r_xram_rsp_to_tgt_rsp_data[i] = r_xram_rsp_trt_buf.wdata[i];
3606                r_xram_rsp_to_tgt_rsp_word   = r_xram_rsp_trt_buf.word_index;
3607                r_xram_rsp_to_tgt_rsp_length = r_xram_rsp_trt_buf.read_length;
3608                r_xram_rsp_to_tgt_rsp_rerror = true;
3609                r_xram_rsp_to_tgt_rsp_req    = true;
3610
3611                r_xram_rsp_fsm = XRAM_RSP_IDLE;
3612
3613#if DEBUG_MEMC_XRAM_RSP
3614if( m_debug_xram_rsp_fsm )
3615{
3616    std::cout << "  <MEMC " << name() << ".XRAM_RSP_ERROR_RSP> Request a response error to TGT_RSP FSM:"
3617              << " srcid = " << std::dec << r_xram_rsp_trt_buf.srcid << std::endl;
3618}
3619#endif
3620            }
3621            break;
3622        }
3623    } // end swich r_xram_rsp_fsm
3624
3625    ////////////////////////////////////////////////////////////////////////////////////
3626    //    CLEANUP FSM
3627    ////////////////////////////////////////////////////////////////////////////////////
3628    // The CLEANUP FSM handles the cleanup request from L1 caches.
3629    // It accesses the cache directory and the heap to update the list of copies.
3630    ////////////////////////////////////////////////////////////////////////////////////
3631
3632    switch ( r_cleanup_fsm.read() )
3633    {
3634      //////////////////
3635      case CLEANUP_IDLE:
3636      {
3637        if ( p_vci_tgt_cleanup.cmdval.read() )
3638        {
3639          if (p_vci_tgt_cleanup.srcid.read() >= m_initiators )
3640          {
3641            std::cout << "VCI_MEM_CACHE ERROR " << name()
3642              << " CLEANUP_IDLE state" << std::endl;
3643            std::cout << "illegal srcid for  cleanup request" << std::endl;
3644            exit(0);
3645          }
3646
3647          bool reached = false;
3648          for ( size_t index = 0 ; index < m_ncseg && !reached ; index++ )
3649          {
3650            if ( m_cseg[index]->contains((addr_t)(p_vci_tgt_cleanup.address.read())) )
3651              reached = true;
3652          }
3653          // only write request to a mapped address that are not broadcast are handled
3654          if (( p_vci_tgt_cleanup.cmd.read() == vci_param::CMD_WRITE ) &&
3655              (( p_vci_tgt_cleanup.address.read() & 0x3 ) == 0 ) && reached )
3656          {
3657            addr_t line =(((addr_t) p_vci_tgt_cleanup.be.read() << (vci_param::B*8))) |
3658              (((addr_t) p_vci_tgt_cleanup.wdata.read()));
3659
3660            r_cleanup_nline = line;
3661            r_cleanup_srcid = p_vci_tgt_cleanup.srcid.read();
3662            r_cleanup_trdid = p_vci_tgt_cleanup.trdid.read();
3663            r_cleanup_pktid = p_vci_tgt_cleanup.pktid.read();
3664            r_cleanup_fsm   = CLEANUP_DIR_REQ;
3665
3666  #if DEBUG_MEMC_CLEANUP
3667            if( m_debug_cleanup_fsm )
3668            {
3669              std::cout << "  <MEMC " << name() << ".CLEANUP_IDLE> Cleanup request:" << std::hex
3670                << " line addr = " << line * m_words * 4
3671                << " / owner_id = " << p_vci_tgt_cleanup.srcid.read()
3672                << " / owner_ins = " << (p_vci_tgt_cleanup.trdid.read()&0x1)
3673                << std::endl;
3674            }
3675  #endif
3676            m_cpt_cleanup++;
3677          }
3678        }
3679        break;
3680      }
3681
3682      //////////////////////
3683      case CLEANUP_DIR_REQ:
3684      // Get the lock to the directory
3685      {
3686        if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP )
3687        {
3688          r_cleanup_fsm = CLEANUP_DIR_LOCK;
3689        }
3690
3691#if DEBUG_MEMC_CLEANUP
3692        if( m_debug_cleanup_fsm )
3693        {
3694          std::cout
3695            << "  <MEMC " << name() << ".CLEANUP_DIR_REQ> Requesting DIR lock "
3696            << std::endl;
3697        }
3698#endif
3699        break;
3700      }
3701
3702      //////////////////////
3703      case CLEANUP_DIR_LOCK:  // test directory status
3704      {
3705        if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CLEANUP )
3706        {
3707          // Read the directory
3708          size_t way = 0;
3709          addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
3710          DirectoryEntry entry   = m_cache_directory.read(cleanup_address , way);
3711          r_cleanup_is_cnt       = entry.is_cnt;
3712          r_cleanup_dirty        = entry.dirty;
3713          r_cleanup_tag          = entry.tag;
3714          r_cleanup_lock         = entry.lock;
3715          r_cleanup_way          = way;
3716          r_cleanup_copy         = entry.owner.srcid;
3717#if L1_MULTI_CACHE
3718          r_cleanup_copy_cache   = entry.owner.cache_id;
3719#endif
3720          r_cleanup_copy_inst    = entry.owner.inst;
3721          r_cleanup_count        = entry.count;
3722          r_cleanup_ptr          = entry.ptr;
3723
3724          if( entry.valid) //  hit : the copy must be cleared
3725          {
3726            assert( (entry.count > 0) &&
3727                    "CLEANUP command received with no copy in the directory");
3728
3729            if ( (entry.count==1) || (entry.is_cnt) )  // no access to the heap
3730            {
3731              r_cleanup_fsm = CLEANUP_DIR_WRITE;
3732            }
3733            else          // access to the heap
3734            {
3735              r_cleanup_fsm = CLEANUP_HEAP_REQ;
3736            }
3737          }
3738          else    // miss : we must check the update table
3739          {
3740            r_cleanup_fsm = CLEANUP_UPT_LOCK;
3741          }
3742
3743#if DEBUG_MEMC_CLEANUP
3744          if( m_debug_cleanup_fsm )
3745          {
3746            std::cout
3747              << "  <MEMC " << name()
3748              << ".CLEANUP_DIR_LOCK> Test directory status: " << std::hex
3749              << " line = " << r_cleanup_nline.read() * m_words * 4
3750              << " / hit = " << entry.valid
3751              << " / dir_id = " << entry.owner.srcid
3752              << " / dir_ins = " << entry.owner.inst
3753              << " / search_id = " << r_cleanup_srcid.read()
3754              << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
3755              << " / count = " << entry.count
3756              << " / is_cnt = " << entry.is_cnt << std::endl;
3757          }
3758#endif
3759        }
3760        else
3761        {
3762          std::cout << "VCI_MEM_CACHE ERROR " << name()
3763            << " CLEANUP_DIR_LOCK state"
3764            << " bad DIR allocation" << std::endl;
3765
3766          exit(0);
3767        }
3768        break;
3769      }
3770
3771      ///////////////////////
3772      case CLEANUP_DIR_WRITE:
3773      // Update the directory entry without heap access
3774      {
3775        if ( r_alloc_dir_fsm.read() != ALLOC_DIR_CLEANUP )
3776        {
3777          std::cout << "VCI_MEM_CACHE ERROR " << name()
3778            << " CLEANUP_DIR_WRITE state"
3779            << " bad DIR allocation" << std::endl;
3780          exit(0);
3781        }
3782
3783        size_t way         = r_cleanup_way.read();
3784        size_t set         = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3785        bool cleanup_inst  = r_cleanup_trdid.read() & 0x1;
3786        bool match_srcid   = ((r_cleanup_copy.read() == r_cleanup_srcid.read())
3787#if L1_MULTI_CACHE
3788            and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read())
3789#endif
3790            );
3791        bool match_inst    = (r_cleanup_copy_inst.read()  == cleanup_inst);
3792        bool match         = match_srcid && match_inst;
3793
3794        if (not r_cleanup_is_cnt.read() and not match) {
3795            std::cout
3796              << "VCI_MEM_CACHE ERROR : Cleanup request on a valid "
3797              << "entry using linked list mode with no corresponding "
3798              << "directory or heap entry"
3799              << std::endl;
3800
3801            exit(1);
3802        }
3803
3804        // update the cache directory (for the copies)
3805        DirectoryEntry entry;
3806        entry.valid       = true;
3807        entry.is_cnt      = r_cleanup_is_cnt.read();
3808        entry.dirty       = r_cleanup_dirty.read();
3809        entry.tag         = r_cleanup_tag.read();
3810        entry.lock        = r_cleanup_lock.read();
3811        entry.ptr         = r_cleanup_ptr.read();
3812        entry.count       = r_cleanup_count.read() - 1;
3813        entry.owner.srcid = 0;
3814        entry.owner.inst  = 0;
3815#if L1_MULTI_CACHE
3816        entry.owner.cache_id = 0;
3817#endif
3818
3819        m_cache_directory.write(set, way, entry);
3820
3821        r_cleanup_fsm = CLEANUP_RSP;
3822
3823#if DEBUG_MEMC_CLEANUP
3824        if( m_debug_cleanup_fsm )
3825        {
3826          std::cout
3827            << "  <MEMC " << name()
3828            << ".CLEANUP_DIR_WRITE> Update directory:" << std::hex
3829            << " line = " << r_cleanup_nline.read() * m_words * 4
3830            << " / dir_id = " << entry.owner.srcid
3831            << " / dir_ins = " << entry.owner.inst
3832            << " / count = " << entry.count
3833            << " / is_cnt = " << entry.is_cnt << std::endl;
3834        }
3835#endif
3836
3837        break;
3838      }
3839     
3840      ///////////////////////
3841      case CLEANUP_HEAP_REQ:
3842      // Get the lock to the HEAP directory
3843      {
3844        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3845        {
3846          r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3847        }
3848
3849#if DEBUG_MEMC_CLEANUP
3850        if( m_debug_cleanup_fsm )
3851        {
3852          std::cout
3853            << "  <MEMC " << name() << ".CLEANUP_HEAP_REQ> Requesting HEAP lock "
3854            << std::endl;
3855        }
3856#endif
3857        break;
3858      }
3859
3860      ///////////////////////
3861      case CLEANUP_HEAP_LOCK:
3862      // two cases are handled in this state:
3863      // - the matching copy is directly in the directory
3864      // - the matching copy is the first copy in the heap
3865      {
3866        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3867        {
3868          size_t way              = r_cleanup_way.read();
3869          size_t set              = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3870          HeapEntry heap_entry    = m_heap.read(r_cleanup_ptr.read());
3871          bool last               = (heap_entry.next == r_cleanup_ptr.read());
3872          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1;
3873
3874          // match_dir computation
3875          bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3876          bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
3877          bool match_dir          = match_dir_srcid and match_dir_inst;
3878#if L1_MULTI_CACHE
3879          match_dir = match_dir and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3880#endif
3881
3882          // match_heap computation
3883          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3884          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
3885          bool match_heap         = match_heap_srcid and match_heap_inst;
3886#if L1_MULTI_CACHE
3887          match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3888#endif
3889
3890          r_cleanup_prev_ptr      = r_cleanup_ptr.read();
3891          r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3892#if L1_MULTI_CACHE
3893          r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3894#endif
3895          r_cleanup_prev_inst     = heap_entry.owner.inst;
3896
3897          if (match_dir)
3898          // the matching copy is registered in the directory
3899          {
3900            // the copy registered in the directory must be replaced
3901            // by the first copy registered in the heap
3902            // and the corresponding entry must be freed
3903            DirectoryEntry dir_entry;
3904            dir_entry.valid          = true;
3905            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3906            dir_entry.dirty          = r_cleanup_dirty.read();
3907            dir_entry.tag            = r_cleanup_tag.read();
3908            dir_entry.lock           = r_cleanup_lock.read();
3909            dir_entry.ptr            = heap_entry.next;
3910            dir_entry.count          = r_cleanup_count.read()-1;
3911            dir_entry.owner.srcid    = heap_entry.owner.srcid;
3912#if L1_MULTI_CACHE
3913            dir_entry.owner.cache_id = heap_entry.owner.cache_id;
3914#endif
3915            dir_entry.owner.inst     = heap_entry.owner.inst;
3916
3917            m_cache_directory.write(set,way,dir_entry);
3918
3919            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3920            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3921          }
3922          else if (match_heap)
3923          // the matching copy is the first copy in the heap
3924          {
3925            // The first copy in heap must be freed
3926            // and the copy registered in directory must point to the next copy in heap
3927            DirectoryEntry dir_entry;
3928            dir_entry.valid          = true;
3929            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3930            dir_entry.dirty          = r_cleanup_dirty.read();
3931            dir_entry.tag            = r_cleanup_tag.read();
3932            dir_entry.lock           = r_cleanup_lock.read();
3933            dir_entry.ptr            = heap_entry.next;
3934            dir_entry.count          = r_cleanup_count.read()-1;
3935            dir_entry.owner.srcid    = r_cleanup_copy.read();
3936#if L1_MULTI_CACHE
3937            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3938#endif
3939            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3940
3941            m_cache_directory.write(set,way,dir_entry);
3942
3943            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3944            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3945          }
3946          else if(!last)
3947          // The matching copy is in the heap, but is not the first copy
3948          {
3949            // The directory entry must be modified to decrement count
3950            DirectoryEntry  dir_entry;
3951            dir_entry.valid          = true;
3952            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3953            dir_entry.dirty          = r_cleanup_dirty.read();
3954            dir_entry.tag            = r_cleanup_tag.read();
3955            dir_entry.lock           = r_cleanup_lock.read();
3956            dir_entry.ptr            = r_cleanup_ptr.read();
3957            dir_entry.count          = r_cleanup_count.read()-1;
3958            dir_entry.owner.srcid    = r_cleanup_copy.read();
3959#if L1_MULTI_CACHE
3960            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3961#endif
3962            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3963
3964            m_cache_directory.write(set,way,dir_entry);
3965
3966            r_cleanup_next_ptr       = heap_entry.next;
3967            r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
3968          }
3969          else
3970          {
3971            std::cout << "VCI_MEM_CACHE ERROR " << name()
3972              << " CLEANUP_HEAP_LOCK state"
3973              << " hit but copy not found" << std::endl;
3974            exit(0);
3975          }
3976
3977#if DEBUG_MEMC_CLEANUP
3978          if( m_debug_cleanup_fsm )
3979          {
3980            std::cout
3981              << "  <MEMC " << name() << ".CLEANUP_HEAP_LOCK> Checks matching:"
3982              << " line = " << r_cleanup_nline.read() * m_words * 4
3983              << " / dir_id = " << r_cleanup_copy.read()
3984              << " / dir_ins = " << r_cleanup_copy_inst.read()
3985              << " / heap_id = " << heap_entry.owner.srcid
3986              << " / heap_ins = " << heap_entry.owner.inst
3987              << " / search_id = " << r_cleanup_srcid.read()
3988              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3989          }
3990#endif
3991        }
3992        else
3993        {
3994          std::cout << "VCI_MEM_CACHE ERROR " << name()
3995            << " CLEANUP_HEAP_LOCK state"
3996            << " bad HEAP allocation" << std::endl;
3997
3998          exit(0);
3999        }
4000        break;
4001      }
4002
4003      /////////////////////////
4004      case CLEANUP_HEAP_SEARCH:  // This state is handling the case where the copy
4005      // is in the heap, but is not the first in the linked list
4006      {
4007        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4008        {
4009          std::cout << "VCI_MEM_CACHE ERROR " << name()
4010            << " CLEANUP_HEAP_SEARCH state"
4011            << " bad HEAP allocation" << std::endl;
4012          exit(0);
4013        }
4014
4015        HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
4016        bool last             = (heap_entry.next == r_cleanup_next_ptr.read());
4017        bool cleanup_inst     = r_cleanup_trdid.read() & 0x1;
4018        bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
4019        bool match_heap_inst  = (heap_entry.owner.inst  == cleanup_inst);
4020        bool match_heap       = match_heap_srcid && match_heap_inst;
4021#if L1_MULTI_CACHE
4022        match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
4023#endif
4024
4025#if DEBUG_MEMC_CLEANUP
4026        if( m_debug_cleanup_fsm )
4027        {
4028          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Cheks matching:"
4029            << " line = " << r_cleanup_nline.read() * m_words * 4
4030            << " / heap_id = " << heap_entry.owner.srcid
4031            << " / heap_ins = " << heap_entry.owner.inst
4032            << " / search_id = " << r_cleanup_srcid.read()
4033            << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
4034            << " / last = " << last << std::endl;
4035        }
4036#endif
4037        if(match_heap) // the matching copy must be removed
4038        {
4039          r_cleanup_ptr = heap_entry.next; // reuse ressources
4040          r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
4041        }
4042        else
4043        {
4044          if ( last )
4045          {
4046            std::cout << "VCI_MEM_CACHE_ERROR " << name()
4047              << " CLEANUP_HEAP_SEARCH state"
4048              << " cleanup hit but copy not found" << std::endl;
4049            exit(0);
4050          }
4051          else // test the next in the linked list
4052          {
4053            r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
4054            r_cleanup_prev_srcid    = heap_entry.owner.srcid;
4055#if L1_MULTI_CACHE
4056            r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
4057#endif
4058            r_cleanup_prev_inst     = heap_entry.owner.inst;
4059            r_cleanup_next_ptr      = heap_entry.next;
4060            r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
4061
4062#if DEBUG_MEMC_CLEANUP
4063            if( m_debug_cleanup_fsm )
4064            {
4065              std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
4066                << " line = " << r_cleanup_nline.read() * m_words * 4
4067                << " / heap_id = " << heap_entry.owner.srcid
4068                << " / heap_ins = " << heap_entry.owner.inst
4069                << " / search_id = " << r_cleanup_srcid.read()
4070                << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
4071            }
4072#endif
4073          }
4074        }
4075        break;
4076      }
4077
4078      ////////////////////////
4079      case CLEANUP_HEAP_CLEAN:  // remove a copy in the linked list
4080      {
4081        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4082        {
4083          std::cout << "VCI_MEM_CACHE ERROR " << name()
4084            << " CLEANUP_HEAP_CLEAN state"
4085            << "Bad HEAP allocation" << std::endl;
4086          exit(0);
4087        }
4088
4089        bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
4090        HeapEntry heap_entry;
4091        heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4092#if L1_MULTI_CACHE
4093        heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4094#endif
4095        heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4096       
4097        if(last) // this is the last entry of the list of copies
4098        {
4099          heap_entry.next     = r_cleanup_prev_ptr.read();
4100        }
4101        else  // this is not the last entry
4102        {
4103          heap_entry.next     = r_cleanup_ptr.read();
4104        }
4105
4106        m_heap.write(r_cleanup_prev_ptr.read(),heap_entry);
4107        r_cleanup_fsm = CLEANUP_HEAP_FREE;
4108
4109#if DEBUG_MEMC_CLEANUP
4110        if( m_debug_cleanup_fsm )
4111        {
4112          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Remove the copy in the linked list" << std::endl;
4113        }
4114#endif
4115        break;
4116      }
4117
4118      ///////////////////////
4119      case CLEANUP_HEAP_FREE:
4120      // The heap entry pointed by r_cleanup_next_ptr is freed
4121      // and becomes the head of the list of free entries
4122      {
4123        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4124        {
4125          std::cout
4126            << "VCI_MEM_CACHE ERROR " << name()
4127            << " CLEANUP_HEAP_CLEAN state" << std::endl
4128            << "Bad HEAP allocation" << std::endl;
4129
4130          exit(0);
4131        }
4132
4133        HeapEntry heap_entry;
4134        heap_entry.owner.srcid    = 0;
4135#if L1_MULTI_CACHE
4136        heap_entry.owner.cache_id = 0;
4137#endif
4138        heap_entry.owner.inst     = false;
4139
4140        if(m_heap.is_full())
4141        {
4142          heap_entry.next = r_cleanup_next_ptr.read();
4143        }
4144        else
4145        {
4146          heap_entry.next = m_heap.next_free_ptr();
4147        }
4148
4149        m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4150        m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4151        m_heap.unset_full();
4152
4153        r_cleanup_fsm = CLEANUP_RSP;
4154
4155#if DEBUG_MEMC_CLEANUP
4156        if( m_debug_cleanup_fsm )
4157        {
4158          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Update the list of free entries" << std::endl;
4159        }
4160#endif
4161        break;
4162      }
4163
4164      //////////////////////
4165      case CLEANUP_UPT_LOCK:
4166      {
4167        if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
4168        {
4169          size_t index = 0;
4170          bool hit_inval;
4171          hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
4172
4173          if ( !hit_inval ) // no pending inval
4174          {
4175
4176#if DEBUG_MEMC_CLEANUP
4177            if( m_debug_cleanup_fsm )
4178            {
4179              std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_LOCK> Unexpected cleanup with no corresponding UPT entry:"
4180                << " address = " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::endl;
4181            }
4182#endif
4183            r_cleanup_fsm = CLEANUP_RSP;
4184          }
4185          else    // pending inval
4186          {
4187            r_cleanup_write_srcid = m_update_tab.srcid(index);
4188            r_cleanup_write_trdid = m_update_tab.trdid(index);
4189            r_cleanup_write_pktid = m_update_tab.pktid(index);
4190            r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
4191            r_cleanup_fsm = CLEANUP_UPT_WRITE;
4192          }
4193          r_cleanup_index.write(index) ;
4194        }
4195        break;
4196      }
4197
4198      ///////////////////////
4199      case CLEANUP_UPT_WRITE:  // decrement response counter
4200      {
4201        size_t count = 0;
4202        m_update_tab.decrement(r_cleanup_index.read(), count);
4203        if ( count == 0 )
4204        {
4205          m_update_tab.clear(r_cleanup_index.read());
4206
4207#if DEBUG_MEMC_CLEANUP
4208          if( m_debug_cleanup_fsm )
4209          {
4210            std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_WRITE> Decrement response counter in UPT:"
4211              << " UPT_index = " << r_cleanup_index.read()
4212              << " rsp_count = " << count << std::endl;
4213          }
4214#endif
4215          if( r_cleanup_need_rsp.read() ) r_cleanup_fsm = CLEANUP_WRITE_RSP ;
4216          else                      r_cleanup_fsm = CLEANUP_RSP;
4217        }
4218        else
4219        {
4220          r_cleanup_fsm = CLEANUP_RSP ;
4221        }
4222        break;
4223      }
4224
4225      ///////////////////////
4226      case CLEANUP_WRITE_RSP: // Response to a previous write on the direct network
4227      {
4228        if( !r_cleanup_to_tgt_rsp_req.read() )
4229        {
4230          r_cleanup_to_tgt_rsp_req     = true;
4231          r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4232          r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4233          r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4234          r_cleanup_fsm                = CLEANUP_RSP;
4235
4236#if DEBUG_MEMC_CLEANUP
4237          if( m_debug_cleanup_fsm )
4238          {
4239            std::cout << "  <MEMC " << name() << ".CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
4240              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4241              << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read() << std::endl;
4242          }
4243#endif
4244        }
4245        break;
4246      }
4247
4248      /////////////////
4249      case CLEANUP_RSP: // Response to a cleanup on the coherence network
4250      {
4251        if ( p_vci_tgt_cleanup.rspack.read() )
4252        {
4253          r_cleanup_fsm = CLEANUP_IDLE;
4254
4255#if DEBUG_MEMC_CLEANUP
4256          if( m_debug_cleanup_fsm )
4257          {
4258            std::cout << "  <MEMC " << name() << ".CLEANUP_RSP> Send the response to a cleanup request:"
4259              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4260              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
4261          }
4262#endif
4263        }
4264        break;
4265      }
4266    } // end switch cleanup fsm
4267
4268    ////////////////////////////////////////////////////////////////////////////////////
4269    //    CAS FSM
4270    ////////////////////////////////////////////////////////////////////////////////////
4271    // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4272    // that are handled as "compare-and-swap instructions.
4273    //
4274    // This command contains two or four flits:
4275    // - In case of 32 bits atomic access, the first flit contains the value read
4276    // by a previous LL instruction, the second flit contains the value to be writen.
4277    // - In case of 64 bits atomic access, the 2 first flits contains the value read
4278    // by a previous LL instruction, the 2 next flits contains the value to be writen.
4279    //
4280    // The target address is cachable. If it is replicated in other L1 caches
4281    // than the writer, a coherence operation is done.
4282    //
4283    // It access the directory to check hit / miss.
4284    // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4285    // If a read transaction to the XRAM for this line already exists,
4286    // or if the transaction table is full, it goes to the WAIT state
4287    // to release the locks and try again. When the GET transaction has been
4288    // launched, it goes to the WAIT state and try again.
4289    // The CAS request is not consumed in the FIFO until a HIT is obtained.
4290    // - In case of hit...
4291    ///////////////////////////////////////////////////////////////////////////////////
4292
4293    switch ( r_cas_fsm.read() )
4294    {
4295        /////////////
4296        case CAS_IDLE:     // fill the local rdata buffers
4297        {
4298            if( m_cmd_cas_addr_fifo.rok() )
4299            {
4300
4301#if DEBUG_MEMC_CAS
4302if( m_debug_cas_fsm )
4303{
4304    std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
4305              << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4306              << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4307              << " wdata = " << m_cmd_cas_wdata_fifo.read()
4308              << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4309              << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4310}
4311#endif
4312                if( m_cmd_cas_eop_fifo.read() )
4313                {
4314                    m_cpt_cas++;
4315                    r_cas_fsm = CAS_DIR_REQ;
4316                }
4317                else  // we keep the last word in the FIFO
4318                {
4319                    cmd_cas_fifo_get = true;
4320                }
4321                // We fill the two buffers
4322                if ( r_cas_cpt.read() < 2 ) // 32 bits access
4323                    r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4324
4325                if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4326                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4327
4328                if( r_cas_cpt.read()>3 ) // more than 4 flits...
4329                {
4330                    std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4331                              << std::endl;
4332                    exit(0);
4333                }
4334
4335                if ( r_cas_cpt.read()==2 )
4336                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4337
4338                r_cas_cpt = r_cas_cpt.read()+1;
4339            }
4340            break;
4341        }
4342       
4343        /////////////////
4344        case CAS_DIR_REQ:
4345        {
4346            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4347            {
4348                r_cas_fsm = CAS_DIR_LOCK;
4349            }
4350
4351#if DEBUG_MEMC_CAS
4352            if( m_debug_cas_fsm )
4353            {
4354                std::cout
4355                    << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
4356                    << std::endl;
4357            }
4358#endif
4359            break;
4360        }
4361
4362        /////////////////
4363        case CAS_DIR_LOCK:  // Read the directory
4364        {
4365            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4366            {
4367                size_t way = 0;
4368                DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4369
4370                r_cas_is_cnt     = entry.is_cnt;
4371                r_cas_dirty      = entry.dirty;
4372                r_cas_tag        = entry.tag;
4373                r_cas_way        = way;
4374                r_cas_copy       = entry.owner.srcid;
4375#if L1_MULTI_CACHE
4376                r_cas_copy_cache = entry.owner.cache_id;
4377#endif
4378                r_cas_copy_inst  = entry.owner.inst;
4379                r_cas_ptr        = entry.ptr;
4380                r_cas_count      = entry.count;
4381
4382                if ( entry.valid )  r_cas_fsm = CAS_DIR_HIT_READ;
4383                else                r_cas_fsm = CAS_MISS_TRT_LOCK;
4384
4385#if DEBUG_MEMC_CAS
4386if( m_debug_cas_fsm )
4387{
4388    std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
4389              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4390              << " / hit = " << std::dec << entry.valid
4391              << " / count = " << entry.count
4392              << " / is_cnt = " << entry.is_cnt << std::endl;
4393}
4394#endif
4395            }
4396            else
4397            {
4398                std::cout
4399                    << "VCI_MEM_CACHE ERROR " << name()
4400                    << " CAS_DIR_LOCK state" << std::endl
4401                    << "Bad DIR allocation"   << std::endl;
4402
4403                exit(0);
4404            }
4405
4406            break;
4407        }
4408
4409        /////////////////////
4410        case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4411                                // and check data change in cache
4412        {
4413            size_t way  = r_cas_way.read();
4414            size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4415
4416            // update directory (lock & dirty bits)
4417            DirectoryEntry entry;
4418            entry.valid          = true;
4419            entry.is_cnt         = r_cas_is_cnt.read();
4420            entry.dirty          = true;
4421            entry.lock           = true;
4422            entry.tag            = r_cas_tag.read();
4423            entry.owner.srcid    = r_cas_copy.read();
4424#if L1_MULTI_CACHE
4425            entry.owner.cache_id = r_cas_copy_cache.read();
4426#endif
4427            entry.owner.inst     = r_cas_copy_inst.read();
4428            entry.count          = r_cas_count.read();
4429            entry.ptr            = r_cas_ptr.read();
4430
4431            m_cache_directory.write(set, way, entry);
4432
4433            // Stored data from cache in buffer to do the comparison in next state
4434            m_cache_data.read_line(way, set, r_cas_data);
4435
4436            r_cas_fsm = CAS_DIR_HIT_COMPARE;
4437
4438#if DEBUG_MEMC_CAS
4439            if(m_debug_cas_fsm)
4440            {
4441                std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Read data from "
4442                    << " cache and store it in buffer"
4443                    << std::endl;
4444            }
4445#endif
4446            break;
4447        }
4448
4449        case CAS_DIR_HIT_COMPARE:
4450        {
4451            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4452
4453            // Read data in buffer & check data change
4454            bool ok = (r_cas_rdata[0].read() == r_cas_data[word].read());
4455
4456            if(r_cas_cpt.read() == 4)     // 64 bits CAS
4457                ok &= (r_cas_rdata[1] == r_cas_data[word+1]);
4458
4459            // to avoid livelock, force the atomic access to fail pseudo-randomly
4460            bool forced_fail = ((r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS);
4461            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((- (r_cas_lfsr & 1)) & 0xd0000001);
4462
4463            // cas success
4464            if(ok and not forced_fail)
4465            {
4466                r_cas_fsm = CAS_DIR_HIT_WRITE;
4467            }
4468            // cas failure
4469            else
4470            {
4471                r_cas_fsm = CAS_RSP_FAIL;
4472            }
4473
4474#if DEBUG_MEMC_CAS
4475            if(m_debug_cas_fsm)
4476            {
4477                std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_COMPARE> Compare the old"
4478                    << " and the new data"
4479                    << " / expected value = " << r_cas_rdata[0].read()
4480                    << " / actual value = "   << r_cas_data[word].read()
4481                    << " / forced_fail = "    << forced_fail << std::endl;
4482            }
4483#endif
4484            break;
4485        }
4486
4487        //////////////////////
4488        case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4489                                   // write data in cache if no CC request
4490        {
4491            // The CAS is a success => sw access to the llsc_global_table
4492            m_llsc_table.sw(m_cmd_cas_addr_fifo.read());
4493
4494            // test coherence request
4495            if(r_cas_count.read())   // replicated line
4496            {
4497                if ( r_cas_is_cnt.read() )
4498                {
4499                    r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4500                }
4501                else if( !r_cas_to_init_cmd_multi_req.read() &&
4502                         !r_cas_to_init_cmd_brdcast_req.read()  )
4503                {
4504                    r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4505                }
4506                else
4507                {
4508                    r_cas_fsm = CAS_WAIT;
4509                }
4510            }
4511            else                    // no copies
4512            {
4513                size_t way  = r_cas_way.read();
4514                size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4515                size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4516
4517                // cache update
4518                m_cache_data.write(way, set, word, r_cas_wdata.read());
4519                if(r_cas_cpt.read()==4)
4520                    m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4521
4522                r_cas_fsm = CAS_RSP_SUCCESS;
4523
4524                // monitor
4525                if ( m_monitor_ok )
4526                {
4527                    vci_addr_t address = m_cmd_cas_addr_fifo.read();
4528
4529                    char buf[80];
4530                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d",
4531                             m_cmd_cas_srcid_fifo.read());
4532
4533                    check_monitor( buf, address, r_cas_wdata.read() );
4534                    if ( r_cas_cpt.read()==4 )
4535                    check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4536                }
4537
4538#if DEBUG_MEMC_CAS
4539if( m_debug_cas_fsm )
4540{
4541    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
4542              << " way = " << std::dec << way
4543              << " / set = " << set
4544              << " / word = " << word
4545              << " / value = " << r_cas_wdata.read()
4546              << " / count = " << r_cas_count.read() << std::endl;
4547    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> global_llsc_table SW access" << std::endl;
4548}
4549#endif
4550            }
4551            break;
4552        }
4553        /////////////////
4554        case CAS_UPT_LOCK:  // try to register the transaction in UPT
4555                           // and write data in cache if successful registration
4556                           // releases locks to retry later if UPT full
4557        {
4558            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4559            {
4560                bool        wok        = false;
4561                size_t      index      = 0;
4562                size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4563                size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4564                size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4565                addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4566                size_t      nb_copies  = r_cas_count.read();
4567
4568                wok = m_update_tab.set(true,  // it's an update transaction
4569                                       false,   // it's not a broadcast
4570                                       true,    // it needs a response
4571                                       srcid,
4572                                       trdid,
4573                                       pktid,
4574                                       nline,
4575                                       nb_copies,
4576                                       index);
4577                if (wok)  // coherence transaction registered in UPT
4578                {
4579                    // cache update
4580                    size_t way  = r_cas_way.read();
4581                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4582                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4583
4584                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4585                    if(r_cas_cpt.read()==4)
4586                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4587
4588                    // monitor
4589                    if ( m_monitor_ok )
4590                    {
4591                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4592                    char buf[80];
4593                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4594                        check_monitor( buf, address, r_cas_wdata.read() );
4595                        if ( r_cas_cpt.read()==4 )
4596                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4597                    }
4598
4599                    r_cas_upt_index = index;
4600                    r_cas_fsm = CAS_UPT_HEAP_LOCK;
4601                }
4602                else       //  releases the locks protecting UPT and DIR UPT full
4603                {
4604                    r_cas_fsm = CAS_WAIT;
4605                }
4606
4607#if DEBUG_MEMC_CAS
4608if( m_debug_cas_fsm )
4609{
4610    std::cout << "  <MEMC " << name() << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
4611              << " / wok = " << wok
4612              << " / nline  = " << std::hex << nline
4613              << " / count = " << nb_copies << std::endl;
4614}
4615#endif
4616            }
4617            break;
4618        }
4619        /////////////
4620        case CAS_WAIT:   // release all locks and retry from beginning
4621        {
4622
4623#if DEBUG_MEMC_CAS
4624if( m_debug_cas_fsm )
4625{
4626    std::cout << "  <MEMC " << name() << ".CAS_WAIT> Release all locks" << std::endl;
4627}
4628#endif
4629            r_cas_fsm = CAS_DIR_REQ;
4630            break;
4631        }
4632        //////////////////
4633        case CAS_UPT_HEAP_LOCK:  // lock the heap
4634        {
4635            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS )
4636            {
4637
4638#if DEBUG_MEMC_CAS
4639if( m_debug_cas_fsm )
4640{
4641    std::cout << "  <MEMC " << name() << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4642}
4643#endif
4644                r_cas_fsm = CAS_UPT_REQ;
4645            }
4646            break;
4647        }
4648        ////////////////
4649        case CAS_UPT_REQ:  // send a first update request to INIT_CMD FSM
4650        {
4651            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4652                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4653
4654            if( !r_cas_to_init_cmd_multi_req.read() && !r_cas_to_init_cmd_brdcast_req.read() )
4655            {
4656                r_cas_to_init_cmd_brdcast_req  = false;
4657                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4658                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4659                r_cas_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4660                r_cas_to_init_cmd_wdata        = r_cas_wdata.read();
4661
4662                if(r_cas_cpt.read() == 4)
4663                {
4664                    r_cas_to_init_cmd_is_long    = true;
4665                    r_cas_to_init_cmd_wdata_high = m_cmd_cas_wdata_fifo.read();
4666                }
4667                else
4668                {
4669                    r_cas_to_init_cmd_is_long    = false;
4670                    r_cas_to_init_cmd_wdata_high = 0;
4671                }
4672
4673                // We put the first copy in the fifo
4674                cas_to_init_cmd_fifo_put     = true;
4675                cas_to_init_cmd_fifo_inst    = r_cas_copy_inst.read();
4676                cas_to_init_cmd_fifo_srcid   = r_cas_copy.read();
4677#if L1_MULTI_CACHE
4678                cas_to_init_cmd_fifo_cache_id= r_cas_copy_cache.read();
4679#endif
4680                if(r_cas_count.read() == 1) // one single copy
4681                {
4682                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4683                                            // update responses
4684                    cmd_cas_fifo_get            = true;
4685                    r_cas_to_init_cmd_multi_req = true;
4686                    r_cas_cpt = 0;
4687                }
4688                else      // several copies
4689                {
4690                    r_cas_fsm = CAS_UPT_NEXT;
4691                }
4692
4693#if DEBUG_MEMC_CAS
4694if( m_debug_cas_fsm )
4695{
4696    std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to INIT_CMD FSM "
4697              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4698              << " / wdata = " << std::hex << r_cas_wdata.read()
4699              << " / srcid = " << std::dec << r_cas_copy.read()
4700              << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
4701}
4702#endif
4703            }
4704            break;
4705        }
4706        /////////////////
4707        case CAS_UPT_NEXT:     // send a multi-update request to INIT_CMD FSM
4708        {
4709            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4710                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4711
4712            HeapEntry entry = m_heap.read(r_cas_ptr.read());
4713            cas_to_init_cmd_fifo_srcid    = entry.owner.srcid;
4714#if L1_MULTI_CACHE
4715            cas_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
4716#endif
4717            cas_to_init_cmd_fifo_inst     = entry.owner.inst;
4718            cas_to_init_cmd_fifo_put = true;
4719
4720            if( m_cas_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
4721            {
4722                r_cas_ptr = entry.next;
4723                if( entry.next == r_cas_ptr.read() )  // last copy
4724                {
4725                    r_cas_to_init_cmd_multi_req = true;
4726                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4727                                            // all update responses
4728                    cmd_cas_fifo_get = true;
4729                    r_cas_cpt        = 0;
4730                }
4731            }
4732
4733#if DEBUG_MEMC_CAS
4734if( m_debug_cas_fsm )
4735{
4736    std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to INIT_CMD FSM "
4737              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4738              << " / wdata = " << std::hex << r_cas_wdata.read()
4739              << " / srcid = " << std::dec << entry.owner.srcid
4740              << " / inst = " << std::dec << entry.owner.inst << std::endl;
4741}
4742#endif
4743            break;
4744        }
4745        /////////////////////
4746        case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
4747        {
4748            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4749            {
4750                if( !r_cas_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
4751                {
4752                    // fill the data buffer
4753                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4754                    for(size_t i = 0; i<m_words; i++)
4755                    {
4756                        if (i == word)
4757                        {
4758                            r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
4759                        }
4760                        else if ( (i == word+1) && (r_cas_cpt.read()==4) ) // 64 bit CAS
4761                        {
4762                            r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
4763                        }
4764                        else
4765                        {
4766                            r_cas_to_ixr_cmd_data[i] = r_cas_data[i].read();
4767                        }
4768                    }
4769                    size_t wok_index = 0;
4770                    bool   wok       = !m_transaction_tab.full(wok_index);
4771                    if ( wok )
4772                    {
4773                        r_cas_trt_index = wok_index;
4774                        r_cas_fsm       = CAS_BC_UPT_LOCK;
4775                    }
4776                    else
4777                    {
4778                        r_cas_fsm       = CAS_WAIT;
4779                    }
4780                }
4781                else
4782                {
4783                    r_cas_fsm = CAS_WAIT;
4784                }
4785            }
4786            break;
4787        }
4788        ///////////////////
4789        case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
4790                              // write data in cache in case of successful registration
4791        {
4792            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4793            {
4794                bool        wok       = false;
4795                size_t      index     = 0;
4796                size_t      srcid     = m_cmd_cas_srcid_fifo.read();
4797                size_t      trdid     = m_cmd_cas_trdid_fifo.read();
4798                size_t      pktid     = m_cmd_cas_pktid_fifo.read();
4799                addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4800                size_t      nb_copies = r_cas_count.read();
4801
4802                // register a broadcast inval transaction in UPT
4803                wok = m_update_tab.set(false, // it's an inval transaction
4804                                       true,    // it's a broadcast
4805                                       true,    // it needs a response
4806                                       srcid,
4807                                       trdid,
4808                                       pktid,
4809                                       nline,
4810                                       nb_copies,
4811                                       index);
4812
4813                if ( wok )  // UPT not full
4814                {
4815                    // cache update
4816                    size_t way  = r_cas_way.read();
4817                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4818                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4819
4820                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4821                    if(r_cas_cpt.read()==4)
4822                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4823
4824                    // monitor
4825                    if ( m_monitor_ok )
4826                    {
4827                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4828                    char buf[80];
4829                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4830                        check_monitor( buf, address, r_cas_wdata.read() );
4831                        if ( r_cas_cpt.read()==4 )
4832                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4833                    }
4834                    r_cas_upt_index = index;
4835                    r_cas_fsm = CAS_BC_DIR_INVAL;
4836#if DEBUG_MEMC_CAS
4837if( m_debug_cas_fsm )
4838{
4839    std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
4840              << " / nline = " << nline
4841              << " / count = " << nb_copies
4842              << " / upt_index = " << index << std::endl;
4843}
4844#endif
4845                }
4846                else      //  releases the lock protecting UPT
4847                {
4848                     r_cas_fsm = CAS_WAIT;
4849                }
4850            }
4851            break;
4852        }
4853        //////////////////
4854        case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
4855        {
4856            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS ) &&
4857                 (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS ) &&
4858                 (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS ))
4859            {
4860                // set TRT
4861                m_transaction_tab.set(r_cas_trt_index.read(),
4862                                      false,    // PUT request to XRAM
4863                                      m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())],
4864                                      0,
4865                                      0,
4866                                      0,
4867                                      false,    // not a processor read
4868                                      0,
4869                                      0,
4870                                      std::vector<be_t>(m_words,0),
4871                                      std::vector<data_t>(m_words,0));
4872
4873                // invalidate directory entry
4874                DirectoryEntry entry;
4875                entry.valid         = false;
4876                entry.dirty         = false;
4877                entry.tag         = 0;
4878                entry.is_cnt        = false;
4879                entry.lock          = false;
4880                entry.count         = 0;
4881                entry.owner.srcid   = 0;
4882#if L1_MULTI_CACHE
4883                entry.owner.cache_id= 0;
4884#endif
4885                entry.owner.inst    = false;
4886                entry.ptr           = 0;
4887                size_t set          = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4888                size_t way          = r_cas_way.read();
4889                m_cache_directory.write(set, way, entry);
4890
4891                r_cas_fsm = CAS_BC_CC_SEND;
4892
4893#if DEBUG_MEMC_CAS
4894if( m_debug_cas_fsm )
4895{
4896    std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
4897              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
4898              << " / set = " << std::dec << set << " / way = " << way << std::endl;
4899}
4900#endif
4901            }
4902            else
4903            {
4904                assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
4905            }
4906            break;
4907        }
4908        ///////////////////
4909        case CAS_BC_CC_SEND:  // Request the broadcast inval to INIT_CMD FSM
4910        {
4911            if ( !r_cas_to_init_cmd_multi_req.read() &&
4912                 !r_cas_to_init_cmd_brdcast_req.read())
4913            {
4914                r_cas_to_init_cmd_multi_req    = false;
4915                r_cas_to_init_cmd_brdcast_req  = true;
4916                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4917                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4918                r_cas_to_init_cmd_index        = 0;
4919                r_cas_to_init_cmd_wdata        = 0;
4920
4921                r_cas_fsm = CAS_BC_XRAM_REQ;
4922            }
4923            break;
4924        }
4925        ////////////////////
4926        case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
4927        {
4928            if ( !r_cas_to_ixr_cmd_req )
4929            {
4930                r_cas_to_ixr_cmd_req     = true;
4931                r_cas_to_ixr_cmd_write   = true;
4932                r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4933                r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
4934                r_cas_fsm                = CAS_IDLE;
4935                cmd_cas_fifo_get         = true;
4936                r_cas_cpt                = 0;
4937
4938#if DEBUG_MEMC_CAS
4939if( m_debug_cas_fsm )
4940{
4941    std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
4942              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
4943              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
4944}
4945#endif
4946            }
4947            else
4948            {
4949               std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
4950                         << std::endl;
4951            }
4952            break;
4953        }
4954        /////////////////
4955        case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
4956        {
4957            if( !r_cas_to_tgt_rsp_req )
4958            {
4959                cmd_cas_fifo_get     = true;
4960                r_cas_cpt              = 0;
4961                r_cas_to_tgt_rsp_req = true;
4962                r_cas_to_tgt_rsp_data  = 1;
4963                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4964                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4965                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4966                r_cas_fsm              = CAS_IDLE;
4967
4968#if DEBUG_MEMC_CAS
4969if( m_debug_cas_fsm )
4970{
4971    std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
4972}
4973#endif
4974            }
4975            break;
4976        }
4977        ////////////////////
4978        case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
4979        {
4980            if( !r_cas_to_tgt_rsp_req )
4981            {
4982                cmd_cas_fifo_get       = true;
4983                r_cas_cpt              = 0;
4984                r_cas_to_tgt_rsp_req = true;
4985                r_cas_to_tgt_rsp_data  = 0;
4986                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4987                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4988                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4989                r_cas_fsm              = CAS_IDLE;
4990
4991#if DEBUG_MEMC_CAS
4992if( m_debug_cas_fsm )
4993{
4994    std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
4995}
4996#endif
4997            }
4998            break;
4999        }
5000        /////////////////////
5001        case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
5002        {
5003            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
5004            {
5005                size_t   index = 0;
5006                bool hit_read = m_transaction_tab.hit_read(
5007                                  m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],index);
5008                bool hit_write = m_transaction_tab.hit_write(
5009                                   m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]);
5010                bool wok = !m_transaction_tab.full(index);
5011
5012#if DEBUG_MEMC_CAS
5013if( m_debug_cas_fsm )
5014{
5015    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_LOCK> Check TRT state"
5016              << " / hit_read = "  << hit_read
5017              << " / hit_write = " << hit_write
5018              << " / wok = " << wok
5019              << " / index = " << index << std::endl;
5020}
5021#endif
5022
5023                if ( hit_read || !wok || hit_write ) // missing line already requested or no space in TRT
5024                {
5025                    r_cas_fsm = CAS_WAIT;
5026                }
5027                else
5028                {
5029                    r_cas_trt_index = index;
5030                    r_cas_fsm       = CAS_MISS_TRT_SET;
5031                }
5032            }
5033            break;
5034        }
5035        ////////////////////
5036        case CAS_MISS_TRT_SET: // register the GET transaction in TRT
5037        {
5038            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
5039            {
5040                std::vector<be_t> be_vector;
5041                std::vector<data_t> data_vector;
5042                be_vector.clear();
5043                data_vector.clear();
5044                for ( size_t i=0; i<m_words; i++ )
5045                {
5046                    be_vector.push_back(0);
5047                    data_vector.push_back(0);
5048                }
5049
5050                m_transaction_tab.set(r_cas_trt_index.read(),
5051                                      true,   // read request
5052                                      m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],
5053                                      m_cmd_cas_srcid_fifo.read(),
5054                                      m_cmd_cas_trdid_fifo.read(),
5055                                      m_cmd_cas_pktid_fifo.read(),
5056                                      false,    // write request from processor
5057                                      0,
5058                                      0,
5059                                      be_vector,
5060                                      data_vector);
5061                r_cas_fsm = CAS_MISS_XRAM_REQ;
5062
5063#if DEBUG_MEMC_CAS
5064if( m_debug_cas_fsm )
5065{
5066    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
5067              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
5068              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5069}
5070#endif
5071            }
5072            break;
5073        }
5074        //////////////////////
5075        case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
5076        {
5077            if ( !r_cas_to_ixr_cmd_req )
5078            {
5079                r_cas_to_ixr_cmd_req        = true;
5080                r_cas_to_ixr_cmd_write      = false;
5081                r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
5082                r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()];
5083                r_cas_fsm                   = CAS_WAIT;
5084
5085#if DEBUG_MEMC_CAS
5086if( m_debug_cas_fsm )
5087{
5088    std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
5089              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
5090              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
5091}
5092#endif
5093            }
5094            break;
5095        }
5096    } // end switch r_cas_fsm
5097
5098
5099    //////////////////////////////////////////////////////////////////////////////
5100    //    INIT_CMD FSM
5101    //////////////////////////////////////////////////////////////////////////////
5102    // The INIT_CMD fsm controls the VCI CMD initiator port on the coherence
5103    // network, used to update or invalidate cache lines in L1 caches.
5104    //
5105    // It implements a round-robin priority between the three possible client FSMs
5106    // XRAM_RSP, WRITE and CAS. Each FSM can request two types of services:
5107    // - r_xram_rsp_to_init_cmd_multi_req : multi-inval
5108    //   r_xram_rsp_to_init_cmd_brdcast_req : broadcast-inval
5109    // - r_write_to_init_cmd_multi_req : multi-update
5110    //   r_write_to_init_cmd_brdcast_req : broadcast-inval
5111    // - r_cas_to_init_cmd_multi_req : multi-update
5112    //   r_cas_to_init_cmd_brdcast_req : broadcast-inval
5113    //
5114    // An inval request is a single cell VCI write command containing the
5115    // index of the line to be invalidated.
5116    // An update request is a multi-cells VCI write command : The first cell
5117    // contains the index of the cache line to be updated. The second cell contains
5118    // the index of the first modified word in the line. The following cells
5119    // contain the data.
5120    ///////////////////////////////////////////////////////////////////////////////
5121
5122    switch ( r_init_cmd_fsm.read() )
5123    {
5124        ////////////////////////
5125        case INIT_CMD_UPDT_IDLE:  // XRAM_RSP FSM has highest priority
5126        {
5127            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5128                 r_xram_rsp_to_init_cmd_multi_req.read()  )
5129            {
5130                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5131                m_cpt_inval++;
5132            }
5133            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5134            {
5135                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5136                m_cpt_inval++;
5137            }
5138            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5139                      r_write_to_init_cmd_multi_req.read() )
5140            {
5141                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5142                m_cpt_update++;
5143            }
5144            else if ( r_write_to_init_cmd_brdcast_req.read() )
5145            {
5146                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5147                m_cpt_inval++;
5148            }
5149            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5150                      r_cas_to_init_cmd_multi_req.read()  )
5151            {
5152                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5153                m_cpt_update++;
5154            }
5155            else if( r_cas_to_init_cmd_brdcast_req.read() )
5156            {
5157                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5158                m_cpt_inval++;
5159            }
5160            break;
5161        }
5162        /////////////////////////
5163        case INIT_CMD_INVAL_IDLE: // WRITE FSM has highest priority
5164        {
5165            if ( m_write_to_init_cmd_inst_fifo.rok() ||
5166                 r_write_to_init_cmd_multi_req.read() )
5167            {
5168                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5169                m_cpt_update++;
5170            }
5171            else if ( r_write_to_init_cmd_brdcast_req.read() )
5172            {
5173                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5174                m_cpt_inval++;
5175            }
5176            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5177                      r_cas_to_init_cmd_multi_req.read()  )
5178            {
5179                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5180                m_cpt_update++;
5181            }
5182            else if( r_cas_to_init_cmd_brdcast_req.read() )
5183            {
5184                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5185                m_cpt_inval++;
5186            }
5187            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5188                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5189            {
5190                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5191                m_cpt_inval++;
5192            }
5193            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5194            {
5195                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5196                m_cpt_inval++;
5197            }
5198            break;
5199        }
5200        //////////////////////////
5201        case INIT_CMD_CAS_UPDT_IDLE: // CAS FSM has highest priority
5202        {
5203            if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5204                 r_cas_to_init_cmd_multi_req.read()  )
5205            {
5206                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5207                m_cpt_update++;
5208            }
5209            else if( r_cas_to_init_cmd_brdcast_req.read() )
5210            {
5211                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5212                m_cpt_inval++;
5213            }
5214            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5215                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5216            {
5217                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5218                m_cpt_inval++;
5219            }
5220            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5221            {
5222                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5223                m_cpt_inval++;
5224            }
5225            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5226                      r_write_to_init_cmd_multi_req.read() )
5227            {
5228                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5229                m_cpt_update++;
5230            }
5231            else if ( r_write_to_init_cmd_brdcast_req.read() )
5232            {
5233                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5234                m_cpt_inval++;
5235            }
5236            break;
5237        }
5238        //////////////////////////
5239        case INIT_CMD_INVAL_NLINE:  // send a multi-inval (from XRAM_RSP)
5240        {
5241            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() )
5242            {
5243                if ( p_vci_ini.cmdack )
5244                {
5245                    m_cpt_inval_mult++;
5246                    r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5247                    xram_rsp_to_init_cmd_fifo_get = true;
5248                }
5249            }
5250            else
5251            {
5252                if( r_xram_rsp_to_init_cmd_multi_req.read() ) r_xram_rsp_to_init_cmd_multi_req = false;
5253                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5254            }
5255            break;
5256        }
5257        ///////////////////////////
5258        case INIT_CMD_XRAM_BRDCAST: // send a broadcast-inval (from XRAM_RSP)
5259        {
5260            if ( p_vci_ini.cmdack )
5261            {
5262                m_cpt_inval_brdcast++;
5263                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5264                r_xram_rsp_to_init_cmd_brdcast_req = false;
5265            }
5266            break;
5267        }
5268        ////////////////////////////
5269        case INIT_CMD_WRITE_BRDCAST:  // send a broadcast-inval (from WRITE FSM)
5270        {
5271            if( p_vci_ini.cmdack )
5272            {
5273
5274#if DEBUG_MEMC_INIT_CMD
5275if( m_debug_init_cmd_fsm )
5276{
5277    std::cout << "  <MEMC " << name() << ".INIT_CMD_WRITE_BRDCAST> Broadcast-Inval for line "
5278              << r_write_to_init_cmd_nline.read() << std::endl;
5279}
5280#endif
5281                m_cpt_inval_brdcast++;
5282                r_write_to_init_cmd_brdcast_req = false;
5283                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5284            }
5285            break;
5286        }
5287        /////////////////////////
5288        case INIT_CMD_UPDT_NLINE:  // send nline for a multi-update (from WRITE FSM)
5289        {
5290            if ( m_write_to_init_cmd_inst_fifo.rok() )
5291            {
5292                if ( p_vci_ini.cmdack )
5293                {
5294                    m_cpt_update_mult++;
5295                    r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
5296                    // write_to_init_cmd_fifo_get = true;
5297                }
5298            }
5299            else
5300            {
5301                if ( r_write_to_init_cmd_multi_req.read() ) r_write_to_init_cmd_multi_req = false;
5302                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5303            }
5304            break;
5305        }
5306        /////////////////////////
5307        case INIT_CMD_UPDT_INDEX:  // send word index for a multi-update (from WRITE FSM)
5308        {
5309            r_init_cmd_cpt    = 0;
5310            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
5311            break;
5312        }
5313        ////////////////////////
5314        case INIT_CMD_UPDT_DATA:  // send the data for a multi-update (from WRITE FSM)
5315        {
5316            if ( p_vci_ini.cmdack )
5317            {
5318                if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) )
5319                {
5320                    r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5321                    write_to_init_cmd_fifo_get = true;
5322                }
5323                else
5324                {
5325                    r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
5326                }
5327            }
5328            break;
5329        }
5330        /////////////////////////
5331        case INIT_CMD_CAS_BRDCAST: // send a broadcast-inval (from CAS FSM)
5332        {
5333            if( p_vci_ini.cmdack )
5334            {
5335                m_cpt_inval_brdcast++;
5336                r_cas_to_init_cmd_brdcast_req = false;
5337                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5338            }
5339            break;
5340        }
5341        ////////////////////////////
5342        case INIT_CMD_CAS_UPDT_NLINE:   // send nline for a multi-update (from CAS FSM)
5343        {
5344            if ( m_cas_to_init_cmd_inst_fifo.rok() )
5345            {
5346                if ( p_vci_ini.cmdack )
5347                {
5348                    m_cpt_update_mult++;
5349                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_INDEX;
5350                }
5351            }
5352            else
5353            {
5354                if( r_cas_to_init_cmd_multi_req.read() ) r_cas_to_init_cmd_multi_req = false;
5355                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5356            }
5357            break;
5358        }
5359        ////////////////////////////
5360        case INIT_CMD_CAS_UPDT_INDEX:  // send word index for a multi-update (from CAS FSM)
5361        {
5362            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA;
5363            break;
5364        }
5365        ///////////////////////////
5366        case INIT_CMD_CAS_UPDT_DATA:  // send first data for a multi-update (from CAS FSM)
5367        {
5368            if ( p_vci_ini.cmdack )
5369            {
5370                if ( r_cas_to_init_cmd_is_long.read() )
5371                {
5372                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA_HIGH;
5373                }
5374                else
5375                {
5376                    cas_to_init_cmd_fifo_get = true;
5377                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5378                }
5379            }
5380            break;
5381        }
5382        ////////////////////////
5383        case INIT_CMD_CAS_UPDT_DATA_HIGH:  // send second data for a multi-update (from CAS FSM)
5384        {
5385            if ( p_vci_ini.cmdack )
5386            {
5387                cas_to_init_cmd_fifo_get = true;
5388                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5389            }
5390            break;
5391        }
5392    } // end switch r_init_cmd_fsm
5393
5394    /////////////////////////////////////////////////////////////////////
5395    //    TGT_RSP FSM
5396    /////////////////////////////////////////////////////////////////////
5397    // The TGT_RSP fsm sends the responses on the VCI target port
5398    // with a round robin priority between six requests :
5399    // - r_read_to_tgt_rsp_req
5400    // - r_write_to_tgt_rsp_req
5401    // - r_cas_to_tgt_rsp_req
5402    // - r_cleanup_to_tgt_rsp_req
5403    // - r_xram_rsp_to_tgt_rsp_req
5404    // - r_init_rsp_to_tgt_rsp_req
5405    // The  ordering is :  read > write > cas > xram > init > cleanup
5406    /////////////////////////////////////////////////////////////////////
5407
5408    switch ( r_tgt_rsp_fsm.read() )
5409    {
5410        ///////////////////////
5411        case TGT_RSP_READ_IDLE:   // write requests have the highest priority
5412        {
5413          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5414          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5415          else if ( r_xram_rsp_to_tgt_rsp_req )
5416          {
5417            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5418            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5419          }
5420          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5421          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5422          else if ( r_read_to_tgt_rsp_req     )
5423          {
5424            r_tgt_rsp_fsm = TGT_RSP_READ;
5425            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5426          }
5427          break;
5428        }
5429        ////////////////////////
5430        case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
5431        {
5432          if      ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS;
5433          else if ( r_xram_rsp_to_tgt_rsp_req )
5434          {
5435            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5436            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5437          }
5438          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5439          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5440          else if ( r_read_to_tgt_rsp_req     )
5441          {
5442            r_tgt_rsp_fsm = TGT_RSP_READ;
5443            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5444          }
5445
5446          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5447          break;
5448        }
5449        ///////////////////////
5450        case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
5451        {
5452          if ( r_xram_rsp_to_tgt_rsp_req )
5453          {
5454            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5455            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5456          }
5457          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5458          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5459          else if ( r_read_to_tgt_rsp_req     )
5460          {
5461            r_tgt_rsp_fsm = TGT_RSP_READ;
5462            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5463          }
5464          else if ( r_write_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5465          else if ( r_cas_to_tgt_rsp_req   ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5466          break;
5467        }
5468        ///////////////////////
5469        case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
5470        {
5471
5472          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5473          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5474          else if ( r_read_to_tgt_rsp_req     )
5475          {
5476            r_tgt_rsp_fsm = TGT_RSP_READ;
5477            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5478          }
5479          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5480          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5481          else if ( r_xram_rsp_to_tgt_rsp_req )
5482          {
5483            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5484            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5485          }
5486          break;
5487        }
5488        ///////////////////////
5489        case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
5490        {
5491          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5492          else if ( r_read_to_tgt_rsp_req     )
5493          {
5494            r_tgt_rsp_fsm = TGT_RSP_READ;
5495            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5496          }
5497          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5498          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5499          else if ( r_xram_rsp_to_tgt_rsp_req )
5500          {
5501            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5502            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5503          }
5504          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
5505          break;
5506        }
5507        ///////////////////////
5508        case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
5509        {
5510          if      ( r_read_to_tgt_rsp_req     )
5511          {
5512            r_tgt_rsp_fsm = TGT_RSP_READ;
5513            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5514          }
5515          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5516          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5517          else if ( r_xram_rsp_to_tgt_rsp_req )
5518          {
5519            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5520            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5521          }
5522          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5523          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5524          break;
5525        }
5526        //////////////////
5527        case TGT_RSP_READ:    // send the response to a read
5528        {
5529            if ( p_vci_tgt.rspack )
5530            {
5531
5532#if DEBUG_MEMC_TGT_RSP
5533if( m_debug_tgt_rsp_fsm )
5534{
5535    std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
5536              << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
5537              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
5538              << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
5539              << " / rdata = " << std::hex << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5540              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5541}
5542#endif
5543                if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) )
5544                {
5545                    r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
5546                    r_read_to_tgt_rsp_req = false;
5547                }
5548                else
5549                {
5550                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5551                }
5552            }
5553            break;
5554        }
5555        ///////////////////
5556        case TGT_RSP_WRITE:   // send the write acknowledge
5557        {
5558            if ( p_vci_tgt.rspack )
5559            {
5560
5561#if DEBUG_MEMC_TGT_RSP
5562if( m_debug_tgt_rsp_fsm )
5563{
5564    std::cout << "  <MEMC " << name() << ".TGT_RSP_WRITE> Write response"
5565              << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
5566              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
5567              << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
5568}
5569#endif
5570                r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
5571                r_write_to_tgt_rsp_req = false;
5572            }
5573            break;
5574        }
5575        ///////////////////
5576        case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
5577        {
5578            if ( p_vci_tgt.rspack )
5579            {
5580
5581#if DEBUG_MEMC_TGT_RSP
5582if( m_debug_tgt_rsp_fsm )
5583{
5584    std::cout << "  <MEMC " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
5585              << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
5586              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
5587              << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
5588}
5589#endif
5590                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
5591                r_cleanup_to_tgt_rsp_req = false;
5592            }
5593            break;
5594        }
5595        //////////////////
5596        case TGT_RSP_CAS:    // send one atomic word response
5597        {
5598            if ( p_vci_tgt.rspack )
5599            {
5600
5601#if DEBUG_MEMC_TGT_RSP
5602if( m_debug_tgt_rsp_fsm )
5603{
5604    std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
5605              << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
5606              << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
5607              << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
5608}
5609#endif
5610                r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
5611                r_cas_to_tgt_rsp_req = false;
5612            }
5613            break;
5614        }
5615
5616        ///////////////////////
5617        case TGT_RSP_XRAM:    // send the response after XRAM access
5618        {
5619            if ( p_vci_tgt.rspack )
5620            {
5621
5622#if DEBUG_MEMC_TGT_RSP
5623if( m_debug_tgt_rsp_fsm )
5624{
5625    std::cout << "  <MEMC " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
5626              << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
5627              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
5628              << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
5629              << " / rdata = " << std::hex << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5630              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5631}
5632#endif
5633                if ( (r_tgt_rsp_cpt.read() ==
5634                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
5635                   || r_xram_rsp_to_tgt_rsp_rerror.read() )
5636                {
5637                    r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
5638                    r_xram_rsp_to_tgt_rsp_req = false;
5639                }
5640                else
5641                {
5642                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5643                }
5644            }
5645            break;
5646        }
5647        //////////////////
5648        case TGT_RSP_INIT:    // send the write response after coherence transaction
5649        {
5650            if ( p_vci_tgt.rspack )
5651            {
5652
5653#if DEBUG_MEMC_TGT_RSP
5654if( m_debug_tgt_rsp_fsm )
5655{
5656    std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
5657              << " / rsrcid = " << std::dec << r_init_rsp_to_tgt_rsp_srcid.read()
5658              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read()
5659              << " / rpktid = " << r_init_rsp_to_tgt_rsp_pktid.read() << std::endl;
5660}
5661#endif
5662                r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
5663                r_init_rsp_to_tgt_rsp_req = false;
5664            }
5665            break;
5666        }
5667    } // end switch tgt_rsp_fsm
5668
5669    ////////////////////////////////////////////////////////////////////////////////////
5670    //    ALLOC_UPT FSM
5671    ////////////////////////////////////////////////////////////////////////////////////
5672    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
5673    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
5674    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
5675    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
5676    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
5677    // - The CLEANUP  FSM decrement an entry in UPT.
5678    // The resource is always allocated.
5679    /////////////////////////////////////////////////////////////////////////////////////
5680
5681    switch ( r_alloc_upt_fsm.read() )
5682    {
5683
5684      ////////////////////////
5685      case ALLOC_UPT_INIT_RSP:
5686        if (( r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK  ) &&
5687            ( r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR ))
5688        {
5689          if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5690              ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5691            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5692
5693          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5694            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5695
5696          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5697            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5698
5699          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5700                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5701            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5702        }
5703        break;
5704
5705        /////////////////////
5706      case ALLOC_UPT_WRITE:
5707        if (( r_write_fsm.read() != WRITE_UPT_LOCK    ) &&
5708            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK ))
5709        {
5710          if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5711            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5712
5713          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5714            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5715
5716          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5717                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5718            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5719
5720          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5721            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5722        }
5723        break;
5724
5725        ////////////////////////
5726      case ALLOC_UPT_XRAM_RSP:
5727        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
5728        {
5729          if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5730            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5731
5732          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5733                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5734            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5735
5736          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5737            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5738
5739          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    )   ||
5740                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5741            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5742        }
5743        break;
5744
5745        //////////////////////////
5746      case ALLOC_UPT_CLEANUP:
5747        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
5748        {
5749          if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5750              ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5751            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5752
5753          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5754            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5755
5756          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5757                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5758            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5759
5760          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5761            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5762        }
5763        break;
5764
5765        //////////////////////////
5766      case ALLOC_UPT_CAS:
5767        if (( r_cas_fsm.read() != CAS_UPT_LOCK    ) &&
5768            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK ))
5769        {
5770          if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5771            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5772
5773          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5774                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5775            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5776
5777          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5778            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5779
5780          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5781            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5782        }
5783        break;
5784
5785    } // end switch r_alloc_upt_fsm
5786
5787    ////////////////////////////////////////////////////////////////////////////////////
5788    //    ALLOC_DIR FSM
5789    ////////////////////////////////////////////////////////////////////////////////////
5790    // The ALLOC_DIR FSM allocates the access to the directory and
5791    // the data cache with a round robin priority between 5 user FSMs :
5792    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
5793    // The ressource is always allocated.
5794    /////////////////////////////////////////////////////////////////////////////////////
5795
5796    switch ( r_alloc_dir_fsm.read() )
5797    {
5798      case ALLOC_DIR_RESET:
5799        // Initializes the directory one SET each cycle. All the WAYS of a SET are
5800        // initialize in parallel
5801
5802        r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
5803
5804        if (r_alloc_dir_reset_cpt.read() == (m_sets - 1)) {
5805          m_cache_directory.init();
5806
5807          r_alloc_dir_fsm = ALLOC_DIR_READ;
5808        }
5809        break;
5810
5811      ////////////////////
5812      case ALLOC_DIR_READ:
5813        if ((( r_read_fsm.read()       != READ_DIR_REQ    )   &&
5814             ( r_read_fsm.read()       != READ_DIR_LOCK   )   &&
5815             ( r_read_fsm.read()       != READ_TRT_LOCK   )   &&
5816             ( r_read_fsm.read()       != READ_HEAP_REQ   ))
5817            ||
5818            (( r_read_fsm.read()       == READ_TRT_LOCK   )   &&
5819             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_READ  )))
5820        {
5821          if (r_write_fsm.read() == WRITE_DIR_REQ)
5822            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5823
5824          else if (r_cas_fsm.read() == CAS_DIR_REQ)
5825            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5826
5827          else if (r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5828            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5829
5830          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
5831            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5832        }
5833        break;
5834
5835        /////////////////////
5836      case ALLOC_DIR_WRITE:
5837        if ((( r_write_fsm.read()      != WRITE_DIR_REQ       )  &&
5838             ( r_write_fsm.read()      != WRITE_DIR_LOCK      )  &&
5839             ( r_write_fsm.read()      != WRITE_DIR_READ      )  &&
5840             ( r_write_fsm.read()      != WRITE_DIR_HIT       )  &&
5841             ( r_write_fsm.read()      != WRITE_BC_TRT_LOCK   )  &&
5842             ( r_write_fsm.read()      != WRITE_BC_UPT_LOCK   )  &&
5843             ( r_write_fsm.read()      != WRITE_MISS_TRT_LOCK )  &&
5844             ( r_write_fsm.read()      != WRITE_UPT_LOCK      )  &&
5845             ( r_write_fsm.read()      != WRITE_UPT_HEAP_LOCK ))
5846            ||
5847            (( r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK )  &&
5848             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE    ))
5849            ||
5850            (( r_write_fsm.read()      == WRITE_MISS_TRT_LOCK )  &&
5851             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE     )))
5852        {
5853          if ( r_cas_fsm.read() == CAS_DIR_REQ )
5854            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5855
5856          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5857            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5858
5859          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5860            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5861
5862          else if ( r_read_fsm.read() == READ_DIR_REQ )
5863            r_alloc_dir_fsm = ALLOC_DIR_READ;
5864        }
5865        break;
5866
5867        ////////////////////
5868        case ALLOC_DIR_CAS:
5869        if ((( r_cas_fsm.read()        != CAS_DIR_REQ         )  &&
5870             ( r_cas_fsm.read()        != CAS_DIR_LOCK        )  &&
5871             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ    )  &&
5872             ( r_cas_fsm.read()        != CAS_DIR_HIT_COMPARE )  &&
5873             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE   )  &&
5874             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK     )  &&
5875             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK     )  &&
5876             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK   )  &&
5877             ( r_cas_fsm.read()        != CAS_UPT_LOCK        )  &&
5878             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK   ))
5879            ||
5880            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK   )  &&
5881             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS      ))
5882            ||
5883            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK   )  &&
5884             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS       )))
5885        {
5886          if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5887            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5888
5889          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5890            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5891
5892          else if ( r_read_fsm.read() == READ_DIR_REQ )
5893            r_alloc_dir_fsm = ALLOC_DIR_READ;
5894
5895          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5896            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5897        }
5898        break;
5899
5900        ///////////////////////
5901        case ALLOC_DIR_CLEANUP:
5902        if (( r_cleanup_fsm.read() != CLEANUP_DIR_REQ   ) &&
5903            ( r_cleanup_fsm.read() != CLEANUP_DIR_LOCK  ) &&
5904            ( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ  ) &&
5905            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK ))
5906        {
5907          if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5908            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5909
5910          else if ( r_read_fsm.read() == READ_DIR_REQ )
5911            r_alloc_dir_fsm = ALLOC_DIR_READ;
5912
5913          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5914            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5915
5916          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5917            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5918        }
5919        break;
5920
5921        ////////////////////////
5922        case ALLOC_DIR_XRAM_RSP:
5923        if (( r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK   ) &&
5924            ( r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY   ) &&
5925            ( r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK ))
5926        {
5927          if ( r_read_fsm.read() == READ_DIR_REQ )
5928            r_alloc_dir_fsm = ALLOC_DIR_READ;
5929
5930          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5931            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5932
5933          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5934            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5935
5936          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5937            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5938        }
5939        break;
5940
5941    } // end switch alloc_dir_fsm
5942
5943    ////////////////////////////////////////////////////////////////////////////////////
5944    //    ALLOC_TRT FSM
5945    ////////////////////////////////////////////////////////////////////////////////////
5946    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
5947    // with a round robin priority between 4 user FSMs :
5948    // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
5949    // The ressource is always allocated.
5950    ///////////////////////////////////////////////////////////////////////////////////
5951
5952    switch ( r_alloc_trt_fsm.read() )
5953    {
5954      ////////////////////
5955      case ALLOC_TRT_READ:
5956        if ( r_read_fsm.read() != READ_TRT_LOCK )
5957        {
5958          if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5959              ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5960            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5961
5962          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5963                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5964            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5965
5966          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5967                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5968            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5969
5970          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5971                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5972            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5973        }
5974        break;
5975
5976      /////////////////////
5977      case ALLOC_TRT_WRITE:
5978        if (( r_write_fsm.read() != WRITE_MISS_TRT_LOCK ) &&
5979            ( r_write_fsm.read() != WRITE_BC_TRT_LOCK   ) &&
5980            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK   ))
5981        {
5982          if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5983              ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5984            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5985
5986          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5987                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5988            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5989
5990          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5991                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5992            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5993
5994          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5995            r_alloc_trt_fsm = ALLOC_TRT_READ;
5996        }
5997        break;
5998
5999      ////////////////////
6000      case ALLOC_TRT_CAS:
6001        if (( r_cas_fsm.read() != CAS_MISS_TRT_LOCK ) &&
6002            ( r_cas_fsm.read() != CAS_BC_TRT_LOCK   ) &&
6003            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK   ))
6004        {
6005          if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
6006              ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
6007            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6008
6009          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
6010                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
6011            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6012
6013          else if ( r_read_fsm.read() == READ_TRT_LOCK )
6014            r_alloc_trt_fsm = ALLOC_TRT_READ;
6015
6016          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
6017                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
6018            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6019        }
6020        break;
6021
6022      ////////////////////////
6023      case ALLOC_TRT_XRAM_RSP:
6024        if ((( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK   )  ||
6025             ( r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP  )) &&
6026             ( r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY   )  &&
6027             ( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT   )  &&
6028             ( r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK ))
6029        {
6030          if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
6031              ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
6032            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
6033
6034          else if ( r_read_fsm.read() == READ_TRT_LOCK )
6035            r_alloc_trt_fsm = ALLOC_TRT_READ;
6036
6037          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
6038                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
6039            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6040
6041          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
6042                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
6043            r_alloc_trt_fsm = ALLOC_TRT_CAS;
6044        }
6045        break;
6046
6047      ////////////////////////
6048      case ALLOC_TRT_IXR_RSP:
6049        if (( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE ) &&
6050            ( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ  ))
6051        {
6052          if ( r_read_fsm.read() == READ_TRT_LOCK )
6053            r_alloc_trt_fsm = ALLOC_TRT_READ;
6054
6055          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
6056                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
6057            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
6058
6059          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
6060                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
6061            r_alloc_trt_fsm = ALLOC_TRT_CAS;
6062
6063          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
6064                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
6065            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
6066        }
6067        break;
6068
6069    } // end switch alloc_trt_fsm
6070
6071    ////////////////////////////////////////////////////////////////////////////////////
6072    //    ALLOC_HEAP FSM
6073    ////////////////////////////////////////////////////////////////////////////////////
6074    // The ALLOC_HEAP FSM allocates the access to the heap
6075    // with a round robin priority between 5 user FSMs :
6076    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
6077    // The ressource is always allocated.
6078    /////////////////////////////////////////////////////////////////////////////////////
6079
6080    switch ( r_alloc_heap_fsm.read() )
6081    {
6082        ////////////////////
6083        case ALLOC_HEAP_RESET:
6084          // Initializes the heap one ENTRY each cycle.
6085
6086          r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
6087
6088          if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1)) {
6089            m_heap.init();
6090
6091            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6092          }
6093          break;
6094
6095        ////////////////////
6096        case ALLOC_HEAP_READ:
6097        if (( r_read_fsm.read() != READ_HEAP_REQ   ) &&
6098            ( r_read_fsm.read() != READ_HEAP_LOCK  ) &&
6099            ( r_read_fsm.read() != READ_HEAP_ERASE ))
6100        {
6101          if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6102            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6103
6104          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6105            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6106
6107          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6108            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6109
6110          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6111            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6112        }
6113        break;
6114
6115        /////////////////////
6116        case ALLOC_HEAP_WRITE:
6117        if (( r_write_fsm.read() != WRITE_UPT_HEAP_LOCK ) &&
6118            ( r_write_fsm.read() != WRITE_UPT_REQ       ) &&
6119            ( r_write_fsm.read() != WRITE_UPT_NEXT      ))
6120        {
6121          if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6122            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6123
6124          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6125            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6126
6127          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6128            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6129
6130          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6131            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6132        }
6133        break;
6134
6135        ////////////////////
6136        case ALLOC_HEAP_CAS:
6137        if (( r_cas_fsm.read() != CAS_UPT_HEAP_LOCK ) &&
6138            ( r_cas_fsm.read() != CAS_UPT_REQ       ) &&
6139            ( r_cas_fsm.read() != CAS_UPT_NEXT      ))
6140        {
6141          if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6142            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6143
6144          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6145            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6146
6147          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6148            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6149
6150          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6151            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6152        }
6153        break;
6154
6155        ///////////////////////
6156        case ALLOC_HEAP_CLEANUP:
6157        if (( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ    ) &&
6158            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK   ) &&
6159            ( r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH ) &&
6160            ( r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN  ))
6161        {
6162          if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6163            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6164
6165          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6166            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6167
6168          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6169            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6170
6171          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6172            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6173        }
6174        break;
6175
6176        ////////////////////////
6177        case ALLOC_HEAP_XRAM_RSP:
6178        if (( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ   ) &&
6179            ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE ))
6180        {
6181          if  ( r_read_fsm.read() == READ_HEAP_REQ )
6182            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6183
6184          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6185            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6186
6187          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6188            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6189
6190          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6191            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6192
6193        }
6194        break;
6195
6196    } // end switch alloc_heap_fsm
6197
6198
6199    ////////////////////////////////////////////////////////////////////////////////////
6200    //    TGT_CMD to READ FIFO
6201    ////////////////////////////////////////////////////////////////////////////////////
6202
6203    if ( cmd_read_fifo_put ) {
6204      if ( cmd_read_fifo_get ) {
6205        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6206        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
6207        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6208        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6209        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6210      } else {
6211        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6212        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
6213        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6214        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6215        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6216      }
6217    } else {
6218      if ( cmd_read_fifo_get ) {
6219        m_cmd_read_addr_fifo.simple_get();
6220        m_cmd_read_length_fifo.simple_get();
6221        m_cmd_read_srcid_fifo.simple_get();
6222        m_cmd_read_trdid_fifo.simple_get();
6223        m_cmd_read_pktid_fifo.simple_get();
6224      }
6225    }
6226    /////////////////////////////////////////////////////////////////////
6227    //    TGT_CMD to WRITE FIFO
6228    /////////////////////////////////////////////////////////////////////
6229
6230    if ( cmd_write_fifo_put ) {
6231      if ( cmd_write_fifo_get ) {
6232        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6233        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6234        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6235        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6236        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6237        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
6238        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
6239      } else {
6240        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6241        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
6242        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6243        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6244        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6245        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
6246        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
6247      }
6248    } else {
6249      if ( cmd_write_fifo_get ) {
6250        m_cmd_write_addr_fifo.simple_get();
6251        m_cmd_write_eop_fifo.simple_get();
6252        m_cmd_write_srcid_fifo.simple_get();
6253        m_cmd_write_trdid_fifo.simple_get();
6254        m_cmd_write_pktid_fifo.simple_get();
6255        m_cmd_write_data_fifo.simple_get();
6256        m_cmd_write_be_fifo.simple_get();
6257      }
6258    }
6259    ////////////////////////////////////////////////////////////////////////////////////
6260    //    TGT_CMD to CAS FIFO
6261    ////////////////////////////////////////////////////////////////////////////////////
6262
6263    if ( cmd_cas_fifo_put ) {
6264      if ( cmd_cas_fifo_get ) {
6265        m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6266        m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6267        m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6268        m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6269        m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6270        m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
6271      } else {
6272        m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6273        m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
6274        m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6275        m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6276        m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6277        m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
6278      }
6279    } else {
6280      if ( cmd_cas_fifo_get ) {
6281        m_cmd_cas_addr_fifo.simple_get();
6282        m_cmd_cas_eop_fifo.simple_get();
6283        m_cmd_cas_srcid_fifo.simple_get();
6284        m_cmd_cas_trdid_fifo.simple_get();
6285        m_cmd_cas_pktid_fifo.simple_get();
6286        m_cmd_cas_wdata_fifo.simple_get();
6287      }
6288    }
6289    ////////////////////////////////////////////////////////////////////////////////////
6290    //    WRITE to INIT_CMD FIFO
6291    ////////////////////////////////////////////////////////////////////////////////////
6292
6293    if ( write_to_init_cmd_fifo_put ) {
6294      if ( write_to_init_cmd_fifo_get ) {
6295        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
6296        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
6297#if L1_MULTI_CACHE
6298        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
6299#endif
6300      } else {
6301        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
6302        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
6303#if L1_MULTI_CACHE
6304        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
6305#endif
6306      }
6307    } else {
6308      if ( write_to_init_cmd_fifo_get ) {
6309        m_write_to_init_cmd_inst_fifo.simple_get();
6310        m_write_to_init_cmd_srcid_fifo.simple_get();
6311#if L1_MULTI_CACHE
6312        m_write_to_init_cmd_cache_id_fifo.simple_get();
6313#endif
6314      }
6315    }
6316    ////////////////////////////////////////////////////////////////////////////////////
6317    //    XRAM_RSP to INIT_CMD FIFO
6318    ////////////////////////////////////////////////////////////////////////////////////
6319
6320    if ( xram_rsp_to_init_cmd_fifo_put ) {
6321      if ( xram_rsp_to_init_cmd_fifo_get ) {
6322        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
6323        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
6324#if L1_MULTI_CACHE
6325        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
6326#endif
6327      } else {
6328        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
6329        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
6330#if L1_MULTI_CACHE
6331        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
6332#endif
6333      }
6334    } else {
6335      if ( xram_rsp_to_init_cmd_fifo_get ) {
6336        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
6337        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
6338#if L1_MULTI_CACHE
6339        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
6340#endif
6341      }
6342    }
6343    ////////////////////////////////////////////////////////////////////////////////////
6344    //    CAS to INIT_CMD FIFO
6345    ////////////////////////////////////////////////////////////////////////////////////
6346
6347    if ( cas_to_init_cmd_fifo_put ) {
6348      if ( cas_to_init_cmd_fifo_get ) {
6349        m_cas_to_init_cmd_inst_fifo.put_and_get(cas_to_init_cmd_fifo_inst);
6350        m_cas_to_init_cmd_srcid_fifo.put_and_get(cas_to_init_cmd_fifo_srcid);
6351#if L1_MULTI_CACHE
6352        m_cas_to_init_cmd_cache_id_fifo.put_and_get(cas_to_init_cmd_fifo_cache_id);
6353#endif
6354      } else {
6355          m_cas_to_init_cmd_inst_fifo.simple_put(cas_to_init_cmd_fifo_inst);
6356          m_cas_to_init_cmd_srcid_fifo.simple_put(cas_to_init_cmd_fifo_srcid);
6357#if L1_MULTI_CACHE
6358          m_cas_to_init_cmd_cache_id_fifo.simple_put(cas_to_init_cmd_fifo_cache_id);
6359#endif
6360      }
6361    } else {
6362        if ( cas_to_init_cmd_fifo_get ) {
6363            m_cas_to_init_cmd_inst_fifo.simple_get();
6364            m_cas_to_init_cmd_srcid_fifo.simple_get();
6365#if L1_MULTI_CACHE
6366            m_cas_to_init_cmd_cache_id_fifo.simple_get();
6367#endif
6368      }
6369    }
6370
6371    m_cpt_cycles++;
6372
6373} // end transition()
6374
6375/////////////////////////////
6376tmpl(void)::genMoore()
6377/////////////////////////////
6378{
6379    ////////////////////////////////////////////////////////////
6380    // Command signals on the p_vci_ixr port
6381    ////////////////////////////////////////////////////////////
6382
6383    p_vci_ixr.be      = 0xF;
6384    p_vci_ixr.pktid   = 0;
6385    p_vci_ixr.srcid   = m_srcid_ixr;
6386    p_vci_ixr.cons    = false;
6387    p_vci_ixr.wrap    = false;
6388    p_vci_ixr.contig  = true;
6389    p_vci_ixr.clen    = 0;
6390    p_vci_ixr.cfixed  = false;
6391
6392    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
6393      p_vci_ixr.cmd     = vci_param::CMD_READ;
6394      p_vci_ixr.cmdval  = true;
6395      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
6396      p_vci_ixr.plen    = m_words*4;
6397      p_vci_ixr.wdata   = 0x00000000;
6398      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
6399      p_vci_ixr.eop     = true;
6400    }
6401    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE ) {
6402      if(r_cas_to_ixr_cmd_write.read()){
6403        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6404        p_vci_ixr.cmdval  = true;
6405        p_vci_ixr.address = (addr_t)((r_cas_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6406        p_vci_ixr.plen    = m_words*4;
6407        p_vci_ixr.wdata   = r_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6408        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6409        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6410      } else {
6411        p_vci_ixr.cmd     = vci_param::CMD_READ;
6412        p_vci_ixr.cmdval  = true;
6413        p_vci_ixr.address = (addr_t)(r_cas_to_ixr_cmd_nline.read()*m_words*4);
6414        p_vci_ixr.plen    = m_words*4;
6415        p_vci_ixr.wdata   = 0x00000000;
6416        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6417        p_vci_ixr.eop     = true;
6418      }
6419    }
6420    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
6421      if(r_write_to_ixr_cmd_write.read()){
6422        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6423        p_vci_ixr.cmdval  = true;
6424        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6425        p_vci_ixr.plen    = m_words*4;
6426        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6427        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6428        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6429      } else {
6430        p_vci_ixr.cmd     = vci_param::CMD_READ;
6431        p_vci_ixr.cmdval  = true;
6432        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
6433        p_vci_ixr.plen    = m_words*4;
6434        p_vci_ixr.wdata   = 0x00000000;
6435        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6436        p_vci_ixr.eop     = true;
6437      }
6438    }
6439    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
6440      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6441      p_vci_ixr.cmdval  = true;
6442      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6443      p_vci_ixr.plen    = m_words*4;
6444      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6445      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
6446      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6447    } else {
6448      p_vci_ixr.cmdval  = false;
6449      p_vci_ixr.address = 0;
6450      p_vci_ixr.plen    = 0;
6451      p_vci_ixr.wdata   = 0;
6452      p_vci_ixr.trdid   = 0;
6453      p_vci_ixr.eop = false;
6454    }
6455
6456    ////////////////////////////////////////////////////
6457    // Response signals on the p_vci_ixr port
6458    ////////////////////////////////////////////////////
6459
6460    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
6461          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
6462        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
6463    else                                        p_vci_ixr.rspack = false;
6464
6465    ////////////////////////////////////////////////////
6466    // Command signals on the p_vci_tgt port
6467    ////////////////////////////////////////////////////
6468
6469    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
6470      case TGT_CMD_IDLE:
6471        p_vci_tgt.cmdack  = false;
6472        break;
6473      case TGT_CMD_READ:
6474        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
6475        break;
6476      case TGT_CMD_WRITE:
6477        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
6478        break;
6479      case TGT_CMD_CAS:
6480        p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
6481        break;
6482      default:
6483        p_vci_tgt.cmdack  = false;
6484        break;
6485    }
6486
6487    ////////////////////////////////////////////////////
6488    // Response signals on the p_vci_tgt port
6489    ////////////////////////////////////////////////////
6490    switch ( r_tgt_rsp_fsm.read() ) {
6491
6492      case TGT_RSP_READ_IDLE:
6493      case TGT_RSP_WRITE_IDLE:
6494      case TGT_RSP_CAS_IDLE:
6495      case TGT_RSP_XRAM_IDLE:
6496      case TGT_RSP_INIT_IDLE:
6497      case TGT_RSP_CLEANUP_IDLE:
6498        p_vci_tgt.rspval  = false;
6499        p_vci_tgt.rsrcid  = 0;
6500        p_vci_tgt.rdata   = 0;
6501        p_vci_tgt.rpktid  = 0;
6502        p_vci_tgt.rtrdid  = 0;
6503        p_vci_tgt.rerror  = 0;
6504        p_vci_tgt.reop    = false;
6505        break;
6506      case TGT_RSP_READ:
6507        p_vci_tgt.rspval   = true;
6508        if( ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6509            && (r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1)) )
6510          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()-1].read();
6511        else if ((r_read_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6512          p_vci_tgt.rdata  = r_read_to_tgt_rsp_ll_key.read();
6513        else
6514          p_vci_tgt.rdata  = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6515        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
6516        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
6517        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
6518        p_vci_tgt.rerror   = 0;
6519        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
6520        break;
6521      case TGT_RSP_WRITE:
6522        /*if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) )
6523            {
6524              std::cout << "SC RSP / rsrcid = " << r_write_to_tgt_rsp_srcid.read() << " / rdata = " << r_write_to_tgt_rsp_sc_fail.read() << std::endl;
6525            }*/
6526        p_vci_tgt.rspval   = true;
6527        if( ((r_write_to_tgt_rsp_pktid.read() & 0x7) == TYPE_SC) && r_write_to_tgt_rsp_sc_fail.read() )
6528          p_vci_tgt.rdata  = 1;
6529        else
6530          p_vci_tgt.rdata  = 0;
6531        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
6532        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
6533        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
6534        //p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
6535        p_vci_tgt.rerror   = 0;
6536        p_vci_tgt.reop     = true;
6537        break;
6538      case TGT_RSP_CLEANUP:
6539        p_vci_tgt.rspval   = true;
6540        p_vci_tgt.rdata    = 0;
6541        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
6542        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
6543        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
6544        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
6545        p_vci_tgt.reop     = true;
6546        break;
6547      case TGT_RSP_CAS:
6548        p_vci_tgt.rspval   = true;
6549        p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
6550        p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
6551        p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
6552        p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
6553        p_vci_tgt.rerror   = 0;
6554        p_vci_tgt.reop     = true;
6555        break;
6556      case TGT_RSP_XRAM:
6557        p_vci_tgt.rspval   = true;
6558        if( ((r_xram_rsp_to_tgt_rsp_pktid.read() & 0x7) == TYPE_LL)
6559            && (r_tgt_rsp_cpt.read() == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length-1)) )
6560          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_ll_key.read();
6561        else
6562          p_vci_tgt.rdata  = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6563        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
6564        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
6565        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
6566        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
6567        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
6568              == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
6569            || r_xram_rsp_to_tgt_rsp_rerror.read());
6570        break;
6571      case TGT_RSP_INIT:
6572        p_vci_tgt.rspval   = true;
6573        p_vci_tgt.rdata    = 0; // Can be a CAS or SC rsp
6574        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
6575        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
6576        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
6577        p_vci_tgt.rerror   = 0;
6578        p_vci_tgt.reop     = true;
6579        break;
6580    } // end switch r_tgt_rsp_fsm
6581
6582    ///////////////////////////////////////////////////
6583    // Command signals on the p_vci_ini port
6584    ///////////////////////////////////////////////////
6585
6586    p_vci_ini.cmd     = vci_param::CMD_WRITE;
6587    p_vci_ini.srcid   = m_srcid_ini;
6588    p_vci_ini.cons    = true;
6589    p_vci_ini.wrap    = false;
6590    p_vci_ini.contig  = false;
6591    p_vci_ini.clen    = 0;
6592    p_vci_ini.cfixed  = false;
6593
6594    vci_addr_t vci_ini_address = 0;
6595    switch ( r_init_cmd_fsm.read() ) {
6596
6597      case INIT_CMD_UPDT_IDLE:
6598      case INIT_CMD_INVAL_IDLE:
6599      case INIT_CMD_CAS_UPDT_IDLE:
6600        p_vci_ini.cmdval  = false;
6601        p_vci_ini.address = 0;
6602        p_vci_ini.wdata   = 0;
6603        p_vci_ini.be      = 0;
6604        p_vci_ini.plen    = 0;
6605        p_vci_ini.trdid   = 0;
6606        p_vci_ini.pktid   = 0;
6607        p_vci_ini.eop     = false;
6608        break;
6609      case INIT_CMD_INVAL_NLINE:
6610      {
6611        vci_ini_address = (vci_addr_t)
6612            m_xram_rsp_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6613
6614        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
6615        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
6616          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
6617              p_vci_ini.address = (addr_t) (vci_ini_address+4);
6618          } else {
6619              p_vci_ini.address = (addr_t) (vci_ini_address);
6620          }
6621        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
6622        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6623        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6624        p_vci_ini.plen    = 4;
6625        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6626#if L1_MULTI_CACHE
6627        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
6628#endif
6629        p_vci_ini.eop     = true;
6630        break;
6631      }
6632      case INIT_CMD_XRAM_BRDCAST:
6633        p_vci_ini.cmdval  = true;
6634        p_vci_ini.address = m_broadcast_address;
6635        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6636        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6637        p_vci_ini.plen    = 4;
6638        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6639        p_vci_ini.pktid   = 0;
6640        p_vci_ini.eop     = true;
6641        break;
6642
6643      case INIT_CMD_WRITE_BRDCAST:
6644        p_vci_ini.cmdval  = true;
6645        p_vci_ini.address = m_broadcast_address;
6646        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
6647        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
6648        p_vci_ini.plen    = 4 ;
6649        p_vci_ini.eop     = true;
6650        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6651        p_vci_ini.pktid   = 0;
6652        break;
6653      case INIT_CMD_UPDT_NLINE:
6654        vci_ini_address = (vci_addr_t)
6655            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6656
6657        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
6658        if(m_write_to_init_cmd_inst_fifo.rok()){
6659          if(m_write_to_init_cmd_inst_fifo.read()) {
6660            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6661          } else {
6662            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6663          }
6664        } else {
6665          p_vci_ini.address = 0;
6666        }
6667        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
6668        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
6669        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6670        p_vci_ini.eop     = false;
6671        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6672#if L1_MULTI_CACHE
6673        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6674#endif
6675        break;
6676      case INIT_CMD_UPDT_INDEX:
6677        vci_ini_address = (vci_addr_t)
6678            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6679
6680        p_vci_ini.cmdval  = true;
6681        if(m_write_to_init_cmd_inst_fifo.read()) {
6682          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6683        } else {
6684          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6685        }
6686        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
6687        p_vci_ini.be      = 0xF;
6688        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6689        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6690#if L1_MULTI_CACHE
6691        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6692#endif
6693        p_vci_ini.eop     = false;
6694        break;
6695      case INIT_CMD_UPDT_DATA:
6696        vci_ini_address = (vci_addr_t)
6697            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6698
6699        p_vci_ini.cmdval  = true;
6700        if(m_write_to_init_cmd_inst_fifo.read()) {
6701          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6702        } else {
6703          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6704        }
6705        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
6706          r_write_to_init_cmd_index.read()].read();
6707        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
6708            r_write_to_init_cmd_index.read()].read()  ;
6709        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6710        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6711#if L1_MULTI_CACHE
6712        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6713#endif
6714        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
6715        break;
6716
6717      case INIT_CMD_CAS_BRDCAST:
6718        p_vci_ini.cmdval  = true;
6719        p_vci_ini.address = m_broadcast_address;
6720        p_vci_ini.wdata   = (addr_t)r_cas_to_init_cmd_nline.read();
6721        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32) & 0x3);
6722        p_vci_ini.plen    = 4 ;
6723        p_vci_ini.eop     = true;
6724        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6725        p_vci_ini.pktid   = 0;
6726        break;
6727      case INIT_CMD_CAS_UPDT_NLINE:
6728        vci_ini_address = (vci_addr_t)
6729            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6730
6731        p_vci_ini.cmdval  = m_cas_to_init_cmd_inst_fifo.rok();
6732        if(m_cas_to_init_cmd_inst_fifo.rok()){
6733          if( m_cas_to_init_cmd_inst_fifo.read() ) {
6734            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6735          } else {
6736            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6737          }
6738        } else {
6739          p_vci_ini.address = 0;
6740        }
6741        p_vci_ini.wdata   = (uint32_t)r_cas_to_init_cmd_nline.read();
6742        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32 ) & 0x3);
6743        if(r_cas_to_init_cmd_is_long.read()){
6744            p_vci_ini.plen    = 4 * 4;
6745        } else {
6746            p_vci_ini.plen    = 4 * 3;
6747        }
6748        p_vci_ini.eop     = false;
6749        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6750#if L1_MULTI_CACHE
6751        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6752#endif
6753        break;
6754      case INIT_CMD_CAS_UPDT_INDEX:
6755        vci_ini_address = (vci_addr_t)
6756            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6757
6758        p_vci_ini.cmdval  = true;
6759        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6760          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6761        } else {
6762          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6763        }
6764        p_vci_ini.wdata   = r_cas_to_init_cmd_index.read();
6765        p_vci_ini.be      = 0xF;
6766        if(r_cas_to_init_cmd_is_long.read()){
6767            p_vci_ini.plen    = 4 * 4;
6768        } else {
6769            p_vci_ini.plen    = 4 * 3;
6770        }
6771        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6772#if L1_MULTI_CACHE
6773        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6774#endif
6775        p_vci_ini.eop     = false;
6776        break;
6777      case INIT_CMD_CAS_UPDT_DATA:
6778        vci_ini_address = (vci_addr_t)
6779            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6780
6781        p_vci_ini.cmdval  = true;
6782        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6783          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6784        } else {
6785          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6786        }
6787        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata.read();
6788        p_vci_ini.be      = 0xF;
6789        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6790#if L1_MULTI_CACHE
6791        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6792#endif
6793        if(r_cas_to_init_cmd_is_long.read()){
6794            p_vci_ini.plen    = 4 * 4;
6795            p_vci_ini.eop     = false;
6796        } else {
6797            p_vci_ini.plen    = 4 * 3;
6798            p_vci_ini.eop     = true;
6799        }
6800        break;
6801      case INIT_CMD_CAS_UPDT_DATA_HIGH:
6802        vci_ini_address = (vci_addr_t)
6803            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6804
6805        p_vci_ini.cmdval  = true;
6806        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6807          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6808        } else {
6809          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6810        }
6811        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata_high.read();
6812        p_vci_ini.be      = 0xF;
6813        p_vci_ini.plen    = 4 * 4;
6814        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6815#if L1_MULTI_CACHE
6816        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6817#endif
6818        p_vci_ini.eop     = true;
6819        break;
6820
6821    } // end switch r_init_cmd_fsm
6822
6823    //////////////////////////////////////////////////////
6824    // Response signals on the p_vci_ini port
6825    //////////////////////////////////////////////////////
6826
6827    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
6828    else                                          p_vci_ini.rspack  = false;
6829
6830    //////////////////////////////////////////////////////
6831    // Response signals on the p_vci_tgt_cleanup port
6832    //////////////////////////////////////////////////////
6833    p_vci_tgt_cleanup.rspval = false;
6834    p_vci_tgt_cleanup.rsrcid = 0;
6835    p_vci_tgt_cleanup.rdata  = 0;
6836    p_vci_tgt_cleanup.rpktid = 0;
6837    p_vci_tgt_cleanup.rtrdid = 0;
6838    p_vci_tgt_cleanup.rerror = 0;
6839    p_vci_tgt_cleanup.reop   = false;
6840    p_vci_tgt_cleanup.cmdack = false ;
6841
6842    switch(r_cleanup_fsm.read()){
6843      case CLEANUP_IDLE:
6844        {
6845          p_vci_tgt_cleanup.cmdack = true ;
6846          break;
6847        }
6848      case CLEANUP_RSP:
6849        {
6850          /////////////////////////////////////////////////////////////////////
6851          // Returning L1 cache SET index in RDATA.
6852          // The maximum SET index width of a L1 cache must be 16 bits.
6853          p_vci_tgt_cleanup.rspval = true;
6854          p_vci_tgt_cleanup.rdata  = r_cleanup_nline.read() & 0xFFFF;
6855          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
6856          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
6857          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
6858          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
6859          p_vci_tgt_cleanup.reop   = 1;
6860          break;
6861        }
6862
6863    }
6864
6865} // end genMoore()
6866
6867}} // end name space
6868
6869// Local Variables:
6870// tab-width: 2
6871// c-basic-offset: 2
6872// c-file-offsets:((innamespace . 0)(inline-open . 0))
6873// indent-tabs-mode: nil
6874// End:
6875
6876// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
Note: See TracBrowser for help on using the repository browser.