source: branches/v5/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp @ 305

Last change on this file since 305 was 305, checked in by joannou, 11 years ago

In vci_mem_cache component:
Adding an assert for cleanup commands received with no copy in the directory
(such a cleanup should not be received by the vci_mem_cache)

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