source: trunk/modules/vci_cc_xcache_wrapper_v4/caba/source/src/vci_cc_xcache_wrapper_v4.cpp @ 161

Last change on this file since 161 was 161, checked in by alain, 13 years ago

bug fix (line 2385)

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Author Date Id Rev URL Revision"
  • Property svn:mime-type set to text/plain
File size: 124.0 KB
RevLine 
[2]1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *         Alain Greiner <alain.greiner@lip6.fr>, 2008
25 *
26 * Maintainers: alain eric.guthmuller@polytechnique.edu nipo
27 */
28
29/////////////////////////////////////////////////////////////////////////////
30// History
31// - 25/04/2008
32//   The existing vci_xcache component has been extended to include
33//   a VCI target port to support a directory based coherence protocol.
34//   Two types of packets can be send by the L2 cache to the L1 cache
35//   * INVALIDATE packets : length = 1
36//   * UPDATE packets : length = n + 2   
37//   The CLEANUP packets are sent by the L1 cache to the L2 cache,
38//   to signal a replaced cache line.
39// - 12/08/2008
40//   The vci_cc_xcache_wrapper component instanciates directly the processsor
41//   iss, in order to supress the processor/cache interface.
42//   According to the VCI advanced specification, this component uses one
43//   word VCI CMD packets for MISS transactions, and accept one word VCI RSP
44//   packets for Write burst  transactions.
45//   The write buffer has been modified to use the WriteBuffer object.
46//   A VCI write burst is constructed when two conditions are satisfied :
47//   The processor make strictly successive write requests, and they are
48//   in the same cache line. The write buffer performs re-ordering, to
49//   respect the contiguous addresses VCI constraint. In case of several
50//   WRITE_WORD requests in the same word, only the last request is conserved.
51//   In case of several WRITE_HALF or WRITE_WORD requests in the same word,
52//   the requests are merged in the same word. In case of uncached write
53//   requests, each request is transmited as a single VCI transaction.
54//   Both the data & instruction caches can be flushed in one single cycle.
55///////////////////////////////////////////////////////////////////////////////
56
[147]57#include <cassert>
[134]58#include <iomanip>
[2]59#include "arithmetics.h"
60#include "../include/vci_cc_xcache_wrapper_v4.h"
61
[134]62#if CC_XCACHE_WRAPPER_DEBUG
[147]63# define PRINTF(msg...) do { if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN) printf(msg); } while (0);
[134]64#else
65# define PRINTF(msg...)
66#endif
[2]67
[147]68# define ASSERT(cond,msg) assert ((cond) and msg);
[134]69
[147]70#if CC_XCACHE_WRAPPER_FIFO_RSP
71# define CACHE_MISS_BUF_ALLOC
72# define CACHE_MISS_BUF_DEALLOC
73# define CACHE_MISS_BUF_RESET(c)        while (r_##c##cache_miss_buf.size()>0) {r_##c##cache_miss_buf.pop();}
74# define CACHE_MISS_BUF_REQ_INIT(c)
75# define CACHE_MISS_BUF_RSP_VAL(c,n)    (r_##c##cache_miss_buf.size()>0)
76# define CACHE_MISS_BUF_RSP_ACK(c)      (r_##c##cache_miss_buf.size()<2)
77# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf.front()
78# define CACHE_MISS_BUF_RSP_POP(c)      do { r_##c##cache_miss_buf.pop();} while (0)
79# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do { r_##c##cache_miss_buf.push(d);} while (0)
80# define CACHE_MISS_BUF_RSP_PRINT(c)    do { PRINTF("    * cache_miss_buf - size : %d\n",r_##c##cache_miss_buf.size());} while (0)
[134]81#else
[147]82# define CACHE_MISS_BUF_ALLOC           do { \
83                                        r_icache_miss_val = new bool  [m_icache_words]; \
84                                        r_icache_miss_buf = new data_t[m_icache_words]; \
85                                        r_dcache_miss_val = new bool  [m_dcache_words]; \
86                                        r_dcache_miss_buf = new data_t[m_dcache_words]; \
87                                        } while (0)
88# define CACHE_MISS_BUF_DEALLOC         do { \
89                                        delete [] r_icache_miss_val; \
90                                        delete [] r_icache_miss_buf; \
91                                        delete [] r_dcache_miss_val; \
92                                        delete [] r_dcache_miss_buf; \
93                                        } while (0)
94# define CACHE_MISS_BUF_RESET(c)
95# define CACHE_MISS_BUF_REQ_INIT(c)     do {for (uint32_t i=0; i<m_##c##cache_words;++i) r_##c##cache_miss_val[i] = false;} while (0)
96# define CACHE_MISS_BUF_RSP_VAL(c,n)    r_##c##cache_miss_val[n]
97# define CACHE_MISS_BUF_RSP_ACK(c)      true
98# define CACHE_MISS_BUF_RSP_DATA(c,n)   r_##c##cache_miss_buf[n]
99# define CACHE_MISS_BUF_RSP_POP(c)
100# define CACHE_MISS_BUF_RSP_PUSH(c,n,d) do {r_##c##cache_miss_val[n] = true; r_##c##cache_miss_buf[n] = d;} while (0)
101# define CACHE_MISS_BUF_RSP_PRINT(c)    do {for (uint32_t i=0; i<m_##c##cache_words;++i) PRINTF("%d %x |",r_##c##cache_miss_val[i],r_##c##cache_miss_buf[i]); PRINTF("\n");} while (0)
[134]102#endif
103
[2]104namespace soclib {
105namespace caba {
[134]106    namespace {
[2]107
108        const char *dcache_fsm_state_str[] = {
109            "DCACHE_IDLE",
110            "DCACHE_WRITE_UPDT",
[147]111#if CC_XCACHE_WRAPPER_SELECT_VICTIM
[134]112            "DCACHE_MISS_VICTIM",
[147]113#endif
[2]114            "DCACHE_MISS_WAIT",
115            "DCACHE_MISS_UPDT",
116            "DCACHE_UNC_WAIT",
117            "DCACHE_SC_WAIT",
118            "DCACHE_INVAL",
[134]119            "DCACHE_SYNC",
[2]120            "DCACHE_ERROR",
121            "DCACHE_CC_CHECK",
122            "DCACHE_CC_INVAL",
123            "DCACHE_CC_UPDT",
124            "DCACHE_CC_CLEANUP",
125        };
126        const char *icache_fsm_state_str[] = {
127            "ICACHE_IDLE",
[147]128#if CC_XCACHE_WRAPPER_SELECT_VICTIM
[134]129            "ICACHE_MISS_VICTIM",
[147]130#endif
[2]131            "ICACHE_MISS_WAIT",
132            "ICACHE_MISS_UPDT",
133            "ICACHE_UNC_WAIT",
134            "ICACHE_ERROR",
135            "ICACHE_CC_CLEANUP",
136            "ICACHE_CC_CHECK",
137            "ICACHE_CC_INVAL",
138            "ICACHE_CC_UPDT",
139        };
140        const char *cmd_fsm_state_str[] = {
141            "CMD_IDLE",
142            "CMD_INS_MISS",
143            "CMD_INS_UNC",
144            "CMD_DATA_MISS",
145            "CMD_DATA_UNC",
146            "CMD_DATA_WRITE",
147            "CMD_DATA_SC",
148        };
149        const char *rsp_fsm_state_str[] = {
150            "RSP_IDLE",
151            "RSP_INS_MISS",
152            "RSP_INS_UNC",
153            "RSP_DATA_MISS",
154            "RSP_DATA_UNC",
155            "RSP_DATA_WRITE",
156            "RSP_DATA_SC",
157        };
158        const char *tgt_fsm_state_str[] = {
159            "TGT_IDLE",
160            "TGT_UPDT_WORD",
161            "TGT_UPDT_DATA",
162            "TGT_REQ_BROADCAST",
163            "TGT_REQ_ICACHE",
164            "TGT_REQ_DCACHE",
165            "TGT_RSP_BROADCAST",
166            "TGT_RSP_ICACHE",
167            "TGT_RSP_DCACHE",
168        };
[134]169
170        const char *cleanup_fsm_state_str[] = {
171            "CLEANUP_IDLE",
[147]172            "CLEANUP_DCACHE",
173            "CLEANUP_ICACHE",
[134]174        };
[2]175    }
176
177#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcXCacheWrapperV4<vci_param, iss_t>
178
179    using soclib::common::uint32_log2;
180
181    /////////////////////////////////
182    tmpl(/**/)::VciCcXCacheWrapperV4(
[90]183    /////////////////////////////////
[2]184            sc_module_name name,
185            int proc_id,
186            const soclib::common::MappingTable &mtp,
187            const soclib::common::MappingTable &mtc,
188            const soclib::common::IntTab &initiator_index_rw,
189            const soclib::common::IntTab &initiator_index_c,
190            const soclib::common::IntTab &target_index,
191            size_t icache_ways,
192            size_t icache_sets,
193            size_t icache_words,
194            size_t dcache_ways,
195            size_t dcache_sets,
[134]196            size_t dcache_words,
197            size_t wbuf_nwords,
198            size_t wbuf_nlines,
199            size_t wbuf_timeout
200                                     )
[2]201        :
202            soclib::caba::BaseModule(name),
203
[134]204            p_clk       ("clk"),
205            p_resetn    ("resetn"),
[2]206            p_vci_ini_rw("vci_ini_rw"),
[134]207            p_vci_ini_c ("vci_ini_c"),
208            p_vci_tgt   ("vci_tgt"),
[2]209
210            m_cacheability_table(mtp.getCacheabilityTable<vci_addr_t>()),
211            m_segment(mtc.getSegment(target_index)),
[147]212            m_iss(this->name(), proc_id),
[2]213            m_srcid_rw(mtp.indexForId(initiator_index_rw)),
214            m_srcid_c(mtc.indexForId(initiator_index_c)),
215
216            m_dcache_ways(dcache_ways),
217            m_dcache_words(dcache_words),
[147]218            m_dcache_words_shift(uint32_log2(dcache_words)+2),
[134]219            m_dcache_yzmask((~0)<<m_dcache_words_shift),
[2]220            m_icache_ways(icache_ways),
221            m_icache_words(icache_words),
[147]222            m_icache_words_shift(uint32_log2(icache_words)+2),
[134]223            m_icache_yzmask((~0)<<m_icache_words_shift),
224            m_cache_words((dcache_words)?dcache_words:icache_words),
[2]225
[147]226            r_dcache_fsm("r_dcache_fsm"),
227            r_dcache_fsm_save("r_dcache_fsm_save"),
228            r_dcache_addr_save("r_dcache_addr_save"),
229            r_dcache_wdata_save("r_dcache_wdata_save"),
230            r_dcache_rdata_save("r_dcache_rdata_save"),
231            r_dcache_type_save("r_dcache_type_save"),
232            r_dcache_be_save("r_dcache_be_save"),
233            r_dcache_cached_save("r_dcache_cached_save"),
234            r_dcache_cleanup_req("r_dcache_cleanup_req"),
235            r_dcache_cleanup_line("r_dcache_cleanup_line"),
236            r_dcache_miss_req("r_dcache_miss_req"),
237            r_dcache_miss_way("r_dcache_miss_way"),
238            r_dcache_miss_set("r_dcache_miss_set"),
239            r_dcache_unc_req("r_dcache_unc_req"),
240            r_dcache_sc_req("r_dcache_sc_req"),
241            r_dcache_inval_rsp("r_dcache_inval_rsp"),
242            r_dcache_update_addr("r_dcache_update_addr"),
243            r_dcache_ll_data("r_dcache_ll_data"),
244            r_dcache_ll_addr("r_dcache_ll_addr"),
245            r_dcache_ll_valid("r_dcache_ll_valid"),
246            r_dcache_previous_unc("r_dcache_previous_unc"),
[2]247
[147]248            r_icache_fsm("r_icache_fsm"),
249            r_icache_fsm_save("r_icache_fsm_save"),
250            r_icache_addr_save("r_icache_addr_save"),
251            r_icache_miss_req("r_icache_miss_req"),
252            r_icache_miss_way("r_icache_miss_way"),
253            r_icache_miss_set("r_icache_miss_set"),
254            r_icache_unc_req("r_icache_unc_req"),
255            r_icache_cleanup_req("r_icache_cleanup_req"),
256            r_icache_cleanup_line("r_icache_cleanup_line"),
257            r_icache_inval_rsp("r_icache_inval_rsp"),
258            r_icache_update_addr("r_icache_update_addr"),
259
[2]260            r_vci_cmd_fsm("r_vci_cmd_fsm"),
261            r_vci_cmd_min("r_vci_cmd_min"),
262            r_vci_cmd_max("r_vci_cmd_max"),
263            r_vci_cmd_cpt("r_vci_cmd_cpt"),
[134]264            r_vci_cmd_dcache_prior("r_vci_cmd_dcache_prior"),
[2]265
266            r_vci_rsp_fsm("r_vci_rsp_fsm"),
[147]267            r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
268            r_vci_rsp_data_error("r_vci_rsp_data_error"),
[2]269            r_vci_rsp_cpt("r_vci_rsp_cpt"),
[147]270            r_vci_rsp_ack("r_vci_rsp_ack"),
[2]271
[147]272            r_icache_buf_unc_valid("r_icache_buf_unc_valid"),
273
[134]274#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
275            r_cache_word("r_cache_word"),
276#endif
277
[2]278            r_vci_tgt_fsm("r_vci_tgt_fsm"),
[147]279            r_tgt_addr("r_tgt_addr"),
[2]280            r_tgt_word("r_tgt_word"),
281            r_tgt_update("r_tgt_update"),
[134]282            r_tgt_update_data("r_tgt_update_data"),
283         // r_tgt_brdcast("r_tgt_brdcast"),
[2]284            r_tgt_srcid("r_tgt_srcid"),
285            r_tgt_pktid("r_tgt_pktid"),
286            r_tgt_trdid("r_tgt_trdid"),
[134]287         // r_tgt_plen("r_tgt_plen"),
[147]288            r_tgt_icache_req("r_tgt_icache_req"),
289            r_tgt_dcache_req("r_tgt_dcache_req"),
290            r_tgt_icache_rsp("r_tgt_icache_rsp"),
291            r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
[2]292
[134]293            r_cleanup_fsm("r_cleanup_fsm"),
294
[147]295            r_wbuf("r_wbuf", wbuf_nwords, wbuf_nlines, wbuf_timeout, dcache_words),
296            r_icache("icache", icache_ways, icache_sets, icache_words),
297            r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
[2]298            {
[134]299                // Size of word is 32 bits
[147]300                ASSERT( (icache_words*vci_param::B) < (1<<vci_param::K),
301                        "I need more PLEN bits");
[2]302
[147]303                ASSERT( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= wbuf_nlines),
304                        "I need more TRDID bits");
[134]305
306                CACHE_MISS_BUF_ALLOC;
307
[147]308                r_tgt_buf = new data_t[m_cache_words];
309                r_tgt_be  = new be_t  [m_cache_words];
[134]310
[2]311                SC_METHOD(transition);
312                dont_initialize();
313                sensitive << p_clk.pos();
314
315                SC_METHOD(genMoore);
316                dont_initialize();
317                sensitive << p_clk.neg();
318
[147]319
[2]320                typename iss_t::CacheInfo cache_info;
[134]321                cache_info.has_mmu          = false;
[2]322                cache_info.icache_line_size = icache_words*sizeof(data_t);
[134]323                cache_info.icache_assoc     = icache_ways;
324                cache_info.icache_n_lines   = icache_sets;
[2]325                cache_info.dcache_line_size = dcache_words*sizeof(data_t);
[134]326                cache_info.dcache_assoc     = dcache_ways;
327                cache_info.dcache_n_lines   = dcache_sets;
[147]328                m_iss.setCacheInfo(cache_info);
[134]329
330#if CC_XCACHE_WRAPPER_STOP_SIMULATION
331                m_stop_simulation               = false;
[147]332                m_stop_simulation_nb_frz_cycles = 0;
[134]333#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
334
[147]335#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
336                std::ostringstream filename("");
337                filename << "Instruction_flow_" << proc_id << ".log";
338               
339                log_dcache_transaction_file.open(filename.str().c_str() ,std::ios::out | std::ios::trunc);
[134]340#endif
[2]341            } // end constructor
342
343    ///////////////////////////////////
344    tmpl(/**/)::~VciCcXCacheWrapperV4()
[90]345    ///////////////////////////////////
[2]346    {
[147]347#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
348        log_dcache_transaction_file.close();
[134]349#endif
350
[147]351        delete [] r_tgt_buf;
[140]352        delete [] r_tgt_be ;
[134]353
354        CACHE_MISS_BUF_DEALLOC;
[2]355    }
356
357    ////////////////////////
358    tmpl(void)::print_cpi()
[90]359    ////////////////////////
[2]360    {
361        std::cout << "CPU " << m_srcid_rw << " : CPI = "
[147]362            << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
[2]363    }
364    ////////////////////////
[147]365    tmpl(void)::print_stats()
[90]366    ////////////////////////
[2]367    {
[147]368        float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
369
[134]370        uint32_t m_cpt_data_read_cached  = m_cpt_data_read-m_cpt_data_read_uncached;
371        uint32_t m_cpt_data_write_cached = m_cpt_data_write-m_cpt_data_write_uncached;
[2]372        std::cout << "------------------------------------" << std:: dec << std::endl;
373        std::cout << "CPU " << m_srcid_rw << " / Time = " << m_cpt_total_cycles << std::endl;
[147]374        std::cout << "- CPI                            : " << (float)m_cpt_total_cycles/run_cycles << std::endl ;
375        std::cout << "- IPC                            : " << (float)run_cycles/m_cpt_total_cycles << std::endl ;
[134]376        std::cout << "- DATA READ *                    : " << m_cpt_data_read << std::endl ;
377        std::cout << "  + Uncached                     : " << m_cpt_data_read_uncached << " (" << (float)m_cpt_data_read_uncached*100.0/(float)m_cpt_data_read << "%)" << std::endl ;
378        std::cout << "  + Cached and miss              : " << m_cpt_data_read_miss << " (" << (float)m_cpt_data_read_miss*100.0/(float)m_cpt_data_read_cached << "%)" << std::endl;
379        std::cout << "- DATA WRITE *                   : " << m_cpt_data_write << std::endl ;
380        std::cout << "  + Uncached                     : " << m_cpt_data_write_uncached << " (" << (float)m_cpt_data_write_uncached*100.0/(float)m_cpt_data_write << "%)" << std::endl ;
381        std::cout << "  + Cached and miss              : " << m_cpt_data_write_miss << " (" << (float)m_cpt_data_write_miss*100.0/(float)m_cpt_data_write_cached << "%)" << std::endl;
382        // std::cout << "- WRITE RATE                     : " << (float)m_cpt_data_write/run_cycles << std::endl;
383        // std::cout << "- UNCACHED READ RATE             : " << (float)m_cpt_data_read_uncached/m_cpt_data_read << std::endl ;
384        // std::cout << "- CACHED WRITE RATE              : " << (float)m_cpt_data_write_cached/m_cpt_data_write << std::endl ;
385        // std::cout << "- IMISS_RATE                     : " << (float)m_cpt_ins_miss/run_cycles << std::endl;
386        // std::cout << "- DMISS RATE                     : " << (float)m_cpt_data_miss/(m_cpt_data_read-m_cpt_data_read_uncached) << std::endl ;
387        // std::cout << "- INS MISS COST                  : " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl;
388        // std::cout << "- IMISS TRANSACTION              : " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl;
389        // std::cout << "- DMISS COST                     : " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl;
390        // std::cout << "- DMISS TRANSACTION              : " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl;
391        // std::cout << "- UNC COST                       : " << (float)m_cost_unc_read_frz/m_cpt_data_read_uncached << std::endl;
392        // std::cout << "- UNC TRANSACTION                : " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl;
393        // std::cout << "- WRITE COST                     : " << (float)m_cost_write_frz/m_cpt_data_write << std::endl;
394        // std::cout << "- WRITE TRANSACTION              : " << (float)m_cost_write_transaction/m_cpt_data_write_transaction << std::endl;
395        // std::cout << "- WRITE LENGTH                   : " << (float)m_length_write_transaction/m_cpt_data_write_transaction << std::endl;
396
397        std::cout << "- CC_UPDATE_ICACHE               : " << m_cpt_cc_update_icache  << std::endl;
398        std::cout << "  + AVERAGE WORD USEFUL          : " << (float)m_cpt_cc_update_icache_word_useful/(float)m_cpt_cc_update_icache << " on " << m_icache_words << " words" << std::endl;
399        std::cout << "- CC_UPDATE_DCACHE               : " << m_cpt_cc_update_dcache  << std::endl;
400        std::cout << "  + AVERAGE WORD USEFUL          : " << (float)m_cpt_cc_update_dcache_word_useful/(float)m_cpt_cc_update_dcache << " on " << m_dcache_words << " words" << std::endl;
401        uint32_t m_cpt_cc_inval = m_cpt_cc_inval_broadcast+m_cpt_cc_inval_icache+m_cpt_cc_inval_dcache;
402        std::cout << "- CC_INVALID                     : " << m_cpt_cc_inval << std::endl;
403        std::cout << "  + ICACHE Only                  : " << (float)m_cpt_cc_inval_icache   *100.0/(float)m_cpt_cc_inval << "%" << std::endl;
404        std::cout << "  + DCACHE Only                  : " << (float)m_cpt_cc_inval_dcache   *100.0/(float)m_cpt_cc_inval << "%" << std::endl;
405        std::cout << "  + BROADCAST                    : " << (float)m_cpt_cc_inval_broadcast*100.0/(float)m_cpt_cc_inval << "%" << std::endl;
406        std::cout << "* : accepted or not by the cache" << std::endl ;
407
[147]408        r_wbuf.printStatistics();
[2]409    }
[134]410
[114]411    ////////////////////////////////////
412    tmpl(void)::print_trace(size_t mode)
413    ////////////////////////////////////
[90]414    {
[134]415        // b0 : write buffer print trace
416        // b1 : write buffer verbose
417        // b2 : dcache print trace
418        // b3 : icache print trace
419
[90]420        typename iss_t::InstructionRequest  ireq;
421        typename iss_t::DataRequest         dreq;
[134]422
[147]423        m_iss.getRequests( ireq, dreq );
[134]424        std::cout << std::dec << "Proc \"" << name() << "\"" << std::endl;
[147]425        std::cout << ireq << std::endl;
426        std::cout << dreq << std::endl;
427        std::cout << "  " << dcache_fsm_state_str[r_dcache_fsm]
428                  << "  " << icache_fsm_state_str[r_icache_fsm]
429                  << "  " << cmd_fsm_state_str[r_vci_cmd_fsm]
[134]430                  << "  " << rsp_fsm_state_str[r_vci_rsp_fsm]
431                  << "  " << tgt_fsm_state_str[r_vci_tgt_fsm]
432                  << "  " << cleanup_fsm_state_str[r_cleanup_fsm] << std::endl;
[2]433
[134]434        if(mode & 0x1)
[114]435        {
[147]436            r_wbuf.printTrace((mode>>1)&1);
[114]437        }
[134]438        if(mode & 0x4)
[114]439        {
[134]440            std::cout << "  Data cache" << std::endl;
[147]441            r_dcache.printTrace();
[114]442        }
[134]443        if(mode & 0x8)
444        {
445            std::cout << "  Instruction cache" << std::endl;
[147]446            r_icache.printTrace();
[134]447        }
[147]448
449        // if(mode & 0x10)
450        // {
451        //     std::cout << "  Icache miss buffer : ";
452        //     CACHE_MISS_BUF_RSP_PRINT(i);
453        //     std::cout << std::endl;
454
455        //     std::cout << "  Dcache miss buffer : ";
456        //     CACHE_MISS_BUF_RSP_PRINT(d);
457        //     std::cout << std::endl;
458        // }
[90]459    }
[134]460
[2]461    //////////////////////////
462    tmpl(void)::transition()
[90]463    //////////////////////////
[2]464    {
[134]465        if ( not p_resetn.read() ) {
[2]466
[147]467            m_iss.reset();
[2]468
469            // FSM states
[147]470            r_dcache_fsm  = DCACHE_IDLE;
471            r_icache_fsm  = ICACHE_IDLE;
[2]472            r_vci_cmd_fsm = CMD_IDLE;
473            r_vci_rsp_fsm = RSP_IDLE;
474            r_vci_tgt_fsm = TGT_IDLE;
[134]475            r_cleanup_fsm = CLEANUP_IDLE;
[2]476
477            // write buffer & caches
[147]478            r_wbuf.reset();
479            r_icache.reset();
480            r_dcache.reset();
[2]481
482            // synchronisation flip-flops from ICACHE & DCACHE FSMs to VCI  FSMs
[147]483            r_icache_miss_req    = false;
484            r_icache_unc_req     = false;
485            r_icache_cleanup_req = false;
486            r_dcache_miss_req    = false;
487            r_dcache_unc_req     = false;
488            r_dcache_sc_req      = false;
489            r_dcache_cleanup_req = false;
490            r_dcache_previous_unc= false;
[2]491
492            // synchronisation flip-flops from TGT FSM to ICACHE & DCACHE FSMs
[147]493            r_tgt_icache_req     = false;
494            r_tgt_dcache_req     = false;
495            r_tgt_icache_rsp     = false;
496            r_tgt_dcache_rsp     = false;
[2]497
[147]498#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
499            r_cache_word         = 0;
500#endif
[134]501
502
[2]503            // internal messages in DCACHE et ICACHE FSMs
[147]504            r_icache_inval_rsp   = false;
505            r_dcache_inval_rsp   = false;
[2]506
507            // error signals from the VCI RSP FSM to the ICACHE or DCACHE FSMs
[147]508            r_dcache_ll_valid      = false;
509            r_icache_buf_unc_valid = false;
[134]510
[147]511            r_vci_cmd_dcache_prior = false;
[140]512
[147]513            r_vci_rsp_data_error   = false;
514            r_vci_rsp_ins_error    = false;
[140]515
[134]516            CACHE_MISS_BUF_RESET(i);
517            CACHE_MISS_BUF_RESET(d);
518
[2]519            // activity counters
520            m_cpt_dcache_data_read  = 0;
521            m_cpt_dcache_data_write = 0;
[134]522            m_cpt_dcache_dir_read   = 0;
523            m_cpt_dcache_dir_write  = 0;
[2]524            m_cpt_icache_data_read  = 0;
525            m_cpt_icache_data_write = 0;
[134]526            m_cpt_icache_dir_read   = 0;
527            m_cpt_icache_dir_write  = 0;
[2]528
[134]529            m_cpt_cc_update_icache             = 0;
530            m_cpt_cc_update_dcache             = 0;
531            m_cpt_cc_inval_broadcast           = 0;
532            m_cpt_cc_inval_icache              = 0;
533            m_cpt_cc_inval_dcache              = 0;
534            m_cpt_cc_update_icache_word_useful = 0;
535            m_cpt_cc_update_dcache_word_useful = 0;
[2]536
[147]537            m_cpt_frz_cycles   = 0;
[2]538            m_cpt_total_cycles = 0;
539
[134]540            m_cpt_data_read            = 0;
541            m_cpt_data_read_miss       = 0;
542            m_cpt_data_read_uncached   = 0;
543            m_cpt_data_write           = 0;
544            m_cpt_data_write_miss      = 0;
545            m_cpt_data_write_uncached  = 0;
[2]546
[134]547            m_cpt_ins_miss     = 0;
548
[2]549            m_cost_write_frz = 0;
550            m_cost_data_miss_frz = 0;
551            m_cost_unc_read_frz = 0;
552            m_cost_ins_miss_frz = 0;
553
554            m_cpt_imiss_transaction = 0;
555            m_cpt_dmiss_transaction = 0;
556            m_cpt_unc_transaction = 0;
[134]557            m_cpt_data_write_transaction = 0;
[2]558
559            m_cost_imiss_transaction = 0;
560            m_cost_dmiss_transaction = 0;
561            m_cost_unc_transaction = 0;
562            m_cost_write_transaction = 0;
563            m_length_write_transaction = 0;
564
565            return;
566        }
567
[134]568        // printf("%d\n",(uint32_t)m_cpt_total_cycles);
569
570        PRINTF("--------------------------------------------\n");
[147]571        PRINTF("  * CC_XCACHE_WRAPPER \"%s\" - Time = %d\n",name().c_str(),(uint32_t)m_cpt_total_cycles);
572        PRINTF("    * fsm dcache          = %s\n",dcache_fsm_state_str[r_dcache_fsm]);
573        PRINTF("    * fsm icache          = %s\n",icache_fsm_state_str[r_icache_fsm]);
574        PRINTF("    * fsm cmd             = %s\n",cmd_fsm_state_str[r_vci_cmd_fsm]);
575        PRINTF("    * fsm rsp             = %s\n",rsp_fsm_state_str[r_vci_rsp_fsm]);
576        PRINTF("    * fsm tgt             = %s\n",tgt_fsm_state_str[r_vci_tgt_fsm]);
577        PRINTF("    * fsm cleanup         = %s\n",cleanup_fsm_state_str[r_cleanup_fsm]);
578        PRINTF("    * ll info             : %d %llx %llx\n",r_dcache_ll_valid.read(), (uint64_t)r_dcache_ll_addr.read(), (uint64_t)r_dcache_ll_data.read());
579        PRINTF("    * dcache_previous_unc : %d\n",r_dcache_previous_unc.read());
580        // CACHE_MISS_BUF_RSP_PRINT(i);
581        // CACHE_MISS_BUF_RSP_PRINT(d);
[134]582
583#if CC_XCACHE_WRAPPER_DEBUG
[147]584        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
585            {
586                r_wbuf.printTrace(1);
587            }
[2]588#endif
589
590        m_cpt_total_cycles++;
591
592        /////////////////////////////////////////////////////////////////////
593        // The TGT_FSM controls the following ressources:
594        // - r_vci_tgt_fsm
595        // - r_tgt_buf[nwords]
596        // - r_tgt_be[nwords]
597        // - r_tgt_update
598        // - r_tgt_word
599        // - r_tgt_addr
600        // - r_tgt_srcid
601        // - r_tgt_trdid
602        // - r_tgt_pktid
603        // All VCI commands must be CMD_WRITE.
604        // If the VCI address offset is null, the command is an invalidate
605        // request. It is an update request otherwise.
606        // The VCI_TGT FSM stores the external request arguments in the
607        // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req
608        // & r_tgt_dcache_req flip-flops to signal the external request to
609        // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
610        // of the update or invalidate request in the RSP state.
611        // -  for an invalidate request the VCI packet length is 1 word.
612        // The WDATA field contains the line index (i.e. the Z & Y fields).
613        // -  for an update request the VCI packet length is (n+2) words.
614        // The WDATA field of the first VCI word contains the line number.
615        // The WDATA field of the second VCI word contains the word index.
616        // The WDATA field of the n following words contains the values.
617        // -  for both invalidate & update requests, the VCI response
618        // is one single word.
619        // In case of errors in the VCI command packet, the simulation
620        // is stopped with an error message.
621        /////////////////////////////////////////////////////////////////////
622
623        switch(r_vci_tgt_fsm) {
624
625            case TGT_IDLE:
626                if ( p_vci_tgt.cmdval.read() )
627                {
[147]628                    PRINTF("    * <TGT> request\n");
[134]629
[2]630                    addr_40 address = p_vci_tgt.address.read();
631
632                    if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE)
633                    {
634                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
[113]635                        std::cout << "coherence request is not a write" << std::endl;
[147]636                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
[134]637                        std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
[2]638                        exit(0);
639                    }
640
641                    // multi-update or multi-invalidate for data type
[134]642                    if ( ((address&0x3) != 0x3) and (not m_segment.contains(address)) )
[2]643                    {
644                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
[113]645                        std::cout << "out of segment coherence request" << std::endl;
[147]646                        std::cout << "oddress = " << std::hex << address << std::dec << std::endl;
[134]647                        std::cout << "srcid   = " << p_vci_tgt.srcid.read() << std::endl;
[2]648                        exit(0);
649                    }
650
[147]651                    r_tgt_addr = (((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) |
652                                 ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4;     
653                    r_tgt_srcid = p_vci_tgt.srcid.read();
654                    r_tgt_trdid = p_vci_tgt.trdid.read();
655                    r_tgt_pktid = p_vci_tgt.pktid.read();
656                 // r_tgt_plen  = p_vci_tgt.plen.read();
657                   
658                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)address);
659                    PRINTF("    * <TGT> address : %llx\n",(uint64_t)((((addr_40) ((p_vci_tgt.be.read() & 0x3) << 32)) |
660                                                                      ((addr_40) (p_vci_tgt.wdata.read()))) * m_dcache_words * 4));
[140]661
[82]662                    if ( (address&0x3) == 0x3 )   // broadcast invalidate for data or instruction type
[2]663                    {
[134]664                        if ( not p_vci_tgt.eop.read() )
[2]665                        {
666                            std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
667                            std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
668                            exit(0);
669                        }
670                        r_tgt_update = false;
[134]671                        // r_tgt_brdcast= true;
[2]672                        r_vci_tgt_fsm = TGT_REQ_BROADCAST;
[134]673                        m_cpt_cc_inval_broadcast++ ;
[2]674                    }
675                    else                    // multi-update or multi-invalidate for data type
676                    {
677                        uint32_t cell = address - m_segment.baseAddress(); // addr_40
[134]678                        // r_tgt_brdcast = false;
[2]679                        if (cell == 0)
680                        {                                       // invalidate data
[134]681                            if ( not p_vci_tgt.eop.read() )
[2]682                            {
683                                std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
684                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
685                                exit(0);
686                            }
687                            r_tgt_update = false;
688                            r_vci_tgt_fsm = TGT_REQ_DCACHE;
[134]689                            m_cpt_cc_inval_dcache++ ;
[2]690                        }
691                        else if (cell == 4)                     // invalidate instruction
692                        {                         
[134]693                            if ( not p_vci_tgt.eop.read() )
[2]694                            {
695                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
696                                std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
697                                exit(0);
698                            }
699                            r_tgt_update = false;
700                            r_vci_tgt_fsm = TGT_REQ_ICACHE;
[134]701                            m_cpt_cc_inval_icache++ ;
[2]702                        }
[134]703                        else if ( (cell == 8) or (cell==12) )    // update data or instruction
[2]704                        {                               
705                            if ( p_vci_tgt.eop.read() )
706                            {
707                                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
708                                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
709                                exit(0);
710                            }
711                            if(cell == 8)
[134]712                            {
713                                m_cpt_cc_update_dcache++;
[2]714                                r_tgt_update_data = true;
[134]715                            }
[2]716                            else
[134]717                            {
718                                m_cpt_cc_update_icache++;
[2]719                                r_tgt_update_data = false;
[134]720                            }
[2]721                            r_tgt_update = true;
722                            r_vci_tgt_fsm = TGT_UPDT_WORD;
723                        }
724
725                    } // end if address
726                } // end if cmdval
727                break;
728
729            case TGT_UPDT_WORD:
730                if (p_vci_tgt.cmdval.read())
731                {
732                    if ( p_vci_tgt.eop.read() )
733                    {
734                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
735                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
736                        exit(0);
737                    }
738                    for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = 0;
739                    r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
740#ifdef COHERENCE_DEBUG
[147]741                    std::cout << "PROC " << m_srcid_rw << " update, line : " << std::hex << r_tgt_addr.read() << " word : " << p_vci_tgt.wdata.read() << std::dec << std::endl;
[2]742#endif
743                    r_vci_tgt_fsm = TGT_UPDT_DATA;
744                }
745                break;
746
747            case TGT_UPDT_DATA:
748                if (p_vci_tgt.cmdval.read())
749                {
750                    size_t word = r_tgt_word.read();
[134]751                    if ( word >= m_cache_words )
[2]752                    {
753                        std::cout << "error in component VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
754                        std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
755                        exit(0);
756                    }
757#ifdef COHERENCE_DEBUG
758                    std::cout << "PROC " << m_srcid_rw << " update, data : " << p_vci_tgt.wdata.read() << " be : " << std::hex << p_vci_tgt.be.read() << std::dec << std::endl;
759#endif
[134]760
[2]761                    r_tgt_buf[word] = p_vci_tgt.wdata.read();
[134]762                    r_tgt_be [word] = p_vci_tgt.be.read();
763
764                    if (p_vci_tgt.be.read())
765                    {
766                        if(r_tgt_update_data.read())
767                            m_cpt_cc_update_dcache_word_useful++ ;
768                        else
769                            m_cpt_cc_update_icache_word_useful++ ;
770                    }
771
[2]772                    r_tgt_word = word + 1;
773                    if (p_vci_tgt.eop.read()){
[134]774#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
775                      uint32_t word=0;
776                      for (; word<m_cache_words; ++word)
777                          if (r_tgt_be[word] != 0)
778                              break;
779                      r_cache_word = word;
780#endif
[2]781                      if(r_tgt_update_data.read()){
782                        r_vci_tgt_fsm = TGT_REQ_DCACHE;
783                      } else {
784                        r_vci_tgt_fsm = TGT_REQ_ICACHE;
785                      }
786                    }
787                }
788                break;
789
790            case TGT_REQ_BROADCAST:
[147]791                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() )
[2]792                {
[147]793                    r_vci_tgt_fsm = TGT_RSP_BROADCAST;
794                    r_tgt_icache_req = true;
795                    r_tgt_dcache_req = true;
[2]796                }
797                break;
798                ////////////////////
799            case TGT_REQ_ICACHE:
800                {
[147]801                    if ( not r_tgt_icache_req.read() )
[2]802                    {
803                        r_vci_tgt_fsm = TGT_RSP_ICACHE;
[147]804                        r_tgt_icache_req = true;
[2]805                    }
806                    break;
807                }
808
809            case TGT_REQ_DCACHE:
[147]810                if ( not r_tgt_dcache_req.read() )
[2]811                {
[147]812                    r_vci_tgt_fsm = TGT_RSP_DCACHE;
813                    r_tgt_dcache_req = true;
814                }
815                break;
[140]816
[2]817            case TGT_RSP_BROADCAST:
[147]818                if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() )
[2]819                {
[147]820                    // one response
821                    if ( not r_tgt_icache_rsp or not r_tgt_dcache_rsp )
[2]822                    {
[147]823                        if ( p_vci_tgt.rspack.read() )
[2]824                        {
[147]825                            r_vci_tgt_fsm = TGT_IDLE;
826                            r_tgt_icache_rsp = false;
827                            r_tgt_dcache_rsp = false;
[2]828                        }
[147]829                    }
[2]830
[147]831                    // if data and instruction have the inval line, need two responses 
832                    if ( r_tgt_icache_rsp and r_tgt_dcache_rsp )
833                    {
834                        if ( p_vci_tgt.rspack.read() )
[2]835                        {
[147]836                            r_tgt_icache_rsp = false; // only reset one for respond the second time
[2]837                        }
[147]838                    }
[2]839
[147]840                    // if there is no need for a response
841                    if ( not r_tgt_icache_rsp and not r_tgt_dcache_rsp )
842                    {
843                        r_vci_tgt_fsm = TGT_IDLE;
844                    }
[140]845
[2]846                }
[147]847                break;
[2]848                ////////////////////
849            case TGT_RSP_ICACHE:
850                {
[147]851                    if ( (p_vci_tgt.rspack.read() or not r_tgt_icache_rsp.read()) and not r_tgt_icache_req.read() )
[2]852                    {
853                        r_vci_tgt_fsm = TGT_IDLE;
[147]854                        r_tgt_icache_rsp = false;
[2]855                    }
856                    break;
857                }
858
859            case TGT_RSP_DCACHE:
860                {
[147]861                    if ( (p_vci_tgt.rspack.read() or not r_tgt_dcache_rsp.read()) and not r_tgt_dcache_req.read() )
[2]862                    {
863                        r_vci_tgt_fsm = TGT_IDLE;
[147]864                        r_tgt_dcache_rsp = false;
[2]865                    }
866                    break;
867                }
868        } // end switch TGT_FSM
869
870        /////////////////////////////////////////////////////////////////////
871        // The ICACHE FSM controls the following ressources:
872        // - r_icache_fsm
873        // - r_icache_fsm_save
874        // - r_icache instruction cache access
875        // - r_icache_addr_save
876        // - r_icache_miss_req set
877        // - r_icache_unc_req set
878        // - r_icache_buf_unc_valid set
[134]879        // - r_vci_rsp_icache_miss_ok reset
[2]880        // - r_vci_rsp_ins_error reset
881        // - r_tgt_icache_req reset
882        // - ireq & irsp structures for communication with the processor
883        //
884        // 1/ External requests (update or invalidate) have highest priority.
885        //    They are taken into account in the IDLE and WAIT states.
886        //    As external hit should be extremly rare on the ICACHE,
887        //    all external requests are handled as invalidate...
888        //    In case of external request the ICACHE FSM goes to the CC_CHECK
889        //    state to test the external hit, and returns in the
890        //    pre-empted state after completion.
891        // 2/ Processor requests are taken into account only in the IDLE state.
892        //    In case of MISS, or in case of uncached instruction, the FSM
893        //    writes the missing address line in the  r_icache_addr_save register
894        //    and sets the r_icache_miss_req or the r_icache_unc_req flip-flops.
895        //    These request flip-flops are reset by the VCI_RSP FSM
896        //    when the VCI transaction is completed and the r_icache_buf_unc_valid
897        //    is set in case of uncached access.
898        //    In case of bus error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
899        //    flip-flop. It is reset by the ICACHE FSM.
900        ///////////////////////////////////////////////////////////////////////
901
[147]902        typename iss_t::InstructionRequest  ireq = ISS_IREQ_INITIALIZER;
903        typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
904
905        typename iss_t::DataRequest         dreq = ISS_DREQ_INITIALIZER;
906        typename iss_t::DataResponse        drsp = ISS_DRSP_INITIALIZER;
907
908        m_iss.getRequests( ireq, dreq );
909
910#if CC_XCACHE_WRAPPER_DEBUG
911        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
912            std::cout << "    * Instruction Request  : " << ireq << std::endl;
913#endif
914
915        switch(r_icache_fsm) {
[2]916            /////////////////
917            case ICACHE_IDLE:
918                {
[147]919                    if ( r_tgt_icache_req ) {   // external request
920                        if ( ireq.valid ) m_cost_ins_miss_frz++;
921                        r_icache_fsm = ICACHE_CC_CHECK;
922                        r_icache_fsm_save = r_icache_fsm.read();
[2]923                        break;
924                    }
[147]925                    if ( ireq.valid ) {
926                        data_t  icache_ins = 0;
927                        bool    icache_hit = false;
928                        bool    icache_cached = m_cacheability_table[(vci_addr_t)ireq.addr];
929                        bool    icache_cleanup_hit = r_icache_cleanup_req and (((addr_40)ireq.addr >> (addr_40)m_icache_words_shift) == r_icache_cleanup_line.read());
[134]930
[2]931                        // icache_hit & icache_ins evaluation
932                        if ( icache_cached ) {
[147]933                            icache_hit = r_icache.read((vci_addr_t) ireq.addr, &icache_ins);
[2]934                        } else {
[134]935                            // if uncache, again in the icache_miss_buf
[147]936                            icache_hit = ( r_icache_buf_unc_valid and ((addr_40) ireq.addr == (addr_40)r_icache_addr_save));
937                            icache_ins = CACHE_MISS_BUF_RSP_DATA(i,0);
938                            CACHE_MISS_BUF_RSP_POP(i);
[2]939                        }
[134]940
[147]941                        PRINTF("    * <ICACHE> hit %d - cached %d - cleanup_hit %d\n",icache_hit, icache_cached, icache_cleanup_hit);
[134]942
[147]943                        ASSERT( not (icache_hit and icache_cleanup_hit),
944                                "Icache hit and icache_cleanup_hit");
[144]945
[147]946                        if ( not icache_hit and not icache_cleanup_hit) {
947                            m_cpt_ins_miss++;
948                            m_cost_ins_miss_frz++;
949                            r_icache_addr_save = (addr_40) ireq.addr;
[144]950
[147]951                            CACHE_MISS_BUF_REQ_INIT(i);
952
953                            if ( icache_cached ) {
954#if CC_XCACHE_WRAPPER_SELECT_VICTIM
955                                r_icache_fsm = ICACHE_MISS_VICTIM;
956#else
957                                r_icache_fsm = ICACHE_MISS_WAIT;
958#endif
959                                r_icache_miss_req = true;
960                               
961                            } else {
962                                r_icache_fsm = ICACHE_UNC_WAIT;
963                                r_icache_unc_req = true;
[2]964                            }
[147]965                        } else {
966                            r_icache_buf_unc_valid = false;
[2]967                        }
[147]968                        m_cpt_icache_dir_read += m_icache_ways;
969                        m_cpt_icache_data_read += m_icache_ways;
970                        irsp.valid          = icache_hit;
971                        irsp.instruction    = icache_ins;
972                    }
[2]973                    break;
974                }
975                //////////////////////
[147]976#if CC_XCACHE_WRAPPER_SELECT_VICTIM
[134]977            case ICACHE_MISS_VICTIM:
978                {
[147]979                    if (not r_icache_cleanup_req)
[134]980                    {
981                        size_t     way;
982                        size_t     set;
[147]983                        vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read();
[134]984                        vci_addr_t victim;
985                       
[147]986                        r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
987                        r_icache_cleanup_line = (addr_40) victim;
988                        r_icache_miss_way     = way;
989                        r_icache_miss_set     = set;
[134]990                       
[147]991                        r_icache_fsm = ICACHE_MISS_WAIT;
[134]992                    }
993                    break;
994                }
[147]995#endif
[134]996                //////////////////////
[2]997            case ICACHE_MISS_WAIT:
998                {
999                    m_cost_ins_miss_frz++;
[147]1000                    if ( r_tgt_icache_req ) {   // external request
1001                        r_icache_fsm = ICACHE_CC_CHECK;
1002                        r_icache_fsm_save = r_icache_fsm.read();
[2]1003                        break;
1004                    }
[134]1005
[147]1006                    bool val = CACHE_MISS_BUF_RSP_VAL(i,0);
[134]1007
[147]1008                    PRINTF("    * <ICACHE> val                  : %d\n",val);
[134]1009
1010                    if (val)
1011                    {
[147]1012                        PRINTF("    * <ICACHE> r_icache_inval_rsp   : %d\n",(int) r_icache_inval_rsp  );
1013                        PRINTF("    * <ICACHE> r_vci_rsp_ins_error  : %d\n",(int) r_vci_rsp_ins_error );
1014                        PRINTF("    * <ICACHE> r_icache_cleanup_req : %d\n",(int) r_icache_cleanup_req);
[134]1015
[147]1016                        // if (not r_icache_inval_rsp )
1017                        // {
1018                            // Miss read response and no invalidation
1019                            if ( r_vci_rsp_ins_error ) {
1020                                r_icache_fsm = ICACHE_ERROR;
1021                            } else {
1022#if not CC_XCACHE_WRAPPER_SELECT_VICTIM
1023                                if (not r_icache_cleanup_req.read())
1024#endif
1025                                {
1026                                    r_icache_update_addr = 0;
1027                                    r_icache_fsm         = ICACHE_MISS_UPDT;
1028                                }
1029                            }
1030                        // }
1031                        // else
1032                        // {
1033                        //     r_icache_inval_rsp = false;
1034                           
1035                        //     // Miss read response and invalidation
1036                        //     if ( r_vci_rsp_ins_error )
1037                        //         r_icache_fsm = ICACHE_ERROR;
1038                        //     else
1039                        //         r_icache_fsm = ICACHE_CC_CLEANUP;
1040                        // }
[2]1041                    }
1042                    break;
1043                }
1044                /////////////////////
1045            case ICACHE_UNC_WAIT:
1046                {
1047                    m_cost_ins_miss_frz++;
[147]1048                    if ( r_tgt_icache_req ) {   // external request
1049                        r_icache_fsm = ICACHE_CC_CHECK;
1050                        r_icache_fsm_save = r_icache_fsm.read();
[2]1051                        break;
[134]1052                    }
1053
[147]1054                    bool ok = CACHE_MISS_BUF_RSP_VAL(i,0);
[134]1055
1056                    if (ok)
1057                    {
[147]1058                        if ( r_vci_rsp_ins_error ) {
1059                            r_icache_fsm = ICACHE_ERROR;
[2]1060                        } else {
[147]1061                            r_icache_fsm = ICACHE_IDLE;
1062                            r_icache_buf_unc_valid = true;
[2]1063                        }
1064                    }
1065                    break;
1066                }
1067                //////////////////
1068            case ICACHE_ERROR:
1069                {
[147]1070                    if ( (addr_40)ireq.addr == (addr_40)r_icache_addr_save ) {
1071                        irsp.error          = true;
1072                        irsp.valid          = true;
[109]1073                    }
[147]1074                    r_icache_fsm = ICACHE_IDLE;
1075                    r_vci_rsp_ins_error = false;
[2]1076                    break;
1077                }
1078                //////////////////////
1079            case ICACHE_MISS_UPDT:
1080                {
[147]1081                    size_t     word = r_icache_update_addr.read();
1082                    vci_addr_t addr = (vci_addr_t) r_icache_addr_save.read();
1083                    size_t     way  = 0;
1084                    size_t     set  = 0;
[2]1085
[147]1086                    // need invalid rsp, don't select a victim
1087                    if (not r_icache_inval_rsp )
1088                    {
1089#if CC_XCACHE_WRAPPER_SELECT_VICTIM
1090                        way = r_icache_miss_way.read();
1091                        set = r_icache_miss_set.read();
1092#else
[134]1093
[147]1094                        // First word : select an victim !
1095                        if (word == 0)
1096                        {
1097                            vci_addr_t victim;
1098                       
1099                            // r_icache_cleanup_req is false because is the transition condition to go in ICACHE_MISS_UPDT state
1100                            r_icache_cleanup_req  = r_icache.victim_select(addr, &victim, &way, &set );
1101                            r_icache.victim_update_tag(addr, way, set);
1102                       
1103                            r_icache_cleanup_line = (addr_40) victim;
1104                            r_icache_miss_way     = way;
1105                            r_icache_miss_set     = set;
1106                        }
1107                        else
1108                        {
1109                            way = r_icache_miss_way.read();
1110                            set = r_icache_miss_set.read();
1111                        }
1112#endif
1113                    }
1114                    bool val = CACHE_MISS_BUF_RSP_VAL(i,word);
1115
[134]1116                    if (val)
1117                    {
[147]1118                        PRINTF("    * <ICACHE> rsp_val            : %d/%d\n",(int)r_icache_update_addr,m_icache_words);
1119                        PRINTF("    * <ICACHE> r_icache_inval_rsp : %d\n",(int)r_icache_inval_rsp);
1120                        PRINTF("    * <ICACHE> ins : %x\n",(int)CACHE_MISS_BUF_RSP_DATA(i,word));
[134]1121
1122                        // m_cpt_icache_dir_write++;
1123                        // m_cpt_icache_data_write++;
[147]1124                        // if ( ireq.valid ) m_cost_ins_miss_frz++;
[134]1125
1126                        // if need invalid rsp, don't modify the cache, but pop the buf_rsp
[147]1127                        if (not r_icache_inval_rsp )
1128                            r_icache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(i,word));
1129                        CACHE_MISS_BUF_RSP_POP(i);
[134]1130
[147]1131                        r_icache_update_addr = ++word;
[134]1132                           
1133                        // if last word, finish the update
1134                        if (word >= m_icache_words)
1135                        {
1136                            // Last word : if previous invalid_rsp, can cleanup, else update the TAG
[147]1137                            if (r_icache_inval_rsp)
[134]1138                            {
[147]1139                                r_icache_inval_rsp  = false;
1140                                r_icache_fsm = ICACHE_CC_CLEANUP;
[134]1141                            }
1142                            else
1143                            {
[147]1144#if CC_XCACHE_WRAPPER_SELECT_VICTIM
1145                                r_icache.victim_update_tag(addr, way, set);
1146#endif
1147                                r_icache_fsm = ICACHE_IDLE;
[134]1148                            }
1149                        }
[2]1150                    }
[134]1151
1152                    break;
[2]1153                }
1154                ////////////////////
1155            case ICACHE_CC_CLEANUP:
1156                {
[147]1157                    // external cache invalidate request
1158                    if ( r_tgt_icache_req )     
1159                    {
1160                        r_icache_fsm = ICACHE_CC_CHECK;
1161                        r_icache_fsm_save = r_icache_fsm.read();
1162                        break;
1163                    }
[2]1164                    // cleanup
[147]1165                    if(not r_icache_cleanup_req){
1166                        r_icache_cleanup_req = true;
1167                        r_icache_cleanup_line = r_icache_addr_save.read() >> m_icache_words_shift;
1168                        r_icache_fsm = ICACHE_IDLE;
[2]1169                    }
1170                    break;
1171                }
1172                /////////////////////
1173            case ICACHE_CC_CHECK:   // read directory in case of invalidate or update request
1174                {
1175
[134]1176                    m_cpt_icache_dir_read  += m_icache_ways;
[2]1177                    m_cpt_icache_data_read += m_icache_ways;
[147]1178                    addr_40 ad = r_tgt_addr;
[2]1179                    data_t  icache_rdata = 0;
1180
[147]1181                    if((r_icache_fsm_save == ICACHE_MISS_WAIT) and
1182                            ( (r_icache_addr_save.read() & ~((m_icache_words<<2)-1)) == (ad & ~((m_icache_words<<2)-1)))) {
1183                        r_icache_inval_rsp = true;
1184                        r_tgt_icache_req = false;
[2]1185                        if(r_tgt_update){    // Also send a cleanup and answer
[147]1186                            r_tgt_icache_rsp     = true;
[2]1187                        } else {            // Also send a cleanup but don't answer
[147]1188                            r_tgt_icache_rsp     = false;
[2]1189                        }
[147]1190                        r_icache_fsm = r_icache_fsm_save;
[2]1191                    } else {
[147]1192                        bool    icache_hit   = r_icache.read(ad, &icache_rdata);
1193                        if ( icache_hit and r_tgt_update )
[134]1194                        {
1195#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1196                            uint32_t word  = r_cache_word;
1197                            data_t   mask  = vci_param::be2mask(r_tgt_be[word]);
1198                            data_t   rdata = 0;
1199
[147]1200                            r_icache.read(ad+word*4,&rdata);
[134]1201                            r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
1202                           
1203                            word ++;
1204#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1205                            for (; word<m_icache_words; ++word)
1206                                if (r_tgt_be[word] != 0)
1207                                    break;
1208#endif
1209
1210                            if (word==m_icache_words)
1211                            {
[147]1212                                r_icache_fsm = ICACHE_CC_UPDT;
[134]1213
1214#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1215                                for (word=0; word<m_icache_words; ++word)
1216                                    if (r_tgt_be[word] != 0)
1217                                        break;
1218#else
1219                                word = 0;
1220#endif
1221                            }
1222                            r_cache_word = word;
1223#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
[147]1224                            r_icache_fsm = ICACHE_CC_UPDT;
[2]1225                            // complete the line buffer in case of update
[58]1226                            for(size_t i=0; i<m_icache_words; i++){
[2]1227                                data_t rdata = 0;
[147]1228                                r_icache.read(ad + i*4,&rdata);
[2]1229                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
1230                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
1231                            }
[134]1232#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
[147]1233                        } else if ( icache_hit and not r_tgt_update ) {
1234                            r_icache_fsm = ICACHE_CC_INVAL;
[2]1235                        } else { // instruction not found (can happen)
[147]1236                            r_tgt_icache_req = false;
[2]1237                            if(r_tgt_update){
[147]1238                                r_tgt_icache_rsp = true;
[2]1239                            } else {
[147]1240                                r_tgt_icache_rsp = false;
[2]1241                            }
[147]1242                            r_icache_fsm = r_icache_fsm_save;
[2]1243                        }
1244                    }
1245                    break;
1246                }
1247                /////////////////////
1248            case ICACHE_CC_INVAL: 
1249                {                       
[147]1250                    addr_40    ad  = r_tgt_addr;
1251                    if ( ireq.valid ) m_cost_ins_miss_frz++;
[2]1252                    m_cpt_icache_dir_read += m_icache_ways;
[147]1253                    r_tgt_icache_rsp = true;
1254                    r_icache.inval(ad);
1255                    r_tgt_icache_req = false;
1256                    r_icache_fsm = r_icache_fsm_save;
[2]1257                    break;
1258                }   
1259                /////////////////////
1260            case ICACHE_CC_UPDT:
1261                {                       
[147]1262                    addr_40 ad = r_tgt_addr.read();
[2]1263                    m_cpt_icache_dir_write++;
1264                    m_cpt_icache_data_write++;
[134]1265
1266#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1267                    uint32_t word  = r_cache_word;
1268
1269                    if(r_tgt_be[word])
[147]1270                        r_icache.write(ad+word*4, r_tgt_buf[word]);
[134]1271
1272                    word ++;
1273#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1274                    for (; word<m_icache_words; ++word)
1275                        if (r_tgt_be[word] != 0)
1276                            break;
1277#endif
1278
1279                    if (word==m_icache_words)
1280                    {
[147]1281                        r_tgt_icache_req = false;
1282                        r_tgt_icache_rsp = true;
1283                        r_icache_fsm     = r_icache_fsm_save.read();
[134]1284                        word = 0;
1285                    }
1286                    r_cache_word = word;
1287#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
[2]1288                    data_t* buf    = r_tgt_buf;
1289                    for(size_t i=0; i<m_icache_words;i++){
[147]1290                        if(r_tgt_be[i]) r_icache.write( ad + i*4, buf[i]);
[2]1291                    }
[147]1292                    r_tgt_icache_req = false;
1293                    r_tgt_icache_rsp = true;
1294                    r_icache_fsm     = r_icache_fsm_save.read();
[134]1295#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1296
[2]1297                    break;
1298                }   
1299
[147]1300        } // end switch r_icache_fsm
[2]1301
[147]1302#if CC_XCACHE_WRAPPER_DEBUG
1303        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
1304            std::cout << "    * Instruction Response : " << irsp << std::endl;
1305#endif
[2]1306
1307        //////////////////////////////////////////////////////////////////////://///////////
1308        // The DCACHE FSM controls the following ressources:
1309        // - r_dcache_fsm
1310        // - r_dcache_fsm_save
1311        // - r_dcache (data cache access)
1312        // - r_dcache_addr_save
1313        // - r_dcache_wdata_save
1314        // - r_dcache_rdata_save
1315        // - r_dcache_type_save
1316        // - r_dcache_be_save
1317        // - r_dcache_cached_save
1318        // - r_dcache_miss_req set
1319        // - r_dcache_unc_req set
1320        // - r_dcache_cleanup_req set
1321        // - r_vci_rsp_data_error reset
1322        // - r_tgt_dcache_req reset
1323        // - r_wbuf write
1324        // - dreq & drsp structures for communication with the processor
1325        //
1326        // 1/ EXTERNAL REQUEST :
1327        //    There is an external request when the tgt_dcache req flip-flop is set,
1328        //    requesting a line invalidation or a line update.
1329        //    External requests are taken into account in the states  IDLE, WRITE_REQ, 
1330        //    UNC_WAIT, MISS_WAIT, and have the highest priority :
1331        //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
1332        //    goes to the CC_CHECK state to execute the requested action, and returns to the
1333        //    pre-empted state.
1334        //  2/ PROCESSOR REQUEST :
1335        //   In order to support VCI write burst, the processor requests are taken into account
1336        //   in the WRITE_REQ state as well as in the IDLE state.
1337        //   - In the IDLE state, the processor request cannot be satisfied if
1338        //   there is a cached read miss, or an uncached read.
1339        //   - In the WRITE_REQ state, the request cannot be satisfied if
1340        //   there is a cached read miss, or an uncached read,
1341        //   or when the write buffer is full.
1342        //   - In all other states, the processor request is not satisfied.
1343        //
1344        //   The cache access takes into account the cacheability_table.
1345        //   In case of processor request, there is five conditions to exit the IDLE state:
1346        //   - CACHED READ MISS => to the MISS_WAIT state (waiting the r_miss_ok signal),
1347        //     then to the MISS_UPDT state, and finally to the IDLE state.
1348        //   - UNCACHED READ  => to the UNC_WAIT state (waiting the r_miss_ok signal),
1349        //     and to the IDLE state.
1350        //   - CACHE INVALIDATE HIT => to the INVAL state for one cycle, then to IDLE state.
1351        //   - WRITE MISS => directly to the WRITE_REQ state to access the write buffer.
1352        //   - WRITE HIT => to the WRITE_UPDT state, then to the WRITE_REQ state.
1353        //
1354        // Error handling :  Read Bus Errors are synchronous events, but
1355        // Write Bus Errors are asynchronous events (processor is not frozen).
1356        // - If a Read Bus Error is detected, the VCI_RSP FSM sets the
1357        //   r_vci_rsp_data_error flip-flop, and the synchronous error is signaled
1358        //   by the DCACHE FSM.
1359        // - If a Write Bus Error is detected, the VCI_RSP FSM  signals
1360        //   the asynchronous error using the setWriteBerr() method.
1361        ///////////////////////////////////////////////////////////////////////////////////
1362
[147]1363#if CC_XCACHE_WRAPPER_DEBUG
1364        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
1365            std::cout << "    * Data        Request  : " << dreq << std::endl;
1366#endif
[2]1367
[147]1368        switch ( r_dcache_fsm ) {
[2]1369
1370                /////////////////
1371            case DCACHE_IDLE:
1372                {
[147]1373                    if ( r_tgt_dcache_req ) {   // external request
1374                        r_dcache_fsm = DCACHE_CC_CHECK;
1375                        r_dcache_fsm_save = r_dcache_fsm;
[2]1376                        break;
1377                    }
1378
[147]1379                    if ( dreq.valid ) {
1380                        PRINTF("    * <DCACHE> Have dreq\n");
[2]1381
[134]1382                        data_t      dcache_rdata       = 0;
[147]1383                        // dcache_cached and dcache_hit don't used with dreq.type == {DATA_SC, XTN_READ, XTN_WRITE}
1384                        bool        dcache_cached      = m_cacheability_table[(vci_addr_t)dreq.addr];
1385                        bool        dcache_hit         = r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
1386                        bool        dcache_cleanup_hit = r_dcache_cleanup_req and (((addr_40)dreq.addr >> (addr_40)m_dcache_words_shift) == r_dcache_cleanup_line.read());
[2]1387
[147]1388                        PRINTF("    * <DCACHE> hit %d - cached %d - cleanup_hit %d\n",dcache_hit, dcache_cached, dcache_cleanup_hit);
[134]1389                       
1390                        m_cpt_dcache_data_read += m_dcache_ways;
1391                        m_cpt_dcache_dir_read  += m_dcache_ways;
[2]1392
[147]1393                        switch( dreq.type ) {
[2]1394                            case iss_t::DATA_READ:
1395                            case iss_t::DATA_LL:
[134]1396                                {
1397                                    m_cpt_data_read++; // new dcache read
1398
1399                                    if (dcache_hit) // no special test for uncached read, because it's always miss
1400                                        {
1401                                            // address is in the cache : return the word
[147]1402                                            r_dcache_fsm = DCACHE_IDLE;
1403                                            drsp.valid   = true;
1404                                            drsp.rdata   = dcache_rdata; // return read data (cf dcache_hit)
[134]1405                                           
1406                                            // if the request is a Load Linked instruction, save request information
[147]1407                                            if(dreq.type == iss_t::DATA_LL)
[134]1408                                                {
[147]1409                                                    PRINTF("    * <DCACHE> ll_valid = true\n");
[134]1410
[147]1411                                                    r_dcache_ll_valid = true;
1412                                                    r_dcache_ll_data = dcache_rdata;
1413                                                    r_dcache_ll_addr = (vci_addr_t) dreq.addr;
[2]1414#ifdef COHERENCE_DEBUG
[147]1415                                                    std::cout << "Value returned for LL at address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
1416                                                    r_dcache.read((vci_addr_t) dreq.addr, &dcache_rdata);
1417                                                    std::cout << "Value stored at this  address : " << std::hex << dreq.addr << " data : " << std::dec << dcache_rdata<< std::endl;
[2]1418#endif
[134]1419                                                }
1420                                        }
1421                                    else
1422                                        {
1423                                            if (not dcache_cleanup_hit)
1424                                            {
[147]1425                                                CACHE_MISS_BUF_REQ_INIT(d);
[134]1426                                               
1427                                                // Miss : send signal at the CMD_FSM (via r_dcache_miss_req or r_dcache_unc_req)
1428                                                if ( dcache_cached ) {
[147]1429                                                    m_cpt_data_read_miss++;
1430                                                    m_cost_data_miss_frz++;
1431                                                    r_dcache_miss_req = true;
1432#if CC_XCACHE_WRAPPER_SELECT_VICTIM
1433                                                    r_dcache_fsm = DCACHE_MISS_VICTIM;
1434#else
1435                                                    r_dcache_fsm = DCACHE_MISS_WAIT;
1436#endif
1437                                                   
[134]1438                                                } else {
[147]1439                                                    if (not r_dcache_previous_unc.read()) // strongly order to the uncached access
[134]1440                                                    {
[147]1441                                                        r_dcache_previous_unc = true;
[134]1442                                                       
1443                                                        m_cpt_data_read_uncached++;
1444                                                        m_cost_unc_read_frz++;
[147]1445                                                        r_dcache_unc_req = true;
1446                                                        r_dcache_fsm = DCACHE_UNC_WAIT;
[134]1447                                                    }
1448                                                }
1449                                            }
1450                                        }
[2]1451                                }
1452                                break;
1453                            case iss_t::DATA_SC:
1454                            {
[147]1455                                PRINTF("    * <DCACHE> DATA_SC - ll_valid = %d\n",r_dcache_ll_valid.read());
[134]1456
[147]1457                                if (not r_dcache_previous_unc.read() and not dcache_cleanup_hit) // strongly order to the uncached access
[134]1458                                {
1459                                    //m_cpt_data_read_unc++; // instruction must read the memory in uncached mode
1460                                    m_cost_unc_read_frz++;
1461                                   
1462                                    // if previous load linked (with the same address), make a transaction
1463                                    // else, keep in IDLE state and return 1 (no OK)
[147]1464                                    if(r_dcache_ll_valid.read() and (r_dcache_ll_addr.read() == (vci_addr_t)dreq.addr)){
1465                                        PRINTF("    * <DCACHE> have previous load linked\n");
[134]1466                                       
[147]1467                                        r_dcache_previous_unc = true;
[134]1468
[147]1469                                        r_dcache_sc_req   = true;
[134]1470
[147]1471                                        CACHE_MISS_BUF_REQ_INIT(d);
1472
1473                                        r_dcache_fsm = DCACHE_SC_WAIT;
[134]1474                                    } else {
[147]1475                                        PRINTF("    * <DCACHE> don't have previous load linked\n");
[134]1476                                       
[147]1477                                        drsp.valid = true;
1478                                        drsp.rdata = 1; // SC rsp NOK
1479                                        r_dcache_ll_valid = false;
[134]1480                                    }
[2]1481                                }
[134]1482
[2]1483                                break;
1484                            }
1485                            case iss_t::XTN_READ:
1486                            case iss_t::XTN_WRITE:
[134]1487                                {
[147]1488                                    bool drsp_valid = false;
[134]1489                                    // only DCACHE INVALIDATE and SYNC request are supported
[147]1490                                    switch (dreq.addr>>2)
[134]1491                                        {
1492                                        case iss_t::XTN_DCACHE_INVAL :
1493                                            {
[147]1494                                                drsp_valid = true;
1495                                                r_dcache_fsm = DCACHE_INVAL;
[134]1496                                                break;
1497                                            }
1498                                        case iss_t::XTN_SYNC :
1499                                            {
1500                                                // Test if write buffer is already empty
1501                                                //  * gain : 1 cycle
1502                                                //  * cost : can be on the critical path
[147]1503                                                if (r_wbuf.empty())
[134]1504                                                    {
[147]1505                                                        drsp_valid = true;
1506                                                        r_dcache_fsm = DCACHE_IDLE;
[134]1507                                                    }
1508                                                else
1509                                                    {
[147]1510                                                        drsp_valid = false;
1511                                                        r_dcache_fsm = DCACHE_SYNC;
[134]1512                                                    }
1513                                                break;
1514                                            }
1515                                        default :
1516                                            {
1517                                                // std::cout << "Warning in VCI_CC_XCACHE_WRAPPER " << name() << std::endl;
[147]1518                                                // std::cout << "Unsupported  external access : " << (dreq.addr>>2) << std::endl;
[134]1519
[147]1520                                                r_dcache_fsm = DCACHE_IDLE;
[134]1521                                            }
[147]1522                                        }//end switch (dreq.addr>>2)
[134]1523
[147]1524                                    drsp.valid = drsp_valid;
1525                                    drsp.rdata = 0;
[2]1526                                    break;
[134]1527                                }
[2]1528                            case iss_t::DATA_WRITE:
[134]1529
[147]1530                                if (dcache_cached or not r_dcache_previous_unc.read()) // strongly order to the uncached access
[134]1531                                {
[147]1532                                    bool drsp_valid;
[134]1533
[147]1534                                    drsp_valid = r_wbuf.write((addr_40) dreq.addr, dreq.be, dreq.wdata, dcache_cached);
[140]1535
[147]1536                                    if (drsp_valid)
[134]1537                                    {
1538                                        m_cpt_data_write++;
1539                                       
1540                                        if (not dcache_cached)
1541                                        {
[147]1542                                            r_dcache_previous_unc = true;
[134]1543                                            m_cpt_data_write_uncached++;
1544                                        }
1545                                        else if (not dcache_hit)
1546                                            m_cpt_data_write_miss++;
1547                                       
[147]1548                                        if ( dcache_hit) {
1549                                            r_dcache_fsm = DCACHE_WRITE_UPDT;
[134]1550                                        } else {
[147]1551                                            r_dcache_fsm = DCACHE_IDLE;
[134]1552                                        }
[2]1553                                    }
[134]1554
[147]1555                                    drsp.valid = drsp_valid;
1556                                    drsp.rdata = 0;
[134]1557                                }
1558                                break;
[147]1559                        } // end switch dreq.type
[2]1560
[147]1561                        r_dcache_addr_save      = (addr_40) dreq.addr;
1562                        r_dcache_type_save      = dreq.type;
1563                        r_dcache_wdata_save     = dreq.wdata;
1564                        r_dcache_be_save        = dreq.be;
1565                        r_dcache_rdata_save     = dcache_rdata;
1566                        r_dcache_cached_save    = dcache_cached;
1567                       
1568                    } else {    // end if dreq.valid
1569                        r_dcache_fsm = DCACHE_IDLE;
[2]1570                    }
[134]1571                   
[2]1572                    break;
1573                }
1574                ///////////////////////
1575            case DCACHE_WRITE_UPDT:
1576                {
1577                    m_cpt_dcache_data_write++;
[147]1578                    data_t mask = vci_param::be2mask(r_dcache_be_save);
1579                    data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
1580                    vci_addr_t ad = r_dcache_addr_save.read();
1581                    r_dcache.write(ad, wdata);
[134]1582
[147]1583                    r_dcache_fsm = DCACHE_IDLE;
[134]1584
[2]1585                    break;
1586                }
1587                //////////////////////
[147]1588#if CC_XCACHE_WRAPPER_SELECT_VICTIM
[134]1589            case DCACHE_MISS_VICTIM:
1590                {
[147]1591                    if (not r_dcache_cleanup_req.read())
[134]1592                     {
1593                         size_t     way;
1594                         size_t     set;
[147]1595                         vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read();
[134]1596                         vci_addr_t victim;
1597                         
[147]1598                         r_dcache_cleanup_req  = r_dcache.victim_select(addr, &victim, &way, &set );
1599                         r_dcache_cleanup_line = (addr_40) victim;
1600                         r_dcache_miss_way     = way;
1601                         r_dcache_miss_set     = set;
1602                         
1603                         r_dcache_fsm = DCACHE_MISS_WAIT;
[134]1604                     }
1605                   
1606                    break;
1607                }
[147]1608#endif
[134]1609                //////////////////////
[2]1610            case DCACHE_MISS_WAIT:
1611                {
1612
[147]1613                    if ( dreq.valid ) m_cost_data_miss_frz++;
1614                    if ( r_tgt_dcache_req.read() ) {   // external request
1615                        r_dcache_fsm = DCACHE_CC_CHECK;
1616                        r_dcache_fsm_save = r_dcache_fsm;
[2]1617                        break;
1618                    }
[134]1619
[147]1620                    bool val = CACHE_MISS_BUF_RSP_VAL(d,0);
[134]1621                    if (val)
1622                    {
[147]1623                        // if (not r_dcache_inval_rsp )
1624                        //  {
1625
[134]1626                        // Miss read response and no invalidation
[147]1627                        if ( r_vci_rsp_data_error )
[134]1628                        {
[147]1629                            r_dcache_fsm = DCACHE_ERROR;
[134]1630                        }
1631                        else
1632                        {
[147]1633#if not CC_XCACHE_WRAPPER_SELECT_VICTIM
1634                            if (not r_dcache_cleanup_req.read())
1635#endif
1636                            {
1637                                r_dcache_update_addr = 0;
1638                                r_dcache_fsm         = DCACHE_MISS_UPDT;
1639                            }
[2]1640                        }
[147]1641                        //  }
1642                        // else
1643                        // {
1644                        //     r_dcache_inval_rsp  = false;
1645
1646                        //     // Miss read response and invalidation
1647                        //     if ( r_vci_rsp_data_error ) {
1648                        //         r_dcache_fsm = DCACHE_ERROR;
1649                        //     } else {
1650                        //         r_dcache_fsm = DCACHE_CC_CLEANUP;
1651                        //     }
1652                        // }
[2]1653                    }
1654                    break;
1655                }
1656                //////////////////////
1657            case DCACHE_MISS_UPDT:
[134]1658                {
[147]1659                    size_t     word = r_dcache_update_addr.read();
1660                    vci_addr_t addr = (vci_addr_t) r_dcache_addr_save.read();
1661                    size_t     way  = 0;
1662                    size_t     set  = 0;
[134]1663                   
[147]1664                    // need invalid rsp, don't select a victim
1665                    if (not r_dcache_inval_rsp )
1666                    {
1667#if CC_XCACHE_WRAPPER_SELECT_VICTIM
1668                        way = r_dcache_miss_way.read();
1669                        set = r_dcache_miss_set.read();
1670#else
1671                        // First word : select an victim !
1672                        if (word == 0)
1673                        {
1674                            vci_addr_t victim;
1675                       
1676                            // r_dcache_cleanup_req is false (condition to enter in DCACHE_MISS_UPDT
1677                            r_dcache_cleanup_req  = r_dcache.victim_select(addr, &victim, &way, &set );
1678                            r_dcache.victim_update_tag(addr, way, set);
1679                            r_dcache_cleanup_line = (addr_40) victim;
[2]1680
[147]1681                            r_dcache_miss_way     = way;
1682                            r_dcache_miss_set     = set;
1683                        }
1684                        else
1685                        {
1686                            way = r_dcache_miss_way.read();
1687                            set = r_dcache_miss_set.read();
1688                        }
1689#endif
1690                    }
1691
1692                    bool val = CACHE_MISS_BUF_RSP_VAL(d,word);
1693                    if (val)
[134]1694                    {
1695                        // m_cpt_dcache_dir_write++;
[147]1696                        // if ( ireq.valid ) m_cost_data_miss_frz++;
[134]1697
1698                        // if need invalid rsp, don't modify the cache, but pop the buf_rsp
[147]1699                        if (not r_dcache_inval_rsp )
[134]1700                        {
[147]1701                            r_dcache.write(way, set, word, CACHE_MISS_BUF_RSP_DATA(d,word));
[134]1702                            m_cpt_dcache_data_write++;
[2]1703                        }
1704
[147]1705                        CACHE_MISS_BUF_RSP_POP(d);
1706                        r_dcache_update_addr = ++word;
[134]1707                           
1708                        // if last word, finish the update
1709                        if (word >= m_dcache_words)
1710                        {
1711                            // Last word : if previous invalid_rsp, can cleanup, else update the TAG
[147]1712                            if (r_dcache_inval_rsp)
[134]1713                            {
[147]1714                                r_dcache_inval_rsp  = false;
1715                                r_dcache_fsm = DCACHE_CC_CLEANUP;
[134]1716                            }
1717                            else
1718                            {
[147]1719#if CC_XCACHE_WRAPPER_SELECT_VICTIM
1720                                r_dcache.victim_update_tag(addr, way, set);
1721#endif
1722                                r_dcache_fsm = DCACHE_IDLE;
[134]1723                            }
1724                        }
[2]1725                    }
[134]1726               
[2]1727                    break;
1728                }
1729                ////////////////////
1730            case DCACHE_UNC_WAIT:
1731                {
[147]1732                    if ( dreq.valid ) m_cost_unc_read_frz++;
1733                    if ( r_tgt_dcache_req ) {   // external request
1734                        r_dcache_fsm = DCACHE_CC_CHECK;
1735                        r_dcache_fsm_save = r_dcache_fsm;
[2]1736                        break;
1737                    }
[134]1738
[147]1739                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,0);
[134]1740
1741                    if (ok) {
[147]1742                        if ( r_vci_rsp_data_error ) {
1743                            r_dcache_fsm = DCACHE_ERROR;
[2]1744                        } else {
[147]1745                            data_t rdata = CACHE_MISS_BUF_RSP_DATA(d,0);
1746                            CACHE_MISS_BUF_RSP_POP(d);
[134]1747
[147]1748                            if(dreq.type == iss_t::DATA_LL){
1749                                PRINTF("    * <DCACHE> ll_valid = true\n");
[134]1750
[147]1751                                r_dcache_ll_valid = true;
1752                                r_dcache_ll_data = rdata;
1753                                r_dcache_ll_addr = (vci_addr_t) dreq.addr;
[2]1754                            }
[147]1755                            r_dcache_fsm = DCACHE_IDLE;
1756                            drsp.valid = true;
1757                            drsp.rdata = rdata;
[2]1758                        }
1759                    }
1760                    break;
1761                }
1762                ////////////////////
1763            case DCACHE_SC_WAIT:
1764                {
[147]1765                    if ( dreq.valid ) m_cost_unc_read_frz++;
1766                    if ( r_tgt_dcache_req ) {   // external request
1767                        r_dcache_fsm = DCACHE_CC_CHECK;
1768                        r_dcache_fsm_save = r_dcache_fsm;
[2]1769                        break;
1770                    }
[134]1771
[147]1772                    bool ok = CACHE_MISS_BUF_RSP_VAL(d,0);
[134]1773
1774                    if (ok) {
[147]1775                        if ( r_vci_rsp_data_error ) {
1776                            r_dcache_fsm = DCACHE_ERROR;
[2]1777                        } else {
[147]1778                            r_dcache_fsm = DCACHE_IDLE;
1779                            drsp.valid = true;
1780                            drsp.rdata = CACHE_MISS_BUF_RSP_DATA(d,0);
1781                            CACHE_MISS_BUF_RSP_POP(d);
1782                            r_dcache_ll_valid = false;
[2]1783                        }
1784                    }
1785                    break;
1786                }
1787
1788                //////////////////
1789            case DCACHE_ERROR:
1790                {
[147]1791                    r_dcache_fsm = DCACHE_IDLE;
1792                    r_vci_rsp_data_error = false;
1793                    drsp.error = true;
1794                    drsp.valid = true;
[2]1795                    break;
1796                }
1797                /////////////////   
1798            case DCACHE_INVAL:
1799                {
[147]1800                    if ( r_tgt_dcache_req.read() ) {   // external request
1801                        r_dcache_fsm = DCACHE_CC_CHECK;
1802                        r_dcache_fsm_save = r_dcache_fsm;
[2]1803                        break;
1804                    }
[147]1805                    if( not r_dcache_cleanup_req.read() ){
[2]1806                        m_cpt_dcache_dir_read += m_dcache_ways;
[147]1807                        vci_addr_t  ad  = r_dcache_addr_save.read();
1808                        r_dcache_cleanup_req = r_dcache.inval(ad);
1809                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
[2]1810
[147]1811                        r_dcache_fsm = DCACHE_IDLE;
[2]1812                    }
1813                    break;
1814                }
[134]1815            case DCACHE_SYNC :
1816                {
[147]1817                    if ( r_tgt_dcache_req ) {   // external request
1818                        r_dcache_fsm = DCACHE_CC_CHECK;
1819                        r_dcache_fsm_save = r_dcache_fsm;
[134]1820                        break;
1821                    }
1822
[147]1823                    if (r_wbuf.empty())
1824                        {
1825                            drsp.valid = true; // end, can accept the sync request
1826                            r_dcache_fsm = DCACHE_IDLE;
1827                        }
[134]1828                    break;
1829                }
[2]1830                /////////////////////
1831            case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
1832                {
[147]1833                    addr_40  ad          = r_tgt_addr;
[2]1834                    data_t  dcache_rdata = 0;
1835
[147]1836                    if((r_dcache_fsm_save == DCACHE_MISS_WAIT) and
1837                            ( (r_dcache_addr_save.read() & ~((m_dcache_words<<2)-1)) == (ad & ~((m_dcache_words<<2)-1)))) {
1838                        r_dcache_inval_rsp = true;
1839                        r_tgt_dcache_req = false;
[2]1840                        if(r_tgt_update){    // Also send a cleanup and answer
[147]1841                            r_tgt_dcache_rsp     = true;
[2]1842                        } else {            // Also send a cleanup but don't answer
[147]1843                            r_tgt_dcache_rsp     = false;
[2]1844                        }
[147]1845                        r_dcache_fsm = r_dcache_fsm_save;
[2]1846                    } else {
[147]1847                        bool    dcache_hit   = r_dcache.read(ad, &dcache_rdata);
[134]1848
1849                        m_cpt_dcache_data_read += m_dcache_ways;
1850                        m_cpt_dcache_dir_read += m_dcache_ways;
1851
[2]1852#ifdef COHERENCE_DEBUG
1853                        std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_CHECK, hit ? : " << dcache_hit << std::endl;
1854#endif
[134]1855                        if ( dcache_hit and r_tgt_update )
1856                        {
1857#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1858                            uint32_t word  = r_cache_word;
1859                            data_t   mask  = vci_param::be2mask(r_tgt_be[word]);
1860                            data_t   rdata = 0;
1861
[147]1862                            r_dcache.read(ad+word*4,&rdata);
[134]1863                           
1864                            r_tgt_buf[word] = (mask & r_tgt_buf[word]) | (~mask & rdata);
1865
1866                            word ++;
1867#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1868                            for (; word<m_dcache_words; ++word)
1869                                if (r_tgt_be[word] != 0)
1870                                    break;
1871#endif
1872
1873                            if (word==m_dcache_words)
1874                            {
[147]1875                                r_dcache_fsm = DCACHE_CC_UPDT;
[134]1876#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1877                                for (word=0; word<m_dcache_words; ++word)
1878                                    if (r_tgt_be[word] != 0)
1879                                        break;
1880#else
1881                                word = 0;
1882#endif
1883                            }
1884                            r_cache_word = word;
1885#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
[2]1886                            // complete the line buffer in case of update
1887                            for(size_t i=0; i<m_dcache_words; i++){
1888                                data_t rdata = 0;
[147]1889                                r_dcache.read(ad + i*4,&rdata);
[2]1890                                data_t mask = vci_param::be2mask(r_tgt_be[i]);
1891                                r_tgt_buf[i] = (mask & r_tgt_buf[i]) | (~mask & rdata);
1892                            }
[147]1893                            r_dcache_fsm = DCACHE_CC_UPDT;
[134]1894#endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1895                        } else if ( dcache_hit and not r_tgt_update ) {
[147]1896                            r_dcache_fsm = DCACHE_CC_INVAL;
[2]1897                        } else {
1898                            if(r_tgt_update){
[147]1899                                r_tgt_dcache_rsp = true;
[2]1900                            } else {
[147]1901                                r_tgt_dcache_rsp = false;
[2]1902                            }
[147]1903                            r_tgt_dcache_req = false;
1904                            r_dcache_fsm = r_dcache_fsm_save;
[2]1905                        }
1906                    }
1907                    break;
1908                }
1909                ///////////////////
1910            case DCACHE_CC_UPDT:    // update directory and data cache       
1911                {
[147]1912                    addr_40 ad = r_tgt_addr;
[134]1913
[2]1914                    m_cpt_dcache_dir_write++;
1915                    m_cpt_dcache_data_write++;
[134]1916
1917# ifdef COHERENCE_DEBUG
[2]1918                    std::cout << "PROC " << m_srcid_rw << " DCACHE_CC_UPDT, update : " << std::endl;
[134]1919# endif
1920
1921#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1922                    uint32_t word  = r_cache_word;
1923                   
1924                    if(r_tgt_be[word])
[147]1925                        r_dcache.write(ad+word*4, r_tgt_buf[word]);
[134]1926# ifdef COHERENCE_DEBUG
1927                    std::cout << " address " << std::hex << ad+word*4 << " data " << std::dec << r_tgt_buf[word] << std::endl;
1928                    data_t rdata = 0xAAAAAAAA;
[147]1929                    r_dcache.read(ad+word*4,&rdata);
[134]1930                    std::cout << "data written " << rdata << std::endl;
1931# endif
1932
1933                    word ++;
1934#if CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE_OPT
1935                    for (; word<m_dcache_words; ++word)
1936                        if (r_tgt_be[word] != 0)
1937                            break;
[2]1938#endif
[134]1939                   
1940                    if (word==m_dcache_words)
1941                    {
[147]1942                        r_tgt_dcache_req = false;
1943                        r_tgt_dcache_rsp = true;
1944                        r_dcache_fsm = r_dcache_fsm_save;
[134]1945                        word = 0;
1946                    }
1947                    r_cache_word = word;
1948#else //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
1949                    data_t* buf = r_tgt_buf;
[2]1950                    for(size_t i=0; i<m_dcache_words; i++){
1951                        if(r_tgt_be[i]) {
[147]1952                            r_dcache.write( ad + i*4, buf[i]);
[134]1953# ifdef COHERENCE_DEBUG
[2]1954                            std::cout << " address " << std::hex << ad+i*4 << " data " << std::dec << buf[i] << std::endl;
1955                            data_t rdata = 0xAAAAAAAA;
[147]1956                            r_dcache.read(ad + i*4,&rdata);
[2]1957                            std::cout << "data written " << rdata << std::endl;
[134]1958# endif //CC_XCACHE_WRAPPER_CC_UPDATE_MULTI_CYCLE
[2]1959                        }
1960                    }
[147]1961                    r_tgt_dcache_req = false;
1962                    r_tgt_dcache_rsp = true;
1963                    r_dcache_fsm = r_dcache_fsm_save;
[134]1964#endif
[2]1965                    break;
1966                }
1967                /////////////////////
1968            case DCACHE_CC_INVAL:   // invalidate a cache line
1969                {
[147]1970                    addr_40  ad      = r_tgt_addr;
1971                    r_tgt_dcache_rsp = true;
1972                    r_dcache.inval(ad);
1973                    r_tgt_dcache_req = false;
1974                    r_dcache_fsm = r_dcache_fsm_save;
[2]1975                    break;
1976                }
1977                ///////////////////
1978            case DCACHE_CC_CLEANUP:   
1979                {
[147]1980                    // external cache invalidate request
1981                    if ( r_tgt_dcache_req )   
1982                    {
1983                        r_dcache_fsm = DCACHE_CC_CHECK;
1984                        r_dcache_fsm_save = r_dcache_fsm;
1985                        break;
1986                    }       
[2]1987                    // cleanup
[147]1988                    if(not r_dcache_cleanup_req){
1989                        r_dcache_cleanup_req = true;
1990                        r_dcache_cleanup_line = r_dcache_addr_save.read() >> m_dcache_words_shift;
1991                        r_dcache_fsm = DCACHE_IDLE;
[2]1992                    }
1993                    break;
1994                }   
1995
1996        } // end switch r_dcache_fsm
[134]1997       
1998        ////////// write buffer state update  /////////////
1999        // The update() method must be called at each cycle to update the internal state.
2000        // All pending write requests must be locked in case of SYNC
[147]2001        bool wbuf_flush=(r_dcache_fsm == DCACHE_SYNC);
[134]2002#if   (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==1)
[147]2003        r_wbuf.update_multi_scan      (wbuf_flush);
[134]2004#elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==2)
[147]2005        r_wbuf.update_round_robin_scan(wbuf_flush);
[134]2006#elif (CC_XCACHE_WRAPPER_WBUF_UPDATE_SCHEME==3)
[147]2007        r_wbuf.update_one_scan        (wbuf_flush);
[134]2008#else
[147]2009        r_wbuf.update                 (wbuf_flush);
[134]2010#endif
[2]2011
[147]2012#if CC_XCACHE_WRAPPER_DEBUG
2013        if (m_cpt_total_cycles>=CC_XCACHE_WRAPPER_DEBUG_CYCLE_MIN)
2014            std::cout << "    * Data        Response : " << drsp << std::endl;
2015#endif
2016
2017        /////////// execute one iss cycle /////////////////////////////////////////////
[140]2018        {
[147]2019            uint32_t it = 0;
2020            for (size_t i=0; i<(size_t)iss_t::n_irq; i++)
2021                if(p_irq[i].read()) it |= (1<<i);
2022            m_iss.executeNCycles(1, irsp, drsp, it);
2023        }
[2]2024
[147]2025        if ( (ireq.valid and not irsp.valid) or
2026             (dreq.valid and not drsp.valid))
2027        {
2028            m_cpt_frz_cycles++;
2029#if CC_XCACHE_WRAPPER_STOP_SIMULATION
2030            m_stop_simulation_nb_frz_cycles ++;
2031           
2032            if (m_stop_simulation and (m_stop_simulation_nb_frz_cycles >= m_stop_simulation_nb_frz_cycles_max))
2033            {
2034                std::cout << std::dec << "CC_XCACHE_WRAPPER \"" << name() << "\" : cycle " << m_cpt_total_cycles << ", the cpu is frozen since " << m_stop_simulation_nb_frz_cycles << " cycles." << std::endl;
2035                ASSERT(false,"CPU : anormal activity"); // exit
2036            }
[140]2037        }
[147]2038        else
2039        {
2040            m_stop_simulation_nb_frz_cycles = 0; // reinit counter
2041#endif //CC_XCACHE_WRAPPER_STOP_SIMULATION
2042        }
[140]2043
2044
[147]2045#if CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
2046        if (dreq.valid and drsp.valid)
[2]2047        {
[147]2048            log_dcache_transaction_file
2049                << "[" << m_cpt_total_cycles << "]"
2050                << std::hex
2051                << " @ "     << std::setw(8) << (uint32_t)dreq.addr
2052                << " be "    << std::setw(1) << (uint32_t)dreq.be
2053                << " W "     << std::setw(8) << (uint32_t)dreq.wdata
2054                << " R "     << std::setw(8) << (uint32_t)drsp.rdata
2055                << " error "            << (uint32_t)drsp.error
2056                << std::dec
2057                << " "  << type_str(dreq.type);
[2]2058
[147]2059            if ((dreq.type == iss_t::XTN_READ) or
2060                (dreq.type == iss_t::XTN_WRITE))
2061                //log_dcache_transaction_file << xtn_str(dreq.addr>>2);
2062                switch (dreq.addr>>2)
2063                {
2064                case iss_t::XTN_DCACHE_INVAL : log_dcache_transaction_file << " INVAL"; break;
2065                case iss_t::XTN_SYNC         : log_dcache_transaction_file << " SYNC"; break;
2066                default                      : log_dcache_transaction_file << " invalid"; break;
2067                }                                                                           
[140]2068
[147]2069            log_dcache_transaction_file << std::endl;
[140]2070
[147]2071            // printf("[%d] @ %.8x be %.1x W %.8x R %.8x error %d - %s"
2072            //        ,(uint32_t)m_cpt_total_cycles
2073            //        ,(uint32_t)dreq.addr
2074            //        ,(uint32_t)dreq.be
2075            //        ,(uint32_t)dreq.wdata
2076            //        ,(uint32_t)drsp.rdata
2077            //        ,(uint32_t)drsp.error
2078            //        ,type_str(dreq.type));
2079            // if ((dreq.type == iss_t::XTN_READ) or
2080            //     (dreq.type == iss_t::XTN_WRITE))
2081            //     //     printf(" %s",xtn_str(dreq.addr>>2));
2082            //     switch (dreq.addr>>2)
2083            //     {
2084            //     case iss_t::XTN_DCACHE_INVAL : printf(" INVAL"); break;
2085            //     case iss_t::XTN_SYNC         : printf(" SYNC"); break;
2086            //     default                      : printf(" invalid"); break;
2087            //     }                                                                           
2088            // printf("\n");
2089        }
2090#endif //CC_XCACHE_WRAPPER_DEBUG_DCACHE_TRANSACTION
[140]2091
[2]2092        ////////////////////////////////////////////////////////////////////////////
[134]2093        // This CLEANUP FSM controls the transmission of the cleanup transactions
2094        // on the coherence network. It controls the following ressources:
2095        // - r_cleanup_fsm
2096        // - r_dcache_cleanup_req (reset)
2097        // - r_icache_cleanup_req (reset)
2098        //
2099        // This FSM handles cleanup requests from both the DCACHE FSM & ICACHE FSM
2100        // - Instruction Cleanup  : r_icache_cleanup_req
2101        // - Data Cleanup         : r_dcache_cleanup_req
2102        // In case of simultaneous requests, the data request have highest priority.
2103        // There is only one cleanup transaction at a given time (sequencial behavior)
2104        // because the same FSM controls both command & response.
2105        // The the r_icache_cleanup_req & r_dcache_cleanup_req are reset only
2106        // when the response packet is received.
2107        // Error handling :
2108        // As the coherence trafic is controled by hardware, errors are not reported
2109        // to software : In case of errors, the simulation stops.
2110        ////////////////////////////////////////////////////////////////////////////
2111
2112        switch (r_cleanup_fsm) {
2113
2114            case CLEANUP_IDLE:
[147]2115            {   
[134]2116                if ( p_vci_ini_c.cmdack )
2117                {
[147]2118                    if      (r_dcache_cleanup_req)      r_cleanup_fsm = CLEANUP_DCACHE;
2119                    else if (r_icache_cleanup_req)      r_cleanup_fsm = CLEANUP_ICACHE;
[134]2120                }
2121                break;
2122            }
[147]2123            case CLEANUP_DCACHE:
[134]2124            {
2125                if ( p_vci_ini_c.rspval )
2126                {
2127                    PRINTF("      * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1));
2128
2129                    ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_DATA_CLEANUP),
[147]2130                            "illegal response packet received for a cleanup transaction");
[160]2131                    ASSERT( (p_vci_ini_c.rerror.read()&0x1) == vci_param::ERR_NORMAL,
[134]2132                           "error signaled in a cleanup response" );
[147]2133                   
[134]2134                    r_cleanup_fsm = CLEANUP_IDLE;
[147]2135                    r_dcache_cleanup_req = false;
2136                    // m_cpt_cc_cleanup_data++; TODO
[134]2137                }
2138                break;
2139            }
[147]2140            case CLEANUP_ICACHE:
[134]2141            {
2142                if ( p_vci_ini_c.rspval )
2143                {
2144                    PRINTF("      * <CLEANUP> rerror : %d (%d)\n",(uint32_t)p_vci_ini_c.rerror.read(),0x2 & ( (1 << vci_param::E) - 1));
2145
2146                    ASSERT(p_vci_ini_c.reop and (p_vci_ini_c.rtrdid.read() == TYPE_INS_CLEANUP),
2147                           "illegal response packet received for a cleanup transaction");
[160]2148                    ASSERT( (p_vci_ini_c.rerror.read()&0x1) == vci_param::ERR_NORMAL,
[134]2149                           "error signaled in a cleanup response" );
2150                   
2151                    r_cleanup_fsm = CLEANUP_IDLE;
[147]2152                    r_icache_cleanup_req = false;
2153                    // m_cpt_cc_cleanup_ins++; TODO
[134]2154                }
2155                break;
2156            }
2157        } // end switch r_cleanup_fsm   
2158
2159        ////////////////////////////////////////////////////////////////////////////
[2]2160        // The VCI_CMD FSM controls the following ressources:
2161        // - r_vci_cmd_fsm
2162        // - r_vci_cmd_min
2163        // - r_vci_cmd_max
2164        // - r_vci_cmd_cpt
[134]2165        // - wbuf (reset)
2166        // - r_icache_miss_req (reset)
2167        // - r_icache_unc_req (reset)
2168        // - r_dcache_miss_req (reset)
2169        // - r_dcache_sc_req (reset)
[2]2170        //
2171        // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
2172        // There is 7 request types, with the following priorities :
[134]2173        // 1 - Data Read Miss         : r_dcache_miss_req and miss in the write buffer
2174        // 2 - Data Read Uncachable   : r_dcache_unc_req  and miss in the write buffer
2175        // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
2176        // 4 - Instruction Uncachable : r_icache_unc_req  and miss in the write buffer
2177        // 5 - Data Write             : r_wbuf.rok()     
2178        // 6 - Data Store Conditionnal: r_dcache_sc_req
[2]2179        // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM
2180        // and RSP_FSM exit simultaneously the IDLE state.
2181        //
2182        // VCI formats:
2183        // According to the VCI advanced specification, all read requests packets
2184        // (read Uncached, Miss data, Miss instruction) are one word packets.
2185        // For write burst packets, all words must be in the same cache line,
2186        // and addresses must be contiguous (the BE field is 0 in case of "holes").
2187        //////////////////////////////////////////////////////////////////////////////
2188
[134]2189        r_vci_cmd_dcache_prior = not r_vci_cmd_dcache_prior;
2190
[2]2191        switch (r_vci_cmd_fsm) {
2192
2193            case CMD_IDLE:
[134]2194                {
2195                // if (r_vci_rsp_fsm != RSP_IDLE) break;
[2]2196
[147]2197                size_t  min;
2198                size_t  max;
2199
[2]2200                r_vci_cmd_cpt = 0;
[134]2201
2202                // Requests :
2203
2204                // multi_write_buffer access is conditionnal with dcache_miss_req and icache_miss_req
2205
[143]2206#if   (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==1)
[147]2207                //  1) two access authorized
2208                bool dcache_miss_req =  r_dcache_miss_req;
2209                bool icache_miss_req =  r_icache_miss_req;
[143]2210#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==2)
[147]2211                //  2) one access with static priority (dcache prior)
2212                bool dcache_miss_req = r_dcache_miss_req; // dcache prior
2213                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
[134]2214#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==3)
[147]2215                //  3) one access with static priority (icache prior)
2216                bool icache_miss_req = r_icache_miss_req;
2217                bool dcache_miss_req = not icache_miss_req and r_dcache_miss_req; // dcache prior
2218#elif (CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY==4)
2219                //  4) one access with round robin priority
2220                bool dcache_miss_req = ((r_dcache_miss_req and not r_icache_miss_req) or // only dcache
2221                                        (r_dcache_miss_req and r_vci_cmd_dcache_prior)); // dcache prior
2222                bool icache_miss_req = not dcache_miss_req and r_icache_miss_req;
[134]2223#else
2224#error "Invalid value to CC_XCACHE_WRAPPER_VCI_CMD_PRIORITY"
2225#endif
2226                // 1 - Data Read
[147]2227                if (dcache_miss_req and r_wbuf.miss(r_dcache_addr_save))
[134]2228                {
[147]2229                    r_vci_cmd_fsm = CMD_DATA_MISS;
2230                    r_dcache_miss_req = false;
[134]2231                    m_cpt_dmiss_transaction++;
2232                }
2233
2234                // 2 - Data Read Uncachable
[147]2235                else if ( r_dcache_unc_req )
[134]2236                {
[147]2237                    r_vci_cmd_fsm = CMD_DATA_UNC;
2238                    r_dcache_unc_req = false;
2239                 // m_cpt_data_unc_transaction++;
[134]2240                }
2241
2242                // 3 - Instruction Miss
[147]2243                else if (icache_miss_req and r_wbuf.miss(r_icache_addr_save))
[134]2244                {
[147]2245                    r_vci_cmd_fsm = CMD_INS_MISS;
2246                    r_icache_miss_req = false;
[2]2247                    m_cpt_imiss_transaction++;
[134]2248                }
2249
2250                // 4 - Instruction Uncachable
[147]2251                else if ( r_icache_unc_req )
[134]2252                {
[147]2253                    r_vci_cmd_fsm = CMD_INS_UNC;
2254                    r_icache_unc_req = false;
[134]2255                 // m_cpt_ins_unc_transaction++;
2256                }
2257
2258                // 5 - Data Write
[147]2259                else if ( r_wbuf.rok(&min, &max) )
[134]2260                {
[147]2261                    r_vci_cmd_fsm = CMD_DATA_WRITE;
2262                    r_vci_cmd_cpt = min;
2263                    r_vci_cmd_min = min;
2264                    r_vci_cmd_max = max;
[134]2265                    m_cpt_data_write_transaction++;
[147]2266                    m_length_write_transaction += (max-min+1);
[134]2267                }
2268
2269                // 6 - Data Store Conditionnal
[147]2270                else if ( r_dcache_sc_req )
[134]2271                {
[147]2272                    r_vci_cmd_fsm = CMD_DATA_SC;
2273                    r_vci_cmd_max = 1;
[2]2274                    m_cpt_unc_transaction++;
[147]2275                    r_dcache_sc_req = false;
[2]2276                }
[134]2277
[2]2278                break;
[134]2279                }
[2]2280            case CMD_DATA_WRITE:
2281                if ( p_vci_ini_rw.cmdack.read() ) {
2282                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
2283                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
2284                        r_vci_cmd_fsm = CMD_IDLE ;
[147]2285                        r_wbuf.sent() ;
[2]2286                    }
2287                }
2288                break;
2289
2290            case CMD_DATA_SC:
2291                if ( p_vci_ini_rw.cmdack.read() ) {
2292                    r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
2293                    if (r_vci_cmd_cpt == r_vci_cmd_max) {
2294                        r_vci_cmd_fsm = CMD_IDLE ;
2295                    }
2296                }
2297                break;
2298            case CMD_INS_MISS:
2299            case CMD_INS_UNC:
2300            case CMD_DATA_MISS:
2301            case CMD_DATA_UNC:
2302                if ( p_vci_ini_rw.cmdack.read() ) {
2303                    r_vci_cmd_fsm = CMD_IDLE;
2304                }
2305                break;
2306
2307        } // end  switch r_vci_cmd_fsm
2308
2309        //////////////////////////////////////////////////////////////////////////
2310        // The VCI_RSP FSM controls the following ressources:
2311        // - r_vci_rsp_fsm:
2312        // - r_icache_miss_buf[m_icache_words]
2313        // - r_dcache_miss_buf[m_dcache_words]
2314        // - r_vci_rsp_data_error set
2315        // - r_vci_rsp_ins_error set
2316        // - r_vci_rsp_cpt
2317        // In order to have only one active VCI transaction, this VCI_RSP_FSM
2318        // is synchronized with the VCI_CMD FSM, and both FSMs exit the
2319        // IDLE state simultaneously.
2320        //
2321        // VCI formats:
2322        // This component accepts single word or multi-word response packets for
2323        // write response packets.
2324        //
2325        // Error handling:
2326        // This FSM analyzes the VCI error code and signals directly the
2327        // Write Bus Error.
2328        // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
2329        // flip_flop and the error is signaled by the DCACHE FSM. 
2330        // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
2331        // flip_flop and the error is signaled by the DCACHE FSM. 
2332        // In case of Cleanup Error, the simulation stops with an error message...
2333        //////////////////////////////////////////////////////////////////////////
2334
2335        switch (r_vci_rsp_fsm) {
2336
2337            case RSP_IDLE:
[134]2338
2339                if( p_vci_ini_rw.rspval.read() )
[2]2340                {
[147]2341                    PRINTF("      * <RSP> have rsp - trdid : %x\n",(uint32_t)p_vci_ini_rw.rtrdid.read());
[134]2342
2343                    r_vci_rsp_cpt = 0;
2344
2345                    if ((p_vci_ini_rw.rtrdid.read()>>(vci_param::T-1)) != 0 )
2346                        r_vci_rsp_fsm = RSP_DATA_WRITE;
2347                    else
2348                    {
2349                        switch (p_vci_ini_rw.rtrdid.read())
2350                        {
[147]2351                        case TYPE_INS_MISS     : r_vci_rsp_fsm = RSP_INS_MISS;     break;
2352                        case TYPE_INS_UNC      : r_vci_rsp_fsm = RSP_INS_UNC;      break;
2353                        case TYPE_DATA_MISS    : r_vci_rsp_fsm = RSP_DATA_MISS;    break;
2354                        case TYPE_DATA_UNC     : r_vci_rsp_fsm = RSP_DATA_UNC;     break;
2355                        case TYPE_DATA_SC      : r_vci_rsp_fsm = RSP_DATA_SC;      break;
[134]2356                        default :
2357                            {
2358                                ASSERT(false, "Unexpected response");
2359                            }
2360                        }
2361                    }
[2]2362                }
2363                break;
2364
2365            case RSP_INS_MISS:
[134]2366
[2]2367                m_cost_imiss_transaction++;
[147]2368                PRINTF("      * <RSP> rspval/ack : %d - %d\n",(uint32_t)p_vci_ini_rw.rspval.read(), (uint32_t)r_vci_rsp_ack);
[2]2369
[147]2370                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
[134]2371                {
2372                    PRINTF("      * <RSP> have rsp - r_vci_rsp_cpt : %d/%d\n",(uint32_t)r_vci_rsp_cpt.read(),(uint32_t)m_icache_words);
2373                    PRINTF("      * <RSP> ins : %x\n",(int)p_vci_ini_rw.rdata.read());
2374
2375                    ASSERT( (r_vci_rsp_cpt < m_icache_words),
2376                            "The VCI response packet for instruction miss is too long" );
2377                    r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
[147]2378                    CACHE_MISS_BUF_RSP_PUSH(i,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
[134]2379                    if ( p_vci_ini_rw.reop.read() )
2380                    {
2381                        PRINTF("      * <RSP> have reop\n");
[161]2382                        ASSERT( ((r_vci_rsp_cpt.read() == m_icache_words - 1) or
[134]2383                                 p_vci_ini_rw.rerror.read() or
[147]2384                                 (r_vci_rsp_ins_error.read()&0x1)),
[134]2385                                "The VCI response packet for instruction miss is too short");
2386                        r_vci_rsp_cpt    = 0;
2387                        r_vci_rsp_fsm    = RSP_IDLE;
2388
2389                    }
[147]2390                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
[2]2391                }
2392                break;
2393
2394            case RSP_INS_UNC:
[134]2395
[2]2396                m_cost_imiss_transaction++;
[147]2397                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
[134]2398                {
2399                    ASSERT(p_vci_ini_rw.reop.read(),
2400                           "illegal VCI response packet for uncached instruction");
2401
[147]2402                    CACHE_MISS_BUF_RSP_PUSH(i,0,(data_t)p_vci_ini_rw.rdata.read());
[134]2403
2404                    r_vci_rsp_fsm = RSP_IDLE;
2405
[147]2406                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_ins_error = true;
[134]2407                }
[2]2408                break;
2409
2410            case RSP_DATA_MISS:
[134]2411
[2]2412                m_cost_dmiss_transaction++;
[147]2413                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
[134]2414                {
2415                    PRINTF("      * <RSP> have rspval - error : %d\n",(int)p_vci_ini_rw.rerror.read());
2416
2417                    ASSERT(r_vci_rsp_cpt < m_dcache_words,
2418                           "illegal VCI response packet for data read miss");
2419                    r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
2420
[147]2421                    CACHE_MISS_BUF_RSP_PUSH(d,r_vci_rsp_cpt,(data_t)p_vci_ini_rw.rdata.read());
[134]2422
2423                    if ( p_vci_ini_rw.reop.read() ) {
2424                        ASSERT( ((r_vci_rsp_cpt == m_dcache_words - 1)
2425                                 or (p_vci_ini_rw.rerror.read()&0x1)
[147]2426                                 or r_vci_rsp_data_error.read()),
[134]2427                                "illegal VCI response packet for data read miss");
2428                        r_vci_rsp_cpt     = 0;
2429                        r_vci_rsp_fsm     = RSP_IDLE;
2430                    }
[147]2431                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
[2]2432                }
2433                break;
2434
2435            case RSP_DATA_WRITE:
[147]2436
[2]2437                m_cost_write_transaction++;
[134]2438                if (p_vci_ini_rw.rspval.read())
2439                {
2440                    PRINTF("      * <RSP> have rspval - error : %d\n",(int)p_vci_ini_rw.rerror.read());
2441
2442                    ASSERT(p_vci_ini_rw.reop.read(),
2443                           "A VCI response packet must contain one flit for a write transaction");
[2]2444                    r_vci_rsp_fsm = RSP_IDLE;
[147]2445                    bool cached = r_wbuf.completed(p_vci_ini_rw.rtrdid.read() - (1<<(vci_param::T-1)) );
[134]2446
2447                    PRINTF("      * <RSP> cached : %d\n",cached);
2448
2449                    if (not cached)
[147]2450                        r_dcache_previous_unc = false;
[134]2451
[147]2452                    if ((p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL) m_iss.setWriteBerr();
[2]2453                }
2454                break;
2455
2456            case RSP_DATA_UNC:
2457                m_cost_unc_transaction++;
[147]2458                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
[134]2459                {
2460                    ASSERT(p_vci_ini_rw.reop.read(),
2461                           "illegal VCI response packet for data read uncached");
2462
[147]2463                    CACHE_MISS_BUF_RSP_PUSH(d,0,(data_t)p_vci_ini_rw.rdata.read());
[134]2464
2465                    r_vci_rsp_fsm = RSP_IDLE;
[147]2466                    r_dcache_previous_unc = false;
[134]2467
[147]2468                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
[134]2469                }
[2]2470                break;
2471
2472            case RSP_DATA_SC:
2473                m_cost_unc_transaction++;
[147]2474                if (p_vci_ini_rw.rspval.read() and r_vci_rsp_ack)
[134]2475                {
2476                    ASSERT(p_vci_ini_rw.reop.read(),
2477                           "illegal VCI response packet for data SC");
[2]2478
[147]2479                    CACHE_MISS_BUF_RSP_PUSH(d,0,(data_t)p_vci_ini_rw.rdata.read());
[134]2480
2481                    r_vci_rsp_fsm = RSP_IDLE;
[147]2482                    r_dcache_previous_unc = false;
[134]2483
[147]2484                    if ( (p_vci_ini_rw.rerror.read()&0x1) != vci_param::ERR_NORMAL ) r_vci_rsp_data_error = true;
[134]2485                }
[2]2486                break;
2487
2488        } // end switch r_vci_rsp_fsm
2489
[147]2490    } // end transition()
[2]2491
2492    //////////////////////////////////////////////////////////////////////////////////
2493    tmpl(void)::genMoore()
[90]2494    //////////////////////////////////////////////////////////////////////////////////
[2]2495    {
[134]2496
[2]2497        // VCI initiator response
[134]2498        switch ( r_cleanup_fsm.read() ) {
[147]2499
[134]2500            case CLEANUP_IDLE:
2501                p_vci_ini_c.rspack  = false;
[147]2502                p_vci_ini_c.cmdval  = r_icache_cleanup_req || r_dcache_cleanup_req;
2503                if ( r_dcache_cleanup_req )
[134]2504                {
[147]2505                    p_vci_ini_c.address =  r_dcache_cleanup_line.read() * (m_dcache_words << 2);
2506                    p_vci_ini_c.trdid   = TYPE_DATA_CLEANUP;
[134]2507                }
2508                else
2509                {
[147]2510                    p_vci_ini_c.address =  r_icache_cleanup_line.read() * (m_icache_words << 2);
2511                    p_vci_ini_c.trdid   = TYPE_INS_CLEANUP;
[134]2512                }
[147]2513                p_vci_ini_c.wdata  = 0;
2514                p_vci_ini_c.be     = 0xF;
2515                p_vci_ini_c.plen   = 4;
2516                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
2517                p_vci_ini_c.pktid  = 0;
2518                p_vci_ini_c.srcid  = m_srcid_c;
2519                p_vci_ini_c.cons   = false;
2520                p_vci_ini_c.wrap   = false;
2521                p_vci_ini_c.contig = false;
2522                p_vci_ini_c.clen   = 0;
2523                p_vci_ini_c.cfixed = false;
2524                p_vci_ini_c.eop    = true;
[134]2525                break;
[2]2526
[147]2527           case CLEANUP_DCACHE:
[134]2528                p_vci_ini_c.rspack  = true;
2529                p_vci_ini_c.cmdval  = false;
2530                p_vci_ini_c.address = 0;
2531                p_vci_ini_c.wdata  = 0;
2532                p_vci_ini_c.be     = 0;
2533                p_vci_ini_c.plen   = 0;
2534                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
2535                p_vci_ini_c.trdid  = 0;
2536                p_vci_ini_c.pktid  = 0;
2537                p_vci_ini_c.srcid  = 0;
2538                p_vci_ini_c.cons   = false;
2539                p_vci_ini_c.wrap   = false;
2540                p_vci_ini_c.contig = false;
2541                p_vci_ini_c.clen   = 0;
2542                p_vci_ini_c.cfixed = false;
2543                p_vci_ini_c.eop = false;
2544                break;
2545
[147]2546           case CLEANUP_ICACHE:
[134]2547                p_vci_ini_c.rspack  = true;
2548                p_vci_ini_c.cmdval  = false;
2549                p_vci_ini_c.address = 0;
2550                p_vci_ini_c.wdata  = 0;
2551                p_vci_ini_c.be     = 0;
2552                p_vci_ini_c.plen   = 0;
2553                p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
2554                p_vci_ini_c.trdid  = 0;
2555                p_vci_ini_c.pktid  = 0;
2556                p_vci_ini_c.srcid  = 0;
2557                p_vci_ini_c.cons   = false;
2558                p_vci_ini_c.wrap   = false;
2559                p_vci_ini_c.contig = false;
2560                p_vci_ini_c.clen   = 0;
2561                p_vci_ini_c.cfixed = false;
2562                p_vci_ini_c.eop = false;
2563                break;
2564           } // end switch r_cleanup_fsm
2565
[2]2566        // VCI initiator command
2567
2568        switch (r_vci_cmd_fsm.read() ) {
[147]2569
[2]2570            case CMD_IDLE:
2571                p_vci_ini_rw.cmdval  = false;
2572                p_vci_ini_rw.address = 0;
2573                p_vci_ini_rw.wdata   = 0;
2574                p_vci_ini_rw.be      = 0;
2575                p_vci_ini_rw.plen    = 0;
2576                p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
2577                p_vci_ini_rw.trdid   = 0;
2578                p_vci_ini_rw.pktid   = 0;
2579                p_vci_ini_rw.srcid   = 0;
2580                p_vci_ini_rw.cons    = false;
2581                p_vci_ini_rw.wrap    = false;
2582                p_vci_ini_rw.contig  = false;
2583                p_vci_ini_rw.clen    = 0;
2584                p_vci_ini_rw.cfixed  = false;
2585                p_vci_ini_rw.eop     = false;
2586
2587                break;
[147]2588
[2]2589            case CMD_DATA_UNC:
2590                p_vci_ini_rw.cmdval = true;
[147]2591                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
2592                switch( r_dcache_type_save ) {
[2]2593                    case iss_t::DATA_READ:
2594                        p_vci_ini_rw.wdata = 0;
[147]2595                        p_vci_ini_rw.be  = r_dcache_be_save.read();
[2]2596                        p_vci_ini_rw.cmd = vci_param::CMD_READ;
2597                        break;
2598                    case iss_t::DATA_LL:
2599                        p_vci_ini_rw.wdata = 0;
2600                        p_vci_ini_rw.be  = 0xF;
2601                        p_vci_ini_rw.cmd = vci_param::CMD_LOCKED_READ;
2602                        break;
2603                    default:
[134]2604                        ASSERT(false,"this should not happen");
[2]2605                }
2606                p_vci_ini_rw.plen = 4;
[134]2607                p_vci_ini_rw.trdid  = TYPE_DATA_UNC;   // data cache uncached read
[147]2608                p_vci_ini_rw.pktid  = 0;
[2]2609                p_vci_ini_rw.srcid  = m_srcid_rw;
2610                p_vci_ini_rw.cons   = false;
2611                p_vci_ini_rw.wrap   = false;
2612                p_vci_ini_rw.contig = true;
2613                p_vci_ini_rw.clen   = 0;
2614                p_vci_ini_rw.cfixed = false;
2615                p_vci_ini_rw.eop    = true;
2616
2617                break;
[147]2618
[2]2619            case CMD_DATA_SC:
2620                p_vci_ini_rw.cmdval = true;
[147]2621                p_vci_ini_rw.address = (addr_40) r_dcache_addr_save.read() & ~0x3;
[2]2622                if(r_vci_cmd_max.read() == 3){
[134]2623                    ASSERT(false, "Not handled yet");
[2]2624                } else { // r_vci_cmd_cpt == 1
2625                    switch(r_vci_cmd_cpt.read()){
2626                        case 0:
[147]2627                            p_vci_ini_rw.wdata = (uint32_t)(r_dcache_ll_data.read() & 0xFFFFFFFF);
[2]2628                            break;
2629                        case 1:
[147]2630                            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
[2]2631                            break;
2632                    }
2633                }
2634                p_vci_ini_rw.be     = 0xF;
2635                p_vci_ini_rw.cmd    = vci_param::CMD_STORE_COND;
2636                p_vci_ini_rw.plen   = 4*(r_vci_cmd_max.read()+1);
[134]2637                p_vci_ini_rw.trdid  = TYPE_DATA_SC;   // data cache uncached read
[147]2638                p_vci_ini_rw.pktid  = 0;
[2]2639                p_vci_ini_rw.srcid  = m_srcid_rw;
2640                p_vci_ini_rw.cons   = true;
2641                p_vci_ini_rw.wrap   = false;
2642                p_vci_ini_rw.contig = false;
2643                p_vci_ini_rw.clen   = 0;
2644                p_vci_ini_rw.cfixed = false;
2645                p_vci_ini_rw.eop    = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
2646
2647                break;
[147]2648
[2]2649            case CMD_DATA_WRITE:
2650                p_vci_ini_rw.cmdval  = true;
[147]2651                p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt)&~0x3;
2652                p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
2653                p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
[2]2654                p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
2655                p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
[147]2656                p_vci_ini_rw.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
2657                p_vci_ini_rw.pktid   = 0;
[2]2658                p_vci_ini_rw.srcid   = m_srcid_rw;
2659                p_vci_ini_rw.cons    = false;
2660                p_vci_ini_rw.wrap    = false;
2661                p_vci_ini_rw.contig  = true;
2662                p_vci_ini_rw.clen    = 0;
2663                p_vci_ini_rw.cfixed  = false;
2664                p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
2665
2666                break;
[147]2667
[2]2668            case CMD_DATA_MISS:
2669                p_vci_ini_rw.cmdval = true;
[147]2670                p_vci_ini_rw.address = r_dcache_addr_save.read() & (addr_40) m_dcache_yzmask;
[2]2671                p_vci_ini_rw.be     = 0xF;
2672                p_vci_ini_rw.plen   = m_dcache_words << 2;
2673                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
[134]2674                p_vci_ini_rw.trdid  = TYPE_DATA_MISS;   // data cache cached read
[147]2675                p_vci_ini_rw.pktid  = 0;
[2]2676                p_vci_ini_rw.srcid  = m_srcid_rw;
2677                p_vci_ini_rw.cons   = false;
2678                p_vci_ini_rw.wrap   = false;
2679                p_vci_ini_rw.contig = true;
2680                p_vci_ini_rw.clen   = 0;
2681                p_vci_ini_rw.cfixed = false;
2682                p_vci_ini_rw.eop = true;
2683
2684                break;
[147]2685
[2]2686            case CMD_INS_MISS:
2687                p_vci_ini_rw.cmdval = true;
[147]2688                p_vci_ini_rw.address = r_icache_addr_save.read() & (addr_40) m_icache_yzmask;
[2]2689                p_vci_ini_rw.be     = 0xF;
2690                p_vci_ini_rw.plen   = m_icache_words << 2;
2691                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
[134]2692                p_vci_ini_rw.trdid  = TYPE_INS_MISS;   // ins cache cached read
[147]2693                p_vci_ini_rw.pktid  = 0;
[2]2694                p_vci_ini_rw.srcid  = m_srcid_rw;
2695                p_vci_ini_rw.cons   = false;
2696                p_vci_ini_rw.wrap   = false;
2697                p_vci_ini_rw.contig = true;
2698                p_vci_ini_rw.clen   = 0;
2699                p_vci_ini_rw.cfixed = false;
2700                p_vci_ini_rw.eop = true;
2701
2702                break;
[147]2703
[2]2704            case CMD_INS_UNC:
2705                p_vci_ini_rw.cmdval = true;
[147]2706                p_vci_ini_rw.address = r_icache_addr_save.read() & ~0x3;
[2]2707                p_vci_ini_rw.be     = 0xF;
2708                p_vci_ini_rw.plen   = 4;
2709                p_vci_ini_rw.cmd    = vci_param::CMD_READ;
[134]2710                p_vci_ini_rw.trdid  = TYPE_INS_UNC;   // ins cache uncached read
[147]2711                p_vci_ini_rw.pktid  = 0;
[2]2712                p_vci_ini_rw.srcid  = m_srcid_rw;
2713                p_vci_ini_rw.cons   = false;
2714                p_vci_ini_rw.wrap   = false;
2715                p_vci_ini_rw.contig = true;
2716                p_vci_ini_rw.clen   = 0;
2717                p_vci_ini_rw.cfixed = false;
2718                p_vci_ini_rw.eop = true;
2719
2720                break;
[147]2721
[134]2722        } // end switch r_vci_cmd_fsm
[2]2723
[147]2724        bool ack;
[2]2725
[147]2726        switch (r_vci_rsp_fsm.read() ) {
2727        case RSP_IDLE       : ack = false; break;
2728        case RSP_DATA_WRITE : ack = true; break;
2729        case RSP_INS_MISS   :
2730        case RSP_INS_UNC    : ack = CACHE_MISS_BUF_RSP_ACK(i); break;
2731        case RSP_DATA_MISS  :
2732        case RSP_DATA_UNC   :
2733        case RSP_DATA_SC    : ack = CACHE_MISS_BUF_RSP_ACK(d); break;
2734        } // end switch r_vci_cmd_fsm
[2]2735
[147]2736        r_vci_rsp_ack       = ack;
2737        p_vci_ini_rw.rspack = ack;
2738       
[2]2739        // VCI_TGT
2740
2741        switch ( r_vci_tgt_fsm.read() ) {
2742
2743            case TGT_IDLE:
2744            case TGT_UPDT_WORD:
2745            case TGT_UPDT_DATA:
2746                p_vci_tgt.cmdack  = true;
2747                p_vci_tgt.rspval  = false;
2748                break;
2749
2750            case TGT_RSP_BROADCAST:
[147]2751                p_vci_tgt.cmdack  = false;
2752                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() and ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
2753                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2754                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2755                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2756                p_vci_tgt.rdata   = 0;
2757                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2758                p_vci_tgt.reop    = true;
2759                break;
[2]2760
2761            case TGT_RSP_ICACHE:
[147]2762                p_vci_tgt.cmdack  = false;
2763                p_vci_tgt.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
2764                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2765                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2766                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2767                p_vci_tgt.rdata   = 0;
2768                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2769                p_vci_tgt.reop    = true;
2770                break;
[2]2771
2772            case TGT_RSP_DCACHE:
[147]2773                p_vci_tgt.cmdack  = false;
2774                p_vci_tgt.rspval  = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read();
2775                p_vci_tgt.rsrcid  = r_tgt_srcid.read();
2776                p_vci_tgt.rpktid  = r_tgt_pktid.read();
2777                p_vci_tgt.rtrdid  = r_tgt_trdid.read();
2778                p_vci_tgt.rdata   = 0;
2779                p_vci_tgt.rerror  = 0x2 & ( (1 << vci_param::E) - 1); // Write OK
2780                p_vci_tgt.reop    = true;
2781                break;
[2]2782
2783            case TGT_REQ_BROADCAST:
2784            case TGT_REQ_ICACHE:
2785            case TGT_REQ_DCACHE:
2786                p_vci_tgt.cmdack  = false;
2787                p_vci_tgt.rspval  = false;
2788                break;
2789
2790        } // end switch TGT_FSM
2791    } // end genMoore()
2792
[134]2793    //////////////////////////////////////////////////////////////////////////////////
2794    tmpl(void)::stop_simulation (uint32_t nb_frz_cycles)
2795    //////////////////////////////////////////////////////////////////////////////////
2796    {
2797#if CC_XCACHE_WRAPPER_STOP_SIMULATION
2798        if (nb_frz_cycles == 0)
2799            {
2800                PRINTF("CC_XCACHE_WRAPPER \"%s\" : don't stop the simulation.\n",name().c_str());
2801                m_stop_simulation = false;
2802            }
2803        else
2804            {
2805                PRINTF("CC_XCACHE_WRAPPER \"%s\" : stop the simulation after %d cycles.\n",name().c_str(),nb_frz_cycles);
2806                m_stop_simulation = true;
2807                m_stop_simulation_nb_frz_cycles_max = nb_frz_cycles;
2808            }
2809#else
2810        std::cout << "CC_XCACHE_WRAPPER \"" << name() << "\" : flag CC_XCACHE_WRAPPER_STOP_SIMULATION is unset, you can't use stop_simulation." << std::endl;
2811#endif // CC_XCACHE_WRAPPER_STOP_SIMULATION
2812       
2813    }
2814
[2]2815}} // end namespace
2816
2817// Local Variables:
2818// tab-width: 4
2819// c-basic-offset: 4
2820// c-file-offsets:((innamespace . 0)(inline-open . 0))
2821// indent-tabs-mode: nil
2822// End:
2823
2824// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.