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

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

Erasing in the vci_mem_cache_v4 CLEANUP FSM the transition
between the states CLEANUP_DIR_WRITE and CLEANUP_UPT_LOCK.

If the CLEANUP FSM is in the state DIR_WRITE, is because there
is a valid entry in the Memory Cache directory for the line
concerned by the cleanup operation. Another condition to go to
the DIR_WRITE state is that the concerned line must be in counter
mode or in linked list mode with only one copy enregistered.

Therefore, once the FSM is in the DIR_WRITE state, the FSM can
do one of two things:

  • The line is in counter mode and then the only thing to do is to decrement the copies counter.
  • The line is not in counter mode and then the copies counter must be decremented and the copy enregistered in the directory must be erased.

If the cleanup operation goes into the second category, the srcid and the
type of cache (instruction or data) carried by the cleanup operation must
be equal to the srcid and type of cache stored in the Memory Cache directory.

If this is not the case, it is an error (An assert has been also introduced
in the code to detect this kind of problem).

  • 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: 240.9 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        if (not r_cleanup_is_cnt.read() and not match) {
3704            std::cout
3705              << "VCI_MEM_CACHE ERROR : Cleanup request on a valid"
3706              << "entry using linked list mode with no corresponding"
3707              << "directory or heap entry"
3708              << std::endl;
3709
3710            exit(1);
3711        }
3712
3713        // update the cache directory (for the copies)
3714        DirectoryEntry entry;
3715        entry.valid       = true;
3716        entry.is_cnt      = r_cleanup_is_cnt.read();
3717        entry.dirty       = r_cleanup_dirty.read();
3718        entry.tag         = r_cleanup_tag.read();
3719        entry.lock        = r_cleanup_lock.read();
3720        entry.ptr         = r_cleanup_ptr.read();
3721        entry.count       = r_cleanup_count.read() - 1;
3722        entry.owner.srcid = 0;
3723        entry.owner.inst  = 0;
3724#if L1_MULTI_CACHE
3725        entry.owner.cache_id = 0;
3726#endif
3727
3728        m_cache_directory.write(set, way, entry);
3729
3730        r_cleanup_fsm = CLEANUP_RSP;
3731
3732#if DEBUG_MEMC_CLEANUP
3733        if( m_debug_cleanup_fsm )
3734        {
3735          std::cout
3736            << "  <MEMC " << name()
3737            << ".CLEANUP_DIR_WRITE> Update directory:" << std::hex
3738            << " line = " << r_cleanup_nline.read() * m_words * 4
3739            << " / dir_id = " << entry.owner.srcid
3740            << " / dir_ins = " << entry.owner.inst
3741            << " / count = " << entry.count
3742            << " / is_cnt = " << entry.is_cnt << std::endl;
3743        }
3744#endif
3745
3746        break;
3747      }
3748     
3749      ///////////////////////
3750      case CLEANUP_HEAP_REQ:
3751      // Get the lock to the HEAP directory
3752      {
3753        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3754        {
3755          r_cleanup_fsm = CLEANUP_HEAP_LOCK;
3756        }
3757
3758#if DEBUG_MEMC_CLEANUP
3759        if( m_debug_cleanup_fsm )
3760        {
3761          std::cout
3762            << "  <MEMC " << name() << ".CLEANUP_HEAP_REQ> Requesting HEAP lock "
3763            << std::endl;
3764        }
3765#endif
3766        break;
3767      }
3768
3769      ///////////////////////
3770      case CLEANUP_HEAP_LOCK:
3771      // two cases are handled in this state:
3772      // - the matching copy is directly in the directory
3773      // - the matching copy is the first copy in the heap
3774      {
3775        if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CLEANUP )
3776        {
3777          size_t way              = r_cleanup_way.read();
3778          size_t set              = m_y[(vci_addr_t)(r_cleanup_nline.read()*m_words*4)];
3779          HeapEntry heap_entry    = m_heap.read(r_cleanup_ptr.read());
3780          bool last               = (heap_entry.next == r_cleanup_ptr.read());
3781          bool cleanup_inst       = r_cleanup_trdid.read() & 0x1;
3782
3783          // match_dir computation
3784          bool match_dir_srcid    = (r_cleanup_copy.read() == r_cleanup_srcid.read());
3785          bool match_dir_inst     = (r_cleanup_copy_inst.read()  == cleanup_inst);
3786          bool match_dir          = match_dir_srcid and match_dir_inst;
3787#if L1_MULTI_CACHE
3788          match_dir = match_dir and (r_cleanup_copy_cache.read() == r_cleanup_pktid.read());
3789#endif
3790
3791          // match_heap computation
3792          bool match_heap_srcid   = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3793          bool match_heap_inst    = (heap_entry.owner.inst  == cleanup_inst);
3794          bool match_heap         = match_heap_srcid and match_heap_inst;
3795#if L1_MULTI_CACHE
3796          match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3797#endif
3798
3799          r_cleanup_prev_ptr      = r_cleanup_ptr.read();
3800          r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3801#if L1_MULTI_CACHE
3802          r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3803#endif
3804          r_cleanup_prev_inst     = heap_entry.owner.inst;
3805
3806          if (match_dir)
3807          // the matching copy is registered in the directory
3808          {
3809            // the copy registered in the directory must be replaced
3810            // by the first copy registered in the heap
3811            // and the corresponding entry must be freed
3812            DirectoryEntry dir_entry;
3813            dir_entry.valid          = true;
3814            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3815            dir_entry.dirty          = r_cleanup_dirty.read();
3816            dir_entry.tag            = r_cleanup_tag.read();
3817            dir_entry.lock           = r_cleanup_lock.read();
3818            dir_entry.ptr            = heap_entry.next;
3819            dir_entry.count          = r_cleanup_count.read()-1;
3820            dir_entry.owner.srcid    = heap_entry.owner.srcid;
3821#if L1_MULTI_CACHE
3822            dir_entry.owner.cache_id = heap_entry.owner.cache_id;
3823#endif
3824            dir_entry.owner.inst     = heap_entry.owner.inst;
3825
3826            m_cache_directory.write(set,way,dir_entry);
3827
3828            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3829            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3830          }
3831          else if (match_heap)
3832          // the matching copy is the first copy in the heap
3833          {
3834            // The first copy in heap must be freed
3835            // and the copy registered in directory must point to the next copy in heap
3836            DirectoryEntry dir_entry;
3837            dir_entry.valid          = true;
3838            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3839            dir_entry.dirty          = r_cleanup_dirty.read();
3840            dir_entry.tag            = r_cleanup_tag.read();
3841            dir_entry.lock           = r_cleanup_lock.read();
3842            dir_entry.ptr            = heap_entry.next;
3843            dir_entry.count          = r_cleanup_count.read()-1;
3844            dir_entry.owner.srcid    = r_cleanup_copy.read();
3845#if L1_MULTI_CACHE
3846            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3847#endif
3848            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3849
3850            m_cache_directory.write(set,way,dir_entry);
3851
3852            r_cleanup_next_ptr       = r_cleanup_ptr.read();
3853            r_cleanup_fsm            = CLEANUP_HEAP_FREE;
3854          }
3855          else if(!last)
3856          // The matching copy is in the heap, but is not the first copy
3857          {
3858            // The directory entry must be modified to decrement count
3859            DirectoryEntry  dir_entry;
3860            dir_entry.valid          = true;
3861            dir_entry.is_cnt         = r_cleanup_is_cnt.read();
3862            dir_entry.dirty          = r_cleanup_dirty.read();
3863            dir_entry.tag            = r_cleanup_tag.read();
3864            dir_entry.lock           = r_cleanup_lock.read();
3865            dir_entry.ptr            = r_cleanup_ptr.read();
3866            dir_entry.count          = r_cleanup_count.read()-1;
3867            dir_entry.owner.srcid    = r_cleanup_copy.read();
3868#if L1_MULTI_CACHE
3869            dir_entry.owner.cache_id = r_cleanup_copy_cache.read();
3870#endif
3871            dir_entry.owner.inst     = r_cleanup_copy_inst.read();
3872
3873            m_cache_directory.write(set,way,dir_entry);
3874
3875            r_cleanup_next_ptr       = heap_entry.next;
3876            r_cleanup_fsm            = CLEANUP_HEAP_SEARCH;
3877          }
3878          else
3879          {
3880            std::cout << "VCI_MEM_CACHE ERROR " << name()
3881              << " CLEANUP_HEAP_LOCK state"
3882              << " hit but copy not found" << std::endl;
3883            exit(0);
3884          }
3885
3886#if DEBUG_MEMC_CLEANUP
3887          if( m_debug_cleanup_fsm )
3888          {
3889            std::cout
3890              << "  <MEMC " << name() << ".CLEANUP_HEAP_LOCK> Checks matching:"
3891              << " line = " << r_cleanup_nline.read() * m_words * 4
3892              << " / dir_id = " << r_cleanup_copy.read()
3893              << " / dir_ins = " << r_cleanup_copy_inst.read()
3894              << " / heap_id = " << heap_entry.owner.srcid
3895              << " / heap_ins = " << heap_entry.owner.inst
3896              << " / search_id = " << r_cleanup_srcid.read()
3897              << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3898          }
3899#endif
3900        }
3901        else
3902        {
3903          std::cout << "VCI_MEM_CACHE ERROR " << name()
3904            << " CLEANUP_HEAP_LOCK state"
3905            << " bad HEAP allocation" << std::endl;
3906
3907          exit(0);
3908        }
3909        break;
3910      }
3911
3912      /////////////////////////
3913      case CLEANUP_HEAP_SEARCH:  // This state is handling the case where the copy
3914      // is in the heap, but is not the first in the linked list
3915      {
3916        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3917        {
3918          std::cout << "VCI_MEM_CACHE ERROR " << name()
3919            << " CLEANUP_HEAP_SEARCH state"
3920            << " bad HEAP allocation" << std::endl;
3921          exit(0);
3922        }
3923
3924        HeapEntry heap_entry  = m_heap.read(r_cleanup_next_ptr.read());
3925        bool last             = (heap_entry.next == r_cleanup_next_ptr.read());
3926        bool cleanup_inst     = r_cleanup_trdid.read() & 0x1;
3927        bool match_heap_srcid = (heap_entry.owner.srcid == r_cleanup_srcid.read());
3928        bool match_heap_inst  = (heap_entry.owner.inst  == cleanup_inst);
3929        bool match_heap       = match_heap_srcid && match_heap_inst;
3930#if L1_MULTI_CACHE
3931        match_heap = match_heap and (heap_entry.owner.cache_id == r_cleanup_pktid.read());
3932#endif
3933
3934#if DEBUG_MEMC_CLEANUP
3935        if( m_debug_cleanup_fsm )
3936        {
3937          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Cheks matching:"
3938            << " line = " << r_cleanup_nline.read() * m_words * 4
3939            << " / heap_id = " << heap_entry.owner.srcid
3940            << " / heap_ins = " << heap_entry.owner.inst
3941            << " / search_id = " << r_cleanup_srcid.read()
3942            << " / search_ins = " << (r_cleanup_trdid.read()&0x1)
3943            << " / last = " << last << std::endl;
3944        }
3945#endif
3946        if(match_heap) // the matching copy must be removed
3947        {
3948          r_cleanup_ptr = heap_entry.next; // reuse ressources
3949          r_cleanup_fsm = CLEANUP_HEAP_CLEAN;
3950        }
3951        else
3952        {
3953          if ( last )
3954          {
3955            std::cout << "VCI_MEM_CACHE_ERROR " << name()
3956              << " CLEANUP_HEAP_SEARCH state"
3957              << " cleanup hit but copy not found" << std::endl;
3958            exit(0);
3959          }
3960          else // test the next in the linked list
3961          {
3962            r_cleanup_prev_ptr      = r_cleanup_next_ptr.read();
3963            r_cleanup_prev_srcid    = heap_entry.owner.srcid;
3964#if L1_MULTI_CACHE
3965            r_cleanup_prev_cache_id = heap_entry.owner.cache_id;
3966#endif
3967            r_cleanup_prev_inst     = heap_entry.owner.inst;
3968            r_cleanup_next_ptr      = heap_entry.next;
3969            r_cleanup_fsm           = CLEANUP_HEAP_SEARCH;
3970
3971#if DEBUG_MEMC_CLEANUP
3972            if( m_debug_cleanup_fsm )
3973            {
3974              std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Matching copy not found, search next:"
3975                << " line = " << r_cleanup_nline.read() * m_words * 4
3976                << " / heap_id = " << heap_entry.owner.srcid
3977                << " / heap_ins = " << heap_entry.owner.inst
3978                << " / search_id = " << r_cleanup_srcid.read()
3979                << " / search_ins = " << (r_cleanup_trdid.read()&0x1) << std::endl;
3980            }
3981#endif
3982          }
3983        }
3984        break;
3985      }
3986
3987      ////////////////////////
3988      case CLEANUP_HEAP_CLEAN:  // remove a copy in the linked list
3989      {
3990        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
3991        {
3992          std::cout << "VCI_MEM_CACHE ERROR " << name()
3993            << " CLEANUP_HEAP_CLEAN state"
3994            << "Bad HEAP allocation" << std::endl;
3995          exit(0);
3996        }
3997
3998        bool last = (r_cleanup_next_ptr.read() == r_cleanup_ptr.read());
3999        HeapEntry heap_entry;
4000        heap_entry.owner.srcid    = r_cleanup_prev_srcid.read();
4001#if L1_MULTI_CACHE
4002        heap_entry.owner.cache_id = r_cleanup_prev_cache_id.read();
4003#endif
4004        heap_entry.owner.inst     = r_cleanup_prev_inst.read();
4005       
4006        if(last) // this is the last entry of the list of copies
4007        {
4008          heap_entry.next     = r_cleanup_prev_ptr.read();
4009        }
4010        else  // this is not the last entry
4011        {
4012          heap_entry.next     = r_cleanup_ptr.read();
4013        }
4014
4015        m_heap.write(r_cleanup_prev_ptr.read(),heap_entry);
4016        r_cleanup_fsm = CLEANUP_HEAP_FREE;
4017
4018#if DEBUG_MEMC_CLEANUP
4019        if( m_debug_cleanup_fsm )
4020        {
4021          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Remove the copy in the linked list" << std::endl;
4022        }
4023#endif
4024        break;
4025      }
4026
4027      ///////////////////////
4028      case CLEANUP_HEAP_FREE:
4029      // The heap entry pointed by r_cleanup_next_ptr is freed
4030      // and becomes the head of the list of free entries
4031      {
4032        if ( r_alloc_heap_fsm.read() != ALLOC_HEAP_CLEANUP )
4033        {
4034          std::cout
4035            << "VCI_MEM_CACHE ERROR " << name()
4036            << " CLEANUP_HEAP_CLEAN state" << std::endl
4037            << "Bad HEAP allocation" << std::endl;
4038
4039          exit(0);
4040        }
4041
4042        HeapEntry heap_entry;
4043        heap_entry.owner.srcid    = 0;
4044#if L1_MULTI_CACHE
4045        heap_entry.owner.cache_id = 0;
4046#endif
4047        heap_entry.owner.inst     = false;
4048
4049        if(m_heap.is_full())
4050        {
4051          heap_entry.next = r_cleanup_next_ptr.read();
4052        }
4053        else
4054        {
4055          heap_entry.next = m_heap.next_free_ptr();
4056        }
4057
4058        m_heap.write(r_cleanup_next_ptr.read(),heap_entry);
4059        m_heap.write_free_ptr(r_cleanup_next_ptr.read());
4060        m_heap.unset_full();
4061
4062        r_cleanup_fsm = CLEANUP_RSP;
4063
4064#if DEBUG_MEMC_CLEANUP
4065        if( m_debug_cleanup_fsm )
4066        {
4067          std::cout << "  <MEMC " << name() << ".CLEANUP_HEAP_SEARCH> Update the list of free entries" << std::endl;
4068        }
4069#endif
4070        break;
4071      }
4072
4073      //////////////////////
4074      case CLEANUP_UPT_LOCK:
4075      {
4076        if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CLEANUP )
4077        {
4078          size_t index = 0;
4079          bool hit_inval;
4080          hit_inval = m_update_tab.search_inval(r_cleanup_nline.read(),index);
4081
4082          if ( !hit_inval ) // no pending inval
4083          {
4084
4085#if DEBUG_MEMC_CLEANUP
4086            if( m_debug_cleanup_fsm )
4087            {
4088              std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_LOCK> Unexpected cleanup with no corresponding UPT entry:"
4089                << " address = " << std::hex << (r_cleanup_nline.read()*4*m_words) << std::endl;
4090            }
4091#endif
4092            r_cleanup_fsm = CLEANUP_RSP;
4093          }
4094          else    // pending inval
4095          {
4096            r_cleanup_write_srcid = m_update_tab.srcid(index);
4097            r_cleanup_write_trdid = m_update_tab.trdid(index);
4098            r_cleanup_write_pktid = m_update_tab.pktid(index);
4099            r_cleanup_need_rsp    = m_update_tab.need_rsp(index);
4100            r_cleanup_fsm = CLEANUP_UPT_WRITE;
4101          }
4102          r_cleanup_index.write(index) ;
4103        }
4104        break;
4105      }
4106
4107      ///////////////////////
4108      case CLEANUP_UPT_WRITE:  // decrement response counter
4109      {
4110        size_t count = 0;
4111        m_update_tab.decrement(r_cleanup_index.read(), count);
4112        if ( count == 0 )
4113        {
4114          m_update_tab.clear(r_cleanup_index.read());
4115
4116#if DEBUG_MEMC_CLEANUP
4117          if( m_debug_cleanup_fsm )
4118          {
4119            std::cout << "  <MEMC " << name() << ".CLEANUP_UPT_WRITE> Decrement response counter in UPT:"
4120              << " UPT_index = " << r_cleanup_index.read()
4121              << " rsp_count = " << count << std::endl;
4122          }
4123#endif
4124          if( r_cleanup_need_rsp.read() ) r_cleanup_fsm = CLEANUP_WRITE_RSP ;
4125          else                      r_cleanup_fsm = CLEANUP_RSP;
4126        }
4127        else
4128        {
4129          r_cleanup_fsm = CLEANUP_RSP ;
4130        }
4131        break;
4132      }
4133
4134      ///////////////////////
4135      case CLEANUP_WRITE_RSP: // Response to a previous write on the direct network
4136      {
4137        if( !r_cleanup_to_tgt_rsp_req.read() )
4138        {
4139          r_cleanup_to_tgt_rsp_req     = true;
4140          r_cleanup_to_tgt_rsp_srcid   = r_cleanup_write_srcid.read();
4141          r_cleanup_to_tgt_rsp_trdid   = r_cleanup_write_trdid.read();
4142          r_cleanup_to_tgt_rsp_pktid   = r_cleanup_write_pktid.read();
4143          r_cleanup_fsm                = CLEANUP_RSP;
4144
4145#if DEBUG_MEMC_CLEANUP
4146          if( m_debug_cleanup_fsm )
4147          {
4148            std::cout << "  <MEMC " << name() << ".CLEANUP_WRITE_RSP> Send a response to a cleanup request:"
4149              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4150              << " / rtrdid = " << std::dec << r_cleanup_write_trdid.read() << std::endl;
4151          }
4152#endif
4153        }
4154        break;
4155      }
4156
4157      /////////////////
4158      case CLEANUP_RSP: // Response to a cleanup on the coherence network
4159      {
4160        if ( p_vci_tgt_cleanup.rspack.read() )
4161        {
4162          r_cleanup_fsm = CLEANUP_IDLE;
4163
4164#if DEBUG_MEMC_CLEANUP
4165          if( m_debug_cleanup_fsm )
4166          {
4167            std::cout << "  <MEMC " << name() << ".CLEANUP_RSP> Send the response to a cleanup request:"
4168              << " rsrcid = " << std::dec << r_cleanup_write_srcid.read()
4169              << " / rtrdid = " << r_cleanup_write_trdid.read() << std::endl;
4170          }
4171#endif
4172        }
4173        break;
4174      }
4175    } // end switch cleanup fsm
4176
4177    ////////////////////////////////////////////////////////////////////////////////////
4178    //    CAS FSM
4179    ////////////////////////////////////////////////////////////////////////////////////
4180    // The CAS FSM handles the CAS (Store Conditionnal) atomic commands,
4181    // that are handled as "compare-and-swap instructions.
4182    //
4183    // This command contains two or four flits:
4184    // - In case of 32 bits atomic access, the first flit contains the value read
4185    // by a previous LL instruction, the second flit contains the value to be writen.
4186    // - In case of 64 bits atomic access, the 2 first flits contains the value read
4187    // by a previous LL instruction, the 2 next flits contains the value to be writen.
4188    //
4189    // The target address is cachable. If it is replicated in other L1 caches
4190    // than the writer, a coherence operation is done.
4191    //
4192    // It access the directory to check hit / miss.
4193    // - In case of miss, the CAS FSM must register a GET transaction in TRT.
4194    // If a read transaction to the XRAM for this line already exists,
4195    // or if the transaction table is full, it goes to the WAIT state
4196    // to release the locks and try again. When the GET transaction has been
4197    // launched, it goes to the WAIT state and try again.
4198    // The CAS request is not consumed in the FIFO until a HIT is obtained.
4199    // - In case of hit...
4200    ///////////////////////////////////////////////////////////////////////////////////
4201
4202    switch ( r_cas_fsm.read() )
4203    {
4204        /////////////
4205        case CAS_IDLE:     // fill the local rdata buffers
4206        {
4207            if( m_cmd_cas_addr_fifo.rok() )
4208            {
4209
4210#if DEBUG_MEMC_CAS
4211if( m_debug_cas_fsm )
4212{
4213    std::cout << "  <MEMC " << name() << ".CAS_IDLE> CAS command: " << std::hex
4214              << " srcid = " <<  std::dec << m_cmd_cas_srcid_fifo.read()
4215              << " addr = " << std::hex << m_cmd_cas_addr_fifo.read()
4216              << " wdata = " << m_cmd_cas_wdata_fifo.read()
4217              << " eop = " << std::dec << m_cmd_cas_eop_fifo.read()
4218              << " cpt  = " << std::dec << r_cas_cpt.read() << std::endl;
4219}
4220#endif
4221                if( m_cmd_cas_eop_fifo.read() )
4222                {
4223                    m_cpt_cas++;
4224                    r_cas_fsm = CAS_DIR_REQ;
4225                }
4226                else  // we keep the last word in the FIFO
4227                {
4228                    cmd_cas_fifo_get = true;
4229                }
4230                // We fill the two buffers
4231                if ( r_cas_cpt.read() < 2 ) // 32 bits access
4232                    r_cas_rdata[r_cas_cpt.read()] = m_cmd_cas_wdata_fifo.read();
4233
4234                if((r_cas_cpt.read() == 1) && m_cmd_cas_eop_fifo.read())
4235                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4236
4237                if( r_cas_cpt.read()>3 ) // more than 4 flits...
4238                {
4239                    std::cout << "VCI_MEM_CACHE ERROR in CAS_IDLE state : illegal CAS command"
4240                              << std::endl;
4241                    exit(0);
4242                }
4243
4244                if ( r_cas_cpt.read()==2 )
4245                    r_cas_wdata = m_cmd_cas_wdata_fifo.read();
4246
4247                r_cas_cpt = r_cas_cpt.read()+1;
4248            }
4249            break;
4250        }
4251       
4252        /////////////////
4253        case CAS_DIR_REQ:
4254        {
4255            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4256            {
4257              r_cas_fsm = CAS_DIR_LOCK;
4258            }
4259
4260#if DEBUG_MEMC_CAS
4261            if( m_debug_cas_fsm )
4262            {
4263              std::cout
4264                << "  <MEMC " << name() << ".CAS_DIR_REQ> Requesting DIR lock "
4265                << std::endl;
4266            }
4267#endif
4268            break;
4269        }
4270
4271        /////////////////
4272        case CAS_DIR_LOCK:  // Read the directory
4273        {
4274            if( r_alloc_dir_fsm.read() == ALLOC_DIR_CAS )
4275            {
4276                size_t way = 0;
4277                DirectoryEntry entry(m_cache_directory.read(m_cmd_cas_addr_fifo.read(), way));
4278
4279                r_cas_is_cnt     = entry.is_cnt;
4280                r_cas_dirty      = entry.dirty;
4281                r_cas_tag        = entry.tag;
4282                r_cas_way        = way;
4283                r_cas_copy       = entry.owner.srcid;
4284#if L1_MULTI_CACHE
4285                r_cas_copy_cache = entry.owner.cache_id;
4286#endif
4287                r_cas_copy_inst  = entry.owner.inst;
4288                r_cas_ptr        = entry.ptr;
4289                r_cas_count      = entry.count;
4290
4291                if ( entry.valid )  r_cas_fsm = CAS_DIR_HIT_READ;
4292                else          r_cas_fsm = CAS_MISS_TRT_LOCK;
4293
4294#if DEBUG_MEMC_CAS
4295if( m_debug_cas_fsm )
4296{
4297    std::cout << "  <MEMC " << name() << ".CAS_DIR_LOCK> Directory acces"
4298              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4299              << " / hit = " << std::dec << entry.valid
4300              << " / count = " << entry.count
4301              << " / is_cnt = " << entry.is_cnt << std::endl;
4302}
4303#endif
4304            }
4305            else
4306            {
4307              std::cout
4308                << "VCI_MEM_CACHE ERROR " << name()
4309                << " CAS_DIR_LOCK state" << std::endl
4310                << "Bad DIR allocation"   << std::endl;
4311
4312              exit(0);
4313            }
4314
4315            break;
4316        }
4317        /////////////////////
4318        case CAS_DIR_HIT_READ:  // update directory for lock and dirty bit
4319                               // and check data change in cache
4320        {
4321            size_t way  = r_cas_way.read();
4322            size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4323            size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4324
4325            // update directory (lock & dirty bits)
4326            DirectoryEntry entry;
4327            entry.valid          = true;
4328            entry.is_cnt         = r_cas_is_cnt.read();
4329            entry.dirty          = true;
4330            entry.lock           = true;
4331            entry.tag          = r_cas_tag.read();
4332            entry.owner.srcid    = r_cas_copy.read();
4333#if L1_MULTI_CACHE
4334            entry.owner.cache_id = r_cas_copy_cache.read();
4335#endif
4336            entry.owner.inst     = r_cas_copy_inst.read();
4337            entry.count          = r_cas_count.read();
4338            entry.ptr            = r_cas_ptr.read();
4339
4340            m_cache_directory.write(set, way, entry);
4341
4342            // read data in cache & check data change
4343            bool ok = ( r_cas_rdata[0].read() == m_cache_data.read(way, set, word) );
4344            if ( r_cas_cpt.read()==4 )  // 64 bits CAS
4345                ok &= ( r_cas_rdata[1] == m_cache_data.read(way, set, word+1));
4346
4347            // to avoid livelock, force the atomic access to fail pseudo-randomly
4348            bool forced_fail = ( (r_cas_lfsr % (64) == 0) && RANDOMIZE_CAS );
4349            r_cas_lfsr = (r_cas_lfsr >> 1) ^ ((-(r_cas_lfsr & 1)) & 0xd0000001);
4350
4351            if( ok and not forced_fail )  // no data change
4352            {
4353                r_cas_fsm = CAS_DIR_HIT_WRITE;
4354            }
4355            else                            // return failure
4356            {
4357                r_cas_fsm = CAS_RSP_FAIL;
4358            }
4359
4360#if DEBUG_MEMC_CAS
4361if( m_debug_cas_fsm )
4362{
4363    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_READ> Test if CAS success:"
4364              << " / expected value = " << r_cas_rdata[0].read()
4365              << " / actual value = " << m_cache_data.read(way, set, word)
4366              << " / forced_fail = " << forced_fail << std::endl;
4367}
4368#endif
4369            break;
4370        }
4371        //////////////////////
4372        case CAS_DIR_HIT_WRITE:    // test if a CC transaction is required
4373                                    // write data in cache if no CC request
4374        {
4375            // test coherence request
4376            if(r_cas_count.read())   // replicated line
4377            {
4378                if ( r_cas_is_cnt.read() )
4379                {
4380                    r_cas_fsm = CAS_BC_TRT_LOCK;    // broadcast invalidate required
4381                }
4382                else if( !r_cas_to_init_cmd_multi_req.read() &&
4383                         !r_cas_to_init_cmd_brdcast_req.read()  )
4384                {
4385                    r_cas_fsm = CAS_UPT_LOCK;     // multi update required
4386                }
4387                else
4388                {
4389                    r_cas_fsm = CAS_WAIT;
4390                }
4391            }
4392            else                    // no copies
4393            {
4394                size_t way  = r_cas_way.read();
4395                size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4396                size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4397
4398                // cache update
4399                m_cache_data.write(way, set, word, r_cas_wdata.read());
4400                if(r_cas_cpt.read()==4)
4401                    m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4402
4403                // monitor
4404                if ( m_monitor_ok )
4405                {
4406                    vci_addr_t address = m_cmd_cas_addr_fifo.read();
4407                char buf[80];
4408                snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4409                    check_monitor( buf, address, r_cas_wdata.read() );
4410                    if ( r_cas_cpt.read()==4 )
4411                    check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4412                }
4413                r_cas_fsm = CAS_RSP_SUCCESS;
4414
4415#if DEBUG_MEMC_CAS
4416if( m_debug_cas_fsm )
4417{
4418    std::cout << "  <MEMC " << name() << ".CAS_DIR_HIT_WRITE> Update cache:"
4419              << " way = " << std::dec << way
4420              << " / set = " << set
4421              << " / word = " << word
4422              << " / value = " << r_cas_wdata.read()
4423              << " / count = " << r_cas_count.read() << std::endl;
4424}
4425#endif
4426            }
4427            break;
4428        }
4429        /////////////////
4430        case CAS_UPT_LOCK:  // try to register the transaction in UPT
4431                           // and write data in cache if successful registration
4432                           // releases locks to retry later if UPT full
4433        {
4434            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4435            {
4436                bool        wok        = false;
4437                size_t      index      = 0;
4438                size_t      srcid      = m_cmd_cas_srcid_fifo.read();
4439                size_t      trdid      = m_cmd_cas_trdid_fifo.read();
4440                size_t      pktid      = m_cmd_cas_pktid_fifo.read();
4441                addr_t      nline      = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4442                size_t      nb_copies  = r_cas_count.read();
4443
4444                wok = m_update_tab.set(true,  // it's an update transaction
4445                                       false,   // it's not a broadcast
4446                                       true,    // it needs a response
4447                                       srcid,
4448                                       trdid,
4449                                       pktid,
4450                                       nline,
4451                                       nb_copies,
4452                                       index);
4453                if (wok)  // coherence transaction registered in UPT
4454                {
4455                    // cache update
4456                    size_t way  = r_cas_way.read();
4457                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4458                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4459
4460                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4461                    if(r_cas_cpt.read()==4)
4462                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4463
4464                    // monitor
4465                    if ( m_monitor_ok )
4466                    {
4467                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4468                    char buf[80];
4469                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4470                        check_monitor( buf, address, r_cas_wdata.read() );
4471                        if ( r_cas_cpt.read()==4 )
4472                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4473                    }
4474
4475                    r_cas_upt_index = index;
4476                    r_cas_fsm = CAS_UPT_HEAP_LOCK;
4477                }
4478                else       //  releases the locks protecting UPT and DIR UPT full
4479                {
4480                    r_cas_fsm = CAS_WAIT;
4481                }
4482
4483#if DEBUG_MEMC_CAS
4484if( m_debug_cas_fsm )
4485{
4486    std::cout << "  <MEMC " << name() << ".CAS_UPT_LOCK> Register multi-update transaction in UPT"
4487              << " / wok = " << wok
4488              << " / nline  = " << std::hex << nline
4489              << " / count = " << nb_copies << std::endl;
4490}
4491#endif
4492            }
4493            break;
4494        }
4495        /////////////
4496        case CAS_WAIT:   // release all locks and retry from beginning
4497        {
4498
4499#if DEBUG_MEMC_CAS
4500if( m_debug_cas_fsm )
4501{
4502    std::cout << "  <MEMC " << name() << ".CAS_WAIT> Release all locks" << std::endl;
4503}
4504#endif
4505            r_cas_fsm = CAS_DIR_REQ;
4506            break;
4507        }
4508        //////////////////
4509        case CAS_UPT_HEAP_LOCK:  // lock the heap
4510        {
4511            if( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS )
4512            {
4513
4514#if DEBUG_MEMC_CAS
4515if( m_debug_cas_fsm )
4516{
4517    std::cout << "  <MEMC " << name() << ".CAS_UPT_HEAP_LOCK> Get access to the heap" << std::endl;
4518}
4519#endif
4520                r_cas_fsm = CAS_UPT_REQ;
4521            }
4522            break;
4523        }
4524        ////////////////
4525        case CAS_UPT_REQ:  // send a first update request to INIT_CMD FSM
4526        {
4527            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS) and
4528                   "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4529
4530            if( !r_cas_to_init_cmd_multi_req.read() && !r_cas_to_init_cmd_brdcast_req.read() )
4531            {
4532                r_cas_to_init_cmd_brdcast_req  = false;
4533                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4534                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4535                r_cas_to_init_cmd_index        = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4536                r_cas_to_init_cmd_wdata        = r_cas_wdata.read();
4537
4538                if(r_cas_cpt.read() == 4)
4539                {
4540                    r_cas_to_init_cmd_is_long    = true;
4541                    r_cas_to_init_cmd_wdata_high = m_cmd_cas_wdata_fifo.read();
4542                }
4543                else
4544                {
4545                    r_cas_to_init_cmd_is_long    = false;
4546                    r_cas_to_init_cmd_wdata_high = 0;
4547                }
4548
4549                // We put the first copy in the fifo
4550                cas_to_init_cmd_fifo_put     = true;
4551                cas_to_init_cmd_fifo_inst    = r_cas_copy_inst.read();
4552                cas_to_init_cmd_fifo_srcid   = r_cas_copy.read();
4553#if L1_MULTI_CACHE
4554                cas_to_init_cmd_fifo_cache_id= r_cas_copy_cache.read();
4555#endif
4556                if(r_cas_count.read() == 1) // one single copy
4557                {
4558                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4559                                            // update responses
4560                    cmd_cas_fifo_get            = true;
4561                    r_cas_to_init_cmd_multi_req = true;
4562                    r_cas_cpt = 0;
4563                }
4564                else      // several copies
4565                {
4566                    r_cas_fsm = CAS_UPT_NEXT;
4567                }
4568
4569#if DEBUG_MEMC_CAS
4570if( m_debug_cas_fsm )
4571{
4572    std::cout << "  <MEMC " << name() << ".CAS_UPT_REQ> Send the first update request to INIT_CMD FSM "
4573              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4574              << " / wdata = " << std::hex << r_cas_wdata.read()
4575              << " / srcid = " << std::dec << r_cas_copy.read()
4576              << " / inst = " << std::dec << r_cas_copy_inst.read() << std::endl;
4577}
4578#endif
4579            }
4580            break;
4581        }
4582        /////////////////
4583        case CAS_UPT_NEXT:     // send a multi-update request to INIT_CMD FSM
4584        {
4585            assert((r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS)
4586                 and "VCI_MEM_CACHE ERROR : bad HEAP allocation");
4587
4588            HeapEntry entry = m_heap.read(r_cas_ptr.read());
4589            cas_to_init_cmd_fifo_srcid    = entry.owner.srcid;
4590#if L1_MULTI_CACHE
4591            cas_to_init_cmd_fifo_cache_id = entry.owner.cache_id;
4592#endif
4593            cas_to_init_cmd_fifo_inst     = entry.owner.inst;
4594            cas_to_init_cmd_fifo_put = true;
4595
4596            if( m_cas_to_init_cmd_inst_fifo.wok() ) // request accepted by INIT_CMD FSM
4597            {
4598                r_cas_ptr = entry.next;
4599                if( entry.next == r_cas_ptr.read() )  // last copy
4600                {
4601                    r_cas_to_init_cmd_multi_req = true;
4602                    r_cas_fsm = CAS_IDLE;   // Response will be sent after receiving
4603                                            // all update responses
4604                    cmd_cas_fifo_get = true;
4605                    r_cas_cpt        = 0;
4606                }
4607            }
4608
4609#if DEBUG_MEMC_CAS
4610if( m_debug_cas_fsm )
4611{
4612    std::cout << "  <MEMC " << name() << ".CAS_UPT_NEXT> Send the next update request to INIT_CMD FSM "
4613              << " / address = " << std::hex << m_cmd_cas_addr_fifo.read()
4614              << " / wdata = " << std::hex << r_cas_wdata.read()
4615              << " / srcid = " << std::dec << entry.owner.srcid
4616              << " / inst = " << std::dec << entry.owner.inst << std::endl;
4617}
4618#endif
4619            break;
4620        }
4621        /////////////////////
4622        case CAS_BC_TRT_LOCK:      // check the TRT to register a PUT transaction
4623        {
4624            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4625            {
4626                if( !r_cas_to_ixr_cmd_req )  // we can transfer the request to IXR_CMD FSM
4627                {
4628                    // fill the data buffer
4629                    size_t way  = r_cas_way.read();
4630                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4631                        size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4632                    for(size_t i = 0; i<m_words; i++)
4633                    {
4634                        if (i == word)
4635                        {
4636                            r_cas_to_ixr_cmd_data[i] = r_cas_wdata.read();
4637                        }
4638                        else if ( (i == word+1) && (r_cas_cpt.read()==4) ) // 64 bit CAS
4639                        {
4640                            r_cas_to_ixr_cmd_data[i] = m_cmd_cas_wdata_fifo.read();
4641                        }
4642                        else
4643                        {
4644                            r_cas_to_ixr_cmd_data[i] = m_cache_data.read(way, set, i);
4645                        }
4646                    }
4647                    size_t wok_index = 0;
4648                    bool   wok       = !m_transaction_tab.full(wok_index);
4649                    if ( wok )
4650                    {
4651                        r_cas_trt_index = wok_index;
4652                        r_cas_fsm       = CAS_BC_UPT_LOCK;
4653                    }
4654                    else
4655                    {
4656                        r_cas_fsm       = CAS_WAIT;
4657                    }
4658                }
4659                else
4660                {
4661                    r_cas_fsm = CAS_WAIT;
4662                }
4663            }
4664            break;
4665        }
4666        ///////////////////
4667        case CAS_BC_UPT_LOCK:  // register a broadcast inval transaction in UPT
4668                              // write data in cache in case of successful registration
4669        {
4670            if ( r_alloc_upt_fsm.read() == ALLOC_UPT_CAS )
4671            {
4672                bool        wok       = false;
4673                size_t      index     = 0;
4674                size_t      srcid     = m_cmd_cas_srcid_fifo.read();
4675                size_t      trdid     = m_cmd_cas_trdid_fifo.read();
4676                size_t      pktid     = m_cmd_cas_pktid_fifo.read();
4677                addr_t      nline     = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4678                size_t      nb_copies = r_cas_count.read();
4679
4680                // register a broadcast inval transaction in UPT
4681                wok = m_update_tab.set(false, // it's an inval transaction
4682                                       true,    // it's a broadcast
4683                                       true,    // it needs a response
4684                                       srcid,
4685                                       trdid,
4686                                       pktid,
4687                                       nline,
4688                                       nb_copies,
4689                                       index);
4690
4691                if ( wok )  // UPT not full
4692                {
4693                    // cache update
4694                    size_t way  = r_cas_way.read();
4695                    size_t set  = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4696                    size_t word = m_x[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4697
4698                    m_cache_data.write(way, set, word, r_cas_wdata.read());
4699                    if(r_cas_cpt.read()==4)
4700                        m_cache_data.write(way, set, word+1, m_cmd_cas_wdata_fifo.read());
4701
4702                    // monitor
4703                    if ( m_monitor_ok )
4704                    {
4705                        vci_addr_t address = m_cmd_cas_addr_fifo.read();
4706                    char buf[80];
4707                    snprintf(buf, 80, "CAS_DIR_HIT_WRITE srcid %d", m_cmd_cas_srcid_fifo.read());
4708                        check_monitor( buf, address, r_cas_wdata.read() );
4709                        if ( r_cas_cpt.read()==4 )
4710                        check_monitor( buf, address+4, m_cmd_cas_wdata_fifo.read() );
4711                    }
4712                    r_cas_upt_index = index;
4713                    r_cas_fsm = CAS_BC_DIR_INVAL;
4714#if DEBUG_MEMC_CAS
4715if( m_debug_cas_fsm )
4716{
4717    std::cout << "  <MEMC " << name() << ".CAS_BC_UPT_LOCK> Register a broadcast inval transaction in UPT"
4718              << " / nline = " << nline
4719              << " / count = " << nb_copies
4720              << " / upt_index = " << index << std::endl;
4721}
4722#endif
4723                }
4724                else      //  releases the lock protecting UPT
4725                {
4726                     r_cas_fsm = CAS_WAIT;
4727                }
4728            }
4729            break;
4730        }
4731        //////////////////
4732        case CAS_BC_DIR_INVAL:  // Register the PUT transaction in TRT, and inval the DIR entry
4733        {
4734            if ( (r_alloc_trt_fsm.read() == ALLOC_TRT_CAS ) &&
4735                 (r_alloc_upt_fsm.read() == ALLOC_UPT_CAS ) &&
4736                 (r_alloc_dir_fsm.read() == ALLOC_DIR_CAS ))
4737            {
4738                // set TRT
4739                m_transaction_tab.set(r_cas_trt_index.read(),
4740                                      false,    // PUT request to XRAM
4741                                      m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())],
4742                                      0,
4743                                      0,
4744                                      0,
4745                                      false,    // not a processor read
4746                                      0,
4747                                      0,
4748                                      std::vector<be_t>(m_words,0),
4749                                      std::vector<data_t>(m_words,0));
4750
4751                // invalidate directory entry
4752                DirectoryEntry entry;
4753                entry.valid         = false;
4754                entry.dirty         = false;
4755                entry.tag         = 0;
4756                entry.is_cnt        = false;
4757                entry.lock          = false;
4758                entry.count         = 0;
4759                entry.owner.srcid   = 0;
4760#if L1_MULTI_CACHE
4761                entry.owner.cache_id= 0;
4762#endif
4763                entry.owner.inst    = false;
4764                entry.ptr           = 0;
4765                size_t set          = m_y[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4766                size_t way          = r_cas_way.read();
4767                m_cache_directory.write(set, way, entry);
4768
4769                r_cas_fsm = CAS_BC_CC_SEND;
4770
4771#if DEBUG_MEMC_CAS
4772if( m_debug_cas_fsm )
4773{
4774    std::cout << "  <MEMC " << name() << ".CAS_BC_DIR_INVAL> Register the PUT in TRT and invalidate DIR entry"
4775              << " / nline = " << std::hex << m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())]
4776              << " / set = " << std::dec << set << " / way = " << way << std::endl;
4777}
4778#endif
4779            }
4780            else
4781            {
4782                assert(false and "LOCK ERROR in CAS_FSM, STATE = CAS_BC_DIR_INVAL");
4783            }
4784            break;
4785        }
4786        ///////////////////
4787        case CAS_BC_CC_SEND:  // Request the broadcast inval to INIT_CMD FSM
4788        {
4789            if ( !r_cas_to_init_cmd_multi_req.read() &&
4790                 !r_cas_to_init_cmd_brdcast_req.read())
4791            {
4792                r_cas_to_init_cmd_multi_req    = false;
4793                r_cas_to_init_cmd_brdcast_req  = true;
4794                r_cas_to_init_cmd_trdid        = r_cas_upt_index.read();
4795                r_cas_to_init_cmd_nline        = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4796                r_cas_to_init_cmd_index        = 0;
4797                r_cas_to_init_cmd_wdata        = 0;
4798
4799                r_cas_fsm = CAS_BC_XRAM_REQ;
4800            }
4801            break;
4802        }
4803        ////////////////////
4804        case CAS_BC_XRAM_REQ: // request the IXR FSM to start a put transaction
4805        {
4806            if ( !r_cas_to_ixr_cmd_req )
4807            {
4808                r_cas_to_ixr_cmd_req     = true;
4809                r_cas_to_ixr_cmd_write   = true;
4810                r_cas_to_ixr_cmd_nline   = m_nline[(vci_addr_t)(m_cmd_cas_addr_fifo.read())];
4811                r_cas_to_ixr_cmd_trdid   = r_cas_trt_index.read();
4812                r_cas_fsm                = CAS_IDLE;
4813                cmd_cas_fifo_get         = true;
4814                r_cas_cpt                = 0;
4815
4816#if DEBUG_MEMC_CAS
4817if( m_debug_cas_fsm )
4818{
4819    std::cout << "  <MEMC " << name() << ".CAS_BC_XRAM_REQ> Request a PUT transaction to IXR_CMD FSM" << std::hex
4820              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
4821              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
4822}
4823#endif
4824            }
4825            else
4826            {
4827               std::cout << "MEM_CACHE, CAS_BC_XRAM_REQ state : request should not have been previously set"
4828                         << std::endl;
4829            }
4830            break;
4831        }
4832        /////////////////
4833        case CAS_RSP_FAIL:  // request TGT_RSP FSM to send a failure response
4834        {
4835            if( !r_cas_to_tgt_rsp_req )
4836            {
4837                cmd_cas_fifo_get     = true;
4838                r_cas_cpt              = 0;
4839                r_cas_to_tgt_rsp_req = true;
4840                r_cas_to_tgt_rsp_data  = 1;
4841                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4842                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4843                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4844                r_cas_fsm              = CAS_IDLE;
4845
4846#if DEBUG_MEMC_CAS
4847if( m_debug_cas_fsm )
4848{
4849    std::cout << "  <MEMC " << name() << ".CAS_RSP_FAIL> Request TGT_RSP to send a failure response" << std::endl;
4850}
4851#endif
4852            }
4853            break;
4854        }
4855        ////////////////////
4856        case CAS_RSP_SUCCESS:  // request TGT_RSP FSM to send a success response
4857        {
4858            if( !r_cas_to_tgt_rsp_req )
4859            {
4860                cmd_cas_fifo_get       = true;
4861                r_cas_cpt              = 0;
4862                r_cas_to_tgt_rsp_req = true;
4863                r_cas_to_tgt_rsp_data  = 0;
4864                r_cas_to_tgt_rsp_srcid = m_cmd_cas_srcid_fifo.read();
4865                r_cas_to_tgt_rsp_trdid = m_cmd_cas_trdid_fifo.read();
4866                r_cas_to_tgt_rsp_pktid = m_cmd_cas_pktid_fifo.read();
4867                r_cas_fsm              = CAS_IDLE;
4868
4869#if DEBUG_MEMC_CAS
4870if( m_debug_cas_fsm )
4871{
4872    std::cout << "  <MEMC " << name() << ".CAS_RSP_SUCCESS> Request TGT_RSP to send a success response" << std::endl;
4873}
4874#endif
4875            }
4876            break;
4877        }
4878        /////////////////////
4879        case CAS_MISS_TRT_LOCK:         // cache miss : request access to transaction Table
4880        {
4881            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4882            {
4883                size_t   index = 0;
4884                bool hit_read = m_transaction_tab.hit_read(
4885                                  m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],index);
4886                bool hit_write = m_transaction_tab.hit_write(
4887                                   m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]);
4888                bool wok = !m_transaction_tab.full(index);
4889
4890#if DEBUG_MEMC_CAS
4891if( m_debug_cas_fsm )
4892{
4893    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_LOCK> Check TRT state"
4894              << " / hit_read = "  << hit_read
4895              << " / hit_write = " << hit_write
4896              << " / wok = " << wok
4897              << " / index = " << index << std::endl;
4898}
4899#endif
4900
4901                if ( hit_read || !wok || hit_write ) // missing line already requested or no space in TRT
4902                {
4903                    r_cas_fsm = CAS_WAIT;
4904                }
4905                else
4906                {
4907                    r_cas_trt_index = index;
4908                    r_cas_fsm       = CAS_MISS_TRT_SET;
4909                }
4910            }
4911            break;
4912        }
4913        ////////////////////
4914        case CAS_MISS_TRT_SET: // register the GET transaction in TRT
4915        {
4916            if( r_alloc_trt_fsm.read() == ALLOC_TRT_CAS )
4917            {
4918                std::vector<be_t> be_vector;
4919                std::vector<data_t> data_vector;
4920                be_vector.clear();
4921                data_vector.clear();
4922                for ( size_t i=0; i<m_words; i++ )
4923                {
4924                    be_vector.push_back(0);
4925                    data_vector.push_back(0);
4926                }
4927
4928                m_transaction_tab.set(r_cas_trt_index.read(),
4929                                      true,   // read request
4930                                      m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()],
4931                                      m_cmd_cas_srcid_fifo.read(),
4932                                      m_cmd_cas_trdid_fifo.read(),
4933                                      m_cmd_cas_pktid_fifo.read(),
4934                                      false,    // write request from processor
4935                                      0,
4936                                      0,
4937                                      be_vector,
4938                                      data_vector);
4939                r_cas_fsm = CAS_MISS_XRAM_REQ;
4940
4941#if DEBUG_MEMC_CAS
4942if( m_debug_cas_fsm )
4943{
4944    std::cout << "  <MEMC " << name() << ".CAS_MISS_TRT_SET> Register a GET transaction in TRT" << std::hex
4945              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
4946              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
4947}
4948#endif
4949            }
4950            break;
4951        }
4952        //////////////////////
4953        case CAS_MISS_XRAM_REQ:  // request the IXR_CMD FSM to fetch the missing line
4954        {
4955            if ( !r_cas_to_ixr_cmd_req )
4956            {
4957                r_cas_to_ixr_cmd_req        = true;
4958                r_cas_to_ixr_cmd_write      = false;
4959                r_cas_to_ixr_cmd_trdid      = r_cas_trt_index.read();
4960                r_cas_to_ixr_cmd_nline      = m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()];
4961                r_cas_fsm                   = CAS_WAIT;
4962
4963#if DEBUG_MEMC_CAS
4964if( m_debug_cas_fsm )
4965{
4966    std::cout << "  <MEMC " << name() << ".CAS_MISS_XRAM_REQ> Request a GET transaction to IXR_CMD FSM" << std::hex
4967              << " / nline = " << m_nline[(vci_addr_t)m_cmd_cas_addr_fifo.read()]
4968              << " / trt_index = " << r_cas_trt_index.read() << std::endl;
4969}
4970#endif
4971            }
4972            break;
4973        }
4974    } // end switch r_cas_fsm
4975
4976
4977    //////////////////////////////////////////////////////////////////////////////
4978    //    INIT_CMD FSM
4979    //////////////////////////////////////////////////////////////////////////////
4980    // The INIT_CMD fsm controls the VCI CMD initiator port on the coherence
4981    // network, used to update or invalidate cache lines in L1 caches.
4982    //
4983    // It implements a round-robin priority between the three possible client FSMs
4984    // XRAM_RSP, WRITE and CAS. Each FSM can request two types of services:
4985    // - r_xram_rsp_to_init_cmd_multi_req : multi-inval
4986    //   r_xram_rsp_to_init_cmd_brdcast_req : broadcast-inval
4987    // - r_write_to_init_cmd_multi_req : multi-update
4988    //   r_write_to_init_cmd_brdcast_req : broadcast-inval
4989    // - r_cas_to_init_cmd_multi_req : multi-update
4990    //   r_cas_to_init_cmd_brdcast_req : broadcast-inval
4991    //
4992    // An inval request is a single cell VCI write command containing the
4993    // index of the line to be invalidated.
4994    // An update request is a multi-cells VCI write command : The first cell
4995    // contains the index of the cache line to be updated. The second cell contains
4996    // the index of the first modified word in the line. The following cells
4997    // contain the data.
4998    ///////////////////////////////////////////////////////////////////////////////
4999
5000    switch ( r_init_cmd_fsm.read() )
5001    {
5002        ////////////////////////
5003        case INIT_CMD_UPDT_IDLE:  // XRAM_RSP FSM has highest priority
5004        {
5005            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5006                 r_xram_rsp_to_init_cmd_multi_req.read()  )
5007            {
5008                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5009                m_cpt_inval++;
5010            }
5011            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5012            {
5013                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5014                m_cpt_inval++;
5015            }
5016            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5017                      r_write_to_init_cmd_multi_req.read() )
5018            {
5019                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5020                m_cpt_update++;
5021            }
5022            else if ( r_write_to_init_cmd_brdcast_req.read() )
5023            {
5024                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5025                m_cpt_inval++;
5026            }
5027            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5028                      r_cas_to_init_cmd_multi_req.read()  )
5029            {
5030                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5031                m_cpt_update++;
5032            }
5033            else if( r_cas_to_init_cmd_brdcast_req.read() )
5034            {
5035                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5036                m_cpt_inval++;
5037            }
5038            break;
5039        }
5040        /////////////////////////
5041        case INIT_CMD_INVAL_IDLE: // WRITE FSM has highest priority
5042        {
5043            if ( m_write_to_init_cmd_inst_fifo.rok() ||
5044                 r_write_to_init_cmd_multi_req.read() )
5045            {
5046                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5047                m_cpt_update++;
5048            }
5049            else if ( r_write_to_init_cmd_brdcast_req.read() )
5050            {
5051                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5052                m_cpt_inval++;
5053            }
5054            else if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5055                      r_cas_to_init_cmd_multi_req.read()  )
5056            {
5057                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5058                m_cpt_update++;
5059            }
5060            else if( r_cas_to_init_cmd_brdcast_req.read() )
5061            {
5062                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5063                m_cpt_inval++;
5064            }
5065            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5066                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5067            {
5068                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5069                m_cpt_inval++;
5070            }
5071            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5072            {
5073                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5074                m_cpt_inval++;
5075            }
5076            break;
5077        }
5078        //////////////////////////
5079        case INIT_CMD_CAS_UPDT_IDLE: // CAS FSM has highest priority
5080        {
5081            if ( m_cas_to_init_cmd_inst_fifo.rok() ||
5082                 r_cas_to_init_cmd_multi_req.read()  )
5083            {
5084                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5085                m_cpt_update++;
5086            }
5087            else if( r_cas_to_init_cmd_brdcast_req.read() )
5088            {
5089                r_init_cmd_fsm = INIT_CMD_CAS_BRDCAST;
5090                m_cpt_inval++;
5091            }
5092            else if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() ||
5093                      r_xram_rsp_to_init_cmd_multi_req.read()  )
5094            {
5095                r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5096                m_cpt_inval++;
5097            }
5098            else if ( r_xram_rsp_to_init_cmd_brdcast_req.read() )
5099            {
5100                r_init_cmd_fsm = INIT_CMD_XRAM_BRDCAST;
5101                m_cpt_inval++;
5102            }
5103            else if ( m_write_to_init_cmd_inst_fifo.rok() ||
5104                      r_write_to_init_cmd_multi_req.read() )
5105            {
5106                r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5107                m_cpt_update++;
5108            }
5109            else if ( r_write_to_init_cmd_brdcast_req.read() )
5110            {
5111                r_init_cmd_fsm = INIT_CMD_WRITE_BRDCAST;
5112                m_cpt_inval++;
5113            }
5114            break;
5115        }
5116        //////////////////////////
5117        case INIT_CMD_INVAL_NLINE:  // send a multi-inval (from XRAM_RSP)
5118        {
5119            if ( m_xram_rsp_to_init_cmd_inst_fifo.rok() )
5120            {
5121                if ( p_vci_ini.cmdack )
5122                {
5123                    m_cpt_inval_mult++;
5124                    r_init_cmd_fsm = INIT_CMD_INVAL_NLINE;
5125                    xram_rsp_to_init_cmd_fifo_get = true;
5126                }
5127            }
5128            else
5129            {
5130                if( r_xram_rsp_to_init_cmd_multi_req.read() ) r_xram_rsp_to_init_cmd_multi_req = false;
5131                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5132            }
5133            break;
5134        }
5135        ///////////////////////////
5136        case INIT_CMD_XRAM_BRDCAST: // send a broadcast-inval (from XRAM_RSP)
5137        {
5138            if ( p_vci_ini.cmdack )
5139            {
5140                m_cpt_inval_brdcast++;
5141                r_init_cmd_fsm = INIT_CMD_INVAL_IDLE;
5142                r_xram_rsp_to_init_cmd_brdcast_req = false;
5143            }
5144            break;
5145        }
5146        ////////////////////////////
5147        case INIT_CMD_WRITE_BRDCAST:  // send a broadcast-inval (from WRITE FSM)
5148        {
5149            if( p_vci_ini.cmdack )
5150            {
5151
5152#if DEBUG_MEMC_INIT_CMD
5153if( m_debug_init_cmd_fsm )
5154{
5155    std::cout << "  <MEMC " << name() << ".INIT_CMD_WRITE_BRDCAST> Broadcast-Inval for line "
5156              << r_write_to_init_cmd_nline.read() << std::endl;
5157}
5158#endif
5159                m_cpt_inval_brdcast++;
5160                r_write_to_init_cmd_brdcast_req = false;
5161                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5162            }
5163            break;
5164        }
5165        /////////////////////////
5166        case INIT_CMD_UPDT_NLINE:  // send nline for a multi-update (from WRITE FSM)
5167        {
5168            if ( m_write_to_init_cmd_inst_fifo.rok() )
5169            {
5170                if ( p_vci_ini.cmdack )
5171                {
5172                    m_cpt_update_mult++;
5173                    r_init_cmd_fsm = INIT_CMD_UPDT_INDEX;
5174                    // write_to_init_cmd_fifo_get = true;
5175                }
5176            }
5177            else
5178            {
5179                if ( r_write_to_init_cmd_multi_req.read() ) r_write_to_init_cmd_multi_req = false;
5180                r_init_cmd_fsm = INIT_CMD_UPDT_IDLE;
5181            }
5182            break;
5183        }
5184        /////////////////////////
5185        case INIT_CMD_UPDT_INDEX:  // send word index for a multi-update (from WRITE FSM)
5186        {
5187            r_init_cmd_cpt    = 0;
5188            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_UPDT_DATA;
5189            break;
5190        }
5191        ////////////////////////
5192        case INIT_CMD_UPDT_DATA:  // send the data for a multi-update (from WRITE FSM)
5193        {
5194            if ( p_vci_ini.cmdack )
5195            {
5196                if ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) )
5197                {
5198                    r_init_cmd_fsm = INIT_CMD_UPDT_NLINE;
5199                    write_to_init_cmd_fifo_get = true;
5200                }
5201                else
5202                {
5203                    r_init_cmd_cpt = r_init_cmd_cpt.read() + 1;
5204                }
5205            }
5206            break;
5207        }
5208        /////////////////////////
5209        case INIT_CMD_CAS_BRDCAST: // send a broadcast-inval (from CAS FSM)
5210        {
5211            if( p_vci_ini.cmdack )
5212            {
5213                m_cpt_inval_brdcast++;
5214                r_cas_to_init_cmd_brdcast_req = false;
5215                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5216            }
5217            break;
5218        }
5219        ////////////////////////////
5220        case INIT_CMD_CAS_UPDT_NLINE:   // send nline for a multi-update (from CAS FSM)
5221        {
5222            if ( m_cas_to_init_cmd_inst_fifo.rok() )
5223            {
5224                if ( p_vci_ini.cmdack )
5225                {
5226                    m_cpt_update_mult++;
5227                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_INDEX;
5228                }
5229            }
5230            else
5231            {
5232                if( r_cas_to_init_cmd_multi_req.read() ) r_cas_to_init_cmd_multi_req = false;
5233                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_IDLE;
5234            }
5235            break;
5236        }
5237        ////////////////////////////
5238        case INIT_CMD_CAS_UPDT_INDEX:  // send word index for a multi-update (from CAS FSM)
5239        {
5240            if ( p_vci_ini.cmdack )  r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA;
5241            break;
5242        }
5243        ///////////////////////////
5244        case INIT_CMD_CAS_UPDT_DATA:  // send first data for a multi-update (from CAS FSM)
5245        {
5246            if ( p_vci_ini.cmdack )
5247            {
5248                if ( r_cas_to_init_cmd_is_long.read() )
5249                {
5250                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_DATA_HIGH;
5251                }
5252                else
5253                {
5254                    cas_to_init_cmd_fifo_get = true;
5255                    r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5256                }
5257            }
5258            break;
5259        }
5260        ////////////////////////
5261        case INIT_CMD_CAS_UPDT_DATA_HIGH:  // send second data for a multi-update (from CAS FSM)
5262        {
5263            if ( p_vci_ini.cmdack )
5264            {
5265                cas_to_init_cmd_fifo_get = true;
5266                r_init_cmd_fsm = INIT_CMD_CAS_UPDT_NLINE;
5267            }
5268            break;
5269        }
5270    } // end switch r_init_cmd_fsm
5271
5272    /////////////////////////////////////////////////////////////////////
5273    //    TGT_RSP FSM
5274    /////////////////////////////////////////////////////////////////////
5275    // The TGT_RSP fsm sends the responses on the VCI target port
5276    // with a round robin priority between six requests :
5277    // - r_read_to_tgt_rsp_req
5278    // - r_write_to_tgt_rsp_req
5279    // - r_cas_to_tgt_rsp_req
5280    // - r_cleanup_to_tgt_rsp_req
5281    // - r_xram_rsp_to_tgt_rsp_req
5282    // - r_init_rsp_to_tgt_rsp_req
5283    // The  ordering is :  read > write > cas > xram > init > cleanup
5284    /////////////////////////////////////////////////////////////////////
5285
5286    switch ( r_tgt_rsp_fsm.read() )
5287    {
5288        ///////////////////////
5289        case TGT_RSP_READ_IDLE:   // write requests have the highest priority
5290        {
5291          if      ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5292          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5293          else if ( r_xram_rsp_to_tgt_rsp_req )
5294          {
5295            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5296            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5297          }
5298          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5299          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5300          else if ( r_read_to_tgt_rsp_req     )
5301          {
5302            r_tgt_rsp_fsm = TGT_RSP_READ;
5303            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5304          }
5305          break;
5306        }
5307        ////////////////////////
5308        case TGT_RSP_WRITE_IDLE:  // cas requests have the highest priority
5309        {
5310          if      ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS;
5311          else if ( r_xram_rsp_to_tgt_rsp_req )
5312          {
5313            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5314            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5315          }
5316          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5317          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5318          else if ( r_read_to_tgt_rsp_req     )
5319          {
5320            r_tgt_rsp_fsm = TGT_RSP_READ;
5321            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5322          }
5323
5324          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5325          break;
5326        }
5327        ///////////////////////
5328        case TGT_RSP_CAS_IDLE:   // xram_rsp requests have the highest priority
5329        {
5330          if ( r_xram_rsp_to_tgt_rsp_req )
5331          {
5332            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5333            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5334          }
5335          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5336          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5337          else if ( r_read_to_tgt_rsp_req     )
5338          {
5339            r_tgt_rsp_fsm = TGT_RSP_READ;
5340            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5341          }
5342          else if ( r_write_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5343          else if ( r_cas_to_tgt_rsp_req   ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5344          break;
5345        }
5346        ///////////////////////
5347        case TGT_RSP_XRAM_IDLE:   // init requests have the highest priority
5348        {
5349
5350          if      ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5351          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5352          else if ( r_read_to_tgt_rsp_req     )
5353          {
5354            r_tgt_rsp_fsm = TGT_RSP_READ;
5355            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5356          }
5357          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5358          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5359          else if ( r_xram_rsp_to_tgt_rsp_req )
5360          {
5361            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5362            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5363          }
5364          break;
5365        }
5366        ///////////////////////
5367        case TGT_RSP_INIT_IDLE:   // cleanup requests have the highest priority
5368        {
5369          if      ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5370          else if ( r_read_to_tgt_rsp_req     )
5371          {
5372            r_tgt_rsp_fsm = TGT_RSP_READ;
5373            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5374          }
5375          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5376          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5377          else if ( r_xram_rsp_to_tgt_rsp_req )
5378          {
5379            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5380            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5381          }
5382          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT;
5383          break;
5384        }
5385        ///////////////////////
5386        case TGT_RSP_CLEANUP_IDLE:    // read requests have the highest priority
5387        {
5388          if      ( r_read_to_tgt_rsp_req     )
5389          {
5390            r_tgt_rsp_fsm = TGT_RSP_READ;
5391            r_tgt_rsp_cpt = r_read_to_tgt_rsp_word.read();
5392          }
5393          else if ( r_write_to_tgt_rsp_req    ) r_tgt_rsp_fsm = TGT_RSP_WRITE;
5394          else if ( r_cas_to_tgt_rsp_req      ) r_tgt_rsp_fsm = TGT_RSP_CAS  ;
5395          else if ( r_xram_rsp_to_tgt_rsp_req )
5396          {
5397            r_tgt_rsp_fsm = TGT_RSP_XRAM;
5398            r_tgt_rsp_cpt = r_xram_rsp_to_tgt_rsp_word.read();
5399          }
5400          else if ( r_init_rsp_to_tgt_rsp_req ) r_tgt_rsp_fsm = TGT_RSP_INIT   ;
5401          else if ( r_cleanup_to_tgt_rsp_req  ) r_tgt_rsp_fsm = TGT_RSP_CLEANUP;
5402          break;
5403        }
5404        //////////////////
5405        case TGT_RSP_READ:    // send the response to a read
5406        {
5407            if ( p_vci_tgt.rspack )
5408            {
5409
5410#if DEBUG_MEMC_TGT_RSP
5411if( m_debug_tgt_rsp_fsm )
5412{
5413    std::cout << "  <MEMC " << name() << ".TGT_RSP_READ> Read response"
5414              << " / rsrcid = " << std::dec << r_read_to_tgt_rsp_srcid.read()
5415              << " / rtrdid = " << r_read_to_tgt_rsp_trdid.read()
5416              << " / rpktid = " << r_read_to_tgt_rsp_pktid.read()
5417              << " / rdata = " << std::hex << r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5418              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5419}
5420#endif
5421                if ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) )
5422                {
5423                    r_tgt_rsp_fsm = TGT_RSP_READ_IDLE;
5424                    r_read_to_tgt_rsp_req = false;
5425                }
5426                else
5427                {
5428                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5429                }
5430            }
5431            break;
5432        }
5433        ///////////////////
5434        case TGT_RSP_WRITE:   // send the write acknowledge
5435        {
5436            if ( p_vci_tgt.rspack )
5437            {
5438
5439#if DEBUG_MEMC_TGT_RSP
5440if( m_debug_tgt_rsp_fsm )
5441{
5442    std::cout << "  <MEMC " << name() << ".TGT_RSP_WRITE> Write response"
5443              << " / rsrcid = " << std::dec << r_write_to_tgt_rsp_srcid.read()
5444              << " / rtrdid = " << r_write_to_tgt_rsp_trdid.read()
5445              << " / rpktid = " << r_write_to_tgt_rsp_pktid.read() << std::endl;
5446}
5447#endif
5448                r_tgt_rsp_fsm = TGT_RSP_WRITE_IDLE;
5449                r_write_to_tgt_rsp_req = false;
5450            }
5451            break;
5452        }
5453        ///////////////////
5454        case TGT_RSP_CLEANUP:   // pas clair pour moi (AG)
5455        {
5456            if ( p_vci_tgt.rspack )
5457            {
5458
5459#if DEBUG_MEMC_TGT_RSP
5460if( m_debug_tgt_rsp_fsm )
5461{
5462    std::cout << "  <MEMC " << name() << ".TGT_RSP_CLEANUP> Cleanup response"
5463              << " / rsrcid = " << std::dec << r_cleanup_to_tgt_rsp_srcid.read()
5464              << " / rtrdid = " << r_cleanup_to_tgt_rsp_trdid.read()
5465              << " / rpktid = " << r_cleanup_to_tgt_rsp_pktid.read() << std::endl;
5466}
5467#endif
5468                r_tgt_rsp_fsm = TGT_RSP_CLEANUP_IDLE;
5469                r_cleanup_to_tgt_rsp_req = false;
5470            }
5471            break;
5472        }
5473        //////////////////
5474        case TGT_RSP_CAS:    // send one atomic word response
5475        {
5476            if ( p_vci_tgt.rspack )
5477            {
5478
5479#if DEBUG_MEMC_TGT_RSP
5480if( m_debug_tgt_rsp_fsm )
5481{
5482    std::cout << "  <MEMC " << name() << ".TGT_RSP_CAS> CAS response"
5483              << " / rsrcid = " << std::dec << r_cas_to_tgt_rsp_srcid.read()
5484              << " / rtrdid = " << r_cas_to_tgt_rsp_trdid.read()
5485              << " / rpktid = " << r_cas_to_tgt_rsp_pktid.read() << std::endl;
5486}
5487#endif
5488                r_tgt_rsp_fsm = TGT_RSP_CAS_IDLE;
5489                r_cas_to_tgt_rsp_req = false;
5490            }
5491            break;
5492        }
5493
5494        ///////////////////////
5495        case TGT_RSP_XRAM:    // send the response after XRAM access
5496        {
5497            if ( p_vci_tgt.rspack )
5498            {
5499
5500#if DEBUG_MEMC_TGT_RSP
5501if( m_debug_tgt_rsp_fsm )
5502{
5503    std::cout << "  <MEMC " << name() << ".TGT_RSP_XRAM> Response following XRAM access"
5504              << " / rsrcid = " << std::dec << r_xram_rsp_to_tgt_rsp_srcid.read()
5505              << " / rtrdid = " << r_xram_rsp_to_tgt_rsp_trdid.read()
5506              << " / rpktid = " << r_xram_rsp_to_tgt_rsp_pktid.read()
5507              << " / rdata = " << std::hex << r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read()
5508              << " / cpt = " << std::dec << r_tgt_rsp_cpt.read() << std::endl;
5509}
5510#endif
5511                if ( (r_tgt_rsp_cpt.read() ==
5512                     (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
5513                   || r_xram_rsp_to_tgt_rsp_rerror.read() )
5514                {
5515                    r_tgt_rsp_fsm = TGT_RSP_XRAM_IDLE;
5516                    r_xram_rsp_to_tgt_rsp_req = false;
5517                }
5518                else
5519                {
5520                    r_tgt_rsp_cpt = r_tgt_rsp_cpt.read() + 1;
5521                }
5522            }
5523            break;
5524        }
5525        //////////////////
5526        case TGT_RSP_INIT:    // send the write response after coherence transaction
5527        {
5528            if ( p_vci_tgt.rspack )
5529            {
5530
5531#if DEBUG_MEMC_TGT_RSP
5532if( m_debug_tgt_rsp_fsm )
5533{
5534    std::cout << "  <MEMC " << name() << ".TGT_RSP_INIT> Write response after coherence transaction"
5535              << " / rsrcid = " << std::dec << r_init_rsp_to_tgt_rsp_srcid.read()
5536              << " / rtrdid = " << r_init_rsp_to_tgt_rsp_trdid.read()
5537              << " / rpktid = " << r_init_rsp_to_tgt_rsp_pktid.read() << std::endl;
5538}
5539#endif
5540                r_tgt_rsp_fsm = TGT_RSP_INIT_IDLE;
5541                r_init_rsp_to_tgt_rsp_req = false;
5542            }
5543            break;
5544        }
5545    } // end switch tgt_rsp_fsm
5546
5547    ////////////////////////////////////////////////////////////////////////////////////
5548    //    ALLOC_UPT FSM
5549    ////////////////////////////////////////////////////////////////////////////////////
5550    // The ALLOC_UPT FSM allocates the access to the Update/Inval Table (UPT).
5551    // with a round robin priority between three FSMs : INIT_RSP > WRITE > XRAM_RSP > CLEANUP
5552    // - The WRITE FSM initiates update transactions and sets  new entry in UPT.
5553    // - The XRAM_RSP FSM initiates inval transactions and sets  new entry in UPT.
5554    // - The INIT_RSP FSM complete those trasactions and erase the UPT entry.
5555    // - The CLEANUP  FSM decrement an entry in UPT.
5556    // The resource is always allocated.
5557    /////////////////////////////////////////////////////////////////////////////////////
5558
5559    switch ( r_alloc_upt_fsm.read() )
5560    {
5561
5562      ////////////////////////
5563      case ALLOC_UPT_INIT_RSP:
5564        if (( r_init_rsp_fsm.read() != INIT_RSP_UPT_LOCK  ) &&
5565            ( r_init_rsp_fsm.read() != INIT_RSP_UPT_CLEAR ))
5566        {
5567          if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5568              ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5569            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5570
5571          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5572            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5573
5574          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5575            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5576
5577          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5578                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5579            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5580        }
5581        break;
5582
5583        /////////////////////
5584      case ALLOC_UPT_WRITE:
5585        if (( r_write_fsm.read() != WRITE_UPT_LOCK    ) &&
5586            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK ))
5587        {
5588          if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5589            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5590
5591          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5592            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5593
5594          else if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5595                   ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5596            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5597
5598          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5599            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5600        }
5601        break;
5602
5603        ////////////////////////
5604      case ALLOC_UPT_XRAM_RSP:
5605        if (r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK)
5606        {
5607          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          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    )   ||
5618                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5619            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5620        }
5621        break;
5622
5623        //////////////////////////
5624      case ALLOC_UPT_CLEANUP:
5625        if(r_cleanup_fsm.read() != CLEANUP_UPT_LOCK )
5626        {
5627          if (( r_cas_fsm.read() == CAS_UPT_LOCK    ) ||
5628              ( r_cas_fsm.read() == CAS_BC_UPT_LOCK ))
5629            r_alloc_upt_fsm = ALLOC_UPT_CAS;
5630
5631          else if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5632            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5633
5634          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5635                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5636            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5637
5638          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5639            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5640        }
5641        break;
5642
5643        //////////////////////////
5644      case ALLOC_UPT_CAS:
5645        if (( r_cas_fsm.read() != CAS_UPT_LOCK    ) &&
5646            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK ))
5647        {
5648          if ( r_init_rsp_fsm.read() == INIT_RSP_UPT_LOCK )
5649            r_alloc_upt_fsm = ALLOC_UPT_INIT_RSP;
5650
5651          else if (( r_write_fsm.read() == WRITE_UPT_LOCK    ) ||
5652                   ( r_write_fsm.read() == WRITE_BC_UPT_LOCK ))
5653            r_alloc_upt_fsm = ALLOC_UPT_WRITE;
5654
5655          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_INVAL_LOCK )
5656            r_alloc_upt_fsm = ALLOC_UPT_XRAM_RSP;
5657
5658          else if ( r_cleanup_fsm.read() == CLEANUP_UPT_LOCK )
5659            r_alloc_upt_fsm = ALLOC_UPT_CLEANUP;
5660        }
5661        break;
5662
5663    } // end switch r_alloc_upt_fsm
5664
5665    ////////////////////////////////////////////////////////////////////////////////////
5666    //    ALLOC_DIR FSM
5667    ////////////////////////////////////////////////////////////////////////////////////
5668    // The ALLOC_DIR FSM allocates the access to the directory and
5669    // the data cache with a round robin priority between 5 user FSMs :
5670    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
5671    // The ressource is always allocated.
5672    /////////////////////////////////////////////////////////////////////////////////////
5673
5674    switch ( r_alloc_dir_fsm.read() )
5675    {
5676      case ALLOC_DIR_RESET:
5677        // Initializes the directory one SET each cycle. All the WAYS of a SET are
5678        // initialize in parallel
5679
5680        r_alloc_dir_reset_cpt.write(r_alloc_dir_reset_cpt.read() + 1);
5681
5682        if (r_alloc_dir_reset_cpt.read() == (m_sets - 1)) {
5683          m_cache_directory.init();
5684
5685          r_alloc_dir_fsm = ALLOC_DIR_READ;
5686        }
5687        break;
5688
5689      ////////////////////
5690      case ALLOC_DIR_READ:
5691        if ((( r_read_fsm.read()       != READ_DIR_REQ    )   &&
5692             ( r_read_fsm.read()       != READ_DIR_LOCK   )   &&
5693             ( r_read_fsm.read()       != READ_TRT_LOCK   )   &&
5694             ( r_read_fsm.read()       != READ_HEAP_REQ   ))
5695            ||
5696            (( r_read_fsm.read()       == READ_TRT_LOCK   )   &&
5697             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_READ  )))
5698        {
5699          if (r_write_fsm.read() == WRITE_DIR_REQ)
5700            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5701
5702          else if (r_cas_fsm.read() == CAS_DIR_REQ)
5703            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5704
5705          else if (r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5706            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5707
5708          else if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
5709            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5710        }
5711        break;
5712
5713        /////////////////////
5714      case ALLOC_DIR_WRITE:
5715        if ((( r_write_fsm.read()      != WRITE_DIR_REQ       )  &&
5716             ( r_write_fsm.read()      != WRITE_DIR_LOCK      )  &&
5717             ( r_write_fsm.read()      != WRITE_DIR_READ      )  &&
5718             ( r_write_fsm.read()      != WRITE_DIR_HIT       )  &&
5719             ( r_write_fsm.read()      != WRITE_BC_TRT_LOCK   )  &&
5720             ( r_write_fsm.read()      != WRITE_BC_UPT_LOCK   )  &&
5721             ( r_write_fsm.read()      != WRITE_MISS_TRT_LOCK )  &&
5722             ( r_write_fsm.read()      != WRITE_UPT_LOCK      )  &&
5723             ( r_write_fsm.read()      != WRITE_UPT_HEAP_LOCK ))
5724            ||
5725            (( r_write_fsm.read()      == WRITE_UPT_HEAP_LOCK )  &&
5726             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_WRITE    ))
5727            ||
5728            (( r_write_fsm.read()      == WRITE_MISS_TRT_LOCK )  &&
5729             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_WRITE     )))
5730        {
5731          if ( r_cas_fsm.read() == CAS_DIR_REQ )
5732            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5733
5734          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5735            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5736
5737          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5738            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5739
5740          else if ( r_read_fsm.read() == READ_DIR_REQ )
5741            r_alloc_dir_fsm = ALLOC_DIR_READ;
5742        }
5743        break;
5744
5745        ////////////////////
5746        case ALLOC_DIR_CAS:
5747        if ((( r_cas_fsm.read()        != CAS_DIR_REQ       )  &&
5748             ( r_cas_fsm.read()        != CAS_DIR_LOCK      )  &&
5749             ( r_cas_fsm.read()        != CAS_DIR_HIT_READ  )  &&
5750             ( r_cas_fsm.read()        != CAS_DIR_HIT_WRITE )  &&
5751             ( r_cas_fsm.read()        != CAS_BC_TRT_LOCK   )  &&
5752             ( r_cas_fsm.read()        != CAS_BC_UPT_LOCK   )  &&
5753             ( r_cas_fsm.read()        != CAS_MISS_TRT_LOCK )  &&
5754             ( r_cas_fsm.read()        != CAS_UPT_LOCK      )  &&
5755             ( r_cas_fsm.read()        != CAS_UPT_HEAP_LOCK ))
5756            ||
5757            (( r_cas_fsm.read()        == CAS_UPT_HEAP_LOCK )  &&
5758             ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CAS    ))
5759            ||
5760            (( r_cas_fsm.read()        == CAS_MISS_TRT_LOCK )  &&
5761             ( r_alloc_trt_fsm.read()  == ALLOC_TRT_CAS     )))
5762        {
5763          if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5764            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5765
5766          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5767            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5768
5769          else if ( r_read_fsm.read() == READ_DIR_REQ )
5770            r_alloc_dir_fsm = ALLOC_DIR_READ;
5771
5772          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5773            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5774        }
5775        break;
5776
5777        ///////////////////////
5778        case ALLOC_DIR_CLEANUP:
5779        if (( r_cleanup_fsm.read() != CLEANUP_DIR_REQ   ) &&
5780            ( r_cleanup_fsm.read() != CLEANUP_DIR_LOCK  ) &&
5781            ( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ  ) &&
5782            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK ))
5783        {
5784          if ( r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK )
5785            r_alloc_dir_fsm = ALLOC_DIR_XRAM_RSP;
5786
5787          else if ( r_read_fsm.read() == READ_DIR_REQ )
5788            r_alloc_dir_fsm = ALLOC_DIR_READ;
5789
5790          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5791            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5792
5793          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5794            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5795        }
5796        break;
5797
5798        ////////////////////////
5799        case ALLOC_DIR_XRAM_RSP:
5800        if (( r_xram_rsp_fsm.read() != XRAM_RSP_DIR_LOCK   ) &&
5801            ( r_xram_rsp_fsm.read() != XRAM_RSP_TRT_COPY   ) &&
5802            ( r_xram_rsp_fsm.read() != XRAM_RSP_INVAL_LOCK ))
5803        {
5804          if ( r_read_fsm.read() == READ_DIR_REQ )
5805            r_alloc_dir_fsm = ALLOC_DIR_READ;
5806
5807          else if ( r_write_fsm.read() == WRITE_DIR_REQ )
5808            r_alloc_dir_fsm = ALLOC_DIR_WRITE;
5809
5810          else if ( r_cas_fsm.read() == CAS_DIR_REQ )
5811            r_alloc_dir_fsm = ALLOC_DIR_CAS;
5812
5813          else if ( r_cleanup_fsm.read() == CLEANUP_DIR_REQ )
5814            r_alloc_dir_fsm = ALLOC_DIR_CLEANUP;
5815        }
5816        break;
5817
5818    } // end switch alloc_dir_fsm
5819
5820    ////////////////////////////////////////////////////////////////////////////////////
5821    //    ALLOC_TRT FSM
5822    ////////////////////////////////////////////////////////////////////////////////////
5823    // The ALLOC_TRT fsm allocates the access to the Transaction Table (write buffer)
5824    // with a round robin priority between 4 user FSMs :
5825    // The cyclic priority is READ > WRITE > CAS > XRAM_RSP
5826    // The ressource is always allocated.
5827    ///////////////////////////////////////////////////////////////////////////////////
5828
5829    switch ( r_alloc_trt_fsm.read() )
5830    {
5831      ////////////////////
5832      case ALLOC_TRT_READ:
5833        if ( r_read_fsm.read() != READ_TRT_LOCK )
5834        {
5835          if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5836              ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5837            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5838
5839          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5840                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5841            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5842
5843          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5844                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5845            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5846
5847          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5848                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5849            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5850        }
5851        break;
5852
5853      /////////////////////
5854      case ALLOC_TRT_WRITE:
5855        if (( r_write_fsm.read() != WRITE_MISS_TRT_LOCK ) &&
5856            ( r_write_fsm.read() != WRITE_BC_TRT_LOCK   ) &&
5857            ( r_write_fsm.read() != WRITE_BC_UPT_LOCK   ))
5858        {
5859          if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5860              ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5861            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5862
5863          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5864                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5865            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5866
5867          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5868                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5869            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5870
5871          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5872            r_alloc_trt_fsm = ALLOC_TRT_READ;
5873        }
5874        break;
5875
5876      ////////////////////
5877      case ALLOC_TRT_CAS:
5878        if (( r_cas_fsm.read() != CAS_MISS_TRT_LOCK ) &&
5879            ( r_cas_fsm.read() != CAS_BC_TRT_LOCK   ) &&
5880            ( r_cas_fsm.read() != CAS_BC_UPT_LOCK   ))
5881        {
5882          if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5883              ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5884            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5885
5886          else if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5887                   ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5888            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5889
5890          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5891            r_alloc_trt_fsm = ALLOC_TRT_READ;
5892
5893          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5894                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5895            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5896        }
5897        break;
5898
5899      ////////////////////////
5900      case ALLOC_TRT_XRAM_RSP:
5901        if ((( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_LOCK   )  ||
5902             ( r_alloc_dir_fsm.read() != ALLOC_DIR_XRAM_RSP  )) &&
5903             ( r_xram_rsp_fsm.read()  != XRAM_RSP_TRT_COPY   )  &&
5904             ( r_xram_rsp_fsm.read()  != XRAM_RSP_DIR_UPDT   )  &&
5905             ( r_xram_rsp_fsm.read()  != XRAM_RSP_INVAL_LOCK ))
5906        {
5907          if (( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_ERASE ) ||
5908              ( r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ  ))
5909            r_alloc_trt_fsm = ALLOC_TRT_IXR_RSP;
5910
5911          else if ( r_read_fsm.read() == READ_TRT_LOCK )
5912            r_alloc_trt_fsm = ALLOC_TRT_READ;
5913
5914          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5915                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5916            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5917
5918          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5919                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5920            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5921        }
5922        break;
5923
5924      ////////////////////////
5925      case ALLOC_TRT_IXR_RSP:
5926        if (( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_ERASE ) &&
5927            ( r_ixr_rsp_fsm.read() != IXR_RSP_TRT_READ  ))
5928        {
5929          if ( r_read_fsm.read() == READ_TRT_LOCK )
5930            r_alloc_trt_fsm = ALLOC_TRT_READ;
5931
5932          else if (( r_write_fsm.read() == WRITE_MISS_TRT_LOCK ) ||
5933                   ( r_write_fsm.read() == WRITE_BC_TRT_LOCK   ))
5934            r_alloc_trt_fsm = ALLOC_TRT_WRITE;
5935
5936          else if (( r_cas_fsm.read() == CAS_MISS_TRT_LOCK ) ||
5937                   ( r_cas_fsm.read() == CAS_BC_TRT_LOCK   ))
5938            r_alloc_trt_fsm = ALLOC_TRT_CAS;
5939
5940          else if (( r_xram_rsp_fsm.read()  == XRAM_RSP_DIR_LOCK  ) &&
5941                   ( r_alloc_dir_fsm.read() == ALLOC_DIR_XRAM_RSP ))
5942            r_alloc_trt_fsm = ALLOC_TRT_XRAM_RSP;
5943        }
5944        break;
5945
5946    } // end switch alloc_trt_fsm
5947
5948    ////////////////////////////////////////////////////////////////////////////////////
5949    //    ALLOC_HEAP FSM
5950    ////////////////////////////////////////////////////////////////////////////////////
5951    // The ALLOC_HEAP FSM allocates the access to the heap
5952    // with a round robin priority between 5 user FSMs :
5953    // The cyclic ordering is READ > WRITE > CAS > CLEANUP > XRAM_RSP
5954    // The ressource is always allocated.
5955    /////////////////////////////////////////////////////////////////////////////////////
5956
5957    switch ( r_alloc_heap_fsm.read() )
5958    {
5959        ////////////////////
5960        case ALLOC_HEAP_RESET:
5961          // Initializes the heap one ENTRY each cycle.
5962
5963          r_alloc_heap_reset_cpt.write(r_alloc_heap_reset_cpt.read() + 1);
5964
5965          if(r_alloc_heap_reset_cpt.read() == (m_heap_size-1)) {
5966            m_heap.init();
5967
5968            r_alloc_heap_fsm = ALLOC_HEAP_READ;
5969          }
5970          break;
5971
5972        ////////////////////
5973        case ALLOC_HEAP_READ:
5974        if (( r_read_fsm.read() != READ_HEAP_REQ   ) &&
5975            ( r_read_fsm.read() != READ_HEAP_LOCK  ) &&
5976            ( r_read_fsm.read() != READ_HEAP_ERASE ))
5977        {
5978          if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
5979            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
5980
5981          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
5982            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
5983
5984          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
5985            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
5986
5987          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
5988            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
5989        }
5990        break;
5991
5992        /////////////////////
5993        case ALLOC_HEAP_WRITE:
5994        if (( r_write_fsm.read() != WRITE_UPT_HEAP_LOCK ) &&
5995            ( r_write_fsm.read() != WRITE_UPT_REQ       ) &&
5996            ( r_write_fsm.read() != WRITE_UPT_NEXT      ))
5997        {
5998          if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
5999            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6000
6001          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6002            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6003
6004          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6005            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6006
6007          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6008            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6009        }
6010        break;
6011
6012        ////////////////////
6013        case ALLOC_HEAP_CAS:
6014        if (( r_cas_fsm.read() != CAS_UPT_HEAP_LOCK ) &&
6015            ( r_cas_fsm.read() != CAS_UPT_REQ       ) &&
6016            ( r_cas_fsm.read() != CAS_UPT_NEXT      ))
6017        {
6018          if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6019            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6020
6021          else if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6022            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6023
6024          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6025            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6026
6027          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6028            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6029        }
6030        break;
6031
6032        ///////////////////////
6033        case ALLOC_HEAP_CLEANUP:
6034        if (( r_cleanup_fsm.read() != CLEANUP_HEAP_REQ    ) &&
6035            ( r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK   ) &&
6036            ( r_cleanup_fsm.read() != CLEANUP_HEAP_SEARCH ) &&
6037            ( r_cleanup_fsm.read() != CLEANUP_HEAP_CLEAN  ))
6038        {
6039          if ( r_xram_rsp_fsm.read() == XRAM_RSP_HEAP_REQ )
6040            r_alloc_heap_fsm = ALLOC_HEAP_XRAM_RSP;
6041
6042          else if ( r_read_fsm.read() == READ_HEAP_REQ )
6043            r_alloc_heap_fsm = ALLOC_HEAP_READ;
6044
6045          else if ( r_write_fsm.read() == WRITE_UPT_HEAP_LOCK )
6046            r_alloc_heap_fsm = ALLOC_HEAP_WRITE;
6047
6048          else if ( r_cas_fsm.read() == CAS_UPT_HEAP_LOCK )
6049            r_alloc_heap_fsm = ALLOC_HEAP_CAS;
6050        }
6051        break;
6052
6053        ////////////////////////
6054        case ALLOC_HEAP_XRAM_RSP:
6055        if (( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_REQ   ) &&
6056            ( r_xram_rsp_fsm.read() != XRAM_RSP_HEAP_ERASE ))
6057        {
6058          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          else if ( r_cleanup_fsm.read() == CLEANUP_HEAP_REQ )
6068            r_alloc_heap_fsm = ALLOC_HEAP_CLEANUP;
6069
6070        }
6071        break;
6072
6073    } // end switch alloc_heap_fsm
6074
6075
6076    ////////////////////////////////////////////////////////////////////////////////////
6077    //    TGT_CMD to READ FIFO
6078    ////////////////////////////////////////////////////////////////////////////////////
6079
6080    if ( cmd_read_fifo_put ) {
6081      if ( cmd_read_fifo_get ) {
6082        m_cmd_read_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6083        m_cmd_read_length_fifo.put_and_get(p_vci_tgt.plen.read()>>2);
6084        m_cmd_read_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6085        m_cmd_read_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6086        m_cmd_read_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6087      } else {
6088        m_cmd_read_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6089        m_cmd_read_length_fifo.simple_put(p_vci_tgt.plen.read()>>2);
6090        m_cmd_read_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6091        m_cmd_read_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6092        m_cmd_read_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6093      }
6094    } else {
6095      if ( cmd_read_fifo_get ) {
6096        m_cmd_read_addr_fifo.simple_get();
6097        m_cmd_read_length_fifo.simple_get();
6098        m_cmd_read_srcid_fifo.simple_get();
6099        m_cmd_read_trdid_fifo.simple_get();
6100        m_cmd_read_pktid_fifo.simple_get();
6101      }
6102    }
6103    /////////////////////////////////////////////////////////////////////
6104    //    TGT_CMD to WRITE FIFO
6105    /////////////////////////////////////////////////////////////////////
6106
6107    if ( cmd_write_fifo_put ) {
6108      if ( cmd_write_fifo_get ) {
6109        m_cmd_write_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6110        m_cmd_write_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6111        m_cmd_write_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6112        m_cmd_write_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6113        m_cmd_write_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6114        m_cmd_write_data_fifo.put_and_get(p_vci_tgt.wdata.read());
6115        m_cmd_write_be_fifo.put_and_get(p_vci_tgt.be.read());
6116      } else {
6117        m_cmd_write_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6118        m_cmd_write_eop_fifo.simple_put(p_vci_tgt.eop.read());
6119        m_cmd_write_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6120        m_cmd_write_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6121        m_cmd_write_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6122        m_cmd_write_data_fifo.simple_put(p_vci_tgt.wdata.read());
6123        m_cmd_write_be_fifo.simple_put(p_vci_tgt.be.read());
6124      }
6125    } else {
6126      if ( cmd_write_fifo_get ) {
6127        m_cmd_write_addr_fifo.simple_get();
6128        m_cmd_write_eop_fifo.simple_get();
6129        m_cmd_write_srcid_fifo.simple_get();
6130        m_cmd_write_trdid_fifo.simple_get();
6131        m_cmd_write_pktid_fifo.simple_get();
6132        m_cmd_write_data_fifo.simple_get();
6133        m_cmd_write_be_fifo.simple_get();
6134      }
6135    }
6136    ////////////////////////////////////////////////////////////////////////////////////
6137    //    TGT_CMD to CAS FIFO
6138    ////////////////////////////////////////////////////////////////////////////////////
6139
6140    if ( cmd_cas_fifo_put ) {
6141      if ( cmd_cas_fifo_get ) {
6142        m_cmd_cas_addr_fifo.put_and_get((addr_t)(p_vci_tgt.address.read()));
6143        m_cmd_cas_eop_fifo.put_and_get(p_vci_tgt.eop.read());
6144        m_cmd_cas_srcid_fifo.put_and_get(p_vci_tgt.srcid.read());
6145        m_cmd_cas_trdid_fifo.put_and_get(p_vci_tgt.trdid.read());
6146        m_cmd_cas_pktid_fifo.put_and_get(p_vci_tgt.pktid.read());
6147        m_cmd_cas_wdata_fifo.put_and_get(p_vci_tgt.wdata.read());
6148      } else {
6149        m_cmd_cas_addr_fifo.simple_put((addr_t)(p_vci_tgt.address.read()));
6150        m_cmd_cas_eop_fifo.simple_put(p_vci_tgt.eop.read());
6151        m_cmd_cas_srcid_fifo.simple_put(p_vci_tgt.srcid.read());
6152        m_cmd_cas_trdid_fifo.simple_put(p_vci_tgt.trdid.read());
6153        m_cmd_cas_pktid_fifo.simple_put(p_vci_tgt.pktid.read());
6154        m_cmd_cas_wdata_fifo.simple_put(p_vci_tgt.wdata.read());
6155      }
6156    } else {
6157      if ( cmd_cas_fifo_get ) {
6158        m_cmd_cas_addr_fifo.simple_get();
6159        m_cmd_cas_eop_fifo.simple_get();
6160        m_cmd_cas_srcid_fifo.simple_get();
6161        m_cmd_cas_trdid_fifo.simple_get();
6162        m_cmd_cas_pktid_fifo.simple_get();
6163        m_cmd_cas_wdata_fifo.simple_get();
6164      }
6165    }
6166    ////////////////////////////////////////////////////////////////////////////////////
6167    //    WRITE to INIT_CMD FIFO
6168    ////////////////////////////////////////////////////////////////////////////////////
6169
6170    if ( write_to_init_cmd_fifo_put ) {
6171      if ( write_to_init_cmd_fifo_get ) {
6172        m_write_to_init_cmd_inst_fifo.put_and_get(write_to_init_cmd_fifo_inst);
6173        m_write_to_init_cmd_srcid_fifo.put_and_get(write_to_init_cmd_fifo_srcid);
6174#if L1_MULTI_CACHE
6175        m_write_to_init_cmd_cache_id_fifo.put_and_get(write_to_init_cmd_fifo_cache_id);
6176#endif
6177      } else {
6178        m_write_to_init_cmd_inst_fifo.simple_put(write_to_init_cmd_fifo_inst);
6179        m_write_to_init_cmd_srcid_fifo.simple_put(write_to_init_cmd_fifo_srcid);
6180#if L1_MULTI_CACHE
6181        m_write_to_init_cmd_cache_id_fifo.simple_put(write_to_init_cmd_fifo_cache_id);
6182#endif
6183      }
6184    } else {
6185      if ( write_to_init_cmd_fifo_get ) {
6186        m_write_to_init_cmd_inst_fifo.simple_get();
6187        m_write_to_init_cmd_srcid_fifo.simple_get();
6188#if L1_MULTI_CACHE
6189        m_write_to_init_cmd_cache_id_fifo.simple_get();
6190#endif
6191      }
6192    }
6193    ////////////////////////////////////////////////////////////////////////////////////
6194    //    XRAM_RSP to INIT_CMD FIFO
6195    ////////////////////////////////////////////////////////////////////////////////////
6196
6197    if ( xram_rsp_to_init_cmd_fifo_put ) {
6198      if ( xram_rsp_to_init_cmd_fifo_get ) {
6199        m_xram_rsp_to_init_cmd_inst_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_inst);
6200        m_xram_rsp_to_init_cmd_srcid_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_srcid);
6201#if L1_MULTI_CACHE
6202        m_xram_rsp_to_init_cmd_cache_id_fifo.put_and_get(xram_rsp_to_init_cmd_fifo_cache_id);
6203#endif
6204      } else {
6205        m_xram_rsp_to_init_cmd_inst_fifo.simple_put(xram_rsp_to_init_cmd_fifo_inst);
6206        m_xram_rsp_to_init_cmd_srcid_fifo.simple_put(xram_rsp_to_init_cmd_fifo_srcid);
6207#if L1_MULTI_CACHE
6208        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_put(xram_rsp_to_init_cmd_fifo_cache_id);
6209#endif
6210      }
6211    } else {
6212      if ( xram_rsp_to_init_cmd_fifo_get ) {
6213        m_xram_rsp_to_init_cmd_inst_fifo.simple_get();
6214        m_xram_rsp_to_init_cmd_srcid_fifo.simple_get();
6215#if L1_MULTI_CACHE
6216        m_xram_rsp_to_init_cmd_cache_id_fifo.simple_get();
6217#endif
6218      }
6219    }
6220    ////////////////////////////////////////////////////////////////////////////////////
6221    //    CAS to INIT_CMD FIFO
6222    ////////////////////////////////////////////////////////////////////////////////////
6223
6224    if ( cas_to_init_cmd_fifo_put ) {
6225      if ( cas_to_init_cmd_fifo_get ) {
6226        m_cas_to_init_cmd_inst_fifo.put_and_get(cas_to_init_cmd_fifo_inst);
6227        m_cas_to_init_cmd_srcid_fifo.put_and_get(cas_to_init_cmd_fifo_srcid);
6228#if L1_MULTI_CACHE
6229        m_cas_to_init_cmd_cache_id_fifo.put_and_get(cas_to_init_cmd_fifo_cache_id);
6230#endif
6231      } else {
6232          m_cas_to_init_cmd_inst_fifo.simple_put(cas_to_init_cmd_fifo_inst);
6233          m_cas_to_init_cmd_srcid_fifo.simple_put(cas_to_init_cmd_fifo_srcid);
6234#if L1_MULTI_CACHE
6235          m_cas_to_init_cmd_cache_id_fifo.simple_put(cas_to_init_cmd_fifo_cache_id);
6236#endif
6237      }
6238    } else {
6239        if ( cas_to_init_cmd_fifo_get ) {
6240            m_cas_to_init_cmd_inst_fifo.simple_get();
6241            m_cas_to_init_cmd_srcid_fifo.simple_get();
6242#if L1_MULTI_CACHE
6243            m_cas_to_init_cmd_cache_id_fifo.simple_get();
6244#endif
6245      }
6246    }
6247
6248    m_cpt_cycles++;
6249
6250} // end transition()
6251
6252/////////////////////////////
6253tmpl(void)::genMoore()
6254/////////////////////////////
6255{
6256    ////////////////////////////////////////////////////////////
6257    // Command signals on the p_vci_ixr port
6258    ////////////////////////////////////////////////////////////
6259
6260    p_vci_ixr.be      = 0xF;
6261    p_vci_ixr.pktid   = 0;
6262    p_vci_ixr.srcid   = m_srcid_ixr;
6263    p_vci_ixr.cons    = false;
6264    p_vci_ixr.wrap    = false;
6265    p_vci_ixr.contig  = true;
6266    p_vci_ixr.clen    = 0;
6267    p_vci_ixr.cfixed  = false;
6268
6269    if ( r_ixr_cmd_fsm.read() == IXR_CMD_READ_NLINE ) {
6270      p_vci_ixr.cmd     = vci_param::CMD_READ;
6271      p_vci_ixr.cmdval  = true;
6272      p_vci_ixr.address = (addr_t)(r_read_to_ixr_cmd_nline.read()*m_words*4);
6273      p_vci_ixr.plen    = m_words*4;
6274      p_vci_ixr.wdata   = 0x00000000;
6275      p_vci_ixr.trdid   = r_read_to_ixr_cmd_trdid.read();
6276      p_vci_ixr.eop     = true;
6277    }
6278    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_CAS_NLINE ) {
6279      if(r_cas_to_ixr_cmd_write.read()){
6280        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6281        p_vci_ixr.cmdval  = true;
6282        p_vci_ixr.address = (addr_t)((r_cas_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6283        p_vci_ixr.plen    = m_words*4;
6284        p_vci_ixr.wdata   = r_cas_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6285        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6286        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6287      } else {
6288        p_vci_ixr.cmd     = vci_param::CMD_READ;
6289        p_vci_ixr.cmdval  = true;
6290        p_vci_ixr.address = (addr_t)(r_cas_to_ixr_cmd_nline.read()*m_words*4);
6291        p_vci_ixr.plen    = m_words*4;
6292        p_vci_ixr.wdata   = 0x00000000;
6293        p_vci_ixr.trdid   = r_cas_to_ixr_cmd_trdid.read();
6294        p_vci_ixr.eop     = true;
6295      }
6296    }
6297    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_WRITE_NLINE ) {
6298      if(r_write_to_ixr_cmd_write.read()){
6299        p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6300        p_vci_ixr.cmdval  = true;
6301        p_vci_ixr.address = (addr_t)((r_write_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6302        p_vci_ixr.plen    = m_words*4;
6303        p_vci_ixr.wdata   = r_write_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6304        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6305        p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6306      } else {
6307        p_vci_ixr.cmd     = vci_param::CMD_READ;
6308        p_vci_ixr.cmdval  = true;
6309        p_vci_ixr.address = (addr_t)(r_write_to_ixr_cmd_nline.read()*m_words*4);
6310        p_vci_ixr.plen    = m_words*4;
6311        p_vci_ixr.wdata   = 0x00000000;
6312        p_vci_ixr.trdid   = r_write_to_ixr_cmd_trdid.read();
6313        p_vci_ixr.eop     = true;
6314      }
6315    }
6316    else if ( r_ixr_cmd_fsm.read() == IXR_CMD_XRAM_DATA ) {
6317      p_vci_ixr.cmd     = vci_param::CMD_WRITE;
6318      p_vci_ixr.cmdval  = true;
6319      p_vci_ixr.address = (addr_t)((r_xram_rsp_to_ixr_cmd_nline.read()*m_words+r_ixr_cmd_cpt.read())*4);
6320      p_vci_ixr.plen    = m_words*4;
6321      p_vci_ixr.wdata   = r_xram_rsp_to_ixr_cmd_data[r_ixr_cmd_cpt.read()].read();
6322      p_vci_ixr.trdid   = r_xram_rsp_to_ixr_cmd_trdid.read();
6323      p_vci_ixr.eop     = (r_ixr_cmd_cpt == (m_words-1));
6324    } else {
6325      p_vci_ixr.cmdval  = false;
6326      p_vci_ixr.address = 0;
6327      p_vci_ixr.plen    = 0;
6328      p_vci_ixr.wdata   = 0;
6329      p_vci_ixr.trdid   = 0;
6330      p_vci_ixr.eop = false;
6331    }
6332
6333    ////////////////////////////////////////////////////
6334    // Response signals on the p_vci_ixr port
6335    ////////////////////////////////////////////////////
6336
6337    if ( ((r_alloc_trt_fsm.read() == ALLOC_TRT_IXR_RSP) &&
6338          (r_ixr_rsp_fsm.read() == IXR_RSP_TRT_READ)) ||
6339        (r_ixr_rsp_fsm.read() == IXR_RSP_ACK) ) p_vci_ixr.rspack = true;
6340    else                                        p_vci_ixr.rspack = false;
6341
6342    ////////////////////////////////////////////////////
6343    // Command signals on the p_vci_tgt port
6344    ////////////////////////////////////////////////////
6345
6346    switch ((tgt_cmd_fsm_state_e)r_tgt_cmd_fsm.read()) {
6347      case TGT_CMD_IDLE:
6348        p_vci_tgt.cmdack  = false;
6349        break;
6350      case TGT_CMD_READ:
6351        p_vci_tgt.cmdack  = m_cmd_read_addr_fifo.wok();
6352        break;
6353      case TGT_CMD_WRITE:
6354        p_vci_tgt.cmdack  = m_cmd_write_addr_fifo.wok();
6355        break;
6356      case TGT_CMD_CAS:
6357        p_vci_tgt.cmdack  = m_cmd_cas_addr_fifo.wok();
6358        break;
6359      default:
6360        p_vci_tgt.cmdack  = false;
6361        break;
6362    }
6363
6364    ////////////////////////////////////////////////////
6365    // Response signals on the p_vci_tgt port
6366    ////////////////////////////////////////////////////
6367    switch ( r_tgt_rsp_fsm.read() ) {
6368
6369      case TGT_RSP_READ_IDLE:
6370      case TGT_RSP_WRITE_IDLE:
6371      case TGT_RSP_CAS_IDLE:
6372      case TGT_RSP_XRAM_IDLE:
6373      case TGT_RSP_INIT_IDLE:
6374      case TGT_RSP_CLEANUP_IDLE:
6375        p_vci_tgt.rspval  = false;
6376        p_vci_tgt.rsrcid  = 0;
6377        p_vci_tgt.rdata   = 0;
6378        p_vci_tgt.rpktid  = 0;
6379        p_vci_tgt.rtrdid  = 0;
6380        p_vci_tgt.rerror  = 0;
6381        p_vci_tgt.reop    = false;
6382        break;
6383      case TGT_RSP_READ:
6384        p_vci_tgt.rspval   = true;
6385        p_vci_tgt.rdata    = r_read_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6386        p_vci_tgt.rsrcid   = r_read_to_tgt_rsp_srcid.read();
6387        p_vci_tgt.rtrdid   = r_read_to_tgt_rsp_trdid.read();
6388        p_vci_tgt.rpktid   = r_read_to_tgt_rsp_pktid.read();
6389        p_vci_tgt.rerror   = 0;
6390        p_vci_tgt.reop     = ( r_tgt_rsp_cpt.read() == (r_read_to_tgt_rsp_word.read()+r_read_to_tgt_rsp_length-1) );
6391        break;
6392      case TGT_RSP_WRITE:
6393        p_vci_tgt.rspval   = true;
6394        p_vci_tgt.rdata    = 0;
6395        p_vci_tgt.rsrcid   = r_write_to_tgt_rsp_srcid.read();
6396        p_vci_tgt.rtrdid   = r_write_to_tgt_rsp_trdid.read();
6397        p_vci_tgt.rpktid   = r_write_to_tgt_rsp_pktid.read();
6398        p_vci_tgt.rerror   = 0x2 & ( (1 << vci_param::E) - 1);
6399        p_vci_tgt.reop     = true;
6400        break;
6401      case TGT_RSP_CLEANUP:
6402        p_vci_tgt.rspval   = true;
6403        p_vci_tgt.rdata    = 0;
6404        p_vci_tgt.rsrcid   = r_cleanup_to_tgt_rsp_srcid.read();
6405        p_vci_tgt.rtrdid   = r_cleanup_to_tgt_rsp_trdid.read();
6406        p_vci_tgt.rpktid   = r_cleanup_to_tgt_rsp_pktid.read();
6407        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
6408        p_vci_tgt.reop     = true;
6409        break;
6410      case TGT_RSP_CAS:
6411        p_vci_tgt.rspval   = true;
6412        p_vci_tgt.rdata    = r_cas_to_tgt_rsp_data.read();
6413        p_vci_tgt.rsrcid   = r_cas_to_tgt_rsp_srcid.read();
6414        p_vci_tgt.rtrdid   = r_cas_to_tgt_rsp_trdid.read();
6415        p_vci_tgt.rpktid   = r_cas_to_tgt_rsp_pktid.read();
6416        p_vci_tgt.rerror   = 0;
6417        p_vci_tgt.reop     = true;
6418        break;
6419      case TGT_RSP_XRAM:
6420        p_vci_tgt.rspval   = true;
6421        p_vci_tgt.rdata    = r_xram_rsp_to_tgt_rsp_data[r_tgt_rsp_cpt.read()].read();
6422        p_vci_tgt.rsrcid   = r_xram_rsp_to_tgt_rsp_srcid.read();
6423        p_vci_tgt.rtrdid   = r_xram_rsp_to_tgt_rsp_trdid.read();
6424        p_vci_tgt.rpktid   = r_xram_rsp_to_tgt_rsp_pktid.read();
6425        p_vci_tgt.rerror   = r_xram_rsp_to_tgt_rsp_rerror.read();
6426        p_vci_tgt.reop     = (( r_tgt_rsp_cpt.read()
6427              == (r_xram_rsp_to_tgt_rsp_word.read()+r_xram_rsp_to_tgt_rsp_length.read()-1))
6428            || r_xram_rsp_to_tgt_rsp_rerror.read());
6429        break;
6430      case TGT_RSP_INIT:
6431        p_vci_tgt.rspval   = true;
6432        p_vci_tgt.rdata    = 0;
6433        p_vci_tgt.rsrcid   = r_init_rsp_to_tgt_rsp_srcid.read();
6434        p_vci_tgt.rtrdid   = r_init_rsp_to_tgt_rsp_trdid.read();
6435        p_vci_tgt.rpktid   = r_init_rsp_to_tgt_rsp_pktid.read();
6436        p_vci_tgt.rerror   = 0; // Can be a CAS rsp
6437        p_vci_tgt.reop     = true;
6438        break;
6439    } // end switch r_tgt_rsp_fsm
6440
6441    ///////////////////////////////////////////////////
6442    // Command signals on the p_vci_ini port
6443    ///////////////////////////////////////////////////
6444
6445    p_vci_ini.cmd     = vci_param::CMD_WRITE;
6446    p_vci_ini.srcid   = m_srcid_ini;
6447    p_vci_ini.cons    = true;
6448    p_vci_ini.wrap    = false;
6449    p_vci_ini.contig  = false;
6450    p_vci_ini.clen    = 0;
6451    p_vci_ini.cfixed  = false;
6452
6453    vci_addr_t vci_ini_address = 0;
6454    switch ( r_init_cmd_fsm.read() ) {
6455
6456      case INIT_CMD_UPDT_IDLE:
6457      case INIT_CMD_INVAL_IDLE:
6458      case INIT_CMD_CAS_UPDT_IDLE:
6459        p_vci_ini.cmdval  = false;
6460        p_vci_ini.address = 0;
6461        p_vci_ini.wdata   = 0;
6462        p_vci_ini.be      = 0;
6463        p_vci_ini.plen    = 0;
6464        p_vci_ini.trdid   = 0;
6465        p_vci_ini.pktid   = 0;
6466        p_vci_ini.eop     = false;
6467        break;
6468      case INIT_CMD_INVAL_NLINE:
6469      {
6470        vci_ini_address = (vci_addr_t)
6471            m_xram_rsp_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6472
6473        p_vci_ini.cmdval  = m_xram_rsp_to_init_cmd_inst_fifo.rok();
6474        if(m_xram_rsp_to_init_cmd_inst_fifo.rok()){
6475          if(m_xram_rsp_to_init_cmd_inst_fifo.read()) {
6476              p_vci_ini.address = (addr_t) (vci_ini_address+4);
6477          } else {
6478              p_vci_ini.address = (addr_t) (vci_ini_address);
6479          }
6480        } else p_vci_ini.address = 0; // prevent segmentation faults by reading an empty fifo
6481        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6482        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6483        p_vci_ini.plen    = 4;
6484        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6485#if L1_MULTI_CACHE
6486        p_vci_ini.pktid   = m_xram_rsp_to_init_cmd_cache_id_fifo.read();
6487#endif
6488        p_vci_ini.eop     = true;
6489        break;
6490      }
6491      case INIT_CMD_XRAM_BRDCAST:
6492        p_vci_ini.cmdval  = true;
6493        p_vci_ini.address = m_broadcast_address;
6494        p_vci_ini.wdata   = (uint32_t)r_xram_rsp_to_init_cmd_nline.read();
6495        p_vci_ini.be      = ((r_xram_rsp_to_init_cmd_nline.read() >> 32) & 0x3);
6496        p_vci_ini.plen    = 4;
6497        p_vci_ini.trdid   = r_xram_rsp_to_init_cmd_trdid.read();
6498        p_vci_ini.pktid   = 0;
6499        p_vci_ini.eop     = true;
6500        break;
6501
6502      case INIT_CMD_WRITE_BRDCAST:
6503        p_vci_ini.cmdval  = true;
6504        p_vci_ini.address = m_broadcast_address;
6505        p_vci_ini.wdata   = (addr_t)r_write_to_init_cmd_nline.read();
6506        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32) & 0x3);
6507        p_vci_ini.plen    = 4 ;
6508        p_vci_ini.eop     = true;
6509        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6510        p_vci_ini.pktid   = 0;
6511        break;
6512      case INIT_CMD_UPDT_NLINE:
6513        vci_ini_address = (vci_addr_t)
6514            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6515
6516        p_vci_ini.cmdval  = m_write_to_init_cmd_inst_fifo.rok();
6517        if(m_write_to_init_cmd_inst_fifo.rok()){
6518          if(m_write_to_init_cmd_inst_fifo.read()) {
6519            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6520          } else {
6521            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6522          }
6523        } else {
6524          p_vci_ini.address = 0;
6525        }
6526        p_vci_ini.wdata   = (uint32_t)r_write_to_init_cmd_nline.read();
6527        p_vci_ini.be      = ((r_write_to_init_cmd_nline.read() >> 32 ) & 0x3);
6528        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6529        p_vci_ini.eop     = false;
6530        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6531#if L1_MULTI_CACHE
6532        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6533#endif
6534        break;
6535      case INIT_CMD_UPDT_INDEX:
6536        vci_ini_address = (vci_addr_t)
6537            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6538
6539        p_vci_ini.cmdval  = true;
6540        if(m_write_to_init_cmd_inst_fifo.read()) {
6541          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6542        } else {
6543          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6544        }
6545        p_vci_ini.wdata   = r_write_to_init_cmd_index.read();
6546        p_vci_ini.be      = 0xF;
6547        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6548        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6549#if L1_MULTI_CACHE
6550        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6551#endif
6552        p_vci_ini.eop     = false;
6553        break;
6554      case INIT_CMD_UPDT_DATA:
6555        vci_ini_address = (vci_addr_t)
6556            m_write_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6557
6558        p_vci_ini.cmdval  = true;
6559        if(m_write_to_init_cmd_inst_fifo.read()) {
6560          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6561        } else {
6562          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6563        }
6564        p_vci_ini.wdata   = r_write_to_init_cmd_data[r_init_cmd_cpt.read() +
6565          r_write_to_init_cmd_index.read()].read();
6566        p_vci_ini.be      = r_write_to_init_cmd_be[r_init_cmd_cpt.read() +
6567            r_write_to_init_cmd_index.read()].read()  ;
6568        p_vci_ini.plen    = 4 * (r_write_to_init_cmd_count.read() + 2);
6569        p_vci_ini.trdid   = r_write_to_init_cmd_trdid.read();
6570#if L1_MULTI_CACHE
6571        p_vci_ini.pktid   = m_write_to_init_cmd_cache_id_fifo.read();
6572#endif
6573        p_vci_ini.eop     = ( r_init_cmd_cpt.read() == (r_write_to_init_cmd_count.read()-1) );
6574        break;
6575
6576      case INIT_CMD_CAS_BRDCAST:
6577        p_vci_ini.cmdval  = true;
6578        p_vci_ini.address = m_broadcast_address;
6579        p_vci_ini.wdata   = (addr_t)r_cas_to_init_cmd_nline.read();
6580        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32) & 0x3);
6581        p_vci_ini.plen    = 4 ;
6582        p_vci_ini.eop     = true;
6583        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6584        p_vci_ini.pktid   = 0;
6585        break;
6586      case INIT_CMD_CAS_UPDT_NLINE:
6587        vci_ini_address = (vci_addr_t)
6588            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6589
6590        p_vci_ini.cmdval  = m_cas_to_init_cmd_inst_fifo.rok();
6591        if(m_cas_to_init_cmd_inst_fifo.rok()){
6592          if( m_cas_to_init_cmd_inst_fifo.read() ) {
6593            p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6594          } else {
6595            p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6596          }
6597        } else {
6598          p_vci_ini.address = 0;
6599        }
6600        p_vci_ini.wdata   = (uint32_t)r_cas_to_init_cmd_nline.read();
6601        p_vci_ini.be      = ((r_cas_to_init_cmd_nline.read() >> 32 ) & 0x3);
6602        if(r_cas_to_init_cmd_is_long.read()){
6603            p_vci_ini.plen    = 4 * 4;
6604        } else {
6605            p_vci_ini.plen    = 4 * 3;
6606        }
6607        p_vci_ini.eop     = false;
6608        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6609#if L1_MULTI_CACHE
6610        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6611#endif
6612        break;
6613      case INIT_CMD_CAS_UPDT_INDEX:
6614        vci_ini_address = (vci_addr_t)
6615            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6616
6617        p_vci_ini.cmdval  = true;
6618        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6619          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6620        } else {
6621          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6622        }
6623        p_vci_ini.wdata   = r_cas_to_init_cmd_index.read();
6624        p_vci_ini.be      = 0xF;
6625        if(r_cas_to_init_cmd_is_long.read()){
6626            p_vci_ini.plen    = 4 * 4;
6627        } else {
6628            p_vci_ini.plen    = 4 * 3;
6629        }
6630        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6631#if L1_MULTI_CACHE
6632        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6633#endif
6634        p_vci_ini.eop     = false;
6635        break;
6636      case INIT_CMD_CAS_UPDT_DATA:
6637        vci_ini_address = (vci_addr_t)
6638            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6639
6640        p_vci_ini.cmdval  = true;
6641        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6642          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6643        } else {
6644          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6645        }
6646        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata.read();
6647        p_vci_ini.be      = 0xF;
6648        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6649#if L1_MULTI_CACHE
6650        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6651#endif
6652        if(r_cas_to_init_cmd_is_long.read()){
6653            p_vci_ini.plen    = 4 * 4;
6654            p_vci_ini.eop     = false;
6655        } else {
6656            p_vci_ini.plen    = 4 * 3;
6657            p_vci_ini.eop     = true;
6658        }
6659        break;
6660      case INIT_CMD_CAS_UPDT_DATA_HIGH:
6661        vci_ini_address = (vci_addr_t)
6662            m_cas_to_init_cmd_srcid_fifo.read() << (vci_param::N - vci_param::S);
6663
6664        p_vci_ini.cmdval  = true;
6665        if( m_cas_to_init_cmd_inst_fifo.read() ) {
6666          p_vci_ini.address = (addr_t)(vci_ini_address + 12);
6667        } else {
6668          p_vci_ini.address = (addr_t)(vci_ini_address + 8);
6669        }
6670        p_vci_ini.wdata   = r_cas_to_init_cmd_wdata_high.read();
6671        p_vci_ini.be      = 0xF;
6672        p_vci_ini.plen    = 4 * 4;
6673        p_vci_ini.trdid   = r_cas_to_init_cmd_trdid.read();
6674#if L1_MULTI_CACHE
6675        p_vci_ini.pktid   = m_cas_to_init_cmd_cache_id_fifo.read();
6676#endif
6677        p_vci_ini.eop     = true;
6678        break;
6679
6680    } // end switch r_init_cmd_fsm
6681
6682    //////////////////////////////////////////////////////
6683    // Response signals on the p_vci_ini port
6684    //////////////////////////////////////////////////////
6685
6686    if ( r_init_rsp_fsm.read() == INIT_RSP_IDLE ) p_vci_ini.rspack  = true;
6687    else                                          p_vci_ini.rspack  = false;
6688
6689    //////////////////////////////////////////////////////
6690    // Response signals on the p_vci_tgt_cleanup port
6691    //////////////////////////////////////////////////////
6692    p_vci_tgt_cleanup.rspval = false;
6693    p_vci_tgt_cleanup.rsrcid = 0;
6694    p_vci_tgt_cleanup.rdata  = 0;
6695    p_vci_tgt_cleanup.rpktid = 0;
6696    p_vci_tgt_cleanup.rtrdid = 0;
6697    p_vci_tgt_cleanup.rerror = 0;
6698    p_vci_tgt_cleanup.reop   = false;
6699    p_vci_tgt_cleanup.cmdack = false ;
6700
6701    switch(r_cleanup_fsm.read()){
6702      case CLEANUP_IDLE:
6703        {
6704          p_vci_tgt_cleanup.cmdack = true ;
6705          break;
6706        }
6707      case CLEANUP_RSP:
6708        {
6709          p_vci_tgt_cleanup.rspval = true;
6710          p_vci_tgt_cleanup.rdata  = 0;
6711          p_vci_tgt_cleanup.rsrcid = r_cleanup_srcid.read();
6712          p_vci_tgt_cleanup.rpktid = r_cleanup_pktid.read();
6713          p_vci_tgt_cleanup.rtrdid = r_cleanup_trdid.read();
6714          p_vci_tgt_cleanup.rerror = 0x2 & ( (1 << vci_param::E) - 1);
6715          p_vci_tgt_cleanup.reop   = 1;
6716          break;
6717        }
6718
6719    }
6720
6721} // end genMoore()
6722
6723}} // end name space
6724
6725// Local Variables:
6726// tab-width: 2
6727// c-basic-offset: 2
6728// c-file-offsets:((innamespace . 0)(inline-open . 0))
6729// indent-tabs-mode: nil
6730// End:
6731
6732// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=2:softtabstop=2
Note: See TracBrowser for help on using the repository browser.