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

Last change on this file since 120 was 120, checked in by gao, 13 years ago

Separated cleanup from the vci_fsm to avoid deadlock

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