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

Last change on this file since 246 was 246, checked in by cfuguet, 12 years ago

Bug fix in IXR_RSP FSM. Erroneous condition for the error verification

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