source: branches/vci_mem_cache_v4/caba/source/src/vci_mem_cache_v4.cpp @ 294

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

Creating branch repertory for the TSAR svn repository.
Copying the vci_mem_cache_v4 component in the branch directory to
introduce the new modifications in the DHCCP protocol

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