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

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

Bug fix in the vci_cc_vcache_wrapper and vci_mem_cache components
(and the corresponding dspin coherence versions)

vci_cc_vcache_wrapper:

In the VCI_CMD FSM of the cc_vcache, for the SC command as for the
CAS command, we must set the CONS bit in the VCI packet. In the
same manner we must unset the CONTIG bit in the VCI packet for these
two commands.
These two kind of commands have two flits with the same VCI address.

vci_mem_cache

In the state WRITE_DIR_REQ, we don't have to rewrite the registers
address or word index because they will be assigned with the correct
values in the WRITE_IDLE or WRITE_RSP states.

  • 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.3 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 || ((r_write_count.read() == 0) && (r_write_pktid.read() == TYPE_SC)) )
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.