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

Last change on this file since 288 was 284, checked in by joannou, 12 years ago

Updated of the vci trdid/rtrdid and pktid/rpktid fields for the direct network.
The pktid values are commented in the components'headers that use them.

  • In the vci_vdspin_*_wrapper components
    • added the transmission of the pktid/rpktid field
  • In the vci_cc_vcache_wrapper_v4
    • updated gen_moore() to transmit a valid pktid
    • updated transition(), RSP_FSM now checks the rpktid
  • In the vci_mem_cache_v4
    • transition(), tests originally performed on trdid now use pktid
    • gen_moore() transmit rpktid
    • !!! THE L1_MULTI_CACHE MECHANISM IS NO LONGER COMPATIBLE !!!
  • In vci_block_device_tsar_v4
    • updated gen_moore function to transmit a valid pktid

Also renamed the "SC" states in "CAS" states in the concerned FSMs on the vci_cc_vcache_wrapper_v4 and the vci_mem_cache_v4

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