source: trunk/modules/vci_cc_vcache_wrapper2_ring/caba/source/src/vci_cc_vcache_wrapper2_ring.cpp @ 2

Last change on this file since 2 was 2, checked in by nipo, 14 years ago

Import TSAR modules in TSAR's own svn

  • 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: 192.9 KB
Line 
1/* -*- c++ -*-
2 * File : vci_cc_vcache_wrapper2_ring.cpp
3 * Copyright (c) UPMC, Lip6, SoC
4 * Authors : Alain GREINER, Yang GAO
5 *
6 * SOCLIB_LGPL_HEADER_BEGIN
7 *
8 * This file is part of SoCLib, GNU LGPLv2.1.
9 *
10 * SoCLib is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; version 2.1 of the License.
13 *
14 * SoCLib is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with SoCLib; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 * SOCLIB_LGPL_HEADER_END
25 */
26
27#include <cassert>
28#include "arithmetics.h"
29#include "../include/vci_cc_vcache_wrapper2_ring.h"
30
31namespace soclib {
32namespace caba {
33
34#ifdef SOCLIB_MODULE_DEBUG
35namespace {
36const char *icache_fsm_state_str[] = {
37        "ICACHE_IDLE",
38        "ICACHE_BIS",       
39        "ICACHE_TLB1_READ", 
40        "ICACHE_TLB1_WRITE", 
41        "ICACHE_TLB1_UPDT", 
42        "ICACHE_TLB2_READ", 
43        "ICACHE_TLB2_WRITE", 
44        "ICACHE_TLB2_UPDT", 
45        "ICACHE_SW_FLUSH",
46        "ICACHE_CACHE_FLUSH",
47        "ICACHE_TLB_INVAL", 
48        "ICACHE_CACHE_INVAL",
49        "ICACHE_MISS_WAIT",
50        "ICACHE_UNC_WAIT", 
51        "ICACHE_MISS_UPDT", 
52        "ICACHE_ERROR",         
53        "ICACHE_CC_INVAL",
54        "ICACHE_TLB_CC_INVAL",       
55        "ICACHE_TLB_FLUSH",
56    };
57const char *dcache_fsm_state_str[] = {
58        "DCACHE_IDLE",       
59        "DCACHE_BIS",   
60        "DCACHE_DTLB1_READ_CACHE",
61        "DCACHE_TLB1_LL_WAIT",
62        "DCACHE_TLB1_SC_WAIT",   
63        "DCACHE_TLB1_READ",
64        "DCACHE_TLB1_READ_UPDT", 
65        "DCACHE_TLB1_UPDT",
66        "DCACHE_DTLB2_READ_CACHE",
67        "DCACHE_TLB2_LL_WAIT",
68        "DCACHE_TLB2_SC_WAIT",   
69        "DCACHE_TLB2_READ",
70        "DCACHE_TLB2_READ_UPDT", 
71        "DCACHE_TLB2_UPDT",   
72        "DCACHE_CTXT_SWITCH",   
73        "DCACHE_ICACHE_FLUSH",
74        "DCACHE_DCACHE_FLUSH",
75        "DCACHE_ITLB_INVAL",
76        "DCACHE_DTLB_INVAL",
77        "DCACHE_ICACHE_INVAL",
78        "DCACHE_DCACHE_INVAL",
79        "DCACHE_DCACHE_SYNC",
80        "DCACHE_LL_DIRTY_WAIT",
81        "DCACHE_SC_DIRTY_WAIT",
82        "DCACHE_WRITE_UPDT",
83        "DCACHE_WRITE_DIRTY",
84        "DCACHE_WRITE_REQ", 
85        "DCACHE_MISS_WAIT", 
86        "DCACHE_MISS_UPDT", 
87        "DCACHE_UNC_WAIT",   
88        "DCACHE_ERROR",
89        "DCACHE_ITLB_READ",
90        "DCACHE_ITLB_UPDT",
91        "DCACHE_ITLB_LL_WAIT",       
92        "DCACHE_ITLB_SC_WAIT",       
93        "DCACHE_CC_CHECK",
94        "DCACHE_CC_INVAL",
95        "DCACHE_CC_UPDT",
96        "DCACHE_CC_NOP",
97        "DCACHE_TLB_CC_INVAL",
98        "DCACHE_ITLB_CLEANUP",
99    };
100const char *cmd_fsm_state_str[] = {
101        "CMD_IDLE",           
102        "CMD_ITLB_READ",
103        "CMD_ITLB_ACC_LL",               
104        "CMD_ITLB_ACC_SC",               
105        "CMD_INS_MISS",     
106        "CMD_INS_UNC",     
107        "CMD_DTLB_READ",   
108        "CMD_DTLB_ACC_LL",           
109        "CMD_DTLB_ACC_SC",           
110        "CMD_DTLB_DIRTY_LL",         
111        "CMD_DTLB_DIRTY_SC",         
112        "CMD_DATA_UNC",     
113        "CMD_DATA_MISS",   
114        "CMD_DATA_WRITE",
115    };
116const char *rsp_fsm_state_str[] = {
117        "RSP_IDLE",                 
118        "RSP_ITLB_READ",             
119        "RSP_ITLB_ACC_LL",               
120        "RSP_ITLB_ACC_SC",               
121        "RSP_INS_MISS",   
122        "RSP_INS_UNC",           
123        "RSP_DTLB_READ",           
124        "RSP_DTLB_ACC_LL",           
125        "RSP_DTLB_ACC_SC",           
126        "RSP_DTLB_DIRTY_LL",         
127        "RSP_DTLB_DIRTY_SC",         
128        "RSP_DATA_MISS",             
129        "RSP_DATA_UNC",             
130        "RSP_DATA_WRITE", 
131    };
132const char *cmd_cleanup_fsm_state_str[] = {
133        "CMD_CLEANUP_INS_IDLE",           
134        "CMD_CLEANUP_DATA_IDLE",           
135        "CMD_CLEANUP_INS",   
136        "CMD_CLEANUP_DATA",     
137    };
138const char *rsp_cleanup_fsm_state_str[] = {
139        "RSP_CLEANUP_INS_IDLE",                 
140        "RSP_CLEANUP_DATA_IDLE",                 
141        "RSP_CLEANUP_INS",   
142        "RSP_CLEANUP_DATA",       
143    };
144const char *tgt_fsm_state_str[] = {
145        "TGT_IDLE",
146        "TGT_UPDT_WORD",
147        "TGT_UPDT_DATA",
148        "TGT_REQ_BROADCAST",
149        "TGT_REQ_DCACHE",
150        "TGT_RSP_BROADCAST",
151        "TGT_RSP_DCACHE",
152    }; 
153const char *inval_itlb_fsm_state_str[] = {
154        "INVAL_ITLB_IDLE",       
155        "INVAL_ITLB_CHECK"  ,
156        "INVAL_ITLB_INVAL",     
157        "INVAL_ITLB_CLEAR",           
158    };
159const char *inval_dtlb_fsm_state_str[] = {
160        "INVAL_DTLB_IDLE",       
161        "INVAL_DTLB_CHECK",
162        "INVAL_DTLB_INVAL",   
163        "INVAL_DTLB_CLEAR",         
164    };
165}
166#endif
167
168#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapper2Ring<vci_param, iss_t>
169
170using soclib::common::uint32_log2;
171
172/***********************************************/
173tmpl(/**/)::VciCcVCacheWrapper2Ring(
174    sc_module_name name,
175    int proc_id,
176    const soclib::common::MappingTable &mtp,
177    const soclib::common::MappingTable &mtc,
178    const soclib::common::IntTab &initiator_index_rw,
179    const soclib::common::IntTab &initiator_index_c,
180    const soclib::common::IntTab &target_index,
181    size_t itlb_ways,
182    size_t itlb_sets,
183    size_t dtlb_ways,
184    size_t dtlb_sets,
185    size_t icache_ways,
186    size_t icache_sets,
187    size_t icache_words,
188    size_t dcache_ways,
189    size_t dcache_sets,
190    size_t dcache_words,   
191    size_t write_buf_size )
192/***********************************************/
193    : soclib::caba::BaseModule(name),
194
195      p_clk("clk"),
196      p_resetn("resetn"),
197      p_vci_ini_rw("vci_ini_rw"),
198      p_vci_ini_c("vci_ini_c"),
199      p_vci_tgt("vci_tgt"),
200
201      m_cacheability_table(mtp.getCacheabilityTable()),
202      m_segment(mtc.getSegment(target_index)),
203      m_iss(this->name(), proc_id),
204      m_srcid_rw(mtp.indexForId(initiator_index_rw)),
205      m_srcid_c(mtc.indexForId(initiator_index_c)),
206
207      m_itlb_ways(itlb_ways),
208      m_itlb_sets(itlb_sets),
209
210      m_dtlb_ways(dtlb_ways),
211      m_dtlb_sets(dtlb_sets),
212
213      m_icache_ways(icache_ways),
214      m_icache_sets(icache_sets),
215      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
216      m_icache_words(icache_words),
217
218      m_dcache_ways(dcache_ways),
219      m_dcache_sets(dcache_sets),
220      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
221      m_dcache_words(dcache_words),
222
223      m_write_buf_size(write_buf_size),
224      m_paddr_nbits(vci_param::N),
225
226      icache_tlb(itlb_ways,itlb_sets,vci_param::N),
227      dcache_tlb(dtlb_ways,dtlb_sets,vci_param::N),
228
229      r_dcache_fsm("r_dcache_fsm"),
230      r_dcache_paddr_save("r_dcache_paddr_save"),
231      r_dcache_wdata_save("r_dcache_wdata_save"),
232      r_dcache_rdata_save("r_dcache_rdata_save"),
233      r_dcache_type_save("r_dcache_type_save"),
234      r_dcache_be_save("r_dcache_be_save"),
235      r_dcache_cached_save("r_dcache_cached_save"),
236      r_dcache_tlb_paddr("r_dcache_tlb_paddr"),
237      r_dcache_miss_req("r_dcache_miss_req"),
238      r_dcache_unc_req("r_dcache_unc_req"),
239      r_dcache_write_req("r_dcache_write_req"),
240      r_dcache_tlb_read_req("r_dcache_tlb_read_req"),
241      r_dcache_tlb_ll_acc_req("r_dcache_tlb_ll_acc_req"),       
242      r_dcache_tlb_sc_acc_req("r_dcache_tlb_sc_acc_req"),       
243      r_dcache_tlb_ll_dirty_req("r_dcache_tlb_ll_dirty_req"),   
244      r_dcache_tlb_sc_dirty_req("r_dcache_tlb_sc_dirty_req"),
245      r_dcache_tlb_ptba_read("r_dcache_tlb_ptba_read"),
246      r_dcache_xtn_req("r_dcache_xtn_req"),
247
248      r_dcache_fsm_save("r_dcache_fsm_save"),
249      r_dcache_cleanup_req("r_dcache_cleanup_req"),
250      r_dcache_inval_rsp("r_dcache_inval_rsp"),
251
252      r_icache_fsm("r_icache_fsm"),
253      r_icache_paddr_save("r_icache_paddr_save"),
254      r_icache_miss_req("r_icache_miss_req"),
255      r_icache_unc_req("r_icache_unc_req"),
256      r_dcache_itlb_read_req("r_dcache_itlb_read_req"),
257      r_dcache_itlb_ll_acc_req("r_dcache_itlb_ll_acc_req"),     
258      r_dcache_itlb_sc_acc_req("r_dcache_itlb_sc_acc_req"),
259      r_itlb_read_dcache_req("r_itlb_read_dcache_req"),
260      r_itlb_acc_dcache_req("r_itlb_acc_dcache_req"),
261      r_dcache_rsp_itlb_error("r_dcache_rsp_itlb_error"),
262
263      r_icache_fsm_save("r_icache_fsm_save"),
264      r_icache_cleanup_req("r_icache_cleanup_req"),
265      r_icache_inval_rsp("r_icache_inval_rsp"),
266
267      r_vci_cmd_fsm("r_vci_cmd_fsm"),
268      r_vci_cmd_min("r_vci_cmd_min"),
269      r_vci_cmd_max("r_vci_cmd_max"),
270      r_vci_cmd_cpt("r_vci_cmd_cpt"),
271
272      r_vci_rsp_fsm("r_vci_rsp_fsm"),
273      r_vci_rsp_cpt("r_vci_rsp_cpt"),
274      r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
275      r_vci_rsp_data_error("r_vci_rsp_data_error"),
276
277      r_vci_cmd_cleanup_fsm("r_vci_cmd_cleanup_fsm"),
278      r_vci_rsp_cleanup_fsm("r_vci_rsp_cleanup_fsm"),
279
280      r_vci_tgt_fsm("r_vci_tgt_fsm"),
281      r_tgt_addr("r_tgt_addr"),
282      r_tgt_word("r_tgt_word"),
283      r_tgt_update("r_tgt_update"),
284      r_tgt_srcid("r_tgt_srcid"),
285      r_tgt_pktid("r_tgt_pktid"),
286      r_tgt_trdid("r_tgt_trdid"),
287      r_tgt_icache_req("r_tgt_icache_req"),
288      r_tgt_dcache_req("r_tgt_dcache_req"),
289
290      r_inval_itlb_fsm("r_inval_itlb_fsm"),         
291      r_dcache_itlb_inval_req("r_dcache_itlb_inval_req"),
292      r_dcache_itlb_inval_line("r_dcache_itlb_inval_line"),
293      r_itlb_cc_check_end("r_itlb_cc_check_end"),
294      r_ccinval_itlb_way("r_ccinval_itlb_way"),
295      r_ccinval_itlb_set("r_ccinval_itlb_set"),
296      r_icache_inval_tlb_rsp("r_icache_inval_tlb_rsp"),
297      r_icache_tlb_nline("r_icache_tlb_nline"),
298
299      r_inval_dtlb_fsm("r_inval_dtlb_fsm"),         
300      r_dcache_dtlb_inval_req("r_dcache_dtlb_inval_req"),
301      r_dcache_dtlb_inval_line("r_dcache_dtlb_inval_line"),
302      r_dtlb_cc_check_end("r_dtlb_cc_check_end"),
303      r_ccinval_dtlb_way("r_ccinval_dtlb_way"),
304      r_ccinval_dtlb_set("r_ccinval_dtlb_set"),
305      r_dcache_inval_tlb_rsp("r_dcache_inval_tlb_rsp"),
306      r_dcache_tlb_nline("r_dcache_tlb_nline"),
307
308      r_dcache_itlb_cleanup_req("r_dcache_itlb_cleanup_req"),
309      r_dcache_itlb_cleanup_line("r_dcache_itlb_cleanup_line"),
310
311      r_dcache_dtlb_cleanup_req("r_dcache_dtlb_cleanup_req"),
312      r_dcache_dtlb_cleanup_line("r_dcache_dtlb_cleanup_line"),
313
314      r_wbuf("wbuf", write_buf_size ),
315      r_icache("icache", icache_ways, icache_sets, icache_words),
316      r_dcache("dcache", dcache_ways, dcache_sets, dcache_words)
317{
318    r_icache_miss_buf = new data_t[icache_words];
319    r_dcache_miss_buf = new data_t[dcache_words];
320    r_tgt_buf         = new data_t[dcache_words];
321    r_tgt_val         = new bool[dcache_words];
322    r_dcache_in_itlb  = new bool[dcache_ways*dcache_sets];           
323    r_dcache_in_dtlb  = new bool[dcache_ways*dcache_sets];         
324
325    SC_METHOD(transition);
326    dont_initialize();
327    sensitive << p_clk.pos();
328 
329    SC_METHOD(genMoore);
330    dont_initialize();
331    sensitive << p_clk.neg();
332
333    typename iss_t::CacheInfo cache_info;
334    cache_info.has_mmu = true;
335    cache_info.icache_line_size = icache_words*sizeof(data_t);
336    cache_info.icache_assoc = icache_ways;
337    cache_info.icache_n_lines = icache_sets;
338    cache_info.dcache_line_size = dcache_words*sizeof(data_t);
339    cache_info.dcache_assoc = dcache_ways;
340    cache_info.dcache_n_lines = dcache_sets;
341    m_iss.setCacheInfo(cache_info);
342}
343
344/////////////////////////////////////
345tmpl(/**/)::~VciCcVCacheWrapper2Ring()
346/////////////////////////////////////
347{
348    delete [] r_icache_miss_buf;
349    delete [] r_dcache_miss_buf;
350    delete [] r_tgt_val;
351    delete [] r_tgt_buf;
352    delete [] r_dcache_in_itlb;           
353    delete [] r_dcache_in_dtlb;         
354}
355
356////////////////////////
357tmpl(void)::print_cpi()
358////////////////////////
359{
360    std::cout << name() << " CPI = "
361        << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
362}
363
364////////////////////////
365tmpl(void)::print_stats()
366////////////////////////
367{
368    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
369    std::cout << name() << std::endl
370              << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl
371              << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl
372              << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
373              << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl
374              << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl
375              << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl   
376              << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl
377              << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl
378              << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
379              << "- DMISS COST             = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
380              << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
381              << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
382              << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
383              << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl
384              << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
385              << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
386              << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
387              << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
388              << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
389              << "- ITLB WRITE TRANSACTION = " << (float)m_cost_itlb_write_transaction/m_cpt_itlb_write_transaction << std::endl
390              << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/(m_cpt_ins_tlb_miss+m_cpt_ins_tlb_write_et) << std::endl
391              << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl
392              << "- DTLB WRITE TRANSACTION = " << (float)m_cost_dtlb_write_transaction/m_cpt_dtlb_write_transaction << std::endl
393              << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/(m_cpt_data_tlb_miss+m_cpt_data_tlb_write_et+m_cpt_data_tlb_write_dirty) << std::endl;
394}
395
396/*************************************************/
397tmpl(void)::transition()
398/*************************************************/
399{
400    if ( ! p_resetn.read() )
401    {
402        m_iss.reset();
403
404        r_dcache_fsm = DCACHE_IDLE;
405        r_icache_fsm = ICACHE_IDLE;
406        r_vci_cmd_fsm = CMD_IDLE;
407        r_vci_rsp_fsm = RSP_IDLE;
408        r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS_IDLE;
409        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS_IDLE;
410        r_vci_tgt_fsm = TGT_IDLE;
411        r_inval_itlb_fsm = INVAL_ITLB_IDLE;         
412        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;         
413
414        // write buffer & caches
415        r_wbuf.reset();
416        r_icache.reset();
417        r_dcache.reset();
418
419        icache_tlb.reset();   
420        dcache_tlb.reset();   
421
422        std::memset(r_dcache_in_itlb, 0, sizeof(*r_dcache_in_itlb)*m_icache_ways*m_icache_sets);
423        std::memset(r_dcache_in_dtlb, 0, sizeof(*r_dcache_in_dtlb)*m_dcache_ways*m_dcache_sets);
424
425        r_mmu_mode = ALL_DEACTIVE;
426
427        r_icache_miss_req         = false;
428        r_icache_unc_req          = false;
429        r_dcache_itlb_read_req    = false;
430
431        r_itlb_read_dcache_req    = false;     
432        r_itlb_acc_dcache_req     = false;   
433        r_dcache_rsp_itlb_error   = false;
434 
435        r_dcache_miss_req         = false;
436        r_dcache_unc_req          = false;
437        r_dcache_write_req        = false;
438        r_dcache_tlb_read_req     = false;
439        r_dcache_tlb_ptba_read    = false;
440        r_dcache_xtn_req          = false;
441        r_dcache_llsc_reserved    = false;
442
443        r_dcache_tlb_ll_acc_req   = false;   
444        r_dcache_tlb_sc_acc_req   = false;   
445        r_dcache_tlb_ll_dirty_req = false;   
446        r_dcache_tlb_sc_dirty_req = false;   
447        r_dcache_itlb_ll_acc_req  = false;   
448        r_dcache_itlb_sc_acc_req  = false;   
449
450        r_icache_cleanup_req      = false;
451        r_dcache_cleanup_req      = false;
452
453        r_tgt_icache_req          = false;
454        r_tgt_dcache_req          = false;
455
456        r_icache_inval_rsp        = false;
457        r_dcache_inval_rsp        = false;
458
459        r_dcache_dirty_save       = false;
460        r_dcache_hit_p_save       = false;
461
462        r_icache_buf_unc_valid    = false;
463        r_dcache_buf_unc_valid    = false;
464
465        r_vci_rsp_ins_error       = false;
466        r_vci_rsp_data_error      = false;
467
468        r_icache_id1_save         = 0;
469        r_icache_ppn_save         = 0;
470        r_icache_vpn_save         = 0;
471        r_itlb_translation_valid  = false;
472
473        r_dcache_id1_save         = 0;
474        r_dcache_ppn_save         = 0;
475        r_dcache_vpn_save         = 0;
476        r_dtlb_translation_valid  = false;
477
478        r_icache_ptba_ok          = false;
479        r_dcache_ptba_ok          = false;
480
481        r_icache_error_type       = MMU_NONE;
482        r_dcache_error_type       = MMU_NONE;
483
484        // coherence registers
485        r_icache_way              = 0;
486        r_icache_set              = 0;
487        r_icache_cleanup_req      = false;
488        r_icache_inval_rsp        = false;
489
490        r_dcache_way              = 0;
491        r_dcache_set              = 0;
492        r_dcache_cleanup_req      = false;
493        r_dcache_inval_rsp        = false;
494
495        r_itlb_inval_req          = false;
496        r_dcache_itlb_inval_req   = false;
497        r_itlb_cc_check_end       = false;
498        r_ccinval_itlb_way        = 0;
499        r_ccinval_itlb_set        = 0;
500        r_icache_inval_tlb_rsp    = false;
501
502        r_dcache_dtlb_inval_req   = false;
503        r_dtlb_cc_check_end       = false;
504        r_ccinval_dtlb_way        = 0;
505        r_ccinval_dtlb_set        = 0;
506        r_dcache_inval_tlb_rsp    = false;
507
508        r_dcache_itlb_cleanup_req = false;
509        r_dcache_dtlb_cleanup_req = false;
510
511        r_dcache_cc_check         = false;
512
513        // activity counters
514        m_cpt_dcache_data_read  = 0;
515        m_cpt_dcache_data_write = 0;
516        m_cpt_dcache_dir_read   = 0;
517        m_cpt_dcache_dir_write  = 0;
518        m_cpt_icache_data_read  = 0;
519        m_cpt_icache_data_write = 0;
520        m_cpt_icache_dir_read   = 0;
521        m_cpt_icache_dir_write  = 0;
522
523        m_cpt_frz_cycles   = 0;
524        m_cpt_total_cycles = 0;
525
526        m_cpt_read         = 0;
527        m_cpt_write        = 0;
528        m_cpt_data_miss    = 0;
529        m_cpt_ins_miss     = 0;
530        m_cpt_unc_read     = 0;
531        m_cpt_write_cached = 0;
532        m_cpt_ins_read     = 0;
533
534        m_cost_write_frz     = 0;
535        m_cost_data_miss_frz = 0;
536        m_cost_unc_read_frz  = 0;
537        m_cost_ins_miss_frz  = 0;
538
539        m_cpt_imiss_transaction = 0;
540        m_cpt_dmiss_transaction = 0;
541        m_cpt_unc_transaction   = 0;
542        m_cpt_write_transaction = 0;
543
544        m_cost_imiss_transaction   = 0;
545        m_cost_dmiss_transaction   = 0;
546        m_cost_unc_transaction     = 0;
547        m_cost_write_transaction   = 0;
548        m_length_write_transaction = 0;
549
550        m_cpt_ins_tlb_read         = 0;             
551        m_cpt_ins_tlb_miss         = 0;             
552        m_cpt_ins_tlb_write_et     = 0;         
553
554        m_cpt_data_tlb_read        = 0;           
555        m_cpt_data_tlb_miss        = 0;           
556        m_cpt_data_tlb_write_et    = 0;       
557        m_cpt_data_tlb_write_dirty = 0;   
558
559        m_cost_ins_tlb_miss_frz    = 0;     
560        m_cost_data_tlb_miss_frz   = 0;     
561
562        m_cpt_itlbmiss_transaction   = 0;   
563        m_cpt_itlb_write_transaction = 0; 
564        m_cpt_dtlbmiss_transaction   = 0; 
565        m_cpt_dtlb_write_transaction = 0; 
566 
567        m_cost_itlbmiss_transaction   = 0;   
568        m_cost_itlb_write_transaction = 0; 
569        m_cost_dtlbmiss_transaction   = 0;   
570        m_cost_dtlb_write_transaction = 0;   
571        return;
572    }
573
574
575#ifdef SOCLIB_MODULE_DEBUG
576std::cout << name() << "cycle = " << m_cpt_total_cycles 
577          << " tgt fsm: " << tgt_fsm_state_str[r_vci_tgt_fsm]
578          << " dcache fsm: " << dcache_fsm_state_str[r_dcache_fsm]
579          << " icache fsm: " << icache_fsm_state_str[r_icache_fsm]
580          << " cmd fsm: " << cmd_fsm_state_str[r_vci_cmd_fsm]
581          << " rsp fsm: " << rsp_fsm_state_str[r_vci_rsp_fsm]
582          << " cmd cleanup fsm: " << cmd_cleanup_fsm_state_str[r_vci_cmd_cleanup_fsm]
583          << " rsp cleanup fsm: " << rsp_cleanup_fsm_state_str[r_vci_rsp_cleanup_fsm]
584          << " inval itlb fsm: " << inval_itlb_fsm_state_str[r_inval_itlb_fsm]
585          << " inval dtlb fsm: " << inval_dtlb_fsm_state_str[r_inval_dtlb_fsm] << std::endl;
586#endif
587    m_cpt_total_cycles++;
588
589    typename iss_t::InstructionRequest ireq = ISS_IREQ_INITIALIZER;
590    typename iss_t::InstructionResponse irsp = ISS_IRSP_INITIALIZER;
591
592    typename iss_t::DataRequest dreq = ISS_DREQ_INITIALIZER;
593    typename iss_t::DataResponse drsp = ISS_DRSP_INITIALIZER;
594
595    m_iss.getRequests( ireq, dreq );
596
597#ifdef SOCLIB_MODULE_DEBUG
598    std::cout << name() << " Instruction Request: " << ireq << std::endl;
599    std::cout << name() << " Data Request: " << dreq << std::endl;
600#endif
601
602    /////////////////////////////////////////////////////////////////////
603    // The TGT_FSM controls the following ressources:
604    // - r_vci_tgt_fsm
605    // - r_tgt_buf[nwords]
606    // - r_tgt_val[nwords]
607    // - r_tgt_update
608    // - r_tgt_word
609    // - r_tgt_addr
610    // - r_tgt_srcid
611    // - r_tgt_trdid
612    // - r_tgt_pktid
613    // All VCI commands must be CMD_WRITE.
614    // If the VCI address offset is null, the command is an invalidate
615    // request. It is an update request otherwise.
616    // The VCI_TGT FSM stores the external request arguments in the
617    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req
618    // & r_tgt_dcache_req flip-flops to signal the external request to
619    // the ICACHE & DCACHE FSMs in the REQ state. It waits the completion
620    // of the update or invalidate request in the RSP state.
621    // -  for an invalidate request the VCI packet length is 1 word.
622    // The WDATA field contains the line index (i.e. the Z & Y fields).
623    // -  for an update request the VCI packet length is (n+2) words.
624    // The WDATA field of the first VCI word contains the line number.
625    // The WDATA field of the second VCI word contains the word index.
626    // The WDATA field of the n following words contains the values.
627    // -  for both invalidate & update requests, the VCI response
628    // is one single word.
629    // In case of errors in the VCI command packet, the simulation
630    // is stopped with an error message.
631    /////////////////////////////////////////////////////////////////////
632   
633    switch(r_vci_tgt_fsm) {
634    //////////////
635    case TGT_IDLE:
636    {
637        if ( p_vci_tgt.cmdval.read() )
638        {
639            paddr_t address = p_vci_tgt.address.read();
640
641            if ( p_vci_tgt.cmd.read() != vci_param::CMD_WRITE)
642            {
643                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
644                std::cout << "the received VCI command is not a write" << std::endl;
645                exit(0);
646            }
647
648            // multi-update or multi-invalidate for data type
649            if ( ( address != 0x3 ) && ( ! m_segment.contains(address)) )
650            {
651                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
652                std::cout << "out of segment VCI command received for a multi-updt or multi-inval request" << std::endl;
653                exit(0);
654            }
655
656            r_tgt_srcid = p_vci_tgt.srcid.read();
657            r_tgt_trdid = p_vci_tgt.trdid.read();
658            r_tgt_pktid = p_vci_tgt.pktid.read();
659            r_tgt_plen  = p_vci_tgt.plen.read(); // todo: wait L2 modification
660            r_tgt_addr = (paddr_t)p_vci_tgt.wdata.read() * m_dcache_words * 4;
661
662            if ( address == 0x3 ) // broadcast invalidate for data or instruction type
663            {
664                if ( ! p_vci_tgt.eop.read() )
665                {
666                    std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
667                    std::cout << "the BROADCAST INVALIDATE command length must be one word" << std::endl;
668                    exit(0);
669                }
670                r_tgt_update = false;
671                r_vci_tgt_fsm = TGT_REQ_BROADCAST;
672                m_cpt_cc_broadcast++;
673            }
674            else                // multi-update or multi-invalidate for data type
675            {
676                paddr_t cell = address - m_segment.baseAddress();   
677
678                if (cell == 0)                      // invalidate   
679                {                         
680                    if ( ! p_vci_tgt.eop.read() )
681                    {
682                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
683                        std::cout << "the MULTI-INVALIDATE command length must be one word" << std::endl;
684                        exit(0);
685                    }
686                    r_tgt_update = false;
687                    r_vci_tgt_fsm = TGT_REQ_DCACHE;
688                    m_cpt_cc_inval++ ;
689                }
690                else                                // update
691                {                               
692                    if ( p_vci_tgt.eop.read() )
693                    {
694                        std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
695                        std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
696                        exit(0);
697                    }
698                    r_tgt_update = true;
699                    r_vci_tgt_fsm = TGT_UPDT_WORD;
700                    m_cpt_cc_update++ ;
701                }     
702            } // end if address   
703        } // end if cmdval
704        break;
705    }
706    ////////////////////
707    case TGT_UPDT_WORD:
708    {
709        if (p_vci_tgt.cmdval.read())
710        {
711            if ( p_vci_tgt.eop.read() )
712            {
713                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
714                std::cout << "the MULTI-UPDATE command length must be N+2 words" << std::endl;
715                exit(0);
716            }
717            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_val[i] = false;
718            r_tgt_word = p_vci_tgt.wdata.read(); // the first modified word index
719            r_vci_tgt_fsm = TGT_UPDT_DATA;
720        }
721        break;
722    }
723    ////////////////////
724    case TGT_UPDT_DATA:
725    {
726        if (p_vci_tgt.cmdval.read())
727        {
728            size_t word = r_tgt_word.read();
729            if (word >= m_dcache_words)
730            {
731                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
732                std::cout << "the reveived MULTI-UPDATE command length is wrong" << std::endl;
733                exit(0);
734            }
735            r_tgt_buf[word] = p_vci_tgt.wdata.read();
736            if(p_vci_tgt.be.read())    r_tgt_val[word] = true;
737            r_tgt_word = word + 1;
738            if (p_vci_tgt.eop.read())  r_vci_tgt_fsm = TGT_REQ_DCACHE;
739        }
740        break;
741    }
742    ///////////////////////
743    case TGT_REQ_BROADCAST:
744    {
745        if ( !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
746        {
747            r_vci_tgt_fsm = TGT_RSP_BROADCAST;
748            r_tgt_icache_req = true;
749            r_tgt_dcache_req = true;
750        }
751        break;
752    }
753    ////////////////////
754    case TGT_REQ_DCACHE:
755    {
756        if ( !r_tgt_dcache_req.read() )
757        {
758            r_vci_tgt_fsm = TGT_RSP_DCACHE;
759            r_tgt_dcache_req = true;
760        }
761        break;
762    }
763    ///////////////////////
764    case TGT_RSP_BROADCAST:
765    {
766        // no response
767        if ( !r_tgt_icache_rsp.read() && !r_tgt_dcache_rsp.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
768        {
769            r_vci_tgt_fsm = TGT_IDLE;
770            break;
771        }
772
773        if ( p_vci_tgt.rspack.read() && !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() )
774        {
775            // one response
776            if ( !r_tgt_icache_rsp || !r_tgt_dcache_rsp )
777            {
778                r_vci_tgt_fsm = TGT_IDLE;
779                r_tgt_icache_rsp = false;
780                r_tgt_dcache_rsp = false;
781            }
782
783            // if data and instruction have the inval line, need two responses 
784            if ( r_tgt_icache_rsp && r_tgt_dcache_rsp )
785            {
786                r_tgt_icache_rsp = false; // only reset one for respond the second time
787            }
788        }
789        break;
790    }
791    ////////////////////
792    case TGT_RSP_DCACHE:
793    {
794        if ( p_vci_tgt.rspack.read() && !r_tgt_dcache_req.read() )
795        {
796            r_vci_tgt_fsm = TGT_IDLE;
797            r_tgt_dcache_rsp = false;
798        }
799        break;
800    }
801    } // end switch TGT_FSM
802
803    ////////////////////////////////////////////////////////////////////////////////////////
804    //      ICACHE_FSM
805    //
806    // There is 9 mutually exclusive conditions to exit the IDLE state.
807    // Four configurations corresponding to an XTN request from processor,
808    // - Flush TLB (in case of Context switch) => TLB_FLUSH state
809    // - Flush cache => CACHE_FLUSH state
810    // - Invalidate a TLB entry => TLB_INVAL state
811    // - Invalidate a cache line => CACHE_INVAL state
812    // Five configurations corresponding to various TLB or cache MISS :
813    // - TLB miss(in case hit_p miss) => TLB1_READ state
814    // - TLB miss(in case hit_p hit) => TLB2_READ state
815    // - Hit in TLB but VPN changed => BIS state
816    // - Cached read miss => MISS_REQ state
817    // - Uncache read miss => UNC_REQ state
818    //
819    // In case of MISS, the controller writes a request in the r_icache_paddr_save register
820    // and sets the corresponding request flip-flop : r_dcache_itlb_read_req, r_icache_miss_req
821    // or r_icache_unc_req. These request flip-flops are reset by the VCI_RSP controller
822    // when the response is ready in the ICACHE buffer.
823    //
824    // The DCACHE FSM signals XTN processor requests using the r_dcache_xtn_req flip-flop.
825    // The request opcod and the address to be invalidated are transmitted
826    // in the r_dcache_paddr_save & r_dcache_wdata_save registers respectively.
827    // The request flip-flop is reset by the ICACHE_FSM when the operation is completed.
828    //
829    // The r_vci_rsp_ins_error flip-flop is set by the VCI_RSP FSM and reset
830    // by the ICACHE-FSM in the ICACHE_ERROR state.
831    //
832    //-----------------------------------------------------------------------------------
833    // Instruction TLB:
834    // 
835    // - int        ET          (00: unmapped; 01: unused or PTD)
836    //                          (10: PTE new;  11: PTE old      )
837    // - bool       cachable    (cached bit)
838    // - bool       writable    (** not used alwayse false)
839    // - bool       executable  (executable bit)
840    // - bool       user        (access in user mode allowed)
841    // - bool       global      (PTE not invalidated by a TLB flush)
842    // - bool       dirty       (** not used alwayse false)
843    // - uint32_t   vpn         (virtual page number)
844    // - uint32_t   ppn         (physical page number)
845    ////////////////////////////////////////////////////////////////////////////////////////
846
847    switch(r_icache_fsm) {
848
849    ////////////////
850    case ICACHE_IDLE:
851    {
852        pte_info_t  icache_pte_info;
853        paddr_t     tlb_ipaddr       = 0;       // physical address obtained from TLB                         
854        paddr_t     spc_ipaddr       = 0;       // physical adress obtained from PPN_save (speculative)       
855        data_t      icache_ins       = 0;       // read instruction
856        bool        icache_hit_c     = false;   // Cache hit
857        bool        icache_cached    = false;   // cacheable access (read)
858        bool        icache_hit_t     = false;   // hit on TLB
859        bool        icache_hit_x     = false;   // VPN unmodified (can use spc_dpaddr)
860        bool        icache_hit_p     = false;   // PTP unmodified (can skip first level page table walk)
861        size_t      icache_tlb_way   = 0;       // selected way (in case of cache hit)
862        size_t      icache_tlb_set   = 0;       // selected set (Y field in address)
863        paddr_t     icache_tlb_nline = 0;       // TLB NLINE
864
865        // Decoding processor XTN requests
866        // They are sent by DCACHE FSM 
867
868        if (r_dcache_xtn_req)
869        {
870            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
871           
872            if ((int)r_dcache_type_save == (int)iss_t::XTN_PTPR ) 
873            {
874                r_icache_way = 0;
875                r_icache_set = 0;
876                r_icache_fsm = ICACHE_SW_FLUSH;   
877                break;
878            }
879            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_FLUSH)
880            {
881                r_icache_way = 0;
882                r_icache_set = 0;
883                r_icache_fsm = ICACHE_CACHE_FLUSH;   
884                break;
885            }
886            if ((int)r_dcache_type_save == (int)iss_t::XTN_ITLB_INVAL)
887            {
888                r_icache_fsm = ICACHE_TLB_INVAL;   
889                break;
890            }
891            if ((int)r_dcache_type_save == (int)iss_t::XTN_ICACHE_INVAL)
892            {
893                r_icache_fsm = ICACHE_CACHE_INVAL;   
894                break;
895            }
896            if ((int)r_dcache_type_save == (int)iss_t::XTN_DCACHE_FLUSH ) 
897            {
898                // special for ins tlb miss via data cache
899                r_icache_fsm = ICACHE_TLB_FLUSH;   
900                break;
901            }
902        } // end if xtn_req
903
904        // external cache invalidate request
905        if ( r_tgt_icache_req )
906        {
907            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
908            r_icache_fsm = ICACHE_CC_INVAL;
909            r_icache_fsm_save = r_icache_fsm;
910            break;
911        }
912
913        // external tlb invalidate request
914        if ( r_dcache_itlb_inval_req )
915        {
916            if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
917            r_itlb_inval_req = true;
918            r_icache_fsm = ICACHE_TLB_CC_INVAL;
919            r_icache_fsm_save = r_icache_fsm;
920            break;
921        }
922
923        // icache_hit_t_m, icache_hit_t_k, icache_hit_x, icache_hit_p
924        // icache_pte_info, icache_tlb_way, icache_tlb_set & ipaddr & cacheability
925        // - If MMU activated : cacheability is defined by the cachable bit in the TLB
926        // - If MMU not activated : cacheability is defined by the segment table.
927
928        if ( !(r_mmu_mode.read() & INS_TLB_MASK) )   // MMU not activated
929        {
930            icache_hit_t  = true;         
931            icache_hit_x  = true;         
932            icache_hit_p  = true;         
933            tlb_ipaddr    = ireq.addr;
934            spc_ipaddr    = ireq.addr;
935            icache_cached = m_cacheability_table[ireq.addr];
936        }
937        else                                                                // MMU activated
938        {
939            m_cpt_ins_tlb_read++;
940            icache_hit_t  = icache_tlb.cctranslate(ireq.addr, &tlb_ipaddr, &icache_pte_info,
941                                                   &icache_tlb_nline, &icache_tlb_way, &icache_tlb_set);
942            icache_hit_x  = (((vaddr_t)r_icache_vpn_save << PAGE_K_NBITS) == (ireq.addr & ~PAGE_K_MASK)) && r_itlb_translation_valid;
943            icache_hit_p  = (((ireq.addr >> PAGE_M_NBITS) == r_icache_id1_save) && r_icache_ptba_ok);
944            spc_ipaddr    = ((paddr_t)r_icache_ppn_save << PAGE_K_NBITS) | (paddr_t)(ireq.addr & PAGE_K_MASK);
945            icache_cached = icache_pte_info.c;
946        }
947
948        if ( !(r_mmu_mode.read() & INS_CACHE_MASK) )   // cache not actived
949        {
950            icache_cached = false;
951        }
952
953        if ( ireq.valid )
954        {
955            m_cpt_icache_dir_read += m_icache_ways;
956            m_cpt_icache_data_read += m_icache_ways;
957
958            // icache_hit_c & icache_ins
959            if ( icache_cached )    // using speculative physical address for cached access
960            {
961                icache_hit_c = r_icache.read(spc_ipaddr, &icache_ins);
962            }
963            else                    // using actual physical address for uncached access
964            {
965                icache_hit_c = ( r_icache_buf_unc_valid && (tlb_ipaddr == (paddr_t)r_icache_paddr_save) );
966                icache_ins = r_icache_miss_buf[0];
967            }
968
969            if ( r_mmu_mode.read() & INS_TLB_MASK )
970            {
971                if ( icache_hit_t )
972                {
973                    // check access rights
974                    if ( !icache_pte_info.u && (ireq.mode == iss_t::MODE_USER))
975                    {
976                        r_icache_error_type = MMU_READ_PRIVILEGE_VIOLATION; 
977                        r_icache_bad_vaddr = ireq.addr;
978                        irsp.valid = true;
979                        irsp.error = true;
980                        irsp.instruction = 0;
981                        break;
982                    }
983                    if ( !icache_pte_info.x )
984                    {
985                        r_icache_error_type = MMU_READ_EXEC_VIOLATION; 
986                        r_icache_bad_vaddr = ireq.addr;
987                        irsp.valid = true;
988                        irsp.error = true;
989                        irsp.instruction = 0;
990                        break;
991                    }
992                }
993
994                // update LRU, save ppn, vpn and page type
995                if ( icache_hit_t )
996                { 
997                    icache_tlb.setlru(icache_tlb_way,icache_tlb_set);     
998                    r_icache_ppn_save = tlb_ipaddr >> PAGE_K_NBITS;
999                    r_icache_vpn_save = ireq.addr >> PAGE_K_NBITS;
1000                    r_icache_tlb_nline = icache_tlb_nline;
1001                    r_itlb_translation_valid = true;
1002                }
1003                else
1004                {
1005                    r_itlb_translation_valid = false;
1006                }
1007
1008            } // end if MMU activated
1009
1010            // compute next state
1011            if ( !icache_hit_t && !icache_hit_p )      // TLB miss
1012            {
1013                // walk page table  level 1
1014                r_icache_paddr_save = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((ireq.addr>>PAGE_M_NBITS)<<2);
1015                r_itlb_read_dcache_req = true;
1016                r_icache_fsm = ICACHE_TLB1_READ;
1017                m_cpt_ins_tlb_miss++;
1018                m_cost_ins_tlb_miss_frz++;
1019            }
1020            else if ( !icache_hit_t && icache_hit_p )  // TLB Miss with possibility of bypass first level page
1021            {
1022                // walk page table level 2
1023                r_icache_paddr_save = (paddr_t)r_icache_ptba_save |
1024                                      (paddr_t)(((ireq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
1025                r_itlb_read_dcache_req = true;
1026                r_icache_fsm = ICACHE_TLB2_READ;
1027                m_cpt_ins_tlb_miss++;
1028                m_cost_ins_tlb_miss_frz++;
1029            }
1030            else if ( icache_hit_t && !icache_hit_x && icache_cached ) // cached access with an ucorrect speculative physical address
1031            {
1032                r_icache_paddr_save = tlb_ipaddr;   // save actual physical address for BIS
1033                r_icache_fsm = ICACHE_BIS;
1034                m_cost_ins_miss_frz++;
1035            }
1036            else    // cached or uncached access with a correct speculative physical address
1037            {       
1038                m_cpt_ins_read++;
1039                if ( !icache_hit_c )
1040                {
1041                    m_cpt_ins_miss++;
1042                    m_cost_ins_miss_frz++;
1043                    if ( icache_cached )
1044                    {
1045                        r_icache_miss_req = true;
1046                        r_icache_paddr_save = spc_ipaddr;
1047                        r_icache_fsm = ICACHE_MISS_WAIT;
1048                    }
1049                    else
1050                    {
1051                        r_icache_unc_req = true;
1052                        r_icache_buf_unc_valid = false;
1053                        r_icache_paddr_save = tlb_ipaddr;
1054                        r_icache_fsm = ICACHE_UNC_WAIT;
1055                    }
1056                }
1057                else
1058                {
1059                    r_icache_buf_unc_valid = false;
1060                    r_icache_fsm = ICACHE_IDLE;
1061                }
1062                irsp.valid = icache_hit_c;
1063                irsp.instruction = icache_ins;
1064            } // end if next states
1065           
1066        } // end if ireq.valid
1067        break;
1068    }
1069    ////////////////
1070    case ICACHE_BIS:
1071    {
1072        m_cost_ins_miss_frz++;
1073        // external cache invalidate request
1074        if ( r_tgt_icache_req )
1075        {
1076            r_icache_fsm = ICACHE_CC_INVAL;
1077            r_icache_fsm_save = r_icache_fsm;
1078            m_cost_ins_waste_wait_frz++;
1079            break;
1080        }
1081
1082        // external tlb invalidate request
1083        if ( r_dcache_itlb_inval_req )
1084        {
1085            r_itlb_inval_req = true;
1086            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1087            r_icache_fsm_save = r_icache_fsm;
1088            m_cost_ins_waste_wait_frz++;
1089            break;
1090        }
1091     
1092        // using page is invalidated
1093        if ( r_icache_inval_tlb_rsp )
1094        {
1095            r_icache_inval_tlb_rsp = false;
1096            r_icache_fsm = ICACHE_IDLE;
1097            m_cost_ins_tlb_miss_frz++;
1098            break;
1099        }
1100 
1101        data_t  icache_ins = 0;
1102        bool    icache_hit = false;
1103
1104        // acces is always cached in this state
1105        icache_hit = r_icache.read(r_icache_paddr_save, &icache_ins);
1106
1107        m_cpt_ins_read++;
1108        if ( !icache_hit )
1109        {
1110            r_icache_miss_req = true;
1111            r_icache_fsm = ICACHE_MISS_WAIT;
1112            m_cpt_ins_miss++;
1113        }
1114        else
1115        {
1116            r_icache_fsm = ICACHE_IDLE;
1117        }
1118
1119        irsp.valid = icache_hit;
1120        irsp.error = false;
1121        irsp.instruction = icache_ins;
1122        break;
1123    }
1124    //////////////////////
1125    case ICACHE_TLB1_READ:
1126    {
1127        m_cost_ins_tlb_miss_frz++;
1128
1129        // external cache invalidate request
1130        if ( r_tgt_icache_req )
1131        {
1132            r_icache_fsm = ICACHE_CC_INVAL;
1133            r_icache_fsm_save = r_icache_fsm;
1134            m_cost_ins_waste_wait_frz++;
1135            break;
1136        }
1137
1138        // external tlb invalidate request
1139        if ( r_dcache_itlb_inval_req )
1140        {
1141            r_itlb_inval_req = true;
1142            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1143            r_icache_fsm_save = r_icache_fsm;
1144            m_cost_ins_waste_wait_frz++;
1145            break;
1146        }
1147
1148        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response and no invalidation
1149        {
1150            if ( !r_dcache_rsp_itlb_error ) // vci response ok
1151            { 
1152                if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
1153                {
1154                    r_icache_ptba_ok    = false;       
1155                    r_icache_error_type = MMU_READ_PT1_UNMAPPED; 
1156                    r_icache_bad_vaddr  = ireq.addr;
1157                    r_icache_fsm        = ICACHE_ERROR;
1158                }
1159                else if ( (r_dcache_rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT ) // PTD
1160                {
1161                    r_icache_ptba_ok       = true;     
1162                    r_icache_ptba_save     = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS;
1163                    r_icache_id1_save      = ireq.addr >> PAGE_M_NBITS;
1164                    r_icache_paddr_save    = (paddr_t)(r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
1165                                             (paddr_t)(((ireq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
1166                    r_itlb_read_dcache_req = true;
1167                    r_icache_fsm           = ICACHE_TLB2_READ;
1168                }       
1169                else
1170                {
1171                    r_icache_ptba_ok = false;
1172       
1173                    if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
1174                    {
1175                        if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
1176                        {
1177                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
1178                            r_icache_fsm        = ICACHE_TLB1_UPDT;
1179                        }
1180                        else
1181                        {
1182                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
1183                            r_itlb_acc_dcache_req = true;
1184                            r_icache_fsm          = ICACHE_TLB1_WRITE;
1185                            m_cpt_ins_tlb_write_et++;
1186                        }
1187                    }
1188                    else // remotely
1189                    {
1190                        if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
1191                        {
1192                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
1193                            r_icache_fsm        = ICACHE_TLB1_UPDT;
1194                        }
1195                        else
1196                        {
1197                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
1198                            r_itlb_acc_dcache_req = true;
1199                            r_icache_fsm          = ICACHE_TLB1_WRITE;
1200                            m_cpt_ins_tlb_write_et++;
1201                        }
1202                    }
1203                }
1204            }
1205            else                        // vci response error
1206            { 
1207                r_icache_fsm = ICACHE_ERROR;
1208                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;   
1209                r_icache_bad_vaddr = ireq.addr;
1210            }
1211        }
1212
1213        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
1214        {
1215            if ( r_dcache_rsp_itlb_error )
1216            {
1217                r_icache_inval_tlb_rsp = false;
1218                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;   
1219                r_icache_bad_vaddr = ireq.addr;
1220                r_icache_fsm = ICACHE_ERROR;
1221            }
1222            else
1223            {
1224                r_icache_inval_tlb_rsp = false;
1225                r_icache_fsm = ICACHE_IDLE; 
1226            }
1227        }
1228        break;
1229    }
1230    ///////////////////////
1231    case ICACHE_TLB1_WRITE: 
1232    {
1233        m_cost_ins_tlb_miss_frz++;
1234
1235        // external cache invalidate request
1236        if ( r_tgt_icache_req )
1237        {
1238            r_icache_fsm = ICACHE_CC_INVAL;
1239            r_icache_fsm_save = r_icache_fsm;
1240            m_cost_ins_waste_wait_frz++;
1241            break;
1242        }
1243        // external tlb invalidate request
1244        if ( r_dcache_itlb_inval_req )
1245        {
1246            r_itlb_inval_req = true;
1247            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1248            r_icache_fsm_save = r_icache_fsm;
1249            m_cost_ins_waste_wait_frz++;
1250            break;
1251        }
1252
1253        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response and no invalidation       
1254        {
1255            if ( r_dcache_rsp_itlb_error )
1256            {
1257                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS; 
1258                r_icache_bad_vaddr = ireq.addr;
1259                r_icache_fsm = ICACHE_ERROR;
1260            }
1261            else 
1262            {
1263                r_icache_fsm = ICACHE_TLB1_UPDT; 
1264            }
1265        }
1266
1267        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
1268        {   
1269            if ( r_dcache_rsp_itlb_error )
1270            {
1271                r_icache_inval_tlb_rsp = false;
1272                r_icache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS; 
1273                r_icache_bad_vaddr = ireq.addr;
1274                r_icache_fsm = ICACHE_ERROR;
1275            }
1276            else 
1277            {
1278                r_icache_inval_tlb_rsp = false;
1279                r_icache_fsm = ICACHE_IDLE;   
1280            }
1281        }
1282        break;
1283    }
1284    //////////////////////
1285    case ICACHE_TLB1_UPDT:
1286    {
1287        m_cost_ins_tlb_miss_frz++;
1288
1289        // external cache invalidate request
1290        if ( r_tgt_icache_req )
1291        {
1292            r_icache_fsm = ICACHE_CC_INVAL;
1293            r_icache_fsm_save = r_icache_fsm;
1294            m_cost_ins_waste_wait_frz++;
1295            break;
1296        }
1297
1298        // external tlb invalidate request
1299        if ( r_dcache_itlb_inval_req )
1300        {
1301            r_itlb_inval_req = true;
1302            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1303            r_icache_fsm_save = r_icache_fsm;
1304            m_cost_ins_waste_wait_frz++;
1305            break;
1306        }
1307
1308        // TLB update and invalidate different PTE
1309        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp ) 
1310        {
1311            paddr_t victim_index = 0;
1312            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
1313            r_dcache_itlb_cleanup_line = victim_index;
1314            r_icache_fsm = ICACHE_IDLE;
1315        }
1316
1317        // TLB update and invalidate same PTE
1318        if ( r_icache_inval_tlb_rsp )                                 
1319        {
1320            r_icache_inval_tlb_rsp = false;
1321            r_icache_fsm = ICACHE_IDLE;
1322        }
1323        break;
1324    }
1325    /////////////////////
1326    case ICACHE_TLB2_READ:
1327    {
1328        m_cost_ins_tlb_miss_frz++;
1329
1330        // external cache invalidate request
1331        if ( r_tgt_icache_req )
1332        {
1333            r_icache_fsm = ICACHE_CC_INVAL;
1334            r_icache_fsm_save = r_icache_fsm;
1335            m_cost_ins_waste_wait_frz++;
1336            break;
1337        }
1338
1339        // external tlb invalidate request
1340        if ( r_dcache_itlb_inval_req )
1341        {
1342            r_itlb_inval_req = true;
1343            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1344            r_icache_fsm_save = r_icache_fsm;
1345            m_cost_ins_waste_wait_frz++;
1346            break;
1347        }
1348
1349        if ( !r_itlb_read_dcache_req && !r_icache_inval_tlb_rsp ) // TLB miss read response
1350        {
1351            if ( !r_dcache_rsp_itlb_error ) // VCI response ok       
1352            {
1353                if ( !(r_dcache_rsp_itlb_miss >> PTE_V_SHIFT) ) // unmapped
1354                {
1355                    r_icache_error_type = MMU_READ_PT2_UNMAPPED; 
1356                    r_icache_bad_vaddr  = ireq.addr;
1357                    r_icache_fsm = ICACHE_ERROR;
1358                }
1359                else
1360                {
1361                    if ( (m_srcid_rw >> 4) == ((r_dcache_rsp_itlb_miss & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
1362                    {
1363                        if ( (r_dcache_rsp_itlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
1364                        {
1365                            r_icache_fsm        = ICACHE_TLB2_UPDT;
1366                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
1367                        }
1368                        else
1369                        {
1370                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_L_MASK;
1371                            r_itlb_acc_dcache_req = true;
1372                            r_icache_fsm          = ICACHE_TLB2_WRITE;
1373                            m_cpt_ins_tlb_write_et++;
1374                        }
1375                    }
1376                    else // remotely
1377                    {
1378                        if ( (r_dcache_rsp_itlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
1379                        {
1380                            r_icache_fsm        = ICACHE_TLB2_UPDT;
1381                            r_icache_pte_update = r_dcache_rsp_itlb_miss;
1382                        }
1383                        else
1384                        {
1385                            r_icache_pte_update   = r_dcache_rsp_itlb_miss | PTE_R_MASK;
1386                            r_itlb_acc_dcache_req = true;
1387                            r_icache_fsm          = ICACHE_TLB2_WRITE;
1388                            m_cpt_ins_tlb_write_et++;
1389                        }
1390                    }
1391                }
1392            }
1393            else                            // VCI response error       
1394            {
1395                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
1396                r_icache_bad_vaddr = ireq.addr;
1397                r_icache_fsm = ICACHE_ERROR;
1398            }
1399        }
1400
1401        if ( !r_itlb_read_dcache_req && r_icache_inval_tlb_rsp ) // TLB miss read response and invalidation
1402        {
1403            if ( r_dcache_rsp_itlb_error )
1404            {
1405                r_icache_inval_tlb_rsp = false;
1406                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;   
1407                r_icache_bad_vaddr = ireq.addr;
1408                r_icache_fsm = ICACHE_ERROR;
1409            }
1410            else
1411            {
1412                r_icache_inval_tlb_rsp = false;
1413                r_icache_fsm = ICACHE_IDLE; 
1414            }
1415        }
1416        break;
1417    }
1418    /////////////////////////
1419    case ICACHE_TLB2_WRITE:
1420    { 
1421        m_cost_ins_tlb_miss_frz++;
1422
1423        // external cache invalidate request
1424        if ( r_tgt_icache_req )
1425        {
1426            r_icache_fsm = ICACHE_CC_INVAL;
1427            r_icache_fsm_save = r_icache_fsm;
1428            m_cost_ins_waste_wait_frz++;
1429            break;
1430        }
1431        // external tlb invalidate request
1432        if ( r_dcache_itlb_inval_req )
1433        {
1434            r_itlb_inval_req = true;
1435            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1436            r_icache_fsm_save = r_icache_fsm;
1437            m_cost_ins_waste_wait_frz++;
1438            break;
1439        }
1440
1441        if (!r_itlb_acc_dcache_req && !r_icache_inval_tlb_rsp ) // TLB access bits write response         
1442        {
1443            if ( r_dcache_rsp_itlb_error )             
1444            {
1445                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS; 
1446                r_icache_bad_vaddr = ireq.addr;
1447                r_icache_fsm = ICACHE_ERROR;
1448            }
1449            else 
1450            {
1451                r_icache_fsm = ICACHE_TLB2_UPDT; 
1452            }
1453        }
1454        if (!r_itlb_acc_dcache_req && r_icache_inval_tlb_rsp) // TLB ET write response and invalidation     
1455        {   
1456            if ( r_dcache_rsp_itlb_error )
1457            {
1458                r_icache_inval_tlb_rsp = false;
1459                r_icache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS; 
1460                r_icache_bad_vaddr = ireq.addr;
1461                r_icache_fsm = ICACHE_ERROR;
1462            }
1463            else 
1464            {
1465                r_icache_inval_tlb_rsp = false;
1466                r_icache_fsm = ICACHE_IDLE;   
1467            }
1468        }
1469        break;
1470    }
1471    /////////////////////
1472    case ICACHE_TLB2_UPDT:
1473    {
1474        m_cost_ins_tlb_miss_frz++;
1475
1476        // external cache invalidate request
1477        if ( r_tgt_icache_req )
1478        {
1479            r_icache_fsm = ICACHE_CC_INVAL;
1480            r_icache_fsm_save = r_icache_fsm;
1481            m_cost_ins_waste_wait_frz++;
1482            break;
1483        }
1484
1485        // external tlb invalidate request
1486        if ( r_dcache_itlb_inval_req )
1487        {
1488            r_itlb_inval_req = true;
1489            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1490            r_icache_fsm_save = r_icache_fsm;
1491            m_cost_ins_waste_wait_frz++;
1492            break;
1493        }
1494
1495        // TLB update and invalidate different PTE
1496        if ( !r_dcache_itlb_cleanup_req && !r_icache_inval_tlb_rsp )
1497        {
1498            paddr_t victim_index = 0;
1499            r_dcache_itlb_cleanup_req = icache_tlb.update(r_icache_pte_update,r_dcache_rsp_itlb_ppn,ireq.addr,(r_icache_paddr_save.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index);
1500            r_dcache_itlb_cleanup_line = victim_index;
1501            r_icache_fsm = ICACHE_IDLE;
1502        }
1503        // TLB update and invalidate same PTE
1504        if ( r_icache_inval_tlb_rsp )                           
1505        {
1506            r_icache_inval_tlb_rsp = false;
1507            r_icache_fsm = ICACHE_IDLE;
1508        }
1509        break;
1510    }
1511    /////////////////////////////
1512    case ICACHE_SW_FLUSH:
1513    {
1514        size_t way = r_icache_way;
1515        size_t set = r_icache_set;
1516        bool clean = false;
1517
1518        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1519        m_cost_ins_tlb_sw_frz++;
1520
1521        // 4K page size TLB flush leads to cleanup req to data cache
1522        if ( !r_dcache_itlb_cleanup_req )    // last cleanup finish
1523        {
1524            paddr_t victim_index = 0;
1525            for ( ; way < m_itlb_ways; way++)
1526            {
1527                for ( ; set < m_itlb_sets; set++)
1528                {
1529                    if(icache_tlb.checkcleanup(way, set, &victim_index))
1530                    {
1531                        clean = true;
1532                        r_dcache_itlb_cleanup_req = true;
1533                        r_dcache_itlb_cleanup_line = victim_index;
1534                        r_icache_way = way + ((set+1)/m_itlb_sets);
1535                        r_icache_set = (set+1) % m_itlb_sets;
1536                        break;
1537                    }
1538                }
1539                if (clean) break;
1540            }
1541
1542            if ((way == m_itlb_ways) && (set == m_itlb_sets))
1543            {
1544                r_dcache_xtn_req = false;
1545                r_icache_fsm = ICACHE_IDLE;
1546                break;
1547            }
1548        }
1549        break;
1550    }
1551    /////////////////////
1552    case ICACHE_TLB_FLUSH:
1553    {   
1554        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1555
1556        // data cache flush leads to ins tlb flush, flush all tlb entry
1557        icache_tlb.flush(true);    // global entries are invalidated
1558        r_dcache_xtn_req = false;
1559        r_icache_fsm = ICACHE_IDLE;
1560        break;
1561    }
1562    ////////////////////////
1563    case ICACHE_CACHE_FLUSH:
1564    {
1565        // external cache invalidate request
1566        if ( r_tgt_icache_req )
1567        {
1568            r_tgt_icache_req = false;
1569        }
1570
1571        size_t way = r_icache_way;
1572        size_t set = r_icache_set;
1573        bool clean = false;
1574
1575        m_cost_ins_cache_flush_frz++;
1576        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1577
1578        // cache flush and send cleanup to external
1579        if ( !r_icache_cleanup_req )
1580        {
1581            paddr_t victim_index = 0;
1582            for ( ; way < m_icache_ways; way++ )
1583            {   
1584                for ( ; set < m_icache_sets; set++ )
1585                {   
1586                    if ( r_icache.flush(way, set, &victim_index) )
1587                    {
1588                        clean = true;
1589                        r_icache_cleanup_req = true;
1590                        r_icache_cleanup_line = victim_index;
1591                        r_icache_way = way + ((set+1)/m_icache_sets);
1592                        r_icache_set = (set+1) % m_icache_sets;
1593                        break;
1594                    }
1595                }
1596                if (clean) break;
1597            }
1598            if ((way == m_icache_ways) && (set == m_icache_sets))
1599            {
1600                r_dcache_xtn_req = false;
1601                r_icache_fsm = ICACHE_IDLE;
1602                break;
1603            }
1604        }
1605        break;
1606    }
1607    /////////////////////
1608    case ICACHE_TLB_INVAL: 
1609    {
1610        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1611        paddr_t victim_index = 0;
1612
1613        if ( !r_dcache_itlb_cleanup_req )
1614        {
1615            r_dcache_itlb_cleanup_req = icache_tlb.inval(r_dcache_wdata_save, &victim_index);
1616            r_dcache_itlb_cleanup_line = victim_index;
1617            r_dcache_xtn_req = false;
1618            r_icache_fsm = ICACHE_IDLE;
1619        }
1620        break;
1621    }
1622    ////////////////////////
1623    case ICACHE_CACHE_INVAL:
1624    {   
1625        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1626
1627        paddr_t ipaddr = 0;                     
1628        bool    icache_hit_t = false;
1629
1630        if ( !r_icache_cleanup_req )
1631        {   
1632            if ( r_mmu_mode.read() & INS_TLB_MASK )
1633            {
1634                icache_hit_t = icache_tlb.translate(r_dcache_wdata_save, &ipaddr);
1635            }
1636            else
1637            {
1638                ipaddr = (paddr_t)r_dcache_wdata_save;
1639                icache_hit_t = true;
1640            }
1641            if ( icache_hit_t )
1642            {
1643                // invalidate and cleanup if necessary
1644                r_icache_cleanup_req = r_icache.inval(ipaddr);
1645                r_icache_cleanup_line = ipaddr >> (uint32_log2(m_icache_words) + 2);   
1646            }
1647            r_dcache_xtn_req = false;
1648            r_icache_fsm = ICACHE_IDLE;
1649        }
1650        break;
1651    }
1652    ///////////////////////
1653    case ICACHE_MISS_WAIT:
1654    {
1655        m_cost_ins_miss_frz++;
1656
1657        // external cache invalidate request
1658        if ( r_tgt_icache_req )     
1659        {
1660            r_icache_fsm = ICACHE_CC_INVAL;
1661            r_icache_fsm_save = r_icache_fsm;
1662            m_cost_ins_waste_wait_frz++;
1663            break;
1664        }
1665
1666        // external tlb invalidate request
1667        if ( r_dcache_itlb_inval_req )
1668        {
1669            r_itlb_inval_req = true;
1670            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1671            r_icache_fsm_save = r_icache_fsm;
1672            m_cost_ins_waste_wait_frz++;
1673            break;
1674        }
1675       
1676        if ( !r_icache_miss_req )
1677        {
1678            if ( r_vci_rsp_ins_error )
1679            {
1680                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;
1681                r_icache_bad_vaddr = ireq.addr;
1682                r_icache_fsm = ICACHE_ERROR;
1683
1684                if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
1685                if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
1686                break;
1687            }
1688
1689            if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
1690            {
1691                r_icache_fsm = ICACHE_IDLE;
1692                r_icache_inval_tlb_rsp = false;
1693                m_cost_ins_tlb_miss_frz++;
1694                break;
1695            }
1696       
1697            if ( r_icache_inval_rsp ) // Miss read response and tlb invalidation
1698            {
1699                r_icache_fsm = ICACHE_IDLE;
1700                r_icache_inval_rsp = false;
1701                break;
1702            }
1703            r_icache_fsm = ICACHE_MISS_UPDT; 
1704        }       
1705        break;
1706    }
1707    ////////////////////
1708    case ICACHE_UNC_WAIT:
1709    {
1710        m_cost_ins_miss_frz++;
1711
1712        // external cache invalidate request
1713        if ( r_tgt_icache_req )
1714        {
1715            r_icache_fsm = ICACHE_CC_INVAL;
1716            r_icache_fsm_save = r_icache_fsm;
1717            m_cost_ins_waste_wait_frz++;
1718            break;
1719        }
1720
1721        // external tlb invalidate request
1722        if ( r_dcache_itlb_inval_req )
1723        {
1724            r_itlb_inval_req = true;
1725            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1726            r_icache_fsm_save = r_icache_fsm;
1727            m_cost_ins_waste_wait_frz++;
1728            break;
1729        }
1730
1731        if ( !r_icache_unc_req )
1732        {
1733            if ( r_vci_rsp_ins_error )
1734            {
1735                r_icache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;   
1736                r_icache_bad_vaddr = ireq.addr;
1737                r_icache_fsm = ICACHE_ERROR;
1738
1739                if ( r_icache_inval_tlb_rsp ) r_icache_inval_tlb_rsp = false;
1740                //if ( r_icache_inval_rsp ) r_icache_inval_rsp = false;
1741                break;
1742            }
1743
1744            if ( r_icache_inval_tlb_rsp ) // Miss read response and tlb invalidation
1745            {
1746                r_icache_inval_tlb_rsp = false;
1747                r_icache_fsm = ICACHE_IDLE;
1748                break;
1749            }
1750/*         
1751            if ( r_icache_inval_rsp ) // Miss read response and cache invalidation
1752            {
1753                r_icache_inval_rsp = false;
1754                r_icache_fsm = ICACHE_IDLE;
1755                break;
1756            }
1757*/
1758            // Miss read response and no invalidation
1759            r_icache_buf_unc_valid = true;
1760            r_icache_fsm = ICACHE_IDLE;
1761        }       
1762        break;
1763    }
1764    //////////////////////
1765    case ICACHE_MISS_UPDT:
1766    {
1767        m_cost_ins_miss_frz++;
1768
1769        // external cache invalidate request
1770        if ( r_tgt_icache_req )   
1771        {
1772            r_icache_fsm = ICACHE_CC_INVAL;
1773            r_icache_fsm_save = r_icache_fsm;
1774            m_cost_ins_waste_wait_frz++;
1775            break;
1776        }
1777
1778        // external tlb invalidate request
1779        if ( r_dcache_itlb_inval_req )
1780        {
1781            r_itlb_inval_req = true;
1782            r_icache_fsm = ICACHE_TLB_CC_INVAL;
1783            r_icache_fsm_save = r_icache_fsm;
1784            m_cost_ins_waste_wait_frz++;
1785            break;
1786        }
1787
1788        if ( r_icache_inval_tlb_rsp ) // tlb invalidation
1789        {
1790            r_icache_inval_tlb_rsp = false;
1791            r_icache_fsm = ICACHE_IDLE;
1792            m_cost_ins_tlb_miss_frz++;
1793            break;
1794        }
1795
1796        if ( r_icache_inval_rsp ) // invalidation
1797        {
1798            r_icache_inval_rsp = false;
1799            r_icache_fsm = ICACHE_IDLE;
1800            break;
1801        }
1802
1803        if ( !r_icache_cleanup_req ) // Miss update and no invalidation
1804        {
1805            data_t* buf = r_icache_miss_buf;
1806            paddr_t  victim_index = 0;
1807            m_cpt_icache_dir_write++;
1808            m_cpt_icache_data_write++;
1809
1810            r_icache_cleanup_req = r_icache.update(r_icache_paddr_save.read(), buf, &victim_index);
1811            r_icache_cleanup_line = victim_index;           
1812
1813            r_icache_fsm = ICACHE_IDLE;
1814        }
1815        break;
1816    }
1817    ///////////////////
1818    case ICACHE_ERROR:
1819    {
1820        r_vci_rsp_ins_error = false;
1821        r_dcache_rsp_itlb_error = false;
1822        irsp.valid = true;
1823        irsp.error = true;
1824        irsp.instruction = 0;
1825        r_icache_fsm = ICACHE_IDLE;
1826        break;
1827    }
1828    /////////////////////
1829    case ICACHE_CC_INVAL: 
1830    {                       
1831        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;
1832        m_cpt_icache_dir_read += m_icache_ways;
1833
1834        // invalidate cache
1835        if( (( r_icache_fsm_save == ICACHE_MISS_WAIT ) || ( r_icache_fsm_save == ICACHE_MISS_UPDT ) /*||
1836             ( r_icache_fsm_save == ICACHE_UNC_WAIT )*/ ) &&
1837            ((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_icache_words<<2)-1))) )
1838        {
1839            r_icache_inval_rsp = true;
1840        }
1841        else
1842        {
1843            r_tgt_icache_rsp = r_icache.inval(r_tgt_addr.read());
1844        }
1845        r_tgt_icache_req = false;
1846        r_icache_fsm = r_icache_fsm_save;
1847        break;
1848    }
1849    /////////////////////////
1850    case ICACHE_TLB_CC_INVAL:
1851    {
1852        if ( ireq.valid ) m_cost_ins_waste_wait_frz++;       
1853
1854        if ( r_itlb_inval_req ) break;
1855
1856        // invalidate cache
1857        if( (( r_icache_fsm_save == ICACHE_TLB1_READ ) || ( r_icache_fsm_save == ICACHE_TLB2_READ )  ||
1858             ( r_icache_fsm_save == ICACHE_TLB1_WRITE )|| ( r_icache_fsm_save == ICACHE_TLB2_WRITE ) ||
1859             ( r_icache_fsm_save == ICACHE_TLB1_UPDT ) || ( r_icache_fsm_save == ICACHE_TLB2_UPDT )) &&
1860            (((r_icache_paddr_save.read() & ~((m_icache_words<<2)-1)) >> (uint32_log2(m_icache_words) + 2) ) == r_dcache_itlb_inval_line.read()) )
1861        {
1862            r_icache_inval_tlb_rsp = true;
1863        }
1864        else if (((r_icache_fsm_save == ICACHE_BIS)||(r_icache_fsm_save == ICACHE_MISS_WAIT) ||
1865                 (r_icache_fsm_save == ICACHE_UNC_WAIT)||(r_icache_fsm_save == ICACHE_MISS_UPDT)) &&
1866                (r_icache_tlb_nline == r_dcache_itlb_inval_line))
1867        {
1868            r_icache_inval_tlb_rsp = true;
1869        }
1870        r_dcache_itlb_inval_req = false;
1871        r_icache_fsm = r_icache_fsm_save;
1872        break;
1873    }
1874    } // end switch r_icache_fsm
1875
1876#ifdef SOCLIB_MODULE_DEBUG
1877    std::cout << name() << " Instruction Response: " << irsp << std::endl;
1878#endif
1879
1880    ////////////////////////////////////////////////////////////////////////////////////
1881    //      INVAL ITLB CHECK FSM
1882    ////////////////////////////////////////////////////////////////////////////////////////
1883    switch(r_inval_itlb_fsm) {
1884    /////////////////////
1885    case INVAL_ITLB_IDLE:
1886    {
1887        if ( r_itlb_inval_req )
1888        {
1889            r_ccinval_itlb_way = 0;
1890            r_ccinval_itlb_set = 0;
1891            r_inval_itlb_fsm = INVAL_ITLB_CHECK;   
1892            m_cost_ins_tlb_inval_frz++;
1893        }   
1894        break;
1895    }
1896    ////////////////////////////
1897    case INVAL_ITLB_CHECK:
1898    {
1899        m_cost_ins_tlb_inval_frz++;
1900
1901        size_t way = r_ccinval_itlb_way;
1902        size_t set = r_ccinval_itlb_set;
1903        bool end = false;       
1904        bool tlb_hit = icache_tlb.cccheck(r_dcache_itlb_inval_line.read(), way, set, &way, &set, &end);
1905   
1906        if ( tlb_hit )
1907        {
1908            r_ccinval_itlb_way = way;
1909            r_ccinval_itlb_set = set;
1910            r_itlb_cc_check_end = end;
1911            r_inval_itlb_fsm = INVAL_ITLB_INVAL;
1912            m_cpt_ins_tlb_inval++;   
1913        }       
1914        else
1915        {
1916            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;   
1917        }
1918        break;
1919    }
1920    /////////////////////////
1921    case INVAL_ITLB_INVAL:
1922    {
1923        m_cost_ins_tlb_inval_frz++;
1924 
1925        icache_tlb.ccinval(r_ccinval_itlb_way, r_ccinval_itlb_set);
1926
1927        if ( !r_itlb_cc_check_end )
1928        {
1929            r_inval_itlb_fsm = INVAL_ITLB_CHECK;
1930        }
1931        else
1932        {
1933            r_inval_itlb_fsm = INVAL_ITLB_CLEAR;   
1934        }
1935        break;
1936    }
1937    ////////////////////
1938    case INVAL_ITLB_CLEAR:
1939    {
1940        r_itlb_inval_req = false;
1941        r_itlb_cc_check_end = false;
1942        r_ccinval_itlb_way = 0;
1943        r_ccinval_itlb_set = 0;
1944        r_inval_itlb_fsm = INVAL_ITLB_IDLE;   
1945        m_cost_ins_tlb_inval_frz++;
1946        break;
1947    }
1948    } // end switch r_inval_itlb_fsm
1949
1950    ////////////////////////////////////////////////////////////////////////////////////
1951    //      DCACHE FSM
1952    //
1953    // Both the Cacheability Table, and the MMU cached bit are used to define
1954    // the cacheability.
1955    //
1956    // There is 14 mutually exclusive conditions to exit the IDLE state.
1957    // Seven configurations corresponding to an XTN request from processor:
1958    // - Context switch => CTXT_SWITCH state
1959    // - Flush dcache => DCACHE_FLUSH state
1960    // - Flush icache => ICACHE_FLUSH state
1961    // - Invalidate a dtlb entry => DTLB_INVAL state
1962    // - Invalidate a itlb entry => ITLB_INVAL state
1963    // - Invalidate a dcache line => DCACHE_INVAL state
1964    // - Invalidate a icache line => ICACHE_INVAL state
1965    // Seven configurations corresponding to various read miss or write requests:
1966    // - TLB miss(in case hit_p miss) => TLB1_READ state
1967    // - TLB miss(in case hit_p hit) => TLB2_READ state
1968    // - Hit in TLB but VPN changed => BIS state
1969    // - Cached read miss => MISS_REQ state
1970    // - Uncache read miss => UNC_REQ state
1971    // - Write hit => WRITE_UPDT state
1972    // - Write miss => WRITE_REQ
1973    //
1974    // The r_vci_rsp_data_error flip-flop is set by the VCI_RSP controller and reset
1975    // by DCACHE-FSM when its state is in DCACHE_ERROR.
1976    //---------------------------------------------------------------------
1977    // Data TLB:
1978    // 
1979    // - int        ET          (00: unmapped; 01: unused or PTD)
1980    //                          (10: PTE new;  11: PTE old      )
1981    // - bool       cachable    (cached bit)
1982    // - bool       writable    (writable bit)
1983    // - bool       executable  (** not used alwayse false)
1984    // - bool       user        (access in user mode allowed)
1985    // - bool       global      (PTE not invalidated by a TLB flush)
1986    // - bool       dirty       (page has been modified)
1987    // - uint32_t   vpn         (virtual page number)
1988    // - uint32_t   ppn         (physical page number)
1989    ////////////////////////////////////////////////////////////////////////////////////////
1990
1991    switch (r_dcache_fsm) {
1992    //////////////////////
1993    case DCACHE_WRITE_REQ:
1994    {
1995        // external cache invalidate request
1996        if ( r_tgt_dcache_req )
1997        {
1998            r_dcache_fsm = DCACHE_CC_CHECK;
1999            r_dcache_fsm_save = r_dcache_fsm;
2000            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
2001            break;
2002        }
2003
2004        // try to post the write request in the write buffer
2005        if ( !r_dcache_write_req )     // no previous write transaction     
2006        {
2007            if ( r_wbuf.wok(r_dcache_paddr_save) )   // write request in the same cache line
2008            {   
2009                r_wbuf.write(r_dcache_paddr_save.read(), r_dcache_be_save.read(), r_dcache_wdata_save);
2010                // closing the write packet if uncached
2011                if ( !r_dcache_cached_save )
2012                {
2013                    r_dcache_write_req = true;
2014                }
2015            }
2016            else
2017            {    // close the write packet if write request not in the same cache line
2018                r_dcache_write_req = true;
2019                m_cost_write_frz++;
2020                break;  //  posting not possible : stay in DCACHE_WRITEREQ state
2021            }
2022        }
2023        else     //  previous write transaction not completed
2024        {
2025            m_cost_write_frz++;
2026            break;  //  posting not possible : stay in DCACHE_WRITEREQ state
2027        }
2028
2029        // close the write packet if the next processor request is not a write
2030        if ( !dreq.valid || (dreq.type != iss_t::DATA_WRITE))
2031        {
2032            r_dcache_write_req = true;
2033        }
2034       
2035        // The next state and the processor request parameters are computed
2036        // as in the DCACHE_IDLE state (see below ...)
2037    }
2038    /////////////////
2039    case DCACHE_IDLE:
2040    {
2041        // external cache invalidate request
2042        if ( r_tgt_dcache_req )   
2043        {
2044            r_dcache_fsm = DCACHE_CC_CHECK;
2045            r_dcache_fsm_save = DCACHE_IDLE;
2046            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
2047            break;
2048        }       
2049
2050        // ins tlb cleanup
2051        if ( r_dcache_itlb_cleanup_req )
2052        {
2053            r_dcache_fsm = DCACHE_ITLB_CLEANUP;
2054            m_cpt_ins_tlb_cleanup++;
2055            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
2056            break;
2057        }   
2058        // ins tlb miss
2059        if ( r_itlb_read_dcache_req )
2060        {
2061            data_t rsp_itlb_miss;
2062            data_t rsp_itlb_ppn;
2063
2064            bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss);
2065            if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
2066            {   
2067                bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
2068                assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
2069            }
2070
2071            m_cpt_dcache_data_read += m_dcache_ways;
2072            m_cpt_dcache_dir_read += m_dcache_ways;
2073
2074            if ( itlb_hit_dcache )  // ins TLB request hits in data cache
2075            {
2076                r_dcache_rsp_itlb_miss = rsp_itlb_miss;
2077                r_dcache_rsp_itlb_ppn = rsp_itlb_ppn;
2078                r_itlb_read_dcache_req = false;
2079                r_dcache_fsm = DCACHE_IDLE;
2080               
2081                // set TLB bit if it's a PTE
2082                if ( !((rsp_itlb_miss & PTE_T_MASK ) >> PTE_T_SHIFT) )
2083                {
2084                    r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
2085                }
2086            }
2087            else                    // ins TLB request miss in data cache
2088            {
2089                r_dcache_itlb_read_req = true;
2090                r_dcache_fsm = DCACHE_ITLB_READ;
2091            }
2092            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
2093        }
2094        else if ( r_itlb_acc_dcache_req ) // ins tlb write access bit
2095        {
2096            bool write_hit = r_dcache.write(r_icache_paddr_save, r_icache_pte_update);
2097            assert(write_hit && "Write on miss ignores data");
2098            r_dcache_itlb_ll_acc_req = true;
2099            r_dcache_fsm = DCACHE_ITLB_LL_WAIT;                 
2100            if ( dreq.valid ) m_cost_data_waste_wait_frz++;
2101        }
2102        else if (dreq.valid)
2103        {
2104            pte_info_t  dcache_pte_info;
2105            int         xtn_opcod        = (int)dreq.addr/4;
2106            paddr_t     tlb_dpaddr       = 0;        // physical address obtained from TLB
2107            paddr_t     spc_dpaddr       = 0;        // physical adress obtained from PPN_save (speculative)
2108            bool        dcache_hit_t     = false;    // hit on 4Kilo TLB
2109            bool        dcache_hit_x     = false;    // VPN unmodified (can use spc_dpaddr)
2110            bool        dcache_hit_p     = false;    // PTP unmodified (can skip first level page table walk)
2111            bool        dcache_hit_c     = false;    // Cache hit
2112            bool        dcache_cached    = false;    // cacheable access (read or write)
2113            size_t      dcache_tlb_way   = 0;        // selected way (in case of cache hit)
2114            size_t      dcache_tlb_set   = 0;        // selected set (Y field in address)
2115            data_t      dcache_rdata     = 0;        // read data
2116            paddr_t     dcache_tlb_nline = 0;       // TLB NLINE
2117            bool        write_hit        = false;
2118
2119            m_cpt_dcache_data_read += m_dcache_ways;
2120            m_cpt_dcache_dir_read += m_dcache_ways;
2121
2122            // Decoding READ XTN requests from processor
2123            // They are executed in this DCACHE_IDLE state
2124
2125            if (dreq.type == iss_t::XTN_READ)
2126            {
2127                switch(xtn_opcod) {
2128                case iss_t::XTN_INS_ERROR_TYPE:
2129                    drsp.rdata = (uint32_t)r_icache_error_type;
2130                    r_icache_error_type = MMU_NONE;
2131                    drsp.valid = true;
2132                    drsp.error = false;
2133                    break;
2134                case iss_t::XTN_DATA_ERROR_TYPE:
2135                    drsp.rdata = (uint32_t)r_dcache_error_type;
2136                    r_dcache_error_type = MMU_NONE;
2137                    drsp.valid = true;
2138                    drsp.error = false;
2139                    break;
2140                case iss_t::XTN_INS_BAD_VADDR:
2141                    drsp.rdata = (uint32_t)r_icache_bad_vaddr;       
2142                    drsp.valid = true;
2143                    drsp.error = false;
2144                    break;
2145                case iss_t::XTN_DATA_BAD_VADDR:
2146                    drsp.rdata = (uint32_t)r_dcache_bad_vaddr;       
2147                    drsp.valid = true;
2148                    drsp.error = false;
2149                    break;
2150                case iss_t::XTN_PTPR:
2151                    drsp.rdata = (uint32_t)r_mmu_ptpr;
2152                    drsp.valid = true;
2153                    drsp.error = false;
2154                    break;
2155                case iss_t::XTN_TLB_MODE:
2156                    drsp.rdata = (uint32_t)r_mmu_mode;
2157                    drsp.valid = true;
2158                    drsp.error = false;
2159                    break;
2160                default:
2161                    r_dcache_error_type = MMU_READ_UNDEFINED_XTN;
2162                    r_dcache_bad_vaddr  = dreq.addr;
2163                    drsp.valid = true;
2164                    drsp.error = true;
2165                    break;
2166                }
2167                r_dcache_fsm = DCACHE_IDLE;
2168                break;
2169            }
2170
2171            // Decoding WRITE XTN requests from processor
2172            // If there is no privilege violation, they are not executed in this DCACHE_IDLE state,
2173            // but in the next state, because they generally require access to the caches or the TLBs
2174
2175            if (dreq.type == iss_t::XTN_WRITE)
2176            {
2177                drsp.valid = false;
2178                drsp.error = false;
2179                drsp.rdata = 0;
2180                r_dcache_wdata_save = dreq.wdata;   
2181                switch(xtn_opcod) {     
2182
2183                case iss_t::XTN_PTPR:       // context switch : checking the kernel mode
2184                                            // both instruction & data TLBs must be flushed
2185                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL))
2186                    {
2187                        r_mmu_ptpr = dreq.wdata;
2188                        r_icache_error_type = MMU_NONE;
2189                        r_dcache_error_type = MMU_NONE;
2190                        r_dcache_type_save = dreq.addr/4;
2191                        r_dcache_xtn_req = true;
2192                        r_dcache_fsm = DCACHE_CTXT_SWITCH;
2193                    }
2194                    else
2195                    {
2196                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
2197                        r_dcache_bad_vaddr  = dreq.addr;
2198                        drsp.valid = true;
2199                        drsp.error = true;
2200                        r_dcache_fsm = DCACHE_IDLE;
2201                    }
2202                    break;
2203
2204                case iss_t::XTN_TLB_MODE:     // modifying TLBs mode : checking the kernel mode
2205                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL))
2206                    {
2207                        r_mmu_mode = (int)dreq.wdata;
2208                        drsp.valid = true;
2209                    }
2210                    else
2211                    {
2212                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
2213                        r_dcache_bad_vaddr  = dreq.addr;
2214                        drsp.valid = true;
2215                        drsp.error = true;
2216                    }
2217                    r_dcache_fsm = DCACHE_IDLE;
2218                    break;
2219
2220                case iss_t::XTN_DTLB_INVAL:     //  checking the kernel mode
2221                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL))
2222                    {
2223                        r_dcache_fsm = DCACHE_DTLB_INVAL; 
2224                    }
2225                    else
2226                    {
2227                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
2228                        r_dcache_bad_vaddr  = dreq.addr;
2229                        drsp.valid = true;
2230                        drsp.error = true;
2231                        r_dcache_fsm = DCACHE_IDLE;
2232                    }
2233                    break;
2234
2235                case iss_t::XTN_ITLB_INVAL:     //  checking the kernel mode
2236                    if ((dreq.mode == iss_t::MODE_HYPER) || (dreq.mode == iss_t::MODE_KERNEL))
2237                    {
2238                        r_dcache_xtn_req = true;
2239                        r_dcache_type_save = dreq.addr/4;
2240                        r_dcache_fsm = DCACHE_ITLB_INVAL; 
2241                    }
2242                    else
2243                    {
2244                        r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
2245                        r_dcache_bad_vaddr  = dreq.addr;
2246                        drsp.valid = true;
2247                        drsp.error = true;
2248                        r_dcache_fsm = DCACHE_IDLE;
2249                    }
2250                    break;
2251
2252                case iss_t::XTN_DCACHE_INVAL:   // cache inval can be executed in user mode.
2253                    r_dcache_fsm = DCACHE_DCACHE_INVAL;
2254                    break;
2255
2256                case iss_t::XTN_DCACHE_FLUSH:   // cache flush can be executed in user mode.
2257                    r_dcache_type_save = dreq.addr/4;
2258                    r_dcache_xtn_req = true;
2259                    r_dcache_way = 0;
2260                    r_dcache_set = 0;
2261                    r_dcache_fsm = DCACHE_DCACHE_FLUSH;
2262                    break;
2263
2264                case iss_t::XTN_ICACHE_INVAL:   // cache inval can be executed in user mode.
2265                    r_dcache_type_save = dreq.addr/4;
2266                    r_dcache_xtn_req = true;
2267                    r_dcache_fsm = DCACHE_ICACHE_INVAL;
2268                    break;
2269
2270                case iss_t::XTN_ICACHE_FLUSH:   // cache flush can be executed in user mode.
2271                    r_dcache_type_save = dreq.addr/4;
2272                    r_dcache_xtn_req = true;
2273                    r_dcache_fsm = DCACHE_ICACHE_FLUSH;
2274                    break;
2275
2276                case iss_t::XTN_SYNC:           // cache synchronization can be executed in user mode.
2277                    if (r_wbuf.rok())
2278                    {
2279                        r_dcache_fsm = DCACHE_DCACHE_SYNC;
2280                    }
2281                    else
2282                    {
2283                        drsp.valid = true;
2284                        r_dcache_fsm = DCACHE_IDLE;
2285                    }
2286                    break;
2287
2288                default:
2289                    r_dcache_error_type = MMU_WRITE_UNDEFINED_XTN;
2290                    r_dcache_bad_vaddr  = dreq.addr;
2291                    drsp.valid = true;
2292                    drsp.error = true;
2293                    r_dcache_fsm = DCACHE_IDLE;
2294                    break;
2295                } // end switch xtn_opcod
2296
2297                break;
2298            } // end if XTN_WRITE
2299
2300            // Evaluating dcache_hit_t, dcache_hit_x, dcache_hit_p, dcache_hit_c,
2301            // dcache_pte_info, dcache_tlb_way, dcache_tlb_set & dpaddr & cacheability
2302            // - If MMU activated : cacheability is defined by the cachable bit in the TLB
2303            // - If MMU not activated : cacheability is defined by the segment table.
2304
2305            if ( !(r_mmu_mode.read() & DATA_TLB_MASK) ) // MMU not activated
2306            {
2307                dcache_hit_t  = true;       
2308                dcache_hit_x  = true;   
2309                dcache_hit_p  = true; 
2310                tlb_dpaddr    = dreq.addr;
2311                spc_dpaddr    = dreq.addr;   
2312                dcache_cached = m_cacheability_table[dreq.addr] &&
2313                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
2314                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));     
2315            }
2316            else                                                            // MMU activated
2317            {
2318                m_cpt_data_tlb_read++;
2319                dcache_hit_t  = dcache_tlb.cctranslate(dreq.addr, &tlb_dpaddr, &dcache_pte_info,
2320                                                       &dcache_tlb_nline, &dcache_tlb_way, &dcache_tlb_set);                 
2321                dcache_hit_x  = (((vaddr_t)r_dcache_vpn_save << PAGE_K_NBITS) == (dreq.addr & ~PAGE_K_MASK)) && r_dtlb_translation_valid;
2322                dcache_hit_p  = (((dreq.addr >> PAGE_M_NBITS) == r_dcache_id1_save) && r_dcache_ptba_ok );
2323                spc_dpaddr    = ((paddr_t)r_dcache_ppn_save << PAGE_K_NBITS) | (paddr_t)((dreq.addr & PAGE_K_MASK));
2324                dcache_cached = dcache_pte_info.c &&
2325                                ((dreq.type != iss_t::DATA_LL)  && (dreq.type != iss_t::DATA_SC) &&
2326                                 (dreq.type != iss_t::XTN_READ) && (dreq.type != iss_t::XTN_WRITE));   
2327            }
2328
2329            if ( !(r_mmu_mode.read() & DATA_CACHE_MASK) )   // cache not actived
2330            {
2331                dcache_cached = false;
2332            }
2333
2334            // dcache_hit_c & dcache_rdata
2335            if ( dcache_cached )    // using speculative physical address for cached access
2336            {
2337                dcache_hit_c = r_dcache.read(spc_dpaddr, &dcache_rdata);
2338            }
2339            else                    // using actual physical address for uncached access
2340            {
2341                dcache_hit_c = ((tlb_dpaddr == (paddr_t)r_dcache_paddr_save) && r_dcache_buf_unc_valid );
2342                dcache_rdata = r_dcache_miss_buf[0];
2343            }
2344
2345            if ( r_mmu_mode.read() & DATA_TLB_MASK )
2346            {
2347                // Checking access rights
2348                if ( dcache_hit_t )
2349                {
2350                    if (!dcache_pte_info.u && (dreq.mode == iss_t::MODE_USER))
2351                    {
2352                        if ((dreq.type == iss_t::DATA_READ)||(dreq.type == iss_t::DATA_LL))
2353                        {
2354                            r_dcache_error_type = MMU_READ_PRIVILEGE_VIOLATION;
2355                        }
2356                        else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
2357                        {
2358                            r_dcache_error_type = MMU_WRITE_PRIVILEGE_VIOLATION;
2359                        } 
2360                        r_dcache_bad_vaddr = dreq.addr;
2361                        drsp.valid = true;
2362                        drsp.error = true;
2363                        drsp.rdata = 0;
2364                        r_dcache_fsm = DCACHE_IDLE;
2365                        break;
2366                    }
2367                    if (!dcache_pte_info.w && ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC)))
2368                    {
2369                        r_dcache_error_type = MMU_WRITE_ACCES_VIOLATION; 
2370                        r_dcache_bad_vaddr = dreq.addr;
2371                        drsp.valid = true;
2372                        drsp.error = true;
2373                        drsp.rdata = 0;
2374                        r_dcache_fsm = DCACHE_IDLE;
2375                        break;
2376                    }
2377                }
2378
2379                // update LRU, save ppn, vpn and page type
2380                if ( dcache_hit_t ) {
2381                    dcache_tlb.setlru(dcache_tlb_way,dcache_tlb_set);
2382                    r_dcache_ppn_save = tlb_dpaddr >> PAGE_K_NBITS;
2383                    r_dcache_vpn_save = dreq.addr >> PAGE_K_NBITS;
2384                    r_dcache_tlb_nline = dcache_tlb_nline;
2385                    r_dtlb_translation_valid = true;
2386                }
2387                else
2388                {
2389                    r_dtlb_translation_valid = false;
2390                }
2391
2392            } // end if MMU activated
2393
2394            // compute next state
2395            if ( !dcache_hit_p && !dcache_hit_t )  // TLB miss
2396            {
2397                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
2398                r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
2399                m_cpt_data_tlb_miss++;
2400                m_cost_data_tlb_miss_frz++;
2401            }
2402            else if ( dcache_hit_p && !dcache_hit_t )  // TLB Miss with possibility of bypass first level page
2403            {
2404                // walk page table level 2
2405                r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save |
2406                                     (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
2407                r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
2408                m_cpt_data_tlb_miss++;
2409                m_cost_data_tlb_miss_frz++;
2410            }
2411            else if ( dcache_hit_t && !dcache_hit_x && dcache_cached )// cached access with an ucorrect speculative physical address
2412            {
2413                r_dcache_hit_p_save = dcache_hit_p;
2414                r_dcache_fsm = DCACHE_BIS;
2415                m_cost_data_miss_frz++;
2416            }
2417            else  // cached or uncached access with a correct speculative physical address
2418            {
2419                switch( dreq.type ) {
2420                    case iss_t::DATA_READ:
2421                    case iss_t::DATA_LL:
2422                    case iss_t::DATA_SC:
2423                        m_cpt_read++;
2424                        if ( dcache_hit_c )
2425                        {
2426                            r_dcache_buf_unc_valid = false;
2427                            r_dcache_fsm = DCACHE_IDLE;
2428                            drsp.valid = true;
2429                            drsp.rdata = dcache_rdata;
2430                        }
2431                        else
2432                        {
2433                            if ( dcache_cached )
2434                            {
2435                                r_dcache_miss_req = true;
2436                                r_dcache_fsm = DCACHE_MISS_WAIT;
2437                                m_cpt_data_miss++;
2438                                m_cost_data_miss_frz++;
2439                            }
2440                            else
2441                            {
2442                                r_dcache_unc_req = true;
2443                                r_dcache_fsm = DCACHE_UNC_WAIT;
2444                                m_cpt_unc_read++;
2445                                m_cost_unc_read_frz++;
2446                            }
2447                        }
2448                        break;
2449/*
2450                    case iss_t::DATA_READ:
2451                        m_cpt_read++;
2452                        if ( dcache_hit_c )
2453                        {
2454                            r_dcache_buf_unc_valid = false;
2455                            r_dcache_fsm = DCACHE_IDLE;
2456                            drsp.valid = true;
2457                            drsp.rdata = dcache_rdata;
2458                        }
2459                        else
2460                        {
2461                            if ( dcache_cached )
2462                            {
2463                                r_dcache_miss_req = true;
2464                                r_dcache_fsm = DCACHE_MISS_WAIT;
2465                                m_cpt_data_miss++;
2466                                m_cost_data_miss_frz++;
2467                            }
2468                            else
2469                            {
2470                                r_dcache_unc_req = true;
2471                                r_dcache_fsm = DCACHE_UNC_WAIT;
2472                                m_cpt_unc_read++;
2473                                m_cost_unc_read_frz++;
2474                            }
2475                        }
2476                        break;
2477                    case iss_t::DATA_LL:
2478                        if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr) && r_dcache_buf_unc_valid)
2479                        {
2480                            r_dcache_buf_unc_valid = false;
2481                            r_dcache_fsm = DCACHE_IDLE;
2482                            drsp.valid = true;
2483                            drsp.rdata = dcache_rdata;
2484                        }
2485                        else
2486                        {
2487                            r_dcache_llsc_reserved = true;
2488                            r_dcache_llsc_addr_save = tlb_dpaddr;
2489                            r_dcache_unc_req = true;
2490                            r_dcache_fsm = DCACHE_UNC_WAIT;
2491                        }
2492                        break;
2493                    case iss_t::DATA_SC:
2494                        if (r_dcache_llsc_reserved && (r_dcache_llsc_addr_save == tlb_dpaddr))
2495                        {
2496                            r_dcache_llsc_reserved = false;
2497                            r_dcache_unc_req = true;
2498                            r_dcache_fsm = DCACHE_UNC_WAIT;
2499                        }
2500                        else
2501                        {   
2502                            if ( r_dcache_buf_unc_valid )
2503                            {                         
2504                                r_dcache_llsc_reserved = false;
2505                                r_dcache_buf_unc_valid = false;
2506                                drsp.valid = true;
2507                                drsp.rdata = dcache_rdata;
2508                            }
2509                            r_dcache_fsm = DCACHE_IDLE;
2510                        }                       
2511                        break;
2512*/
2513                    case iss_t::DATA_WRITE:
2514                        m_cpt_write++;
2515                        if ( dcache_cached ) m_cpt_write_cached++;
2516
2517                        if ( dcache_hit_c && dcache_cached )    // cache update required
2518                        {
2519                            r_dcache_fsm = DCACHE_WRITE_UPDT;
2520                        }
2521                        else if ( !dcache_pte_info.d && (r_mmu_mode.read() & DATA_TLB_MASK) )   // dirty bit update required
2522                        {
2523                            if ( dcache_tlb.getpagesize(dcache_tlb_way, dcache_tlb_set) )       // 2M page size, one level page table
2524                            {
2525                                r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
2526                                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
2527                                write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2),
2528                                                           (dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK));
2529                                assert(write_hit && "Write on miss ignores data");
2530                                r_dcache_tlb_ll_dirty_req = true;
2531                                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2532                                m_cpt_data_tlb_write_dirty++;
2533                            }
2534                            else        // 4k page size, two levels page table
2535                            {   
2536                                if (dcache_hit_p)
2537                                {
2538                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
2539                                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
2540                                    write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save | (paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)),
2541                                                       (dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK));
2542                                    assert(write_hit && "Write on miss ignores data");
2543                                    r_dcache_tlb_ll_dirty_req = true;
2544                                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2545                                    m_cpt_data_tlb_write_dirty++;
2546                                }
2547                                else    // get PTBA to calculate the physical address of PTE
2548                                {
2549                                    r_dcache_pte_update = dcache_tlb.getpte(dcache_tlb_way, dcache_tlb_set) | PTE_D_MASK;
2550                                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
2551                                    r_dcache_tlb_ptba_read = true;
2552                                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
2553                                }
2554                            }
2555                            m_cost_data_tlb_miss_frz++;
2556                        }
2557                        else                                    // no cache update, not dirty bit update
2558                        {
2559                            r_dcache_fsm = DCACHE_WRITE_REQ;
2560                            drsp.valid = true;
2561                            drsp.rdata = 0;
2562                        }
2563                        break;
2564                    default:
2565                        break;
2566                } // end switch dreq.type
2567            } // end if next states
2568
2569            // save values for the next states
2570            r_dcache_paddr_save   = tlb_dpaddr;
2571            r_dcache_type_save    = dreq.type;
2572            r_dcache_wdata_save   = dreq.wdata;
2573            r_dcache_be_save      = dreq.be;
2574            r_dcache_rdata_save   = dcache_rdata;
2575            r_dcache_cached_save  = dcache_cached;
2576            r_dcache_dirty_save   = dcache_pte_info.d;
2577            r_dcache_tlb_set_save = dcache_tlb_set;
2578            r_dcache_tlb_way_save = dcache_tlb_way;
2579
2580        } // end if dreq.valid
2581        else
2582        {   
2583            r_dcache_fsm = DCACHE_IDLE;
2584        }
2585
2586        // processor request are not accepted in the WRITE_REQ state
2587        // when the write buffer is not writeable
2588
2589        if ((r_dcache_fsm == DCACHE_WRITE_REQ) &&
2590            (r_dcache_write_req || !r_wbuf.wok(r_dcache_paddr_save)))
2591        {
2592            drsp.valid = false;
2593        }
2594        break;
2595    }
2596    /////////////////
2597    case DCACHE_BIS:
2598    {
2599        // external cache invalidate request
2600        if ( r_tgt_dcache_req )   
2601        {
2602            r_dcache_fsm = DCACHE_CC_CHECK;
2603            r_dcache_fsm_save = r_dcache_fsm;
2604            m_cost_data_waste_wait_frz++;
2605            break;
2606        }
2607
2608        // Using tlb entry is invalidated
2609        if ( r_dcache_inval_tlb_rsp )
2610        {
2611            r_dcache_inval_tlb_rsp = false;
2612            r_dcache_fsm = DCACHE_IDLE;
2613            m_cost_data_tlb_miss_frz++;
2614            break;
2615        }
2616
2617        bool    dcache_hit   = false;
2618        bool    write_hit    = false;
2619        data_t  dcache_rdata = 0;
2620
2621        // acces always cached in this state
2622        dcache_hit = r_dcache.read(r_dcache_paddr_save, &dcache_rdata);
2623
2624        if ( dreq.type == iss_t::DATA_READ )  // cached read
2625        {
2626            m_cpt_read++;
2627            if ( !dcache_hit )
2628            {
2629                r_dcache_miss_req = true;
2630                r_dcache_fsm = DCACHE_MISS_WAIT;
2631                m_cpt_data_miss++;
2632                m_cost_data_miss_frz++;
2633            }
2634            else
2635            {
2636                r_dcache_fsm = DCACHE_IDLE;
2637            }
2638            drsp.valid = dcache_hit;
2639            drsp.error = false;
2640            drsp.rdata = dcache_rdata;
2641        }
2642        else    // cached write
2643        {
2644            m_cpt_write++;
2645            m_cpt_write_cached++;
2646            if ( dcache_hit )    // cache update required
2647            {
2648                r_dcache_rdata_save = dcache_rdata;
2649                r_dcache_fsm = DCACHE_WRITE_UPDT;
2650            }
2651            else if (!r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK))   // dirty bit update required
2652            {
2653                if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
2654                {
2655                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
2656                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
2657                    write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2),
2658                                               (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
2659                    assert(write_hit && "Write on miss ignores data");
2660                    r_dcache_tlb_ll_dirty_req = true;
2661                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2662                    m_cpt_data_tlb_write_dirty++;
2663                }
2664                else
2665                {   
2666                    if (r_dcache_hit_p_save)
2667                    {
2668                        r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
2669                        r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
2670                        write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)),
2671                                                    (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
2672                        assert(write_hit && "Write on miss ignores data");
2673                        r_dcache_tlb_ll_dirty_req = true;
2674                        r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2675                        m_cpt_data_tlb_write_dirty++;
2676                    }
2677                    else
2678                    {
2679                        r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
2680                        r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
2681                        r_dcache_tlb_ptba_read = true;
2682                        r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
2683                    }
2684                }
2685                m_cost_data_tlb_miss_frz++;
2686            }
2687            else                                    // no cache update, not dirty bit update
2688            {
2689                r_dcache_fsm = DCACHE_WRITE_REQ;
2690                drsp.valid = true;
2691                drsp.rdata = 0;
2692            }
2693        }
2694        break;
2695    }
2696    //////////////////////////
2697    case DCACHE_LL_DIRTY_WAIT:
2698    {
2699        // external cache invalidate request
2700        if ( r_tgt_dcache_req )   
2701        {
2702            r_dcache_fsm = DCACHE_CC_CHECK;
2703            r_dcache_fsm_save = r_dcache_fsm;
2704            m_cost_data_waste_wait_frz++;
2705            break;
2706        }
2707
2708        if (!r_dcache_tlb_ll_dirty_req)
2709        {
2710            if ( r_vci_rsp_data_error ) // VCI response ko
2711            {
2712                if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
2713                {
2714                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;     
2715                }
2716                else
2717                {
2718                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;     
2719                }
2720                r_dcache_bad_vaddr = dreq.addr;
2721                r_dcache_fsm = DCACHE_ERROR;
2722
2723                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
2724                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
2725            }
2726            else
2727            {
2728                if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )   // unmapped
2729                {
2730                    if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
2731                    {
2732                        r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;       
2733                    }
2734                    else
2735                    {
2736                        r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;       
2737                    }
2738                    r_dcache_bad_vaddr = dreq.addr;
2739                    r_dcache_fsm = DCACHE_ERROR;
2740
2741                    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
2742                    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
2743                }
2744                else if ( r_dcache_inval_tlb_rsp )
2745                {
2746                    r_dcache_inval_tlb_rsp = false;
2747                    r_dcache_fsm = DCACHE_IDLE;
2748                    m_cost_data_tlb_miss_frz++;
2749                }
2750                else if ( r_dcache_inval_rsp )
2751                {
2752                    r_dcache_inval_rsp = false;
2753                    r_dcache_fsm = DCACHE_IDLE;
2754                }
2755                else
2756                {
2757                    r_dcache_tlb_sc_dirty_req = true;
2758                    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
2759                    r_dcache_fsm = DCACHE_SC_DIRTY_WAIT;
2760                }
2761            }
2762        }
2763        break;
2764    }
2765    //////////////////////////
2766    case DCACHE_SC_DIRTY_WAIT:
2767    {
2768        // external cache invalidate request
2769        if ( r_tgt_dcache_req )   
2770        {
2771            r_dcache_fsm = DCACHE_CC_CHECK;
2772            r_dcache_fsm_save = r_dcache_fsm;
2773            m_cost_data_waste_wait_frz++;
2774            break;
2775        }
2776
2777        if ( !r_dcache_tlb_sc_dirty_req )
2778        {
2779            if ( r_vci_rsp_data_error ) // VCI response ko
2780            {
2781                if (dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save))
2782                {
2783                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;   
2784                }
2785                else
2786                {
2787                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;   
2788                }
2789                r_dcache_bad_vaddr = dreq.addr;
2790                r_dcache_fsm = DCACHE_ERROR;
2791
2792                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
2793                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;                                      }
2794            else
2795            {
2796                // Using tlb entry is invalidated
2797                if ( r_dcache_inval_tlb_rsp )
2798                {
2799                    r_dcache_inval_tlb_rsp = false;
2800                    r_dcache_fsm = DCACHE_IDLE;
2801                    m_cost_data_tlb_miss_frz++;
2802                }
2803                else if ( r_dcache_inval_rsp )
2804                {
2805                    r_dcache_inval_rsp = false;
2806                    r_dcache_fsm = DCACHE_IDLE;
2807                }
2808                else if ( r_dcache_tlb_ll_dirty_req )
2809                {
2810                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2811                }
2812                else
2813                {
2814                    r_dcache_fsm = DCACHE_WRITE_DIRTY;
2815                }
2816            }
2817        }
2818        break;
2819    }
2820    ////////////////////////////
2821    case DCACHE_DTLB1_READ_CACHE:
2822    {
2823        m_cost_data_tlb_miss_frz++;
2824
2825        // external cache invalidate request
2826        if ( r_tgt_dcache_req )   
2827        {
2828            r_dcache_fsm = DCACHE_CC_CHECK;
2829            r_dcache_fsm_save = r_dcache_fsm;
2830            m_cost_data_waste_wait_frz++;
2831            break;
2832        }       
2833
2834        // Using tlb entry is invalidated
2835        if ( r_dcache_inval_tlb_rsp )
2836        {
2837            r_dcache_inval_tlb_rsp = false;
2838            r_dcache_fsm = DCACHE_IDLE;
2839            m_cost_data_tlb_miss_frz++;
2840            break;
2841        }
2842
2843        data_t tlb_data = 0;
2844        bool write_hit = false;
2845        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
2846
2847        // DTLB request hit in cache
2848        if ( tlb_hit_cache )
2849        {
2850            if ( !(tlb_data >> PTE_V_SHIFT) )   // unmapped
2851            {
2852                r_dcache_ptba_ok    = false;
2853                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
2854                {
2855                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
2856                }
2857                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
2858                {
2859                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
2860                } 
2861                r_dcache_bad_vaddr  = dreq.addr;
2862                r_dcache_fsm        = DCACHE_ERROR;
2863            }
2864            else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT )  // PTD
2865            {
2866                r_dcache_ptba_ok   = true;
2867                r_dcache_ptba_save = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS; 
2868                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
2869                r_dcache_tlb_paddr = (paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
2870                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
2871                if ( r_dcache_tlb_ptba_read )
2872                {
2873                    r_dcache_tlb_ptba_read = false;
2874                    write_hit = r_dcache.write(((paddr_t)(tlb_data & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
2875                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)), r_dcache_pte_update);
2876                    assert(write_hit && "Write on miss ignores data");
2877                    r_dcache_tlb_ll_dirty_req = true;
2878                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
2879                    m_cpt_data_tlb_write_dirty++;
2880                }
2881                else
2882                {
2883                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
2884                }
2885            }
2886            else        // PTE
2887            {
2888                r_dcache_ptba_ok = false;
2889                if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
2890                {
2891                    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
2892                    {
2893                        r_dcache_pte_update = tlb_data;
2894                        r_dcache_fsm = DCACHE_TLB1_UPDT;
2895                    }
2896                    else
2897                    {
2898                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
2899                        r_dcache_tlb_ll_acc_req = true;
2900                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK)); 
2901                        assert(write_hit && "Write on miss ignores data"); 
2902                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
2903                        m_cpt_ins_tlb_write_et++;
2904                    }
2905                }
2906                else // remotely
2907                {
2908                    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
2909                    {
2910                        r_dcache_pte_update = tlb_data;
2911                        r_dcache_fsm = DCACHE_TLB1_UPDT;
2912                    }
2913                    else
2914                    {
2915                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
2916                        r_dcache_tlb_ll_acc_req = true;
2917                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK)); 
2918                        assert(write_hit && "Write on miss ignores data"); 
2919                        r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
2920                        m_cpt_ins_tlb_write_et++;
2921                    }
2922                }
2923            }
2924        }
2925        else
2926        {
2927            // DTLB request miss in cache and walk page table level 1
2928            r_dcache_tlb_read_req = true;
2929            r_dcache_fsm = DCACHE_TLB1_READ;
2930        }
2931        break;
2932    }
2933    ///////////////////////
2934    case DCACHE_TLB1_LL_WAIT:
2935    {
2936        // external cache invalidate request
2937        if ( r_tgt_dcache_req )   
2938        {
2939            r_dcache_fsm = DCACHE_CC_CHECK;
2940            r_dcache_fsm_save = r_dcache_fsm;
2941            m_cost_data_waste_wait_frz++;
2942            break;
2943        }
2944
2945        if (!r_dcache_tlb_ll_acc_req)
2946        {
2947            if ( r_vci_rsp_data_error ) // VCI response ko
2948            {
2949                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
2950                {
2951                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
2952                }
2953                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
2954                {
2955                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
2956                }
2957                r_dcache_bad_vaddr = dreq.addr;
2958                r_dcache_fsm = DCACHE_ERROR;
2959
2960                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
2961                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;             
2962            }
2963            else
2964            {
2965                if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )   // unmapped
2966                {
2967                    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
2968                    {
2969                        r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
2970                    }
2971                    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
2972                    {
2973                        r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
2974                    }
2975                    r_dcache_bad_vaddr  = dreq.addr;
2976                    r_dcache_fsm        = DCACHE_ERROR;
2977
2978                    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
2979                    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
2980                }
2981                else if ( r_dcache_inval_tlb_rsp )
2982                {
2983                    r_dcache_inval_tlb_rsp = false;
2984                    r_dcache_fsm = DCACHE_IDLE;
2985                    m_cost_data_tlb_miss_frz++;
2986                }
2987                else if ( r_dcache_inval_rsp )
2988                {
2989                    r_dcache_inval_rsp = false;
2990                    r_dcache_fsm = DCACHE_IDLE;
2991                }
2992                else
2993                {
2994                    r_dcache_tlb_sc_acc_req = true;
2995                    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
2996                    r_dcache_fsm = DCACHE_TLB1_SC_WAIT;
2997                }
2998            }
2999        }
3000        break;
3001    }
3002    ///////////////////////
3003    case DCACHE_TLB1_SC_WAIT:
3004    {
3005        // external cache invalidate request
3006        if ( r_tgt_dcache_req )   
3007        {
3008            r_dcache_fsm = DCACHE_CC_CHECK;
3009            r_dcache_fsm_save = r_dcache_fsm;
3010            m_cost_data_waste_wait_frz++;
3011            break;
3012        }
3013
3014        if ( !r_dcache_tlb_sc_acc_req )
3015        {
3016            if ( r_vci_rsp_data_error ) // VCI response ko
3017            {
3018                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3019                {
3020                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
3021                }
3022                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3023                {
3024                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
3025                }
3026                r_dcache_bad_vaddr = dreq.addr;
3027                r_dcache_fsm = DCACHE_ERROR;
3028
3029                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3030                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;     
3031            }
3032            else
3033            {
3034                // Using tlb entry is invalidated
3035                if ( r_dcache_inval_tlb_rsp )
3036                {
3037                    r_dcache_inval_tlb_rsp = false;
3038                    r_dcache_fsm = DCACHE_IDLE;
3039                    m_cost_data_tlb_miss_frz++;
3040                }
3041                else if ( r_dcache_inval_rsp )
3042                {
3043                    r_dcache_inval_rsp = false;
3044                    r_dcache_fsm = DCACHE_IDLE;
3045                }
3046                else if ( r_dcache_tlb_ll_acc_req )
3047                {
3048                    r_dcache_fsm = DCACHE_TLB1_LL_WAIT;
3049                }
3050                else
3051                {
3052                    r_dcache_fsm = DCACHE_TLB1_UPDT;
3053                }
3054            }
3055        }
3056        break;
3057    }
3058    //////////////////////
3059    case DCACHE_TLB1_READ:
3060    {
3061        m_cost_data_tlb_miss_frz++;
3062
3063        // external cache invalidate request
3064        if ( r_tgt_dcache_req )   
3065        {
3066            r_dcache_fsm = DCACHE_CC_CHECK;
3067            r_dcache_fsm_save = r_dcache_fsm;
3068            m_cost_data_waste_wait_frz++;
3069            break;
3070        }       
3071
3072        if ( !r_dcache_tlb_read_req )
3073        {       
3074            if ( r_vci_rsp_data_error ) // VCI response ko
3075            {
3076                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3077                {
3078                    r_dcache_error_type = MMU_READ_PT1_ILLEGAL_ACCESS;
3079                }
3080                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3081                {
3082                    r_dcache_error_type = MMU_WRITE_PT1_ILLEGAL_ACCESS;
3083                }
3084                r_dcache_bad_vaddr = dreq.addr;
3085                r_dcache_fsm = DCACHE_ERROR;
3086
3087                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3088                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;     
3089                break;
3090            }
3091
3092            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
3093            {
3094                r_dcache_fsm = DCACHE_IDLE;
3095                r_dcache_inval_tlb_rsp = false;
3096                break;
3097            }
3098
3099            if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
3100            {
3101                r_dcache_fsm = DCACHE_IDLE;
3102                r_dcache_inval_rsp = false;
3103                break;     
3104            }
3105            // TLB miss response and no invalidation
3106            r_dcache_fsm = DCACHE_TLB1_READ_UPDT;
3107        }
3108        break;
3109    }
3110    //////////////////////////
3111    case DCACHE_TLB1_READ_UPDT:
3112    {
3113        m_cost_data_tlb_miss_frz++;
3114
3115        // external cache invalidate request
3116        if ( r_tgt_dcache_req )   
3117        {
3118            r_dcache_fsm = DCACHE_CC_CHECK;
3119            r_dcache_fsm_save = r_dcache_fsm;
3120            m_cost_data_waste_wait_frz++;
3121            break;
3122        }       
3123
3124        // Using tlb entry is invalidated
3125        if ( r_dcache_inval_tlb_rsp )
3126        {
3127            r_dcache_inval_tlb_rsp = false;
3128            r_dcache_fsm = DCACHE_IDLE;
3129            m_cost_data_tlb_miss_frz++;
3130            break;
3131        }
3132
3133        // Using tlb entry is in the invalidated cache line 
3134        if ( r_dcache_inval_rsp )
3135        {
3136            r_dcache_inval_rsp = false;
3137            r_dcache_fsm = DCACHE_IDLE;
3138            m_cost_data_tlb_miss_frz++;
3139            break;
3140        }
3141
3142        if ( !r_dcache_cleanup_req ) // Miss update and no invalidation
3143        {
3144            // update dcache
3145            data_t   rsp_dtlb_miss = 0;
3146            paddr_t  victim_index = 0;
3147            bool write_hit = false;
3148            size_t way = 0;
3149            size_t set = 0;
3150
3151            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
3152           
3153            if ( cleanup_req )
3154            {       
3155                // ins tlb invalidate verification   
3156                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
3157                r_dcache_itlb_inval_line = victim_index;
3158                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
3159
3160                // data tlb invalidate verification
3161                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
3162                r_dcache_dtlb_inval_line = victim_index;
3163                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
3164
3165                r_dcache_cleanup_req = true;
3166                r_dcache_cleanup_line = victim_index;
3167                r_dcache_fsm = DCACHE_TLB_CC_INVAL;
3168                r_dcache_fsm_save = r_dcache_fsm;
3169                break;
3170            }
3171
3172            r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
3173            r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss); 
3174
3175            if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )      // unmapped
3176            {
3177                r_dcache_ptba_ok    = false;
3178                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3179                {
3180                    r_dcache_error_type = MMU_READ_PT1_UNMAPPED;
3181                }
3182                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3183                {
3184                    r_dcache_error_type = MMU_WRITE_PT1_UNMAPPED;
3185                }
3186                r_dcache_bad_vaddr  = dreq.addr;
3187                r_dcache_fsm        = DCACHE_ERROR;
3188            }
3189            else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
3190            {
3191                r_dcache_ptba_ok   = true;
3192                r_dcache_ptba_save = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS; 
3193                r_dcache_id1_save  = dreq.addr >> PAGE_M_NBITS;
3194                r_dcache_tlb_paddr = (paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
3195                                     (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
3196                if ( r_dcache_tlb_ptba_read )
3197                {
3198                    r_dcache_tlb_ptba_read = false;
3199                    write_hit = r_dcache.write(((paddr_t)(rsp_dtlb_miss & ((1<<(m_paddr_nbits - PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
3200                                                (paddr_t)(((dreq.addr & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3)),r_dcache_pte_update);
3201                    assert(write_hit && "Write on miss ignores data");
3202                    r_dcache_tlb_ll_dirty_req = true;
3203                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
3204                    m_cpt_data_tlb_write_dirty++;
3205                }
3206                else
3207                {
3208                    r_dcache_fsm = DCACHE_DTLB2_READ_CACHE;
3209                }
3210            }
3211            else        // PTE
3212            {
3213                r_dcache_ptba_ok = false;
3214                if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
3215                {
3216                    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
3217                    {
3218                        r_dcache_pte_update = rsp_dtlb_miss;
3219                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
3220                    }
3221                    else
3222                    {
3223                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
3224                        r_dcache_tlb_ll_acc_req = true;
3225                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK)); 
3226                        assert(write_hit && "Write on miss ignores data"); 
3227                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
3228                        m_cpt_ins_tlb_write_et++;
3229                    }
3230                }
3231                else // remotely
3232                {
3233                    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
3234                    {
3235                        r_dcache_pte_update = rsp_dtlb_miss;
3236                        r_dcache_fsm        = DCACHE_TLB1_UPDT;
3237                    }
3238                    else
3239                    {
3240                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
3241                        r_dcache_tlb_ll_acc_req = true;
3242                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK)); 
3243                        assert(write_hit && "Write on miss ignores data"); 
3244                        r_dcache_fsm        = DCACHE_TLB1_LL_WAIT;
3245                        m_cpt_ins_tlb_write_et++;
3246                    }
3247                }
3248            }
3249        }
3250        break;
3251    }
3252    //////////////////////
3253    case DCACHE_TLB1_UPDT:
3254    {
3255        m_cost_data_tlb_miss_frz++;
3256
3257        // external cache invalidate request
3258        if ( r_tgt_dcache_req )   
3259        {
3260            r_dcache_fsm = DCACHE_CC_CHECK;
3261            r_dcache_fsm_save = r_dcache_fsm;
3262            m_cost_data_waste_wait_frz++;
3263            break;
3264        }       
3265
3266        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
3267        {
3268            paddr_t victim_index = 0;
3269            if (dcache_tlb.update(r_dcache_pte_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
3270            {
3271                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
3272            }
3273            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
3274            r_dcache_fsm = DCACHE_IDLE;
3275        }
3276        else 
3277        {
3278            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
3279            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
3280            r_dcache_fsm = DCACHE_IDLE;
3281        }
3282        break;
3283    }
3284    /////////////////////////////
3285    case DCACHE_DTLB2_READ_CACHE:
3286    {
3287        m_cost_data_tlb_miss_frz++;
3288
3289        // external cache invalidate request
3290        if ( r_tgt_dcache_req )   
3291        {
3292            r_dcache_fsm = DCACHE_CC_CHECK;
3293            r_dcache_fsm_save = r_dcache_fsm;
3294            m_cost_data_waste_wait_frz++;
3295            break;
3296        }       
3297
3298        // Using tlb entry is invalidated
3299        if ( r_dcache_inval_tlb_rsp )
3300        {
3301            r_dcache_inval_tlb_rsp = false;
3302            r_dcache_fsm = DCACHE_IDLE;
3303            m_cost_data_tlb_miss_frz++;
3304            break;
3305        }
3306
3307        data_t tlb_data = 0;
3308        data_t tlb_data_ppn = 0;
3309        bool write_hit = false;
3310        bool tlb_hit_cache = r_dcache.read(r_dcache_tlb_paddr, &tlb_data);
3311
3312        if ( tlb_hit_cache )
3313        {
3314            bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
3315            assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
3316        }
3317
3318        // DTLB request hit in cache
3319        if ( tlb_hit_cache )
3320        {
3321            if ( !(tlb_data >> PTE_V_SHIFT) )   // unmapped
3322            {
3323                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3324                {
3325                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
3326                }
3327                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3328                {
3329                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
3330                }
3331                r_dcache_bad_vaddr  = dreq.addr;
3332                r_dcache_fsm        = DCACHE_ERROR;
3333            }
3334            else if ( (tlb_data & PTE_T_MASK) >> PTE_T_SHIFT ) //PTD
3335            {
3336                r_dcache_pte_update = tlb_data;
3337                r_dcache_ppn_update = tlb_data_ppn;
3338                r_dcache_fsm = DCACHE_TLB2_UPDT;
3339            }
3340            else
3341            {
3342                if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
3343                {
3344                    if ( (tlb_data & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
3345                    {
3346                        r_dcache_pte_update = tlb_data;
3347                        r_dcache_ppn_update = tlb_data_ppn;
3348                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
3349                    }
3350                    else
3351                    {
3352                        r_dcache_pte_update = tlb_data | PTE_L_MASK;
3353                        r_dcache_ppn_update = tlb_data_ppn;
3354                        r_dcache_tlb_ll_acc_req = true;
3355                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_L_MASK)); 
3356                        assert(write_hit && "Write on miss ignores data"); 
3357                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
3358                        m_cpt_ins_tlb_write_et++;
3359                    }
3360                }
3361                else // remotely
3362                {
3363                    if ( (tlb_data & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
3364                    {
3365                        r_dcache_pte_update = tlb_data;
3366                        r_dcache_ppn_update = tlb_data_ppn;
3367                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
3368                    }
3369                    else
3370                    {
3371                        r_dcache_pte_update = tlb_data | PTE_R_MASK;
3372                        r_dcache_ppn_update = tlb_data_ppn;
3373                        r_dcache_tlb_ll_acc_req = true;
3374                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(tlb_data | PTE_R_MASK)); 
3375                        assert(write_hit && "Write on miss ignores data"); 
3376                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
3377                        m_cpt_ins_tlb_write_et++;
3378                    }
3379                }
3380            }
3381        }
3382        else
3383        {
3384            // DTLB request miss in cache and walk page table level 2
3385            r_dcache_tlb_read_req = true;
3386            r_dcache_fsm = DCACHE_TLB2_READ;
3387        }
3388        break;
3389    }
3390    ///////////////////////
3391    case DCACHE_TLB2_LL_WAIT:
3392    {
3393        // external cache invalidate request
3394        if ( r_tgt_dcache_req )   
3395        {
3396            r_dcache_fsm = DCACHE_CC_CHECK;
3397            r_dcache_fsm_save = r_dcache_fsm;
3398            m_cost_data_waste_wait_frz++;
3399            break;
3400        }
3401
3402        if (!r_dcache_tlb_ll_acc_req)
3403        {
3404            if ( r_vci_rsp_data_error ) // VCI response ko
3405            {
3406                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3407                {
3408                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
3409                }
3410                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3411                {
3412                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
3413                }
3414                r_dcache_bad_vaddr = dreq.addr;
3415                r_dcache_fsm = DCACHE_ERROR;
3416
3417                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3418                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
3419            }
3420            else
3421            {
3422                if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )   // unmapped
3423                {
3424                    if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3425                    {
3426                        r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
3427                    }
3428                    else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3429                    {
3430                        r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
3431                    }
3432                    r_dcache_bad_vaddr = dreq.addr;
3433                    r_dcache_fsm = DCACHE_ERROR;
3434
3435                    if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3436                    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
3437                }
3438                else if ( r_dcache_inval_tlb_rsp )
3439                {
3440                    r_dcache_inval_tlb_rsp = false;
3441                    r_dcache_fsm = DCACHE_IDLE;
3442                    m_cost_data_tlb_miss_frz++;
3443                }
3444                else if ( r_dcache_inval_rsp )
3445                {
3446                    r_dcache_inval_rsp = false;
3447                    r_dcache_fsm = DCACHE_IDLE;
3448                }
3449                else
3450                {
3451                    r_dcache_tlb_sc_acc_req = true;
3452                    r_dcache_pte_update = r_dcache_miss_buf[0] | r_dcache_pte_update.read();
3453                    r_dcache_fsm = DCACHE_TLB2_SC_WAIT;
3454                }
3455            }
3456        }
3457        break;
3458    }
3459    ///////////////////////
3460    case DCACHE_TLB2_SC_WAIT:
3461    {
3462        // external cache invalidate request
3463        if ( r_tgt_dcache_req )   
3464        {
3465            r_dcache_fsm = DCACHE_CC_CHECK;
3466            r_dcache_fsm_save = r_dcache_fsm;
3467            m_cost_data_waste_wait_frz++;
3468            break;
3469        }
3470
3471        if ( !r_dcache_tlb_sc_acc_req )
3472        {
3473            if ( r_vci_rsp_data_error ) // VCI response ko
3474            {
3475                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3476                {
3477                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
3478                }
3479                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3480                {
3481                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
3482                }
3483                r_dcache_bad_vaddr = dreq.addr;
3484                r_dcache_fsm = DCACHE_ERROR;
3485
3486                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3487                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;     
3488            }
3489            else
3490            {
3491                // Using tlb entry is invalidated
3492                if ( r_dcache_inval_tlb_rsp )
3493                {
3494                    r_dcache_inval_tlb_rsp = false;
3495                    r_dcache_fsm = DCACHE_IDLE;
3496                    m_cost_data_tlb_miss_frz++;
3497                }
3498                else if ( r_dcache_inval_rsp )
3499                {
3500                    r_dcache_inval_rsp = false;
3501                    r_dcache_fsm = DCACHE_IDLE;
3502                }
3503                else if ( r_dcache_tlb_ll_acc_req )
3504                {
3505                    r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
3506                }
3507                else
3508                {
3509                    r_dcache_fsm = DCACHE_TLB2_UPDT;
3510                }
3511            }
3512        }
3513        break;
3514    }
3515    /////////////////////
3516    case DCACHE_TLB2_READ:
3517    {
3518        m_cost_data_tlb_miss_frz++;
3519
3520        // external cache invalidate request
3521        if ( r_tgt_dcache_req )   
3522        {
3523            r_dcache_fsm = DCACHE_CC_CHECK;
3524            r_dcache_fsm_save = r_dcache_fsm;
3525            m_cost_data_waste_wait_frz++;
3526            break;
3527        }       
3528
3529        if ( !r_dcache_tlb_read_req )
3530        {
3531            if ( r_vci_rsp_data_error ) // VCI response ko
3532            {
3533                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3534                {
3535                    r_dcache_error_type = MMU_READ_PT2_ILLEGAL_ACCESS;
3536                }
3537                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3538                {
3539                    r_dcache_error_type = MMU_WRITE_PT2_ILLEGAL_ACCESS;
3540                }
3541                r_dcache_bad_vaddr = dreq.addr;
3542                r_dcache_fsm = DCACHE_ERROR;
3543
3544                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3545                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
3546                break;
3547            }   
3548
3549            if ( r_dcache_inval_tlb_rsp )  // TLB miss response and invalidation
3550            {
3551                r_dcache_fsm = DCACHE_IDLE;
3552                r_dcache_inval_tlb_rsp = false;
3553                break;
3554            }   
3555
3556            if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
3557            {
3558                r_dcache_fsm = DCACHE_IDLE;
3559                r_dcache_inval_rsp = false;
3560                break;     
3561            }
3562            // TLB miss response and no invalidation
3563            r_dcache_fsm = DCACHE_TLB2_READ_UPDT;
3564        }       
3565        break;
3566    }
3567    //////////////////////////
3568    case DCACHE_TLB2_READ_UPDT:
3569    {
3570        m_cost_data_tlb_miss_frz++;
3571
3572        // external cache invalidate request
3573        if ( r_tgt_dcache_req )   
3574        {
3575            r_dcache_fsm = DCACHE_CC_CHECK;
3576            r_dcache_fsm_save = r_dcache_fsm;
3577            m_cost_data_waste_wait_frz++;
3578            break;
3579        }       
3580
3581        // Using tlb entry is invalidated
3582        if ( r_dcache_inval_tlb_rsp )
3583        {
3584            r_dcache_inval_tlb_rsp = false;
3585            r_dcache_fsm = DCACHE_IDLE;
3586            m_cost_data_tlb_miss_frz++;
3587            break;
3588        }
3589
3590        // Using tlb entry is in the invalidated cache line 
3591        if ( r_dcache_inval_rsp )
3592        {
3593            r_dcache_inval_rsp = false;
3594            r_dcache_fsm = DCACHE_IDLE;
3595            m_cost_data_tlb_miss_frz++;
3596            break;
3597        }
3598
3599        if ( !r_dcache_cleanup_req )
3600        {
3601            // update cache
3602            data_t rsp_dtlb_miss;
3603            data_t tlb_data_ppn;
3604            bool write_hit = false;
3605            paddr_t  victim_index = 0;
3606            size_t way = 0;
3607            size_t set = 0;
3608
3609            bool cleanup_req = r_dcache.find(r_dcache_tlb_paddr, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
3610
3611            if ( cleanup_req )
3612            {       
3613                // ins tlb invalidate verification   
3614                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
3615                r_dcache_itlb_inval_line = victim_index;
3616                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
3617
3618                // data tlb invalidate verification
3619                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
3620                r_dcache_dtlb_inval_line = victim_index;
3621                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
3622
3623                r_dcache_cleanup_req = true;
3624                r_dcache_cleanup_line = victim_index;
3625                r_dcache_fsm = DCACHE_TLB_CC_INVAL;
3626                r_dcache_fsm_save = r_dcache_fsm;
3627                break;
3628            }
3629
3630            r_dcache.update(r_dcache_tlb_paddr, way, set, r_dcache_miss_buf);
3631            r_dcache.read(r_dcache_tlb_paddr, &rsp_dtlb_miss);
3632
3633            bool tlb_hit_ppn = r_dcache.read(r_dcache_tlb_paddr.read()+4, &tlb_data_ppn);
3634            assert(tlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
3635
3636            if ( !(rsp_dtlb_miss >> PTE_V_SHIFT) )      // unmapped
3637            {
3638                if ((r_dcache_type_save == iss_t::DATA_READ)||(r_dcache_type_save == iss_t::DATA_LL))
3639                {
3640                    r_dcache_error_type = MMU_READ_PT2_UNMAPPED;
3641                }
3642                else /*if ((dreq.type == iss_t::DATA_WRITE)||(dreq.type == iss_t::DATA_SC))*/
3643                {
3644                    r_dcache_error_type = MMU_WRITE_PT2_UNMAPPED;
3645                } 
3646                r_dcache_bad_vaddr  = dreq.addr;
3647                r_dcache_fsm        = DCACHE_ERROR;
3648            }
3649            else if ( (rsp_dtlb_miss & PTE_T_MASK) >> PTE_T_SHIFT ) // PTD
3650            {
3651                r_dcache_pte_update = rsp_dtlb_miss;
3652                r_dcache_ppn_update = tlb_data_ppn;
3653                r_dcache_fsm = DCACHE_TLB2_UPDT;
3654            }
3655            else
3656            {
3657                if ( (m_srcid_rw >> 4) == ((r_dcache_tlb_paddr.read() & ((1<<(m_paddr_nbits - PAGE_M_NBITS))-1)) >> (m_paddr_nbits - PAGE_M_NBITS -10)) ) // local
3658                {
3659                    if ( (rsp_dtlb_miss & PTE_L_MASK ) >> PTE_L_SHIFT ) // L bit is set
3660                    {
3661                        r_dcache_pte_update = rsp_dtlb_miss;
3662                        r_dcache_ppn_update = tlb_data_ppn;
3663                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
3664                    }
3665                    else
3666                    {
3667                        r_dcache_pte_update = rsp_dtlb_miss | PTE_L_MASK;
3668                        r_dcache_ppn_update = tlb_data_ppn;
3669                        r_dcache_tlb_ll_acc_req = true;
3670                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_L_MASK)); 
3671                        assert(write_hit && "Write on miss ignores data"); 
3672                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
3673                        m_cpt_ins_tlb_write_et++;
3674                    }
3675                }
3676                else // remotely
3677                {
3678                    if ( (rsp_dtlb_miss & PTE_R_MASK ) >> PTE_R_SHIFT ) // R bit is set
3679                    {
3680                        r_dcache_pte_update = rsp_dtlb_miss;
3681                        r_dcache_ppn_update = tlb_data_ppn;
3682                        r_dcache_fsm        = DCACHE_TLB2_UPDT;
3683                    }
3684                    else
3685                    {
3686                        r_dcache_pte_update = rsp_dtlb_miss | PTE_R_MASK;
3687                        r_dcache_ppn_update = tlb_data_ppn;
3688                        r_dcache_tlb_ll_acc_req = true;
3689                        write_hit = r_dcache.write(r_dcache_tlb_paddr,(rsp_dtlb_miss | PTE_R_MASK)); 
3690                        assert(write_hit && "Write on miss ignores data"); 
3691                        r_dcache_fsm = DCACHE_TLB2_LL_WAIT;
3692                        m_cpt_ins_tlb_write_et++;
3693                    }
3694                }
3695            }
3696        }
3697        break;
3698    }
3699    //////////////////////
3700    case DCACHE_TLB2_UPDT: 
3701    {
3702        m_cost_data_tlb_miss_frz++;
3703
3704        // external cache invalidate request
3705        if ( r_tgt_dcache_req )   
3706        {
3707            r_dcache_fsm = DCACHE_CC_CHECK;
3708            r_dcache_fsm_save = r_dcache_fsm;
3709            m_cost_data_waste_wait_frz++;
3710            break;
3711        }       
3712
3713        if ( !r_dcache_inval_tlb_rsp && !r_dcache_inval_rsp )
3714        {
3715            paddr_t victim_index = 0;
3716            if (dcache_tlb.update(r_dcache_pte_update,r_dcache_ppn_update,dreq.addr,(r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2)),&victim_index))
3717            {
3718                r_dcache.setinbit((paddr_t)victim_index*m_dcache_words*2, r_dcache_in_dtlb, false);
3719            }
3720            r_dcache.setinbit(r_dcache_tlb_paddr, r_dcache_in_dtlb, true);
3721            r_dcache_fsm = DCACHE_IDLE;
3722        }
3723        else 
3724        {
3725            if ( r_dcache_inval_tlb_rsp ) r_dcache_inval_tlb_rsp = false;
3726            if ( r_dcache_inval_rsp ) r_dcache_inval_rsp = false;
3727            r_dcache_fsm = DCACHE_IDLE;
3728        }
3729        break;
3730    }
3731    ///////////////////////
3732    case DCACHE_CTXT_SWITCH:
3733    {
3734        // TLB flush leads to cleanup corresponding data cache line
3735        m_cost_data_tlb_sw_frz++;
3736
3737        paddr_t victim_index = 0;
3738        size_t way = 0;
3739        size_t set = 0;
3740
3741        if ( r_dcache_itlb_cleanup_req )
3742        {   
3743            r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
3744            r_dcache_itlb_cleanup_req = false;
3745        }
3746
3747        for ( way = 0; way < m_dtlb_ways; way++)
3748        {
3749            for ( set = 0; set < m_dtlb_sets; set++)
3750            {
3751                if(dcache_tlb.checkcleanup(way, set, &victim_index))
3752                {
3753                    r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false);
3754                }
3755            }
3756        }
3757
3758        if ((way == m_dtlb_ways) && (set == m_dtlb_sets) && (!r_dcache_xtn_req))
3759        {
3760            r_dcache_fsm = DCACHE_IDLE;
3761            drsp.valid = true;
3762        }
3763        break;
3764    }
3765    ////////////////////////
3766    case DCACHE_ICACHE_FLUSH:
3767    case DCACHE_ICACHE_INVAL:
3768    case DCACHE_ITLB_INVAL:
3769    {
3770        if ( !r_dcache_xtn_req )
3771        {
3772            r_dcache_fsm = DCACHE_IDLE;
3773            drsp.valid = true;
3774        }
3775        break;
3776    }
3777    ////////////////////////
3778    case DCACHE_DCACHE_FLUSH:
3779    {
3780        // external cache invalidate request
3781        if ( r_tgt_dcache_req )
3782        {
3783            r_tgt_dcache_req = false;
3784        }   
3785
3786        size_t way = r_dcache_way;
3787        size_t set = r_dcache_set;
3788        bool clean = false;
3789       
3790        m_cost_data_cache_flush_frz++;
3791
3792        // cache flush and send cleanup to external
3793        if ( !r_dcache_cleanup_req )
3794        {
3795            paddr_t victim_index = 0;
3796            for ( ; way < m_dcache_ways; way++ )
3797            {   
3798                for ( ; set < m_dcache_sets; set++ )
3799                { 
3800                    if ( r_dcache.flush(way, set, &victim_index) )
3801                    {
3802                        clean = true;
3803                        r_dcache_cleanup_req = true;
3804                        r_dcache_cleanup_line = victim_index;
3805                        r_dcache_way = way + ((set+1)/m_dcache_sets);
3806                        r_dcache_set = (set+1) % m_dcache_sets;
3807                        break;
3808                    }
3809                }
3810                if (clean) break;
3811            }
3812
3813            if ((way == m_dcache_ways) && (set == m_dcache_sets) && !r_dcache_xtn_req )
3814            {
3815                // data TLB flush
3816                dcache_tlb.flush(true);      // global entries are not invalidated
3817
3818                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
3819                {
3820                    r_dcache_in_itlb[line] = false;
3821                    r_dcache_in_dtlb[line] = false;
3822                }
3823
3824                r_dcache_fsm = DCACHE_IDLE;
3825                drsp.valid = true;
3826                break;
3827            }
3828        }
3829        break;
3830    }
3831    //////////////////////
3832    case DCACHE_DTLB_INVAL:
3833    {
3834        paddr_t victim_index = 0;
3835        // clean indicate data tlb bit
3836        if ( dcache_tlb.inval(r_dcache_wdata_save, &victim_index) )
3837        { 
3838            r_dcache.setinbit((paddr_t)(victim_index << (m_dcache_words+2)), r_dcache_in_dtlb, false);
3839        }
3840        r_dcache_fsm = DCACHE_IDLE;
3841        drsp.valid = true;
3842        break;
3843    }
3844    ////////////////////////
3845    case DCACHE_DCACHE_INVAL:
3846    {
3847        m_cpt_dcache_dir_read += m_dcache_ways;
3848        vaddr_t invadr = dreq.wdata;
3849        paddr_t dpaddr = 0;
3850        bool dcache_hit_t = false;
3851        size_t way = 0;
3852        size_t set = 0;
3853
3854        if ( !r_dcache_cleanup_req )
3855        {
3856            if ( r_mmu_mode.read() & DATA_TLB_MASK )
3857            {
3858                dcache_hit_t = dcache_tlb.translate(invadr, &dpaddr);
3859            }
3860            else
3861            {
3862                dpaddr = invadr; 
3863                dcache_hit_t = true;
3864            }
3865
3866            if ( dcache_hit_t )
3867            {
3868                r_dcache_cleanup_req = r_dcache.inval(dpaddr, &way, &set);
3869                r_dcache_cleanup_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
3870               
3871                if ( r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[way*m_dcache_sets+set] )
3872                {       
3873                    // ins tlb invalidate verification
3874                    r_dcache_itlb_inval_req = r_dcache_in_itlb[way*m_dcache_sets+set];
3875                    r_dcache_itlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
3876                    r_dcache_in_itlb[way*m_dcache_sets+set] = false;
3877               
3878                    // data tlb invalidate verification
3879                    r_dcache_dtlb_inval_req = r_dcache_in_dtlb[way*m_dcache_sets+set];
3880                    r_dcache_dtlb_inval_line = dpaddr >> (uint32_log2(m_dcache_words)+2);
3881                    r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
3882                    r_dcache_fsm = DCACHE_TLB_CC_INVAL;
3883                    r_dcache_fsm_save = r_dcache_fsm;
3884                    break;
3885                }
3886            }
3887            r_dcache_fsm = DCACHE_IDLE;
3888            drsp.valid = true;
3889        }
3890        break;
3891    }
3892    /////////////////////////
3893    case DCACHE_DCACHE_SYNC:
3894    {
3895        if ( !r_dcache_write_req )
3896        {
3897            r_dcache_write_req = r_wbuf.rok();
3898            drsp.valid = true;
3899            r_dcache_fsm = DCACHE_IDLE;
3900        }   
3901        break;
3902    }
3903    /////////////////////
3904    case DCACHE_MISS_WAIT:
3905    {
3906        m_cost_data_miss_frz++;
3907
3908        // external cache invalidate request
3909        if ( r_tgt_dcache_req )
3910        {
3911            r_dcache_fsm = DCACHE_CC_CHECK;
3912            r_dcache_fsm_save = r_dcache_fsm;
3913            m_cost_data_waste_wait_frz++;
3914            break;
3915        }
3916
3917        if ( !r_dcache_miss_req )
3918        {
3919            if ( r_vci_rsp_data_error )
3920            {
3921                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;
3922                r_dcache_bad_vaddr = dreq.addr;
3923                r_dcache_fsm = DCACHE_ERROR;
3924
3925                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
3926                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
3927                break;
3928            }
3929
3930            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
3931            {
3932                r_dcache_fsm = DCACHE_IDLE;
3933                r_dcache_inval_tlb_rsp = false;
3934                break;
3935            }   
3936
3937            if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
3938            {
3939                r_dcache_fsm = DCACHE_IDLE;
3940                r_dcache_inval_rsp = false;
3941                break;     
3942            }
3943            // Miss read response and no tlb invalidation
3944            r_dcache_fsm = DCACHE_MISS_UPDT;
3945        }       
3946        break;
3947    }
3948    /////////////////////
3949    case DCACHE_MISS_UPDT:
3950    {
3951        m_cost_data_miss_frz++;
3952
3953        // external cache invalidate request
3954        if ( r_tgt_dcache_req )
3955        {
3956            r_dcache_fsm = DCACHE_CC_CHECK;
3957            r_dcache_fsm_save = r_dcache_fsm;
3958            m_cost_data_waste_wait_frz++;
3959            break;
3960        }
3961
3962        if ( r_dcache_inval_tlb_rsp ) // tlb invalidation
3963        {
3964            r_dcache_inval_tlb_rsp = false;
3965            r_dcache_fsm = DCACHE_IDLE;
3966            m_cost_data_tlb_miss_frz++;
3967            break;
3968        }
3969
3970        // Using tlb entry is in the invalidated cache line 
3971        if ( r_dcache_inval_rsp )
3972        {
3973            r_dcache_inval_rsp = false;
3974            r_dcache_fsm = DCACHE_IDLE;
3975            m_cost_data_tlb_miss_frz++;
3976            break;
3977        }
3978
3979        if (!r_dcache_cleanup_req ) // Miss update and no invalidation
3980        {
3981            paddr_t  victim_index = 0;
3982            size_t way = 0;
3983            size_t set = 0;
3984
3985            m_cpt_dcache_data_write++;
3986            m_cpt_dcache_dir_write++;
3987
3988            bool cleanup_req = r_dcache.find(r_dcache_paddr_save.read(), r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
3989
3990            if ( cleanup_req )
3991            {       
3992                // ins tlb invalidate verification   
3993                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
3994                r_dcache_itlb_inval_line = victim_index;
3995                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
3996
3997                // data tlb invalidate verification
3998                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
3999                r_dcache_dtlb_inval_line = victim_index;
4000                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
4001
4002                r_dcache_cleanup_req = true;
4003                r_dcache_cleanup_line = victim_index;
4004                r_dcache_fsm = DCACHE_TLB_CC_INVAL;
4005                r_dcache_fsm_save = r_dcache_fsm;
4006                break;
4007            }
4008
4009            r_dcache.update(r_dcache_paddr_save.read(), way, set, r_dcache_miss_buf);
4010            r_dcache_fsm = DCACHE_IDLE;
4011        }
4012        break;
4013    }
4014    //////////////////////
4015    case DCACHE_UNC_WAIT:
4016    {
4017        m_cost_unc_read_frz++;
4018
4019        // external cache invalidate request
4020        if ( r_tgt_dcache_req )
4021        {
4022            r_dcache_fsm = DCACHE_CC_CHECK;
4023            r_dcache_fsm_save = r_dcache_fsm;
4024            m_cost_data_waste_wait_frz++;
4025            break;
4026        }
4027
4028        if ( !r_dcache_unc_req )
4029        {
4030            if ( r_vci_rsp_data_error )
4031            {
4032                r_dcache_error_type = MMU_READ_DATA_ILLEGAL_ACCESS;
4033                r_dcache_bad_vaddr = dreq.addr;
4034                r_dcache_fsm = DCACHE_ERROR;
4035
4036                if (r_dcache_inval_tlb_rsp) r_dcache_inval_tlb_rsp = false;
4037                //if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
4038                break;
4039            }
4040
4041            if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
4042            {
4043                r_dcache_fsm = DCACHE_IDLE;
4044                r_dcache_inval_tlb_rsp = false;
4045                break;
4046            }
4047/*
4048            if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
4049            {
4050                r_dcache_fsm = DCACHE_IDLE;
4051                r_dcache_inval_rsp = false;
4052
4053                if ((dreq.type == iss_t::DATA_LL) || (dreq.type == iss_t::DATA_SC))
4054                {
4055                    r_dcache_buf_unc_valid = false;
4056                    r_dcache_llsc_reserved = false;
4057                }
4058                break;     
4059            }
4060*/ 
4061            if(dreq.type == iss_t::DATA_SC)
4062            {
4063                // Simulate an invalidate request
4064                r_dcache.inval(r_dcache_paddr_save);
4065            }           
4066            r_dcache_buf_unc_valid = true;
4067            r_dcache_fsm = DCACHE_IDLE;
4068        }       
4069        break;
4070    }
4071    ///////////////////////
4072    case DCACHE_WRITE_UPDT:
4073    {
4074        m_cost_write_frz++;
4075        size_t way = 0;
4076        size_t set = 0;
4077        bool write_hit = false;
4078        data_t mask = vci_param::be2mask(r_dcache_be_save.read());
4079        data_t wdata = (mask & r_dcache_wdata_save) | (~mask & r_dcache_rdata_save);
4080        write_hit = r_dcache.write(r_dcache_paddr_save, wdata, &way, &set);
4081        assert(write_hit && "Write on miss ignores data");
4082       
4083        if (r_dcache_in_itlb[way*m_dcache_sets+set] || r_dcache_in_dtlb[m_dcache_sets*way+set])
4084        {
4085            // ins tlb invalidate verification   
4086            r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
4087            r_dcache_itlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
4088            r_dcache_in_itlb[way*m_dcache_sets+set] = false;
4089
4090            // data tlb invalidate verification
4091            r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
4092            r_dcache_dtlb_inval_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
4093            r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
4094
4095            r_dcache_cleanup_req = true;
4096            r_dcache_cleanup_line = (r_dcache.get_tag(way, set) * m_dcache_sets) + set;
4097            r_dcache_fsm = DCACHE_TLB_CC_INVAL;
4098            r_dcache_fsm_save = r_dcache_fsm;
4099            break;
4100        }
4101
4102        if ( !r_dcache_dirty_save && (r_mmu_mode.read() & DATA_TLB_MASK) )   
4103        {
4104            if ( dcache_tlb.getpagesize(r_dcache_tlb_way_save, r_dcache_tlb_set_save) ) // 2M page size, one level page table
4105            {
4106                r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
4107                r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
4108                write_hit = r_dcache.write((paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2),
4109                                     (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
4110                assert(write_hit && "Write on miss ignores data");
4111                r_dcache_tlb_ll_dirty_req = true;
4112                r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
4113                m_cpt_data_tlb_write_dirty++;
4114            }
4115            else
4116            {   
4117                if (r_dcache_hit_p_save)
4118                {
4119                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
4120                    r_dcache_tlb_paddr = (paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3);
4121                    write_hit = r_dcache.write(((paddr_t)r_dcache_ptba_save|(paddr_t)(((dreq.addr&PTD_ID2_MASK)>>PAGE_K_NBITS) << 3)),
4122                                     (dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK));
4123                    assert(write_hit && "Write on miss ignores data");
4124                    r_dcache_tlb_ll_dirty_req = true;
4125                    r_dcache_fsm = DCACHE_LL_DIRTY_WAIT;
4126                    m_cpt_data_tlb_write_dirty++;
4127                }
4128                else
4129                {
4130                    r_dcache_pte_update = dcache_tlb.getpte(r_dcache_tlb_way_save, r_dcache_tlb_set_save) | PTE_D_MASK;
4131                    r_dcache_tlb_paddr = (paddr_t)r_mmu_ptpr << (INDEX1_NBITS+2) | (paddr_t)((dreq.addr>>PAGE_M_NBITS)<<2);
4132                    r_dcache_tlb_ptba_read = true;
4133                    r_dcache_fsm = DCACHE_DTLB1_READ_CACHE;
4134                }
4135            }
4136        }
4137        else
4138        {
4139            r_dcache_fsm = DCACHE_WRITE_REQ;
4140            drsp.valid = true;
4141            drsp.rdata = 0;
4142        }
4143        break;
4144    }
4145    ////////////////////////
4146    case DCACHE_WRITE_DIRTY:
4147    {
4148        m_cost_data_tlb_miss_frz++;
4149
4150        // external cache invalidate request
4151        if ( r_tgt_dcache_req )
4152        {
4153            r_dcache_fsm = DCACHE_CC_CHECK;
4154            r_dcache_fsm_save = r_dcache_fsm;
4155            m_cost_data_waste_wait_frz++;
4156            break;
4157        }
4158
4159        if ( r_dcache_inval_tlb_rsp ) // Miss read response and tlb invalidation
4160        {
4161            r_dcache_fsm = DCACHE_IDLE;
4162            r_dcache_inval_tlb_rsp = false;
4163            break;
4164        }
4165
4166        if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
4167        {
4168            r_dcache_fsm = DCACHE_IDLE;
4169            r_dcache_inval_rsp = false;
4170            break;         
4171        }
4172
4173        dcache_tlb.setdirty(r_dcache_tlb_way_save, r_dcache_tlb_set_save);
4174        r_dcache_fsm = DCACHE_WRITE_REQ;
4175        drsp.valid = true;
4176        drsp.rdata = 0;
4177        break;
4178    }
4179    /////////////////
4180    case DCACHE_ERROR:
4181    {
4182        r_vci_rsp_data_error = false;
4183        drsp.valid = true;
4184        drsp.error = true;
4185        drsp.rdata = 0;
4186        r_dcache_fsm = DCACHE_IDLE;
4187        break;
4188    }   
4189    //////////////////////
4190    case DCACHE_ITLB_READ:
4191    {
4192        m_cost_data_waste_wait_frz++;
4193
4194        // external cache invalidate request
4195        if ( r_tgt_dcache_req )
4196        {
4197            r_dcache_fsm = DCACHE_CC_CHECK;
4198            r_dcache_fsm_save = r_dcache_fsm;
4199            m_cost_data_waste_wait_frz++;
4200            break;
4201        }
4202
4203        if ( !r_dcache_itlb_read_req ) // vci response ok
4204        { 
4205            if ( r_vci_rsp_data_error )
4206            {
4207                r_dcache_rsp_itlb_error = true;
4208                r_itlb_read_dcache_req = false;
4209                r_vci_rsp_data_error = false;
4210                r_dcache_fsm = DCACHE_IDLE;
4211
4212                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
4213                break;
4214            }
4215
4216            if ( r_dcache_inval_rsp ) // TLB miss response and cache invalidation
4217            {
4218                r_dcache_fsm = DCACHE_IDLE;
4219                r_dcache_inval_rsp = false;
4220                break;     
4221            }
4222            r_dcache_fsm = DCACHE_ITLB_UPDT;
4223        }
4224        break;         
4225    }
4226    //////////////////////
4227    case DCACHE_ITLB_UPDT:
4228    {
4229        m_cost_data_waste_wait_frz++;
4230
4231        // external cache invalidate request
4232        if ( r_tgt_dcache_req )
4233        {
4234            r_dcache_fsm = DCACHE_CC_CHECK;
4235            r_dcache_fsm_save = r_dcache_fsm;
4236            m_cost_data_waste_wait_frz++;
4237            break;
4238        }
4239
4240        // Using tlb entry is in the invalidated cache line 
4241        if ( r_dcache_inval_rsp )
4242        {
4243            r_dcache_inval_rsp = false;
4244            r_dcache_fsm = DCACHE_IDLE;
4245            m_cost_data_tlb_miss_frz++;
4246            break;
4247        }
4248
4249        if ( !r_dcache_cleanup_req )
4250        {
4251            data_t rsp_itlb_miss = 0;
4252            data_t rsp_itlb_ppn = 0;
4253
4254            paddr_t  victim_index = 0;
4255            size_t way = 0;
4256            size_t set = 0;
4257           
4258            bool cleanup = r_dcache.find(r_icache_paddr_save, r_dcache_in_itlb, r_dcache_in_dtlb, &way, &set, &victim_index);
4259
4260            if ( cleanup )
4261            {       
4262                // ins tlb invalidate verification   
4263                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
4264                r_dcache_itlb_inval_line = victim_index;
4265                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
4266
4267                // data tlb invalidate verification
4268                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
4269                r_dcache_dtlb_inval_line = victim_index;
4270                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
4271
4272                r_dcache_cleanup_req = true;
4273                r_dcache_cleanup_line = victim_index;
4274                r_dcache_fsm = DCACHE_TLB_CC_INVAL;
4275                r_dcache_fsm_save = r_dcache_fsm;
4276                break;
4277            }
4278
4279            r_dcache.update(r_icache_paddr_save, way, set, r_dcache_miss_buf);
4280
4281            r_dcache.setinbit(r_icache_paddr_save, r_dcache_in_itlb, true);
4282            bool itlb_hit_dcache = r_dcache.read(r_icache_paddr_save, &rsp_itlb_miss); 
4283 
4284            if ( (r_icache_fsm == ICACHE_TLB2_READ) && itlb_hit_dcache )
4285            {   
4286                bool itlb_hit_ppn = r_dcache.read(r_icache_paddr_save.read()+4, &rsp_itlb_ppn);
4287                assert(itlb_hit_ppn && "Address of pte[64-32] and pte[31-0] should be successive");
4288            }
4289
4290            r_dcache_rsp_itlb_miss = rsp_itlb_miss;
4291            r_dcache_rsp_itlb_ppn = rsp_itlb_ppn;
4292            r_dcache_rsp_itlb_error = false;   
4293            r_itlb_read_dcache_req = false;
4294            r_dcache_fsm = DCACHE_IDLE;
4295        }
4296        break;
4297    }
4298    //////////////////////////
4299    case DCACHE_ITLB_LL_WAIT:
4300    {
4301        // external cache invalidate request
4302        if ( r_tgt_dcache_req )   
4303        {
4304            r_dcache_fsm = DCACHE_CC_CHECK;
4305            r_dcache_fsm_save = r_dcache_fsm;
4306            m_cost_data_waste_wait_frz++;
4307            break;
4308        }
4309
4310        if (!r_dcache_itlb_ll_acc_req)
4311        {
4312            if ( r_vci_rsp_data_error ) // VCI response ko
4313            {
4314                r_dcache_rsp_itlb_error = true; 
4315                r_vci_rsp_data_error = false;
4316                r_itlb_acc_dcache_req = false;
4317                r_dcache_fsm = DCACHE_IDLE;
4318                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;     
4319            }
4320            else
4321            {
4322                if ( !(r_dcache_miss_buf[0] >> PTE_V_SHIFT) )   // unmapped
4323                {
4324                    r_dcache_rsp_itlb_error = true; 
4325                    r_itlb_acc_dcache_req = false;
4326                    r_dcache_fsm = DCACHE_IDLE;
4327                    if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;
4328                }
4329                else if ( r_dcache_inval_rsp )
4330                {
4331                    r_dcache_inval_rsp = false;
4332                    r_dcache_fsm = DCACHE_IDLE;
4333                    m_cost_data_tlb_miss_frz++;
4334                }
4335                else
4336                {
4337                    r_dcache_itlb_sc_acc_req = true;
4338                    r_icache_pte_update = r_dcache_miss_buf[0] | r_icache_pte_update.read();   
4339                    r_dcache_fsm = DCACHE_ITLB_SC_WAIT;
4340                }
4341            }
4342        }
4343        break;
4344    }
4345    //////////////////////////
4346    case DCACHE_ITLB_SC_WAIT:
4347    {
4348        // external cache invalidate request
4349        if ( r_tgt_dcache_req )   
4350        {
4351            r_dcache_fsm = DCACHE_CC_CHECK;
4352            r_dcache_fsm_save = r_dcache_fsm;
4353            m_cost_data_waste_wait_frz++;
4354            break;
4355        }
4356       
4357        if ( !r_dcache_itlb_sc_acc_req )
4358        {
4359            if ( r_vci_rsp_data_error ) // VCI response ko
4360            {
4361                r_dcache_rsp_itlb_error = true; 
4362                r_vci_rsp_data_error = false;
4363                r_itlb_acc_dcache_req = false;
4364                r_dcache_fsm = DCACHE_IDLE;
4365                if (r_dcache_inval_rsp) r_dcache_inval_rsp = false;             
4366            }
4367            else
4368            {
4369                if ( r_dcache_inval_rsp )
4370                {
4371                    r_dcache_inval_rsp = false;
4372                    r_dcache_fsm = DCACHE_IDLE;
4373                    m_cost_data_tlb_miss_frz++;
4374                }
4375                else if ( r_dcache_itlb_ll_acc_req )
4376                {
4377                    r_dcache_fsm = DCACHE_ITLB_LL_WAIT;
4378                }
4379                else
4380                {
4381                    r_itlb_acc_dcache_req = false;
4382                    r_dcache_fsm = DCACHE_IDLE;
4383                }
4384            }
4385        }
4386        break;
4387    }
4388    /////////////////////
4389    case DCACHE_CC_CHECK:   // read directory in case of invalidate or update request
4390    {
4391        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4392
4393        m_cpt_dcache_dir_read += m_dcache_ways;
4394        m_cpt_dcache_data_read += m_dcache_ways;
4395
4396        data_t dcache_rdata = 0;
4397        size_t way = 0;
4398        size_t set = 0;
4399
4400        bool dcache_hit = r_dcache.read(r_tgt_addr.read(), &dcache_rdata, &way, &set);
4401
4402        if ( dcache_hit )
4403        {
4404            if ( r_dcache_in_dtlb[m_dcache_sets*way+set] || r_dcache_in_itlb[m_dcache_sets*way+set] )
4405            {
4406                // ins tlb invalidate verification   
4407                r_dcache_itlb_inval_req = r_dcache_in_itlb[m_dcache_sets*way+set];
4408                r_dcache_itlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
4409                r_dcache_in_itlb[way*m_dcache_sets+set] = false;
4410
4411                // data tlb invalidate verification
4412                r_dcache_dtlb_inval_req = r_dcache_in_dtlb[m_dcache_sets*way+set];
4413                r_dcache_dtlb_inval_line = r_tgt_addr.read() >> (uint32_log2(m_dcache_words)+2);
4414                r_dcache_in_dtlb[way*m_dcache_sets+set] = false;
4415               
4416                r_dcache_cc_check = true;
4417                r_dcache_fsm = DCACHE_TLB_CC_INVAL;
4418                break;
4419            }
4420
4421            if(( /*( r_dcache_fsm_save == DCACHE_UNC_WAIT ) ||*/
4422                 ( r_dcache_fsm_save == DCACHE_MISS_WAIT ) || ( r_dcache_fsm_save == DCACHE_MISS_UPDT ) ) &&
4423               ( (r_dcache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))))
4424            {
4425                r_dcache_inval_rsp = true;
4426            }
4427
4428            if(( ( r_dcache_fsm_save == DCACHE_TLB1_READ )      || ( r_dcache_fsm_save == DCACHE_TLB2_READ )      ||
4429                 ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT ) || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT ) ||
4430                 ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )      || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )      ||
4431                 ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )   ||
4432                 ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )   || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )   ||
4433                 ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )  || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )  ||
4434                 ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY ) ) &&
4435               ( (r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) )
4436            {
4437                r_dcache_inval_rsp = true;
4438            }
4439
4440            if(( ( r_dcache_fsm_save == DCACHE_ITLB_READ ) || ( r_dcache_fsm_save == DCACHE_ITLB_UPDT ) ||
4441                 ( r_dcache_fsm_save == DCACHE_ITLB_LL_WAIT ) || ( r_dcache_fsm_save == DCACHE_ITLB_SC_WAIT ) ) &&
4442               ( (r_icache_paddr_save.read() & ~((m_dcache_words<<2)-1)) == (r_tgt_addr.read() & ~((m_dcache_words<<2)-1))) )
4443            {
4444                r_dcache_inval_rsp = true;
4445            }
4446
4447            if ( r_tgt_update ) // update
4448            {
4449                r_dcache_fsm = DCACHE_CC_UPDT;
4450            }
4451            else                // invalidate
4452            {
4453                r_dcache_fsm = DCACHE_CC_INVAL;
4454            }
4455        }
4456        else                    // nothing
4457        {
4458            r_dcache_fsm = DCACHE_CC_NOP;
4459        }
4460        break;
4461    }
4462    ///////////////////
4463    case DCACHE_CC_UPDT:    // update directory and data cache       
4464    {
4465        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4466
4467        m_cpt_dcache_dir_write++;
4468        m_cpt_dcache_data_write++;
4469        data_t* buf = r_tgt_buf;
4470        for( size_t i = 0; i < m_dcache_words; i++ )
4471        {
4472            if( r_tgt_val[i] ) r_dcache.write( r_tgt_addr.read() + i*4, buf[i] );
4473        }
4474           
4475        r_tgt_dcache_req = false;
4476        r_dcache_fsm = r_dcache_fsm_save;
4477        break;
4478    }
4479    /////////////////////
4480    case DCACHE_CC_INVAL:   // invalidate a cache line
4481    {
4482        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4483
4484        r_tgt_dcache_rsp = r_dcache.inval(r_tgt_addr.read());
4485        r_tgt_dcache_req = false;
4486        r_dcache_fsm = r_dcache_fsm_save;
4487        break;
4488    }
4489    ///////////////////
4490    case DCACHE_CC_NOP:     // no external hit
4491    {
4492        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4493
4494        r_tgt_dcache_req = false;
4495        r_dcache_fsm = r_dcache_fsm_save;
4496        break;
4497    }   
4498    /////////////////////////
4499    case DCACHE_TLB_CC_INVAL:
4500    {
4501        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4502
4503        if ( r_dcache_itlb_inval_req || r_dcache_dtlb_inval_req ) break;
4504
4505        if( (( r_dcache_fsm_save == DCACHE_TLB1_READ )        || ( r_dcache_fsm_save == DCACHE_TLB2_READ )        ||
4506             ( r_dcache_fsm_save == DCACHE_TLB1_READ_UPDT )   || ( r_dcache_fsm_save == DCACHE_TLB2_READ_UPDT )   ||
4507             ( r_dcache_fsm_save == DCACHE_TLB1_LL_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_LL_WAIT )     ||
4508             ( r_dcache_fsm_save == DCACHE_TLB1_SC_WAIT )     || ( r_dcache_fsm_save == DCACHE_TLB2_SC_WAIT )     ||
4509             ( r_dcache_fsm_save == DCACHE_TLB1_UPDT )        || ( r_dcache_fsm_save == DCACHE_TLB2_UPDT )        ||
4510             ( r_dcache_fsm_save == DCACHE_DTLB1_READ_CACHE ) || ( r_dcache_fsm_save == DCACHE_DTLB2_READ_CACHE ) ||
4511             ( r_dcache_fsm_save == DCACHE_LL_DIRTY_WAIT )    || ( r_dcache_fsm_save == DCACHE_SC_DIRTY_WAIT )    ||
4512             ( r_dcache_fsm_save == DCACHE_WRITE_DIRTY )) &&
4513            (((r_dcache_tlb_paddr.read() & ~((m_dcache_words<<2)-1)) >> (uint32_log2(m_dcache_words) + 2)) == r_dcache_dtlb_inval_line.read()) )
4514        {
4515            r_dcache_inval_tlb_rsp = true;
4516        }
4517
4518        if (((r_dcache_fsm_save == DCACHE_BIS)||(r_dcache_fsm_save == DCACHE_MISS_WAIT) ||
4519             (r_dcache_fsm_save == DCACHE_UNC_WAIT)||(r_dcache_fsm_save == DCACHE_MISS_UPDT)) &&
4520             (r_dcache_tlb_nline == r_dcache_dtlb_inval_line))
4521        {
4522            r_dcache_inval_tlb_rsp = true;
4523        }
4524
4525        if ( !r_dcache_cc_check )
4526        {
4527            r_dcache_fsm = r_dcache_fsm_save;
4528        }
4529        else
4530        {
4531            r_dcache_fsm = DCACHE_CC_CHECK;
4532            r_dcache_cc_check = false;
4533        }
4534        break;
4535    }
4536    /////////////////////////
4537    case DCACHE_ITLB_CLEANUP:
4538    {
4539        if ( dreq.valid ) m_cost_data_waste_wait_frz++;
4540
4541        r_dcache.setinbit(((paddr_t)r_dcache_itlb_cleanup_line.read()*m_dcache_words*2), r_dcache_in_itlb, false);
4542        r_dcache_itlb_cleanup_req = false;
4543        r_dcache_fsm = DCACHE_IDLE;
4544        break;
4545    }
4546    } // end switch r_dcache_fsm
4547
4548#ifdef SOCLIB_MODULE_DEBUG
4549    std::cout << name() << " Data Response: " << drsp << std::endl;
4550#endif
4551
4552    ////////////////////////////////////////////////////////////////////////////////////
4553    //      INVAL DTLB CHECK FSM
4554    ////////////////////////////////////////////////////////////////////////////////////////
4555    switch(r_inval_dtlb_fsm) {
4556    /////////////////////
4557    case INVAL_DTLB_IDLE:
4558    {
4559        if ( r_dcache_dtlb_inval_req )
4560        {
4561            r_ccinval_dtlb_way = 0;
4562            r_ccinval_dtlb_set = 0;
4563            r_inval_dtlb_fsm = INVAL_DTLB_CHECK;   
4564            m_cost_data_tlb_inval_frz++;
4565        }   
4566        break;
4567    }
4568    ////////////////////////////
4569    case INVAL_DTLB_CHECK:
4570    {
4571        m_cost_data_tlb_inval_frz++;
4572
4573        size_t way = r_ccinval_dtlb_way;
4574        size_t set = r_ccinval_dtlb_set;
4575        bool end = false;       
4576        bool tlb_hit = dcache_tlb.cccheck(r_dcache_dtlb_inval_line.read(), way, set, &way, &set, &end);
4577   
4578        if ( tlb_hit )
4579        {
4580            r_ccinval_dtlb_way = way;
4581            r_ccinval_dtlb_set = set;
4582            r_dtlb_cc_check_end = end;
4583            r_inval_dtlb_fsm = INVAL_DTLB_INVAL;
4584            m_cpt_data_tlb_inval++;   
4585        }       
4586        else
4587        {
4588            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;   
4589        }
4590        break;
4591    }
4592    /////////////////////////
4593    case INVAL_DTLB_INVAL:
4594    {
4595        m_cost_data_tlb_inval_frz++;
4596
4597        dcache_tlb.ccinval(r_ccinval_dtlb_way, r_ccinval_dtlb_set);
4598
4599        if ( !r_dtlb_cc_check_end )
4600        {
4601            r_inval_dtlb_fsm = INVAL_DTLB_CHECK;
4602        }
4603        else
4604        {
4605            r_inval_dtlb_fsm = INVAL_DTLB_CLEAR;   
4606        }
4607        break;
4608    }
4609    ////////////////////
4610    case INVAL_DTLB_CLEAR:
4611    {
4612        r_dcache_dtlb_inval_req = false;
4613        r_dtlb_cc_check_end = false;
4614        r_ccinval_dtlb_way = 0;
4615        r_ccinval_dtlb_set = 0;
4616        r_inval_dtlb_fsm = INVAL_DTLB_IDLE;   
4617        m_cpt_data_tlb_inval++;   
4618        break;
4619    }
4620    } // end switch r_inval_itlb_fsm
4621
4622    /////////// execute one iss cycle /////////////////////////////////
4623    {
4624    uint32_t it = 0;
4625    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
4626    m_iss.executeNCycles(1, irsp, drsp, it);
4627    }
4628
4629    ////////////// number of frozen cycles //////////////////////////
4630    if ( (ireq.valid && !irsp.valid) || (dreq.valid && !drsp.valid) )
4631    {
4632        m_cpt_frz_cycles++;
4633    }
4634
4635    ////////////////////////////////////////////////////////////////////////////
4636    //     VCI_CMD FSM
4637    //
4638    // This FSM handles requests from both the DCACHE controler
4639    // (request registers) and the ICACHE controler (request registers).
4640    // There is 10 VCI transaction types :
4641    // - INS_TLB_READ
4642    // - INS_TLB_WRITE
4643    // - INS_MISS
4644    // - INS_UNC_MISS
4645    // - DATA_TLB_READ
4646    // - DATA_TLB_WRITE
4647    // - DATA_TLB_DIRTY
4648    // - DATA_MISS
4649    // - DATA_UNC
4650    // - DATA_WRITE
4651    // The ICACHE requests have the highest priority.
4652    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
4653    // exit simultaneously the IDLE state.
4654    //////////////////////////////////////////////////////////////////////////////
4655
4656    switch (r_vci_cmd_fsm) {
4657   
4658    case CMD_IDLE:
4659        if (r_vci_rsp_fsm != RSP_IDLE)
4660            break;
4661
4662        r_vci_cmd_cpt = 0;
4663
4664        if (r_dcache_itlb_read_req)           
4665        {           
4666            r_vci_cmd_fsm = CMD_ITLB_READ;
4667            m_cpt_itlbmiss_transaction++;
4668        }
4669        else if (r_dcache_itlb_ll_acc_req)
4670        {
4671            r_vci_cmd_fsm = CMD_ITLB_ACC_LL;
4672            m_cpt_itlb_write_transaction++;
4673        }
4674        else if (r_dcache_itlb_sc_acc_req)
4675        {
4676            r_vci_cmd_fsm = CMD_ITLB_ACC_SC;
4677            m_cpt_itlb_write_transaction++;
4678        }
4679        else if (r_icache_miss_req)
4680        {   
4681            r_vci_cmd_fsm = CMD_INS_MISS;
4682            m_cpt_imiss_transaction++;
4683        }
4684        else if (r_icache_unc_req)
4685        {   
4686            r_vci_cmd_fsm = CMD_INS_UNC;
4687            m_cpt_imiss_transaction++;
4688        } 
4689        else if (r_dcache_tlb_read_req)
4690        {           
4691            r_vci_cmd_fsm = CMD_DTLB_READ;
4692            m_cpt_dtlbmiss_transaction++;
4693        }
4694        else if (r_dcache_tlb_ll_acc_req)
4695        { 
4696            r_vci_cmd_fsm = CMD_DTLB_ACC_LL;
4697            m_cpt_dtlb_write_transaction++;
4698        }
4699        else if (r_dcache_tlb_sc_acc_req)
4700        { 
4701            r_vci_cmd_fsm = CMD_DTLB_ACC_SC;
4702            m_cpt_dtlb_write_transaction++;
4703        }
4704        else if (r_dcache_tlb_ll_dirty_req)
4705        { 
4706            r_vci_cmd_fsm = CMD_DTLB_DIRTY_LL;
4707            m_cpt_dtlb_write_transaction++;
4708        }
4709        else if (r_dcache_tlb_sc_dirty_req)
4710        { 
4711            r_vci_cmd_fsm = CMD_DTLB_DIRTY_SC;
4712            m_cpt_dtlb_write_transaction++;
4713        }
4714        else if (r_dcache_write_req)
4715        {
4716            r_vci_cmd_fsm = CMD_DATA_WRITE;
4717            r_vci_cmd_cpt = r_wbuf.getMin();
4718            r_vci_cmd_min = r_wbuf.getMin();
4719            r_vci_cmd_max = r_wbuf.getMax();
4720            m_cpt_write_transaction++;
4721            m_length_write_transaction += (r_wbuf.getMax() - r_wbuf.getMin() + 1);
4722        }
4723        else if (r_dcache_miss_req) 
4724        {
4725            r_vci_cmd_fsm = CMD_DATA_MISS;
4726            m_cpt_dmiss_transaction++;
4727        }
4728        else if (r_dcache_unc_req) 
4729        {
4730            r_vci_cmd_fsm = CMD_DATA_UNC;
4731            m_cpt_unc_transaction++;
4732        }
4733        break;
4734
4735    case CMD_DATA_WRITE:
4736        if ( p_vci_ini_rw.cmdack.read() )
4737        {
4738            r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4739            if (r_vci_cmd_cpt == r_vci_cmd_max)
4740            {
4741                r_vci_cmd_fsm = CMD_IDLE;
4742                r_wbuf.reset();
4743            }
4744        }
4745        break;
4746
4747    default:
4748        if ( p_vci_ini_rw.cmdack.read() )
4749        { 
4750            r_vci_cmd_fsm = CMD_IDLE;
4751        }
4752        break;
4753
4754    } // end  switch r_vci_cmd_fsm
4755
4756    //////////////////////////////////////////////////////////////////////////
4757    //      VCI_RSP FSM
4758    //
4759    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
4760    // IDLE state simultaneously.
4761    //////////////////////////////////////////////////////////////////////////
4762
4763    switch (r_vci_rsp_fsm) {
4764
4765    case RSP_IDLE:
4766        assert( ! p_vci_ini_rw.rspval.read() && "Unexpected response" );
4767
4768        if (r_vci_cmd_fsm != CMD_IDLE)
4769            break;
4770
4771        r_vci_rsp_cpt = 0;
4772        if (r_dcache_itlb_read_req)          // ITLB miss response
4773        {           
4774            r_vci_rsp_fsm = RSP_ITLB_READ;
4775        }
4776        else if (r_dcache_itlb_ll_acc_req)   // ITLB linked load response
4777        {   
4778            r_vci_rsp_fsm = RSP_ITLB_ACC_LL;
4779        }
4780        else if (r_dcache_itlb_sc_acc_req)   // ITLB store conditional response
4781        {   
4782            r_vci_rsp_fsm = RSP_ITLB_ACC_SC;
4783        }
4784        else if (r_icache_miss_req)         // ICACHE cached miss response
4785        {   
4786            r_vci_rsp_fsm = RSP_INS_MISS;
4787        }
4788        else if (r_icache_unc_req)          // ICACHE uncached miss response
4789        {   
4790            r_vci_rsp_fsm = RSP_INS_UNC;
4791        } 
4792        else if (r_dcache_tlb_read_req)     // ITLB miss response
4793        {
4794            r_vci_rsp_fsm = RSP_DTLB_READ;
4795        }
4796        else if (r_dcache_tlb_ll_acc_req)    // DTLB access bits linked load response
4797        {
4798            r_vci_rsp_fsm = RSP_DTLB_ACC_LL;
4799        }
4800        else if (r_dcache_tlb_sc_acc_req)    // DTLB access bits store conditional response
4801        {
4802            r_vci_rsp_fsm = RSP_DTLB_ACC_SC;
4803        }
4804        else if (r_dcache_tlb_ll_dirty_req)  // DTLB dirty bit linked load response
4805        {
4806            r_vci_rsp_fsm = RSP_DTLB_DIRTY_LL;
4807        }
4808        else if (r_dcache_tlb_sc_dirty_req)  // DTLB dirty bit store conditional response
4809        {
4810            r_vci_rsp_fsm = RSP_DTLB_DIRTY_SC;
4811        }
4812        else if (r_dcache_write_req)        // DCACHE write request
4813        {
4814            r_vci_rsp_fsm = RSP_DATA_WRITE;
4815        }
4816        else if (r_dcache_miss_req)         // DCACHE read request
4817        {
4818            r_vci_rsp_fsm = RSP_DATA_MISS;
4819        }
4820        else if (r_dcache_unc_req)          // DCACHE uncached read request
4821        {
4822            r_vci_rsp_fsm = RSP_DATA_UNC;
4823        }
4824        break;
4825
4826    case RSP_ITLB_READ:
4827        m_cost_itlbmiss_transaction++;
4828        if ( ! p_vci_ini_rw.rspval.read() )
4829            break;
4830
4831        assert(r_vci_rsp_cpt != m_dcache_words &&
4832               "illegal VCI response packet for data read miss");
4833
4834        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
4835        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
4836
4837        if ( p_vci_ini_rw.reop.read() )
4838        {
4839            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
4840                    "illegal VCI response packet for data read miss");
4841            r_dcache_itlb_read_req = false;
4842            r_vci_rsp_fsm = RSP_IDLE;
4843        }
4844        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4845        {
4846            r_vci_rsp_data_error = true;
4847        }
4848        break;
4849
4850    case RSP_ITLB_ACC_LL:
4851        if ( ! p_vci_ini_rw.rspval.read() )
4852            break;
4853
4854        assert(p_vci_ini_rw.reop.read() &&
4855               "illegal VCI response packet for ll tlb");
4856
4857        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4858        {
4859            r_vci_rsp_data_error = true;
4860        }
4861        else
4862        {
4863            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
4864        }
4865        r_dcache_itlb_ll_acc_req = false;
4866        r_vci_rsp_fsm = RSP_IDLE;
4867        break;
4868
4869    case RSP_ITLB_ACC_SC:
4870        if ( ! p_vci_ini_rw.rspval.read() )
4871            break;
4872
4873        assert(p_vci_ini_rw.reop.read() &&
4874               "illegal VCI response packet for sc tlb");
4875
4876        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4877        {
4878            r_vci_rsp_data_error = true;
4879        }
4880        else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
4881        {
4882            r_dcache_itlb_ll_acc_req = true;
4883        }
4884        r_dcache_itlb_sc_acc_req = false;
4885        r_vci_rsp_fsm = RSP_IDLE;
4886        break;
4887
4888    case RSP_INS_MISS:
4889        m_cost_imiss_transaction++;
4890        if ( ! p_vci_ini_rw.rspval.read() )
4891            break;
4892
4893        assert( (r_vci_rsp_cpt < m_icache_words) &&
4894               "The VCI response packet for instruction miss is too long");
4895        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
4896        r_icache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
4897
4898        if ( p_vci_ini_rw.reop.read() )
4899        {
4900            assert( (r_vci_rsp_cpt == m_icache_words - 1) &&
4901                       "The VCI response packet for instruction miss is too short");
4902            r_icache_miss_req = false;
4903            r_vci_rsp_fsm = RSP_IDLE;
4904               
4905        }
4906        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4907        {
4908            r_vci_rsp_ins_error = true;
4909        }
4910        break;
4911
4912    case RSP_INS_UNC:
4913        m_cost_imiss_transaction++;
4914        if ( ! p_vci_ini_rw.rspval.read() )
4915            break;
4916
4917        assert(p_vci_ini_rw.reop.read() &&
4918               "illegal VCI response packet for uncached instruction");
4919
4920        r_icache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
4921        r_icache_buf_unc_valid = true;
4922        r_icache_unc_req = false;
4923        r_vci_rsp_fsm = RSP_IDLE;
4924
4925        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4926        {
4927            r_vci_rsp_ins_error = true;
4928        }
4929        break;
4930
4931    case RSP_DTLB_READ:
4932        m_cost_dtlbmiss_transaction++;
4933        if ( ! p_vci_ini_rw.rspval.read() )
4934            break;
4935
4936        assert(r_vci_rsp_cpt != m_dcache_words &&
4937               "illegal VCI response packet for data read miss");
4938
4939        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
4940        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
4941        if ( p_vci_ini_rw.reop.read() )
4942        {
4943            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
4944                    "illegal VCI response packet for data read miss");
4945            r_dcache_tlb_read_req = false;
4946            r_vci_rsp_fsm = RSP_IDLE;
4947        }
4948        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4949        {
4950            r_vci_rsp_data_error = true;
4951        }
4952        break;
4953
4954    case RSP_DTLB_ACC_LL:
4955        if ( ! p_vci_ini_rw.rspval.read() )
4956            break;
4957
4958        assert(p_vci_ini_rw.reop.read() &&
4959               "illegal VCI response packet for ll tlb");
4960
4961        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4962        {
4963            r_vci_rsp_data_error = true;
4964        }
4965        else
4966        {
4967            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
4968        }
4969        r_dcache_tlb_ll_acc_req = false;
4970        r_vci_rsp_fsm = RSP_IDLE;
4971        break;
4972
4973    case RSP_DTLB_ACC_SC:
4974        if ( ! p_vci_ini_rw.rspval.read() )
4975            break;
4976
4977        assert(p_vci_ini_rw.reop.read() &&
4978               "illegal VCI response packet for sc tlb");
4979
4980        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
4981        {
4982            r_vci_rsp_data_error = true;
4983        }
4984        else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
4985        {
4986            r_dcache_tlb_ll_acc_req = true;
4987        }
4988        r_dcache_tlb_sc_acc_req = false;
4989        r_vci_rsp_fsm = RSP_IDLE;
4990        break;
4991
4992    case RSP_DTLB_DIRTY_LL:
4993        if ( ! p_vci_ini_rw.rspval.read() )
4994            break;
4995
4996        assert(p_vci_ini_rw.reop.read() &&
4997               "illegal VCI response packet for ll tlb");
4998
4999        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
5000        {
5001            r_vci_rsp_data_error = true;
5002        }
5003        else
5004        {
5005            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
5006        }
5007        r_dcache_tlb_ll_dirty_req = false;
5008        r_vci_rsp_fsm = RSP_IDLE;
5009        break;
5010
5011    case RSP_DTLB_DIRTY_SC:
5012        if ( ! p_vci_ini_rw.rspval.read() )
5013            break;
5014
5015        assert(p_vci_ini_rw.reop.read() &&
5016               "illegal VCI response packet for sc tlb");
5017
5018        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
5019        {
5020            r_vci_rsp_data_error = true;
5021        }
5022        else if ( p_vci_ini_rw.rdata.read() == 1 ) // store conditional is not successful
5023        {
5024            r_dcache_tlb_ll_dirty_req = true;
5025        }
5026        r_dcache_tlb_sc_dirty_req = false;
5027        r_vci_rsp_fsm = RSP_IDLE;
5028        break;
5029
5030    case RSP_DATA_UNC:
5031        m_cost_unc_transaction++;
5032        if ( ! p_vci_ini_rw.rspval.read() )
5033            break;
5034
5035        assert(p_vci_ini_rw.reop.read() &&
5036               "illegal VCI response packet for data read uncached");
5037
5038        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
5039        {
5040            r_vci_rsp_data_error = true;
5041        }
5042        else
5043        {
5044            r_dcache_miss_buf[0] = (data_t)p_vci_ini_rw.rdata.read();
5045            r_dcache_buf_unc_valid = true;
5046        }
5047        r_dcache_unc_req = false;
5048        r_vci_rsp_fsm = RSP_IDLE;
5049        break;
5050
5051    case RSP_DATA_MISS:
5052        m_cost_dmiss_transaction++;
5053        if ( ! p_vci_ini_rw.rspval.read() )
5054            break;
5055
5056        assert(r_vci_rsp_cpt != m_dcache_words &&
5057               "illegal VCI response packet for data read miss");
5058
5059        r_vci_rsp_cpt = r_vci_rsp_cpt + 1;
5060        r_dcache_miss_buf[r_vci_rsp_cpt] = (data_t)p_vci_ini_rw.rdata.read();
5061        if ( p_vci_ini_rw.reop.read() )
5062        {
5063            assert(r_vci_rsp_cpt == m_dcache_words - 1 &&
5064                    "illegal VCI response packet for data read miss");
5065            r_dcache_miss_req = false;
5066            r_vci_rsp_fsm = RSP_IDLE;
5067        }
5068        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
5069        {
5070            r_vci_rsp_data_error = true;
5071        }
5072        break;
5073
5074    case RSP_DATA_WRITE:
5075        m_cost_write_transaction++;
5076        if ( ! p_vci_ini_rw.rspval.read() )
5077            break;
5078
5079        if ( p_vci_ini_rw.reop.read() )
5080        {
5081            r_vci_rsp_fsm = RSP_IDLE;
5082            r_dcache_write_req = false;
5083        }
5084        if ( p_vci_ini_rw.rerror.read() != vci_param::ERR_NORMAL )
5085        {
5086            m_iss.setWriteBerr();
5087        }
5088        break;
5089    } // end switch r_vci_rsp_fsm
5090
5091    ////////////////////////////////////////////////////////////////////////////
5092    //     VCI_CMD_CLEANUP FSM
5093    //
5094    // This FSM handles requests from both the DCACHE controler
5095    // (request registers) and the ICACHE controler (request registers).
5096    // There is 10 VCI transaction types :
5097    // - INS_TLB_READ
5098    // - INS_TLB_WRITE
5099    // - INS_MISS
5100    // - INS_UNC_MISS
5101    // - DATA_TLB_READ
5102    // - DATA_TLB_WRITE
5103    // - DATA_TLB_DIRTY
5104    // - DATA_MISS
5105    // - DATA_UNC
5106    // - DATA_WRITE
5107    // The ICACHE requests have the highest priority.
5108    // There is at most one (CMD/RSP) VCI transaction, as both CMD_FSM and RSP_FSM
5109    // exit simultaneously the IDLE state.
5110    //////////////////////////////////////////////////////////////////////////////
5111
5112    switch (r_vci_cmd_cleanup_fsm) {
5113   
5114    case CMD_CLEANUP_INS_IDLE:
5115        if ((r_vci_rsp_cleanup_fsm != RSP_CLEANUP_INS_IDLE) && (r_vci_rsp_cleanup_fsm != RSP_CLEANUP_DATA_IDLE))
5116            break;
5117
5118        if (r_icache_cleanup_req)           
5119        {           
5120            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS;
5121            //m_cpt_ins_cleanup_transaction++;
5122        }
5123        else if (r_dcache_cleanup_req)     
5124        { 
5125            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA;
5126            //m_cpt_data_cleanup_transaction++;
5127        }
5128        break;
5129
5130    case CMD_CLEANUP_DATA_IDLE:
5131        if ((r_vci_rsp_cleanup_fsm != RSP_CLEANUP_INS_IDLE) && (r_vci_rsp_cleanup_fsm != RSP_CLEANUP_DATA_IDLE))
5132            break;
5133
5134        if (r_dcache_cleanup_req)           
5135        {           
5136            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA;
5137            //m_cpt_data_cleanup_transaction++;
5138        }
5139        else if (r_icache_cleanup_req)     
5140        { 
5141            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS;
5142            //m_cpt_ins_cleanup_transaction++;
5143        }
5144        break;
5145
5146    case CMD_CLEANUP_INS:
5147        if ( p_vci_ini_c.cmdack.read() )
5148        { 
5149            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_DATA_IDLE;
5150        }
5151        break;
5152
5153    case CMD_CLEANUP_DATA:
5154        if ( p_vci_ini_c.cmdack.read() )
5155        { 
5156            r_vci_cmd_cleanup_fsm = CMD_CLEANUP_INS_IDLE;
5157        }
5158        break;
5159    } // end  switch r_vci_cmd_cleanup_fsm
5160
5161    //////////////////////////////////////////////////////////////////////////
5162    //      VCI_RSP FSM
5163    //
5164    // This FSM is synchronized with the VCI_CMD FSM, as both FSMs exit the
5165    // IDLE state simultaneously.
5166    //////////////////////////////////////////////////////////////////////////
5167
5168    switch (r_vci_rsp_cleanup_fsm) {
5169
5170    case RSP_CLEANUP_INS_IDLE:
5171        assert( ! p_vci_ini_c.rspval.read() && "Unexpected response" );
5172
5173        if ((r_vci_cmd_cleanup_fsm != CMD_CLEANUP_INS_IDLE) && (r_vci_cmd_cleanup_fsm != CMD_CLEANUP_DATA_IDLE))
5174            break;
5175
5176        if (r_icache_cleanup_req)
5177        {
5178            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS;
5179        }
5180        else if (r_dcache_cleanup_req)
5181        {
5182            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA;
5183        }
5184        break;
5185
5186    case RSP_CLEANUP_DATA_IDLE:
5187        assert( ! p_vci_ini_c.rspval.read() && "Unexpected response" );
5188
5189        if ((r_vci_cmd_cleanup_fsm != CMD_CLEANUP_INS_IDLE) && (r_vci_cmd_cleanup_fsm != CMD_CLEANUP_DATA_IDLE))
5190            break;
5191
5192        if (r_dcache_cleanup_req)
5193        {
5194            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA;
5195        }
5196        else if (r_icache_cleanup_req)
5197        {
5198            r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS;
5199        }
5200        break;
5201
5202    case RSP_CLEANUP_INS:
5203        if ( ! p_vci_ini_c.rspval.read() )
5204            break;
5205        assert( p_vci_ini_c.reop.read() &&
5206                "illegal VCI CLEANUP response packet for icache cleanup");
5207        assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
5208                "error in response packet for icache cleanup");
5209
5210        r_icache_cleanup_req = false;
5211        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_DATA_IDLE;
5212        break;
5213
5214    case RSP_CLEANUP_DATA:
5215        if ( ! p_vci_ini_c.rspval.read() )
5216            break;
5217        assert( p_vci_ini_c.reop.read() &&
5218                "illegal VCI CLEANUP response packet for icache cleanup");
5219        assert( (p_vci_ini_c.rerror.read() == vci_param::ERR_NORMAL) &&
5220                "error in response packet for icache cleanup");
5221
5222        r_dcache_cleanup_req = false;
5223        r_vci_rsp_cleanup_fsm = RSP_CLEANUP_INS_IDLE;
5224        break;
5225
5226    } // end switch r_vci_rsp_cleanup_fsm
5227} // end transition()
5228
5229///////////////////////
5230tmpl(void)::genMoore()
5231///////////////////////
5232{
5233    // VCI initiator response
5234
5235    p_vci_ini_rw.rspack = true;
5236
5237    // VCI initiator command
5238
5239    p_vci_ini_rw.pktid  = 0;
5240    p_vci_ini_rw.srcid  = m_srcid_rw;
5241    p_vci_ini_rw.cons   = false;
5242    p_vci_ini_rw.wrap   = false;
5243    p_vci_ini_rw.contig = true;
5244    p_vci_ini_rw.clen   = 0;
5245    p_vci_ini_rw.cfixed = false;
5246
5247    switch (r_vci_cmd_fsm) {
5248
5249    case CMD_IDLE:
5250        p_vci_ini_rw.cmdval  = false;
5251        p_vci_ini_rw.address = 0;
5252        p_vci_ini_rw.wdata   = 0;
5253        p_vci_ini_rw.be      = 0;
5254        p_vci_ini_rw.trdid   = 0;
5255        p_vci_ini_rw.plen    = 0;
5256        p_vci_ini_rw.cmd     = vci_param::CMD_NOP;
5257        p_vci_ini_rw.eop     = false;
5258        break;
5259
5260    case CMD_ITLB_READ:     
5261        p_vci_ini_rw.cmdval  = true;
5262        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_dcache_yzmask;
5263        p_vci_ini_rw.wdata   = 0;
5264        p_vci_ini_rw.be      = 0xF;
5265        p_vci_ini_rw.trdid   = 1; // via data cache cached read
5266        p_vci_ini_rw.plen    = m_dcache_words << 2;
5267        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
5268        p_vci_ini_rw.eop     = true;
5269        break;
5270
5271    case CMD_ITLB_ACC_LL:
5272        p_vci_ini_rw.cmdval  = true;
5273        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
5274        p_vci_ini_rw.wdata   = 0;
5275        p_vci_ini_rw.be      = 0xF;
5276        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5277        p_vci_ini_rw.plen    = 4;
5278        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
5279        p_vci_ini_rw.eop     = true;
5280        break;
5281
5282    case CMD_ITLB_ACC_SC:
5283        p_vci_ini_rw.cmdval  = true;
5284        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
5285        p_vci_ini_rw.wdata   = r_icache_pte_update.read();
5286        p_vci_ini_rw.be      = 0xF;
5287        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5288        p_vci_ini_rw.plen    = 4;
5289        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
5290        p_vci_ini_rw.eop     = true;
5291        break; 
5292
5293    case CMD_INS_MISS:
5294        p_vci_ini_rw.cmdval  = true;
5295        p_vci_ini_rw.address = r_icache_paddr_save.read() & m_icache_yzmask;
5296        p_vci_ini_rw.wdata   = 0;
5297        p_vci_ini_rw.be      = 0xF;
5298        p_vci_ini_rw.trdid   = 3; // ins cache cached read
5299        p_vci_ini_rw.plen    = m_icache_words << 2;
5300        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
5301        p_vci_ini_rw.eop     = true;
5302        break;
5303
5304    case CMD_INS_UNC:
5305        p_vci_ini_rw.cmdval  = true;
5306        p_vci_ini_rw.address = r_icache_paddr_save.read() & ~0x3;
5307        p_vci_ini_rw.wdata   = 0;
5308        p_vci_ini_rw.be      = 0xF;
5309        p_vci_ini_rw.trdid   = 2; // ins cache uncached read
5310        p_vci_ini_rw.plen    = 4;
5311        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
5312        p_vci_ini_rw.eop     = true;
5313        break;
5314
5315    case CMD_DTLB_READ:     
5316        p_vci_ini_rw.cmdval  = true;
5317        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & m_dcache_yzmask;
5318        p_vci_ini_rw.wdata   = 0;
5319        p_vci_ini_rw.be      = 0xF;
5320        p_vci_ini_rw.trdid   = 1; // via dcache cached read
5321        p_vci_ini_rw.plen    = m_dcache_words << 2;
5322        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
5323        p_vci_ini_rw.eop     = true;
5324        break;
5325
5326    case CMD_DTLB_ACC_LL:
5327        p_vci_ini_rw.cmdval  = true;
5328        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
5329        p_vci_ini_rw.wdata   = 0;
5330        p_vci_ini_rw.be      = 0xF;
5331        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5332        p_vci_ini_rw.plen    = 4;
5333        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
5334        p_vci_ini_rw.eop     = true;
5335        break;
5336
5337    case CMD_DTLB_ACC_SC:
5338        p_vci_ini_rw.cmdval  = true;
5339        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
5340        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
5341        p_vci_ini_rw.be      = 0xF;
5342        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5343        p_vci_ini_rw.plen    = 4;
5344        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
5345        p_vci_ini_rw.eop     = true;
5346        break; 
5347
5348    case CMD_DTLB_DIRTY_LL:
5349        p_vci_ini_rw.cmdval  = true;
5350        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
5351        p_vci_ini_rw.wdata   = 0;
5352        p_vci_ini_rw.be      = 0xF;
5353        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5354        p_vci_ini_rw.plen    = 4;
5355        p_vci_ini_rw.cmd     = vci_param::CMD_LOCKED_READ;
5356        p_vci_ini_rw.eop     = true;
5357        break;
5358
5359    case CMD_DTLB_DIRTY_SC:
5360        p_vci_ini_rw.cmdval  = true;
5361        p_vci_ini_rw.address = r_dcache_tlb_paddr.read() & ~0x3;
5362        p_vci_ini_rw.wdata   = r_dcache_pte_update.read();
5363        p_vci_ini_rw.be      = 0xF;
5364        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5365        p_vci_ini_rw.plen    = 4;
5366        p_vci_ini_rw.cmd     = vci_param::CMD_STORE_COND;
5367        p_vci_ini_rw.eop     = true;
5368        break; 
5369
5370    case CMD_DATA_UNC:
5371        p_vci_ini_rw.cmdval  = true;
5372        p_vci_ini_rw.address = r_dcache_paddr_save.read() & ~0x3;
5373        p_vci_ini_rw.trdid   = 0; // data cache uncached read
5374        p_vci_ini_rw.plen    = 4;
5375        p_vci_ini_rw.eop     = true;
5376        switch(r_dcache_type_save) {
5377        case iss_t::DATA_READ:
5378            p_vci_ini_rw.wdata = 0;
5379            p_vci_ini_rw.be    = r_dcache_be_save.read();
5380            p_vci_ini_rw.cmd   = vci_param::CMD_READ;
5381            break;
5382        case iss_t::DATA_LL:
5383            p_vci_ini_rw.wdata = 0;
5384            p_vci_ini_rw.be    = 0xF;
5385            p_vci_ini_rw.cmd   = vci_param::CMD_LOCKED_READ;
5386            break;
5387        case iss_t::DATA_SC:
5388            p_vci_ini_rw.wdata = r_dcache_wdata_save.read();
5389            p_vci_ini_rw.be    = 0xF;
5390            p_vci_ini_rw.cmd   = vci_param::CMD_STORE_COND;
5391            break;
5392        default:
5393            assert("this should not happen");
5394        }
5395        break;
5396
5397    case CMD_DATA_WRITE:
5398        p_vci_ini_rw.cmdval  = true;
5399        p_vci_ini_rw.address = r_wbuf.getAddress(r_vci_cmd_cpt);
5400        p_vci_ini_rw.wdata   = r_wbuf.getData(r_vci_cmd_cpt);
5401        p_vci_ini_rw.be      = r_wbuf.getBe(r_vci_cmd_cpt);
5402        p_vci_ini_rw.trdid   = 0; // data cache write
5403        p_vci_ini_rw.plen    = (r_vci_cmd_max - r_vci_cmd_min + 1)<<2;
5404        p_vci_ini_rw.cmd     = vci_param::CMD_WRITE;
5405        p_vci_ini_rw.eop     = (r_vci_cmd_cpt == r_vci_cmd_max);
5406        break;
5407
5408    case CMD_DATA_MISS:
5409        p_vci_ini_rw.cmdval  = true;
5410        p_vci_ini_rw.address = r_dcache_paddr_save.read() & m_dcache_yzmask;
5411        p_vci_ini_rw.wdata   = 0;
5412        p_vci_ini_rw.be      = 0xF;
5413        p_vci_ini_rw.trdid   = 1; // data cache cached read
5414        p_vci_ini_rw.plen    = m_dcache_words << 2;
5415        p_vci_ini_rw.cmd     = vci_param::CMD_READ;
5416        p_vci_ini_rw.eop     = true;
5417        break;
5418    } // end switch r_vci_cmd_fsm
5419
5420    // VCI initiator response
5421
5422    p_vci_ini_c.rspack = true;
5423
5424    // VCI initiator command
5425
5426    p_vci_ini_c.pktid  = 0;
5427    p_vci_ini_c.srcid  = m_srcid_c;
5428    p_vci_ini_c.cons   = false;
5429    p_vci_ini_c.wrap   = false;
5430    p_vci_ini_c.contig = true;
5431    p_vci_ini_c.clen   = 0;
5432    p_vci_ini_c.cfixed = false;
5433
5434    switch (r_vci_cmd_cleanup_fsm) {
5435
5436    case CMD_CLEANUP_INS_IDLE:
5437    case CMD_CLEANUP_DATA_IDLE:
5438        p_vci_ini_c.cmdval  = false;
5439        p_vci_ini_c.address = 0;
5440        p_vci_ini_c.wdata   = 0;
5441        p_vci_ini_c.be      = 0;
5442        p_vci_ini_c.trdid   = 0;
5443        p_vci_ini_c.plen    = 0;
5444        p_vci_ini_c.cmd     = vci_param::CMD_NOP;
5445        p_vci_ini_c.eop     = false;
5446        break;
5447
5448    case CMD_CLEANUP_INS:
5449    case CMD_CLEANUP_DATA:
5450        p_vci_ini_c.cmdval = true;
5451        if ( r_vci_cmd_cleanup_fsm == CMD_CLEANUP_INS ) p_vci_ini_c.address = r_icache_cleanup_line.read() * (m_icache_words<<2);
5452        else                                            p_vci_ini_c.address = r_dcache_cleanup_line.read() * (m_dcache_words<<2);
5453        p_vci_ini_c.wdata  = 0;
5454        p_vci_ini_c.be     = 0;
5455        p_vci_ini_c.trdid  = 1; // cleanup for distinguish from a write
5456        p_vci_ini_c.plen   = 4;
5457        p_vci_ini_c.cmd    = vci_param::CMD_WRITE;
5458        p_vci_ini_c.contig = false;
5459        p_vci_ini_c.eop    = true;
5460        break;
5461
5462    } // end switch r_vci_cmd_cleanup_fsm
5463
5464    // VCI_TGT
5465    switch ( r_vci_tgt_fsm.read() ) {
5466
5467    case TGT_IDLE:
5468    case TGT_UPDT_WORD:
5469    case TGT_UPDT_DATA:
5470        p_vci_tgt.cmdack  = true;
5471        p_vci_tgt.rspval  = false;
5472        break;
5473
5474    case TGT_RSP_BROADCAST:
5475        p_vci_tgt.cmdack  = false;
5476        p_vci_tgt.rspval  = !r_tgt_icache_req.read() && !r_tgt_dcache_req.read() && ( r_tgt_icache_rsp | r_tgt_dcache_rsp );
5477        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
5478        p_vci_tgt.rpktid  = r_tgt_pktid.read();
5479        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
5480        p_vci_tgt.rdata   = 0;
5481        p_vci_tgt.rerror  = 0;
5482        p_vci_tgt.reop    = true;
5483        break;
5484
5485    case TGT_RSP_DCACHE:
5486        p_vci_tgt.cmdack  = false;
5487        p_vci_tgt.rspval  = !r_tgt_dcache_req.read();
5488        p_vci_tgt.rsrcid  = r_tgt_srcid.read();
5489        p_vci_tgt.rpktid  = r_tgt_pktid.read();
5490        p_vci_tgt.rtrdid  = r_tgt_trdid.read();
5491        p_vci_tgt.rdata   = 0;
5492        p_vci_tgt.rerror  = 0;
5493        p_vci_tgt.reop    = true;
5494        break;
5495
5496    case TGT_REQ_BROADCAST:
5497    case TGT_REQ_DCACHE:
5498        p_vci_tgt.cmdack  = false;
5499        p_vci_tgt.rspval  = false;
5500        break;
5501
5502    } // end switch TGT_FSM
5503
5504#ifdef SOCLIB_MODULE_DEBUG
5505   std::cout << name()
5506             << "Moore:" << std::hex
5507             << " p_vci_ini_rw.cmdval: " << p_vci_ini_rw.cmdval
5508             << " p_vci_ini_rw.address: " << p_vci_ini_rw.address
5509             << " p_vci_ini_rw.wdata: " << p_vci_ini_rw.wdata
5510             << " p_vci_ini_rw.cmd: " << p_vci_ini_rw.cmd
5511             << " p_vci_ini_rw.eop: " << p_vci_ini_rw.eop
5512             << std::endl;
5513
5514   std::cout << name()
5515             << "Moore:" << std::hex
5516             << " p_vci_ini_c.cmdval: " << p_vci_ini_c.cmdval
5517             << " p_vci_ini_c.address: " << p_vci_ini_c.address
5518             << " p_vci_ini_c.wdata: " << p_vci_ini_c.wdata
5519             << " p_vci_ini_c.cmd: " << p_vci_ini_c.cmd
5520             << " p_vci_ini_c.eop: " << p_vci_ini_c.eop
5521             << std::endl;
5522#endif
5523
5524}
5525
5526}}
5527
5528// Local Variables:
5529// tab-width: 4
5530// c-basic-offset: 4
5531// c-file-offsets:((innamespace . 0)(inline-open . 0))
5532// indent-tabs-mode: nil
5533// End:
5534
5535// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
Note: See TracBrowser for help on using the repository browser.