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

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

Bug correction

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