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

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

Modificating the VCI Memory Cache to align the VHDL and the SOCLIB models.
The primary modification consists to add a state DIR_REQ or HEAP_REQ, in all
FSMs using these two structures.

In these states a FSM take the lock of the DIRECTORY or HEAP, respectively,
and at the end of the cycle sends the READ request. Is in the next cycle,
when the response of the READ is obtained.

With this modifications, the behavior of a Synchonous RAM is emulated.

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