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

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

Erasing always false condition in the if statement of the
WRITE_UPT_REQ state.

In this state the r_write_count register, is always bigger than 0.

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