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

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

Erasing useless template parameters for the communication/dspin_dhccp_param class.

Modifying consequently the vci_mem_cache_dspin_coherence class to use the
dspin_dhccp_param class without templates.

Introducing in the vci_mem_cache and the vci_mem_cache_dspin_coherence modules
the state CAS_DIR_HIT_COMPARE.

Before this modification, the comparison between the expected data and the actual
data was done directly in the CAS_DIR_HIT_READ state using the data obtained in the
same cycle from the cache.

Now, the data obtained from the cache is stored in a buffer and the next cycle,
in the CAS_DIR_HIT_COMPARE state, the comparison is made using the data from the
buffer.

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