Ignore:
Timestamp:
Aug 30, 2013, 6:28:10 PM (11 years ago)
Author:
meunier
Message:
  • Added activity counters to the vci_mem_cache
  • Modified the print_trace function accordingly
  • Refactored code in vci_mem_cache because there was a mix of 2-space and 4-space indentation
  • Modified topcell to factorize ALMOS specifications
Location:
trunk/modules/vci_mem_cache/caba/source
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/modules/vci_mem_cache/caba/source/include/vci_mem_cache.h

    r499 r504  
    404404
    405405      // instrumentation counters
    406       uint32_t     m_cpt_cycles;        // Counter of cycles
    407 
    408       uint32_t     m_cpt_read;          // Number of READ transactions
    409       uint32_t     m_cpt_read_remote;   // number of remote READ transactions
    410       uint32_t     m_cpt_read_flits;    // number of flits for READs
    411       uint32_t     m_cpt_read_cost;     // Number of (flits * distance) for READs
    412 
    413       uint32_t     m_cpt_read_miss;     // Number of MISS READ
    414 
    415       uint32_t     m_cpt_write;         // Number of WRITE transactions
    416       uint32_t     m_cpt_write_remote;  // number of remote WRITE transactions
    417       uint32_t     m_cpt_write_flits;   // number of flits for WRITEs
    418       uint32_t     m_cpt_write_cost;    // Number of (flits * distance) for WRITEs
    419 
    420       uint32_t     m_cpt_write_miss;    // Number of MISS WRITE
    421       uint32_t     m_cpt_write_cells;   // Cumulated length for WRITE transactions
    422       uint32_t     m_cpt_write_dirty;   // Cumulated length for WRITE transactions
    423       uint32_t     m_cpt_update;        // Number of UPDATE transactions
    424       uint32_t     m_cpt_trt_rb;        // Read blocked by a hit in trt
    425       uint32_t     m_cpt_trt_full;      // Transaction blocked due to a full trt
    426       uint32_t     m_cpt_update_mult;   // Number of targets for UPDATE
    427       uint32_t     m_cpt_inval;         // Number of INVAL  transactions
    428       uint32_t     m_cpt_inval_mult;    // Number of targets for INVAL
    429       uint32_t     m_cpt_inval_brdcast; // Number of BROADCAST INVAL
    430       uint32_t     m_cpt_cleanup;       // Number of CLEANUP transactions
    431       uint32_t     m_cpt_ll;            // Number of LL transactions
    432       uint32_t     m_cpt_sc;            // Number of SC transactions
    433       uint32_t     m_cpt_cas;           // Number of CAS transactions
    434 
    435       uint32_t     m_cpt_cleanup_cost;  // Number of (flits * distance) for CLEANUPs
    436 
    437       uint32_t     m_cpt_update_flits;  // Number of flits for UPDATEs
    438       uint32_t     m_cpt_update_cost;   // Number of (flits * distance) for UPDATEs
    439 
    440       uint32_t     m_cpt_inval_cost;    // Number of (flits * distance) for INVALs
     406      uint32_t     m_cpt_cycles;         // Counter of cycles
     407
     408      // Counters accessible in software (not yet but eventually)
     409      uint32_t     m_cpt_read_local;     // Number of local READ transactions
     410      uint32_t     m_cpt_read_remote;    // number of remote READ transactions
     411      uint32_t     m_cpt_read_cost;      // Number of (flits * distance) for READs
     412
     413      uint32_t     m_cpt_write_local;    // Number of local WRITE transactions
     414      uint32_t     m_cpt_write_remote;   // number of remote WRITE transactions
     415      uint32_t     m_cpt_write_flits_local;  // number of flits for local WRITEs
     416      uint32_t     m_cpt_write_flits_remote; // number of flits for remote WRITEs
     417      uint32_t     m_cpt_write_cost;     // Number of (flits * distance) for WRITEs
     418
     419      uint32_t     m_cpt_ll_local;       // Number of local LL transactions
     420      uint32_t     m_cpt_ll_remote;      // number of remote LL transactions
     421      uint32_t     m_cpt_ll_cost;        // Number of (flits * distance) for LLs
     422
     423      uint32_t     m_cpt_sc_local;       // Number of local SC transactions
     424      uint32_t     m_cpt_sc_remote;      // number of remote SC transactions
     425      uint32_t     m_cpt_sc_cost;        // Number of (flits * distance) for SCs
     426
     427      uint32_t     m_cpt_cas_local;      // Number of local SC transactions
     428      uint32_t     m_cpt_cas_remote;     // number of remote SC transactions
     429      uint32_t     m_cpt_cas_cost;       // Number of (flits * distance) for SCs
     430
     431      uint32_t     m_cpt_update;         // Number of requests causing an UPDATE
     432      uint32_t     m_cpt_update_local;   // Number of local UPDATE transactions
     433      uint32_t     m_cpt_update_remote;  // Number of remote UPDATE transactions
     434      uint32_t     m_cpt_update_cost;    // Number of (flits * distance) for UPDT
     435
     436      uint32_t     m_cpt_m_inval;        // Number of requests causing M_INV
     437      uint32_t     m_cpt_m_inval_local;  // Number of local M_INV transactions
     438      uint32_t     m_cpt_m_inval_remote; // Number of remote M_INV transactions
     439      uint32_t     m_cpt_m_inval_cost;   // Number of (flits * distance) for M_INV
     440
     441      uint32_t     m_cpt_br_inval;       // Number of BROADCAST INVAL
     442
     443      uint32_t     m_cpt_cleanup_local;  // Number of local CLEANUP transactions
     444      uint32_t     m_cpt_cleanup_remote; // Number of remote CLEANUP transactions
     445      uint32_t     m_cpt_cleanup_cost;   // Number of (flits * distance) for CLEANUPs
     446
     447      // Counters not accessible by software
     448      uint32_t     m_cpt_read_miss;      // Number of MISS READ
     449      uint32_t     m_cpt_write_miss;     // Number of MISS WRITE
     450      uint32_t     m_cpt_write_dirty;    // Cumulated length for WRITE transactions
     451
     452      uint32_t     m_cpt_trt_rb;         // Read blocked by a hit in trt
     453      uint32_t     m_cpt_trt_full;       // Transaction blocked due to a full trt
    441454
    442455      uint32_t     m_cpt_get;
    443 
    444456      uint32_t     m_cpt_put;
    445457
     
    466478          const soclib::common::IntTab       &tgtid_d,        // global index INT network
    467479          const size_t                       cc_global_id,    // global index CC network
     480          const size_t                       x_width,         // X width in platform
     481          const size_t                       y_width,         // Y width in platform
    468482          const size_t                       nways,           // Number of ways per set
    469483          const size_t                       nsets,           // Number of sets
     
    479493      ~VciMemCache();
    480494
    481       void print_stats();
     495      void print_stats(bool activity_counters, bool stats);
    482496      void print_trace();
    483497      void cache_monitor(addr_t addr);
     
    490504      void genMoore();
    491505      void check_monitor(addr_t addr, data_t data, bool read);
     506      uint32_t req_distance(uint32_t req_srcid);
     507      bool is_local_req(uint32_t req_srcid);
    492508
    493509      // Component attributes
     
    503519      const size_t                       m_words;            // Number of words in a line
    504520      const size_t                       m_cc_global_id;     // global_index on cc network
     521      const size_t                       m_xwidth;           // number of x bits in platform
     522      const size_t                       m_ywidth;           // number of y bits in platform
    505523      size_t                             m_debug_start_cycle;
    506524      bool                               m_debug_ok;
  • trunk/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp

    r499 r504  
    11/* -*- c++ -*-
    2 *
    3 * File       : vci_mem_cache.cpp
    4 * Date       : 30/10/2008
    5 * Copyright  : UPMC / LIP6
    6 * Authors    : Alain Greiner / Eric Guthmuller
    7 *
    8 * SOCLIB_LGPL_HEADER_BEGIN
    9 *
    10 * This file is part of SoCLib, GNU LGPLv2.1.
    11 *
    12 * SoCLib is free software; you can redistribute it and/or modify it
    13 * under the terms of the GNU Lesser General Public License as published
    14 * by the Free Software Foundation; version 2.1 of the License.
    15 *
    16 * SoCLib is distributed in the hope that it will be useful, but
    17 * WITHOUT ANY WARRANTY; without even the implied warranty of
    18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    19 * Lesser General Public License for more details.
    20 *
    21 * You should have received a copy of the GNU Lesser General Public
    22 * License along with SoCLib; if not, write to the Free Software
    23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    24 * 02110-1301 USA
    25 *
    26 * SOCLIB_LGPL_HEADER_END
    27 *
    28 * Maintainers: alain.greiner@lip6.fr
    29 *              eric.guthmuller@polytechnique.edu
    30 *              cesar.fuguet-tortolero@lip6.fr
    31 *              alexandre.joannou@lip6.fr
    32 */
     2 *
     3 * File       : vci_mem_cache.cpp
     4 * Date       : 30/10/2008
     5 * Copyright  : UPMC / LIP6
     6 * Authors    : Alain Greiner / Eric Guthmuller
     7 *
     8 * SOCLIB_LGPL_HEADER_BEGIN
     9 *
     10 * This file is part of SoCLib, GNU LGPLv2.1.
     11 *
     12 * SoCLib is free software; you can redistribute it and/or modify it
     13 * under the terms of the GNU Lesser General Public License as published
     14 * by the Free Software Foundation; version 2.1 of the License.
     15 *
     16 * SoCLib is distributed in the hope that it will be useful, but
     17 * WITHOUT ANY WARRANTY; without even the implied warranty of
     18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     19 * Lesser General Public License for more details.
     20 *
     21 * You should have received a copy of the GNU Lesser General Public
     22 * License along with SoCLib; if not, write to the Free Software
     23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     24 * 02110-1301 USA
     25 *
     26 * SOCLIB_LGPL_HEADER_END
     27 *
     28 * Maintainers: alain.greiner@lip6.fr
     29 *              eric.guthmuller@polytechnique.edu
     30 *              cesar.fuguet-tortolero@lip6.fr
     31 *              alexandre.joannou@lip6.fr
     32 */
    3333
    3434#include "../include/vci_mem_cache.h"
     
    5858namespace soclib { namespace caba {
    5959
    60 const char *tgt_cmd_fsm_str[] =
    61 {
    62   "TGT_CMD_IDLE",
    63   "TGT_CMD_ERROR",
    64   "TGT_CMD_READ",
    65   "TGT_CMD_WRITE",
    66   "TGT_CMD_CAS",
    67   "TGT_CMD_CONFIG"
    68 };
    69 const char *tgt_rsp_fsm_str[] =
    70 {
    71   "TGT_RSP_CONFIG_IDLE",
    72   "TGT_RSP_TGT_CMD_IDLE",
    73   "TGT_RSP_READ_IDLE",
    74   "TGT_RSP_WRITE_IDLE",
    75   "TGT_RSP_CAS_IDLE",
    76   "TGT_RSP_XRAM_IDLE",
    77   "TGT_RSP_MULTI_ACK_IDLE",
    78   "TGT_RSP_CLEANUP_IDLE",
    79   "TGT_RSP_CONFIG",
    80   "TGT_RSP_TGT_CMD",
    81   "TGT_RSP_READ",
    82   "TGT_RSP_WRITE",
    83   "TGT_RSP_CAS",
    84   "TGT_RSP_XRAM",
    85   "TGT_RSP_MULTI_ACK",
    86   "TGT_RSP_CLEANUP"
    87 };
    88 const char *cc_receive_fsm_str[] =
    89 {
    90   "CC_RECEIVE_IDLE",
    91   "CC_RECEIVE_CLEANUP",
    92   "CC_RECEIVE_CLEANUP_EOP",
    93   "CC_RECEIVE_MULTI_ACK"
    94 };
    95 const char *cc_send_fsm_str[] =
    96 {
    97   "CC_SEND_CONFIG_IDLE",
    98   "CC_SEND_XRAM_RSP_IDLE",
    99   "CC_SEND_WRITE_IDLE",
    100   "CC_SEND_CAS_IDLE",
    101   "CC_SEND_CONFIG_INVAL_HEADER",
    102   "CC_SEND_CONFIG_INVAL_NLINE",
    103   "CC_SEND_CONFIG_BRDCAST_HEADER",
    104   "CC_SEND_CONFIG_BRDCAST_NLINE",
    105   "CC_SEND_XRAM_RSP_BRDCAST_HEADER",
    106   "CC_SEND_XRAM_RSP_BRDCAST_NLINE",
    107   "CC_SEND_XRAM_RSP_INVAL_HEADER",
    108   "CC_SEND_XRAM_RSP_INVAL_NLINE",
    109   "CC_SEND_WRITE_BRDCAST_HEADER",
    110   "CC_SEND_WRITE_BRDCAST_NLINE",
    111   "CC_SEND_WRITE_UPDT_HEADER",
    112   "CC_SEND_WRITE_UPDT_NLINE",
    113   "CC_SEND_WRITE_UPDT_DATA",
    114   "CC_SEND_CAS_BRDCAST_HEADER",
    115   "CC_SEND_CAS_BRDCAST_NLINE",
    116   "CC_SEND_CAS_UPDT_HEADER",
    117   "CC_SEND_CAS_UPDT_NLINE",
    118   "CC_SEND_CAS_UPDT_DATA",
    119   "CC_SEND_CAS_UPDT_DATA_HIGH"
    120 };
    121 const char *multi_ack_fsm_str[] =
    122 {
    123   "MULTI_ACK_IDLE",
    124   "MULTI_ACK_UPT_LOCK",
    125   "MULTI_ACK_UPT_CLEAR",
    126   "MULTI_ACK_WRITE_RSP"
    127 };
    128 const char *config_fsm_str[] =
    129 {
    130   "CONFIG_IDLE",
    131   "CONFIG_LOOP",
    132   "CONFIG_WAIT",
    133   "CONFIG_RSP",
    134   "CONFIG_DIR_REQ",
    135   "CONFIG_DIR_ACCESS",
    136   "CONFIG_IVT_LOCK",
    137   "CONFIG_BC_SEND",
    138   "CONFIG_INVAL_SEND",
    139   "CONFIG_HEAP_REQ",
    140   "CONFIG_HEAP_SCAN",
    141   "CONFIG_HEAP_LAST",
    142   "CONFIG_TRT_LOCK",
    143   "CONFIG_TRT_SET",
    144   "CONFIG_PUT_REQ"
    145 };
    146 const char *read_fsm_str[] =
    147 {
    148   "READ_IDLE",
    149   "READ_DIR_REQ",
    150   "READ_DIR_LOCK",
    151   "READ_DIR_HIT",
    152   "READ_HEAP_REQ",
    153   "READ_HEAP_LOCK",
    154   "READ_HEAP_WRITE",
    155   "READ_HEAP_ERASE",
    156   "READ_HEAP_LAST",
    157   "READ_RSP",
    158   "READ_TRT_LOCK",
    159   "READ_TRT_SET",
    160   "READ_TRT_REQ"
    161 };
    162 const char *write_fsm_str[] =
    163 {
    164   "WRITE_IDLE",
    165   "WRITE_NEXT",
    166   "WRITE_DIR_REQ",
    167   "WRITE_DIR_LOCK",
    168   "WRITE_DIR_HIT",
    169   "WRITE_UPT_LOCK",
    170   "WRITE_UPT_HEAP_LOCK",
    171   "WRITE_UPT_REQ",
    172   "WRITE_UPT_NEXT",
    173   "WRITE_UPT_DEC",
    174   "WRITE_RSP",
    175   "WRITE_MISS_TRT_LOCK",
    176   "WRITE_MISS_TRT_DATA",
    177   "WRITE_MISS_TRT_SET",
    178   "WRITE_MISS_XRAM_REQ",
    179   "WRITE_BC_DIR_READ",
    180   "WRITE_BC_TRT_LOCK",
    181   "WRITE_BC_IVT_LOCK",
    182   "WRITE_BC_DIR_INVAL",
    183   "WRITE_BC_CC_SEND",
    184   "WRITE_BC_XRAM_REQ",
    185   "WRITE_WAIT"
    186 };
    187 const char *ixr_rsp_fsm_str[] =
    188 {
    189   "IXR_RSP_IDLE",
    190   "IXR_RSP_TRT_ERASE",
    191   "IXR_RSP_TRT_READ"
    192 };
    193 const char *xram_rsp_fsm_str[] =
    194 {
    195   "XRAM_RSP_IDLE",
    196   "XRAM_RSP_TRT_COPY",
    197   "XRAM_RSP_TRT_DIRTY",
    198   "XRAM_RSP_DIR_LOCK",
    199   "XRAM_RSP_DIR_UPDT",
    200   "XRAM_RSP_DIR_RSP",
    201   "XRAM_RSP_IVT_LOCK",
    202   "XRAM_RSP_INVAL_WAIT",
    203   "XRAM_RSP_INVAL",
    204   "XRAM_RSP_WRITE_DIRTY",
    205   "XRAM_RSP_HEAP_REQ",
    206   "XRAM_RSP_HEAP_ERASE",
    207   "XRAM_RSP_HEAP_LAST",
    208   "XRAM_RSP_ERROR_ERASE",
    209   "XRAM_RSP_ERROR_RSP"
    210 };
    211 const char *ixr_cmd_fsm_str[] =
    212 {
    213   "IXR_CMD_READ_IDLE",
    214   "IXR_CMD_WRITE_IDLE",
    215   "IXR_CMD_CAS_IDLE",
    216   "IXR_CMD_XRAM_IDLE",
    217   "IXR_CMD_CONFIG_IDLE",
    218   "IXR_CMD_READ_TRT",
    219   "IXR_CMD_WRITE_TRT",
    220   "IXR_CMD_CAS_TRT",
    221   "IXR_CMD_XRAM_TRT",
    222   "IXR_CMD_CONFIG_TRT",
    223   "IXR_CMD_READ_SEND",
    224   "IXR_CMD_WRITE_SEND",
    225   "IXR_CMD_CAS_SEND",
    226   "IXR_CMD_XRAM_SEND",
    227   "IXR_CMD_CONFIG_SEND"
    228 };
    229 const char *cas_fsm_str[] =
    230 {
    231   "CAS_IDLE",
    232   "CAS_DIR_REQ",
    233   "CAS_DIR_LOCK",
    234   "CAS_DIR_HIT_READ",
    235   "CAS_DIR_HIT_COMPARE",
    236   "CAS_DIR_HIT_WRITE",
    237   "CAS_UPT_LOCK",
    238   "CAS_UPT_HEAP_LOCK",
    239   "CAS_UPT_REQ",
    240   "CAS_UPT_NEXT",
    241   "CAS_BC_TRT_LOCK",
    242   "CAS_BC_IVT_LOCK",
    243   "CAS_BC_DIR_INVAL",
    244   "CAS_BC_CC_SEND",
    245   "CAS_BC_XRAM_REQ",
    246   "CAS_RSP_FAIL",
    247   "CAS_RSP_SUCCESS",
    248   "CAS_MISS_TRT_LOCK",
    249   "CAS_MISS_TRT_SET",
    250   "CAS_MISS_XRAM_REQ",
    251   "CAS_WAIT"
    252 };
    253 const char *cleanup_fsm_str[] =
    254 {
    255   "CLEANUP_IDLE",
    256   "CLEANUP_GET_NLINE",
    257   "CLEANUP_DIR_REQ",
    258   "CLEANUP_DIR_LOCK",
    259   "CLEANUP_DIR_WRITE",
    260   "CLEANUP_HEAP_REQ",
    261   "CLEANUP_HEAP_LOCK",
    262   "CLEANUP_HEAP_SEARCH",
    263   "CLEANUP_HEAP_CLEAN",
    264   "CLEANUP_HEAP_FREE",
    265   "CLEANUP_IVT_LOCK",
    266   "CLEANUP_IVT_DECREMENT",
    267   "CLEANUP_IVT_CLEAR",
    268   "CLEANUP_WRITE_RSP",
    269   "CLEANUP_SEND_CLACK"
    270 };
    271 const char *alloc_dir_fsm_str[] =
    272 {
    273   "ALLOC_DIR_RESET",
    274   "ALLOC_DIR_CONFIG",
    275   "ALLOC_DIR_READ",
    276   "ALLOC_DIR_WRITE",
    277   "ALLOC_DIR_CAS",
    278   "ALLOC_DIR_CLEANUP",
    279   "ALLOC_DIR_XRAM_RSP"
    280 };
    281 const char *alloc_trt_fsm_str[] =
    282 {
    283   "ALLOC_TRT_READ",
    284   "ALLOC_TRT_WRITE",
    285   "ALLOC_TRT_CAS",
    286   "ALLOC_TRT_XRAM_RSP",
    287   "ALLOC_TRT_IXR_RSP",
    288   "ALLOC_TRT_CONFIG",
    289   "ALLOC_TRT_IXR_CMD"
    290 };
    291 const char *alloc_upt_fsm_str[] =
    292 {
    293   "ALLOC_UPT_WRITE",
    294   "ALLOC_UPT_CAS",
    295   "ALLOC_UPT_MULTI_ACK"
    296 };
    297 const char *alloc_ivt_fsm_str[] =
    298 {
    299   "ALLOC_IVT_WRITE",
    300   "ALLOC_IVT_XRAM_RSP",
    301   "ALLOC_IVT_CLEANUP",
    302   "ALLOC_IVT_CAS",
    303   "ALLOC_IVT_CONFIG"
    304 };
    305 const char *alloc_heap_fsm_str[] =
    306 {
    307   "ALLOC_HEAP_RESET",
    308   "ALLOC_HEAP_READ",
    309   "ALLOC_HEAP_WRITE",
    310   "ALLOC_HEAP_CAS",
    311   "ALLOC_HEAP_CLEANUP",
    312   "ALLOC_HEAP_XRAM_RSP",
    313   "ALLOC_HEAP_CONFIG"
    314 };
     60    const char *tgt_cmd_fsm_str[] =
     61    {
     62        "TGT_CMD_IDLE",
     63        "TGT_CMD_ERROR",
     64        "TGT_CMD_READ",
     65        "TGT_CMD_WRITE",
     66        "TGT_CMD_CAS",
     67        "TGT_CMD_CONFIG"
     68    };
     69    const char *tgt_rsp_fsm_str[] =
     70    {
     71        "TGT_RSP_CONFIG_IDLE",
     72        "TGT_RSP_TGT_CMD_IDLE",
     73        "TGT_RSP_READ_IDLE",
     74        "TGT_RSP_WRITE_IDLE",
     75        "TGT_RSP_CAS_IDLE",
     76        "TGT_RSP_XRAM_IDLE",
     77        "TGT_RSP_MULTI_ACK_IDLE",
     78        "TGT_RSP_CLEANUP_IDLE",
     79        "TGT_RSP_CONFIG",
     80        "TGT_RSP_TGT_CMD",
     81        "TGT_RSP_READ",
     82        "TGT_RSP_WRITE",
     83        "TGT_RSP_CAS",
     84        "TGT_RSP_XRAM",
     85        "TGT_RSP_MULTI_ACK",
     86        "TGT_RSP_CLEANUP"
     87    };
     88    const char *cc_receive_fsm_str[] =
     89    {
     90        "CC_RECEIVE_IDLE",
     91        "CC_RECEIVE_CLEANUP",
     92        "CC_RECEIVE_CLEANUP_EOP",
     93        "CC_RECEIVE_MULTI_ACK"
     94    };
     95    const char *cc_send_fsm_str[] =
     96    {
     97        "CC_SEND_CONFIG_IDLE",
     98        "CC_SEND_XRAM_RSP_IDLE",
     99        "CC_SEND_WRITE_IDLE",
     100        "CC_SEND_CAS_IDLE",
     101        "CC_SEND_CONFIG_INVAL_HEADER",
     102        "CC_SEND_CONFIG_INVAL_NLINE",
     103        "CC_SEND_CONFIG_BRDCAST_HEADER",
     104        "CC_SEND_CONFIG_BRDCAST_NLINE",
     105        "CC_SEND_XRAM_RSP_BRDCAST_HEADER",
     106        "CC_SEND_XRAM_RSP_BRDCAST_NLINE",
     107        "CC_SEND_XRAM_RSP_INVAL_HEADER",
     108        "CC_SEND_XRAM_RSP_INVAL_NLINE",
     109        "CC_SEND_WRITE_BRDCAST_HEADER",
     110        "CC_SEND_WRITE_BRDCAST_NLINE",
     111        "CC_SEND_WRITE_UPDT_HEADER",
     112        "CC_SEND_WRITE_UPDT_NLINE",
     113        "CC_SEND_WRITE_UPDT_DATA",
     114        "CC_SEND_CAS_BRDCAST_HEADER",
     115        "CC_SEND_CAS_BRDCAST_NLINE",
     116        "CC_SEND_CAS_UPDT_HEADER",
     117        "CC_SEND_CAS_UPDT_NLINE",
     118        "CC_SEND_CAS_UPDT_DATA",
     119        "CC_SEND_CAS_UPDT_DATA_HIGH"
     120    };
     121    const char *multi_ack_fsm_str[] =
     122    {
     123        "MULTI_ACK_IDLE",
     124        "MULTI_ACK_UPT_LOCK",
     125        "MULTI_ACK_UPT_CLEAR",
     126        "MULTI_ACK_WRITE_RSP"
     127    };
     128    const char *config_fsm_str[] =
     129    {
     130        "CONFIG_IDLE",
     131        "CONFIG_LOOP",
     132        "CONFIG_WAIT",
     133        "CONFIG_RSP",
     134        "CONFIG_DIR_REQ",
     135        "CONFIG_DIR_ACCESS",
     136        "CONFIG_IVT_LOCK",
     137        "CONFIG_BC_SEND",
     138        "CONFIG_INVAL_SEND",
     139        "CONFIG_HEAP_REQ",
     140        "CONFIG_HEAP_SCAN",
     141        "CONFIG_HEAP_LAST",
     142        "CONFIG_TRT_LOCK",
     143        "CONFIG_TRT_SET",
     144        "CONFIG_PUT_REQ"
     145    };
     146    const char *read_fsm_str[] =
     147    {
     148        "READ_IDLE",
     149        "READ_DIR_REQ",
     150        "READ_DIR_LOCK",
     151        "READ_DIR_HIT",
     152        "READ_HEAP_REQ",
     153        "READ_HEAP_LOCK",
     154        "READ_HEAP_WRITE",
     155        "READ_HEAP_ERASE",
     156        "READ_HEAP_LAST",
     157        "READ_RSP",
     158        "READ_TRT_LOCK",
     159        "READ_TRT_SET",
     160        "READ_TRT_REQ"
     161    };
     162    const char *write_fsm_str[] =
     163    {
     164        "WRITE_IDLE",
     165        "WRITE_NEXT",
     166        "WRITE_DIR_REQ",
     167        "WRITE_DIR_LOCK",
     168        "WRITE_DIR_HIT",
     169        "WRITE_UPT_LOCK",
     170        "WRITE_UPT_HEAP_LOCK",
     171        "WRITE_UPT_REQ",
     172        "WRITE_UPT_NEXT",
     173        "WRITE_UPT_DEC",
     174        "WRITE_RSP",
     175        "WRITE_MISS_TRT_LOCK",
     176        "WRITE_MISS_TRT_DATA",
     177        "WRITE_MISS_TRT_SET",
     178        "WRITE_MISS_XRAM_REQ",
     179        "WRITE_BC_DIR_READ",
     180        "WRITE_BC_TRT_LOCK",
     181        "WRITE_BC_IVT_LOCK",
     182        "WRITE_BC_DIR_INVAL",
     183        "WRITE_BC_CC_SEND",
     184        "WRITE_BC_XRAM_REQ",
     185        "WRITE_WAIT"
     186    };
     187    const char *ixr_rsp_fsm_str[] =
     188    {
     189        "IXR_RSP_IDLE",
     190        "IXR_RSP_TRT_ERASE",
     191        "IXR_RSP_TRT_READ"
     192    };
     193    const char *xram_rsp_fsm_str[] =
     194    {
     195        "XRAM_RSP_IDLE",
     196        "XRAM_RSP_TRT_COPY",
     197        "XRAM_RSP_TRT_DIRTY",
     198        "XRAM_RSP_DIR_LOCK",
     199        "XRAM_RSP_DIR_UPDT",
     200        "XRAM_RSP_DIR_RSP",
     201        "XRAM_RSP_IVT_LOCK",
     202        "XRAM_RSP_INVAL_WAIT",
     203        "XRAM_RSP_INVAL",
     204        "XRAM_RSP_WRITE_DIRTY",
     205        "XRAM_RSP_HEAP_REQ",
     206        "XRAM_RSP_HEAP_ERASE",
     207        "XRAM_RSP_HEAP_LAST",
     208        "XRAM_RSP_ERROR_ERASE",
     209        "XRAM_RSP_ERROR_RSP"
     210    };
     211    const char *ixr_cmd_fsm_str[] =
     212    {
     213        "IXR_CMD_READ_IDLE",
     214        "IXR_CMD_WRITE_IDLE",
     215        "IXR_CMD_CAS_IDLE",
     216        "IXR_CMD_XRAM_IDLE",
     217        "IXR_CMD_CONFIG_IDLE",
     218        "IXR_CMD_READ_TRT",
     219        "IXR_CMD_WRITE_TRT",
     220        "IXR_CMD_CAS_TRT",
     221        "IXR_CMD_XRAM_TRT",
     222        "IXR_CMD_CONFIG_TRT",
     223        "IXR_CMD_READ_SEND",
     224        "IXR_CMD_WRITE_SEND",
     225        "IXR_CMD_CAS_SEND",
     226        "IXR_CMD_XRAM_SEND",
     227        "IXR_CMD_CONFIG_SEND"
     228    };
     229    const char *cas_fsm_str[] =
     230    {
     231        "CAS_IDLE",
     232        "CAS_DIR_REQ",
     233        "CAS_DIR_LOCK",
     234        "CAS_DIR_HIT_READ",
     235        "CAS_DIR_HIT_COMPARE",
     236        "CAS_DIR_HIT_WRITE",
     237        "CAS_UPT_LOCK",
     238        "CAS_UPT_HEAP_LOCK",
     239        "CAS_UPT_REQ",
     240        "CAS_UPT_NEXT",
     241        "CAS_BC_TRT_LOCK",
     242        "CAS_BC_IVT_LOCK",
     243        "CAS_BC_DIR_INVAL",
     244        "CAS_BC_CC_SEND",
     245        "CAS_BC_XRAM_REQ",
     246        "CAS_RSP_FAIL",
     247        "CAS_RSP_SUCCESS",
     248        "CAS_MISS_TRT_LOCK",
     249        "CAS_MISS_TRT_SET",
     250        "CAS_MISS_XRAM_REQ",
     251        "CAS_WAIT"
     252    };
     253    const char *cleanup_fsm_str[] =
     254    {
     255        "CLEANUP_IDLE",
     256        "CLEANUP_GET_NLINE",
     257        "CLEANUP_DIR_REQ",
     258        "CLEANUP_DIR_LOCK",
     259        "CLEANUP_DIR_WRITE",
     260        "CLEANUP_HEAP_REQ",
     261        "CLEANUP_HEAP_LOCK",
     262        "CLEANUP_HEAP_SEARCH",
     263        "CLEANUP_HEAP_CLEAN",
     264        "CLEANUP_HEAP_FREE",
     265        "CLEANUP_IVT_LOCK",
     266        "CLEANUP_IVT_DECREMENT",
     267        "CLEANUP_IVT_CLEAR",
     268        "CLEANUP_WRITE_RSP",
     269        "CLEANUP_SEND_CLACK"
     270    };
     271    const char *alloc_dir_fsm_str[] =
     272    {
     273        "ALLOC_DIR_RESET",
     274        "ALLOC_DIR_CONFIG",
     275        "ALLOC_DIR_READ",
     276        "ALLOC_DIR_WRITE",
     277        "ALLOC_DIR_CAS",
     278        "ALLOC_DIR_CLEANUP",
     279        "ALLOC_DIR_XRAM_RSP"
     280    };
     281    const char *alloc_trt_fsm_str[] =
     282    {
     283        "ALLOC_TRT_READ",
     284        "ALLOC_TRT_WRITE",
     285        "ALLOC_TRT_CAS",
     286        "ALLOC_TRT_XRAM_RSP",
     287        "ALLOC_TRT_IXR_RSP",
     288        "ALLOC_TRT_CONFIG",
     289        "ALLOC_TRT_IXR_CMD"
     290    };
     291    const char *alloc_upt_fsm_str[] =
     292    {
     293        "ALLOC_UPT_WRITE",
     294        "ALLOC_UPT_CAS",
     295        "ALLOC_UPT_MULTI_ACK"
     296    };
     297    const char *alloc_ivt_fsm_str[] =
     298    {
     299        "ALLOC_IVT_WRITE",
     300        "ALLOC_IVT_XRAM_RSP",
     301        "ALLOC_IVT_CLEANUP",
     302        "ALLOC_IVT_CAS",
     303        "ALLOC_IVT_CONFIG"
     304    };
     305    const char *alloc_heap_fsm_str[] =
     306    {
     307        "ALLOC_HEAP_RESET",
     308        "ALLOC_HEAP_READ",
     309        "ALLOC_HEAP_WRITE",
     310        "ALLOC_HEAP_CAS",
     311        "ALLOC_HEAP_CLEANUP",
     312        "ALLOC_HEAP_XRAM_RSP",
     313        "ALLOC_HEAP_CONFIG"
     314    };
    315315
    316316#define tmpl(x) \
    317   template<typename vci_param_int, \
    318            typename vci_param_ext, \
    319            size_t dspin_in_width,  \
    320            size_t dspin_out_width> x \
    321   VciMemCache<vci_param_int, vci_param_ext, dspin_in_width, dspin_out_width>
    322 
    323 using namespace soclib::common;
    324 
    325 ////////////////////////////////
    326 //  Constructor
    327 ////////////////////////////////
    328 
    329 tmpl(/**/) ::VciMemCache(
    330   sc_module_name      name,
    331   const MappingTable  &mtp,              // mapping table for direct network
    332   const MappingTable  &mtx,              // mapping table for external network
    333   const IntTab        &srcid_x,          // global index on external network
    334   const IntTab        &tgtid_d,          // global index on direct network
    335   const size_t        cc_global_id,      // global index on cc network
    336   const size_t        nways,             // number of ways per set
    337   const size_t        nsets,             // number of associative sets
    338   const size_t        nwords,            // number of words in cache line
    339   const size_t        max_copies,        // max number of copies in heap
    340   const size_t        heap_size,         // number of heap entries
    341   const size_t        trt_lines,         // number of TRT entries
    342   const size_t        upt_lines,         // number of UPT entries
    343   const size_t        ivt_lines,         // number of IVT entries
    344   const size_t        debug_start_cycle,
    345   const bool          debug_ok)
    346 
    347   : soclib::caba::BaseModule(name),
    348 
    349     p_clk( "p_clk" ),
    350     p_resetn( "p_resetn" ),
    351     p_vci_tgt( "p_vci_tgt" ),
    352     p_vci_ixr( "p_vci_ixr" ),
    353     p_dspin_p2m( "p_dspin_p2m" ),
    354     p_dspin_m2p( "p_dspin_m2p" ),
    355     p_dspin_clack( "p_dspin_clack" ),
    356 
    357     m_seglist( mtp.getSegmentList(tgtid_d) ),
    358     m_nseg( 0 ),
    359     m_srcid_x( mtx.indexForId(srcid_x) ),
    360     m_initiators( 1 << vci_param_int::S ),
    361     m_heap_size( heap_size ),
    362     m_ways( nways ),
    363     m_sets( nsets ),
    364     m_words( nwords ),
    365     m_cc_global_id( cc_global_id ),
    366     m_debug_start_cycle( debug_start_cycle ),
    367     m_debug_ok( debug_ok ),
    368     m_trt_lines(trt_lines),
    369     m_trt(this->name(), trt_lines, nwords),
    370     m_upt_lines(upt_lines),
    371     m_upt(upt_lines),
    372     m_ivt(ivt_lines),
    373     m_cache_directory(nways, nsets, nwords, vci_param_int::N),
    374     m_cache_data(nways, nsets, nwords),
    375     m_heap(m_heap_size),
    376     m_max_copies( max_copies ),
    377     m_llsc_table(),
     317    template<typename vci_param_int, \
     318    typename vci_param_ext, \
     319    size_t dspin_in_width,  \
     320    size_t dspin_out_width> x \
     321    VciMemCache<vci_param_int, vci_param_ext, dspin_in_width, dspin_out_width>
     322
     323    using namespace soclib::common;
     324
     325    ////////////////////////////////
     326    //  Constructor
     327    ////////////////////////////////
     328
     329    tmpl(/**/)::VciMemCache(
     330            sc_module_name      name,
     331            const MappingTable  &mtp,              // mapping table for direct network
     332            const MappingTable  &mtx,              // mapping table for external network
     333            const IntTab        &srcid_x,          // global index on external network
     334            const IntTab        &tgtid_d,          // global index on direct network
     335            const size_t        cc_global_id,      // global index on cc network
     336            const size_t        x_width,           // number of x bits in platform
     337            const size_t        y_width,           // number of x bits in platform
     338            const size_t        nways,             // number of ways per set
     339            const size_t        nsets,             // number of associative sets
     340            const size_t        nwords,            // number of words in cache line
     341            const size_t        max_copies,        // max number of copies in heap
     342            const size_t        heap_size,         // number of heap entries
     343            const size_t        trt_lines,         // number of TRT entries
     344            const size_t        upt_lines,         // number of UPT entries
     345            const size_t        ivt_lines,         // number of IVT entries
     346            const size_t        debug_start_cycle,
     347            const bool          debug_ok)
     348
     349        : soclib::caba::BaseModule(name),
     350
     351        p_clk( "p_clk" ),
     352        p_resetn( "p_resetn" ),
     353        p_vci_tgt( "p_vci_tgt" ),
     354        p_vci_ixr( "p_vci_ixr" ),
     355        p_dspin_p2m( "p_dspin_p2m" ),
     356        p_dspin_m2p( "p_dspin_m2p" ),
     357        p_dspin_clack( "p_dspin_clack" ),
     358
     359        m_seglist(mtp.getSegmentList(tgtid_d)),
     360        m_nseg(0),
     361        m_srcid_x( mtx.indexForId(srcid_x)),
     362        m_initiators(1 << vci_param_int::S),
     363        m_heap_size(heap_size),
     364        m_ways(nways),
     365        m_sets(nsets),
     366        m_words(nwords),
     367        m_cc_global_id(cc_global_id),
     368        m_xwidth(x_width),
     369        m_ywidth(y_width),
     370        m_debug_start_cycle(debug_start_cycle),
     371        m_debug_ok(debug_ok),
     372        m_trt_lines(trt_lines),
     373        m_trt(this->name(), trt_lines, nwords),
     374        m_upt_lines(upt_lines),
     375        m_upt(upt_lines),
     376        m_ivt(ivt_lines),
     377        m_cache_directory(nways, nsets, nwords, vci_param_int::N),
     378        m_cache_data(nways, nsets, nwords),
     379        m_heap(m_heap_size),
     380        m_max_copies(max_copies),
     381        m_llsc_table(),
    378382
    379383#define L2 soclib::common::uint32_log2
    380     m_x(L2(m_words), 2),
    381     m_y(L2(m_sets), L2(m_words) + 2),
    382     m_z(vci_param_int::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
    383     m_nline(vci_param_int::N - L2(m_words) - 2, L2(m_words) + 2),
     384        m_x(L2(m_words), 2),
     385        m_y(L2(m_sets), L2(m_words) + 2),
     386        m_z(vci_param_int::N - L2(m_sets) - L2(m_words) - 2, L2(m_sets) + L2(m_words) + 2),
     387        m_nline(vci_param_int::N - L2(m_words) - 2, L2(m_words) + 2),
    384388#undef L2
    385389
    386     // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits)
    387     //   0b00000    /   0b11111    /   0b00000    /   0b11111
    388     m_broadcast_boundaries(0x7C1F),
    389 
    390 
    391     //  FIFOs
    392     m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
    393     m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
    394     m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
    395     m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
    396     m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
    397 
    398     m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
    399     m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
    400     m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
    401     m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
    402     m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
    403     m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
    404     m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
    405 
    406     m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4),
    407     m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4),
    408     m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4),
    409     m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4),
    410     m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4),
    411     m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4),
    412 
    413     m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4),
    414     m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4),
    415 
    416     r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
    417 
    418     r_config_fsm( "r_config_fsm" ),
    419 
    420     m_config_to_cc_send_inst_fifo( "m_config_to_cc_send_inst_fifo", 8 ),
    421     m_config_to_cc_send_srcid_fifo( "m_config_to_cc_send_srcid_fifo", 8 ),
    422 
    423     r_read_fsm( "r_read_fsm" ),
    424 
    425     r_write_fsm( "r_write_fsm" ),
    426 
    427     m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8),
    428     m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8),
    429 
    430     r_multi_ack_fsm("r_multi_ack_fsm"),
    431 
    432     r_cleanup_fsm("r_cleanup_fsm"),
    433 
    434     r_cas_fsm("r_cas_fsm"),
    435 
    436     m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8),
    437     m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8),
    438 
    439     r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
    440     r_xram_rsp_fsm("r_xram_rsp_fsm"),
    441 
    442     m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8),
    443     m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8),
    444 
    445     r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
    446 
    447     r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
    448 
    449     r_cc_send_fsm("r_cc_send_fsm"),
    450     r_cc_receive_fsm("r_cc_receive_fsm"),
    451 
    452     r_alloc_dir_fsm("r_alloc_dir_fsm"),
    453     r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"),
    454     r_alloc_trt_fsm("r_alloc_trt_fsm"),
    455     r_alloc_upt_fsm("r_alloc_upt_fsm"),
    456     r_alloc_ivt_fsm("r_alloc_ivt_fsm"),
    457     r_alloc_heap_fsm("r_alloc_heap_fsm"),
    458     r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt")
    459 {
    460     std::cout << "  - Building VciMemCache : " << name << std::endl;
    461 
    462     assert(IS_POW_OF_2(nsets));
    463     assert(IS_POW_OF_2(nwords));
    464     assert(IS_POW_OF_2(nways));
    465     assert(nsets);
    466     assert(nwords);
    467     assert(nways);
    468 
    469     // check Transaction table size
    470     assert((uint32_log2(trt_lines) <= vci_param_ext::T) and
    471     "MEMC ERROR : Need more bits for VCI TRDID field");
    472 
    473     // check internal and external data width
    474     assert( (vci_param_int::B == 4 ) and
    475     "MEMC ERROR : VCI internal data width must be 32 bits");
    476 
    477     assert( (vci_param_ext::B == 8) and
    478     "MEMC ERROR : VCI external data width must be 64 bits");
    479 
    480     // Check coherence between internal & external addresses
    481     assert( (vci_param_int::N == vci_param_ext::N) and
    482     "MEMC ERROR : VCI internal & external addresses must have the same width");
    483 
    484     // Get the segments associated to the MemCache
    485     std::list<soclib::common::Segment>::iterator seg;
    486     size_t i = 0;
    487 
    488     for(seg = m_seglist.begin(); seg != m_seglist.end() ; seg++)
     390        // XMIN(5 bits) / XMAX(5 bits) / YMIN(5 bits) / YMAX(5 bits)
     391        //   0b00000    /   0b11111    /   0b00000    /   0b11111
     392        m_broadcast_boundaries(0x7C1F),
     393
     394
     395        //  FIFOs
     396        m_cmd_read_addr_fifo("m_cmd_read_addr_fifo", 4),
     397        m_cmd_read_length_fifo("m_cmd_read_length_fifo", 4),
     398        m_cmd_read_srcid_fifo("m_cmd_read_srcid_fifo", 4),
     399        m_cmd_read_trdid_fifo("m_cmd_read_trdid_fifo", 4),
     400        m_cmd_read_pktid_fifo("m_cmd_read_pktid_fifo", 4),
     401
     402        m_cmd_write_addr_fifo("m_cmd_write_addr_fifo",8),
     403        m_cmd_write_eop_fifo("m_cmd_write_eop_fifo",8),
     404        m_cmd_write_srcid_fifo("m_cmd_write_srcid_fifo",8),
     405        m_cmd_write_trdid_fifo("m_cmd_write_trdid_fifo",8),
     406        m_cmd_write_pktid_fifo("m_cmd_write_pktid_fifo",8),
     407        m_cmd_write_data_fifo("m_cmd_write_data_fifo",8),
     408        m_cmd_write_be_fifo("m_cmd_write_be_fifo",8),
     409
     410        m_cmd_cas_addr_fifo("m_cmd_cas_addr_fifo",4),
     411        m_cmd_cas_eop_fifo("m_cmd_cas_eop_fifo",4),
     412        m_cmd_cas_srcid_fifo("m_cmd_cas_srcid_fifo",4),
     413        m_cmd_cas_trdid_fifo("m_cmd_cas_trdid_fifo",4),
     414        m_cmd_cas_pktid_fifo("m_cmd_cas_pktid_fifo",4),
     415        m_cmd_cas_wdata_fifo("m_cmd_cas_wdata_fifo",4),
     416
     417        m_cc_receive_to_cleanup_fifo("m_cc_receive_to_cleanup_fifo", 4),
     418        m_cc_receive_to_multi_ack_fifo("m_cc_receive_to_multi_ack_fifo", 4),
     419
     420        r_tgt_cmd_fsm("r_tgt_cmd_fsm"),
     421
     422        r_config_fsm( "r_config_fsm" ),
     423
     424        m_config_to_cc_send_inst_fifo( "m_config_to_cc_send_inst_fifo", 8 ),
     425        m_config_to_cc_send_srcid_fifo( "m_config_to_cc_send_srcid_fifo", 8 ),
     426
     427        r_read_fsm( "r_read_fsm" ),
     428
     429        r_write_fsm( "r_write_fsm" ),
     430
     431        m_write_to_cc_send_inst_fifo("m_write_to_cc_send_inst_fifo",8),
     432        m_write_to_cc_send_srcid_fifo("m_write_to_cc_send_srcid_fifo",8),
     433
     434        r_multi_ack_fsm("r_multi_ack_fsm"),
     435
     436        r_cleanup_fsm("r_cleanup_fsm"),
     437
     438        r_cas_fsm("r_cas_fsm"),
     439
     440        m_cas_to_cc_send_inst_fifo("m_cas_to_cc_send_inst_fifo",8),
     441        m_cas_to_cc_send_srcid_fifo("m_cas_to_cc_send_srcid_fifo",8),
     442
     443        r_ixr_rsp_fsm("r_ixr_rsp_fsm"),
     444        r_xram_rsp_fsm("r_xram_rsp_fsm"),
     445
     446        m_xram_rsp_to_cc_send_inst_fifo("m_xram_rsp_to_cc_send_inst_fifo",8),
     447        m_xram_rsp_to_cc_send_srcid_fifo("m_xram_rsp_to_cc_send_srcid_fifo",8),
     448
     449        r_ixr_cmd_fsm("r_ixr_cmd_fsm"),
     450
     451        r_tgt_rsp_fsm("r_tgt_rsp_fsm"),
     452
     453        r_cc_send_fsm("r_cc_send_fsm"),
     454        r_cc_receive_fsm("r_cc_receive_fsm"),
     455
     456        r_alloc_dir_fsm("r_alloc_dir_fsm"),
     457        r_alloc_dir_reset_cpt("r_alloc_dir_reset_cpt"),
     458        r_alloc_trt_fsm("r_alloc_trt_fsm"),
     459        r_alloc_upt_fsm("r_alloc_upt_fsm"),
     460        r_alloc_ivt_fsm("r_alloc_ivt_fsm"),
     461        r_alloc_heap_fsm("r_alloc_heap_fsm"),
     462        r_alloc_heap_reset_cpt("r_alloc_heap_reset_cpt")
     463        {
     464            std::cout << "  - Building VciMemCache : " << name << std::endl;
     465
     466            assert(IS_POW_OF_2(nsets));
     467            assert(IS_POW_OF_2(nwords));
     468            assert(IS_POW_OF_2(nways));
     469            assert(nsets);
     470            assert(nwords);
     471            assert(nways);
     472
     473            // check Transaction table size
     474            assert((uint32_log2(trt_lines) <= vci_param_ext::T) and
     475                    "MEMC ERROR : Need more bits for VCI TRDID field");
     476
     477            // check internal and external data width
     478            assert( (vci_param_int::B == 4 ) and
     479                    "MEMC ERROR : VCI internal data width must be 32 bits");
     480
     481            assert( (vci_param_ext::B == 8) and
     482                    "MEMC ERROR : VCI external data width must be 64 bits");
     483
     484            // Check coherence between internal & external addresses
     485            assert( (vci_param_int::N == vci_param_ext::N) and
     486                    "MEMC ERROR : VCI internal & external addresses must have the same width");
     487
     488            // Get the segments associated to the MemCache
     489            std::list<soclib::common::Segment>::iterator seg;
     490            size_t i = 0;
     491
     492            for (seg = m_seglist.begin(); seg != m_seglist.end(); seg++)
     493            {
     494                std::cout << "    => segment " << seg->name()
     495                    << " / base = " << std::hex << seg->baseAddress()
     496                    << " / size = " << seg->size() << std::endl;
     497                m_nseg++;
     498            }
     499
     500            m_seg = new soclib::common::Segment*[m_nseg];
     501
     502            for (seg = m_seglist.begin(); seg != m_seglist.end(); seg++)
     503            {
     504                if (seg->special() ) m_seg_config = i;
     505                m_seg[i] = & (*seg);
     506                i++;
     507            }
     508
     509            // Allocation for IXR_RSP FSM
     510            r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
     511
     512            // Allocation for XRAM_RSP FSM
     513            r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
     514            r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
     515
     516            // Allocation for READ FSM
     517            r_read_data                = new sc_signal<data_t>[nwords];
     518            r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
     519
     520            // Allocation for WRITE FSM
     521            r_write_data               = new sc_signal<data_t>[nwords];
     522            r_write_be                 = new sc_signal<be_t>[nwords];
     523            r_write_to_cc_send_data    = new sc_signal<data_t>[nwords];
     524            r_write_to_cc_send_be      = new sc_signal<be_t>[nwords];
     525
     526            // Allocation for CAS FSM
     527            r_cas_data                 = new sc_signal<data_t>[nwords];
     528            r_cas_rdata                = new sc_signal<data_t>[2];
     529
     530            // Allocation for IXR_CMD FSM
     531            r_ixr_cmd_wdata            = new sc_signal<data_t>[nwords];
     532
     533            // Allocation for debug
     534            m_debug_previous_data      = new data_t[nwords];
     535            m_debug_data               = new data_t[nwords];
     536
     537            SC_METHOD(transition);
     538            dont_initialize();
     539            sensitive << p_clk.pos();
     540
     541            SC_METHOD(genMoore);
     542            dont_initialize();
     543            sensitive << p_clk.neg();
     544        } // end constructor
     545
     546
     547    /////////////////////////////////////////////////////
     548    tmpl(void) ::cache_monitor(addr_t addr)
     549    /////////////////////////////////////////////////////
    489550    {
    490         std::cout << "    => segment " << seg->name()
    491                   << " / base = " << std::hex << seg->baseAddress()
    492                   << " / size = " << seg->size() << std::endl;
    493         m_nseg++;
    494     }
    495 
    496     m_seg = new soclib::common::Segment*[m_nseg];
    497 
    498     for(seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++)
    499     {
    500         if ( seg->special() ) m_seg_config = i;
    501         m_seg[i] = & (*seg);
    502         i++;
    503     }
    504 
    505     // Allocation for IXR_RSP FSM
    506     r_ixr_rsp_to_xram_rsp_rok  = new sc_signal<bool>[m_trt_lines];
    507 
    508     // Allocation for XRAM_RSP FSM
    509     r_xram_rsp_victim_data     = new sc_signal<data_t>[nwords];
    510     r_xram_rsp_to_tgt_rsp_data = new sc_signal<data_t>[nwords];
    511 
    512     // Allocation for READ FSM
    513     r_read_data                = new sc_signal<data_t>[nwords];
    514     r_read_to_tgt_rsp_data     = new sc_signal<data_t>[nwords];
    515 
    516     // Allocation for WRITE FSM
    517     r_write_data               = new sc_signal<data_t>[nwords];
    518     r_write_be                 = new sc_signal<be_t>[nwords];
    519     r_write_to_cc_send_data    = new sc_signal<data_t>[nwords];
    520     r_write_to_cc_send_be      = new sc_signal<be_t>[nwords];
    521 
    522     // Allocation for CAS FSM
    523     r_cas_data                 = new sc_signal<data_t>[nwords];
    524     r_cas_rdata                = new sc_signal<data_t>[2];
    525 
    526     // Allocation for IXR_CMD FSM
    527     r_ixr_cmd_wdata            = new sc_signal<data_t>[nwords];
    528 
    529     // Allocation for debug
    530     m_debug_previous_data      = new data_t[nwords];
    531     m_debug_data               = new data_t[nwords];
    532 
    533     SC_METHOD(transition);
    534     dont_initialize();
    535     sensitive << p_clk.pos();
    536 
    537     SC_METHOD(genMoore);
    538     dont_initialize();
    539     sensitive << p_clk.neg();
    540 } // end constructor
    541 
    542 
    543 /////////////////////////////////////////////////////
    544 tmpl(void) ::cache_monitor(addr_t addr)
    545 /////////////////////////////////////////////////////
    546 {
    547     size_t way = 0;
    548     size_t set = 0;
    549     DirectoryEntry entry = m_cache_directory.read_neutral(addr, &way, &set );
    550 
    551     // read data and compute data_change
    552     bool data_change = false;
    553     if ( entry.valid )
    554     {
    555         for ( size_t word = 0 ; word<m_words ; word++ )
     551        size_t way = 0;
     552        size_t set = 0;
     553        DirectoryEntry entry = m_cache_directory.read_neutral(addr, &way, &set);
     554
     555        // read data and compute data_change
     556        bool data_change = false;
     557        if (entry.valid)
    556558        {
    557             m_debug_data[word] = m_cache_data.read(way, set, word);
    558             if ( m_debug_previous_valid and
    559                  (m_debug_data[word] != m_debug_previous_data[word]) )
     559            for (size_t word = 0; word<m_words; word++)
    560560            {
    561                 data_change = true;
     561                m_debug_data[word] = m_cache_data.read(way, set, word);
     562                if (m_debug_previous_valid and
     563                        (m_debug_data[word] != m_debug_previous_data[word]))
     564                {
     565                    data_change = true;
     566                }
    562567            }
    563568        }
     569
     570        // print values if any change
     571        if ((entry.valid != m_debug_previous_valid) or
     572                (entry.valid and (entry.count != m_debug_previous_count)) or
     573                (entry.valid and (entry.dirty != m_debug_previous_dirty)) or data_change)
     574        {
     575            std::cout << "Monitor MEMC " << name()
     576                << " at cycle " << std::dec << m_cpt_cycles
     577                << " for address " << std::hex << addr
     578                << " / VAL = " << std::dec << entry.valid
     579                << " / WAY = " << way
     580                << " / COUNT = " << entry.count
     581                << " / DIRTY = " << entry.dirty
     582                << " / DATA_CHANGE = " << data_change
     583                << std::endl;
     584            std::cout << std::hex << "     /0:" << m_debug_data[0]
     585                << "/1:" << m_debug_data[1]
     586                << "/2:" << m_debug_data[2]
     587                << "/3:" << m_debug_data[3]
     588                << "/4:" << m_debug_data[4]
     589                << "/5:" << m_debug_data[5]
     590                << "/6:" << m_debug_data[6]
     591                << "/7:" << m_debug_data[7]
     592                << "/8:" << m_debug_data[8]
     593                << "/9:" << m_debug_data[9]
     594                << "/A:" << m_debug_data[10]
     595                << "/B:" << m_debug_data[11]
     596                << "/C:" << m_debug_data[12]
     597                << "/D:" << m_debug_data[13]
     598                << "/E:" << m_debug_data[14]
     599                << "/F:" << m_debug_data[15]
     600                << std::endl;
     601        }
     602
     603        // register values
     604        m_debug_previous_count = entry.count;
     605        m_debug_previous_valid = entry.valid;
     606        m_debug_previous_dirty = entry.dirty;
     607        for (size_t word = 0; word < m_words; word++)
     608            m_debug_previous_data[word] = m_debug_data[word];
    564609    }
     610
    565611   
    566     // print values if any change
    567     if ( (entry.valid != m_debug_previous_valid) or
    568          (entry.valid and (entry.count != m_debug_previous_count)) or
    569          (entry.valid and (entry.dirty != m_debug_previous_dirty)) or data_change )
     612    /////////////////////////////////////////////////////
     613    tmpl(uint32_t)::req_distance(uint32_t req_srcid)
     614    /////////////////////////////////////////////////////
    570615    {
    571         std::cout << "Monitor MEMC " << name()
    572                   << " at cycle " << std::dec << m_cpt_cycles
    573                   << " for address " << std::hex << addr
    574                   << " / VAL = " << std::dec << entry.valid
    575                   << " / WAY = " << way
    576                   << " / COUNT = " << entry.count
    577                   << " / DIRTY = " << entry.dirty
    578                   << " / DATA_CHANGE = " << data_change
    579                   << std::endl;
    580         std::cout << std::hex << "     /0:" << m_debug_data[0]
    581                   << "/1:" << m_debug_data[1]
    582                   << "/2:" << m_debug_data[2]
    583                   << "/3:" << m_debug_data[3]
    584                   << "/4:" << m_debug_data[4]
    585                   << "/5:" << m_debug_data[5]
    586                   << "/6:" << m_debug_data[6]
    587                   << "/7:" << m_debug_data[7]
    588                   << "/8:" << m_debug_data[8]
    589                   << "/9:" << m_debug_data[9]
    590                   << "/A:" << m_debug_data[10]
    591                   << "/B:" << m_debug_data[11]
    592                   << "/C:" << m_debug_data[12]
    593                   << "/D:" << m_debug_data[13]
    594                   << "/E:" << m_debug_data[14]
    595                   << "/F:" << m_debug_data[15]
    596                   << std::endl;
     616        uint8_t self_x_srcid = m_cc_global_id >> (14 - m_xwidth);
     617        uint8_t self_y_srcid = ((m_cc_global_id << m_xwidth) >> (14 - m_ywidth));
     618
     619        uint8_t x_srcid = req_srcid >> (14 - m_xwidth);
     620        uint8_t y_srcid = ((req_srcid << m_xwidth) >> (14 - m_ywidth));
     621        return abs(self_x_srcid - x_srcid) + abs(self_y_srcid - y_srcid);
    597622    }
    598623
    599     // register values
    600     m_debug_previous_count = entry.count;
    601     m_debug_previous_valid = entry.valid;
    602     m_debug_previous_dirty = entry.dirty;
    603     for( size_t word=0 ; word<m_words ; word++ )
    604         m_debug_previous_data[word] = m_debug_data[word];
    605 }
    606 
    607 //////////////////////////////////////////////////
    608 tmpl(void) ::print_trace()
    609 //////////////////////////////////////////////////
    610 {
    611   std::cout << "MEMC " << name() << std::endl;
    612   std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]
     624
     625    /////////////////////////////////////////////////////
     626    tmpl(bool)::is_local_req(uint32_t req_srcid)
     627    /////////////////////////////////////////////////////
     628    {
     629        return req_distance(req_srcid) == 0;
     630    }
     631
     632
     633    //////////////////////////////////////////////////
     634    tmpl(void)::print_trace()
     635    //////////////////////////////////////////////////
     636    {
     637        std::cout << "MEMC " << name() << std::endl;
     638        std::cout << "  "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]
    613639            << " | " << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]
    614640            << " | " << read_fsm_str[r_read_fsm.read()]
     
    617643            << " | " << config_fsm_str[r_config_fsm.read()]
    618644            << " | " << cleanup_fsm_str[r_cleanup_fsm.read()] << std::endl;
    619   std::cout << "  "  << cc_send_fsm_str[r_cc_send_fsm.read()]
     645        std::cout << "  "  << cc_send_fsm_str[r_cc_send_fsm.read()]
    620646            << " | " << cc_receive_fsm_str[r_cc_receive_fsm.read()]
    621647            << " | " << multi_ack_fsm_str[r_multi_ack_fsm.read()]
     
    623649            << " | " << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]
    624650            << " | " << xram_rsp_fsm_str[r_xram_rsp_fsm.read()] << std::endl;
    625   std::cout << "  "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]
     651        std::cout << "  "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]
    626652            << " | " << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]
    627653            << " | " << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]
    628654            << " | " << alloc_ivt_fsm_str[r_alloc_ivt_fsm.read()]
    629655            << " | " << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
    630 }
    631 
    632 /////////////////////////////////////////
    633 tmpl(void) ::print_stats()
    634 /////////////////////////////////////////
    635 {
    636   std::cout << "----------------------------------" << std::dec << std::endl;
    637   std::cout
    638       << "MEM_CACHE " << name() << " / Time = " << m_cpt_cycles << std::endl
    639       << "- READ RATE            = " << (double) m_cpt_read/m_cpt_cycles << std::endl
    640       << "- READ TOTAL           = " << m_cpt_read << std::endl
    641       << "- READ MISS RATE       = " << (double) m_cpt_read_miss/m_cpt_read << std::endl
    642       << "- WRITE RATE           = " << (double) m_cpt_write/m_cpt_cycles << std::endl
    643       << "- WRITE TOTAL          = " << m_cpt_write << std::endl
    644       << "- WRITE MISS RATE      = " << (double) m_cpt_write_miss/m_cpt_write << std::endl
    645       << "- WRITE BURST LENGTH   = " << (double) m_cpt_write_cells/m_cpt_write << std::endl
    646       << "- WRITE BURST TOTAL    = " << m_cpt_write_cells << std::endl
    647       << "- REQUESTS TRT FULL    = " << m_cpt_trt_full << std::endl
    648       << "- READ TRT BLOKED HIT  = " << m_cpt_trt_rb << std::endl
    649       << "- UPDATE RATE          = " << (double) m_cpt_update/m_cpt_cycles << std::endl
    650       << "- UPDATE ARITY         = " << (double) m_cpt_update_mult/m_cpt_update << std::endl
    651       << "- INVAL MULTICAST RATE = " << (double)(m_cpt_inval-m_cpt_inval_brdcast) /m_cpt_cycles << std::endl
    652       << "- INVAL MULTICAST ARITY= " << (double) m_cpt_inval_mult/ (m_cpt_inval-m_cpt_inval_brdcast) << std::endl
    653       << "- INVAL BROADCAST RATE = " << (double) m_cpt_inval_brdcast/m_cpt_cycles << std::endl
    654       << "- SAVE DIRTY RATE      = " << (double) m_cpt_write_dirty/m_cpt_cycles << std::endl
    655       << "- CLEANUP RATE         = " << (double) m_cpt_cleanup/m_cpt_cycles << std::endl
    656       << "- LL RATE              = " << (double) m_cpt_ll/m_cpt_cycles << std::endl
    657       << "- SC RATE              = " << (double) m_cpt_sc/m_cpt_cycles << std::endl
    658       << "- CAS RATE             = " << (double) m_cpt_cas/m_cpt_cycles << std::endl;
    659 }
    660 
    661 /////////////////////////////////
    662 tmpl(/**/) ::~VciMemCache()
    663 /////////////////////////////////
    664 {
    665   delete [] r_ixr_rsp_to_xram_rsp_rok;
    666 
    667   delete [] r_xram_rsp_victim_data;
    668   delete [] r_xram_rsp_to_tgt_rsp_data;
    669 
    670   delete [] r_read_data;
    671   delete [] r_read_to_tgt_rsp_data;
    672 
    673   delete [] r_write_data;
    674   delete [] r_write_be;
    675   delete [] r_write_to_cc_send_data;
    676 }
    677 
    678 //////////////////////////////////
    679 tmpl(void) ::transition()
    680 //////////////////////////////////
    681 {
    682   using soclib::common::uint32_log2;
    683 
    684   // RESET
    685   if(! p_resetn.read())
    686   {
    687 
    688     // Initializing FSMs
    689     r_tgt_cmd_fsm    = TGT_CMD_IDLE;
    690     r_config_fsm     = CONFIG_IDLE;
    691     r_tgt_rsp_fsm    = TGT_RSP_TGT_CMD_IDLE;
    692     r_cc_send_fsm    = CC_SEND_XRAM_RSP_IDLE;
    693     r_cc_receive_fsm = CC_RECEIVE_IDLE;
    694     r_multi_ack_fsm  = MULTI_ACK_IDLE;
    695     r_read_fsm       = READ_IDLE;
    696     r_write_fsm      = WRITE_IDLE;
    697     r_cas_fsm        = CAS_IDLE;
    698     r_cleanup_fsm    = CLEANUP_IDLE;
    699     r_alloc_dir_fsm  = ALLOC_DIR_RESET;
    700     r_alloc_heap_fsm = ALLOC_HEAP_RESET;
    701     r_alloc_trt_fsm  = ALLOC_TRT_READ;
    702     r_alloc_upt_fsm  = ALLOC_UPT_WRITE;
    703     r_alloc_ivt_fsm  = ALLOC_IVT_XRAM_RSP;
    704     r_ixr_rsp_fsm    = IXR_RSP_IDLE;
    705     r_xram_rsp_fsm   = XRAM_RSP_IDLE;
    706     r_ixr_cmd_fsm    = IXR_CMD_READ_IDLE;
    707 
    708     m_debug                = false;
    709     m_debug_previous_valid = false;
    710     m_debug_previous_dirty = false;
    711     m_debug_previous_count = 0;
    712 
    713     //  Initializing Tables
    714     m_trt.init();
    715     m_upt.init();
    716     m_ivt.init();
    717     m_llsc_table.init();
    718 
    719     // initializing FIFOs and communication Buffers
    720 
    721     m_cmd_read_addr_fifo.init();
    722     m_cmd_read_length_fifo.init();
    723     m_cmd_read_srcid_fifo.init();
    724     m_cmd_read_trdid_fifo.init();
    725     m_cmd_read_pktid_fifo.init();
    726 
    727     m_cmd_write_addr_fifo.init();
    728     m_cmd_write_eop_fifo.init();
    729     m_cmd_write_srcid_fifo.init();
    730     m_cmd_write_trdid_fifo.init();
    731     m_cmd_write_pktid_fifo.init();
    732     m_cmd_write_data_fifo.init();
    733 
    734     m_cmd_cas_addr_fifo.init()  ;
    735     m_cmd_cas_srcid_fifo.init() ;
    736     m_cmd_cas_trdid_fifo.init() ;
    737     m_cmd_cas_pktid_fifo.init() ;
    738     m_cmd_cas_wdata_fifo.init() ;
    739     m_cmd_cas_eop_fifo.init()   ;
    740 
    741     r_config_cmd  = MEMC_CMD_NOP;
    742     r_config_lock = false;
    743 
    744     m_config_to_cc_send_inst_fifo.init();
    745     m_config_to_cc_send_srcid_fifo.init();
    746 
    747     r_tgt_cmd_to_tgt_rsp_req = false;
    748 
    749     r_read_to_tgt_rsp_req = false;
    750     r_read_to_ixr_cmd_req = false;
    751 
    752     r_write_to_tgt_rsp_req          = false;
    753     r_write_to_ixr_cmd_req          = false;
    754     r_write_to_cc_send_multi_req    = false;
    755     r_write_to_cc_send_brdcast_req  = false;
    756     r_write_to_multi_ack_req        = false;
    757 
    758     m_write_to_cc_send_inst_fifo.init();
    759     m_write_to_cc_send_srcid_fifo.init();
    760 
    761     r_cleanup_to_tgt_rsp_req      = false;
    762 
    763     m_cc_receive_to_cleanup_fifo.init();
    764 
    765     r_multi_ack_to_tgt_rsp_req    = false;
    766 
    767     m_cc_receive_to_multi_ack_fifo.init();
    768 
    769     r_cas_to_tgt_rsp_req          = false;
    770     r_cas_cpt                     = 0    ;
    771     r_cas_lfsr                    = -1   ;
    772     r_cas_to_ixr_cmd_req          = false;
    773     r_cas_to_cc_send_multi_req    = false;
    774     r_cas_to_cc_send_brdcast_req  = false;
    775 
    776     m_cas_to_cc_send_inst_fifo.init();
    777     m_cas_to_cc_send_srcid_fifo.init();
    778 
    779     for(size_t i=0; i<m_trt_lines ; i++)
     656    }
     657
     658
     659    /////////////////////////////////////////
     660    tmpl(void)::print_stats(bool activity_counters = true, bool stats = true)
     661    /////////////////////////////////////////
    780662    {
    781       r_ixr_rsp_to_xram_rsp_rok[i] = false;
    782     }
    783 
    784     r_xram_rsp_to_tgt_rsp_req          = false;
    785     r_xram_rsp_to_cc_send_multi_req   = false;
    786     r_xram_rsp_to_cc_send_brdcast_req = false;
    787     r_xram_rsp_to_ixr_cmd_req          = false;
    788     r_xram_rsp_trt_index               = 0;
    789 
    790     m_xram_rsp_to_cc_send_inst_fifo.init();
    791     m_xram_rsp_to_cc_send_srcid_fifo.init();
    792 
    793     r_alloc_dir_reset_cpt  = 0;
    794     r_alloc_heap_reset_cpt = 0;
    795 
    796     r_tgt_rsp_key_sent  = false;
    797 
    798     // Activity counters
    799     m_cpt_cycles        = 0;
    800     m_cpt_read          = 0;
    801     m_cpt_read_miss     = 0;
    802     m_cpt_write         = 0;
    803     m_cpt_write_miss    = 0;
    804     m_cpt_write_cells   = 0;
    805     m_cpt_write_dirty   = 0;
    806     m_cpt_update        = 0;
    807     m_cpt_update_mult   = 0;
    808     m_cpt_inval_brdcast = 0;
    809     m_cpt_inval         = 0;
    810     m_cpt_inval_mult    = 0;
    811     m_cpt_cleanup       = 0;
    812     m_cpt_ll            = 0;
    813     m_cpt_sc            = 0;
    814     m_cpt_cas           = 0;
    815     m_cpt_trt_full      = 0;
    816     m_cpt_trt_rb        = 0;
    817 
    818     return;
    819   }
    820 
    821   bool    cmd_read_fifo_put = false;
    822   bool    cmd_read_fifo_get = false;
    823 
    824   bool    cmd_write_fifo_put = false;
    825   bool    cmd_write_fifo_get = false;
    826 
    827   bool    cmd_cas_fifo_put = false;
    828   bool    cmd_cas_fifo_get = false;
    829 
    830   bool    cc_receive_to_cleanup_fifo_get = false;
    831   bool    cc_receive_to_cleanup_fifo_put = false;
    832 
    833   bool    cc_receive_to_multi_ack_fifo_get = false;
    834   bool    cc_receive_to_multi_ack_fifo_put = false;
    835 
    836   bool    write_to_cc_send_fifo_put   = false;
    837   bool    write_to_cc_send_fifo_get   = false;
    838   bool    write_to_cc_send_fifo_inst  = false;
    839   size_t  write_to_cc_send_fifo_srcid = 0;
    840 
    841   bool    xram_rsp_to_cc_send_fifo_put   = false;
    842   bool    xram_rsp_to_cc_send_fifo_get   = false;
    843   bool    xram_rsp_to_cc_send_fifo_inst  = false;
    844   size_t  xram_rsp_to_cc_send_fifo_srcid = 0;
    845 
    846   bool    config_to_cc_send_fifo_put   = false;
    847   bool    config_to_cc_send_fifo_get   = false;
    848   bool    config_to_cc_send_fifo_inst  = false;
    849   size_t  config_to_cc_send_fifo_srcid = 0;
    850 
    851   bool    cas_to_cc_send_fifo_put   = false;
    852   bool    cas_to_cc_send_fifo_get   = false;
    853   bool    cas_to_cc_send_fifo_inst  = false;
    854   size_t  cas_to_cc_send_fifo_srcid = 0;
    855 
    856   m_debug = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
    857 
    858 #if DEBUG_MEMC_GLOBAL
    859 if(m_debug)
    860 {
    861     std::cout
    862         << "---------------------------------------------"           << std::dec << std::endl
    863         << "MEM_CACHE "            << name()
    864         << " ; Time = "            << m_cpt_cycles                                << std::endl
    865         << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
    866         << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
    867         << " - CC_SEND FSM  = "    << cc_send_fsm_str[r_cc_send_fsm.read()]       << std::endl
    868         << " - CC_RECEIVE FSM  = " << cc_receive_fsm_str[r_cc_receive_fsm.read()] << std::endl
    869         << " - MULTI_ACK FSM  = "  << multi_ack_fsm_str[r_multi_ack_fsm.read()]   << std::endl
    870         << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
    871         << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
    872         << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
    873         << " - CLEANUP FSM    = "  << cleanup_fsm_str[r_cleanup_fsm.read()]       << std::endl
    874         << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
    875         << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
    876         << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
    877         << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
    878         << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
    879         << " - ALLOC_UPT FSM  = "  << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]   << std::endl
    880         << " - ALLOC_HEAP FSM = "  << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
    881 }
    882 #endif
    883 
    884   ////////////////////////////////////////////////////////////////////////////////////
    885   //    TGT_CMD FSM
    886   ////////////////////////////////////////////////////////////////////////////////////
    887   // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors,
    888   // and dispatch these commands to the proper FSM through dedicated FIFOs.
    889   //
    890   // There are 5 types of commands accepted in the XRAM segment:
    891   // - READ   : A READ request has a length of 1 VCI flit. It can be a single word
    892   //            or an entire cache line, depending on the PLEN value => READ FSM
    893   // - WRITE  : A WRITE request has a maximum length of 16 flits, and can only
    894   //            concern words in a same line => WRITE FSM
    895   // - CAS    : A CAS request has a length of 2 flits or 4 flits => CAS FSM
    896   // - LL     : An LL request has a length of 1 flit => READ FSM
    897   // - SC     : An SC request has a length of 2 flits. First flit contains the
    898   //            acces key, second flit the data to write => WRITE FSM.
    899   //
    900   // The READ/WRITE commands accepted in the configuration segment are targeting
    901   // configuration or status registers. They must contain one single flit.
    902   // - For almost all addressable registers, the response is returned immediately.
    903   // - For MEMC_CMD_TYPE, the response is delayed until the operation is completed.
    904   ////////////////////////////////////////////////////////////////////////////////////
    905 
    906 //std::cout << std::endl << "tgt_cmd_fsm" << std::endl;
    907 
    908   switch(r_tgt_cmd_fsm.read())
    909   {
    910     //////////////////
    911     case TGT_CMD_IDLE:     // waiting a VCI command (RAM or CONFIG)
    912     if(p_vci_tgt.cmdval)
    913     {
    914 
    915 #if DEBUG_MEMC_TGT_CMD
    916 if(m_debug)
    917 std::cout << "  <MEMC " << name()
    918           << " TGT_CMD_IDLE> Receive command from srcid "
    919           << std::hex << p_vci_tgt.srcid.read()
    920           << " / address " << std::hex << p_vci_tgt.address.read() << std::endl;
    921 #endif
    922         // checking segmentation violation
    923         addr_t      address  = p_vci_tgt.address.read();
    924         uint32_t    plen     = p_vci_tgt.plen.read();
    925         bool        found    = false;
    926         bool        config   = false;
    927 
    928         for(size_t seg_id = 0 ; (seg_id < m_nseg) and not found ; seg_id++)
    929         {
    930             if( m_seg[seg_id]->contains(address) and
    931                 m_seg[seg_id]->contains(address + plen - vci_param_int::B) )
    932             {
    933                 found = true;
    934                 if ( m_seg[seg_id]->special() ) config = true;
    935             }
     663        std::cout << "**********************************" << std::dec << std::endl;
     664        std::cout << "*** MEM_CACHE " << name() << std::endl;
     665        std::cout << "**********************************" << std::dec << std::endl;
     666        if (activity_counters) {
     667            std::cout << "   ----------------------------------" << std::dec << std::endl;
     668            std::cout << "   ---     Activity Counters      ---" << std::dec << std::endl;
     669            std::cout << "   ----------------------------------" << std::dec << std::endl;
     670            std::cout
     671                << "   - NUMBER OF CYCLES          = " << m_cpt_cycles << std::endl
     672                << std::endl
     673                << "   - LOCAL READ                = " << m_cpt_read_local << std::endl
     674                << "   - REMOTE READ               = " << m_cpt_read_remote << std::endl
     675                << "   - READ COST (FLITS * DIST)  = " << m_cpt_read_cost << std::endl
     676                << std::endl
     677                << "   - LOCAL WRITE               = " << m_cpt_write_local << std::endl
     678                << "   - REMOTE WRITE              = " << m_cpt_write_remote << std::endl
     679                << "   - WRITE FLITS LOCAL         = " << m_cpt_write_flits_local << std::endl
     680                << "   - WRITE FLITS REMOTE        = " << m_cpt_write_flits_remote << std::endl
     681                << "   - WRITE COST (FLITS * DIST) = " << m_cpt_write_cost << std::endl
     682                << std::endl
     683                << "   - LOCAL LL                  = " << m_cpt_ll_local << std::endl
     684                << "   - REMOTE LL                 = " << m_cpt_ll_remote << std::endl
     685                << "   - LL COST (FLITS * DIST)    = " << m_cpt_ll_cost << std::endl
     686                << std::endl
     687                << "   - LOCAL SC                  = " << m_cpt_sc_local << std::endl
     688                << "   - REMOTE SC                 = " << m_cpt_sc_remote << std::endl
     689                << "   - SC COST (FLITS * DIST)    = " << m_cpt_sc_cost << std::endl
     690                << std::endl
     691                << "   - LOCAL CAS                 = " << m_cpt_cas_local << std::endl
     692                << "   - REMOTE CAS                = " << m_cpt_cas_remote << std::endl
     693                << "   - CAS COST (FLITS * DIST)   = " << m_cpt_cas_cost << std::endl
     694                << std::endl
     695                << "   - REQUESTS TRIG. UPDATE     = " << m_cpt_update << std::endl
     696                << "   - LOCAL UPDATE              = " << m_cpt_update_local << std::endl
     697                << "   - REMOTE UPDATE             = " << m_cpt_update_remote << std::endl
     698                << "   - UPDT COST (FLITS * DIST)  = " << m_cpt_update_cost << std::endl
     699                << std::endl
     700                << "   - REQUESTS TRIG. M_INV      = " << m_cpt_m_inval << std::endl
     701                << "   - LOCAL M_INV               = " << m_cpt_m_inval_local << std::endl
     702                << "   - REMOTE M_INV              = " << m_cpt_m_inval_remote << std::endl
     703                << "   - M_INV COST (FLITS * DIST) = " << m_cpt_m_inval_cost << std::endl
     704                << std::endl
     705                << "   - BROADCAT INVAL            = " << m_cpt_br_inval << std::endl
     706                << std::endl
     707                << "   - LOCAL CLEANUP             = " << m_cpt_cleanup_local << std::endl
     708                << "   - REMOTE CLEANUP            = " << m_cpt_cleanup_remote << std::endl
     709                << "   - CLNUP COST (FLITS * DIST) = " << m_cpt_cleanup_cost << std::endl
     710                << std::endl
     711                << std::endl
     712                << "   - READ MISS                 = " << m_cpt_read_miss << std::endl
     713                << "   - WRITE MISS                = " << m_cpt_write_miss << std::endl
     714                << "   - WRITE DIRTY               = " << m_cpt_write_dirty << std::endl
     715                << "   - RD BLOCKED BY HIT IN TRT  = " << m_cpt_trt_rb << std::endl
     716                << "   - TRANS BLOCKED BY FULL TRT = " << m_cpt_trt_full << std::endl
     717                << "   - PUT                       = " << m_cpt_put << std::endl
     718                << "   - GET                       = " << m_cpt_get << std::endl;
    936719        }
    937720
    938         if ( not found )                /////////// out of segment error
    939         {
    940             r_tgt_cmd_fsm   = TGT_CMD_ERROR;
    941         }
    942         else if ( config )              /////////// configuration command
    943         {
    944             if ( not p_vci_tgt.eop.read() ) r_tgt_cmd_fsm = TGT_CMD_ERROR;
    945             else                            r_tgt_cmd_fsm = TGT_CMD_CONFIG;
    946         }
    947         else                            //////////// memory access
    948         {
    949             if ( p_vci_tgt.cmd.read() == vci_param_int::CMD_READ )
    950             {
    951                 // check that the pktid is either :
    952                 // TYPE_READ_DATA_UNC
    953                 // TYPE_READ_DATA_MISS
    954                 // TYPE_READ_INS_UNC
    955                 // TYPE_READ_INS_MISS
    956                 // ==> bit2 must be zero with the TSAR encoding
    957                 // ==> mask = 0b0100 = 0x4
    958                 assert( ((p_vci_tgt.pktid.read() & 0x4) == 0x0) and
    959                 "The type specified in the pktid field is incompatible with the READ CMD");
    960                 r_tgt_cmd_fsm = TGT_CMD_READ;
    961             }
    962             else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
    963             {
    964                 // check that the pktid is TYPE_WRITE
    965                 // ==> TYPE_WRITE = X100 with the TSAR encoding
    966                 // ==> mask = 0b0111 = 0x7
    967                 assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) and
    968                 "The type specified in the pktid field is incompatible with the WRITE CMD");
    969                 r_tgt_cmd_fsm = TGT_CMD_WRITE;
    970             }
    971             else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
    972             {
    973                 // check that the pktid is TYPE_LL
    974                 // ==> TYPE_LL = X110 with the TSAR encoding
    975                 // ==> mask = 0b0111 = 0x7
    976                 assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) and
    977                 "The type specified in the pktid field is incompatible with the LL CMD");
    978                 r_tgt_cmd_fsm = TGT_CMD_READ;
    979             }
    980             else if(p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
    981             {
    982                 // check that the pktid is either :
    983                 // TYPE_CAS
    984                 // TYPE_SC
    985                 // ==> TYPE_CAS = X101 with the TSAR encoding
    986                 // ==> TYPE_SC  = X111 with the TSAR encoding
    987                 // ==> mask = 0b0101 = 0x5
    988                 assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) and
    989                 "The type specified in the pktid field is incompatible with the NOP CMD");
    990 
    991                 if((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS) r_tgt_cmd_fsm = TGT_CMD_CAS;
    992                 else                                           r_tgt_cmd_fsm = TGT_CMD_WRITE;
    993             }
    994             else
    995             {
    996                 r_tgt_cmd_fsm = TGT_CMD_ERROR;
    997             }
     721        if (stats) {
     722            std::cout << "   ----------------------------------" << std::dec << std::endl;
     723            std::cout << "   ---      Calculated Stats      ---" << std::dec << std::endl;
     724            std::cout << "   ----------------------------------" << std::dec << std::endl;
     725            std::cout
     726                << "   - READ TOTAL            = " << m_cpt_read_local + m_cpt_read_remote << std::endl
     727                << "   - READ RATE             = " << (double) (m_cpt_read_local + m_cpt_read_remote) / m_cpt_cycles << std::endl
     728                << "   - LOCAL READ RATE       = " << (double) m_cpt_read_local / m_cpt_cycles << std::endl
     729                << "   - REMOTE READ RATE      = " << (double) m_cpt_read_remote / m_cpt_cycles << std::endl
     730                << "   - READ MISS RATE        = " << (double) m_cpt_read_miss / (m_cpt_read_local + m_cpt_read_remote) << std::endl
     731                << std::endl
     732                << "   - WRITE TOTAL           = " << m_cpt_write_local + m_cpt_write_remote << std::endl
     733                << "   - WRITE RATE            = " << (double) (m_cpt_write_local + m_cpt_write_remote) / m_cpt_cycles << std::endl
     734                << "   - LOCAL WRITE RATE      = " << (double) m_cpt_write_local / m_cpt_cycles << std::endl
     735                << "   - REMOTE WRITE RATE     = " << (double) m_cpt_write_remote / m_cpt_cycles << std::endl
     736                << "   - WRITE MISS RATE       = " << (double) m_cpt_write_miss / (m_cpt_write_local + m_cpt_write_remote) << std::endl
     737                << "   - WRITE BURST TOTAL     = " << m_cpt_write_flits_local + m_cpt_write_flits_remote << std::endl
     738                << "   - WRITE BURST AVERAGE   = " << (double) (m_cpt_write_flits_local + m_cpt_write_flits_remote) / (m_cpt_write_local + m_cpt_write_remote) << std::endl
     739                << "   - LOCAL WRITE BURST AV. = " << (double) m_cpt_write_flits_local / (m_cpt_write_local + m_cpt_write_remote) << std::endl
     740                << "   - REMOTE WRITE BURST AV = " << (double) m_cpt_write_flits_remote / (m_cpt_write_local + m_cpt_write_remote) << std::endl
     741                << std::endl
     742                << "   - UPDATE RATE                = " << (double) m_cpt_update / m_cpt_cycles << std::endl
     743                << "   - AV. UPDATE PER UP REQ      = " << (double) (m_cpt_update_local + m_cpt_update_remote) / m_cpt_update << std::endl
     744                << "   - AV. LOC UPDT PER UP REQ    = " << (double) m_cpt_update_local / m_cpt_update << std::endl
     745                << "   - AV. REMOTE UPDT PER UP REQ = " << (double) m_cpt_update_remote / m_cpt_update << std::endl
     746                << std::endl
     747                << "   - INVAL MULTICAST RATE  = " << (double) m_cpt_m_inval / m_cpt_cycles << std::endl
     748                << "   - AVE. INVAL PER M_INV  = " << (double) (m_cpt_m_inval_local + m_cpt_m_inval_remote) / m_cpt_m_inval << std::endl
     749                << "   - AV. LOC INV PER M_INV = " << (double) m_cpt_m_inval_local / m_cpt_m_inval << std::endl
     750                << "   - AV. REM INV PER M_INV = " << (double) m_cpt_m_inval_remote / m_cpt_m_inval << std::endl
     751                << std::endl
     752                << "   - INVAL BROADCAST RATE  = " << (double) m_cpt_br_inval / m_cpt_cycles << std::endl
     753                << "   - WRITE DIRTY RATE      = " << (double) m_cpt_write_dirty / m_cpt_cycles << std::endl
     754                << std::endl
     755                << "   - CLEANUP RATE          = " << (double) (m_cpt_cleanup_local + m_cpt_cleanup_remote) / m_cpt_cycles << std::endl
     756                << "   - LOCAL CLEANUP RATE    = " << (double) m_cpt_cleanup_local / m_cpt_cycles << std::endl
     757                << "   - REMOTE CLEANUP RATE   = " << (double) m_cpt_cleanup_remote / m_cpt_cycles << std::endl
     758                << "   - LL RATE               = " << (double) (m_cpt_ll_local + m_cpt_ll_remote) / m_cpt_cycles << std::endl
     759                << "   - LOCAL LL RATE         = " << (double) m_cpt_ll_local / m_cpt_cycles << std::endl
     760                << "   - REMOTE LL RATE        = " << (double) m_cpt_ll_remote / m_cpt_cycles << std::endl
     761                << "   - SC RATE               = " << (double) (m_cpt_sc_local + m_cpt_sc_remote) / m_cpt_cycles << std::endl
     762                << "   - LOCAL SC RATE         = " << (double) m_cpt_sc_local / m_cpt_cycles << std::endl
     763                << "   - REMOTE SC RATE        = " << (double) m_cpt_sc_remote / m_cpt_cycles << std::endl
     764                << "   - CAS RATE              = " << (double) (m_cpt_cas_local + m_cpt_cas_remote) / m_cpt_cycles << std::endl
     765                << "   - LOCAL CAS RATE        = " << (double) m_cpt_cas_local / m_cpt_cycles << std::endl
     766                << "   - REMOTE CAS RATE       = " << (double) m_cpt_cas_remote / m_cpt_cycles << std::endl;
    998767        }
    999768    }
    1000     break;
    1001 
    1002     ///////////////////
    1003     case TGT_CMD_ERROR:  // response error must be sent
    1004 
    1005     // wait if pending request
    1006     if(r_tgt_cmd_to_tgt_rsp_req.read()) break;
    1007 
    1008     // consume all the command packet flits before sending response error
    1009     if ( p_vci_tgt.cmdval and p_vci_tgt.eop )
     769
     770
     771    /////////////////////////////////
     772    tmpl(/**/)::~VciMemCache()
     773    /////////////////////////////////
    1010774    {
    1011         r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
    1012         r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
    1013         r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
    1014         r_tgt_cmd_to_tgt_rsp_req   = true;
    1015         r_tgt_cmd_to_tgt_rsp_error = 1;
    1016         r_tgt_cmd_fsm              = TGT_CMD_IDLE;
     775        delete [] r_ixr_rsp_to_xram_rsp_rok;
     776
     777        delete [] r_xram_rsp_victim_data;
     778        delete [] r_xram_rsp_to_tgt_rsp_data;
     779
     780        delete [] r_read_data;
     781        delete [] r_read_to_tgt_rsp_data;
     782
     783        delete [] r_write_data;
     784        delete [] r_write_be;
     785        delete [] r_write_to_cc_send_data;
     786        print_stats();
     787    }
     788
     789    //////////////////////////////////
     790    tmpl(void) ::transition()
     791    //////////////////////////////////
     792    {
     793        using soclib::common::uint32_log2;
     794
     795        // RESET
     796        if (! p_resetn.read())
     797        {
     798
     799            // Initializing FSMs
     800            r_tgt_cmd_fsm    = TGT_CMD_IDLE;
     801            r_config_fsm     = CONFIG_IDLE;
     802            r_tgt_rsp_fsm    = TGT_RSP_TGT_CMD_IDLE;
     803            r_cc_send_fsm    = CC_SEND_XRAM_RSP_IDLE;
     804            r_cc_receive_fsm = CC_RECEIVE_IDLE;
     805            r_multi_ack_fsm  = MULTI_ACK_IDLE;
     806            r_read_fsm       = READ_IDLE;
     807            r_write_fsm      = WRITE_IDLE;
     808            r_cas_fsm        = CAS_IDLE;
     809            r_cleanup_fsm    = CLEANUP_IDLE;
     810            r_alloc_dir_fsm  = ALLOC_DIR_RESET;
     811            r_alloc_heap_fsm = ALLOC_HEAP_RESET;
     812            r_alloc_trt_fsm  = ALLOC_TRT_READ;
     813            r_alloc_upt_fsm  = ALLOC_UPT_WRITE;
     814            r_alloc_ivt_fsm  = ALLOC_IVT_XRAM_RSP;
     815            r_ixr_rsp_fsm    = IXR_RSP_IDLE;
     816            r_xram_rsp_fsm   = XRAM_RSP_IDLE;
     817            r_ixr_cmd_fsm    = IXR_CMD_READ_IDLE;
     818
     819            m_debug                = false;
     820            m_debug_previous_valid = false;
     821            m_debug_previous_dirty = false;
     822            m_debug_previous_count = 0;
     823
     824            //  Initializing Tables
     825            m_trt.init();
     826            m_upt.init();
     827            m_ivt.init();
     828            m_llsc_table.init();
     829
     830            // initializing FIFOs and communication Buffers
     831
     832            m_cmd_read_addr_fifo.init();
     833            m_cmd_read_length_fifo.init();
     834            m_cmd_read_srcid_fifo.init();
     835            m_cmd_read_trdid_fifo.init();
     836            m_cmd_read_pktid_fifo.init();
     837
     838            m_cmd_write_addr_fifo.init();
     839            m_cmd_write_eop_fifo.init();
     840            m_cmd_write_srcid_fifo.init();
     841            m_cmd_write_trdid_fifo.init();
     842            m_cmd_write_pktid_fifo.init();
     843            m_cmd_write_data_fifo.init();
     844
     845            m_cmd_cas_addr_fifo.init()  ;
     846            m_cmd_cas_srcid_fifo.init() ;
     847            m_cmd_cas_trdid_fifo.init() ;
     848            m_cmd_cas_pktid_fifo.init() ;
     849            m_cmd_cas_wdata_fifo.init() ;
     850            m_cmd_cas_eop_fifo.init()   ;
     851
     852            r_config_cmd  = MEMC_CMD_NOP;
     853            r_config_lock = false;
     854
     855            m_config_to_cc_send_inst_fifo.init();
     856            m_config_to_cc_send_srcid_fifo.init();
     857
     858            r_tgt_cmd_to_tgt_rsp_req = false;
     859
     860            r_read_to_tgt_rsp_req = false;
     861            r_read_to_ixr_cmd_req = false;
     862
     863            r_write_to_tgt_rsp_req          = false;
     864            r_write_to_ixr_cmd_req          = false;
     865            r_write_to_cc_send_multi_req    = false;
     866            r_write_to_cc_send_brdcast_req  = false;
     867            r_write_to_multi_ack_req        = false;
     868
     869            m_write_to_cc_send_inst_fifo.init();
     870            m_write_to_cc_send_srcid_fifo.init();
     871
     872            r_cleanup_to_tgt_rsp_req      = false;
     873
     874            m_cc_receive_to_cleanup_fifo.init();
     875
     876            r_multi_ack_to_tgt_rsp_req    = false;
     877
     878            m_cc_receive_to_multi_ack_fifo.init();
     879
     880            r_cas_to_tgt_rsp_req          = false;
     881            r_cas_cpt                     = 0    ;
     882            r_cas_lfsr                    = -1   ;
     883            r_cas_to_ixr_cmd_req          = false;
     884            r_cas_to_cc_send_multi_req    = false;
     885            r_cas_to_cc_send_brdcast_req  = false;
     886
     887            m_cas_to_cc_send_inst_fifo.init();
     888            m_cas_to_cc_send_srcid_fifo.init();
     889
     890            for (size_t i = 0; i < m_trt_lines ; i++)
     891            {
     892                r_ixr_rsp_to_xram_rsp_rok[i] = false;
     893            }
     894
     895            r_xram_rsp_to_tgt_rsp_req          = false;
     896            r_xram_rsp_to_cc_send_multi_req    = false;
     897            r_xram_rsp_to_cc_send_brdcast_req  = false;
     898            r_xram_rsp_to_ixr_cmd_req          = false;
     899            r_xram_rsp_trt_index               = 0;
     900
     901            m_xram_rsp_to_cc_send_inst_fifo.init();
     902            m_xram_rsp_to_cc_send_srcid_fifo.init();
     903
     904            r_alloc_dir_reset_cpt  = 0;
     905            r_alloc_heap_reset_cpt = 0;
     906
     907            r_tgt_rsp_key_sent  = false;
     908
     909            // Activity counters
     910            m_cpt_cycles             = 0;
     911            m_cpt_read_local         = 0;
     912            m_cpt_read_remote        = 0;
     913            m_cpt_read_cost          = 0;
     914            m_cpt_write_local        = 0;
     915            m_cpt_write_remote       = 0;
     916            m_cpt_write_flits_local  = 0;
     917            m_cpt_write_flits_remote = 0;
     918            m_cpt_write_cost         = 0;
     919            m_cpt_ll_local           = 0;
     920            m_cpt_ll_remote          = 0;
     921            m_cpt_ll_cost            = 0;
     922            m_cpt_sc_local           = 0;
     923            m_cpt_sc_remote          = 0;
     924            m_cpt_sc_cost            = 0;
     925            m_cpt_cas_local          = 0;
     926            m_cpt_cas_remote         = 0;
     927            m_cpt_cas_cost           = 0;
     928            m_cpt_update             = 0;
     929            m_cpt_update_local       = 0;
     930            m_cpt_update_remote      = 0;
     931            m_cpt_update_cost        = 0;
     932            m_cpt_m_inval            = 0;
     933            m_cpt_m_inval_local      = 0;
     934            m_cpt_m_inval_remote     = 0;
     935            m_cpt_m_inval_cost       = 0;
     936            m_cpt_br_inval           = 0;
     937            m_cpt_cleanup_local      = 0;
     938            m_cpt_cleanup_remote     = 0;
     939            m_cpt_cleanup_cost       = 0;
     940
     941            m_cpt_read_miss     = 0;
     942            m_cpt_write_miss    = 0;
     943            m_cpt_write_dirty   = 0;
     944            m_cpt_trt_rb        = 0;
     945            m_cpt_trt_full      = 0;
     946            m_cpt_get           = 0;
     947            m_cpt_put           = 0;
     948
     949            return;
     950        }
     951
     952        bool   cmd_read_fifo_put = false;
     953        bool   cmd_read_fifo_get = false;
     954
     955        bool   cmd_write_fifo_put = false;
     956        bool   cmd_write_fifo_get = false;
     957
     958        bool   cmd_cas_fifo_put = false;
     959        bool   cmd_cas_fifo_get = false;
     960
     961        bool   cc_receive_to_cleanup_fifo_get = false;
     962        bool   cc_receive_to_cleanup_fifo_put = false;
     963
     964        bool   cc_receive_to_multi_ack_fifo_get = false;
     965        bool   cc_receive_to_multi_ack_fifo_put = false;
     966
     967        bool   write_to_cc_send_fifo_put   = false;
     968        bool   write_to_cc_send_fifo_get   = false;
     969        bool   write_to_cc_send_fifo_inst  = false;
     970        size_t write_to_cc_send_fifo_srcid = 0;
     971
     972        bool   xram_rsp_to_cc_send_fifo_put   = false;
     973        bool   xram_rsp_to_cc_send_fifo_get   = false;
     974        bool   xram_rsp_to_cc_send_fifo_inst  = false;
     975        size_t xram_rsp_to_cc_send_fifo_srcid = 0;
     976
     977        bool   config_to_cc_send_fifo_put   = false;
     978        bool   config_to_cc_send_fifo_get   = false;
     979        bool   config_to_cc_send_fifo_inst  = false;
     980        size_t config_to_cc_send_fifo_srcid = 0;
     981
     982        bool   cas_to_cc_send_fifo_put   = false;
     983        bool   cas_to_cc_send_fifo_get   = false;
     984        bool   cas_to_cc_send_fifo_inst  = false;
     985        size_t cas_to_cc_send_fifo_srcid = 0;
     986
     987        m_debug = (m_cpt_cycles > m_debug_start_cycle) and m_debug_ok;
     988
     989#if DEBUG_MEMC_GLOBAL
     990        if (m_debug)
     991        {
     992            std::cout
     993                << "---------------------------------------------"           << std::dec << std::endl
     994                << "MEM_CACHE "            << name()
     995                << " ; Time = "            << m_cpt_cycles                                << std::endl
     996                << " - TGT_CMD FSM    = "  << tgt_cmd_fsm_str[r_tgt_cmd_fsm.read()]       << std::endl
     997                << " - TGT_RSP FSM    = "  << tgt_rsp_fsm_str[r_tgt_rsp_fsm.read()]       << std::endl
     998                << " - CC_SEND FSM  = "    << cc_send_fsm_str[r_cc_send_fsm.read()]       << std::endl
     999                << " - CC_RECEIVE FSM  = " << cc_receive_fsm_str[r_cc_receive_fsm.read()] << std::endl
     1000                << " - MULTI_ACK FSM  = "  << multi_ack_fsm_str[r_multi_ack_fsm.read()]   << std::endl
     1001                << " - READ FSM       = "  << read_fsm_str[r_read_fsm.read()]             << std::endl
     1002                << " - WRITE FSM      = "  << write_fsm_str[r_write_fsm.read()]           << std::endl
     1003                << " - CAS FSM        = "  << cas_fsm_str[r_cas_fsm.read()]               << std::endl
     1004                << " - CLEANUP FSM    = "  << cleanup_fsm_str[r_cleanup_fsm.read()]       << std::endl
     1005                << " - IXR_CMD FSM    = "  << ixr_cmd_fsm_str[r_ixr_cmd_fsm.read()]       << std::endl
     1006                << " - IXR_RSP FSM    = "  << ixr_rsp_fsm_str[r_ixr_rsp_fsm.read()]       << std::endl
     1007                << " - XRAM_RSP FSM   = "  << xram_rsp_fsm_str[r_xram_rsp_fsm.read()]     << std::endl
     1008                << " - ALLOC_DIR FSM  = "  << alloc_dir_fsm_str[r_alloc_dir_fsm.read()]   << std::endl
     1009                << " - ALLOC_TRT FSM  = "  << alloc_trt_fsm_str[r_alloc_trt_fsm.read()]   << std::endl
     1010                << " - ALLOC_UPT FSM  = "  << alloc_upt_fsm_str[r_alloc_upt_fsm.read()]   << std::endl
     1011                << " - ALLOC_HEAP FSM = "  << alloc_heap_fsm_str[r_alloc_heap_fsm.read()] << std::endl;
     1012        }
     1013#endif
     1014
     1015        ////////////////////////////////////////////////////////////////////////////////////
     1016        //    TGT_CMD FSM
     1017        ////////////////////////////////////////////////////////////////////////////////////
     1018        // The TGT_CMD_FSM controls the incoming VCI command pakets from the processors,
     1019        // and dispatch these commands to the proper FSM through dedicated FIFOs.
     1020        //
     1021        // There are 5 types of commands accepted in the XRAM segment:
     1022        // - READ   : A READ request has a length of 1 VCI flit. It can be a single word
     1023        //            or an entire cache line, depending on the PLEN value => READ FSM
     1024        // - WRITE  : A WRITE request has a maximum length of 16 flits, and can only
     1025        //            concern words in a same line => WRITE FSM
     1026        // - CAS    : A CAS request has a length of 2 flits or 4 flits => CAS FSM
     1027        // - LL     : An LL request has a length of 1 flit => READ FSM
     1028        // - SC     : An SC request has a length of 2 flits. First flit contains the
     1029        //            acces key, second flit the data to write => WRITE FSM.
     1030        //
     1031        // The READ/WRITE commands accepted in the configuration segment are targeting
     1032        // configuration or status registers. They must contain one single flit.
     1033        // - For almost all addressable registers, the response is returned immediately.
     1034        // - For MEMC_CMD_TYPE, the response is delayed until the operation is completed.
     1035        ////////////////////////////////////////////////////////////////////////////////////
     1036
     1037
     1038        switch (r_tgt_cmd_fsm.read())
     1039        {
     1040            //////////////////
     1041            case TGT_CMD_IDLE:     // waiting a VCI command (RAM or CONFIG)
     1042                if (p_vci_tgt.cmdval)
     1043                {
    10171044
    10181045#if DEBUG_MEMC_TGT_CMD
    1019 if(m_debug)
    1020   std::cout << "  <MEMC " << name()
    1021     << " TGT_CMD_ERROR> Segmentation violation:"
    1022     << " address = " << std::hex << p_vci_tgt.address.read()
    1023     << " / srcid = " << p_vci_tgt.srcid.read()
    1024     << " / trdid = " << p_vci_tgt.trdid.read()
    1025     << " / pktid = " << p_vci_tgt.pktid.read()
    1026     << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
    1027 #endif
    1028 
    1029     }
    1030     break;
    1031 
    1032     ////////////////////
    1033     case TGT_CMD_CONFIG:    // execute config request and return response
    1034     {
    1035         addr_t   seg_base = m_seg[m_seg_config]->baseAddress();
    1036         addr_t   address  = p_vci_tgt.address.read();
    1037         size_t   cell     = (address - seg_base)/vci_param_int::B;
    1038      
    1039         bool     need_rsp;
    1040         size_t   error; 
    1041         uint32_t rdata = 0;         // default value
    1042         uint32_t wdata = p_vci_tgt.wdata.read();
    1043 
    1044         if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)         // get lock
    1045              and (cell == MEMC_LOCK) )
     1046                    if (m_debug)
     1047                        std::cout << "  <MEMC " << name()
     1048                            << " TGT_CMD_IDLE> Receive command from srcid "
     1049                            << std::hex << p_vci_tgt.srcid.read()
     1050                            << " / address " << std::hex << p_vci_tgt.address.read() << std::endl;
     1051#endif
     1052                    // checking segmentation violation
     1053                    addr_t   address = p_vci_tgt.address.read();
     1054                    uint32_t plen    = p_vci_tgt.plen.read();
     1055                    bool     found   = false;
     1056                    bool     config  = false;
     1057
     1058                    for (size_t seg_id = 0; (seg_id < m_nseg) && !found; seg_id++)
     1059                    {
     1060                        if (m_seg[seg_id]->contains(address) &&
     1061                                m_seg[seg_id]->contains(address + plen - vci_param_int::B))
     1062                        {
     1063                            found = true;
     1064                            if (m_seg[seg_id]->special()) config = true;
     1065                        }
     1066                    }
     1067
     1068                    if (!found)                /////////// out of segment error
     1069                    {
     1070                        r_tgt_cmd_fsm = TGT_CMD_ERROR;
     1071                    }
     1072                    else if (config)              /////////// configuration command
     1073                    {
     1074                        if (!p_vci_tgt.eop.read()) r_tgt_cmd_fsm = TGT_CMD_ERROR;
     1075                        else                       r_tgt_cmd_fsm = TGT_CMD_CONFIG;
     1076                    }
     1077                    else                            //////////// memory access
     1078                    {
     1079                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)
     1080                        {
     1081                            // check that the pktid is either :
     1082                            // TYPE_READ_DATA_UNC
     1083                            // TYPE_READ_DATA_MISS
     1084                            // TYPE_READ_INS_UNC
     1085                            // TYPE_READ_INS_MISS
     1086                            // ==> bit2 must be zero with the TSAR encoding
     1087                            // ==> mask = 0b0100 = 0x4
     1088                            assert(((p_vci_tgt.pktid.read() & 0x4) == 0x0) and
     1089                                    "The type specified in the pktid field is incompatible with the READ CMD");
     1090                            r_tgt_cmd_fsm = TGT_CMD_READ;
     1091                        }
     1092                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
     1093                        {
     1094                            // check that the pktid is TYPE_WRITE
     1095                            // ==> TYPE_WRITE = X100 with the TSAR encoding
     1096                            // ==> mask = 0b0111 = 0x7
     1097                            assert(((p_vci_tgt.pktid.read() & 0x7) == 0x4) and
     1098                                    "The type specified in the pktid field is incompatible with the WRITE CMD");
     1099                            r_tgt_cmd_fsm = TGT_CMD_WRITE;
     1100                        }
     1101                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ)
     1102                        {
     1103                            // check that the pktid is TYPE_LL
     1104                            // ==> TYPE_LL = X110 with the TSAR encoding
     1105                            // ==> mask = 0b0111 = 0x7
     1106                            assert(((p_vci_tgt.pktid.read() & 0x7) == 0x6) and
     1107                                    "The type specified in the pktid field is incompatible with the LL CMD");
     1108                            r_tgt_cmd_fsm = TGT_CMD_READ;
     1109                        }
     1110                        else if (p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP)
     1111                        {
     1112                            // check that the pktid is either :
     1113                            // TYPE_CAS
     1114                            // TYPE_SC
     1115                            // ==> TYPE_CAS = X101 with the TSAR encoding
     1116                            // ==> TYPE_SC  = X111 with the TSAR encoding
     1117                            // ==> mask = 0b0101 = 0x5
     1118                            assert(((p_vci_tgt.pktid.read() & 0x5) == 0x5) and
     1119                                    "The type specified in the pktid field is incompatible with the NOP CMD");
     1120
     1121                            if ((p_vci_tgt.pktid.read() & 0x7) == TYPE_CAS) r_tgt_cmd_fsm = TGT_CMD_CAS;
     1122                            else                                            r_tgt_cmd_fsm = TGT_CMD_WRITE;
     1123                        }
     1124                        else
     1125                        {
     1126                            r_tgt_cmd_fsm = TGT_CMD_ERROR;
     1127                        }
     1128                    }
     1129                }
     1130                break;
     1131
     1132                ///////////////////
     1133            case TGT_CMD_ERROR:  // response error must be sent
     1134
     1135                // wait if pending request
     1136                if (r_tgt_cmd_to_tgt_rsp_req.read()) break;
     1137
     1138                // consume all the command packet flits before sending response error
     1139                if (p_vci_tgt.cmdval and p_vci_tgt.eop)
     1140                {
     1141                    r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
     1142                    r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
     1143                    r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
     1144                    r_tgt_cmd_to_tgt_rsp_req   = true;
     1145                    r_tgt_cmd_to_tgt_rsp_error = 1;
     1146                    r_tgt_cmd_fsm              = TGT_CMD_IDLE;
     1147
     1148#if DEBUG_MEMC_TGT_CMD
     1149                    if (m_debug)
     1150                        std::cout << "  <MEMC " << name()
     1151                            << " TGT_CMD_ERROR> Segmentation violation:"
     1152                            << " address = " << std::hex << p_vci_tgt.address.read()
     1153                            << " / srcid = " << p_vci_tgt.srcid.read()
     1154                            << " / trdid = " << p_vci_tgt.trdid.read()
     1155                            << " / pktid = " << p_vci_tgt.pktid.read()
     1156                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
     1157#endif
     1158
     1159                }
     1160                break;
     1161
     1162                ////////////////////
     1163            case TGT_CMD_CONFIG:    // execute config request and return response
     1164                {
     1165                    addr_t   seg_base = m_seg[m_seg_config]->baseAddress();
     1166                    addr_t   address  = p_vci_tgt.address.read();
     1167                    size_t   cell     = (address - seg_base) / vci_param_int::B;
     1168
     1169                    bool     need_rsp;
     1170                    size_t   error; 
     1171                    uint32_t rdata = 0;         // default value
     1172                    uint32_t wdata = p_vci_tgt.wdata.read();
     1173
     1174                    if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_READ)         // get lock
     1175                            and (cell == MEMC_LOCK))
     1176                    {
     1177                        rdata            = (uint32_t) r_config_lock.read();
     1178                        need_rsp         = true;
     1179                        error            = 0;
     1180                        r_config_lock    = true;
     1181                        if (rdata == 0)
     1182                        {
     1183                            r_tgt_cmd_srcid = p_vci_tgt.srcid.read();
     1184                            r_tgt_cmd_trdid = p_vci_tgt.trdid.read();
     1185                            r_tgt_cmd_pktid = p_vci_tgt.pktid.read();
     1186                        }
     1187                    }
     1188                    else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)  // release lock
     1189                            and (cell == MEMC_LOCK))
     1190                    {
     1191                        need_rsp      = true;
     1192                        error         = 0;
     1193                        r_config_lock = false;
     1194                    }
     1195                    else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_lo
     1196                            and (cell == MEMC_ADDR_LO))
     1197                    {
     1198                        assert( ((wdata % (m_words * vci_param_int::B)) == 0) and
     1199                                "VCI_MEM_CACHE CONFIG ERROR: The buffer must be aligned on a cache line");
     1200
     1201                        need_rsp         = true;
     1202                        error            = 0;
     1203                        r_config_address = (r_config_address.read() & 0xFFFFFFFF00000000LL) |
     1204                            ((addr_t)wdata);
     1205                    }
     1206                    else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_hi
     1207                            and (cell == MEMC_ADDR_HI))
     1208
     1209                    {
     1210                        need_rsp         = true;
     1211                        error            = 0;
     1212                        r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) |
     1213                            (((addr_t) wdata) << 32);
     1214                    }
     1215                    else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set buf_lines
     1216                            and (cell == MEMC_BUF_LENGTH))
     1217                    {
     1218                        need_rsp         = true;
     1219                        error            = 0;
     1220                        size_t lines     = wdata / (m_words << 2);
     1221                        if (wdata % (m_words << 2)) lines++;
     1222                        r_config_cmd_lines = lines;
     1223                        r_config_rsp_lines = lines;
     1224                    }
     1225                    else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set cmd type
     1226                            and (cell == MEMC_CMD_TYPE))
     1227                    {
     1228                        need_rsp         = false;
     1229                        error            = 0;
     1230                        r_config_cmd     = wdata;
     1231
     1232                        // prepare delayed response from CONFIG FSM
     1233                        r_config_srcid   = p_vci_tgt.srcid.read();
     1234                        r_config_trdid   = p_vci_tgt.trdid.read();
     1235                        r_config_pktid   = p_vci_tgt.pktid.read();
     1236                    }
     1237                    else
     1238                    {
     1239                        need_rsp         = true;
     1240                        error            = 1;
     1241                    }
     1242
     1243                    if (need_rsp)
     1244                    {
     1245                        // blocked if previous pending request to TGT_RSP FSM
     1246                        if (r_tgt_cmd_to_tgt_rsp_req.read()) break;
     1247
     1248                        r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
     1249                        r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
     1250                        r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
     1251                        r_tgt_cmd_to_tgt_rsp_req   = true;
     1252                        r_tgt_cmd_to_tgt_rsp_error = error;
     1253                        r_tgt_cmd_to_tgt_rsp_rdata = rdata;
     1254                        r_tgt_cmd_fsm              = TGT_CMD_IDLE;
     1255                    }
     1256                    else
     1257                    {
     1258                        r_tgt_cmd_fsm              = TGT_CMD_IDLE;
     1259                    }
     1260
     1261#if DEBUG_MEMC_TGT_CMD
     1262                    if (m_debug)
     1263                        std::cout << "  <MEMC " << name() << " TGT_CMD_CONFIG> Configuration request:"
     1264                            << " address = " << std::hex << p_vci_tgt.address.read()
     1265                            << " / wdata = " << p_vci_tgt.wdata.read()
     1266                            << " / need_rsp = " << need_rsp
     1267                            << " / error = " << error << std::endl;
     1268#endif
     1269                    break;
     1270                }
     1271                //////////////////
     1272            case TGT_CMD_READ:    // Push a read request into read fifo
     1273
     1274                // check that the read does not cross a cache line limit.
     1275                if (((m_x[(addr_t) p_vci_tgt.address.read()] + (p_vci_tgt.plen.read() >> 2)) > 16) and
     1276                        (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ))
     1277                {
     1278                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
     1279                        << " illegal address/plen for VCI read command" << std::endl;
     1280                    exit(0);
     1281                }
     1282                // check single flit
     1283                if (!p_vci_tgt.eop.read())
     1284                {
     1285                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
     1286                        << " read command packet must contain one single flit" << std::endl;
     1287                    exit(0);
     1288                }
     1289                // check plen for LL
     1290                if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) and
     1291                        (p_vci_tgt.plen.read() != 8))
     1292                {
     1293                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
     1294                        << " ll command packets must have a plen of 8" << std::endl;
     1295                    exit(0);
     1296                }
     1297
     1298                if (p_vci_tgt.cmdval and m_cmd_read_addr_fifo.wok())
     1299                {
     1300
     1301#if DEBUG_MEMC_TGT_CMD
     1302                    if (m_debug)
     1303                        std::cout << "  <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:"
     1304                            << " address = " << std::hex << p_vci_tgt.address.read()
     1305                            << " / srcid = " << p_vci_tgt.srcid.read()
     1306                            << " / trdid = " << p_vci_tgt.trdid.read()
     1307                            << " / pktid = " << p_vci_tgt.pktid.read()
     1308                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
     1309#endif
     1310                    cmd_read_fifo_put = true;
     1311                    // <Activity counters>
     1312                    if (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) {
     1313                        if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_ll_local++;
     1314                        else                                      m_cpt_ll_remote++;
     1315                        m_cpt_ll_cost += req_distance(p_vci_tgt.srcid.read()); // LL on a single word
     1316                    }
     1317                    else {
     1318                        if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_read_local++;
     1319                        else                                      m_cpt_read_remote++;
     1320                        m_cpt_read_cost += m_words * req_distance(p_vci_tgt.srcid.read());
     1321                    }
     1322                    // </Activity counters>
     1323                    r_tgt_cmd_fsm = TGT_CMD_IDLE;
     1324                }
     1325                break;
     1326
     1327                ///////////////////
     1328            case TGT_CMD_WRITE:
     1329                if (p_vci_tgt.cmdval and m_cmd_write_addr_fifo.wok())
     1330                {
     1331
     1332#if DEBUG_MEMC_TGT_CMD
     1333                    if (m_debug)
     1334                        std::cout << "  <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:"
     1335                            << " address = " << std::hex << p_vci_tgt.address.read()
     1336                            << " / srcid = " << p_vci_tgt.srcid.read()
     1337                            << " / trdid = " << p_vci_tgt.trdid.read()
     1338                            << " / pktid = " << p_vci_tgt.pktid.read()
     1339                            << " / wdata = " << p_vci_tgt.wdata.read()
     1340                            << " / be = " << p_vci_tgt.be.read()
     1341                            << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
     1342#endif
     1343                    cmd_write_fifo_put = true;
     1344                    // <Activity counters>
     1345                    if (p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP) {
     1346                        m_cpt_sc_cost += req_distance(p_vci_tgt.srcid.read());
     1347                    }
     1348                    else {
     1349                        if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_write_flits_local++;
     1350                        else                                      m_cpt_write_flits_remote++;
     1351                        m_cpt_write_cost += req_distance(p_vci_tgt.srcid.read());
     1352                    }
     1353                    // </Activity counters>
     1354
     1355                    if (p_vci_tgt.eop) {
     1356                        // <Activity counters>
     1357                        if (p_vci_tgt.cmd.read() == vci_param_int::CMD_NOP) {
     1358                            if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_sc_local++;
     1359                            else                                      m_cpt_sc_remote++;
     1360
     1361                        }
     1362                        else {
     1363                            if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_write_local++;
     1364                            else                                      m_cpt_write_remote++;
     1365                        }
     1366                        // </Activity counters>
     1367                        r_tgt_cmd_fsm = TGT_CMD_IDLE;
     1368                    }
     1369                }
     1370                break;
     1371
     1372                /////////////////
     1373            case TGT_CMD_CAS:
     1374                if ((p_vci_tgt.plen.read() != 8) and (p_vci_tgt.plen.read() != 16))
     1375                {
     1376                    std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
     1377                        << "illegal format for CAS command " << std::endl;
     1378                    exit(0);
     1379                }
     1380
     1381                if (p_vci_tgt.cmdval and m_cmd_cas_addr_fifo.wok())
     1382                {
     1383
     1384#if DEBUG_MEMC_TGT_CMD
     1385                    if (m_debug)
     1386                        std::cout << "  <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
     1387                            << " address = " << std::hex << p_vci_tgt.address.read()
     1388                            << " srcid = " << p_vci_tgt.srcid.read()
     1389                            << " trdid = " << p_vci_tgt.trdid.read()
     1390                            << " pktid = " << p_vci_tgt.pktid.read()
     1391                            << " wdata = " << p_vci_tgt.wdata.read()
     1392                            << " be = " << p_vci_tgt.be.read()
     1393                            << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
     1394#endif
     1395                    cmd_cas_fifo_put = true;
     1396                    if (p_vci_tgt.eop) {
     1397                        // <Activity counters>
     1398                        if (is_local_req(p_vci_tgt.srcid.read())) m_cpt_cas_local++;
     1399                        else                                      m_cpt_cas_remote++;
     1400                        m_cpt_cas_cost += req_distance(p_vci_tgt.srcid.read());
     1401                        // </Activity counters>
     1402                        r_tgt_cmd_fsm = TGT_CMD_IDLE;
     1403                    }
     1404                }
     1405                break;
     1406        } // end switch tgt_cmd_fsm
     1407
     1408        /////////////////////////////////////////////////////////////////////////
     1409        //    MULTI_ACK FSM
     1410        /////////////////////////////////////////////////////////////////////////
     1411        // This FSM controls the response to the multicast update requests sent
     1412        // by the memory cache to the L1 caches and update the UPT.
     1413        //
     1414        // - The FSM decrements the proper entry in UPT,
     1415        //   and clear the UPT entry when all responses have been received.
     1416        // - If required, it sends a request to the TGT_RSP FSM to complete
     1417        //   a pending  write transaction.
     1418        //
     1419        // All those multi-ack packets are one flit packet.
     1420        // The index in the UPT is defined in the TRDID field.
     1421        ////////////////////////////////////////////////////////////////////////
     1422
     1423        //std::cout << std::endl << "multi_ack_fsm" << std::endl;
     1424
     1425        switch(r_multi_ack_fsm.read())
    10461426        {
    1047             rdata            = (uint32_t)r_config_lock.read();
    1048             need_rsp         = true;
    1049             error            = 0;
    1050             r_config_lock    = true;
    1051             if ( rdata == 0 )
    1052             {
    1053                 r_tgt_cmd_srcid = p_vci_tgt.srcid.read();
    1054                 r_tgt_cmd_trdid = p_vci_tgt.trdid.read();
    1055                 r_tgt_cmd_pktid = p_vci_tgt.pktid.read();
    1056             }
    1057         }
    1058         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)  // release lock
    1059                    and (cell == MEMC_LOCK) )
     1427            ////////////////////
     1428            case MULTI_ACK_IDLE:
     1429                {
     1430                    bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok();
     1431
     1432                    // No CC_RECEIVE FSM request and no WRITE FSM request
     1433                    if (not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read())
     1434                        break;
     1435
     1436                    uint8_t updt_index;
     1437
     1438                    // handling WRITE FSM request to decrement update table response
     1439                    // counter if no CC_RECEIVE FSM request
     1440                    if (not multi_ack_fifo_rok)
     1441                    {
     1442                        updt_index               = r_write_to_multi_ack_upt_index.read();
     1443                        r_write_to_multi_ack_req = false;
     1444                    }
     1445                    // Handling CC_RECEIVE FSM request
     1446                    else
     1447                    {
     1448                        uint64_t flit = m_cc_receive_to_multi_ack_fifo.read();
     1449                        updt_index    = DspinDhccpParam::dspin_get(flit,
     1450                                DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
     1451
     1452                        cc_receive_to_multi_ack_fifo_get = true;
     1453                    }
     1454
     1455                    assert((updt_index < m_upt.size()) and
     1456                            "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : "
     1457                            "index too large for UPT");
     1458
     1459                    r_multi_ack_upt_index = updt_index;
     1460                    r_multi_ack_fsm       = MULTI_ACK_UPT_LOCK;
     1461
     1462#if DEBUG_MEMC_MULTI_ACK
     1463                    if (m_debug)
     1464                    {
     1465                        if (multi_ack_fifo_rok)
     1466                        {
     1467                            std::cout << "  <MEMC " << name()
     1468                                << " MULTI_ACK_IDLE> Response for UPT entry "
     1469                                << (size_t)updt_index << std::endl;
     1470                        }
     1471                        else
     1472                        {
     1473                            std::cout << "  <MEMC " << name()
     1474                                << " MULTI_ACK_IDLE> Write FSM request to decrement UPT entry "
     1475                                << updt_index << std::endl;
     1476                        }
     1477                    }
     1478#endif
     1479                    break;
     1480                }
     1481
     1482                ////////////////////////
     1483            case MULTI_ACK_UPT_LOCK:
     1484                {
     1485                    // get lock to the UPDATE table
     1486                    if (r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
     1487
     1488                    // decrement the number of expected responses
     1489                    size_t count = 0;
     1490                    bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
     1491
     1492                    if (not valid)
     1493                    {
     1494                        std::cout << "VCI_MEM_CACHE ERROR " << name()
     1495                            << " MULTI_ACK_UPT_LOCK state" << std::endl
     1496                            << "unsuccessful access to decrement the UPT" << std::endl;
     1497                        exit(0);
     1498                    }
     1499
     1500                    if (count == 0)
     1501                    {
     1502                        r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR;
     1503                    }
     1504                    else
     1505                    {
     1506                        r_multi_ack_fsm = MULTI_ACK_IDLE;
     1507                    }
     1508
     1509#if DEBUG_MEMC_MULTI_ACK
     1510                    if (m_debug)
     1511                        std::cout << "  <MEMC " << name()
     1512                            << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:"
     1513                            << " entry = "       << r_multi_ack_upt_index.read()
     1514                            << " / rsp_count = " << std::dec << count << std::endl;
     1515#endif
     1516                    break;
     1517                }
     1518
     1519                /////////////////////////
     1520            case MULTI_ACK_UPT_CLEAR:   // Clear UPT entry / Test if rsp or ack required
     1521                {
     1522                    if (r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)
     1523                    {
     1524                        std::cout << "VCI_MEM_CACHE ERROR " << name()
     1525                            << " MULTI_ACK_UPT_CLEAR state"
     1526                            << " bad UPT allocation" << std::endl;
     1527                        exit(0);
     1528                    }
     1529
     1530                    r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read());
     1531                    r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read());
     1532                    r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read());
     1533                    r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read());
     1534                    bool need_rsp     = m_upt.need_rsp(r_multi_ack_upt_index.read());
     1535
     1536                    // clear the UPT entry
     1537                    m_upt.clear(r_multi_ack_upt_index.read());
     1538
     1539                    if      ( need_rsp ) r_multi_ack_fsm = MULTI_ACK_WRITE_RSP;
     1540                    else                 r_multi_ack_fsm = MULTI_ACK_IDLE;
     1541
     1542#if DEBUG_MEMC_MULTI_ACK
     1543                    if (m_debug)
     1544                        std::cout <<  "  <MEMC " << name()
     1545                            << " MULTI_ACK_UPT_CLEAR> Clear UPT entry "
     1546                            << std::dec << r_multi_ack_upt_index.read() << std::endl;
     1547#endif
     1548                    break;
     1549                }
     1550                /////////////////////////
     1551            case MULTI_ACK_WRITE_RSP:     // Post a response request to TGT_RSP FSM
     1552                // Wait if pending request
     1553                {
     1554                    if (r_multi_ack_to_tgt_rsp_req.read()) break;
     1555
     1556                    r_multi_ack_to_tgt_rsp_req   = true;
     1557                    r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read();
     1558                    r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read();
     1559                    r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read();
     1560                    r_multi_ack_fsm              = MULTI_ACK_IDLE;
     1561
     1562#if DEBUG_MEMC_MULTI_ACK
     1563                    if (m_debug)
     1564                        std::cout << "  <MEMC " << name() << " MULTI_ACK_WRITE_RSP>"
     1565                            << " Request TGT_RSP FSM to send a response to srcid "
     1566                            << std::hex << r_multi_ack_srcid.read() << std::endl;
     1567#endif
     1568                    break;
     1569                }
     1570        } // end switch r_multi_ack_fsm
     1571
     1572        ////////////////////////////////////////////////////////////////////////////////////
     1573        //    CONFIG FSM
     1574        ////////////////////////////////////////////////////////////////////////////////////
     1575        // The CONFIG FSM handles the VCI configuration requests (INVAL & SYNC).
     1576        // The target buffer can have any size, and there is one single command for
     1577        // all cache lines covered by the target buffer.
     1578        //
     1579        // An INVAL or SYNC configuration operation is defined by the following registers:
     1580        // - bool      r_config_cmd        : INVAL / SYNC / NOP
     1581        // - uint64_t  r_config_address    : buffer base address
     1582        // - uint32_t  r_config_cmd_lines  : number of lines to be handled
     1583        // - uint32_t  r_config_rsp_lines  : number of lines not completed
     1584        //
     1585        // For both INVAL and SYNC commands, the CONFIG FSM contains the loop handling
     1586        // all cache lines covered by the buffer. The various lines of a given buffer
     1587        // can be pipelined: the CONFIG FSM does not wait the response for line (n) to send
     1588        // the command for line (n+1). It decrements the r_config_cmd_lines counter until
     1589        // the last request has been registered in TRT (for a SYNC), or in IVT (for an INVAL).
     1590        //
     1591        // - INVAL request:
     1592        //   For each line, it access to the DIR.
     1593        //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
     1594        //   In case of hit, with no copies in L1 caches, the line is invalidated and
     1595        //   a response is requested to TGT_RSP FSM.
     1596        //   If there is copies, a multi-inval, or a broadcast-inval coherence transaction
     1597        //   is launched and registered in UPT. The multi-inval transaction completion
     1598        //   is signaled by the CLEANUP FSM by decrementing the r_config_rsp_lines counter.
     1599        //   The CONFIG INVAL response is sent only when the last line has been invalidated.
     1600        //   TODO : The target buffer address must be aligned on a cache line boundary.
     1601        //   This constraint can be released, but it requires to make 2 PUT transactions
     1602        //   for the first and the last line...
     1603        //
     1604        // - SYNC request:
     1605        //   For each line, it access to the DIR.
     1606        //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
     1607        //   In case of hit, a PUT transaction is registered in TRT and a request is sent
     1608        //   to IXR_CMD FSM. The IXR_RSP FSM decrements the r_config_rsp_lines counter
     1609        //   when a PUT response is received.
     1610        //   The CONFIG SYNC response is sent only when the last PUT response is received.
     1611        //
     1612        // From the software point of view, a configuration request is a sequence
     1613        // of 6 atomic accesses in an uncached segment. A dedicated lock is used
     1614        // to handle only one configuration command at a given time:
     1615        // - Read  MEMC_LOCK       : Get the lock
     1616        // - Write MEMC_ADDR_LO    : Set the buffer address LSB
     1617        // - Write MEMC_ADDR_HI    : Set the buffer address MSB
     1618        // - Write MEMC_BUF_LENGTH : set buffer length (bytes)
     1619        // - Write MEMC_CMD_TYPE   : launch the actual operation
     1620        // - WRITE MEMC_LOCK       : release the lock
     1621        ////////////////////////////////////////////////////////////////////////////////////
     1622
     1623        //std::cout << std::endl << "config_fsm" << std::endl;
     1624
     1625        switch( r_config_fsm.read())
    10601626        {
    1061             need_rsp         = true;
    1062             error            = 0;
    1063             r_config_lock    = false;
    1064         }
    1065         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_lo
    1066                    and (cell == MEMC_ADDR_LO) )
     1627            /////////////////
     1628            case CONFIG_IDLE:  // waiting a config request
     1629                {
     1630                    if (r_config_cmd.read() != MEMC_CMD_NOP ) 
     1631                    {
     1632                        r_config_fsm    = CONFIG_LOOP;
     1633
     1634#if DEBUG_MEMC_CONFIG
     1635                        if (m_debug)
     1636                            std::cout << "  <MEMC " << name() << " CONFIG_IDLE> Config Request received"
     1637                                << " / address = " << std::hex << r_config_address.read()
     1638                                << " / lines = " << std::dec << r_config_cmd_lines.read()
     1639                                << " / type = " << r_config_cmd.read() << std::endl;
     1640#endif
     1641                    }
     1642                    break;
     1643                }
     1644                /////////////////
     1645            case CONFIG_LOOP:   // test if last line to be handled
     1646                {
     1647                    if (r_config_cmd_lines.read() == 0 )
     1648                    {
     1649                        r_config_cmd = MEMC_CMD_NOP;
     1650                        r_config_fsm = CONFIG_WAIT;
     1651                    }
     1652                    else
     1653                    {
     1654                        r_config_fsm = CONFIG_DIR_REQ;
     1655                    }
     1656
     1657#if DEBUG_MEMC_CONFIG
     1658                    if (m_debug)
     1659                        std::cout << "  <MEMC " << name() << " CONFIG_LOOP>"
     1660                            << " / address = " << std::hex << r_config_address.read()   
     1661                            << " / lines not handled = " << std::dec << r_config_cmd_lines.read()
     1662                            << " / command = " << r_config_cmd.read() << std::endl;
     1663#endif
     1664                    break;
     1665                }
     1666                /////////////////
     1667            case CONFIG_WAIT:   // wait completion (last response)
     1668                {
     1669                    if (r_config_rsp_lines.read() == 0 )  // last response received
     1670                    {
     1671                        r_config_fsm = CONFIG_RSP;
     1672                    }
     1673
     1674#if DEBUG_MEMC_CONFIG
     1675                    if (m_debug)
     1676                        std::cout << "  <MEMC " << name() << " CONFIG_WAIT>"
     1677                            << " / lines to do = " << std::dec << r_config_rsp_lines.read() << std::endl;
     1678#endif
     1679                    break;
     1680                }
     1681                ////////////////
     1682            case CONFIG_RSP:  // request TGT_RSP FSM to return response
     1683                {
     1684                    if (not r_config_to_tgt_rsp_req.read())
     1685                    {
     1686                        r_config_to_tgt_rsp_srcid  = r_config_srcid.read();
     1687                        r_config_to_tgt_rsp_trdid  = r_config_trdid.read();
     1688                        r_config_to_tgt_rsp_pktid  = r_config_pktid.read();
     1689                        r_config_to_tgt_rsp_error  = false;
     1690                        r_config_to_tgt_rsp_req    = true;
     1691                        r_config_fsm               = CONFIG_IDLE;
     1692
     1693#if DEBUG_MEMC_CONFIG
     1694                        if (m_debug)
     1695                            std::cout << "  <MEMC " << name() << " CONFIG_RSP> Request TGT_RSP FSM to return response:"
     1696                                << " error = " << r_config_to_tgt_rsp_error.read()
     1697                                << " / rsrcid = " << std::hex << r_config_srcid.read()
     1698                                << " / rtrdid = " << std::hex << r_config_trdid.read()
     1699                                << " / rpktid = " << std::hex << r_config_pktid.read() << std::endl;
     1700#endif
     1701                    }
     1702                    break;
     1703
     1704                }
     1705                ////////////////////
     1706            case CONFIG_DIR_REQ:  // Request directory lock
     1707                {
     1708                    if (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG )
     1709                    {
     1710                        r_config_fsm = CONFIG_DIR_ACCESS;
     1711                    }
     1712
     1713#if DEBUG_MEMC_CONFIG
     1714                    if (m_debug)
     1715                        std::cout << "  <MEMC " << name() << " CONFIG_DIR_REQ>"
     1716                            << " Request DIR access" << std::endl;
     1717#endif
     1718                    break;
     1719                }
     1720                ///////////////////////
     1721            case CONFIG_DIR_ACCESS:   // Access directory and decode config command
     1722                {
     1723                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
     1724                            "MEMC ERROR in CONFIG_DIR_ACCESS state: bad DIR allocation");
     1725
     1726                    size_t way = 0;
     1727                    DirectoryEntry entry = m_cache_directory.read(r_config_address.read(), way);
     1728
     1729                    r_config_dir_way        = way;
     1730                    r_config_dir_copy_inst  = entry.owner.inst;
     1731                    r_config_dir_copy_srcid = entry.owner.srcid;
     1732                    r_config_dir_is_cnt     = entry.is_cnt;
     1733                    r_config_dir_lock       = entry.lock;
     1734                    r_config_dir_count      = entry.count;
     1735                    r_config_dir_ptr        = entry.ptr;
     1736
     1737                    if (entry.valid and                            // hit & inval command
     1738                            (r_config_cmd.read() == MEMC_CMD_INVAL))
     1739                    {
     1740                        r_config_fsm       = CONFIG_IVT_LOCK;
     1741                    }
     1742                    else if (entry.valid and                       // hit & sync command
     1743                            entry.dirty and
     1744                            (r_config_cmd.read() == MEMC_CMD_SYNC))
     1745                    {
     1746                        r_config_fsm       = CONFIG_TRT_LOCK;
     1747                    }
     1748                    else                                            // miss : return to LOOP
     1749                    {
     1750                        r_config_cmd_lines = r_config_cmd_lines.read() - 1;
     1751                        r_config_rsp_lines = r_config_rsp_lines.read() - 1;
     1752                        r_config_address   = r_config_address.read() + (m_words<<2);
     1753                        r_config_fsm       = CONFIG_LOOP;
     1754                    }
     1755
     1756#if DEBUG_MEMC_CONFIG
     1757                    if (m_debug)
     1758                        std::cout << "  <MEMC " << name() << " CONFIG_DIR_ACCESS> Accessing directory: "
     1759                            << " address = " << std::hex << r_config_address.read()
     1760                            << " / hit = " << std::dec << entry.valid
     1761                            << " / dirty = " << entry.dirty
     1762                            << " / count = " << entry.count
     1763                            << " / is_cnt = " << entry.is_cnt << std::endl;
     1764#endif
     1765                    break;
     1766                }
     1767                /////////////////////
     1768            case CONFIG_TRT_LOCK:      // enter this state in case of SYNC command
     1769                // to a dirty cache line
     1770                // keep DIR lock, and try to get TRT lock
     1771                // return to LOOP state if TRT full
     1772                // reset dirty bit in DIR and register a PUT
     1773                // trabsaction in TRT if not full.
     1774                {
     1775                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
     1776                            "MEMC ERROR in CONFIG_TRT_LOCK state: bad DIR allocation");
     1777
     1778                    if (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG )
     1779                    {
     1780                        size_t index = 0;
     1781                        bool   wok   = not m_trt.full(index);
     1782
     1783                        if (not wok )
     1784                        {
     1785                            r_config_fsm = CONFIG_LOOP;
     1786                        }
     1787                        else
     1788                        {
     1789                            size_t          way = r_config_dir_way.read();
     1790                            size_t          set = m_y[r_config_address.read()];
     1791
     1792                            // reset dirty bit in DIR
     1793                            DirectoryEntry  entry;
     1794                            entry.valid       = true;
     1795                            entry.dirty       = false;
     1796                            entry.tag         = m_z[r_config_address.read()];
     1797                            entry.is_cnt      = r_config_dir_is_cnt.read();
     1798                            entry.lock        = r_config_dir_lock.read();
     1799                            entry.ptr         = r_config_dir_ptr.read();
     1800                            entry.count       = r_config_dir_count.read();
     1801                            entry.owner.inst  = r_config_dir_copy_inst.read();
     1802                            entry.owner.srcid = r_config_dir_copy_srcid.read();
     1803                            m_cache_directory.write( set, way, entry );
     1804
     1805                            r_config_trt_index = index;
     1806                            r_config_fsm       = CONFIG_TRT_SET;
     1807                        }
     1808
     1809#if DEBUG_MEMC_CONFIG
     1810                        if (m_debug)
     1811                            std::cout << "  <MEMC " << name() << " CONFIG_TRT_LOCK> Access TRT: "
     1812                                << " wok = " << std::dec << wok
     1813                                << " index = " << index << std::endl;
     1814#endif
     1815                    }
     1816                    break;
     1817                }
     1818                ////////////////////
     1819            case CONFIG_TRT_SET:       // read data in cache
     1820                // and post a PUT request in TRT
     1821                {
     1822                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
     1823                            "MEMC ERROR in CONFIG_TRT_SET state: bad DIR allocation");
     1824
     1825                    assert( (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG) and
     1826                            "MEMC ERROR in CONFIG_TRT_SET state: bad TRT allocation");
     1827
     1828                    // read data into cache
     1829                    size_t              way = r_config_dir_way.read();
     1830                    size_t              set = m_y[r_config_address.read()];
     1831                    std::vector<data_t> data_vector;
     1832                    data_vector.clear();
     1833                    for(size_t word=0; word<m_words; word++)
     1834                    {
     1835                        uint32_t data = m_cache_data.read( way, set, word );
     1836                        data_vector.push_back( data );
     1837                    }
     1838
     1839                    // post the PUT request in TRT
     1840                    m_trt.set( r_config_trt_index.read(),
     1841                            false,                               // PUT transaction
     1842                            m_nline[r_config_address.read()],    // line index
     1843                            0,                                   // srcid:           unused
     1844                            0,                                   // trdid:           unused
     1845                            0,                                   // pktid:           unused
     1846                            false,                               // not proc_read
     1847                            0,                                   // read_length:     unused
     1848                            0,                                   // word_index:      unused
     1849                            std::vector<be_t>(m_words,0xF),      // byte-enable:     unused
     1850                            data_vector,                         // data to be written
     1851                            0,                                   // ll_key:          unused
     1852                            true );                              // requested by config FSM
     1853                    r_config_fsm = CONFIG_PUT_REQ;
     1854
     1855#if DEBUG_MEMC_CONFIG
     1856                    if (m_debug)
     1857                        std::cout << "  <MEMC " << name() << " CONFIG_TRT_SET> PUT request in TRT:"
     1858                            << " address = " << std::hex << r_config_address.read()
     1859                            << " index = " << std::dec << r_config_trt_index.read() << std::endl;
     1860#endif
     1861                    break;
     1862                }
     1863                ////////////////////
     1864            case CONFIG_PUT_REQ:       // post PUT request to IXR_CMD_FSM
     1865                {
     1866                    if (not r_config_to_ixr_cmd_req.read())
     1867                    {
     1868                        r_config_to_ixr_cmd_req   = true;
     1869                        r_config_to_ixr_cmd_index = r_config_trt_index.read();
     1870
     1871                        // prepare next iteration
     1872                        r_config_cmd_lines              = r_config_cmd_lines.read() - 1;
     1873                        r_config_address                = r_config_address.read() + (m_words<<2);
     1874                        r_config_fsm                    = CONFIG_LOOP;
     1875
     1876#if DEBUG_MEMC_CONFIG
     1877                        if (m_debug)
     1878                            std::cout << "  <MEMC " << name() << " CONFIG_PUT_REQ> post PUT request to IXR_CMD_FSM"
     1879                                << " / address = " << std::hex << r_config_address.read() << std::endl;
     1880#endif
     1881                    }
     1882                    break;
     1883                }
     1884                /////////////////////
     1885            case CONFIG_IVT_LOCK:  // enter this state in case of INVAL command
     1886                // Keep DIR lock and Try to get IVT lock.
     1887                // Return to LOOP state if IVT full.
     1888                // Register inval in IVT, and invalidate the
     1889                // directory if IVT not full.
     1890                {
     1891                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
     1892                            "MEMC ERROR in CONFIG_IVT_LOCK state: bad DIR allocation");
     1893
     1894                    if (r_alloc_ivt_fsm.read() == ALLOC_IVT_CONFIG )
     1895                    {
     1896                        size_t set        = m_y[(addr_t)(r_config_address.read())];
     1897                        size_t way        = r_config_dir_way.read();
     1898
     1899                        if (r_config_dir_count.read() == 0 )     // inval DIR and return to LOOP
     1900                        {
     1901                            m_cache_directory.inval( way, set );
     1902                            r_config_cmd_lines  = r_config_cmd_lines.read() - 1;
     1903                            r_config_rsp_lines  = r_config_rsp_lines.read() - 1;
     1904                            r_config_address    = r_config_address.read() + (m_words<<2);
     1905                            r_config_fsm        = CONFIG_LOOP;
     1906
     1907#if DEBUG_MEMC_CONFIG
     1908                            if (m_debug)
     1909                                std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
     1910                                    << " No copies in L1 : inval DIR entry"  << std::endl;
     1911#endif
     1912                        }
     1913                        else    // try to register inval in IVT
     1914                        {
     1915                            bool        wok       = false;
     1916                            size_t      index     = 0;
     1917                            bool        broadcast = r_config_dir_is_cnt.read();
     1918                            size_t      srcid     = r_config_srcid.read();
     1919                            size_t      trdid     = r_config_trdid.read();
     1920                            size_t      pktid     = r_config_pktid.read();
     1921                            addr_t      nline     = m_nline[(addr_t)(r_config_address.read())];
     1922                            size_t      nb_copies = r_config_dir_count.read();
     1923
     1924                            wok = m_ivt.set(false,       // it's an inval transaction
     1925                                    broadcast,   
     1926                                    false,       // no response required
     1927                                    true,        // acknowledge required
     1928                                    srcid,
     1929                                    trdid,
     1930                                    pktid,
     1931                                    nline,
     1932                                    nb_copies,
     1933                                    index);
     1934
     1935                            if (wok )  // IVT success => inval DIR slot
     1936                            {
     1937                                m_cache_directory.inval( way, set );
     1938                                r_config_ivt_index = index;
     1939                                if (broadcast )  r_config_fsm = CONFIG_BC_SEND;
     1940                                else              r_config_fsm = CONFIG_INVAL_SEND;
     1941
     1942#if DEBUG_MEMC_CONFIG
     1943                                if (m_debug)
     1944                                    std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
     1945                                        << " Inval DIR entry and register inval in IVT"
     1946                                        << " / index = " << std::dec << index
     1947                                        << " / broadcast = " << broadcast << std::endl;
     1948#endif
     1949                            }
     1950                            else       // IVT full => release both DIR and IVT locks
     1951                            {
     1952                                r_config_fsm = CONFIG_LOOP;
     1953
     1954#if DEBUG_MEMC_CONFIG
     1955                                if (m_debug)
     1956                                    std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
     1957                                        << " IVT full : release DIR & IVT locks and retry" << std::endl;
     1958#endif
     1959                            }
     1960                        }
     1961                    }
     1962                    break;
     1963                }
     1964                ////////////////////
     1965            case CONFIG_BC_SEND:    // Post a broadcast inval request to CC_SEND FSM
     1966                {
     1967                    if (not r_config_to_cc_send_multi_req.read() and
     1968                            not r_config_to_cc_send_brdcast_req.read())
     1969                    {
     1970                        // post bc inval request
     1971                        r_config_to_cc_send_multi_req   = false;
     1972                        r_config_to_cc_send_brdcast_req = true;
     1973                        r_config_to_cc_send_trdid       = r_config_ivt_index.read();
     1974                        r_config_to_cc_send_nline       = m_nline[(addr_t)(r_config_address.read())];
     1975
     1976                        // prepare next iteration
     1977                        r_config_cmd_lines              = r_config_cmd_lines.read() - 1;
     1978                        r_config_address                = r_config_address.read() + (m_words << 2);
     1979                        r_config_fsm                    = CONFIG_LOOP;
     1980
     1981#if DEBUG_MEMC_CONFIG
     1982                        if (m_debug)
     1983                            std::cout << "  <MEMC " << name() << " CONFIG_BC_SEND>"
     1984                                << " Post a broadcast inval request to CC_SEND FSM"
     1985                                << " / address = " << r_config_address.read() <<std::endl;
     1986#endif
     1987                    }
     1988                    break;
     1989                }
     1990                ///////////////////////
     1991            case CONFIG_INVAL_SEND:    // Post a multi inval request to CC_SEND FSM
     1992                {
     1993                    if (not r_config_to_cc_send_multi_req.read() and
     1994                            not r_config_to_cc_send_brdcast_req.read())
     1995                    {
     1996                        // post multi inval request
     1997                        r_config_to_cc_send_multi_req   = true;
     1998                        r_config_to_cc_send_brdcast_req = false;
     1999                        r_config_to_cc_send_trdid       = r_config_ivt_index.read();
     2000                        r_config_to_cc_send_nline       = m_nline[(addr_t) (r_config_address.read())];
     2001
     2002                        // post data into FIFO
     2003                        config_to_cc_send_fifo_srcid    = r_config_dir_copy_srcid.read();
     2004                        config_to_cc_send_fifo_inst     = r_config_dir_copy_inst.read();
     2005                        config_to_cc_send_fifo_put      = true;
     2006
     2007                        if (r_config_dir_count.read() == 1 )  // one copy
     2008                        {
     2009                            // prepare next iteration
     2010                            r_config_cmd_lines          = r_config_cmd_lines.read() - 1;
     2011                            r_config_address            = r_config_address.read() + (m_words << 2);
     2012                            r_config_fsm                = CONFIG_LOOP;
     2013                        }
     2014                        else                                   // several copies
     2015                        {
     2016                            r_config_fsm = CONFIG_HEAP_REQ;
     2017                        }
     2018
     2019#if DEBUG_MEMC_CONFIG
     2020                        if (m_debug)
     2021                            std::cout << "  <MEMC " << name() << " CONFIG_INVAL_SEND>"
     2022                                << " Post multi inval request to CC_SEND FSM"
     2023                                << " / address = " << std::hex << r_config_address.read()
     2024                                << " / copy = " << r_config_dir_copy_srcid.read()
     2025                                << " / inst = " << std::dec << r_config_dir_copy_inst.read() << std::endl;
     2026#endif
     2027                    }
     2028                    break;
     2029                }
     2030                /////////////////////
     2031            case CONFIG_HEAP_REQ:  // Try to get access to Heap
     2032                {
     2033                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_CONFIG )
     2034                    {
     2035                        r_config_fsm       = CONFIG_HEAP_SCAN;
     2036                        r_config_heap_next = r_config_dir_ptr.read();
     2037                    }
     2038
     2039#if DEBUG_MEMC_CONFIG
     2040                    if (m_debug)
     2041                        std::cout << "  <MEMC " << name() << " CONFIG_HEAP_REQ>"
     2042                            << " Requesting HEAP lock" << std::endl;
     2043#endif
     2044                    break;
     2045                }
     2046                //////////////////////
     2047            case CONFIG_HEAP_SCAN:      // scan HEAP and send inval to CC_SEND FSM
     2048                {
     2049                    HeapEntry entry = m_heap.read( r_config_heap_next.read());
     2050                    bool last_copy  = (entry.next == r_config_heap_next.read());
     2051
     2052                    config_to_cc_send_fifo_srcid = entry.owner.srcid;
     2053                    config_to_cc_send_fifo_inst  = entry.owner.inst;
     2054                    // config_to_cc_send_fifo_last  = last_copy;
     2055                    config_to_cc_send_fifo_put   = true;
     2056
     2057                    if (m_config_to_cc_send_inst_fifo.wok()) // inval request accepted
     2058                    {
     2059                        r_config_heap_next = entry.next;
     2060                        if (last_copy ) r_config_fsm = CONFIG_HEAP_LAST;
     2061                    }
     2062
     2063#if DEBUG_MEMC_CONFIG
     2064                    if (m_debug)
     2065                        std::cout << "  <MEMC " << name() << " CONFIG_HEAP_SCAN>"
     2066                            << " Post multi inval request to CC_SEND FSM"
     2067                            << " / address = " << std::hex << r_config_address.read()
     2068                            << " / copy = " << entry.owner.srcid
     2069                            << " / inst = " << std::dec << entry.owner.inst << std::endl;
     2070#endif
     2071                    break;
     2072                }
     2073                //////////////////////
     2074            case CONFIG_HEAP_LAST:      // HEAP housekeeping
     2075                {
     2076                    size_t free_pointer = m_heap.next_free_ptr();
     2077                    HeapEntry last_entry;
     2078                    last_entry.owner.srcid = 0;
     2079                    last_entry.owner.inst  = false;
     2080
     2081                    if (m_heap.is_full())
     2082                    {
     2083                        last_entry.next = r_config_dir_ptr.read();
     2084                        m_heap.unset_full();
     2085                    }
     2086                    else
     2087                    {
     2088                        last_entry.next = free_pointer;
     2089                    }
     2090
     2091                    m_heap.write_free_ptr( r_config_dir_ptr.read());
     2092                    m_heap.write( r_config_heap_next.read(), last_entry );
     2093
     2094                    // prepare next iteration
     2095                    r_config_cmd_lines          = r_config_cmd_lines.read() - 1;
     2096                    r_config_address            = r_config_address.read() + (m_words<<2);
     2097                    r_config_fsm                = CONFIG_LOOP;
     2098
     2099#if DEBUG_MEMC_CONFIG
     2100                    if (m_debug)
     2101                        std::cout << "  <MEMC " << name() << " CONFIG_HEAP_LAST>"
     2102                            << " Heap housekeeping" << std::endl;
     2103#endif
     2104                    break;
     2105                }
     2106        }  // end switch r_config_fsm
     2107
     2108        ////////////////////////////////////////////////////////////////////////////////////
     2109        //    READ FSM
     2110        ////////////////////////////////////////////////////////////////////////////////////
     2111        // The READ FSM controls the VCI read  and ll requests.
     2112        // It takes the lock protecting the cache directory to check the cache line status:
     2113        // - In case of HIT
     2114        //   The fsm copies the data (one line, or one single word)
     2115        //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
     2116        //   The requesting initiator is registered in the cache directory.
     2117        //   If the number of copy is larger than 1, the new copy is registered
     2118        //   in the HEAP.
     2119        //   If the number of copy is larger than the threshold, the HEAP is cleared,
     2120        //   and the corresponding line switches to the counter mode.
     2121        // - In case of MISS
     2122        //   The READ fsm takes the lock protecting the transaction tab.
     2123        //   If a read transaction to the XRAM for this line already exists,
     2124        //   or if the transaction tab is full, the fsm is stalled.
     2125        //   If a TRT entry is free, the READ request is registered in TRT,
     2126        //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
     2127        //   The READ FSM returns in the IDLE state as the read transaction will be
     2128        //   completed when the missing line will be received.
     2129        ////////////////////////////////////////////////////////////////////////////////////
     2130
     2131        //std::cout << std::endl << "read_fsm" << std::endl;
     2132
     2133        switch(r_read_fsm.read())
    10672134        {
    1068             assert( ((wdata % (m_words*vci_param_int::B)) == 0) and
    1069             "VCI_MEM_CACHE CONFIG ERROR: The buffer must be aligned on a cache line");
    1070 
    1071             need_rsp         = true;
    1072             error            = 0;
    1073             r_config_address = (r_config_address.read() & 0xFFFFFFFF00000000LL) |
    1074                                ((addr_t)wdata);
    1075         }
    1076         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set addr_hi
    1077                    and (cell == MEMC_ADDR_HI) )
    1078 
     2135            ///////////////
     2136            case READ_IDLE:  // waiting a read request
     2137                {
     2138                    if (m_cmd_read_addr_fifo.rok())
     2139                    {
     2140
     2141#if DEBUG_MEMC_READ
     2142                        if (m_debug)
     2143                            std::cout << "  <MEMC " << name() << " READ_IDLE> Read request"
     2144                                << " : address = " << std::hex << m_cmd_read_addr_fifo.read()
     2145                                << " / srcid = " << m_cmd_read_srcid_fifo.read()
     2146                                << " / trdid = " << m_cmd_read_trdid_fifo.read()
     2147                                << " / pktid = " << m_cmd_read_pktid_fifo.read()
     2148                                << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
     2149#endif
     2150                        r_read_fsm = READ_DIR_REQ;
     2151                    }
     2152                    break;
     2153                }
     2154                //////////////////
     2155            case READ_DIR_REQ:  // Get the lock to the directory
     2156                {
     2157                    if (r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
     2158                    {
     2159                        r_read_fsm = READ_DIR_LOCK;
     2160                    }
     2161
     2162#if DEBUG_MEMC_READ
     2163                    if (m_debug)
     2164                        std::cout << "  <MEMC " << name() << " READ_DIR_REQ> Requesting DIR lock " << std::endl;
     2165#endif
     2166                    break;
     2167                }
     2168
     2169                ///////////////////
     2170            case READ_DIR_LOCK:  // check directory for hit / miss
     2171                {
     2172                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
     2173                            "MEMC ERROR in READ_DIR_LOCK state: Bad DIR allocation");
     2174
     2175                    size_t way = 0;
     2176                    DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
     2177
     2178                    // access the global table ONLY when we have an LL cmd
     2179                    if ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)   
     2180                    {
     2181                        r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
     2182                    }
     2183                    r_read_is_cnt     = entry.is_cnt;
     2184                    r_read_dirty      = entry.dirty;
     2185                    r_read_lock       = entry.lock;
     2186                    r_read_tag        = entry.tag;
     2187                    r_read_way        = way;
     2188                    r_read_count      = entry.count;
     2189                    r_read_copy       = entry.owner.srcid;
     2190                    r_read_copy_inst  = entry.owner.inst;
     2191                    r_read_ptr        = entry.ptr; // pointer to the heap
     2192
     2193                    // check if this is a cached read, this means pktid is either
     2194                    // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
     2195                    // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
     2196                    bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
     2197                    if (entry.valid)    // hit
     2198                    {
     2199                        // test if we need to register a new copy in the heap
     2200                        if (entry.is_cnt or (entry.count == 0) or !cached_read)
     2201                        {
     2202                            r_read_fsm = READ_DIR_HIT;
     2203                        }
     2204                        else
     2205                        {
     2206                            r_read_fsm = READ_HEAP_REQ;
     2207                        }
     2208                    }
     2209                    else      // miss
     2210                    {
     2211                        r_read_fsm = READ_TRT_LOCK;
     2212                    }
     2213
     2214#if DEBUG_MEMC_READ
     2215                    if (m_debug)
     2216                    {
     2217                        std::cout << "  <MEMC " << name() << " READ_DIR_LOCK> Accessing directory: "
     2218                            << " address = " << std::hex << m_cmd_read_addr_fifo.read()
     2219                            << " / hit = " << std::dec << entry.valid
     2220                            << " / count = " <<std::dec << entry.count
     2221                            << " / is_cnt = " << entry.is_cnt;
     2222                        if ((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) std::cout << " / LL access" << std::endl;
     2223                        else                                                std::cout << std::endl;
     2224                    }
     2225#endif
     2226                    break;
     2227                }
     2228                //////////////////
     2229            case READ_DIR_HIT:    //  read data in cache & update the directory
     2230                //  we enter this state in 3 cases:
     2231                //  - the read request is uncachable
     2232                //  - the cache line is in counter mode
     2233                //  - the cache line is valid but not replicated
     2234
     2235                {
     2236                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
     2237                            "MEMC ERROR in READ_DIR_HIT state: Bad DIR allocation");
     2238
     2239                    // check if this is an instruction read, this means pktid is either
     2240                    // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
     2241                    // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
     2242                    bool inst_read    = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
     2243                    // check if this is a cached read, this means pktid is either
     2244                    // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
     2245                    // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
     2246                    bool cached_read  = (m_cmd_read_pktid_fifo.read() & 0x1);
     2247                    bool is_cnt       = r_read_is_cnt.read();
     2248
     2249                    // read data in the cache
     2250                    size_t set        = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
     2251                    size_t way        = r_read_way.read();
     2252
     2253                    m_cache_data.read_line(way, set, r_read_data);
     2254
     2255                    // update the cache directory
     2256                    DirectoryEntry entry;
     2257                    entry.valid   = true;
     2258                    entry.is_cnt  = is_cnt;
     2259                    entry.dirty   = r_read_dirty.read();
     2260                    entry.tag     = r_read_tag.read();
     2261                    entry.lock    = r_read_lock.read();
     2262                    entry.ptr     = r_read_ptr.read();
     2263
     2264                    if (cached_read)   // Cached read => we must update the copies
     2265                    {
     2266                        if (!is_cnt)  // Not counter mode
     2267                        {
     2268                            entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
     2269                            entry.owner.inst     = inst_read;
     2270                            entry.count          = r_read_count.read() + 1;
     2271                        }
     2272                        else  // Counter mode
     2273                        {
     2274                            entry.owner.srcid    = 0;
     2275                            entry.owner.inst     = false;
     2276                            entry.count          = r_read_count.read() + 1;
     2277                        }
     2278                    }
     2279                    else            // Uncached read
     2280                    {
     2281                        entry.owner.srcid     = r_read_copy.read();
     2282                        entry.owner.inst      = r_read_copy_inst.read();
     2283                        entry.count           = r_read_count.read();
     2284                    }
     2285
     2286#if DEBUG_MEMC_READ
     2287                    if (m_debug)
     2288                        std::cout << "  <MEMC " << name() << " READ_DIR_HIT> Update directory entry:"
     2289                            << " addr = " << std::hex << m_cmd_read_addr_fifo.read()
     2290                            << " / set = " << std::dec << set
     2291                            << " / way = " << way
     2292                            << " / owner_id = " << std::hex << entry.owner.srcid
     2293                            << " / owner_ins = " << std::dec << entry.owner.inst
     2294                            << " / count = " << entry.count
     2295                            << " / is_cnt = " << entry.is_cnt << std::endl;
     2296#endif
     2297                    m_cache_directory.write(set, way, entry);
     2298                    r_read_fsm    = READ_RSP;
     2299                    break;
     2300                }
     2301                ///////////////////
     2302            case READ_HEAP_REQ:    // Get the lock to the HEAP directory
     2303                {
     2304                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
     2305                    {
     2306                        r_read_fsm = READ_HEAP_LOCK;
     2307                    }
     2308
     2309#if DEBUG_MEMC_READ
     2310                    if (m_debug)
     2311                        std::cout << "  <MEMC " << name() << " READ_HEAP_REQ>"
     2312                            << " Requesting HEAP lock " << std::endl;
     2313#endif
     2314                    break;
     2315                }
     2316
     2317                ////////////////////
     2318            case READ_HEAP_LOCK:   // read data in cache, update the directory
     2319                // and prepare the HEAP update
     2320                {
     2321                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
     2322                    {
     2323                        // enter counter mode when we reach the limit of copies or the heap is full
     2324                        bool go_cnt = (r_read_count.read() >= m_max_copies) or m_heap.is_full();
     2325
     2326                        // read data in the cache
     2327                        size_t set = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
     2328                        size_t way = r_read_way.read();
     2329
     2330                        m_cache_data.read_line(way, set, r_read_data);
     2331
     2332                        // update the cache directory
     2333                        DirectoryEntry entry;
     2334                        entry.valid  = true;
     2335                        entry.is_cnt = go_cnt;
     2336                        entry.dirty  = r_read_dirty.read();
     2337                        entry.tag    = r_read_tag.read();
     2338                        entry.lock   = r_read_lock.read();
     2339                        entry.count  = r_read_count.read() + 1;
     2340
     2341                        if (not go_cnt)         // Not entering counter mode
     2342                        {
     2343                            entry.owner.srcid    = r_read_copy.read();
     2344                            entry.owner.inst     = r_read_copy_inst.read();
     2345                            entry.ptr            = m_heap.next_free_ptr();   // set pointer on the heap
     2346                        }
     2347                        else                // Entering Counter mode
     2348                        {
     2349                            entry.owner.srcid    = 0;
     2350                            entry.owner.inst     = false;
     2351                            entry.ptr            = 0;
     2352                        }
     2353
     2354                        m_cache_directory.write(set, way, entry);
     2355
     2356                        // prepare the heap update (add an entry, or clear the linked list)
     2357                        if (not go_cnt)      // not switching to counter mode
     2358                        {
     2359                            // We test if the next free entry in the heap is the last
     2360                            HeapEntry heap_entry = m_heap.next_free_entry();
     2361                            r_read_next_ptr      = heap_entry.next;
     2362                            r_read_last_free     = (heap_entry.next == m_heap.next_free_ptr());
     2363
     2364                            r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
     2365                        }
     2366                        else            // switching to counter mode
     2367                        {
     2368                            if (r_read_count.read() >1)              // heap must be cleared
     2369                            {
     2370                                HeapEntry next_entry = m_heap.read(r_read_ptr.read());
     2371                                r_read_next_ptr      = m_heap.next_free_ptr();
     2372                                m_heap.write_free_ptr(r_read_ptr.read());
     2373
     2374                                if (next_entry.next == r_read_ptr.read())    // last entry
     2375                                {
     2376                                    r_read_fsm = READ_HEAP_LAST;    // erase the entry
     2377                                }
     2378                                else                                        // not the last entry
     2379                                {
     2380                                    r_read_ptr = next_entry.next;
     2381                                    r_read_fsm = READ_HEAP_ERASE;   // erase the list
     2382                                }
     2383                            }
     2384                            else  // the heap is not used / nothing to do
     2385                            {
     2386                                r_read_fsm = READ_RSP;
     2387                            }
     2388                        }
     2389
     2390#if DEBUG_MEMC_READ
     2391                        if (m_debug)
     2392                            std::cout << "  <MEMC " << name() << " READ_HEAP_LOCK> Update directory:"
     2393                                << " tag = " << std::hex << entry.tag
     2394                                << " set = " << std::dec << set
     2395                                << " way = " << way
     2396                                << " count = " << entry.count
     2397                                << " is_cnt = " << entry.is_cnt << std::endl;
     2398#endif
     2399                    }
     2400                    else
     2401                    {
     2402                        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LOCK"
     2403                            << "Bad HEAP allocation"   << std::endl;
     2404                        exit(0);
     2405                    }
     2406                    break;
     2407                }
     2408                /////////////////////
     2409            case READ_HEAP_WRITE:       // add an entry in the heap
     2410                {
     2411                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
     2412                    {
     2413                        HeapEntry heap_entry;
     2414                        heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
     2415                        heap_entry.owner.inst     = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
     2416
     2417                        if (r_read_count.read() == 1)  // creation of a new linked list
     2418                        {
     2419                            heap_entry.next         = m_heap.next_free_ptr();
     2420                        }
     2421                        else                         // head insertion in existing list
     2422                        {
     2423                            heap_entry.next         = r_read_ptr.read();
     2424                        }
     2425                        m_heap.write_free_entry(heap_entry);
     2426                        m_heap.write_free_ptr(r_read_next_ptr.read());
     2427                        if (r_read_last_free.read())  m_heap.set_full();
     2428
     2429                        r_read_fsm = READ_RSP;
     2430
     2431#if DEBUG_MEMC_READ
     2432                        if (m_debug)
     2433                            std::cout << "  <MEMC " << name() << " READ_HEAP_WRITE> Add an entry in the heap:"
     2434                                << " owner_id = " << std::hex << heap_entry.owner.srcid
     2435                                << " owner_ins = " << std::dec << heap_entry.owner.inst << std::endl;
     2436#endif
     2437                    }
     2438                    else
     2439                    {
     2440                        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_WRITE"
     2441                            << "Bad HEAP allocation" << std::endl;
     2442                        exit(0);
     2443                    }
     2444                    break;
     2445                }
     2446                /////////////////////
     2447            case READ_HEAP_ERASE:
     2448                {
     2449                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
     2450                    {
     2451                        HeapEntry next_entry = m_heap.read(r_read_ptr.read());
     2452                        if (next_entry.next == r_read_ptr.read())
     2453                        {
     2454                            r_read_fsm = READ_HEAP_LAST;
     2455                        }
     2456                        else
     2457                        {
     2458                            r_read_ptr = next_entry.next;
     2459                            r_read_fsm = READ_HEAP_ERASE;
     2460                        }
     2461                    }
     2462                    else
     2463                    {
     2464                        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_ERASE"
     2465                            << "Bad HEAP allocation" << std::endl;
     2466                        exit(0);
     2467                    }
     2468                    break;
     2469                }
     2470
     2471                ////////////////////
     2472            case READ_HEAP_LAST:
     2473                {
     2474                    if (r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
     2475                    {
     2476                        HeapEntry last_entry;
     2477                        last_entry.owner.srcid    = 0;
     2478                        last_entry.owner.inst     = false;
     2479
     2480                        if (m_heap.is_full())
     2481                        {
     2482                            last_entry.next       = r_read_ptr.read();
     2483                            m_heap.unset_full();
     2484                        }
     2485                        else
     2486                        {
     2487                            last_entry.next       = r_read_next_ptr.read();
     2488                        }
     2489                        m_heap.write(r_read_ptr.read(),last_entry);
     2490                        r_read_fsm = READ_RSP;
     2491                    }
     2492                    else
     2493                    {
     2494                        std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LAST"
     2495                            << "Bad HEAP allocation" << std::endl;
     2496                        exit(0);
     2497                    }
     2498                    break;
     2499                }
     2500                //////////////
     2501            case READ_RSP:    //  request the TGT_RSP FSM to return data
     2502                {
     2503                    if (!r_read_to_tgt_rsp_req)
     2504                    {
     2505                        for(size_t i=0 ; i<m_words ; i++)  r_read_to_tgt_rsp_data[i] = r_read_data[i];
     2506                        r_read_to_tgt_rsp_word   = m_x[(addr_t) m_cmd_read_addr_fifo.read()];
     2507                        r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
     2508                        r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
     2509                        r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
     2510                        r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
     2511                        r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
     2512                        cmd_read_fifo_get        = true;
     2513                        r_read_to_tgt_rsp_req    = true;
     2514                        r_read_fsm               = READ_IDLE;
     2515
     2516#if DEBUG_MEMC_READ
     2517                        if (m_debug)
     2518                            std::cout << "  <MEMC " << name() << " READ_RSP> Request TGT_RSP FSM to return data:"
     2519                                << " rsrcid = " << std::hex << m_cmd_read_srcid_fifo.read()
     2520                                << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
     2521                                << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
     2522#endif
     2523                    }
     2524                    break;
     2525                }
     2526                ///////////////////
     2527            case READ_TRT_LOCK: // read miss : check the Transaction Table
     2528                {
     2529                    if (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
     2530                    {
     2531                        size_t      index     = 0;
     2532                        addr_t      addr      = (addr_t) m_cmd_read_addr_fifo.read();
     2533                        bool        hit_read  = m_trt.hit_read(m_nline[addr], index);
     2534                        bool        hit_write = m_trt.hit_write(m_nline[addr]);
     2535                        bool        wok       = not m_trt.full(index);
     2536
     2537                        if (hit_read or !wok or hit_write)    // line already requested or no space
     2538                        {
     2539                            if (!wok)                    m_cpt_trt_full++;
     2540                            if (hit_read or hit_write)   m_cpt_trt_rb++;
     2541                            r_read_fsm = READ_IDLE;
     2542                        }
     2543                        else                  // missing line is requested to the XRAM
     2544                        {
     2545                            m_cpt_read_miss++;
     2546                            r_read_trt_index = index;
     2547                            r_read_fsm       = READ_TRT_SET;
     2548                        }
     2549
     2550#if DEBUG_MEMC_READ
     2551                        if (m_debug)
     2552                            std::cout << "  <MEMC " << name() << " READ_TRT_LOCK> Check TRT:"
     2553                                << " hit_read = " << hit_read
     2554                                << " / hit_write = " << hit_write
     2555                                << " / full = " << !wok << std::endl;
     2556#endif
     2557                    }
     2558                    break;
     2559                }
     2560                //////////////////
     2561            case READ_TRT_SET:      // register get transaction in TRT
     2562                {
     2563                    if (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
     2564                    {
     2565                        m_trt.set( r_read_trt_index.read(),
     2566                                true,      // GET
     2567                                m_nline[(addr_t)(m_cmd_read_addr_fifo.read())],
     2568                                m_cmd_read_srcid_fifo.read(),
     2569                                m_cmd_read_trdid_fifo.read(),
     2570                                m_cmd_read_pktid_fifo.read(),
     2571                                true,      // proc read
     2572                                m_cmd_read_length_fifo.read(),
     2573                                m_x[(addr_t)(m_cmd_read_addr_fifo.read())],
     2574                                std::vector<be_t> (m_words,0),
     2575                                std::vector<data_t> (m_words,0),
     2576                                r_read_ll_key.read());
     2577#if DEBUG_MEMC_READ
     2578                        if (m_debug)
     2579                            std::cout << "  <MEMC " << name() << " READ_TRT_SET> Set a GET in TRT:"
     2580                                << " address = " << std::hex << m_cmd_read_addr_fifo.read()
     2581                                << " / srcid = " << std::hex << m_cmd_read_srcid_fifo.read() << std::endl;
     2582#endif
     2583                        r_read_fsm = READ_TRT_REQ;
     2584                    }
     2585                    break;
     2586                }
     2587
     2588                //////////////////
     2589            case READ_TRT_REQ:   // consume the read request in FIFO and send it to IXR_CMD_FSM
     2590                {
     2591                    if (not r_read_to_ixr_cmd_req)
     2592                    {
     2593                        cmd_read_fifo_get       = true;
     2594                        r_read_to_ixr_cmd_req   = true;
     2595                        r_read_to_ixr_cmd_index = r_read_trt_index.read();
     2596                        r_read_fsm              = READ_IDLE;
     2597
     2598#if DEBUG_MEMC_READ
     2599                        if (m_debug)
     2600                            std::cout << "  <MEMC " << name() << " READ_TRT_REQ> Request GET transaction for address "
     2601                                << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
     2602#endif
     2603                    }
     2604                    break;
     2605                }
     2606        } // end switch read_fsm
     2607
     2608        ///////////////////////////////////////////////////////////////////////////////////
     2609        //    WRITE FSM
     2610        ///////////////////////////////////////////////////////////////////////////////////
     2611        // The WRITE FSM handles the write bursts and sc requests sent by the processors.
     2612        // All addresses in a burst must be in the same cache line.
     2613        // A complete write burst is consumed in the FIFO & copied to a local buffer.
     2614        // Then the FSM takes the lock protecting the cache directory, to check
     2615        // if the line is in the cache.
     2616        //
     2617        // - In case of HIT, the cache is updated.
     2618        //   If there is no other copy, an acknowledge response is immediately
     2619        //   returned to the writing processor.
     2620        //   If the data is cached by other processors, a coherence transaction must
     2621        //   be launched (sc requests always require a coherence transaction):
     2622        //   It is a multicast update if the line is not in counter mode: the processor
     2623        //   takes the lock protecting the Update Table (UPT) to register this transaction.
     2624        //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
     2625        //   a multi-update request to all owners of the line (but the writer),
     2626        //   through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM
     2627        //   does not respond to the writing processor, as this response will be sent by
     2628        //   the MULTI_ACK FSM when all update responses have been received.
     2629        //   It is a broadcast invalidate if the line is in counter mode: The line
     2630        //   should be erased in memory cache, and written in XRAM with a PUT transaction,
     2631        //   after registration in TRT.
     2632        //
     2633        // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
     2634        //   table (TRT). If a read transaction to the XRAM for this line already exists,
     2635        //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
     2636        //   the WRITE FSM register a new transaction in TRT, and sends a GET request
     2637        //   to the XRAM. If the TRT is full, it releases the lock, and waits.
     2638        //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
     2639        /////////////////////////////////////////////////////////////////////////////////////
     2640
     2641        //std::cout << std::endl << "write_fsm" << std::endl;
     2642
     2643        switch(r_write_fsm.read())
    10792644        {
    1080             need_rsp         = true;
    1081             error            = 0;
    1082             r_config_address = (r_config_address.read() & 0x00000000FFFFFFFFLL) |
    1083                                (((addr_t)wdata)<<32);
    1084         }
    1085         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set buf_lines
    1086                    and (cell == MEMC_BUF_LENGTH) )
    1087         {
    1088             need_rsp         = true;
    1089             error            = 0;
    1090             size_t lines     = wdata/(m_words<<2);
    1091             if ( wdata%(m_words<<2) ) lines++;
    1092             r_config_cmd_lines  = lines;
    1093             r_config_rsp_lines  = lines;
    1094         }
    1095         else if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)   // set cmd type
    1096                    and (cell == MEMC_CMD_TYPE) )
    1097         {
    1098             need_rsp         = false;
    1099             error            = 0;
    1100             r_config_cmd     = wdata;
    1101 
    1102             // prepare delayed response from CONFIG FSM
    1103             r_config_srcid   = p_vci_tgt.srcid.read();
    1104             r_config_trdid   = p_vci_tgt.trdid.read();
    1105             r_config_pktid   = p_vci_tgt.pktid.read();
    1106         }
    1107         else
    1108         {
    1109             need_rsp         = true;
    1110             error            = 1;
    1111         }
    1112 
    1113         if ( need_rsp )
    1114         {
    1115             // blocked if previous pending request to TGT_RSP FSM
    1116             if ( r_tgt_cmd_to_tgt_rsp_req.read() ) break;
    1117 
    1118             r_tgt_cmd_to_tgt_rsp_srcid = p_vci_tgt.srcid.read();
    1119             r_tgt_cmd_to_tgt_rsp_trdid = p_vci_tgt.trdid.read();
    1120             r_tgt_cmd_to_tgt_rsp_pktid = p_vci_tgt.pktid.read();
    1121             r_tgt_cmd_to_tgt_rsp_req   = true;
    1122             r_tgt_cmd_to_tgt_rsp_error = error;
    1123             r_tgt_cmd_to_tgt_rsp_rdata = rdata;
    1124             r_tgt_cmd_fsm              = TGT_CMD_IDLE;
    1125         }
    1126         else
    1127         {
    1128             r_tgt_cmd_fsm              = TGT_CMD_IDLE;
    1129         }
    1130 
    1131 #if DEBUG_MEMC_TGT_CMD
    1132 if(m_debug)
    1133 std::cout << "  <MEMC " << name() << " TGT_CMD_CONFIG> Configuration request:"
    1134           << " address = " << std::hex << p_vci_tgt.address.read()
    1135           << " / wdata = " << p_vci_tgt.wdata.read()
    1136           << " / need_rsp = " << need_rsp
    1137           << " / error = " << error << std::endl;
    1138 #endif
    1139         break;
    1140     }
    1141     //////////////////
    1142     case TGT_CMD_READ:    // Push a read request into read fifo
    1143 
    1144     // check that the read does not cross a cache line limit.
    1145     if ( ((m_x[(addr_t) p_vci_tgt.address.read()]+ (p_vci_tgt.plen.read() >>2)) > 16) and
    1146           (p_vci_tgt.cmd.read() != vci_param_int::CMD_LOCKED_READ))
    1147     {
    1148         std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
    1149                   << " illegal address/plen for VCI read command" << std::endl;
    1150         exit(0);
    1151     }
    1152     // check single flit
    1153     if(!p_vci_tgt.eop.read())
    1154     {
    1155         std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
    1156                   << " read command packet must contain one single flit" << std::endl;
    1157         exit(0);
    1158     }
    1159     // check plen for LL
    1160     if ( (p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) and
    1161          (p_vci_tgt.plen.read() != 8) )
    1162     {
    1163         std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_READ state"
    1164                   << " ll command packets must have a plen of 8" << std::endl;
    1165         exit(0);
    1166     }
    1167 
    1168     if ( p_vci_tgt.cmdval and m_cmd_read_addr_fifo.wok() )
    1169     {
    1170 
    1171 #if DEBUG_MEMC_TGT_CMD
    1172 if(m_debug)
    1173 std::cout << "  <MEMC " << name() << " TGT_CMD_READ> Push into read_fifo:"
    1174           << " address = " << std::hex << p_vci_tgt.address.read()
    1175           << " / srcid = " << p_vci_tgt.srcid.read()
    1176           << " / trdid = " << p_vci_tgt.trdid.read()
    1177           << " / pktid = " << p_vci_tgt.pktid.read()
    1178           << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
    1179 #endif
    1180         cmd_read_fifo_put = true;
    1181         if(p_vci_tgt.cmd.read() == vci_param_int::CMD_LOCKED_READ) m_cpt_ll++;
    1182         else                                                       m_cpt_read++;
    1183         r_tgt_cmd_fsm = TGT_CMD_IDLE;
    1184     }
    1185     break;
    1186 
    1187     ///////////////////
    1188     case TGT_CMD_WRITE:
    1189     if(p_vci_tgt.cmdval and m_cmd_write_addr_fifo.wok())
    1190     {
    1191 
    1192 #if DEBUG_MEMC_TGT_CMD
    1193 if(m_debug)
    1194 std::cout << "  <MEMC " << name() << " TGT_CMD_WRITE> Push into write_fifo:"
    1195           << " address = " << std::hex << p_vci_tgt.address.read()
    1196           << " / srcid = " << p_vci_tgt.srcid.read()
    1197           << " / trdid = " << p_vci_tgt.trdid.read()
    1198           << " / pktid = " << p_vci_tgt.pktid.read()
    1199           << " / wdata = " << p_vci_tgt.wdata.read()
    1200           << " / be = " << p_vci_tgt.be.read()
    1201           << " / plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
    1202 #endif
    1203         cmd_write_fifo_put = true;
    1204         if(p_vci_tgt.eop)  r_tgt_cmd_fsm = TGT_CMD_IDLE;
    1205     }
    1206     break;
    1207 
    1208     /////////////////
    1209     case TGT_CMD_CAS:
    1210     if((p_vci_tgt.plen.read() != 8) and (p_vci_tgt.plen.read() != 16))
    1211     {
    1212         std::cout << "VCI_MEM_CACHE ERROR " << name() << " TGT_CMD_CAS state"
    1213                   << "illegal format for CAS command " << std::endl;
    1214         exit(0);
    1215     }
    1216 
    1217     if(p_vci_tgt.cmdval and m_cmd_cas_addr_fifo.wok())
    1218     {
    1219 
    1220 #if DEBUG_MEMC_TGT_CMD
    1221 if(m_debug)
    1222 std::cout << "  <MEMC " << name() << " TGT_CMD_CAS> Pushing command into cmd_cas_fifo:"
    1223           << " address = " << std::hex << p_vci_tgt.address.read()
    1224           << " srcid = " << p_vci_tgt.srcid.read()
    1225           << " trdid = " << p_vci_tgt.trdid.read()
    1226           << " pktid = " << p_vci_tgt.pktid.read()
    1227           << " wdata = " << p_vci_tgt.wdata.read()
    1228           << " be = " << p_vci_tgt.be.read()
    1229           << " plen = " << std::dec << p_vci_tgt.plen.read() << std::endl;
    1230 #endif
    1231         cmd_cas_fifo_put = true;
    1232         if(p_vci_tgt.eop) r_tgt_cmd_fsm = TGT_CMD_IDLE;
    1233     }
    1234     break;
    1235   } // end switch tgt_cmd_fsm
    1236 
    1237   /////////////////////////////////////////////////////////////////////////
    1238   //    MULTI_ACK FSM
    1239   /////////////////////////////////////////////////////////////////////////
    1240   // This FSM controls the response to the multicast update requests sent
    1241   // by the memory cache to the L1 caches and update the UPT.
    1242   //
    1243   // - The FSM decrements the proper entry in UPT,
    1244   //   and clear the UPT entry when all responses have been received.
    1245   // - If required, it sends a request to the TGT_RSP FSM to complete
    1246   //   a pending  write transaction.
    1247   //
    1248   // All those multi-ack packets are one flit packet.
    1249   // The index in the UPT is defined in the TRDID field.
    1250   ////////////////////////////////////////////////////////////////////////
    1251 
    1252 //std::cout << std::endl << "multi_ack_fsm" << std::endl;
    1253 
    1254   switch(r_multi_ack_fsm.read())
    1255   {
    1256     ////////////////////
    1257     case MULTI_ACK_IDLE:
    1258     {
    1259         bool multi_ack_fifo_rok = m_cc_receive_to_multi_ack_fifo.rok();
    1260 
    1261         // No CC_RECEIVE FSM request and no WRITE FSM request
    1262         if( not multi_ack_fifo_rok and not r_write_to_multi_ack_req.read())
    1263           break;
    1264 
    1265         uint8_t updt_index;
    1266 
    1267         // handling WRITE FSM request to decrement update table response
    1268         // counter if no CC_RECEIVE FSM request
    1269         if(not multi_ack_fifo_rok)
    1270         {
    1271           updt_index               = r_write_to_multi_ack_upt_index.read();
    1272           r_write_to_multi_ack_req = false;
    1273         }
    1274         // Handling CC_RECEIVE FSM request
    1275         else
    1276         {
    1277           uint64_t flit = m_cc_receive_to_multi_ack_fifo.read();
    1278           updt_index    = DspinDhccpParam::dspin_get(flit,
    1279                             DspinDhccpParam::MULTI_ACK_UPDT_INDEX);
    1280 
    1281           cc_receive_to_multi_ack_fifo_get = true;
    1282         }
    1283 
    1284         assert((updt_index < m_upt.size()) and
    1285                "VCI_MEM_CACHE ERROR in MULTI_ACK_IDLE : "
    1286                "index too large for UPT");
    1287 
    1288         r_multi_ack_upt_index = updt_index;
    1289         r_multi_ack_fsm       = MULTI_ACK_UPT_LOCK;
    1290 
    1291 #if DEBUG_MEMC_MULTI_ACK
    1292 if(m_debug)
    1293 {
    1294     if (multi_ack_fifo_rok)
    1295     {
    1296         std::cout << "  <MEMC " << name()
    1297                   << " MULTI_ACK_IDLE> Response for UPT entry "
    1298                   << (size_t)updt_index << std::endl;
    1299     }
    1300     else
    1301     {
    1302         std::cout << "  <MEMC " << name()
    1303                   << " MULTI_ACK_IDLE> Write FSM request to decrement UPT entry "
    1304                   << updt_index << std::endl;
    1305     }
    1306 }
    1307 #endif
    1308         break;
    1309       }
    1310 
    1311     ////////////////////////
    1312     case MULTI_ACK_UPT_LOCK:
    1313     {
    1314         // get lock to the UPDATE table
    1315         if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK) break;
    1316 
    1317         // decrement the number of expected responses
    1318         size_t count = 0;
    1319         bool valid   = m_upt.decrement(r_multi_ack_upt_index.read(), count);
    1320 
    1321         if(not valid)
    1322         {
    1323             std::cout << "VCI_MEM_CACHE ERROR " << name()
    1324                       << " MULTI_ACK_UPT_LOCK state" << std::endl
    1325                       << "unsuccessful access to decrement the UPT" << std::endl;
    1326             exit(0);
    1327         }
    1328 
    1329         if(count == 0)
    1330         {
    1331           r_multi_ack_fsm = MULTI_ACK_UPT_CLEAR;
    1332         }
    1333         else
    1334         {
    1335           r_multi_ack_fsm = MULTI_ACK_IDLE;
    1336         }
    1337 
    1338 #if DEBUG_MEMC_MULTI_ACK
    1339 if(m_debug)
    1340 std::cout << "  <MEMC " << name()
    1341           << " MULTI_ACK_UPT_LOCK> Decrement the responses counter for UPT:"
    1342           << " entry = "       << r_multi_ack_upt_index.read()
    1343           << " / rsp_count = " << std::dec << count << std::endl;
    1344 #endif
    1345         break;
    1346     }
    1347 
    1348     /////////////////////////
    1349     case MULTI_ACK_UPT_CLEAR:   // Clear UPT entry / Test if rsp or ack required
    1350     {
    1351         if(r_alloc_upt_fsm.read() != ALLOC_UPT_MULTI_ACK)
    1352         {
    1353             std::cout << "VCI_MEM_CACHE ERROR " << name()
    1354                       << " MULTI_ACK_UPT_CLEAR state"
    1355                       << " bad UPT allocation" << std::endl;
    1356             exit(0);
    1357         }
    1358 
    1359         r_multi_ack_srcid = m_upt.srcid(r_multi_ack_upt_index.read());
    1360         r_multi_ack_trdid = m_upt.trdid(r_multi_ack_upt_index.read());
    1361         r_multi_ack_pktid = m_upt.pktid(r_multi_ack_upt_index.read());
    1362         r_multi_ack_nline = m_upt.nline(r_multi_ack_upt_index.read());
    1363         bool need_rsp     = m_upt.need_rsp(r_multi_ack_upt_index.read());
    1364 
    1365         // clear the UPT entry
    1366         m_upt.clear(r_multi_ack_upt_index.read());
    1367 
    1368         if      ( need_rsp ) r_multi_ack_fsm = MULTI_ACK_WRITE_RSP;
    1369         else                 r_multi_ack_fsm = MULTI_ACK_IDLE;
    1370 
    1371 #if DEBUG_MEMC_MULTI_ACK
    1372 if(m_debug)
    1373 std::cout <<  "  <MEMC " << name()
    1374           << " MULTI_ACK_UPT_CLEAR> Clear UPT entry "
    1375           << std::dec << r_multi_ack_upt_index.read() << std::endl;
    1376 #endif
    1377         break;
    1378     }
    1379     /////////////////////////
    1380     case MULTI_ACK_WRITE_RSP:     // Post a response request to TGT_RSP FSM
    1381                                   // Wait if pending request
    1382     {
    1383         if ( r_multi_ack_to_tgt_rsp_req.read() ) break;
    1384 
    1385         r_multi_ack_to_tgt_rsp_req   = true;
    1386         r_multi_ack_to_tgt_rsp_srcid = r_multi_ack_srcid.read();
    1387         r_multi_ack_to_tgt_rsp_trdid = r_multi_ack_trdid.read();
    1388         r_multi_ack_to_tgt_rsp_pktid = r_multi_ack_pktid.read();
    1389         r_multi_ack_fsm              = MULTI_ACK_IDLE;
    1390 
    1391 #if DEBUG_MEMC_MULTI_ACK
    1392 if(m_debug)
    1393 std::cout << "  <MEMC " << name() << " MULTI_ACK_WRITE_RSP>"
    1394           << " Request TGT_RSP FSM to send a response to srcid "
    1395           << std::hex << r_multi_ack_srcid.read() << std::endl;
    1396 #endif
    1397         break;
    1398     }
    1399   } // end switch r_multi_ack_fsm
    1400 
    1401   ////////////////////////////////////////////////////////////////////////////////////
    1402   //    CONFIG FSM
    1403   ////////////////////////////////////////////////////////////////////////////////////
    1404   // The CONFIG FSM handles the VCI configuration requests (INVAL & SYNC).
    1405   // The target buffer can have any size, and there is one single command for
    1406   // all cache lines covered by the target buffer.
    1407   //
    1408   // An INVAL or SYNC configuration operation is defined by the following registers:
    1409   // - bool      r_config_cmd        : INVAL / SYNC / NOP
    1410   // - uint64_t  r_config_address    : buffer base address
    1411   // - uint32_t  r_config_cmd_lines  : number of lines to be handled
    1412   // - uint32_t  r_config_rsp_lines  : number of lines not completed
    1413   //
    1414   // For both INVAL and SYNC commands, the CONFIG FSM contains the loop handling
    1415   // all cache lines covered by the buffer. The various lines of a given buffer
    1416   // can be pipelined: the CONFIG FSM does not wait the response for line (n) to send
    1417   // the command for line (n+1). It decrements the r_config_cmd_lines counter until
    1418   // the last request has been registered in TRT (for a SYNC), or in IVT (for an INVAL).
    1419   //
    1420   // - INVAL request:
    1421   //   For each line, it access to the DIR.
    1422   //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
    1423   //   In case of hit, with no copies in L1 caches, the line is invalidated and
    1424   //   a response is requested to TGT_RSP FSM.
    1425   //   If there is copies, a multi-inval, or a broadcast-inval coherence transaction
    1426   //   is launched and registered in UPT. The multi-inval transaction completion
    1427   //   is signaled by the CLEANUP FSM by decrementing the r_config_rsp_lines counter.
    1428   //   The CONFIG INVAL response is sent only when the last line has been invalidated.
    1429   //   TODO : The target buffer address must be aligned on a cache line boundary.
    1430   //   This constraint can be released, but it requires to make 2 PUT transactions
    1431   //   for the first and the last line...
    1432   //
    1433   // - SYNC request:
    1434   //   For each line, it access to the DIR.
    1435   //   In case of miss, it does nothing, and a response is requested to TGT_RSP FSM.
    1436   //   In case of hit, a PUT transaction is registered in TRT and a request is sent
    1437   //   to IXR_CMD FSM. The IXR_RSP FSM decrements the r_config_rsp_lines counter
    1438   //   when a PUT response is received.
    1439   //   The CONFIG SYNC response is sent only when the last PUT response is received.
    1440   //
    1441   // From the software point of view, a configuration request is a sequence
    1442   // of 6 atomic accesses in an uncached segment. A dedicated lock is used
    1443   // to handle only one configuration command at a given time:
    1444   // - Read  MEMC_LOCK       : Get the lock
    1445   // - Write MEMC_ADDR_LO    : Set the buffer address LSB
    1446   // - Write MEMC_ADDR_HI    : Set the buffer address MSB
    1447   // - Write MEMC_BUF_LENGTH : set buffer length (bytes)
    1448   // - Write MEMC_CMD_TYPE   : launch the actual operation
    1449   // - WRITE MEMC_LOCK       : release the lock
    1450   ////////////////////////////////////////////////////////////////////////////////////
    1451 
    1452 //std::cout << std::endl << "config_fsm" << std::endl;
    1453 
    1454   switch( r_config_fsm.read() )
    1455   {
    1456       /////////////////
    1457       case CONFIG_IDLE:  // waiting a config request
    1458       {
    1459           if ( r_config_cmd.read() != MEMC_CMD_NOP ) 
    1460           {
    1461               r_config_fsm    = CONFIG_LOOP;
    1462 
    1463 #if DEBUG_MEMC_CONFIG
    1464 if(m_debug)
    1465 std::cout << "  <MEMC " << name() << " CONFIG_IDLE> Config Request received"
    1466           << " / address = " << std::hex << r_config_address.read()
    1467           << " / lines = " << std::dec << r_config_cmd_lines.read()
    1468           << " / type = " << r_config_cmd.read() << std::endl;
    1469 #endif
    1470           }
    1471           break;
    1472       }
    1473       /////////////////
    1474       case CONFIG_LOOP:   // test if last line to be handled
    1475       {
    1476           if ( r_config_cmd_lines.read() == 0 )
    1477           {
    1478               r_config_cmd = MEMC_CMD_NOP;
    1479               r_config_fsm = CONFIG_WAIT;
    1480           }
    1481           else
    1482           {
    1483               r_config_fsm = CONFIG_DIR_REQ;
    1484           }
    1485 
    1486 #if DEBUG_MEMC_CONFIG
    1487 if(m_debug)
    1488 std::cout << "  <MEMC " << name() << " CONFIG_LOOP>"
    1489           << " / address = " << std::hex << r_config_address.read()   
    1490           << " / lines not handled = " << std::dec << r_config_cmd_lines.read()
    1491           << " / command = " << r_config_cmd.read() << std::endl;
    1492 #endif
    1493           break;
    1494       }
    1495       /////////////////
    1496       case CONFIG_WAIT:   // wait completion (last response)
    1497       {
    1498           if ( r_config_rsp_lines.read() == 0 )  // last response received
    1499           {
    1500               r_config_fsm = CONFIG_RSP;
    1501           }
    1502 
    1503 #if DEBUG_MEMC_CONFIG
    1504 if(m_debug)
    1505 std::cout << "  <MEMC " << name() << " CONFIG_WAIT>"
    1506           << " / lines to do = " << std::dec << r_config_rsp_lines.read() << std::endl;
    1507 #endif
    1508           break;
    1509       }
    1510       ////////////////
    1511       case CONFIG_RSP:  // request TGT_RSP FSM to return response
    1512       {
    1513           if ( not r_config_to_tgt_rsp_req.read() )
    1514           {
    1515               r_config_to_tgt_rsp_srcid  = r_config_srcid.read();
    1516               r_config_to_tgt_rsp_trdid  = r_config_trdid.read();
    1517               r_config_to_tgt_rsp_pktid  = r_config_pktid.read();
    1518               r_config_to_tgt_rsp_error  = false;
    1519               r_config_to_tgt_rsp_req    = true;
    1520               r_config_fsm               = CONFIG_IDLE;
    1521 
    1522 #if DEBUG_MEMC_CONFIG
    1523 if(m_debug)
    1524 std::cout << "  <MEMC " << name() << " CONFIG_RSP> Request TGT_RSP FSM to return response:"
    1525           << " error = " << r_config_to_tgt_rsp_error.read()
    1526           << " / rsrcid = " << std::hex << r_config_srcid.read()
    1527           << " / rtrdid = " << std::hex << r_config_trdid.read()
    1528           << " / rpktid = " << std::hex << r_config_pktid.read() << std::endl;
    1529 #endif
    1530           }
    1531           break;
    1532 
    1533       }
    1534       ////////////////////
    1535       case CONFIG_DIR_REQ:  // Request directory lock
    1536       {
    1537           if ( r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG )
    1538           {
    1539               r_config_fsm = CONFIG_DIR_ACCESS;
    1540           }
    1541 
    1542 #if DEBUG_MEMC_CONFIG
    1543 if(m_debug)
    1544 std::cout << "  <MEMC " << name() << " CONFIG_DIR_REQ>"
    1545           << " Request DIR access" << std::endl;
    1546 #endif
    1547           break;
    1548       }
    1549       ///////////////////////
    1550       case CONFIG_DIR_ACCESS:   // Access directory and decode config command
    1551       {
    1552           assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
    1553           "MEMC ERROR in CONFIG_DIR_ACCESS state: bad DIR allocation");
    1554 
    1555           size_t way = 0;
    1556           DirectoryEntry entry = m_cache_directory.read(r_config_address.read(), way);
    1557 
    1558           r_config_dir_way        = way;
    1559           r_config_dir_copy_inst  = entry.owner.inst;
    1560           r_config_dir_copy_srcid = entry.owner.srcid;
    1561           r_config_dir_is_cnt     = entry.is_cnt;
    1562           r_config_dir_lock       = entry.lock;
    1563           r_config_dir_count      = entry.count;
    1564           r_config_dir_ptr        = entry.ptr;
    1565 
    1566           if ( entry.valid and                            // hit & inval command
    1567                (r_config_cmd.read() == MEMC_CMD_INVAL) )
    1568           {
    1569               r_config_fsm       = CONFIG_IVT_LOCK;
    1570           }
    1571           else if ( entry.valid and                       // hit & sync command
    1572                     entry.dirty and
    1573                     (r_config_cmd.read() == MEMC_CMD_SYNC) )
    1574           {
    1575               r_config_fsm       = CONFIG_TRT_LOCK;
    1576           }
    1577           else                                            // miss : return to LOOP
    1578           {
    1579               r_config_cmd_lines = r_config_cmd_lines.read() - 1;
    1580               r_config_rsp_lines = r_config_rsp_lines.read() - 1;
    1581               r_config_address   = r_config_address.read() + (m_words<<2);
    1582               r_config_fsm       = CONFIG_LOOP;
    1583           }
    1584 
    1585 #if DEBUG_MEMC_CONFIG
    1586 if(m_debug)
    1587 std::cout << "  <MEMC " << name() << " CONFIG_DIR_ACCESS> Accessing directory: "
    1588           << " address = " << std::hex << r_config_address.read()
    1589           << " / hit = " << std::dec << entry.valid
    1590           << " / dirty = " << entry.dirty
    1591           << " / count = " << entry.count
    1592           << " / is_cnt = " << entry.is_cnt << std::endl;
    1593 #endif
    1594           break;
    1595       }
    1596       /////////////////////
    1597       case CONFIG_TRT_LOCK:      // enter this state in case of SYNC command
    1598                                  // to a dirty cache line
    1599                                  // keep DIR lock, and try to get TRT lock
    1600                                  // return to LOOP state if TRT full
    1601                                  // reset dirty bit in DIR and register a PUT
    1602                                  // trabsaction in TRT if not full.
    1603       {
    1604           assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
    1605           "MEMC ERROR in CONFIG_TRT_LOCK state: bad DIR allocation");
    1606 
    1607           if ( r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG )
    1608           {
    1609               size_t index = 0;
    1610               bool   wok   = not m_trt.full(index);
    1611 
    1612               if ( not wok )
    1613               {
    1614                   r_config_fsm = CONFIG_LOOP;
    1615               }
    1616               else
    1617               {
    1618                   size_t          way = r_config_dir_way.read();
    1619                   size_t          set = m_y[r_config_address.read()];
    1620 
    1621                   // reset dirty bit in DIR
    1622                   DirectoryEntry  entry;
    1623                   entry.valid       = true;
    1624                   entry.dirty       = false;
    1625                   entry.tag         = m_z[r_config_address.read()];
    1626                   entry.is_cnt      = r_config_dir_is_cnt.read();
    1627                   entry.lock        = r_config_dir_lock.read();
    1628                   entry.ptr         = r_config_dir_ptr.read();
    1629                   entry.count       = r_config_dir_count.read();
    1630                   entry.owner.inst  = r_config_dir_copy_inst.read();
    1631                   entry.owner.srcid = r_config_dir_copy_srcid.read();
    1632                   m_cache_directory.write( set, way, entry );
    1633 
    1634                   r_config_trt_index = index;
    1635                   r_config_fsm       = CONFIG_TRT_SET;
    1636               }
    1637 
    1638 #if DEBUG_MEMC_CONFIG
    1639 if(m_debug)
    1640 std::cout << "  <MEMC " << name() << " CONFIG_TRT_LOCK> Access TRT: "
    1641           << " wok = " << std::dec << wok
    1642           << " index = " << index << std::endl;
    1643 #endif
    1644           }
    1645           break;
    1646       }
    1647       ////////////////////
    1648       case CONFIG_TRT_SET:       // read data in cache
    1649                                  // and post a PUT request in TRT
    1650       {
    1651           assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
    1652           "MEMC ERROR in CONFIG_TRT_SET state: bad DIR allocation");
    1653 
    1654           assert( (r_alloc_trt_fsm.read() == ALLOC_TRT_CONFIG) and
    1655           "MEMC ERROR in CONFIG_TRT_SET state: bad TRT allocation");
    1656 
    1657           // read data into cache
    1658           size_t              way = r_config_dir_way.read();
    1659           size_t              set = m_y[r_config_address.read()];
    1660           std::vector<data_t> data_vector;
    1661           data_vector.clear();
    1662           for(size_t word=0; word<m_words; word++)
    1663           {
    1664               uint32_t data = m_cache_data.read( way, set, word );
    1665               data_vector.push_back( data );
    1666           }
    1667 
    1668           // post the PUT request in TRT
    1669           m_trt.set( r_config_trt_index.read(),
    1670                      false,                               // PUT transaction
    1671                      m_nline[r_config_address.read()],    // line index
    1672                      0,                                   // srcid:           unused
    1673                      0,                                   // trdid:           unused
    1674                      0,                                   // pktid:           unused
    1675                      false,                               // not proc_read
    1676                      0,                                   // read_length:     unused
    1677                      0,                                   // word_index:      unused
    1678                      std::vector<be_t>(m_words,0xF),      // byte-enable:     unused
    1679                      data_vector,                         // data to be written
    1680                      0,                                   // ll_key:          unused
    1681                      true );                              // requested by config FSM
    1682           r_config_fsm = CONFIG_PUT_REQ;
    1683 
    1684 #if DEBUG_MEMC_CONFIG
    1685 if(m_debug)
    1686 std::cout << "  <MEMC " << name() << " CONFIG_TRT_SET> PUT request in TRT:"
    1687           << " address = " << std::hex << r_config_address.read()
    1688           << " index = " << std::dec << r_config_trt_index.read() << std::endl;
    1689 #endif
    1690           break;
    1691       }
    1692       ////////////////////
    1693       case CONFIG_PUT_REQ:       // post PUT request to IXR_CMD_FSM
    1694       {
    1695           if ( not r_config_to_ixr_cmd_req.read() )
    1696           {
    1697               r_config_to_ixr_cmd_req   = true;
    1698               r_config_to_ixr_cmd_index = r_config_trt_index.read();
    1699 
    1700               // prepare next iteration
    1701               r_config_cmd_lines              = r_config_cmd_lines.read() - 1;
    1702               r_config_address                = r_config_address.read() + (m_words<<2);
    1703               r_config_fsm                    = CONFIG_LOOP;
    1704 
    1705 #if DEBUG_MEMC_CONFIG
    1706 if(m_debug)
    1707 std::cout << "  <MEMC " << name() << " CONFIG_PUT_REQ> post PUT request to IXR_CMD_FSM"
    1708           << " / address = " << std::hex << r_config_address.read() << std::endl;
    1709 #endif
    1710           }
    1711           break;
    1712       }
    1713       /////////////////////
    1714       case CONFIG_IVT_LOCK:  // enter this state in case of INVAL command
    1715                              // Keep DIR lock and Try to get IVT lock.
    1716                              // Return to LOOP state if IVT full.
    1717                              // Register inval in IVT, and invalidate the
    1718                              // directory if IVT not full.
    1719       {
    1720           assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_CONFIG) and
    1721           "MEMC ERROR in CONFIG_IVT_LOCK state: bad DIR allocation");
    1722 
    1723           if ( r_alloc_ivt_fsm.read() == ALLOC_IVT_CONFIG )
    1724           {
    1725               size_t set        = m_y[(addr_t)(r_config_address.read())];
    1726               size_t way        = r_config_dir_way.read();
    1727 
    1728               if ( r_config_dir_count.read() == 0 )     // inval DIR and return to LOOP
    1729               {
    1730                   m_cache_directory.inval( way, set );
    1731                   r_config_cmd_lines  = r_config_cmd_lines.read() - 1;
    1732                   r_config_rsp_lines  = r_config_rsp_lines.read() - 1;
    1733                   r_config_address    = r_config_address.read() + (m_words<<2);
    1734                   r_config_fsm        = CONFIG_LOOP;
    1735 
    1736 #if DEBUG_MEMC_CONFIG
    1737 if(m_debug)
    1738 std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
    1739           << " No copies in L1 : inval DIR entry"  << std::endl;
    1740 #endif
    1741               }
    1742               else    // try to register inval in IVT
    1743               {
    1744                   bool        wok       = false;
    1745                   size_t      index     = 0;
    1746                   bool        broadcast = r_config_dir_is_cnt.read();
    1747                   size_t      srcid     = r_config_srcid.read();
    1748                   size_t      trdid     = r_config_trdid.read();
    1749                   size_t      pktid     = r_config_pktid.read();
    1750                   addr_t      nline     = m_nline[(addr_t)(r_config_address.read())];
    1751                   size_t      nb_copies = r_config_dir_count.read();
    1752 
    1753                   wok = m_ivt.set(false,       // it's an inval transaction
    1754                                   broadcast,   
    1755                                   false,       // no response required
    1756                                   true,        // acknowledge required
    1757                                   srcid,
    1758                                   trdid,
    1759                                   pktid,
    1760                                   nline,
    1761                                   nb_copies,
    1762                                   index);
    1763 
    1764                   if ( wok )  // IVT success => inval DIR slot
    1765                   {
    1766                       m_cache_directory.inval( way, set );
    1767                       r_config_ivt_index = index;
    1768                       if ( broadcast )  r_config_fsm = CONFIG_BC_SEND;
    1769                       else              r_config_fsm = CONFIG_INVAL_SEND;
    1770 
    1771 #if DEBUG_MEMC_CONFIG
    1772 if(m_debug)
    1773 std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
    1774           << " Inval DIR entry and register inval in IVT"
    1775           << " / index = " << std::dec << index
    1776           << " / broadcast = " << broadcast << std::endl;
    1777 #endif
    1778                   }
    1779                   else       // IVT full => release both DIR and IVT locks
    1780                   {
    1781                       r_config_fsm = CONFIG_LOOP;
    1782 
    1783 #if DEBUG_MEMC_CONFIG
    1784 if(m_debug)
    1785 std::cout << "  <MEMC " << name() << " CONFIG_IVT_LOCK>"
    1786           << " IVT full : release DIR & IVT locks and retry" << std::endl;
    1787 #endif
    1788                   }
    1789               }
    1790           }
    1791           break;
    1792       }
    1793       ////////////////////
    1794       case CONFIG_BC_SEND:    // Post a broadcast inval request to CC_SEND FSM
    1795       {
    1796           if( not r_config_to_cc_send_multi_req.read() and
    1797               not r_config_to_cc_send_brdcast_req.read() )
    1798           {
    1799               // post bc inval request
    1800               r_config_to_cc_send_multi_req   = false;
    1801               r_config_to_cc_send_brdcast_req = true;
    1802               r_config_to_cc_send_trdid       = r_config_ivt_index.read();
    1803               r_config_to_cc_send_nline       = m_nline[(addr_t)(r_config_address.read())];
    1804 
    1805               // prepare next iteration
    1806               r_config_cmd_lines              = r_config_cmd_lines.read() - 1;
    1807               r_config_address                = r_config_address.read() + (m_words<<2);
    1808               r_config_fsm                    = CONFIG_LOOP;
    1809 
    1810 #if DEBUG_MEMC_CONFIG
    1811 if(m_debug)
    1812 std::cout << "  <MEMC " << name() << " CONFIG_BC_SEND>"
    1813           << " Post a broadcast inval request to CC_SEND FSM"
    1814           << " / address = " << r_config_address.read() <<std::endl;
    1815 #endif
    1816           }
    1817           break;
    1818       }
    1819       ///////////////////////
    1820       case CONFIG_INVAL_SEND:    // Post a multi inval request to CC_SEND FSM
    1821       {
    1822           if( not r_config_to_cc_send_multi_req.read() and
    1823               not r_config_to_cc_send_brdcast_req.read() )
    1824           {
    1825               // post multi inval request
    1826               r_config_to_cc_send_multi_req   = true;
    1827               r_config_to_cc_send_brdcast_req = false;
    1828               r_config_to_cc_send_trdid       = r_config_ivt_index.read();
    1829               r_config_to_cc_send_nline       = m_nline[(addr_t)(r_config_address.read())];
    1830 
    1831               // post data into FIFO
    1832               config_to_cc_send_fifo_srcid    = r_config_dir_copy_srcid.read();
    1833               config_to_cc_send_fifo_inst     = r_config_dir_copy_inst.read();
    1834               config_to_cc_send_fifo_put      = true;
    1835 
    1836               if ( r_config_dir_count.read() == 1 )  // one copy
    1837               {
    1838                   // prepare next iteration
    1839                   r_config_cmd_lines          = r_config_cmd_lines.read() - 1;
    1840                   r_config_address            = r_config_address.read() + (m_words<<2);
    1841                   r_config_fsm                = CONFIG_LOOP;
    1842               }
    1843               else                                   // several copies
    1844               {
    1845                   r_config_fsm = CONFIG_HEAP_REQ;
    1846               }
    1847 
    1848 #if DEBUG_MEMC_CONFIG
    1849 if(m_debug)
    1850 std::cout << "  <MEMC " << name() << " CONFIG_INVAL_SEND>"
    1851           << " Post multi inval request to CC_SEND FSM"
    1852           << " / address = " << std::hex << r_config_address.read()
    1853           << " / copy = " << r_config_dir_copy_srcid.read()
    1854           << " / inst = " << std::dec << r_config_dir_copy_inst.read() << std::endl;
    1855 #endif
    1856           }
    1857           break;
    1858       }
    1859       /////////////////////
    1860       case CONFIG_HEAP_REQ:  // Try to get access to Heap
    1861       {
    1862           if ( r_alloc_heap_fsm.read() == ALLOC_HEAP_CONFIG )
    1863           {
    1864               r_config_fsm       = CONFIG_HEAP_SCAN;
    1865               r_config_heap_next = r_config_dir_ptr.read();
    1866           }
    1867 
    1868 #if DEBUG_MEMC_CONFIG
    1869 if(m_debug)
    1870 std::cout << "  <MEMC " << name() << " CONFIG_HEAP_REQ>"
    1871           << " Requesting HEAP lock" << std::endl;
    1872 #endif
    1873           break;
    1874       }
    1875       //////////////////////
    1876       case CONFIG_HEAP_SCAN:      // scan HEAP and send inval to CC_SEND FSM
    1877       {
    1878           HeapEntry entry = m_heap.read( r_config_heap_next.read() );
    1879           bool last_copy  = (entry.next == r_config_heap_next.read());
    1880 
    1881           config_to_cc_send_fifo_srcid = entry.owner.srcid;
    1882           config_to_cc_send_fifo_inst  = entry.owner.inst;
    1883           // config_to_cc_send_fifo_last  = last_copy;
    1884           config_to_cc_send_fifo_put   = true;
    1885 
    1886           if ( m_config_to_cc_send_inst_fifo.wok() ) // inval request accepted
    1887           {
    1888               r_config_heap_next = entry.next;
    1889               if ( last_copy ) r_config_fsm = CONFIG_HEAP_LAST;
    1890           }
    1891          
    1892 #if DEBUG_MEMC_CONFIG
    1893 if(m_debug)
    1894 std::cout << "  <MEMC " << name() << " CONFIG_HEAP_SCAN>"
    1895           << " Post multi inval request to CC_SEND FSM"
    1896           << " / address = " << std::hex << r_config_address.read()
    1897           << " / copy = " << entry.owner.srcid
    1898           << " / inst = " << std::dec << entry.owner.inst << std::endl;
    1899 #endif
    1900           break;
    1901       }
    1902       //////////////////////
    1903       case CONFIG_HEAP_LAST:      // HEAP housekeeping
    1904       {
    1905           size_t free_pointer = m_heap.next_free_ptr();
    1906           HeapEntry last_entry;
    1907           last_entry.owner.srcid = 0;
    1908           last_entry.owner.inst  = false;
    1909 
    1910           if ( m_heap.is_full() )
    1911           {
    1912               last_entry.next = r_config_dir_ptr.read();
    1913               m_heap.unset_full();
    1914           }
    1915           else
    1916           {
    1917               last_entry.next = free_pointer;
    1918           }
    1919 
    1920           m_heap.write_free_ptr( r_config_dir_ptr.read() );
    1921           m_heap.write( r_config_heap_next.read(), last_entry );
    1922 
    1923           // prepare next iteration
    1924           r_config_cmd_lines          = r_config_cmd_lines.read() - 1;
    1925           r_config_address            = r_config_address.read() + (m_words<<2);
    1926           r_config_fsm                = CONFIG_LOOP;
    1927 
    1928 #if DEBUG_MEMC_CONFIG
    1929 if(m_debug)
    1930 std::cout << "  <MEMC " << name() << " CONFIG_HEAP_LAST>"
    1931           << " Heap housekeeping" << std::endl;
    1932 #endif
    1933           break;
    1934       }
    1935   }  // end switch r_config_fsm
    1936 
    1937   ////////////////////////////////////////////////////////////////////////////////////
    1938   //    READ FSM
    1939   ////////////////////////////////////////////////////////////////////////////////////
    1940   // The READ FSM controls the VCI read  and ll requests.
    1941   // It takes the lock protecting the cache directory to check the cache line status:
    1942   // - In case of HIT
    1943   //   The fsm copies the data (one line, or one single word)
    1944   //   in the r_read_to_tgt_rsp buffer. It waits if this buffer is not empty.
    1945   //   The requesting initiator is registered in the cache directory.
    1946   //   If the number of copy is larger than 1, the new copy is registered
    1947   //   in the HEAP.
    1948   //   If the number of copy is larger than the threshold, the HEAP is cleared,
    1949   //   and the corresponding line switches to the counter mode.
    1950   // - In case of MISS
    1951   //   The READ fsm takes the lock protecting the transaction tab.
    1952   //   If a read transaction to the XRAM for this line already exists,
    1953   //   or if the transaction tab is full, the fsm is stalled.
    1954   //   If a TRT entry is free, the READ request is registered in TRT,
    1955   //   it is consumed in the request FIFO, and transmited to the IXR_CMD FSM.
    1956   //   The READ FSM returns in the IDLE state as the read transaction will be
    1957   //   completed when the missing line will be received.
    1958   ////////////////////////////////////////////////////////////////////////////////////
    1959 
    1960 //std::cout << std::endl << "read_fsm" << std::endl;
    1961 
    1962   switch(r_read_fsm.read())
    1963   {
    1964     ///////////////
    1965     case READ_IDLE:  // waiting a read request
    1966     {
    1967         if(m_cmd_read_addr_fifo.rok())
    1968         {
    1969 
    1970 #if DEBUG_MEMC_READ
    1971 if(m_debug)
    1972 std::cout << "  <MEMC " << name() << " READ_IDLE> Read request"
    1973           << " : address = " << std::hex << m_cmd_read_addr_fifo.read()
    1974           << " / srcid = " << m_cmd_read_srcid_fifo.read()
    1975           << " / trdid = " << m_cmd_read_trdid_fifo.read()
    1976           << " / pktid = " << m_cmd_read_pktid_fifo.read()
    1977           << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
    1978 #endif
    1979             r_read_fsm = READ_DIR_REQ;
    1980         }
    1981         break;
    1982     }
    1983     //////////////////
    1984     case READ_DIR_REQ:  // Get the lock to the directory
    1985     {
    1986         if(r_alloc_dir_fsm.read() == ALLOC_DIR_READ)
    1987         {
    1988             r_read_fsm = READ_DIR_LOCK;
    1989         }
    1990 
    1991 #if DEBUG_MEMC_READ
    1992 if(m_debug)
    1993 std::cout << "  <MEMC " << name() << " READ_DIR_REQ> Requesting DIR lock " << std::endl;
    1994 #endif
    1995         break;
    1996     }
    1997 
    1998     ///////////////////
    1999     case READ_DIR_LOCK:  // check directory for hit / miss
    2000     {
    2001         assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
    2002         "MEMC ERROR in READ_DIR_LOCK state: Bad DIR allocation");
    2003 
    2004         size_t way = 0;
    2005         DirectoryEntry entry = m_cache_directory.read(m_cmd_read_addr_fifo.read(), way);
    2006 
    2007         // access the global table ONLY when we have an LL cmd
    2008         if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL)   
    2009         {
    2010             r_read_ll_key   = m_llsc_table.ll(m_cmd_read_addr_fifo.read());
    2011         }
    2012         r_read_is_cnt     = entry.is_cnt;
    2013         r_read_dirty      = entry.dirty;
    2014         r_read_lock       = entry.lock;
    2015         r_read_tag        = entry.tag;
    2016         r_read_way        = way;
    2017         r_read_count      = entry.count;
    2018         r_read_copy       = entry.owner.srcid;
    2019         r_read_copy_inst  = entry.owner.inst;
    2020         r_read_ptr        = entry.ptr; // pointer to the heap
    2021 
    2022         // check if this is a cached read, this means pktid is either
    2023         // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
    2024         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
    2025         bool cached_read = (m_cmd_read_pktid_fifo.read() & 0x1);
    2026         if(entry.valid)    // hit
    2027         {
    2028             // test if we need to register a new copy in the heap
    2029             if(entry.is_cnt or (entry.count == 0) or !cached_read)
    2030             {
    2031                 r_read_fsm = READ_DIR_HIT;
    2032             }
    2033             else
    2034             {
    2035                 r_read_fsm = READ_HEAP_REQ;
    2036             }
    2037         }
    2038         else      // miss
    2039         {
    2040             r_read_fsm = READ_TRT_LOCK;
    2041         }
    2042 
    2043 #if DEBUG_MEMC_READ
    2044 if(m_debug)
    2045 {
    2046 std::cout << "  <MEMC " << name() << " READ_DIR_LOCK> Accessing directory: "
    2047           << " address = " << std::hex << m_cmd_read_addr_fifo.read()
    2048           << " / hit = " << std::dec << entry.valid
    2049           << " / count = " <<std::dec << entry.count
    2050           << " / is_cnt = " << entry.is_cnt;
    2051 if((m_cmd_read_pktid_fifo.read() & 0x7) == TYPE_LL) std::cout << " / LL access" << std::endl;
    2052 else                                                std::cout << std::endl;
    2053 }
    2054 #endif
    2055         break;
    2056     }
    2057     //////////////////
    2058     case READ_DIR_HIT:    //  read data in cache & update the directory
    2059                           //  we enter this state in 3 cases:
    2060                           //  - the read request is uncachable
    2061                           //  - the cache line is in counter mode
    2062                           //  - the cache line is valid but not replicated
    2063 
    2064     {
    2065         assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
    2066         "MEMC ERROR in READ_DIR_HIT state: Bad DIR allocation");
    2067 
    2068         // check if this is an instruction read, this means pktid is either
    2069         // TYPE_READ_INS_UNC   0bX010 with TSAR encoding
    2070         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
    2071         bool inst_read    = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
    2072         // check if this is a cached read, this means pktid is either
    2073         // TYPE_READ_DATA_MISS 0bX001 with TSAR encoding
    2074         // TYPE_READ_INS_MISS  0bX011 with TSAR encoding
    2075         bool cached_read  = (m_cmd_read_pktid_fifo.read() & 0x1);
    2076         bool is_cnt       = r_read_is_cnt.read();
    2077 
    2078         // read data in the cache
    2079         size_t set        = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
    2080         size_t way        = r_read_way.read();
    2081 
    2082         m_cache_data.read_line(way, set, r_read_data);
    2083 
    2084         // update the cache directory
    2085         DirectoryEntry entry;
    2086         entry.valid   = true;
    2087         entry.is_cnt  = is_cnt;
    2088         entry.dirty   = r_read_dirty.read();
    2089         entry.tag     = r_read_tag.read();
    2090         entry.lock    = r_read_lock.read();
    2091         entry.ptr     = r_read_ptr.read();
    2092 
    2093         if(cached_read)   // Cached read => we must update the copies
    2094         {
    2095             if(!is_cnt)  // Not counter mode
    2096             {
    2097                 entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
    2098                 entry.owner.inst     = inst_read;
    2099                 entry.count          = r_read_count.read() + 1;
    2100             }
    2101             else  // Counter mode
    2102             {
    2103                 entry.owner.srcid    = 0;
    2104                 entry.owner.inst     = false;
    2105                 entry.count          = r_read_count.read() + 1;
    2106             }
    2107         }
    2108         else            // Uncached read
    2109         {
    2110             entry.owner.srcid     = r_read_copy.read();
    2111             entry.owner.inst      = r_read_copy_inst.read();
    2112             entry.count           = r_read_count.read();
    2113         }
    2114 
    2115 #if DEBUG_MEMC_READ
    2116 if(m_debug)
    2117 std::cout << "  <MEMC " << name() << " READ_DIR_HIT> Update directory entry:"
    2118           << " addr = " << std::hex << m_cmd_read_addr_fifo.read()
    2119           << " / set = " << std::dec << set
    2120           << " / way = " << way
    2121           << " / owner_id = " << std::hex << entry.owner.srcid
    2122           << " / owner_ins = " << std::dec << entry.owner.inst
    2123           << " / count = " << entry.count
    2124           << " / is_cnt = " << entry.is_cnt << std::endl;
    2125 #endif
    2126         m_cache_directory.write(set, way, entry);
    2127         r_read_fsm    = READ_RSP;
    2128         break;
    2129     }
    2130     ///////////////////
    2131     case READ_HEAP_REQ:    // Get the lock to the HEAP directory
    2132     {
    2133       if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
    2134       {
    2135         r_read_fsm = READ_HEAP_LOCK;
    2136       }
    2137 
    2138 #if DEBUG_MEMC_READ
    2139 if(m_debug)
    2140 std::cout << "  <MEMC " << name() << " READ_HEAP_REQ>"
    2141           << " Requesting HEAP lock " << std::endl;
    2142 #endif
    2143       break;
    2144     }
    2145 
    2146     ////////////////////
    2147     case READ_HEAP_LOCK:   // read data in cache, update the directory
    2148                            // and prepare the HEAP update
    2149     {
    2150       if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
    2151       {
    2152         // enter counter mode when we reach the limit of copies or the heap is full
    2153         bool go_cnt = (r_read_count.read() >= m_max_copies) or m_heap.is_full();
    2154 
    2155         // read data in the cache
    2156         size_t set = m_y[(addr_t)(m_cmd_read_addr_fifo.read())];
    2157         size_t way = r_read_way.read();
    2158 
    2159         m_cache_data.read_line(way, set, r_read_data);
    2160 
    2161         // update the cache directory
    2162         DirectoryEntry entry;
    2163         entry.valid  = true;
    2164         entry.is_cnt = go_cnt;
    2165         entry.dirty  = r_read_dirty.read();
    2166         entry.tag    = r_read_tag.read();
    2167         entry.lock   = r_read_lock.read();
    2168         entry.count  = r_read_count.read() + 1;
    2169 
    2170         if(not go_cnt)         // Not entering counter mode
    2171         {
    2172           entry.owner.srcid    = r_read_copy.read();
    2173           entry.owner.inst     = r_read_copy_inst.read();
    2174           entry.ptr            = m_heap.next_free_ptr();   // set pointer on the heap
    2175         }
    2176         else                // Entering Counter mode
    2177         {
    2178           entry.owner.srcid    = 0;
    2179           entry.owner.inst     = false;
    2180           entry.ptr            = 0;
    2181         }
    2182 
    2183         m_cache_directory.write(set, way, entry);
    2184 
    2185         // prepare the heap update (add an entry, or clear the linked list)
    2186         if(not go_cnt)      // not switching to counter mode
    2187         {
    2188           // We test if the next free entry in the heap is the last
    2189           HeapEntry heap_entry = m_heap.next_free_entry();
    2190           r_read_next_ptr      = heap_entry.next;
    2191           r_read_last_free     = (heap_entry.next == m_heap.next_free_ptr());
    2192 
    2193           r_read_fsm           = READ_HEAP_WRITE; // add an entry in the HEAP
    2194         }
    2195         else            // switching to counter mode
    2196         {
    2197           if(r_read_count.read() >1)              // heap must be cleared
    2198           {
    2199             HeapEntry next_entry = m_heap.read(r_read_ptr.read());
    2200             r_read_next_ptr      = m_heap.next_free_ptr();
    2201             m_heap.write_free_ptr(r_read_ptr.read());
    2202 
    2203             if(next_entry.next == r_read_ptr.read())    // last entry
    2204             {
    2205               r_read_fsm = READ_HEAP_LAST;    // erase the entry
    2206             }
    2207             else                                        // not the last entry
    2208             {
    2209               r_read_ptr = next_entry.next;
    2210               r_read_fsm = READ_HEAP_ERASE;   // erase the list
    2211             }
    2212           }
    2213           else  // the heap is not used / nothing to do
    2214           {
    2215             r_read_fsm = READ_RSP;
    2216           }
    2217         }
    2218 
    2219 #if DEBUG_MEMC_READ
    2220 if(m_debug)
    2221 std::cout << "  <MEMC " << name() << " READ_HEAP_LOCK> Update directory:"
    2222           << " tag = " << std::hex << entry.tag
    2223           << " set = " << std::dec << set
    2224           << " way = " << way
    2225           << " count = " << entry.count
    2226           << " is_cnt = " << entry.is_cnt << std::endl;
    2227 #endif
    2228       }
    2229       else
    2230       {
    2231         std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LOCK"
    2232                   << "Bad HEAP allocation"   << std::endl;
    2233         exit(0);
    2234       }
    2235       break;
    2236     }
    2237     /////////////////////
    2238     case READ_HEAP_WRITE:       // add an entry in the heap
    2239     {
    2240       if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
    2241       {
    2242         HeapEntry heap_entry;
    2243         heap_entry.owner.srcid    = m_cmd_read_srcid_fifo.read();
    2244         heap_entry.owner.inst     = ((m_cmd_read_pktid_fifo.read() & 0x2) != 0);
    2245 
    2246         if(r_read_count.read() == 1)  // creation of a new linked list
    2247         {
    2248           heap_entry.next         = m_heap.next_free_ptr();
    2249         }
    2250         else                         // head insertion in existing list
    2251         {
    2252           heap_entry.next         = r_read_ptr.read();
    2253         }
    2254         m_heap.write_free_entry(heap_entry);
    2255         m_heap.write_free_ptr(r_read_next_ptr.read());
    2256         if(r_read_last_free.read())  m_heap.set_full();
    2257 
    2258         r_read_fsm = READ_RSP;
    2259 
    2260 #if DEBUG_MEMC_READ
    2261 if(m_debug)
    2262 std::cout << "  <MEMC " << name() << " READ_HEAP_WRITE> Add an entry in the heap:"
    2263           << " owner_id = " << std::hex << heap_entry.owner.srcid
    2264           << " owner_ins = " << std::dec << heap_entry.owner.inst << std::endl;
    2265 #endif
    2266       }
    2267       else
    2268       {
    2269         std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_WRITE"
    2270                   << "Bad HEAP allocation" << std::endl;
    2271         exit(0);
    2272       }
    2273       break;
    2274     }
    2275     /////////////////////
    2276     case READ_HEAP_ERASE:
    2277     {
    2278       if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
    2279       {
    2280         HeapEntry next_entry = m_heap.read(r_read_ptr.read());
    2281         if(next_entry.next == r_read_ptr.read())
    2282         {
    2283           r_read_fsm = READ_HEAP_LAST;
    2284         }
    2285         else
    2286         {
    2287           r_read_ptr = next_entry.next;
    2288           r_read_fsm = READ_HEAP_ERASE;
    2289         }
    2290       }
    2291       else
    2292       {
    2293         std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_ERASE"
    2294                   << "Bad HEAP allocation" << std::endl;
    2295         exit(0);
    2296       }
    2297       break;
    2298     }
    2299 
    2300     ////////////////////
    2301     case READ_HEAP_LAST:
    2302     {
    2303       if(r_alloc_heap_fsm.read() == ALLOC_HEAP_READ)
    2304       {
    2305         HeapEntry last_entry;
    2306         last_entry.owner.srcid    = 0;
    2307         last_entry.owner.inst     = false;
    2308 
    2309         if(m_heap.is_full())
    2310         {
    2311           last_entry.next       = r_read_ptr.read();
    2312           m_heap.unset_full();
    2313         }
    2314         else
    2315         {
    2316           last_entry.next       = r_read_next_ptr.read();
    2317         }
    2318         m_heap.write(r_read_ptr.read(),last_entry);
    2319         r_read_fsm = READ_RSP;
    2320       }
    2321       else
    2322       {
    2323         std::cout << "VCI_MEM_CACHE ERROR " << name() << " READ_HEAP_LAST"
    2324                   << "Bad HEAP allocation" << std::endl;
    2325         exit(0);
    2326       }
    2327       break;
    2328     }
    2329     //////////////
    2330     case READ_RSP:    //  request the TGT_RSP FSM to return data
    2331     {
    2332         if(!r_read_to_tgt_rsp_req)
    2333         {
    2334             for(size_t i=0 ; i<m_words ; i++)  r_read_to_tgt_rsp_data[i] = r_read_data[i];
    2335             r_read_to_tgt_rsp_word   = m_x[(addr_t) m_cmd_read_addr_fifo.read()];
    2336             r_read_to_tgt_rsp_length = m_cmd_read_length_fifo.read();
    2337             r_read_to_tgt_rsp_srcid  = m_cmd_read_srcid_fifo.read();
    2338             r_read_to_tgt_rsp_trdid  = m_cmd_read_trdid_fifo.read();
    2339             r_read_to_tgt_rsp_pktid  = m_cmd_read_pktid_fifo.read();
    2340             r_read_to_tgt_rsp_ll_key = r_read_ll_key.read();
    2341             cmd_read_fifo_get        = true;
    2342             r_read_to_tgt_rsp_req    = true;
    2343             r_read_fsm               = READ_IDLE;
    2344 
    2345 #if DEBUG_MEMC_READ
    2346 if(m_debug)
    2347 std::cout << "  <MEMC " << name() << " READ_RSP> Request TGT_RSP FSM to return data:"
    2348           << " rsrcid = " << std::hex << m_cmd_read_srcid_fifo.read()
    2349           << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
    2350           << " / nwords = " << std::dec << m_cmd_read_length_fifo.read() << std::endl;
    2351 #endif
    2352         }
    2353         break;
    2354     }
    2355     ///////////////////
    2356     case READ_TRT_LOCK: // read miss : check the Transaction Table
    2357     {
    2358         if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
    2359         {
    2360             size_t      index     = 0;
    2361             addr_t      addr      = (addr_t) m_cmd_read_addr_fifo.read();
    2362             bool        hit_read  = m_trt.hit_read(m_nline[addr], index);
    2363             bool        hit_write = m_trt.hit_write(m_nline[addr]);
    2364             bool        wok       = not m_trt.full(index);
    2365 
    2366             if(hit_read or !wok or hit_write)    // line already requested or no space
    2367             {
    2368                 if(!wok)                    m_cpt_trt_full++;
    2369                 if(hit_read or hit_write)   m_cpt_trt_rb++;
    2370                 r_read_fsm = READ_IDLE;
    2371             }
    2372             else                  // missing line is requested to the XRAM
    2373             {
    2374                 m_cpt_read_miss++;
    2375                 r_read_trt_index = index;
    2376                 r_read_fsm       = READ_TRT_SET;
    2377             }
    2378 
    2379 #if DEBUG_MEMC_READ
    2380 if(m_debug)
    2381 std::cout << "  <MEMC " << name() << " READ_TRT_LOCK> Check TRT:"
    2382           << " hit_read = " << hit_read
    2383           << " / hit_write = " << hit_write
    2384           << " / full = " << !wok << std::endl;
    2385 #endif
    2386         }
    2387         break;
    2388     }
    2389     //////////////////
    2390     case READ_TRT_SET:      // register get transaction in TRT
    2391     {
    2392         if(r_alloc_trt_fsm.read() == ALLOC_TRT_READ)
    2393         {
    2394             m_trt.set( r_read_trt_index.read(),
    2395                        true,      // GET
    2396                        m_nline[(addr_t)(m_cmd_read_addr_fifo.read())],
    2397                        m_cmd_read_srcid_fifo.read(),
    2398                        m_cmd_read_trdid_fifo.read(),
    2399                        m_cmd_read_pktid_fifo.read(),
    2400                        true,      // proc read
    2401                        m_cmd_read_length_fifo.read(),
    2402                        m_x[(addr_t)(m_cmd_read_addr_fifo.read())],
    2403                        std::vector<be_t> (m_words,0),
    2404                        std::vector<data_t> (m_words,0),
    2405                        r_read_ll_key.read() );
    2406 #if DEBUG_MEMC_READ
    2407 if(m_debug)
    2408 std::cout << "  <MEMC " << name() << " READ_TRT_SET> Set a GET in TRT:"
    2409           << " address = " << std::hex << m_cmd_read_addr_fifo.read()
    2410           << " / srcid = " << std::hex << m_cmd_read_srcid_fifo.read() << std::endl;
    2411 #endif
    2412             r_read_fsm = READ_TRT_REQ;
    2413         }
    2414         break;
    2415     }
    2416 
    2417     //////////////////
    2418     case READ_TRT_REQ:   // consume the read request in FIFO and send it to IXR_CMD_FSM
    2419     {
    2420         if(not r_read_to_ixr_cmd_req)
    2421         {
    2422             cmd_read_fifo_get       = true;
    2423             r_read_to_ixr_cmd_req   = true;
    2424             r_read_to_ixr_cmd_index = r_read_trt_index.read();
    2425             r_read_fsm              = READ_IDLE;
    2426 
    2427 #if DEBUG_MEMC_READ
    2428 if(m_debug)
    2429 std::cout << "  <MEMC " << name() << " READ_TRT_REQ> Request GET transaction for address "
    2430           << std::hex << m_cmd_read_addr_fifo.read() << std::endl;
    2431 #endif
    2432         }
    2433         break;
    2434     }
    2435   } // end switch read_fsm
    2436 
    2437   ///////////////////////////////////////////////////////////////////////////////////
    2438   //    WRITE FSM
    2439   ///////////////////////////////////////////////////////////////////////////////////
    2440   // The WRITE FSM handles the write bursts and sc requests sent by the processors.
    2441   // All addresses in a burst must be in the same cache line.
    2442   // A complete write burst is consumed in the FIFO & copied to a local buffer.
    2443   // Then the FSM takes the lock protecting the cache directory, to check
    2444   // if the line is in the cache.
    2445   //
    2446   // - In case of HIT, the cache is updated.
    2447   //   If there is no other copy, an acknowledge response is immediately
    2448   //   returned to the writing processor.
    2449   //   If the data is cached by other processors, a coherence transaction must
    2450   //   be launched (sc requests always require a coherence transaction):
    2451   //   It is a multicast update if the line is not in counter mode: the processor
    2452   //   takes the lock protecting the Update Table (UPT) to register this transaction.
    2453   //   If the UPT is full, it releases the lock(s) and retry. Then, it sends
    2454   //   a multi-update request to all owners of the line (but the writer),
    2455   //   through the CC_SEND FSM. In case of coherence transaction, the WRITE FSM
    2456   //   does not respond to the writing processor, as this response will be sent by
    2457   //   the MULTI_ACK FSM when all update responses have been received.
    2458   //   It is a broadcast invalidate if the line is in counter mode: The line
    2459   //   should be erased in memory cache, and written in XRAM with a PUT transaction,
    2460   //   after registration in TRT.
    2461   //
    2462   // - In case of MISS, the WRITE FSM takes the lock protecting the transaction
    2463   //   table (TRT). If a read transaction to the XRAM for this line already exists,
    2464   //   it writes in the TRT (write buffer). Otherwise, if a TRT entry is free,
    2465   //   the WRITE FSM register a new transaction in TRT, and sends a GET request
    2466   //   to the XRAM. If the TRT is full, it releases the lock, and waits.
    2467   //   Finally, the WRITE FSM returns an aknowledge response to the writing processor.
    2468   /////////////////////////////////////////////////////////////////////////////////////
    2469 
    2470 //std::cout << std::endl << "write_fsm" << std::endl;
    2471 
    2472   switch(r_write_fsm.read())
    2473   {
    2474     ////////////////
    2475     case WRITE_IDLE:  // copy first word of a write burst in local buffer
    2476     {
    2477         if(m_cmd_write_addr_fifo.rok())
    2478         {
    2479             if((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC)
    2480             {
    2481                 m_cpt_sc++;
    2482             }
    2483             else
    2484             {
    2485                 m_cpt_write++;
    2486                 m_cpt_write_cells++;
    2487             }
    2488 
    2489             // consume a word in the FIFO & write it in the local buffer
    2490             cmd_write_fifo_get  = true;
    2491             size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
    2492 
    2493             r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
    2494             r_write_word_index  = index;
    2495             r_write_word_count  = 1;
    2496             r_write_data[index] = m_cmd_write_data_fifo.read();
    2497             r_write_srcid       = m_cmd_write_srcid_fifo.read();
    2498             r_write_trdid       = m_cmd_write_trdid_fifo.read();
    2499             r_write_pktid       = m_cmd_write_pktid_fifo.read();
    2500             r_write_pending_sc  = false;
    2501 
    2502             // initialize the be field for all words
    2503             for(size_t word=0 ; word<m_words ; word++)
    2504             {
    2505                 if(word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
    2506                 else              r_write_be[word] = 0x0;
    2507             }
    2508 
    2509             if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
    2510             {
    2511                 r_write_fsm = WRITE_DIR_REQ;
    2512             }
    2513             else
    2514             {
    2515                 r_write_fsm = WRITE_NEXT;
    2516             }
     2645            ////////////////
     2646            case WRITE_IDLE:  // copy first word of a write burst in local buffer
     2647                {
     2648                    if (m_cmd_write_addr_fifo.rok())
     2649                    {
     2650                        // consume a word in the FIFO & write it in the local buffer
     2651                        cmd_write_fifo_get  = true;
     2652                        size_t index        = m_x[(addr_t)(m_cmd_write_addr_fifo.read())];
     2653
     2654                        r_write_address     = (addr_t)(m_cmd_write_addr_fifo.read());
     2655                        r_write_word_index  = index;
     2656                        r_write_word_count  = 1;
     2657                        r_write_data[index] = m_cmd_write_data_fifo.read();
     2658                        r_write_srcid       = m_cmd_write_srcid_fifo.read();
     2659                        r_write_trdid       = m_cmd_write_trdid_fifo.read();
     2660                        r_write_pktid       = m_cmd_write_pktid_fifo.read();
     2661                        r_write_pending_sc  = false;
     2662
     2663                        // initialize the be field for all words
     2664                        for(size_t word=0 ; word<m_words ; word++)
     2665                        {
     2666                            if (word == index) r_write_be[word] = m_cmd_write_be_fifo.read();
     2667                            else              r_write_be[word] = 0x0;
     2668                        }
     2669
     2670                        if (m_cmd_write_eop_fifo.read() or ((m_cmd_write_pktid_fifo.read() & 0x7) == TYPE_SC))
     2671                        {
     2672                            r_write_fsm = WRITE_DIR_REQ;
     2673                        }
     2674                        else
     2675                        {
     2676                            r_write_fsm = WRITE_NEXT;
     2677                        }
    25172678
    25182679#if DEBUG_MEMC_WRITE
    2519 if(m_debug)
    2520 std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
    2521           << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
    2522           << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
    2523           << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
    2524 #endif
    2525         }
    2526         break;
    2527     }
    2528     ////////////////
    2529     case WRITE_NEXT:  // copy next word of a write burst in local buffer
    2530     {
    2531         if(m_cmd_write_addr_fifo.rok())
    2532         {
     2680                        if (m_debug)
     2681                            std::cout << "  <MEMC " << name() << " WRITE_IDLE> Write request "
     2682                                << " srcid = " << std::hex << m_cmd_write_srcid_fifo.read()
     2683                                << " / address = " << std::hex << m_cmd_write_addr_fifo.read()
     2684                                << " / data = " << m_cmd_write_data_fifo.read() << std::endl;
     2685#endif
     2686                    }
     2687                    break;
     2688                }
     2689                ////////////////
     2690            case WRITE_NEXT:  // copy next word of a write burst in local buffer
     2691                {
     2692                    if (m_cmd_write_addr_fifo.rok())
     2693                    {
    25332694
    25342695#if DEBUG_MEMC_WRITE
    2535 if(m_debug)
    2536 std::cout << "  <MEMC " << name()
    2537           << " WRITE_NEXT> Write another word in local buffer"
    2538           << std::endl;
    2539 #endif
    2540             m_cpt_write_cells++;
    2541 
    2542             // check that the next word is in the same cache line
    2543             assert( (m_nline[(addr_t)(r_write_address.read())] ==
    2544                      m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]) and
    2545             "MEMC ERROR in WRITE_NEXT state: Illegal write burst");
    2546 
    2547             // consume a word in the FIFO & write it in the local buffer
    2548             cmd_write_fifo_get  = true;
    2549             size_t index        = r_write_word_index.read() + r_write_word_count.read();
    2550 
    2551             r_write_be[index]   = m_cmd_write_be_fifo.read();
    2552             r_write_data[index] = m_cmd_write_data_fifo.read();
    2553             r_write_word_count  = r_write_word_count.read() + 1;
    2554 
    2555             if(m_cmd_write_eop_fifo.read()) r_write_fsm = WRITE_DIR_REQ;
    2556         }
    2557         break;
    2558     }
    2559     ///////////////////
    2560     case WRITE_DIR_REQ:    // Get the lock to the directory
    2561                            // and access the llsc_global_table
    2562     {
    2563         if( r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
    2564         {
    2565             if(((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
    2566             {
    2567                 // We enter here if it is a new SC command
    2568                 // If r_write_pending_sc is set the SC is not new and has already been tested
    2569 
    2570                 if(not m_cmd_write_addr_fifo.rok()) break;
    2571 
    2572                 assert( m_cmd_write_eop_fifo.read() and
    2573                 "MEMC ERROR in WRITE_DIR_REQ state: invalid packet format for SC command");
    2574 
    2575                 size_t index    = r_write_word_index.read();
    2576                 bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
    2577                                             r_write_data[index].read());
    2578 
    2579                 // consume a word in the FIFO & write it in the local buffer
    2580                 cmd_write_fifo_get  = true;
    2581                 r_write_data[index] = m_cmd_write_data_fifo.read();
    2582                 r_write_sc_fail     = not sc_success;
    2583                 r_write_pending_sc  = true;
    2584 
    2585                 if(not sc_success) r_write_fsm = WRITE_RSP;
    2586                 else               r_write_fsm = WRITE_DIR_LOCK;
    2587             }
    2588             else
    2589             {
    2590                 // We enter here if it is a SW command or an already tested SC command
    2591 
    2592                 m_llsc_table.sw( m_nline[(addr_t)r_write_address.read()],
    2593                                  r_write_word_index.read(),
    2594                                  r_write_word_index.read() + r_write_word_count.read() );
    2595 
    2596                 r_write_fsm = WRITE_DIR_LOCK;
    2597             }
     2696                        if (m_debug)
     2697                            std::cout << "  <MEMC " << name()
     2698                                << " WRITE_NEXT> Write another word in local buffer"
     2699                                << std::endl;
     2700#endif
     2701
     2702                        // check that the next word is in the same cache line
     2703                        assert((m_nline[(addr_t)(r_write_address.read())] ==
     2704                                    m_nline[(addr_t)(m_cmd_write_addr_fifo.read())]) and
     2705                                "MEMC ERROR in WRITE_NEXT state: Illegal write burst");
     2706
     2707                        // consume a word in the FIFO & write it in the local buffer
     2708                        cmd_write_fifo_get  = true;
     2709                        size_t index        = r_write_word_index.read() + r_write_word_count.read();
     2710
     2711                        r_write_be[index]   = m_cmd_write_be_fifo.read();
     2712                        r_write_data[index] = m_cmd_write_data_fifo.read();
     2713                        r_write_word_count  = r_write_word_count.read() + 1;
     2714
     2715                        if (m_cmd_write_eop_fifo.read()) r_write_fsm = WRITE_DIR_REQ;
     2716                    }
     2717                    break;
     2718                }
     2719                ///////////////////
     2720            case WRITE_DIR_REQ:    // Get the lock to the directory
     2721                // and access the llsc_global_table
     2722                {
     2723                    if (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE )
     2724                    {
     2725                        if (((r_write_pktid.read() & 0x7) == TYPE_SC) and not r_write_pending_sc.read())
     2726                        {
     2727                            // We enter here if it is a new SC command
     2728                            // If r_write_pending_sc is set the SC is not new and has already been tested
     2729
     2730                            if (not m_cmd_write_addr_fifo.rok()) break;
     2731
     2732                            assert( m_cmd_write_eop_fifo.read() and
     2733                                    "MEMC ERROR in WRITE_DIR_REQ state: invalid packet format for SC command");
     2734
     2735                            size_t index    = r_write_word_index.read();
     2736                            bool sc_success = m_llsc_table.sc(r_write_address.read()    ,
     2737                                    r_write_data[index].read());
     2738
     2739                            // consume a word in the FIFO & write it in the local buffer
     2740                            cmd_write_fifo_get  = true;
     2741                            r_write_data[index] = m_cmd_write_data_fifo.read();
     2742                            r_write_sc_fail     = not sc_success;
     2743                            r_write_pending_sc  = true;
     2744
     2745                            if (not sc_success) r_write_fsm = WRITE_RSP;
     2746                            else               r_write_fsm = WRITE_DIR_LOCK;
     2747                        }
     2748                        else
     2749                        {
     2750                            // We enter here if it is a SW command or an already tested SC command
     2751
     2752                            m_llsc_table.sw( m_nline[(addr_t)r_write_address.read()],
     2753                                    r_write_word_index.read(),
     2754                                    r_write_word_index.read() + r_write_word_count.read());
     2755
     2756                            r_write_fsm = WRITE_DIR_LOCK;
     2757                        }
    25982758
    25992759#if DEBUG_MEMC_WRITE
    2600 if(m_debug)
    2601 std::cout << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
    2602           << std::endl;
    2603 #endif
    2604         }
    2605         break;
    2606     }
    2607     ////////////////////
    2608     case WRITE_DIR_LOCK:     // access directory to check hit/miss
    2609     {
    2610         assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE) and
    2611         "MEMC ERROR in ALLOC_DIR_LOCK state: Bad DIR allocation");
    2612 
    2613         size_t  way = 0;
    2614         DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
    2615 
    2616         if(entry.valid)    // hit
    2617         {
    2618             // copy directory entry in local buffer in case of hit
    2619             r_write_is_cnt     = entry.is_cnt;
    2620             r_write_lock       = entry.lock;
    2621             r_write_tag        = entry.tag;
    2622             r_write_copy       = entry.owner.srcid;
    2623             r_write_copy_inst  = entry.owner.inst;
    2624             r_write_count      = entry.count;
    2625             r_write_ptr        = entry.ptr;
    2626             r_write_way        = way;
    2627 
    2628             if(entry.is_cnt and entry.count) r_write_fsm = WRITE_BC_DIR_READ;
    2629             else                             r_write_fsm = WRITE_DIR_HIT;
    2630         }
    2631         else  // miss
    2632         {
    2633             r_write_fsm = WRITE_MISS_TRT_LOCK;
    2634         }
     2760                        if (m_debug)
     2761                            std::cout << "  <MEMC " << name() << " WRITE_DIR_REQ> Requesting DIR lock "
     2762                                << std::endl;
     2763#endif
     2764                    }
     2765                    break;
     2766                }
     2767                ////////////////////
     2768            case WRITE_DIR_LOCK:     // access directory to check hit/miss
     2769                {
     2770                    assert( (r_alloc_dir_fsm.read() == ALLOC_DIR_WRITE) and
     2771                            "MEMC ERROR in ALLOC_DIR_LOCK state: Bad DIR allocation");
     2772
     2773                    size_t  way = 0;
     2774                    DirectoryEntry entry(m_cache_directory.read(r_write_address.read(), way));
     2775
     2776                    if (entry.valid)    // hit
     2777                    {
     2778    &nb