source: trunk/modules/vci_cc_vcache_wrapper2_v1/caba/source/src/vci_cc_vcache_wrapper2_v1.cpp @ 12

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