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

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

Introducing cache data ram with bit masking in the Memory Cache.
The goal of this modifications is the alignment of the SOCLIB model
against the VHDL one.

Due to this new property in the Cache Data of the Memory Cache,
the FSM's of this component do not need to read and then write when
doing a not full word write operation.

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