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

Last change on this file since 188 was 188, checked in by alain, 12 years ago

A maitainable version removing the multi-caches feature.

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