source: trunk/modules/vci_cc_vcache_wrapper2_multi/caba/source/src/vci_cc_vcache_wrapper2_multi.cpp @ 18

Last change on this file since 18 was 18, checked in by gao, 14 years ago

Bug correction

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