Index: branches/reconfiguration/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp
===================================================================
--- branches/reconfiguration/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 985)
+++ branches/reconfiguration/modules/vci_mem_cache/caba/source/src/vci_mem_cache.cpp	(revision 1011)
@@ -172,5 +172,6 @@
         "READ_TRT_LOCK",
         "READ_TRT_SET",
-        "READ_TRT_REQ"
+        "READ_TRT_REQ",
+        "READ_IVT_LOCK",
     };
     const char *write_fsm_str[] =
@@ -317,5 +318,6 @@
         "ALLOC_IVT_CLEANUP",
         "ALLOC_IVT_CAS",
-        "ALLOC_IVT_CONFIG"
+        "ALLOC_IVT_CONFIG",
+        "ALLOC_IVT_READ",
     };
     const char *alloc_heap_fsm_str[] =
@@ -1017,4 +1019,20 @@
 
     //////////////////////////////////
+    tmpl(void)::scratchpad_reset()
+    //////////////////////////////////
+    {
+        const uint32_t xy = (m_x_self << m_y_width) | m_y_self;
+        const uint32_t offset = m_z.getUse() - m_x_width - m_y_width;
+        for (size_t set = 0; set < m_sets; ++set) {
+            for (size_t way = 0; way < m_ways; ++way) {
+                DirectoryEntry entry;
+                entry.valid = true;
+                entry.tag = (xy << offset) | way;
+                m_cache_directory.write(set, way, entry);
+            }
+        }
+    }
+
+    //////////////////////////////////
     tmpl(void)::transition()
     //////////////////////////////////
@@ -1080,5 +1098,6 @@
             m_cmd_cas_eop_fifo.init()   ;
 
-            r_config_cmd  = MEMC_CMD_NOP;
+            r_config_cmd = MEMC_CMD_NOP;
+            r_config_scratchpad = true;
 
             m_config_to_cc_send_inst_fifo.init();
@@ -1516,4 +1535,27 @@
                             r_config_trdid = p_vci_tgt.trdid.read();
                             r_config_pktid = p_vci_tgt.pktid.read();
+                        }
+                        else if ((p_vci_tgt.cmd.read() == vci_param_int::CMD_WRITE)
+                                and (regr == MEMC_SCRATCHPAD))                        // enable/disable
+                                                                                      // scratchpad mode
+                        {
+                            need_rsp = true;
+                            error    = 0;
+                            r_config_scratchpad = wdata > 0 ? true : false;
+
+                            // prepare delayed response from CONFIG FSM
+                            r_config_srcid = p_vci_tgt.srcid.read();
+                            r_config_trdid = p_vci_tgt.trdid.read();
+                            r_config_pktid = p_vci_tgt.pktid.read();
+
+#if DEBUG_MEMC_TGT_CMD
+                            if (m_debug)
+                            {
+                                std::cout << "  <MEMC " << name() << " TGT_CMD_CONFIG> ";
+                                if (wdata) std::cout << "ENABLE the memory cache scratchpad mode";
+                                else       std::cout << "DISABLE the memory cache scratchpad mode";
+                                std::cout << std::endl;
+                            }
+#endif
                         }
                         else
@@ -2056,4 +2098,5 @@
         // - Write MEMC_BUF_LENGTH : set buffer length (bytes)
         // - Write MEMC_CMD_TYPE   : launch the actual operation
+        // - Write MEMC_SCRATCHPAD : enable/disable the scratchpad mode
         ////////////////////////////////////////////////////////////////////////////////////
 
@@ -2687,6 +2730,12 @@
                 if (entry.valid)    // hit
                 {
+                    // check the IVT for pending invalidation when scratchpad mode and
+                    // line in counter mode.
+                    if (r_config_scratchpad.read() and entry.is_cnt)
+                    {
+                        r_read_fsm = READ_IVT_LOCK;
+                    }
                     // test if we need to register a new copy in the heap
-                    if (entry.is_cnt or (entry.count == 0) or !cached_read)
+                    else if (entry.is_cnt or (entry.count == 0) or !cached_read)
                     {
                         r_read_fsm = READ_DIR_HIT;
@@ -2699,4 +2748,23 @@
                 else      // miss
                 {
+                    // miss in scratchpad mode: this shouldn't happen. Drop the request
+                    // (black-hole behavior).
+                    if (r_config_scratchpad.read())
+                    {
+#if DEBUG_MEMC_READ
+                        if (m_debug)
+                        {
+                            std::cout << " WARNING: <MEMC " << name()
+                                      << " READ_DIR_LOCK> READ MISS in scratchpad mode: "
+                                      << " address = " << std::hex << m_cmd_read_addr_fifo.read()
+                                      << std::dec << std::endl;
+                        }
+#endif
+
+                        cmd_read_fifo_get = true;
+                        r_read_fsm = READ_IDLE;
+                        break;
+                    }
+
                     r_read_fsm = READ_TRT_LOCK;
                 }
@@ -3119,4 +3187,36 @@
 #endif
                 }
+                break;
+            }
+            ///////////////////
+            case READ_IVT_LOCK:
+            {
+                if (r_alloc_ivt_fsm.read() != ALLOC_IVT_READ) break;
+
+                assert((r_alloc_dir_fsm.read() == ALLOC_DIR_READ) and
+                       "MEMC ERROR in READ_IVT_LOCK state: Bad DIR allocation");
+
+                size_t index = 0;
+                size_t nline = m_nline[m_cmd_read_addr_fifo.read()];
+                if (m_ivt.search_inval(nline, index))
+                {
+                    // There is a pending invalidation on the requested address.
+                    // Return to IDLE to release all locks and retry.
+                    r_read_fsm = READ_IDLE;
+
+#if DEBUG_MEMC_READ
+                    if (m_debug)
+                    {
+                        std::cout << "  <MEMC " << name() << " READ_IVT_LOCK>"
+                                  << " Got acces to IVT, and there is a pending invalidation"
+                                  << " / address = " << std::hex << m_cmd_read_addr_fifo.read()
+                                  << " / index = " << std::dec << index << std::endl;
+                    }
+#endif
+                    break;
+                }
+
+                // no pending inval
+                r_read_fsm = READ_DIR_HIT;
                 break;
             }
@@ -3326,9 +3426,52 @@
                     r_write_way       = way;
 
-                    if (entry.is_cnt and entry.count) r_write_fsm = WRITE_BC_DIR_READ;
-                    else                              r_write_fsm = WRITE_DIR_HIT;
+                    // in scratchpad mode, when a line is in counter mode, a broadcast is
+                    // triggered but the line is kept in the directory.
+                    if (entry.is_cnt and (entry.count > 0))
+                    {
+                        if (r_config_scratchpad.read())
+                        {
+                            r_write_fsm = WRITE_BC_IVT_LOCK;
+
+#if DEBUG_MEMC_WRITE
+                            if (m_debug)
+                            {
+                                std::cout << " <MEMC " << name()
+                                          << " WRITE_DIR_LOCK> BROADCAST in scratchpad mode: "
+                                          << " address = " << std::hex << r_write_address.read()
+                                          << std::dec << std::endl;
+                            }
+#endif
+                        }
+                        else
+                        {
+                            r_write_fsm = WRITE_BC_DIR_READ;
+                        }
+                    }
+                    else
+                    {
+                        r_write_fsm = WRITE_DIR_HIT;
+                    }
                 }
                 else  // miss
                 {
+                    // miss in scratchpad mode: this shouldn't happen. Drop the request
+                    // (black-hole behavior).
+                    if (r_config_scratchpad.read())
+                    {
+#if DEBUG_MEMC_WRITE
+                        if (m_debug)
+                        {
+                            std::cout << " WARNING: <MEMC " << name()
+                                      << " WRITE_DIR_LOCK> WRITE MISS in scratchpad mode: "
+                                      << " address = " << std::hex << r_write_address.read()
+                                      << std::dec << std::endl;
+                        }
+#endif
+
+                        r_write_fsm = WRITE_IDLE;
+                        break;
+                    }
+
                     r_write_fsm = WRITE_MISS_TRT_LOCK;
                 }
@@ -4025,5 +4168,6 @@
                         "MEMC ERROR in WRITE_BC_IVT_LOCK state: Bad DIR allocation");
 
-                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE) and
+                assert((r_config_scratchpad.read() or
+                       (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)) and
                         "MEMC ERROR in WRITE_BC_IVT_LOCK state: Bad TRT allocation");
 
@@ -4069,5 +4213,6 @@
                         "MEMC ERROR in WRITE_BC_DIR_INVAL state: Bad DIR allocation");
 
-                assert((r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE) and
+                assert((r_config_scratchpad.read() or
+                       (r_alloc_trt_fsm.read() == ALLOC_TRT_WRITE)) and
                         "MEMC ERROR in WRITE_BC_DIR_INVAL state: Bad TRT allocation");
 
@@ -4075,36 +4220,73 @@
                         "MEMC ERROR in WRITE_BC_DIR_INVAL state: Bad IVT allocation");
 
-                // register PUT request in TRT
-                std::vector<data_t> data_vector;
-                data_vector.clear();
-                for (size_t i = 0; i < m_words; i++)
-                {
-                    data_vector.push_back(r_write_data[i].read());
-                }
-                m_trt.set(r_write_trt_index.read(),
-                        false,             // PUT request
-                        m_nline[(addr_t) (r_write_address.read())],
-                        0,                 // unused
-                        0,                 // unused
-                        0,                 // unused
-                        false,             // not a processor read
-                        0,                 // unused
-                        0,                 // unused
-                        std::vector<be_t> (m_words, 0),
-                        data_vector);
-
-                // invalidate directory entry
+                size_t set = m_y[(addr_t) (r_write_address.read())];
+                size_t way = r_write_way.read();
                 DirectoryEntry entry;
-                entry.valid       = false;
-                entry.dirty       = false;
-                entry.tag         = 0;
-                entry.is_cnt      = false;
-                entry.lock        = false;
-                entry.owner.srcid = 0;
-                entry.owner.inst  = false;
-                entry.ptr         = 0;
-                entry.count       = 0;
-                size_t set        = m_y[(addr_t) (r_write_address.read())];
-                size_t way        = r_write_way.read();
+                if (not r_config_scratchpad.read())
+                {
+                    // register PUT request in TRT
+                    std::vector<data_t> data_vector;
+                    data_vector.clear();
+                    for (size_t i = 0; i < m_words; i++)
+                    {
+                        data_vector.push_back(r_write_data[i].read());
+                    }
+                    m_trt.set(r_write_trt_index.read(),
+                              false,             // PUT request
+                              m_nline[(addr_t) (r_write_address.read())],
+                              0,                 // unused
+                              0,                 // unused
+                              0,                 // unused
+                              false,             // not a processor read
+                              0,                 // unused
+                              0,                 // unused
+                              std::vector<be_t> (m_words, 0),
+                              data_vector);
+
+                    // invalidate directory entry
+                    entry.valid       = false;
+                    entry.dirty       = false;
+                    entry.tag         = 0;
+                    entry.is_cnt      = false;
+                    entry.lock        = false;
+                    entry.owner.srcid = 0;
+                    entry.owner.inst  = false;
+                    entry.ptr         = 0;
+                    entry.count       = 0;
+
+#if DEBUG_MEMC_WRITE
+                    if (m_debug)
+                    {
+                        std::cout << "  <MEMC " << name()
+                                  << " WRITE_BC_DIR_INVAL> Inval DIR and register in TRT:"
+                                  << " address = " << std::hex << r_write_address.read()
+                                  << std::dec << std::endl;
+                    }
+#endif
+
+                }
+                else
+                {
+                    // update the data when in scratchpad mode
+                    for (size_t word = 0; word < m_words; word++)
+                    {
+                        m_cache_data.write(way,
+                                           set,
+                                           word,
+                                           r_write_data[word].read(),
+                                           r_write_be[word].read());
+                    }
+
+                    // keep the directory entry, but reset the number of copies
+                    entry.valid       = true;
+                    entry.dirty       = true;
+                    entry.tag         = r_write_tag.read();
+                    entry.is_cnt      = r_write_is_cnt.read();
+                    entry.lock        = r_write_lock.read();
+                    entry.owner.srcid = 0;
+                    entry.owner.inst  = false;
+                    entry.ptr         = 0;
+                    entry.count       = 0;
+                }
 
                 m_cache_directory.write(set, way, entry);
@@ -4115,11 +4297,4 @@
                 }
 
-#if DEBUG_MEMC_WRITE
-                if (m_debug)
-                {
-                    std::cout << "  <MEMC " << name() << " WRITE_BC_DIR_INVAL> Inval DIR and register in TRT:"
-                        << " address = " << std::hex << r_write_address.read() << std::endl;
-                }
-#endif
                 r_write_fsm = WRITE_BC_CC_SEND;
                 break;
@@ -4143,5 +4318,13 @@
                         r_write_to_cc_send_data[i] = 0;
                     }
-                    r_write_fsm = WRITE_BC_XRAM_REQ;
+
+                    if (r_config_scratchpad.read())
+                    {
+                        r_write_fsm = WRITE_IDLE;
+                    }
+                    else
+                    {
+                        r_write_fsm = WRITE_BC_XRAM_REQ;
+                    }
 
 #if DEBUG_MEMC_WRITE
@@ -5406,4 +5589,5 @@
                 addr_t cleanup_address = r_cleanup_nline.read() * m_words * 4;
                 DirectoryEntry entry   = m_cache_directory.read(cleanup_address , way);
+                r_cleanup_valid        = entry.valid;
                 r_cleanup_is_cnt       = entry.is_cnt;
                 r_cleanup_dirty        = entry.dirty;
@@ -5418,8 +5602,14 @@
                 if (entry.valid) // hit : the copy must be cleared
                 {
-                    assert((entry.count > 0) and
+                    assert((r_config_scratchpad.read() or (entry.count > 0)) and
                             "MEMC ERROR in CLEANUP_DIR_LOCK state, CLEANUP on valid entry with no copies");
 
-                    if ((entry.count == 1) or (entry.is_cnt)) // no access to the heap
+                    // when in scratchpad mode, if a line is in counter mode, check first
+                    // if there is a pending inval
+                    if (r_config_scratchpad.read() and entry.is_cnt)
+                    {
+                        r_cleanup_fsm = CLEANUP_IVT_LOCK;
+                    }
+                    else if ((entry.count == 1) or (entry.is_cnt)) // no access to the heap
                     {
                         r_cleanup_fsm = CLEANUP_DIR_WRITE;
@@ -5753,4 +5943,21 @@
                 if (not match_inval) // no pending inval in IVT
                 {
+                    if (r_config_scratchpad.read() and r_cleanup_valid.read())
+                    {
+#if DEBUG_MEMC_CLEANUP
+                        if (m_debug)
+                        {
+                            std::cout << "  <MEMC " << name() << " CLEANUP_IVT_LOCK>"
+                                      << " Cleanup in scratchpad mode with no corresponding IVT entry"
+                                      << " but valid in directory"
+                                      << " / address = " << std::hex << (r_cleanup_nline.read() * 4 * m_words)
+                                      << std::dec << std::endl;
+                        }
+#endif
+
+                        r_cleanup_fsm = CLEANUP_DIR_WRITE;
+                        break;
+                    }
+
                     r_cleanup_fsm = CLEANUP_SEND_CLACK;
 
@@ -8046,5 +8253,5 @@
         // The ALLOC_IVT FSM allocates the access to the Invalidate Table (IVT),
         // with a round robin priority between five FSMs, with the following order:
-        //  WRITE -> XRAM_RSP -> CLEANUP -> CAS -> CONFIG
+        //  WRITE -> XRAM_RSP -> CLEANUP -> CAS -> CONFIG -> READ
         // - The WRITE FSM initiates broadcast invalidate transactions and sets a new entry
         //   in IVT.
@@ -8054,4 +8261,5 @@
         // - The CONFIG FSM does the same thing as the XRAM_RSP FSM
         // - The CLEANUP FSM complete those trasactions and erase the IVT entry.
+        // - The READ FSM checks for pending invalidations when in scratchpad mode.
         // The resource is always allocated.
         /////////////////////////////////////////////////////////////////////////////////////
@@ -8076,4 +8284,8 @@
                     else if (r_config_fsm.read() == CONFIG_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+                    else if (r_read_fsm.read() == READ_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
                 }
                 break;
@@ -8091,4 +8303,7 @@
                     else if (r_config_fsm.read() == CONFIG_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
+
+                    else if (r_read_fsm.read() == READ_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_READ;
 
                     else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
@@ -8108,4 +8323,7 @@
                         r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
 
+                    else if (r_read_fsm.read() == READ_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
                     else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
@@ -8123,4 +8341,7 @@
                         r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
 
+                    else if (r_read_fsm.read() == READ_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
                     else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
@@ -8138,4 +8359,24 @@
                 if (r_config_fsm.read() != CONFIG_IVT_LOCK)
                 {
+                    if (r_read_fsm.read() == READ_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_READ;
+
+                    else if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
+
+                    else if (r_xram_rsp_fsm.read() == XRAM_RSP_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_XRAM_RSP;
+
+                    else if (r_cleanup_fsm.read() == CLEANUP_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_CLEANUP;
+
+                    else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+                }
+                break;
+
+            case ALLOC_IVT_READ:           // allocated to READ FSM
+                if (r_read_fsm.read() != READ_IVT_LOCK)
+                {
                     if (r_write_fsm.read() == WRITE_BC_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_WRITE;
@@ -8149,4 +8390,7 @@
                     else if (r_cas_fsm.read() == CAS_BC_IVT_LOCK)
                         r_alloc_ivt_fsm = ALLOC_IVT_CAS;
+
+                    else if (r_config_fsm.read() == CONFIG_IVT_LOCK)
+                        r_alloc_ivt_fsm = ALLOC_IVT_CONFIG;
                 }
                 break;
@@ -8175,5 +8419,5 @@
                 if (r_alloc_dir_reset_cpt.read() == (m_sets - 1))
                 {
-                    m_cache_directory.init();
+                    scratchpad_reset();
                     r_alloc_dir_fsm = ALLOC_DIR_READ;
                 }
@@ -8209,9 +8453,10 @@
                 if (((r_read_fsm.read() != READ_DIR_REQ) and
                      (r_read_fsm.read() != READ_DIR_LOCK) and
+                     (r_read_fsm.read() != READ_IVT_LOCK) and
                      (r_read_fsm.read() != READ_TRT_LOCK) and
                      (r_read_fsm.read() != READ_HEAP_REQ))
                     or
                      ((r_read_fsm.read() == READ_TRT_LOCK) and
-                     (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)))
+                      (r_alloc_trt_fsm.read() == ALLOC_TRT_READ)))
                 {
                     if (r_write_fsm.read() == WRITE_DIR_REQ)
@@ -8305,8 +8550,12 @@
                 ///////////////////////
             case ALLOC_DIR_CLEANUP:    // allocated to CLEANUP FSM
-                if ((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) and
+                if (((r_cleanup_fsm.read() != CLEANUP_DIR_REQ) and
                         (r_cleanup_fsm.read() != CLEANUP_DIR_LOCK) and
+                        (r_cleanup_fsm.read() != CLEANUP_IVT_LOCK) and
                         (r_cleanup_fsm.read() != CLEANUP_HEAP_REQ) and
                         (r_cleanup_fsm.read() != CLEANUP_HEAP_LOCK))
+                    or
+                        ((r_cleanup_fsm.read() == CLEANUP_IVT_LOCK) and
+                         (not r_config_scratchpad.read())))
                 {
                     if (r_xram_rsp_fsm.read() == XRAM_RSP_DIR_LOCK)
