source: trunk/modules/vci_cc_vcache_wrapper_v4/caba/source/src/vci_cc_vcache_wrapper_v4.cpp @ 209

Last change on this file since 209 was 209, checked in by bouyer, 12 years ago

Initialize all variables that will be used later

File size: 185.0 KB
Line 
1/* -*- c++ -*-C
2 * File : vci_cc_vcache_wrapper_v4.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_wrapper_v4.h"
30
31#define DEBUG_DCACHE            1
32#define DEBUG_ICACHE            1
33#define DEBUG_CLEANUP           0
34
35namespace soclib { 
36namespace caba {
37
38namespace {
39const char *icache_fsm_state_str[] = {
40        "ICACHE_IDLE",
41     
42        "ICACHE_XTN_TLB_FLUSH", 
43        "ICACHE_XTN_CACHE_FLUSH", 
44        "ICACHE_XTN_TLB_INVAL", 
45        "ICACHE_XTN_CACHE_INVAL_VA",
46        "ICACHE_XTN_CACHE_INVAL_PA",
47        "ICACHE_XTN_CACHE_INVAL_GO",
48
49        "ICACHE_TLB_WAIT",
50
51        "ICACHE_MISS_VICTIM",
52        "ICACHE_MISS_INVAL",
53        "ICACHE_MISS_WAIT",
54        "ICACHE_MISS_UPDT", 
55
56        "ICACHE_UNC_WAIT", 
57
58        "ICACHE_CC_CHECK", 
59        "ICACHE_CC_INVAL", 
60        "ICACHE_CC_UPDT", 
61       
62    };
63const char *dcache_fsm_state_str[] = {
64        "DCACHE_IDLE",       
65
66        "DCACHE_TLB_MISS",
67        "DCACHE_TLB_PTE1_GET",
68        "DCACHE_TLB_PTE1_SELECT", 
69        "DCACHE_TLB_PTE1_UPDT", 
70        "DCACHE_TLB_PTE2_GET", 
71        "DCACHE_TLB_PTE2_SELECT",
72        "DCACHE_TLB_PTE2_UPDT",   
73        "DCACHE_TLB_LR_UPDT",
74        "DCACHE_TLB_LR_WAIT",
75        "DCACHE_TLB_RETURN",
76
77        "DCACHE_XTN_SWITCH", 
78        "DCACHE_XTN_SYNC", 
79        "DCACHE_XTN_IC_INVAL_VA",
80        "DCACHE_XTN_IC_FLUSH", 
81        "DCACHE_XTN_IC_INVAL_PA",
82        "DCACHE_XTN_IT_INVAL",
83        "DCACHE_XTN_DC_FLUSH", 
84        "DCACHE_XTN_DC_INVAL_VA",
85        "DCACHE_XTN_DC_INVAL_PA",
86        "DCACHE_XTN_DC_INVAL_END",
87        "DCACHE_XTN_DC_INVAL_GO",
88        "DCACHE_XTN_DT_INVAL",
89
90        "DCACHE_DIRTY_PTE_GET",
91        "DCACHE_DIRTY_SC_WAIT", 
92
93        "DCACHE_MISS_VICTIM",
94        "DCACHE_MISS_INVAL",
95        "DCACHE_MISS_WAIT", 
96        "DCACHE_MISS_UPDT", 
97
98        "DCACHE_UNC_WAIT",   
99        "DCACHE_SC_WAIT",   
100
101        "DCACHE_CC_CHECK",
102        "DCACHE_CC_INVAL",
103        "DCACHE_CC_UPDT",
104
105        "DCACHE_INVAL_TLB_SCAN",
106    };
107const char *cmd_fsm_state_str[] = {
108        "CMD_IDLE",           
109        "CMD_INS_MISS",     
110        "CMD_INS_UNC",     
111        "CMD_DATA_MISS",   
112        "CMD_DATA_UNC",     
113        "CMD_DATA_WRITE", 
114        "CMD_DATA_SC", 
115    };
116const char *rsp_fsm_state_str[] = {
117        "RSP_IDLE",                 
118        "RSP_INS_MISS",   
119        "RSP_INS_UNC",           
120        "RSP_DATA_MISS",             
121        "RSP_DATA_UNC",             
122        "RSP_DATA_WRITE",     
123    };
124const char *cleanup_fsm_state_str[] = {
125        "CLEANUP_DATA_IDLE",           
126        "CLEANUP_DATA_GO",   
127        "CLEANUP_INS_IDLE",     
128        "CLEANUP_INS_GO",     
129    };
130const char *tgt_fsm_state_str[] = {
131        "TGT_IDLE",
132        "TGT_UPDT_WORD",
133        "TGT_UPDT_DATA",
134        "TGT_REQ_BROADCAST",
135        "TGT_REQ_ICACHE",
136        "TGT_REQ_DCACHE",
137        "TGT_RSP_BROADCAST",
138        "TGT_RSP_ICACHE",
139        "TGT_RSP_DCACHE",
140    }; 
141}
142
143#define tmpl(...)  template<typename vci_param, typename iss_t> __VA_ARGS__ VciCcVCacheWrapperV4<vci_param, iss_t>
144
145using soclib::common::uint32_log2;
146
147/////////////////////////////////
148tmpl(/**/)::VciCcVCacheWrapperV4(
149    sc_module_name                      name,
150    int                                 proc_id,
151    const soclib::common::MappingTable  &mtp,
152    const soclib::common::MappingTable  &mtc,
153    const soclib::common::IntTab        &initiator_index_d,
154    const soclib::common::IntTab        &initiator_index_c,
155    const soclib::common::IntTab        &target_index_d,
156    size_t                              itlb_ways,
157    size_t                              itlb_sets,
158    size_t                              dtlb_ways,
159    size_t                              dtlb_sets,
160    size_t                              icache_ways,
161    size_t                              icache_sets,
162    size_t                              icache_words,
163    size_t                              dcache_ways,
164    size_t                              dcache_sets,
165    size_t                              dcache_words,
166    size_t                              wbuf_nlines, 
167    size_t                              wbuf_nwords, 
168    uint32_t                            max_frozen_cycles,
169    uint32_t                            debug_start_cycle,
170    bool                                debug_ok)
171    : soclib::caba::BaseModule(name),
172
173      p_clk("clk"),
174      p_resetn("resetn"),
175      p_vci_ini_d("vci_ini_d"),
176      p_vci_ini_c("vci_ini_c"),
177      p_vci_tgt_c("vci_tgt_d"),
178
179      m_cacheability_table(mtp.getCacheabilityTable()),
180      m_segment(mtc.getSegment(target_index_d)),
181      m_srcid_d(mtp.indexForId(initiator_index_d)),
182      m_srcid_c(mtp.indexForId(initiator_index_c)),
183
184      m_itlb_ways(itlb_ways),
185      m_itlb_sets(itlb_sets),
186
187      m_dtlb_ways(dtlb_ways),
188      m_dtlb_sets(dtlb_sets),
189
190      m_icache_ways(icache_ways),
191      m_icache_sets(icache_sets),
192      m_icache_yzmask((~0)<<(uint32_log2(icache_words) + 2)),
193      m_icache_words(icache_words),
194
195      m_dcache_ways(dcache_ways),
196      m_dcache_sets(dcache_sets),
197      m_dcache_yzmask((~0)<<(uint32_log2(dcache_words) + 2)),
198      m_dcache_words(dcache_words),
199
200      m_proc_id(proc_id),
201
202      m_max_frozen_cycles(max_frozen_cycles),
203
204      m_paddr_nbits(vci_param::N),
205
206      m_debug_start_cycle(debug_start_cycle),
207      m_debug_ok(debug_ok),
208
209      r_mmu_ptpr("r_mmu_ptpr"),
210      r_mmu_mode("r_mmu_mode"),
211      r_mmu_word_lo("r_mmu_word_lo"),
212      r_mmu_word_hi("r_mmu_word_hi"),
213      r_mmu_ibvar("r_mmu_ibvar"),
214      r_mmu_dbvar("r_mmu_dbvar"),
215      r_mmu_ietr("r_mmu_ietr"),
216      r_mmu_detr("r_mmu_detr"),
217
218      r_icache_fsm("r_icache_fsm"),
219      r_icache_fsm_save("r_icache_fsm_save"),
220      r_icache_vci_paddr("r_icache_vci_paddr"),
221      r_icache_vaddr_save("r_icache_vaddr_save"),
222
223      r_icache_miss_way("r_icache_miss_way"),
224      r_icache_miss_set("r_icache_miss_set"),
225      r_icache_miss_word("r_icache_miss_word"),
226      r_icache_miss_inval("r_icache_miss_inval"),
227
228      r_icache_cc_way("r_icache_cc_way"),
229      r_icache_cc_set("r_icache_cc_set"),
230      r_icache_cc_word("r_icache_cc_word"),
231
232      r_icache_flush_count("r_icache_flush_count"),
233
234      r_icache_miss_req("r_icache_miss_req"),
235      r_icache_unc_req("r_icache_unc_req"),
236
237      r_icache_tlb_miss_req("r_icache_tlb_read_req"),
238      r_icache_tlb_rsp_error("r_icache_tlb_rsp_error"),
239
240      r_icache_cleanup_req("r_icache_cleanup_req"),
241      r_icache_cleanup_line("r_icache_cleanup_line"),
242
243      r_dcache_fsm("r_dcache_fsm"),
244      r_dcache_fsm_save("r_dcache_fsm_save"),
245
246      r_dcache_p0_valid("r_dcache_p0_valid"),
247      r_dcache_p0_vaddr("r_dcache_p0_vaddr"),
248      r_dcache_p0_wdata("r_dcache_p0_wdata"),
249      r_dcache_p0_be("r_dcache_p0_be"),
250      r_dcache_p0_paddr("r_dcache_p0_paddr"),
251      r_dcache_p0_cacheable("r_dcache_p0_cacheable"), 
252
253      r_dcache_p1_valid("r_dcache_p1_valid"),
254      r_dcache_p1_wdata("r_dcache_p1_wdata"),
255      r_dcache_p1_be("r_dcache_p1_be"),
256      r_dcache_p1_paddr("r_dcache_p1_paddr"),
257      r_dcache_p1_cache_way("r_dcache_p1_cache_way"),
258      r_dcache_p1_cache_set("r_dcache_p1_cache_set"),
259      r_dcache_p1_cache_word("r_dcache_p1_word_save"),
260
261      r_dcache_dirty_paddr("r_dcache_dirty_paddr"),
262      r_dcache_dirty_way("r_dcache_dirty_way"),
263      r_dcache_dirty_set("r_dcache_dirty_set"),
264
265      r_dcache_vci_paddr("r_dcache_vci_paddr"),
266      r_dcache_vci_miss_req("r_dcache_vci_miss_req"),
267      r_dcache_vci_unc_req("r_dcache_vci_unc_req"),
268      r_dcache_vci_unc_be("r_dcache_vci_unc_be"),
269      r_dcache_vci_sc_req("r_dcache_vci_sc_req"),
270      r_dcache_vci_sc_old("r_dcache_vci_sc_old"),
271      r_dcache_vci_sc_new("r_dcache_vci_sc_new"),
272
273      r_dcache_xtn_way("r_dcache_xtn_way"),
274      r_dcache_xtn_set("r_dcache_xtn_set"),
275
276      r_dcache_pending_unc_write("r_dcache_pending_unc_write"),
277
278      r_dcache_miss_type("r_dcache_miss_type"),
279      r_dcache_miss_word("r_dcache_miss_word"),
280      r_dcache_miss_way("r_dcache_miss_way"),
281      r_dcache_miss_set("r_dcache_miss_set"),
282      r_dcache_miss_inval("r_dcache_miss_inval"),
283
284      r_dcache_cc_way("r_dcache_cc_way"),
285      r_dcache_cc_set("r_dcache_cc_set"),
286      r_dcache_cc_word("r_dcache_cc_word"),
287
288      r_dcache_flush_count("r_dcache_flush_count"),
289
290      r_dcache_tlb_vaddr("r_dcache_tlb_vaddr"),
291      r_dcache_tlb_ins("r_dcache_tlb_ins"),
292      r_dcache_tlb_pte_flags("r_dcache_tlb_pte_flags"),
293      r_dcache_tlb_pte_ppn("r_dcache_tlb_pte_ppn"),
294      r_dcache_tlb_cache_way("r_dcache_tlb_cache_way"),
295      r_dcache_tlb_cache_set("r_dcache_tlb_cache_set"),
296      r_dcache_tlb_cache_word("r_dcache_tlb_cache_word"),
297      r_dcache_tlb_way("r_dcache_tlb_way"),
298      r_dcache_tlb_set("r_dcache_tlb_set"),
299
300      r_dcache_ll_valid("r_dcache_ll_valid"),
301      r_dcache_ll_data("r_dcache_ll_data"),
302      r_dcache_ll_vaddr("r_dcache_ll_vaddr"),
303
304      r_dcache_tlb_inval_line("r_dcache_tlb_inval_line"),
305      r_dcache_tlb_inval_count("r_dcache_tlb_inval_count"),
306
307      r_dcache_xtn_req("r_dcache_xtn_req"),
308      r_dcache_xtn_opcode("r_dcache_xtn_opcode"),
309
310      r_dcache_cleanup_req("r_dcache_cleanup_req"),
311      r_dcache_cleanup_line("r_dcache_cleanup_line"),
312
313      r_vci_cmd_fsm("r_vci_cmd_fsm"),
314      r_vci_cmd_min("r_vci_cmd_min"),
315      r_vci_cmd_max("r_vci_cmd_max"),
316      r_vci_cmd_cpt("r_vci_cmd_cpt"),
317      r_vci_cmd_imiss_prio("r_vci_cmd_imiss_prio"),
318
319      r_vci_rsp_fsm("r_vci_rsp_fsm"),
320      r_vci_rsp_cpt("r_vci_rsp_cpt"),
321      r_vci_rsp_ins_error("r_vci_rsp_ins_error"),
322      r_vci_rsp_data_error("r_vci_rsp_data_error"),
323      r_vci_rsp_fifo_icache("r_vci_rsp_fifo_icache", 2),        // 2 words depth
324      r_vci_rsp_fifo_dcache("r_vci_rsp_fifo_dcache", 2),        // 2 words depth
325
326      r_cleanup_fsm("r_cleanup_fsm"),
327      r_cleanup_trdid("r_cleanup_trdid"),
328      r_cleanup_buffer(4),                      // up to 4 simultaneous cleanups
329
330      r_tgt_fsm("r_tgt_fsm"),
331      r_tgt_paddr("r_tgt_paddr"),
332      r_tgt_word_count("r_tgt_word_count"),
333      r_tgt_word_min("r_tgt_word_min"),
334      r_tgt_word_max("r_tgt_word_max"),
335      r_tgt_update("r_tgt_update"),
336      r_tgt_update_data("r_tgt_update_data"),
337      r_tgt_srcid("r_tgt_srcid"),
338      r_tgt_pktid("r_tgt_pktid"),
339      r_tgt_trdid("r_tgt_trdid"),
340
341      r_tgt_icache_req("r_tgt_icache_req"),
342      r_tgt_dcache_req("r_tgt_dcache_req"),
343      r_tgt_icache_rsp("r_tgt_icache_rsp"),
344      r_tgt_dcache_rsp("r_tgt_dcache_rsp"),
345
346      r_iss(this->name(), proc_id),
347      r_wbuf("wbuf", wbuf_nwords, wbuf_nlines, dcache_words ),
348      r_icache("icache", icache_ways, icache_sets, icache_words),
349      r_dcache("dcache", dcache_ways, dcache_sets, dcache_words),
350      r_itlb("itlb", proc_id, itlb_ways,itlb_sets,vci_param::N),
351      r_dtlb("dtlb", proc_id, dtlb_ways,dtlb_sets,vci_param::N)
352{
353    assert( ((icache_words*vci_param::B) < (1<<vci_param::K)) and
354             "Need more PLEN bits.");
355
356    assert( (vci_param::T > 2) and ((1<<(vci_param::T-1)) >= (wbuf_nlines)) and
357             "Need more TRDID bits.");
358
359    assert( (icache_words == dcache_words) and
360             "icache_words and dcache_words parameters must be equal");
361
362    assert( (itlb_sets == dtlb_sets) and
363             "itlb_sets and dtlb_sets parameters must be etqual");
364
365    assert( (itlb_ways == dtlb_ways) and
366             "itlb_ways and dtlb_ways parameters must be etqual");
367
368    r_mmu_params = (uint32_log2(m_dtlb_ways)   << 29)   | (uint32_log2(m_dtlb_sets)   << 25) |
369                   (uint32_log2(m_dcache_ways) << 22)   | (uint32_log2(m_dcache_sets) << 18) |
370                   (uint32_log2(m_itlb_ways)   << 15)   | (uint32_log2(m_itlb_sets)   << 11) |
371                   (uint32_log2(m_icache_ways) << 8)    | (uint32_log2(m_icache_sets) << 4)  |
372                   (uint32_log2(m_icache_words<<2));
373
374    r_mmu_release = (uint32_t)(1 << 16) | 0x1;
375
376    r_tgt_buf             = new uint32_t[dcache_words];
377    r_tgt_be              = new vci_be_t[dcache_words];
378    r_dcache_in_tlb       = new bool[dcache_ways*dcache_sets];         
379    r_dcache_contains_ptd = new bool[dcache_ways*dcache_sets];         
380
381    SC_METHOD(transition);
382    dont_initialize();
383    sensitive << p_clk.pos();
384 
385    SC_METHOD(genMoore);
386    dont_initialize();
387    sensitive << p_clk.neg();
388
389    typename iss_t::CacheInfo cache_info;
390    cache_info.has_mmu = true;
391    cache_info.icache_line_size = icache_words*sizeof(uint32_t);
392    cache_info.icache_assoc = icache_ways;
393    cache_info.icache_n_lines = icache_sets;
394    cache_info.dcache_line_size = dcache_words*sizeof(uint32_t);
395    cache_info.dcache_assoc = dcache_ways;
396    cache_info.dcache_n_lines = dcache_sets;
397    r_iss.setCacheInfo(cache_info);
398}
399
400/////////////////////////////////////
401tmpl(/**/)::~VciCcVCacheWrapperV4()
402/////////////////////////////////////
403{
404    delete [] r_tgt_be;
405    delete [] r_tgt_buf;
406    delete [] r_dcache_in_tlb;         
407    delete [] r_dcache_contains_ptd;     
408}
409
410////////////////////////
411tmpl(void)::print_cpi()
412////////////////////////
413{
414    std::cout << name() << " CPI = " 
415        << (float)m_cpt_total_cycles/(m_cpt_total_cycles - m_cpt_frz_cycles) << std::endl ;
416}
417
418////////////////////////////////////
419tmpl(void)::print_trace(size_t mode)
420////////////////////////////////////
421{
422    // b0 : write buffer trace
423    // b1 : write buffer verbose
424    // b2 : dcache trace
425    // b3 : icache trace
426    // b4 : dtlb trace
427    // b5 : itlb trace
428
429    std::cout << std::dec << "PROC " << name() << std::endl;
430
431    std::cout << "  " << m_ireq << std::endl;
432    std::cout << "  " << m_irsp << std::endl;
433    std::cout << "  " << m_dreq << std::endl;
434    std::cout << "  " << m_drsp << std::endl;
435
436    std::cout << "  " << icache_fsm_state_str[r_icache_fsm.read()]
437              << " | " << dcache_fsm_state_str[r_dcache_fsm.read()]
438              << " | " << cmd_fsm_state_str[r_vci_cmd_fsm.read()]
439              << " | " << rsp_fsm_state_str[r_vci_rsp_fsm.read()]
440              << " | " << tgt_fsm_state_str[r_tgt_fsm.read()] 
441              << " | " << cleanup_fsm_state_str[r_cleanup_fsm.read()];
442    if (r_dcache_p0_valid.read() ) std::cout << " | P1_WRITE";
443    if (r_dcache_p1_valid.read() ) std::cout << " | P2_WRITE";
444    std::cout << std::endl;
445
446    if(mode & 0x01)
447    {
448        r_wbuf.printTrace((mode>>1)&1);
449    }
450    if(mode & 0x04)
451    {
452        std::cout << "  Data Cache" << std::endl;
453        r_dcache.printTrace();
454    }
455    if(mode & 0x08)
456    {
457        std::cout << "  Instruction Cache" << std::endl;
458        r_icache.printTrace();
459    }
460    if(mode & 0x10)
461    {
462        std::cout << "  Data TLB" << std::endl;
463        r_dtlb.printTrace();
464    }
465    if(mode & 0x20)
466    {
467        std::cout << "  Instruction TLB" << std::endl;
468        r_itlb.printTrace();
469    }
470}
471
472//////////////////////////////////////////
473tmpl(void)::cache_monitor( paddr_t addr )
474//////////////////////////////////////////
475{ 
476    size_t      cache_way;
477    size_t      cache_set;
478    size_t      cache_word;
479    uint32_t    cache_rdata;
480    bool        cache_hit = r_dcache.read( addr,
481                                           &cache_rdata,
482                                           &cache_way,
483                                           &cache_set,
484                                           &cache_word );
485    if ( cache_hit != m_debug_previous_hit )
486    {
487        std::cout << "PROC " << name() 
488                  << " cache change at cycle " << std::dec << m_cpt_total_cycles
489                  << " for adresse " << std::hex << addr
490                  << " / HIT = " << cache_hit << std::endl;
491    }
492    m_debug_previous_hit = cache_hit;
493}
494
495
496
497/*
498////////////////////////
499tmpl(void)::print_stats()
500////////////////////////
501{
502    float run_cycles = (float)(m_cpt_total_cycles - m_cpt_frz_cycles);
503    std::cout << name() << std::endl
504        << "- CPI                    = " << (float)m_cpt_total_cycles/run_cycles << std::endl
505        << "- READ RATE              = " << (float)m_cpt_read/run_cycles << std::endl
506        << "- WRITE RATE             = " << (float)m_cpt_write/run_cycles << std::endl
507        << "- IMISS_RATE             = " << (float)m_cpt_ins_miss/m_cpt_ins_read << std::endl
508        << "- DMISS RATE             = " << (float)m_cpt_data_miss/(m_cpt_read-m_cpt_unc_read) << std::endl 
509        << "- INS MISS COST          = " << (float)m_cost_ins_miss_frz/m_cpt_ins_miss << std::endl     
510        << "- DATA MISS COST         = " << (float)m_cost_data_miss_frz/m_cpt_data_miss << std::endl
511        << "- WRITE COST             = " << (float)m_cost_write_frz/m_cpt_write << std::endl       
512        << "- UNC COST               = " << (float)m_cost_unc_read_frz/m_cpt_unc_read << std::endl
513        << "- UNCACHED READ RATE     = " << (float)m_cpt_unc_read/m_cpt_read << std::endl
514        << "- CACHED WRITE RATE      = " << (float)m_cpt_write_cached/m_cpt_write << std::endl
515        << "- INS TLB MISS RATE      = " << (float)m_cpt_ins_tlb_miss/m_cpt_ins_tlb_read << std::endl
516        << "- DATA TLB MISS RATE     = " << (float)m_cpt_data_tlb_miss/m_cpt_data_tlb_read << std::endl
517        << "- ITLB MISS COST         = " << (float)m_cost_ins_tlb_miss_frz/m_cpt_ins_tlb_miss << std::endl
518        << "- DTLB MISS COST         = " << (float)m_cost_data_tlb_miss_frz/m_cpt_data_tlb_miss << std::endl   
519        << "- ITLB UPDATE ACC COST   = " << (float)m_cost_ins_tlb_update_acc_frz/m_cpt_ins_tlb_update_acc << std::endl
520        << "- DTLB UPDATE ACC COST   = " << (float)m_cost_data_tlb_update_acc_frz/m_cpt_data_tlb_update_acc << std::endl
521        << "- DTLB UPDATE DIRTY COST = " << (float)m_cost_data_tlb_update_dirty_frz/m_cpt_data_tlb_update_dirty << std::endl
522        << "- ITLB HIT IN DCACHE RATE= " << (float)m_cpt_ins_tlb_hit_dcache/m_cpt_ins_tlb_miss << std::endl
523        << "- DTLB HIT IN DCACHE RATE= " << (float)m_cpt_data_tlb_hit_dcache/m_cpt_data_tlb_miss << std::endl
524        << "- DCACHE FROZEN BY ITLB  = " << (float)m_cost_ins_tlb_occup_cache_frz/m_cpt_dcache_frz_cycles << std::endl
525        << "- DCACHE FOR TLB %       = " << (float)m_cpt_tlb_occup_dcache/(m_dcache_ways*m_dcache_sets) << std::endl
526        << "- NB CC BROADCAST        = " << m_cpt_cc_broadcast << std::endl
527        << "- NB CC UPDATE DATA      = " << m_cpt_cc_update_data << std::endl
528        << "- NB CC INVAL DATA       = " << m_cpt_cc_inval_data << std::endl
529        << "- NB CC INVAL INS        = " << m_cpt_cc_inval_ins << std::endl
530        << "- CC BROADCAST COST      = " << (float)m_cost_broadcast_frz/m_cpt_cc_broadcast << std::endl
531        << "- CC UPDATE DATA COST    = " << (float)m_cost_updt_data_frz/m_cpt_cc_update_data << std::endl
532        << "- CC INVAL DATA COST     = " << (float)m_cost_inval_data_frz/m_cpt_cc_inval_data << std::endl
533        << "- CC INVAL INS COST      = " << (float)m_cost_inval_ins_frz/m_cpt_cc_inval_ins << std::endl
534        << "- NB CC CLEANUP DATA     = " << m_cpt_cc_cleanup_data << std::endl
535        << "- NB CC CLEANUP INS      = " << m_cpt_cc_cleanup_ins << std::endl
536        << "- IMISS TRANSACTION      = " << (float)m_cost_imiss_transaction/m_cpt_imiss_transaction << std::endl
537        << "- DMISS TRANSACTION      = " << (float)m_cost_dmiss_transaction/m_cpt_dmiss_transaction << std::endl
538        << "- UNC TRANSACTION        = " << (float)m_cost_unc_transaction/m_cpt_unc_transaction << std::endl
539        << "- WRITE TRANSACTION      = " << (float)m_cost_write_transaction/m_cpt_write_transaction << std::endl
540        << "- WRITE LENGTH           = " << (float)m_length_write_transaction/m_cpt_write_transaction << std::endl
541        << "- ITLB MISS TRANSACTION  = " << (float)m_cost_itlbmiss_transaction/m_cpt_itlbmiss_transaction << std::endl
542        << "- DTLB MISS TRANSACTION  = " << (float)m_cost_dtlbmiss_transaction/m_cpt_dtlbmiss_transaction << std::endl;
543}
544
545////////////////////////
546tmpl(void)::clear_stats()
547////////////////////////
548{
549    m_cpt_dcache_data_read  = 0;
550    m_cpt_dcache_data_write = 0;
551    m_cpt_dcache_dir_read   = 0;
552    m_cpt_dcache_dir_write  = 0;
553    m_cpt_icache_data_read  = 0;
554    m_cpt_icache_data_write = 0;
555    m_cpt_icache_dir_read   = 0;
556    m_cpt_icache_dir_write  = 0;
557   
558    m_cpt_frz_cycles        = 0;
559    m_cpt_dcache_frz_cycles = 0;
560    m_cpt_total_cycles      = 0;
561   
562    m_cpt_read         = 0;
563    m_cpt_write        = 0;
564    m_cpt_data_miss    = 0;
565    m_cpt_ins_miss     = 0;
566    m_cpt_unc_read     = 0;
567    m_cpt_write_cached = 0;
568    m_cpt_ins_read     = 0;
569   
570    m_cost_write_frz     = 0;
571    m_cost_data_miss_frz = 0;
572    m_cost_unc_read_frz  = 0;
573    m_cost_ins_miss_frz  = 0;
574   
575    m_cpt_imiss_transaction      = 0;
576    m_cpt_dmiss_transaction      = 0;
577    m_cpt_unc_transaction        = 0;
578    m_cpt_write_transaction      = 0;
579    m_cpt_icache_unc_transaction = 0;   
580   
581    m_cost_imiss_transaction      = 0;
582    m_cost_dmiss_transaction      = 0;
583    m_cost_unc_transaction        = 0;
584    m_cost_write_transaction      = 0;
585    m_cost_icache_unc_transaction = 0;
586    m_length_write_transaction    = 0;
587   
588    m_cpt_ins_tlb_read       = 0;             
589    m_cpt_ins_tlb_miss       = 0;             
590    m_cpt_ins_tlb_update_acc = 0;         
591   
592    m_cpt_data_tlb_read         = 0;           
593    m_cpt_data_tlb_miss         = 0;           
594    m_cpt_data_tlb_update_acc   = 0;       
595    m_cpt_data_tlb_update_dirty = 0;   
596    m_cpt_ins_tlb_hit_dcache    = 0;
597    m_cpt_data_tlb_hit_dcache   = 0;
598    m_cpt_ins_tlb_occup_cache   = 0;
599    m_cpt_data_tlb_occup_cache  = 0;
600   
601    m_cost_ins_tlb_miss_frz          = 0;     
602    m_cost_data_tlb_miss_frz         = 0;     
603    m_cost_ins_tlb_update_acc_frz    = 0;
604    m_cost_data_tlb_update_acc_frz   = 0;
605    m_cost_data_tlb_update_dirty_frz = 0;
606    m_cost_ins_tlb_occup_cache_frz   = 0;
607    m_cost_data_tlb_occup_cache_frz  = 0;
608   
609    m_cpt_itlbmiss_transaction      = 0;   
610    m_cpt_itlb_ll_transaction       = 0; 
611    m_cpt_itlb_sc_transaction       = 0; 
612    m_cpt_dtlbmiss_transaction      = 0; 
613    m_cpt_dtlb_ll_transaction       = 0; 
614    m_cpt_dtlb_sc_transaction       = 0; 
615    m_cpt_dtlb_ll_dirty_transaction = 0; 
616    m_cpt_dtlb_sc_dirty_transaction = 0; 
617   
618    m_cost_itlbmiss_transaction      = 0;   
619    m_cost_itlb_ll_transaction       = 0; 
620    m_cost_itlb_sc_transaction       = 0; 
621    m_cost_dtlbmiss_transaction      = 0;   
622    m_cost_dtlb_ll_transaction       = 0;   
623    m_cost_dtlb_sc_transaction       = 0;   
624    m_cost_dtlb_ll_dirty_transaction = 0;   
625    m_cost_dtlb_sc_dirty_transaction = 0;
626
627    m_cpt_cc_update_data = 0;
628    m_cpt_cc_inval_ins   = 0;
629    m_cpt_cc_inval_data  = 0;
630    m_cpt_cc_broadcast   = 0;
631
632    m_cost_updt_data_frz  = 0;
633    m_cost_inval_ins_frz  = 0;
634    m_cost_inval_data_frz = 0;
635    m_cost_broadcast_frz  = 0;
636
637    m_cpt_cc_cleanup_data = 0;
638    m_cpt_cc_cleanup_ins  = 0;
639}
640
641*/
642
643/////////////////////////
644tmpl(void)::transition()
645/////////////////////////
646{
647    if ( not p_resetn.read() ) 
648    {
649        r_iss.reset();
650        r_wbuf.reset();
651        r_icache.reset();
652        r_dcache.reset();
653        r_itlb.reset();   
654        r_dtlb.reset();   
655
656        r_dcache_fsm      = DCACHE_IDLE;
657        r_icache_fsm      = ICACHE_IDLE;
658        r_vci_cmd_fsm     = CMD_IDLE;
659        r_vci_rsp_fsm     = RSP_IDLE;
660        r_tgt_fsm         = TGT_IDLE;
661        r_cleanup_fsm     = CLEANUP_DATA_IDLE;
662
663        // reset dcache directory extension
664        for (size_t i=0 ; i< m_dcache_ways*m_dcache_sets ; i++)
665        {
666            r_dcache_in_tlb[i]       = false;
667            r_dcache_contains_ptd[i] = false;
668        } 
669
670        // Response FIFOs and cleanup buffer
671        r_vci_rsp_fifo_icache.init();
672        r_vci_rsp_fifo_dcache.init();
673        r_cleanup_buffer.reset();
674
675        // ICACHE & DCACHE activated
676        r_mmu_mode = 0x3;
677
678        // No request from ICACHE FSM to CMD FSM
679        r_icache_miss_req          = false;
680        r_icache_unc_req           = false;
681
682        // No request from ICACHE_FSM to DCACHE FSM
683        r_icache_tlb_miss_req      = false;     
684 
685        // No request from ICACHE_FSM to CLEANUP FSMs
686        r_icache_cleanup_req       = false;     
687       
688        // No pending write in pipeline
689        r_dcache_p0_valid          = false;
690        r_dcache_p1_valid          = false;
691
692        // No request from DCACHE_FSM to CMD_FSM
693        r_dcache_vci_miss_req      = false;
694        r_dcache_vci_unc_req       = false;
695        r_dcache_vci_sc_req        = false;
696
697        // No uncacheable write pending
698        r_dcache_pending_unc_write = false;
699
700        // No LL reservation
701        r_dcache_ll_valid          = false;
702
703        // No processor XTN request pending
704        r_dcache_xtn_req           = false;
705
706        // No request from DCACHE FSM to CLEANUP FSMs
707        r_dcache_cleanup_req      = false;
708
709        // No request from TGT FSM to ICACHE/DCACHE FSMs
710        r_tgt_icache_req          = false;
711        r_tgt_dcache_req          = false;
712
713        // No signalisation of a coherence request matching a pending miss
714        r_icache_miss_inval       = false;
715        r_dcache_miss_inval       = false;
716
717        // No signalisation  of errors
718        r_vci_rsp_ins_error       = false;
719        r_vci_rsp_data_error      = false;
720
721        // Debug variables
722        m_debug_previous_hit      = false;
723        m_debug_dcache_fsm        = false;
724        m_debug_icache_fsm        = false;
725        m_debug_cleanup_fsm       = false;
726
727        // activity counters
728        m_cpt_dcache_data_read  = 0;
729        m_cpt_dcache_data_write = 0;
730        m_cpt_dcache_dir_read   = 0;
731        m_cpt_dcache_dir_write  = 0;
732        m_cpt_icache_data_read  = 0;
733        m_cpt_icache_data_write = 0;
734        m_cpt_icache_dir_read   = 0;
735        m_cpt_icache_dir_write  = 0;
736
737        m_cpt_frz_cycles        = 0;
738        m_cpt_total_cycles      = 0;
739        m_cpt_stop_simulation   = 0;
740
741        m_cpt_data_miss         = 0;
742        m_cpt_ins_miss          = 0;
743        m_cpt_unc_read          = 0;
744        m_cpt_write_cached      = 0;
745        m_cpt_ins_read          = 0;
746
747        m_cost_write_frz        = 0;
748        m_cost_data_miss_frz    = 0;
749        m_cost_unc_read_frz     = 0;
750        m_cost_ins_miss_frz     = 0;
751
752        m_cpt_imiss_transaction = 0;
753        m_cpt_dmiss_transaction = 0;
754        m_cpt_unc_transaction   = 0;
755        m_cpt_write_transaction = 0;
756        m_cpt_icache_unc_transaction = 0;       
757
758        m_cost_imiss_transaction      = 0;
759        m_cost_dmiss_transaction      = 0;
760        m_cost_unc_transaction        = 0;
761        m_cost_write_transaction      = 0;
762        m_cost_icache_unc_transaction = 0;
763        m_length_write_transaction    = 0;
764
765        m_cpt_ins_tlb_read       = 0;             
766        m_cpt_ins_tlb_miss       = 0;             
767        m_cpt_ins_tlb_update_acc = 0;         
768
769        m_cpt_data_tlb_read         = 0;           
770        m_cpt_data_tlb_miss         = 0;           
771        m_cpt_data_tlb_update_acc   = 0;       
772        m_cpt_data_tlb_update_dirty = 0;   
773        m_cpt_ins_tlb_hit_dcache    = 0;
774        m_cpt_data_tlb_hit_dcache   = 0;
775        m_cpt_ins_tlb_occup_cache   = 0;
776        m_cpt_data_tlb_occup_cache  = 0;
777
778        m_cost_ins_tlb_miss_frz          = 0;     
779        m_cost_data_tlb_miss_frz         = 0;     
780        m_cost_ins_tlb_update_acc_frz    = 0;
781        m_cost_data_tlb_update_acc_frz   = 0;
782        m_cost_data_tlb_update_dirty_frz = 0;
783        m_cost_ins_tlb_occup_cache_frz   = 0;
784        m_cost_data_tlb_occup_cache_frz  = 0;
785
786        m_cpt_ins_tlb_inval       = 0;           
787        m_cpt_data_tlb_inval      = 0;         
788        m_cost_ins_tlb_inval_frz  = 0;     
789        m_cost_data_tlb_inval_frz = 0;         
790
791        m_cpt_cc_broadcast   = 0;
792
793        m_cost_updt_data_frz  = 0;
794        m_cost_inval_ins_frz  = 0;
795        m_cost_inval_data_frz = 0;
796        m_cost_broadcast_frz  = 0;
797
798        m_cpt_cc_cleanup_data = 0;
799        m_cpt_cc_cleanup_ins  = 0;
800
801        m_cpt_itlbmiss_transaction      = 0;   
802        m_cpt_itlb_ll_transaction       = 0; 
803        m_cpt_itlb_sc_transaction       = 0; 
804        m_cpt_dtlbmiss_transaction      = 0; 
805        m_cpt_dtlb_ll_transaction       = 0; 
806        m_cpt_dtlb_sc_transaction       = 0; 
807        m_cpt_dtlb_ll_dirty_transaction = 0; 
808        m_cpt_dtlb_sc_dirty_transaction = 0; 
809 
810        m_cost_itlbmiss_transaction      = 0;   
811        m_cost_itlb_ll_transaction       = 0; 
812        m_cost_itlb_sc_transaction       = 0; 
813        m_cost_dtlbmiss_transaction      = 0;   
814        m_cost_dtlb_ll_transaction       = 0;   
815        m_cost_dtlb_sc_transaction       = 0;   
816        m_cost_dtlb_ll_dirty_transaction = 0;   
817        m_cost_dtlb_sc_dirty_transaction = 0;   
818/*
819        m_cpt_dcache_frz_cycles = 0;
820        m_cpt_read              = 0;
821        m_cpt_write             = 0;
822        m_cpt_cc_update_data = 0;
823        m_cpt_cc_inval_ins   = 0;
824        m_cpt_cc_inval_data  = 0;
825  */
826
827        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_icache      [i]   = 0;
828        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_dcache      [i]   = 0;
829        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_cmd         [i]   = 0;
830        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_rsp         [i]   = 0;
831        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_tgt         [i]   = 0;
832        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_cmd_cleanup [i]   = 0;
833        for (uint32_t i=0; i<32 ; ++i) m_cpt_fsm_rsp_cleanup [i]   = 0;
834
835        return;
836    }
837
838    // Response FIFOs default values
839    bool       vci_rsp_fifo_icache_get       = false;
840    bool       vci_rsp_fifo_icache_put       = false;
841    uint32_t   vci_rsp_fifo_icache_data      = 0;
842
843    bool       vci_rsp_fifo_dcache_get       = false;
844    bool       vci_rsp_fifo_dcache_put       = false;
845    uint32_t   vci_rsp_fifo_dcache_data      = 0;
846
847#ifdef INSTRUMENTATION
848    m_cpt_fsm_dcache  [r_dcache_fsm.read() ] ++;
849    m_cpt_fsm_icache  [r_icache_fsm.read() ] ++;
850    m_cpt_fsm_cmd     [r_vci_cmd_fsm.read()] ++;
851    m_cpt_fsm_rsp     [r_vci_rsp_fsm.read()] ++;
852    m_cpt_fsm_tgt     [r_tgt_fsm.read()    ] ++;
853    m_cpt_fsm_cleanup [r_cleanup_fsm.read()] ++;
854#endif
855
856    m_cpt_total_cycles++;
857
858    m_debug_cleanup_fsm    = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
859    m_debug_icache_fsm     = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
860    m_debug_dcache_fsm     = (m_cpt_total_cycles > m_debug_start_cycle) and m_debug_ok;
861
862    /////////////////////////////////////////////////////////////////////
863    // The TGT_FSM controls the following ressources:
864    // - r_tgt_fsm
865    // - r_tgt_buf[nwords]
866    // - r_tgt_be[nwords]
867    // - r_tgt_update
868    // - r_tgt_word_min
869    // - r_tgt_word_max
870    // - r_tgt_word_count
871    // - r_tgt_paddr
872    // - r_tgt_srcid
873    // - r_tgt_trdid
874    // - r_tgt_pktid
875    // - r_tgt_icache_req (set)
876    // - r_tgt_dcache_req (set)
877    //
878    // All VCI commands must be CMD_WRITE.
879    // - If the 2 LSB bits of the VCI address are 11, it is a broadcast request.
880    //   It is a multicast request otherwise.
881    // - For multicast requests, the ADDRESS[2] bit distinguishes DATA/INS
882    //   (0 for data / 1 for instruction), and the ADDRESS[3] bit distinguishes
883    //   INVAL/UPDATE (0 for invalidate / 1 for UPDATE).
884    //
885    // For all types of coherence request, the line index (i.e. the Z & Y fields)
886    // is coded on 34 bits, and is contained in the WDATA and BE fields
887    // of the first VCI flit.
888    // -  for a multicast invalidate or for a broadcast invalidate request
889    //    the VCI packet length is 1 word.
890    // -  for an update request the VCI packet length is (n+2) words.
891    //    The WDATA field of the second VCI word contains the word index.
892    //    The WDATA field of the n following words contains the values.
893    // -  for all transaction types, the VCI response is one single word.
894    // In case of errors in the VCI command packet, the simulation
895    // is stopped with an error message.
896    //
897    // This FSM is NOT pipelined : It consumes a new coherence request
898    // on the VCI port only when the previous request is completed.
899    //
900    // The VCI_TGT FSM stores the external request arguments in the
901    // IDLE, UPDT_WORD & UPDT_DATA states. It sets the r_tgt_icache_req
902    // and/or the r_tgt_dcache_req flip-flops to signal the coherence request
903    // to the ICACHE & DCACHE FSMs in the REQ_ICACHE, REQ_DCACHE & REQ_BROADCAST
904    // states. It waits the completion of the coherence request  by polling the
905    // r_tgt_*cache_req flip-flops in the RSP_ICACHE, RSP_DCACHE & RSP_BROADCAST
906    // states. These flip-flops are reset by the ICACHE and DCACHE FSMs.
907    // These two FSMs signal if a VCI answer must be send by setting
908    // the r_tgt_icache_rsp and/or the r_tgt_dcache_rsp flip_flops.
909    ///////////////////////////////////////////////////////////////////////////////
910
911    switch( r_tgt_fsm.read() ) 
912    {
913    //////////////
914    case TGT_IDLE:
915    {
916        if ( p_vci_tgt_c.cmdval.read() ) 
917        {
918            paddr_t address = p_vci_tgt_c.address.read();
919
920            // command checking
921            if ( p_vci_tgt_c.cmd.read() != vci_param::CMD_WRITE) 
922            {
923                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
924                std::cout << "the received VCI coherence command is not a write" << std::endl;
925                exit(0);
926            }
927
928            // address checking
929            if ( ( (address & 0x3) != 0x3 ) && ( not m_segment.contains(address)) ) 
930            {
931                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
932                std::cout << "out of segment VCI coherence command received" << std::endl;
933                exit(0);
934            }
935
936            r_tgt_srcid = p_vci_tgt_c.srcid.read();
937            r_tgt_trdid = p_vci_tgt_c.trdid.read();
938            r_tgt_pktid = p_vci_tgt_c.pktid.read();
939
940            r_tgt_paddr  = (paddr_t)(p_vci_tgt_c.be.read() & 0x3) << 32 |
941                          (paddr_t)p_vci_tgt_c.wdata.read() * m_dcache_words * 4; 
942
943            if ( (address&0x3) == 0x3 ) // broadcast invalidate for data or instruction type
944            {
945                if ( not p_vci_tgt_c.eop.read() ) 
946                {
947                    std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
948                    std::cout << "the BROADCAST INVALIDATE command must be one flit" << std::endl;
949                    exit(0);
950                }
951                r_tgt_update = false; 
952                r_tgt_fsm = TGT_REQ_BROADCAST;
953
954#ifdef INSTRUMENTATION
955m_cpt_cc_broadcast++;
956#endif
957            }
958            else                // multi-update or multi-invalidate for data type
959            {
960                paddr_t cell = address - m_segment.baseAddress();   
961
962                if (cell == 0)                      // invalidate data
963                {                         
964                    if ( not p_vci_tgt_c.eop.read() ) 
965                    {
966                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
967                        std::cout << "the MULTI-INVALIDATE command must be one flit" << std::endl;
968                        exit(0);
969                    }
970                    r_tgt_update = false; 
971                    r_tgt_fsm    = TGT_REQ_DCACHE;
972
973#ifdef INSTRUMENTATION
974m_cpt_cc_inval_dcache++;
975#endif
976                }
977                else if (cell == 4)                // invalidate instruction
978                {                               
979                    if ( not p_vci_tgt_c.eop.read() ) 
980                    {
981                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
982                        std::cout << "the MULTI-INVALIDATE command must be one flit" << std::endl;
983                        exit(0);
984                    }
985                    r_tgt_update = false; 
986                    r_tgt_fsm    = TGT_REQ_ICACHE;
987
988#ifdef INSTRUMENTATION
989m_cpt_cc_inval_icache++;
990#endif
991                }     
992                else if (cell == 8)             // update data
993                {
994                    if ( p_vci_tgt_c.eop.read() ) 
995                    {
996                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
997                        std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
998                        exit(0);
999                    }
1000                    r_tgt_update      = true; 
1001                    r_tgt_update_data = true;
1002                    r_tgt_fsm         = TGT_UPDT_WORD;
1003
1004#ifdef INSTRUMENTATION
1005m_cpt_cc_update_dcache++;
1006#endif
1007                }
1008                else                            // update instruction
1009                {
1010                    if ( p_vci_tgt_c.eop.read() ) 
1011                    {
1012                        std::cout << "error in VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
1013                        std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
1014                        exit(0);
1015                    }
1016                    r_tgt_update      = true; 
1017                    r_tgt_update_data = false;
1018                    r_tgt_fsm         = TGT_UPDT_WORD;
1019
1020#ifdef INSTRUMENTATION
1021m_cpt_cc_update_icache++;
1022#endif
1023                }
1024            } // end if multi     
1025        } // end if cmdval
1026        break;
1027    }
1028    ///////////////////
1029    case TGT_UPDT_WORD:         // first word index acquisition
1030    {
1031        if (p_vci_tgt_c.cmdval.read()) 
1032        {
1033            if ( p_vci_tgt_c.eop.read() ) 
1034            {
1035                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
1036                std::cout << "the MULTI-UPDATE command must be N+2 flits" << std::endl;
1037                exit(0);
1038            }
1039            for ( size_t i=0 ; i<m_dcache_words ; i++ ) r_tgt_be[i] = false;
1040
1041            r_tgt_word_min   = p_vci_tgt_c.wdata.read(); // first modifid word index
1042            r_tgt_word_count = p_vci_tgt_c.wdata.read(); // initializing word index
1043            r_tgt_fsm = TGT_UPDT_DATA;
1044        }
1045        break;
1046    }
1047    ///////////////////
1048    case TGT_UPDT_DATA:
1049    {
1050        if (p_vci_tgt_c.cmdval.read()) 
1051        {
1052            size_t word = r_tgt_word_count.read();
1053            if (word >= m_dcache_words) 
1054            {
1055                std::cout << "error in component VCI_CC_VCACHE_WRAPPER " << name() << std::endl;
1056                std::cout << "the reveived MULTI-UPDATE command is wrong" << std::endl;
1057                exit(0);
1058            }
1059            r_tgt_buf[word]  = p_vci_tgt_c.wdata.read();
1060            r_tgt_be[word]   = p_vci_tgt_c.be.read();
1061            r_tgt_word_count = word + 1;       
1062
1063            if (p_vci_tgt_c.eop.read())         // last word
1064            {
1065                 r_tgt_word_max = word;
1066                 if ( r_tgt_update_data.read() )        r_tgt_fsm = TGT_REQ_DCACHE;
1067                 else                                   r_tgt_fsm = TGT_REQ_ICACHE;
1068            }
1069        }
1070        break;
1071    }
1072    ///////////////////////
1073    case TGT_REQ_BROADCAST:     // set requests to DCACHE & ICACHE FSMs
1074    {
1075        if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) 
1076        {
1077            r_tgt_fsm = TGT_RSP_BROADCAST; 
1078            r_tgt_icache_req = true;
1079            r_tgt_dcache_req = true;
1080        }
1081        break;
1082    }
1083    /////////////////////
1084    case TGT_REQ_ICACHE:        // set request to ICACHE FSM (if no previous request pending)
1085    {
1086        if ( not r_tgt_icache_req.read() ) 
1087        {
1088            r_tgt_fsm = TGT_RSP_ICACHE; 
1089            r_tgt_icache_req = true;
1090        }
1091        break;
1092    }
1093    ////////////////////
1094    case TGT_REQ_DCACHE:        // set request to DCACHE FSM (if no previous request pending)
1095    {
1096        if ( not r_tgt_dcache_req.read() ) 
1097        {
1098            r_tgt_fsm = TGT_RSP_DCACHE; 
1099            r_tgt_dcache_req = true;
1100        }
1101        break;
1102    }
1103    ///////////////////////
1104    case TGT_RSP_BROADCAST:     // waiting acknowledge from both DCACHE & ICACHE FSMs
1105                                // no response when r_tgt_*cache_rsp is false
1106    {
1107        if ( not r_tgt_icache_req.read() and not r_tgt_dcache_req.read() ) // both completed
1108        {
1109            if ( r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read() )   // at least one response
1110            {
1111                if ( p_vci_tgt_c.rspack.read() )
1112                {
1113                    // reset dcache first if activated
1114                    if (r_tgt_dcache_rsp)   r_tgt_dcache_rsp = false;
1115                    else                    r_tgt_icache_rsp = false;
1116                }
1117            }
1118            else
1119            {
1120                r_tgt_fsm = TGT_IDLE;
1121            }
1122        }
1123        break;
1124    }
1125    ////////////////////
1126    case TGT_RSP_ICACHE:        // waiting acknowledge from ICACHE FSM
1127    {
1128        // no response when r_tgt_icache_rsp is false
1129        if ( not r_tgt_icache_req.read() and p_vci_tgt_c.rspack.read() )
1130        {
1131            r_tgt_fsm        = TGT_IDLE;
1132            r_tgt_icache_rsp = false;
1133        }
1134        break;
1135    }
1136    ////////////////////
1137    case TGT_RSP_DCACHE:
1138    {
1139        // no response when r_tgt_dcache_rsp is false
1140        if ( not r_tgt_dcache_req.read() and p_vci_tgt_c.rspack.read() )
1141        {
1142            r_tgt_fsm        = TGT_IDLE;
1143            r_tgt_dcache_rsp = false;
1144        }
1145        break;
1146    }
1147    } // end switch TGT_FSM
1148
1149    /////////////////////////////////////////////////////////////////////
1150    // Get data and instruction requests from processor
1151    ///////////////////////////////////////////////////////////////////////
1152
1153    r_iss.getRequests(m_ireq, m_dreq);
1154
1155    ////////////////////////////////////////////////////////////////////////////////////
1156    //      ICACHE_FSM
1157    //
1158    // There is 9 conditions to exit the IDLE state:
1159    // One condition is a coherence request from TGT FSM :
1160    // - Coherence operation                            => ICACHE_CC_CHEK
1161    // Five configurations corresponding to XTN processor requests sent by DCACHE FSM :
1162    // - Flush TLB                                      => ICACHE_XTN_TLB_FLUSH
1163    // - Flush cache                                    => ICACHE_XTN_CACHE_FLUSH
1164    // - Invalidate a TLB entry                         => ICACHE_XTN_TLB_INVAL
1165    // - Invalidate a cache line                        => ICACHE_XTN_CACHE_INVAL_VA@
1166    // - Invalidate a cache line using physical address => ICACHE_XTN_CACHE_INVAL_PA
1167    // three configurations corresponding to instruction processor requests :
1168    // - tlb miss                                       => ICACHE_TLB_WAIT
1169    // - cacheable read miss                            => ICACHE_MISS_VICTIM
1170    // - uncacheable read miss                          => ICACHE_UNC_REQ
1171    //
1172    // In case of cache miss, the ICACHE FSM request a VCI transaction to CMD FSM
1173    // using the r_icache_tlb_miss_req flip-flop, that reset this flip-flop when the
1174    // transaction starts. Then the ICACHE FSM  goes to the ICACHE_MISS VICTIM
1175    // state to select a slot and request a VCI transaction to the CLEANUP FSM.
1176    // It goes next to the ICACHE_MISS_WAIT state waiting a response from RSP FSM.
1177    // The availability of the missing cache line is signaled by the response fifo,
1178    // and the cache update is done (one word per cycle) in the ICACHE_MISS_UPDT state.
1179    //
1180    // In case of uncacheable address, the ICACHE FSM request an uncached VCI transaction
1181    // to CMD FSM using the r_icache_unc_req flip-flop, that reset this flip-flop
1182    // when the transaction starts. The ICACHE FSM goes to ICACHE_UNC_WAIT to wait
1183    // the response from the RSP FSM, through the response fifo. The missing instruction
1184    // is directly returned to processor in this state.
1185    //
1186    // In case of tlb miss, the ICACHE FSM request to the DCACHE FSM to update the tlb
1187    // using the r_icache_tlb_miss_req flip-flop and the r_icache_tlb_miss_vaddr register,
1188    // and goes to the ICACHE_TLB_WAIT state.
1189    // The tlb update is entirely done by the DCACHE FSM (who becomes the owner of dtlb until
1190    // the update is completed, and reset r_icache_tlb_miss_req to signal the completion.
1191    //
1192    // The DCACHE FSM signals XTN processor requests to ICACHE_FSM
1193    // using the r_dcache_xtn_req flip-flop.
1194    // The request opcode and the address to be invalidated are transmitted
1195    // in the r_dcache_xtn_opcode and r_dcache_p0_wdata registers respectively.
1196    // The r_dcache_xtn_req flip-flop is reset by the ICACHE_FSM when the operation
1197    // is completed.
1198    //
1199    // The r_vci_rsp_ins_error flip-flop is set by the RSP FSM in case of bus error
1200    // in a cache miss or uncacheable read VCI transaction. Nothing is written
1201    // in the response fifo. This flip-flop is reset by the ICACHE-FSM.
1202    ////////////////////////////////////////////////////////////////////////////////////////
1203
1204    // default value for m_irsp
1205    m_irsp.valid       = false;
1206    m_irsp.error       = false;
1207    m_irsp.instruction = 0;
1208
1209    switch( r_icache_fsm.read() ) 
1210    {
1211    /////////////////
1212    case ICACHE_IDLE:   // In this state, we handle processor requests, XTN requests sent
1213                        // by DCACHE FSM, and coherence requests with a fixed priority:
1214                        //         coherence > XTN > instruction
1215                        // We access the itlb and dcache in parallel with the virtual address
1216                        // for itlb, and with a speculative physical address for icache,
1217                        // computed during the previous cycle.
1218    {
1219        // coherence request from the target FSM
1220        if ( r_tgt_icache_req.read() )
1221        {
1222            r_icache_fsm = ICACHE_CC_CHECK;
1223            r_icache_fsm_save = r_icache_fsm.read();
1224            break;
1225        }
1226
1227        // Decoding processor XTN requests sent by DCACHE FSM 
1228        // These request are not executed in this IDLE state, because
1229        // they require access to icache or itlb, that are already accessed
1230        if ( r_dcache_xtn_req.read() )
1231        {
1232            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_PTPR ) 
1233            {
1234                r_icache_fsm         = ICACHE_XTN_TLB_FLUSH;   
1235                break;
1236            }
1237            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ICACHE_FLUSH)
1238            {
1239                r_icache_flush_count = 0;
1240                r_icache_fsm         = ICACHE_XTN_CACHE_FLUSH;   
1241                break;
1242            }
1243            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ITLB_INVAL) 
1244            {
1245                r_icache_fsm         = ICACHE_XTN_TLB_INVAL;   
1246                break;
1247            }
1248            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_ICACHE_INVAL) 
1249            {
1250                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_VA;   
1251                break;
1252            }
1253            if ( (int)r_dcache_xtn_opcode.read() == (int)iss_t::XTN_MMU_ICACHE_PA_INV) 
1254            {
1255                r_icache_vci_paddr   = (paddr_t)r_mmu_word_hi.read() << 32 | 
1256                                       (paddr_t)r_mmu_word_lo.read();
1257                r_icache_fsm         = ICACHE_XTN_CACHE_INVAL_PA;   
1258                break;
1259            }
1260        } // end if xtn_req
1261
1262        // processor request
1263        if ( m_ireq.valid )
1264        {
1265            bool        cacheable;
1266            paddr_t     paddr;
1267
1268            // We register processor request
1269            r_icache_vaddr_save = m_ireq.addr;
1270
1271            // speculative icache access (if cache activated)
1272            // we use the speculative PPN computed during the previous cycle
1273           
1274            uint32_t    cache_inst = 0;
1275            bool        cache_hit  = false;
1276
1277            if ( r_mmu_mode.read() & INS_CACHE_MASK )
1278            {
1279                paddr_t   spc_paddr = (r_icache_vci_paddr.read() & ~PAGE_K_MASK) |
1280                                      ((paddr_t)m_ireq.addr & PAGE_K_MASK);
1281
1282#ifdef INSTRUMENTATION
1283m_cpt_icache_data_read++;
1284m_cpt_icache_dir_read++;
1285#endif
1286                cache_hit = r_icache.read( spc_paddr,
1287                                           &cache_inst );
1288            }
1289
1290            // systematic itlb access (if tlb activated)
1291            // we use the virtual address
1292
1293            paddr_t     tlb_paddr;
1294            pte_info_t  tlb_flags; 
1295            size_t      tlb_way; 
1296            size_t      tlb_set;
1297            paddr_t     tlb_nline;
1298            bool        tlb_hit   = false;; 
1299
1300            if ( r_mmu_mode.read() & INS_TLB_MASK )
1301            {
1302
1303#ifdef INSTRUMENTATION
1304m_cpt_itlb_read++;
1305#endif
1306                tlb_hit = r_itlb.translate( m_ireq.addr,
1307                                            &tlb_paddr,
1308                                            &tlb_flags,
1309                                            &tlb_nline, // unused
1310                                            &tlb_way,   // unused
1311                                            &tlb_set ); // unused
1312            }
1313
1314            // We compute cacheability, physical address and check access rights:
1315            // - If MMU activated : cacheability is defined by the C bit in the PTE,
1316            //   the physical address is obtained from the TLB, and the access rights are
1317            //   defined by the U and X bits in the PTE.
1318            // - If MMU not activated : cacheability is defined by the segment table,
1319            //   the physical address is equal to the virtual address (identity mapping)
1320            //   and there is no access rights checking
1321
1322            if ( not (r_mmu_mode.read() & INS_TLB_MASK) )       // tlb not activated:
1323            {
1324                // cacheability
1325                if ( not (r_mmu_mode.read() & INS_CACHE_MASK) ) cacheable = false;
1326                else     cacheable = m_cacheability_table[m_ireq.addr];
1327
1328                // physical address
1329                paddr = (paddr_t)m_ireq.addr;
1330            }
1331            else                                                // itlb activated
1332            {
1333                if ( tlb_hit )  // tlb hit
1334                { 
1335                    // cacheability
1336                    if ( not (r_mmu_mode.read() & INS_CACHE_MASK) ) cacheable = false;
1337                    else  cacheable = tlb_flags.c;
1338
1339                    // physical address
1340                    paddr       = tlb_paddr;
1341
1342                    // access rights checking
1343                    if ( not tlb_flags.u && (m_ireq.mode == iss_t::MODE_USER) )
1344                    {
1345                        r_mmu_ietr        = MMU_READ_PRIVILEGE_VIOLATION;
1346                        r_mmu_ibvar       = m_ireq.addr;
1347                        m_irsp.valid        = true;
1348                        m_irsp.error        = true;
1349                        m_irsp.instruction  = 0;
1350                        break;
1351                    }
1352                    else if ( not tlb_flags.x )
1353                    {
1354                        r_mmu_ietr        = MMU_READ_EXEC_VIOLATION;
1355                        r_mmu_ibvar       = m_ireq.addr;
1356                        m_irsp.valid        = true;
1357                        m_irsp.error        = true;
1358                        m_irsp.instruction  = 0;
1359                        break;
1360                    }
1361                }
1362                // in case of TLB miss we send an itlb miss request to DCACHE FSM and break
1363                else
1364                {
1365
1366#ifdef INSTRUMENTATION
1367m_cpt_itlb_miss++;
1368#endif
1369                    r_icache_fsm          = ICACHE_TLB_WAIT;
1370                    r_icache_tlb_miss_req = true;
1371                    break;
1372                } 
1373            } // end if itlb activated
1374
1375            // physical address registration (for next cycle)
1376            r_icache_vci_paddr   = paddr;
1377
1378            // We enter this section only in case of TLB hit:
1379            // Finally, we get the instruction depending on cacheability,
1380            // we send the response to processor, and compute next state
1381            if ( cacheable )    // cacheable read
1382            {
1383                if ( (r_icache_vci_paddr.read() & ~PAGE_K_MASK) 
1384                      != (paddr & ~PAGE_K_MASK) )       // speculative access KO
1385                {
1386
1387#ifdef INSTRUMENTATION
1388m_cpt_icache_spc_miss++;
1389#endif
1390                    // we return an invalid response and stay in IDLE state
1391                    // the cache access will cost one extra cycle.
1392                    break;
1393                }
1394               
1395                if ( not cache_hit )    // cache miss
1396                {
1397                    // in case of icache miss we send a request to CMD FSM, but we are
1398                    // blocked in IDLE state if the previous cleanup is not completed
1399                    if ( not r_icache_cleanup_req.read() )
1400                    {
1401
1402#ifdef INSTRUMENTATION
1403m_cpt_icache_miss++;
1404#endif
1405                        r_icache_fsm      = ICACHE_MISS_VICTIM;
1406                        r_icache_miss_req = true;
1407                    }
1408                    break;
1409                }
1410                else                    // cache hit
1411                {
1412     
1413#ifdef INSTRUMENTATION
1414m_cpt_ins_read++; 
1415#endif
1416                    m_irsp.valid       = true;
1417                    m_irsp.instruction = cache_inst;
1418                }
1419            }
1420            else                // non cacheable read
1421            {
1422                r_icache_unc_req  = true;
1423                r_icache_fsm      = ICACHE_UNC_WAIT;
1424            }
1425        }    // end if m_ireq.valid
1426        break;
1427    }
1428    /////////////////////
1429    case ICACHE_TLB_WAIT:       // Waiting the itlb update by the DCACHE FSM after a tlb miss
1430                                // the itlb is udated by the DCACHE FSM, as well as the
1431                                // r_mmu_ietr and r_mmu_ibvar registers in case of error.
1432                                // the itlb is not accessed by ICACHE FSM until DCACHE FSM
1433                                // reset the r_icache_tlb_miss_req flip-flop
1434                                // external coherence request are accepted in this state.
1435    {
1436        // external coherence request
1437        if ( r_tgt_icache_req.read() )
1438        {
1439            r_icache_fsm = ICACHE_CC_CHECK;
1440            r_icache_fsm_save = r_icache_fsm.read();
1441            break;
1442        }
1443
1444        if ( m_ireq.valid ) m_cost_ins_tlb_miss_frz++;
1445
1446        // DCACHE FSM signals response by reseting the request flip-flop
1447        if ( not r_icache_tlb_miss_req.read() )
1448        {
1449            if ( r_icache_tlb_rsp_error.read() ) // error reported : tlb not updated
1450            {
1451                r_icache_tlb_rsp_error = false;
1452                m_irsp.error             = true;
1453                m_irsp.valid             = true;
1454                r_icache_fsm           = ICACHE_IDLE;
1455            }
1456            else                                // tlb updated : return to IDLE state
1457            {
1458                r_icache_fsm  = ICACHE_IDLE;
1459            }
1460        }
1461        break;
1462    }
1463    //////////////////////////
1464    case ICACHE_XTN_TLB_FLUSH:          // invalidate in one cycle all non global TLB entries
1465    {   
1466        r_itlb.flush();   
1467        r_dcache_xtn_req     = false;
1468        r_icache_fsm         = ICACHE_IDLE;
1469        break;
1470    }
1471    ////////////////////////////
1472    case ICACHE_XTN_CACHE_FLUSH:        // Invalidate sequencially all cache lines using
1473                                        // the r_icache_flush_count register as a slot counter.
1474                                        // We loop in this state until all slots have been visited.
1475                                        // A cleanup request is generated for each valid line
1476                                        // and we are blocked until the previous cleanup is completed
1477    {
1478        if ( not r_icache_cleanup_req.read() )
1479        {
1480            size_t      way = r_icache_flush_count.read()/m_icache_sets;
1481            size_t      set = r_icache_flush_count.read()%m_icache_sets;
1482            paddr_t     nline;
1483            bool        cleanup_req = r_icache.inval( way, 
1484                                                      set, 
1485                                                      &nline );
1486            if ( cleanup_req )
1487            {
1488                r_icache_cleanup_req  = true;
1489                r_icache_cleanup_line = nline;
1490            }
1491            r_icache_flush_count = r_icache_flush_count.read() + 1;
1492        }
1493       
1494        if ( r_icache_flush_count.read() == (m_icache_sets*m_icache_ways - 1) )
1495        {
1496            r_dcache_xtn_req    = false;
1497            r_icache_fsm        = ICACHE_IDLE;
1498        }
1499        break;
1500    }
1501    //////////////////////////
1502    case ICACHE_XTN_TLB_INVAL:          // invalidate one TLB entry selected by the virtual address
1503                                        // stored in the r_dcache_p0_wdata register
1504    {
1505        r_itlb.inval(r_dcache_p0_wdata.read());
1506        r_dcache_xtn_req     = false;
1507        r_icache_fsm         = ICACHE_IDLE;
1508        break;
1509    }
1510    ///////////////////////////////
1511    case ICACHE_XTN_CACHE_INVAL_VA:     // Selective cache line invalidate with virtual address
1512                                        // requires 3 cycles (in case of hit on itlb and icache).
1513                                        // In this state, we access TLB to translate virtual address
1514                                        // stored in the r_dcache_p0_wdata register.
1515    {
1516        paddr_t         paddr;                     
1517        bool            hit;
1518
1519        // read physical address in TLB when MMU activated
1520        if ( r_mmu_mode.read() & INS_TLB_MASK )         // itlb activated
1521        {
1522
1523#ifdef INSTRUMENTATION
1524m_cpt_itlb_read++;
1525#endif
1526            hit = r_itlb.translate(r_dcache_p0_wdata.read(), 
1527                                   &paddr); 
1528        } 
1529        else                                            // itlb not activated
1530        {
1531            paddr       = (paddr_t)r_dcache_p0_wdata.read();
1532            hit         = true;
1533        }
1534
1535        if ( hit )              // continue the selective inval process
1536        {
1537            r_icache_vci_paddr    = paddr;               
1538            r_icache_fsm          = ICACHE_XTN_CACHE_INVAL_PA;
1539        }
1540        else                    // miss : send a request to DCACHE FSM
1541        {
1542
1543#ifdef INSTRUMENTATION
1544m_cpt_itlb_miss++;
1545#endif
1546            r_icache_tlb_miss_req = true;
1547            r_icache_fsm          = ICACHE_TLB_WAIT;
1548        }
1549        break;
1550    }
1551    ///////////////////////////////
1552    case ICACHE_XTN_CACHE_INVAL_PA:     // selective invalidate cache line with physical address
1553                                        // require 2 cycles. In this state, we read dcache,
1554                                        // with address stored in r_icache_vci_paddr register.
1555    {
1556        uint32_t        data;
1557        size_t          way;
1558        size_t          set;
1559        size_t          word;
1560        bool            hit = r_icache.read(r_icache_vci_paddr.read(),
1561                                            &data,
1562                                            &way,
1563                                            &set,
1564                                            &word);
1565        if ( hit )      // inval to be done
1566        {
1567                r_icache_miss_way = way;
1568                r_icache_miss_set = set;
1569                r_icache_fsm      = ICACHE_XTN_CACHE_INVAL_GO;
1570        }
1571        else            // miss : acknowlege the XTN request and return
1572        {
1573            r_dcache_xtn_req = false; 
1574            r_icache_fsm     = ICACHE_IDLE;
1575        }
1576        break;
1577    }
1578    ///////////////////////////////
1579    case ICACHE_XTN_CACHE_INVAL_GO:     // In this state, we invalidate the cache line & cleanup.
1580                                        // We are blocked if the previous cleanup is not completed
1581    {
1582        paddr_t nline;
1583
1584        if ( not r_icache_cleanup_req.read() )
1585        {
1586            r_icache.inval( r_icache_miss_way.read(),
1587                            r_icache_miss_set.read(),
1588                            &nline );
1589 
1590            // request cleanup
1591            r_icache_cleanup_req  = true;
1592            r_icache_cleanup_line = nline;
1593            // acknowledge the XTN request and return
1594            r_dcache_xtn_req      = false; 
1595            r_icache_fsm          = ICACHE_IDLE;
1596        }
1597        break;
1598    }
1599
1600    ////////////////////////
1601    case ICACHE_MISS_VICTIM:               // Selects a victim line
1602                                           // Set the r_icache_cleanup_req flip-flop
1603                                           // when the selected slot is not empty
1604    {
1605        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1606
1607        bool    valid;
1608        size_t  way;
1609        size_t  set;
1610        paddr_t victim;
1611
1612        valid = r_icache.victim_select(r_icache_vci_paddr.read(),
1613                                       &victim, 
1614                                       &way, 
1615                                       &set);
1616        r_icache_miss_way     = way;
1617        r_icache_miss_set     = set;
1618
1619        if ( valid )
1620        {
1621            r_icache_cleanup_req  = true;
1622            r_icache_cleanup_line = victim;
1623            r_icache_fsm          = ICACHE_MISS_INVAL;
1624        }
1625        else
1626        {
1627            r_icache_fsm          = ICACHE_MISS_WAIT;
1628        }
1629        break;
1630    }
1631    ///////////////////////
1632    case ICACHE_MISS_INVAL:     // invalidate the victim line
1633    {
1634        paddr_t nline;
1635
1636        r_icache.inval( r_icache_miss_way.read(),
1637                        r_icache_miss_set.read(),
1638                        &nline );       // unused
1639
1640        r_icache_fsm = ICACHE_MISS_WAIT;
1641        break;
1642    }
1643    //////////////////////
1644    case ICACHE_MISS_WAIT:      // waiting a response to a miss request from VCI_RSP FSM
1645    {
1646        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1647
1648        // external coherence request
1649        if ( r_tgt_icache_req.read() )     
1650        {
1651            r_icache_fsm = ICACHE_CC_CHECK;
1652            r_icache_fsm_save = r_icache_fsm.read();
1653            break;
1654        }
1655
1656        if ( r_vci_rsp_ins_error.read() ) // bus error
1657        {
1658            r_mmu_ietr = MMU_READ_DATA_ILLEGAL_ACCESS; 
1659            r_mmu_ibvar  = r_icache_vaddr_save.read();
1660            m_irsp.valid           = true;
1661            m_irsp.error           = true;
1662            r_vci_rsp_ins_error  = false;
1663            r_icache_fsm = ICACHE_IDLE;
1664        }
1665        else if ( r_vci_rsp_fifo_icache.rok() ) // response available
1666        {
1667            r_icache_miss_word = 0;
1668            r_icache_fsm       = ICACHE_MISS_UPDT; 
1669        }       
1670        break;
1671    }
1672    //////////////////////
1673    case ICACHE_MISS_UPDT:      // update the cache (one word per cycle)
1674    {
1675        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1676
1677        if ( r_vci_rsp_fifo_icache.rok() )      // response available
1678        {
1679            if ( r_icache_miss_inval )  // Matching coherence request
1680                                        // We pop the response FIFO, without updating the cache
1681                                        // We send a cleanup for the missing line at the last word
1682                                        // Blocked if the previous cleanup is not completed
1683            {
1684                if ( r_icache_miss_word.read() < m_icache_words-1 )     // not the last word
1685                {
1686                    vci_rsp_fifo_icache_get = true;
1687                    r_icache_miss_word = r_icache_miss_word.read() + 1;
1688                }
1689                else                                                    // last word
1690                {
1691                    if ( not r_icache_cleanup_req.read() )      // no pending cleanup
1692                    {
1693                        vci_rsp_fifo_icache_get = true;
1694                        r_icache_cleanup_req    = true;
1695                        r_icache_cleanup_line   = r_icache_vci_paddr.read() >> (uint32_log2(m_icache_words<<2));
1696                        r_icache_miss_inval     = false;
1697                        r_icache_fsm            = ICACHE_IDLE;
1698                    }
1699                }
1700            }
1701            else                        // No matching coherence request
1702                                        // We pop the FIFO and update the cache
1703                                        // We update the directory at the last word
1704            {
1705
1706#ifdef INSTRUMENTATION
1707m_cpt_icache_data_write++;
1708#endif
1709                r_icache.write( r_icache_miss_way.read(),
1710                                r_icache_miss_set.read(),
1711                                r_icache_miss_word.read(),
1712                                r_vci_rsp_fifo_icache.read() );
1713                vci_rsp_fifo_icache_get = true;
1714                r_icache_miss_word = r_icache_miss_word.read() + 1;
1715                if ( r_icache_miss_word.read() == m_icache_words-1 )  // last word
1716                {
1717
1718#ifdef INSTRUMENTATION
1719m_cpt_icache_dir_write++;
1720#endif
1721                    r_icache.victim_update_tag( r_icache_vci_paddr.read(),
1722                                                r_icache_miss_way.read(),
1723                                                r_icache_miss_set.read() );
1724                    r_icache_fsm = ICACHE_IDLE;
1725                }
1726            }
1727        }
1728        break;
1729    }
1730    ////////////////////
1731    case ICACHE_UNC_WAIT:       // waiting a response to an uncacheable read from VCI_RSP FSM
1732                                //
1733    {
1734        // external coherence request
1735        if ( r_tgt_icache_req.read() ) 
1736        {
1737            r_icache_fsm = ICACHE_CC_CHECK;
1738            r_icache_fsm_save = r_icache_fsm.read();
1739            break;
1740        }
1741
1742        if ( r_vci_rsp_ins_error.read() ) // bus error
1743        {
1744            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS;   
1745            r_mmu_ibvar         = m_ireq.addr;
1746            r_vci_rsp_ins_error = false;
1747            m_irsp.valid          = true;
1748            m_irsp.error          = true;
1749            r_icache_fsm        = ICACHE_IDLE;
1750        }
1751        else if (r_vci_rsp_fifo_icache.rok() ) // instruction available
1752        {
1753            vci_rsp_fifo_icache_get = true;
1754            r_icache_fsm            = ICACHE_IDLE;
1755            if ( m_ireq.valid and (m_ireq.addr == r_icache_vaddr_save.read()) )  // request not modified
1756            {
1757                m_irsp.valid       = true;
1758                m_irsp.instruction = r_vci_rsp_fifo_icache.read();
1759            }
1760        }       
1761        break;
1762    }
1763    /////////////////////
1764    case ICACHE_CC_CHECK:       // This state is the entry point of a sub-fsm
1765                                // handling coherence requests.
1766                                // the return state is defined in r_icache_fsm_save.
1767    {
1768        paddr_t  paddr = r_tgt_paddr.read();
1769        paddr_t  mask  = ~((m_icache_words<<2)-1);
1770
1771        if( (r_icache_fsm_save.read() == ICACHE_MISS_WAIT) and
1772                ((r_icache_vci_paddr.read() & mask) == (paddr & mask)))         // matching a pending miss
1773        {
1774            r_icache_miss_inval = true;                         // signaling the matching
1775            r_tgt_icache_req    = false;                        // coherence request completed
1776            r_tgt_icache_rsp    = r_tgt_update.read();          // response required if update
1777            r_icache_fsm        = r_icache_fsm_save.read();
1778        }
1779        else                                                            // no match
1780        {
1781
1782#ifdef INSTRUMENTATION
1783m_cpt_icache_dir_read++;
1784#endif
1785            uint32_t    inst;
1786            size_t      way;
1787            size_t      set;
1788            size_t      word;
1789            bool        hit = r_icache.read(paddr, 
1790                                            &inst,
1791                                            &way, 
1792                                            &set, 
1793                                            &word);
1794            r_icache_cc_way = way;
1795            r_icache_cc_set = set;
1796
1797            if ( hit and r_tgt_update.read() )           // hit update
1798            {
1799                r_icache_fsm         = ICACHE_CC_UPDT;
1800                r_icache_cc_word     = r_tgt_word_min.read();
1801            }
1802            else if ( hit and not r_tgt_update.read() )  // hit inval
1803            {
1804                r_icache_fsm           = ICACHE_CC_INVAL;
1805            }
1806            else                                         // miss can happen
1807            {
1808                r_tgt_icache_req = false;
1809                r_tgt_icache_rsp = r_tgt_update.read();
1810                r_icache_fsm     = r_icache_fsm_save.read();
1811            }
1812        }
1813        break;
1814    }
1815
1816    /////////////////////
1817    case ICACHE_CC_INVAL:       // invalidate a cache line
1818    {                       
1819        paddr_t nline;
1820        r_icache.inval( r_icache_cc_way.read(),
1821                        r_icache_cc_set.read(), 
1822                        &nline );
1823
1824        r_tgt_icache_req = false;
1825        r_tgt_icache_rsp = true;
1826        r_icache_fsm     = r_icache_fsm_save.read();
1827        break;
1828    }
1829    ////////////////////
1830    case ICACHE_CC_UPDT:        // write one word per cycle (from word_min to word_max)
1831    {
1832        size_t  word  = r_icache_cc_word.read();
1833        size_t  way   = r_icache_cc_way.read();
1834        size_t  set   = r_icache_cc_set.read();
1835
1836        r_icache.write( way,
1837                        set,
1838                        word,
1839                        r_tgt_buf[word],
1840                        r_tgt_be[word] );
1841
1842        r_icache_cc_word = word+1;
1843
1844        if ( word == r_tgt_word_max.read() )    // last word
1845        {
1846            r_tgt_icache_req = false;
1847            r_tgt_icache_rsp = true;
1848            r_icache_fsm     = r_icache_fsm_save.read();
1849        }
1850        break;
1851    }
1852
1853    } // end switch r_icache_fsm
1854
1855    ////////////////////////////////////////////////////////////////////////////////////
1856    //      DCACHE FSM
1857    //
1858    // Both the Cacheability Table, and the MMU cacheable bit are used to define
1859    // the cacheability, depending on the MMU mode.
1860    //
1861    // 1/ Coherence requests :
1862    //    There is a coherence request when the tgt_dcache_req flip-flop is set,
1863    //    requesting a line invalidation or a line update.
1864    //    Coherence requests are taken into account in IDLE, UNC_WAIT, MISS_WAIT states.
1865    //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
1866    //    goes to the CC_CHECK state to execute the requested action, and returns to the
1867    //    pre-empted state.
1868    //
1869    // 2/ TLB miss
1870    //    The page tables can be cacheable.
1871    //    In case of miss in itlb or dtlb, the tlb miss is handled by a dedicated
1872    //    sub-fsm (DCACHE_TLB_MISS state), that handle possible miss in DCACHE,
1873    //    this sub-fsm implement the table-walk...
1874    //
1875    // 3/ processor requests :
1876    //    Processor READ, WRITE, LL or SC requests are taken in IDLE state only.
1877    //    The IDLE state implements a three stages pipe-line to handle write bursts:
1878    //    - The physical address is computed by dtlb in stage P0.
1879    //    - The registration in wbuf and the dcache hit are computed in stage P1.
1880    //    - The dcache update is done in stage P2. 
1881    //    WRITE or SC requests can require a PTE Dirty bit update (in memory),
1882    //    that is done (before handling the processor request) by a dedicated sub-fsm
1883    //    (DCACHE_DIRTY_TLB_SET state).
1884    //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
1885    //    cleared by a dedicated sub_fsm (DCACHE_INVAL_TLB_SCAN state).
1886    //    If there is no write in the pipe, dcache and dtlb are accessed in parallel,
1887    //    (virtual address for itlb, and speculative physical address computed during
1888    //    previous cycle for dcache) in order to return the data in one cycle for a READ
1889    //    request. We just pay an extra cycle when the speculative access is failing.
1890    //
1891    // 4/ Atomic instructions LL/SC
1892    //    The LL/SC address can be cacheable or non cacheable.
1893    //    The reservation registers (r_dcache_ll_valid, r_dcache_ll_vaddr and
1894    //    r_dcache_ll_data are stored in the L1 cache controller, and not in the
1895    //    memory controller.
1896    //    - LL requests from the processor are transmitted as standard VCI
1897    //      READ transactions (one word / one line, depending on the cacheability).
1898    //    - SC requests from the processor are systematically transmitted to the
1899    //      memory cache as Compare&swap requests (both the data value stored in the
1900    //      r_dcache_ll_data register and the new value).
1901    //      The cache is not updated, as this is done in case of success by the
1902    //      coherence transaction.
1903    //
1904    // 5/ Non cacheable access:
1905    //    This component implement a strong order between non cacheable access
1906    //    (read or write) : A new non cacheable VCI transaction starts only when
1907    //    the previous non cacheable transaction is completed. Both cacheable and
1908    //    non cacheable transactions use the write buffer, but the DCACHE FSM registers
1909    //    a non cacheable write transaction posted in the write buffer by setting the
1910    //    r_dcache_pending_unc_write flip_flop. All other non cacheable requests
1911    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the
1912    //    pending non cacheable write transaction completes).
1913    //
1914    // 6/ Error handling: 
1915    //    When the MMU is not activated, Read Bus Errors are synchronous events,
1916    //    but Write Bus Errors are asynchronous events (processor is not frozen).
1917    //    - If a Read Bus Error is detected, the VCI_RSP FSM sets the
1918    //      r_vci_rsp_data_error flip-flop, without writing any data in the
1919    //      r_vci_rsp_fifo_dcache FIFO, and the synchronous error is signaled
1920    //      by the DCACHE FSM.
1921    //    - If a Write Bus Error is detected, the VCI_RSP FSM  signals
1922    //      the asynchronous error using the setWriteBerr() method.
1923    //    When the MMU is activated bus error are rare events, as the MMU
1924    //    checks the physical address before the VCI transaction starts.
1925    ////////////////////////////////////////////////////////////////////////////////////////
1926
1927    // default value for m_drsp
1928    m_drsp.valid = false;
1929    m_drsp.error = false;
1930    m_drsp.rdata = 0;
1931
1932    switch ( r_dcache_fsm.read() ) 
1933    {
1934    case DCACHE_IDLE:   // There is 8 conditions to exit the IDLE state :
1935                        // 1) Dirty bit update (processor)      => DCACHE_DIRTY_GET_PTE
1936                        // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK
1937                        // 3) ITLB miss request (ICACHE FSM)    => DCACHE_TLB_MISS
1938                        // 4) XTN request (processor)           => DCACHE_XTN_*
1939                        // 5) DTLB miss (processor)             => DCACHE_TLB_MISS
1940                        // 6) Cacheable read miss (processor)   => DCACHE_MISS_VICTIM
1941                        // 7) Uncacheable read (processor)      => DCACHE_UNC_WAIT
1942                        // 8) SC access (processor)             => DCACHE_SC_WAIT
1943                        //
1944                        // The dtlb is unconditionally accessed to translate the
1945                        // virtual adress from processor.
1946                        //
1947                        // There is 4 configurations to access the cache,
1948                        // depending on the pipe-line state, defined
1949                        // by the r_dcache_p0_valid (V0) flip-flop : P1 stage activated
1950                        // and    r_dcache_p1_valid (V1) flip-flop : P2 stage activated
1951                        //  V0 / V1 / Data      / Directory / comment                   
1952                        //  0  / 0  / read(A0)  / read(A0)  / read speculative access 
1953                        //  0  / 1  / write(A2) / nop       / read request delayed
1954                        //  1  / 0  / nop       / read(A1)  / read request delayed
1955                        //  1  / 1  / write(A2) / read(A1)  / read request delayed
1956    { 
1957        ////////////////////////////////////////////////////////////////////////////////
1958        // Handling P2 pipe-line stage
1959        // Inputs are r_dcache_p1_* registers.
1960        // If r_dcache_p1_valid is true, we update the local copy in dcache.
1961        // If the modified cache line has copies in TLBs, we launch a TLB invalidate
1962        // operation, going to DCACHE_INVAL_TLB_SCAN state.
1963
1964        bool tlb_inval_required = false;
1965
1966        if ( r_dcache_p1_valid.read() )         // P2 stage activated
1967        {
1968            size_t   way        = r_dcache_p1_cache_way.read();
1969            size_t   set        = r_dcache_p1_cache_set.read();
1970            size_t   word       = r_dcache_p1_cache_word.read();
1971            uint32_t wdata      = r_dcache_p1_wdata.read();
1972            vci_be_t be         = r_dcache_p1_be.read();
1973
1974            r_dcache.write( way,
1975                            set,
1976                            word,
1977                            wdata,
1978                            be );
1979#ifdef INSTRUMENTATION
1980m_cpt_dcache_data_write++; 
1981#endif
1982            // cache update after a WRITE hit can require itlb & dtlb inval or flush
1983            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
1984            {
1985                tlb_inval_required       = true;
1986                r_dcache_tlb_inval_count = 0;
1987                r_dcache_tlb_inval_line  = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 
1988                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
1989            }
1990            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
1991            {
1992                r_itlb.reset();
1993                r_dtlb.reset();
1994                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
1995            }
1996
1997#if DEBUG_DCACHE
1998if ( m_debug_dcache_fsm )
1999{
2000    std::cout << "  <PROC.DCACHE_IDLE> Cache update in P2 stage" << std::dec
2001              << " / WAY = " << way
2002              << " / SET = " << set
2003              << " / WORD = " << word << std::hex
2004              << " / DATA = " << wdata
2005              << " / BE = " << be << std::endl;
2006}
2007#endif
2008        } // end P2 stage
2009
2010        ///////////////////////////////////////////////////////////////////////////
2011        // Handling P1 pipe-line stage
2012        // Inputs are r_dcache_p0_* registers.
2013        // We must write into wbuf and test the hit in dcache.
2014        // If the write request is non cacheable, and there is a pending
2015        // non cacheable write, or if the write buffer is full, we break,
2016        // because the P0 and P1 pipe-line stages are frozen until the write
2017        // request registration is possible, but he P2 stage is not frozen.
2018        // The r_dcache_p1_valid bit must be computed at all cycles, and
2019        // the P2 stage must be activated if there is local copy in dcache.
2020
2021        if ( r_dcache_p0_valid.read() )  // P1 stage activated
2022        {
2023            // write not cacheable, and previous non cacheable write registered
2024            if ( not r_dcache_p0_cacheable.read() and r_dcache_pending_unc_write.read() ) 
2025            {
2026                r_dcache_p1_valid = false;
2027                break;
2028            }
2029
2030            // try a registration into write buffer
2031            bool wok = r_wbuf.write( r_dcache_p0_paddr.read(),
2032                                     r_dcache_p0_be.read(),
2033                                     r_dcache_p0_wdata.read(),
2034                                     r_dcache_p0_cacheable.read() );
2035#ifdef INSTRUMENTATION
2036m_cpt_wbuf_write++;
2037#endif
2038            // write buffer full
2039            if ( not wok ) 
2040            {
2041                r_dcache_p1_valid = false;
2042                break; 
2043            }
2044            // update the write_buffer state extension
2045            r_dcache_pending_unc_write = not r_dcache_p0_cacheable.read();
2046
2047            // read directory to check local copy
2048            size_t  cache_way;
2049            size_t  cache_set;
2050            size_t  cache_word;
2051            bool    local_copy;
2052            if ( r_mmu_mode.read() & DATA_CACHE_MASK)   // cache activated
2053            {
2054                local_copy = r_dcache.hit( r_dcache_p0_paddr.read(),
2055                                           &cache_way,
2056                                           &cache_set,
2057                                           &cache_word );
2058#ifdef INSTRUMENTATION
2059m_cpt_dcache_dir_read++; 
2060#endif
2061            }
2062            else
2063            {
2064                local_copy = false;
2065            }
2066
2067            // store values for P2 pipe stage
2068            if ( local_copy )
2069            {
2070                r_dcache_p1_valid       = true;
2071                r_dcache_p1_wdata       = r_dcache_p0_wdata.read();
2072                r_dcache_p1_be          = r_dcache_p0_be.read();
2073                r_dcache_p1_paddr       = r_dcache_p0_paddr.read();
2074                r_dcache_p1_cache_way   = cache_way;
2075                r_dcache_p1_cache_set   = cache_set;
2076                r_dcache_p1_cache_word  = cache_word;
2077            }
2078            else
2079            {
2080                r_dcache_p1_valid       = false;
2081            }
2082        }
2083        else                            // P1 stage not activated
2084        {
2085            r_dcache_p1_valid = false; 
2086        } // end P1 stage
2087
2088        /////////////////////////////////////////////////////////////////////////////////
2089        // handling P0 pipe-line stage
2090        // This stage is controlling r_dcache_fsm and r_dcache_p0_* registers.
2091        // The r_dcache_p0_valid flip-flop is only set in case of a WRITE request.
2092        // - the TLB invalidate requests have the highest priority,
2093        // - then the external coherence requests,
2094        // - then the itlb miss requests,
2095        // - and finally the processor requests.
2096        // If dtlb is activated, there is an unconditionnal access to dtlb,
2097        // for address translation.
2098        // 1) A processor WRITE request is blocked if the Dirty bit mus be set, or if
2099        //    dtlb miss. If dtlb is OK, It enters the three stage pipe-line (fully
2100        //    handled by the IDLE state), and the processor request is acknowledged.
2101        // 2) A processor READ or LL request generate a simultaneouss access to
2102        //    both dcache data and dcache directoty, using speculative PPN, but
2103        //    is delayed if the write pipe-line is not empty.
2104        //    In case of miss, we wait the VCI response in DCACHE_UNC_WAIT or
2105        //    DCACHE_MISS_WAIT states.
2106        // 3) A processor SC request is delayed until the write pipe-line is empty.
2107        //    A VCI SC transaction is launched, and we wait the VCI response in
2108        //    DCACHE_SC_WAIT state. It can be completed by a "long write" if the
2109        //    PTE dirty bit must be updated in dtlb, dcache, and RAM.
2110        //    The data is not modified in dcache, as it will be done by the
2111        //    coherence transaction.   
2112
2113        // TLB inval required
2114        if ( tlb_inval_required )
2115        {
2116            r_dcache_fsm_save = DCACHE_IDLE;
2117            r_dcache_fsm      = DCACHE_INVAL_TLB_SCAN;
2118            r_dcache_p0_valid = false;
2119        }
2120        // external coherence request
2121        else if ( r_tgt_dcache_req.read() )   
2122        {
2123            r_dcache_fsm_save = DCACHE_IDLE;
2124            r_dcache_fsm      = DCACHE_CC_CHECK;
2125            r_dcache_p0_valid = false;
2126        }       
2127
2128        // itlb miss request
2129        else if ( r_icache_tlb_miss_req.read() )
2130        {
2131            r_dcache_tlb_ins    = true;
2132            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
2133            r_dcache_fsm        = DCACHE_TLB_MISS;
2134            r_dcache_p0_valid = false;
2135        }
2136
2137        // processor request
2138        else if ( m_dreq.valid )
2139        {
2140            // dcache access using speculative PPN only if pipe-line empty
2141            paddr_t     cache_paddr;
2142            size_t      cache_way;
2143            size_t      cache_set;
2144            size_t      cache_word;
2145            uint32_t    cache_rdata;
2146            bool        cache_hit;
2147
2148            if ( (r_mmu_mode.read() & DATA_CACHE_MASK) and      // cache activated
2149                 not r_dcache_p0_valid.read() and
2150                 not r_dcache_p1_valid.read() )                 // pipe-line empty
2151            {
2152                cache_paddr = (r_dcache_p0_paddr.read() & ~PAGE_K_MASK) | 
2153                              ((paddr_t)m_dreq.addr & PAGE_K_MASK);
2154
2155                cache_hit = r_dcache.read( cache_paddr,
2156                                           &cache_rdata,
2157                                           &cache_way,
2158                                           &cache_set,
2159                                           &cache_word );
2160#ifdef INSTRUMENTATION
2161m_cpt_dcache_dir_read++;
2162m_cpt_dcache_data_read++;
2163#endif
2164            }
2165            else
2166            {
2167                cache_hit = false;
2168            } // end dcache access   
2169
2170            // systematic dtlb access using virtual address
2171            paddr_t     tlb_paddr;
2172            pte_info_t  tlb_flags; 
2173            size_t      tlb_way; 
2174            size_t      tlb_set; 
2175            paddr_t     tlb_nline; 
2176            bool        tlb_hit;       
2177
2178            if ( r_mmu_mode.read() & DATA_TLB_MASK )    // DTLB activated
2179            {
2180                tlb_hit = r_dtlb.translate( m_dreq.addr,
2181                                            &tlb_paddr,
2182                                            &tlb_flags,
2183                                            &tlb_nline,
2184                                            &tlb_way,   
2185                                            &tlb_set ); 
2186#ifdef INSTRUMENTATION
2187m_cpt_dtlb_read++;
2188#endif
2189            }
2190            else
2191            {
2192                tlb_hit = false;
2193            } // end dtlb access
2194
2195            // register the processor request
2196            r_dcache_p0_vaddr = m_dreq.addr;
2197            r_dcache_p0_be    = m_dreq.be;
2198            r_dcache_p0_wdata = m_dreq.wdata;
2199
2200            // Handling READ XTN requests from processor
2201            // They are executed in this DCACHE_IDLE state.
2202            // The processor must not be in user mode
2203            if (m_dreq.type == iss_t::XTN_READ) 
2204            {
2205                int xtn_opcode = (int)m_dreq.addr/4;
2206
2207                // checking processor mode:
2208                if (m_dreq.mode  == iss_t::MODE_USER)
2209                {
2210                    r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION; 
2211                    r_mmu_dbvar  = m_dreq.addr;
2212                    m_drsp.valid            = true;
2213                    m_drsp.error            = true;
2214                    r_dcache_fsm          = DCACHE_IDLE;
2215                }
2216                else 
2217                {
2218                    switch( xtn_opcode ) 
2219                    {
2220                    case iss_t::XTN_INS_ERROR_TYPE:
2221                        m_drsp.rdata = r_mmu_ietr.read();
2222                        m_drsp.valid = true;
2223                        break;
2224
2225                    case iss_t::XTN_DATA_ERROR_TYPE:
2226                        m_drsp.rdata = r_mmu_detr.read();
2227                        m_drsp.valid = true;
2228                        break;
2229
2230                    case iss_t::XTN_INS_BAD_VADDR:
2231                        m_drsp.rdata = r_mmu_ibvar.read();       
2232                        m_drsp.valid = true;
2233                        break;
2234
2235                    case iss_t::XTN_DATA_BAD_VADDR:
2236                        m_drsp.rdata = r_mmu_dbvar.read();       
2237                        m_drsp.valid = true;
2238                        break;
2239
2240                    case iss_t::XTN_PTPR:
2241                        m_drsp.rdata = r_mmu_ptpr.read();
2242                        m_drsp.valid = true;
2243                        break;
2244
2245                    case iss_t::XTN_TLB_MODE:
2246                        m_drsp.rdata = r_mmu_mode.read();
2247                        m_drsp.valid = true;
2248                        break;
2249
2250                    case iss_t::XTN_MMU_PARAMS:
2251                        m_drsp.rdata = r_mmu_params;
2252                        m_drsp.valid = true;
2253                        break;
2254
2255                    case iss_t::XTN_MMU_RELEASE:
2256                        m_drsp.rdata = r_mmu_release;
2257                        m_drsp.valid = true;
2258                        break;
2259
2260                    case iss_t::XTN_MMU_WORD_LO:
2261                        m_drsp.rdata = r_mmu_word_lo.read();
2262                        m_drsp.valid = true;
2263                        break;
2264
2265                    case iss_t::XTN_MMU_WORD_HI:
2266                        m_drsp.rdata = r_mmu_word_hi.read();
2267                        m_drsp.valid = true;
2268                        break;
2269
2270                    default:
2271                        r_mmu_detr = MMU_READ_UNDEFINED_XTN; 
2272                        r_mmu_dbvar  = m_dreq.addr;
2273                        m_drsp.valid = true;
2274                        m_drsp.error = true;
2275                        break;
2276                    } // end switch xtn_opcode
2277                } // end else
2278                r_dcache_p0_valid = false;
2279            } // end if XTN_READ
2280
2281            // Handling WRITE XTN requests from processor.
2282            // They are not executed in this DCACHE_IDLE state,
2283            // if they require access to the caches or the TLBs
2284            // that are already accessed for speculative read.
2285            // Caches can be invalidated or flushed in user mode,
2286            // and the sync instruction can be executed in user mode
2287            else if (m_dreq.type == iss_t::XTN_WRITE) 
2288            {
2289                int xtn_opcode      = (int)m_dreq.addr/4;
2290                r_dcache_xtn_opcode = xtn_opcode;
2291
2292                // checking processor mode:
2293                if ( (m_dreq.mode  == iss_t::MODE_USER) &&
2294                     (xtn_opcode != iss_t:: XTN_SYNC) &&
2295                     (xtn_opcode != iss_t::XTN_DCACHE_INVAL) &&
2296                     (xtn_opcode != iss_t::XTN_DCACHE_FLUSH) &&
2297                     (xtn_opcode != iss_t::XTN_ICACHE_INVAL) &&
2298                     (xtn_opcode != iss_t::XTN_ICACHE_FLUSH) )
2299                {
2300                    r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION; 
2301                    r_mmu_dbvar  = m_dreq.addr;
2302                    m_drsp.valid          = true;
2303                    m_drsp.error          = true;
2304                    r_dcache_fsm        = DCACHE_IDLE;
2305                }
2306                else
2307                {
2308                    switch( xtn_opcode ) 
2309                    {     
2310                    case iss_t::XTN_PTPR:                       // itlb & dtlb must be flushed
2311                        r_mmu_ptpr       = m_dreq.wdata;
2312                        r_dcache_xtn_req = true;
2313                        r_dcache_fsm     = DCACHE_XTN_SWITCH;
2314                        break;
2315
2316                    case iss_t::XTN_TLB_MODE:                   // no cache or tlb access
2317                        r_mmu_mode = m_dreq.wdata;
2318                        m_drsp.valid = true;
2319                        r_dcache_fsm = DCACHE_IDLE;
2320                        break;
2321
2322                    case iss_t::XTN_DTLB_INVAL:                 // dtlb access
2323                        r_dcache_fsm = DCACHE_XTN_DT_INVAL; 
2324                        break;
2325
2326                    case iss_t::XTN_ITLB_INVAL:                 // itlb access
2327                        r_dcache_xtn_req = true;
2328                        r_dcache_fsm = DCACHE_XTN_IT_INVAL; 
2329                        break;
2330
2331                    case iss_t::XTN_DCACHE_INVAL:               // dcache, dtlb & itlb access
2332                        r_dcache_fsm = DCACHE_XTN_DC_INVAL_VA;
2333                        break;
2334
2335                    case iss_t::XTN_MMU_DCACHE_PA_INV:          // dcache, dtlb & itlb access
2336                        r_dcache_fsm   = DCACHE_XTN_DC_INVAL_PA;
2337                        r_dcache_p0_paddr = (paddr_t)r_mmu_word_hi.read() << 32 | 
2338                                         (paddr_t)r_mmu_word_lo.read();
2339                        break;
2340
2341                    case iss_t::XTN_DCACHE_FLUSH:              // itlb and dtlb must be reset 
2342                        r_dcache_flush_count = 0;
2343                        r_dcache_fsm         = DCACHE_XTN_DC_FLUSH; 
2344                        break;
2345
2346                    case iss_t::XTN_ICACHE_INVAL:               // icache and itlb access
2347                        r_dcache_xtn_req = true;
2348                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA; 
2349                        break;
2350
2351                    case iss_t::XTN_MMU_ICACHE_PA_INV:          // icache access
2352                        r_dcache_xtn_req = true;
2353                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA; 
2354                        break;
2355
2356                    case iss_t::XTN_ICACHE_FLUSH:               // icache access
2357                        r_dcache_xtn_req = true; 
2358                        r_dcache_fsm     = DCACHE_XTN_IC_FLUSH;
2359                        break;
2360
2361                    case iss_t::XTN_SYNC:                       // wait until write buffer empty
2362                        r_dcache_fsm     = DCACHE_XTN_SYNC;
2363                        break;
2364
2365                    case iss_t::XTN_MMU_WORD_LO:                // no cache or tlb access
2366                        r_mmu_word_lo = m_dreq.wdata;
2367                        m_drsp.valid    = true;
2368                        r_dcache_fsm  = DCACHE_IDLE;
2369                        break;
2370
2371                    case iss_t::XTN_MMU_WORD_HI:                // no cache or tlb access
2372                        r_mmu_word_hi = m_dreq.wdata;
2373                        m_drsp.valid    = true;
2374                        r_dcache_fsm  = DCACHE_IDLE;
2375                        break;
2376
2377                    case iss_t::XTN_ICACHE_PREFETCH:            // not implemented : no action
2378                    case iss_t::XTN_DCACHE_PREFETCH:            // not implemented : no action
2379                        m_drsp.valid   = true;
2380                        r_dcache_fsm = DCACHE_IDLE;
2381                        break;
2382       
2383                    default:
2384                        r_mmu_detr = MMU_WRITE_UNDEFINED_XTN; 
2385                        r_mmu_dbvar  = m_dreq.addr;
2386                        m_drsp.valid = true;
2387                        m_drsp.error = true;
2388                        r_dcache_fsm = DCACHE_IDLE;
2389                        break;
2390                    } // end switch xtn_opcode
2391                } // end else
2392                r_dcache_p0_valid = false;
2393            } // end if XTN_WRITE
2394
2395            // Handling read/write/ll/sc processor requests.
2396            // The dtlb and dcache can be activated or not.
2397            // We compute the physical address, the cacheability, and check processor request.
2398            // - If DTLB not activated : cacheability is defined by the segment table,
2399            //   the physical address is equal to the virtual address (identity mapping)
2400            // - If DTLB activated : cacheability is defined by the C bit in the PTE,
2401            //   the physical address is obtained from the TLB, and the U & W bits
2402            //   of the PTE are checked.
2403            // The processor request is decoded only if the TLB is not activated or if
2404            // the virtual address hits in tLB and access rights are OK.
2405            // We call the TLB_MISS sub-fsm in case of dtlb miss.
2406            else
2407            {
2408                bool    valid_req = false;
2409                bool    cacheable = false;
2410                paddr_t paddr     = 0;
2411
2412                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )          // dtlb not activated
2413                {
2414                    valid_req     = true;
2415
2416                    // cacheability
2417                    if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2418                    else cacheable = m_cacheability_table[m_dreq.addr];
2419
2420                    // physical address
2421                    paddr       = (paddr_t)m_dreq.addr;
2422                }
2423                else                                                    // dtlb activated
2424                {
2425                    if ( tlb_hit )                                      // tlb hit
2426                    {
2427                        // cacheability
2428                        if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2429                        else cacheable = tlb_flags.c;
2430
2431                        // access rights checking
2432                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER)) 
2433                        {
2434                            if ( (m_dreq.type == iss_t::DATA_READ) or (m_dreq.type == iss_t::DATA_LL) )
2435                                r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION;
2436                            else 
2437                                r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION;
2438
2439                            r_mmu_dbvar  = m_dreq.addr;
2440                            m_drsp.valid   = true;
2441                            m_drsp.error   = true;
2442                            m_drsp.rdata   = 0;
2443#if DEBUG_DCACHE
2444if ( m_debug_dcache_fsm )
2445{
2446    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but privilege violation" << std::endl;
2447}
2448#endif
2449                        }
2450                        else if ( not tlb_flags.w and
2451                                  ((m_dreq.type == iss_t::DATA_WRITE) or
2452                                   (m_dreq.type == iss_t::DATA_SC)) ) 
2453                        {
2454                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION; 
2455                            r_mmu_dbvar  = m_dreq.addr;
2456                            m_drsp.valid   = true;
2457                            m_drsp.error   = true;
2458                            m_drsp.rdata   = 0;
2459#if DEBUG_DCACHE
2460if ( m_debug_dcache_fsm )
2461{
2462    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but writable violation" << std::endl;
2463}
2464#endif
2465                        }
2466                        else
2467                        {
2468                            valid_req    = true;
2469                        }
2470
2471                        // physical address
2472                        paddr = tlb_paddr;
2473                    }
2474                    else                                                // tlb miss
2475                    {
2476                        r_dcache_tlb_vaddr   = m_dreq.addr;
2477                        r_dcache_tlb_ins     = false; 
2478                        r_dcache_fsm         = DCACHE_TLB_MISS;
2479                    }
2480                }    // end DTLB activated
2481
2482                if ( valid_req )        // processor request is valid after TLB check
2483                {
2484                    // physical address and cacheability registration
2485                    r_dcache_p0_paddr          = paddr;
2486                    r_dcache_p0_cacheable      = cacheable;
2487
2488                    // READ or LL request
2489                    // The read requests are taken only if the write pipe-line is empty.
2490                    // If dcache hit, dtlb hit, and speculative PPN OK, data in one cycle.
2491                    // If speculative access is KO we just pay one extra cycle.
2492                    // If dcache miss, we go to DCACHE_MISS_VICTIM state.
2493                    // If uncacheable, we go to DCACHE_UNC_WAIT state.
2494                    if ( ((m_dreq.type == iss_t::DATA_READ) or (m_dreq.type == iss_t::DATA_LL)) 
2495                        and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
2496                    { 
2497                        if ( cacheable )                        // cacheable read
2498                        {
2499                            // if the speculative access is illegal, we pay an extra cycle
2500                            if ( (r_dcache_p0_paddr.read() & ~PAGE_K_MASK) 
2501                                 != (paddr & ~PAGE_K_MASK))
2502                            {
2503#ifdef INSTRUMENTATION
2504m_cpt_dcache_spec_miss++;
2505#endif
2506                            }
2507                            // if cache miss, try to get the missing line
2508                            else if ( not cache_hit )
2509                            {
2510#ifdef INSTRUMENTATION
2511m_cpt_dcache_miss++;
2512#endif
2513                                // blocked in IDLE state if previous cleanup not completed
2514                                if ( not r_dcache_cleanup_req.read() )
2515                                {
2516                                    r_dcache_vci_paddr    = paddr;
2517                                    r_dcache_vci_miss_req = true;
2518                                    r_dcache_miss_type    = PROC_MISS;
2519                                    r_dcache_fsm          = DCACHE_MISS_VICTIM;
2520                                }
2521                            }
2522                            // if cache hit return the data
2523                            else                   
2524                            {
2525#ifdef INSTRUMENTATION
2526m_cpt_data_read++;
2527#endif
2528                                m_drsp.valid   = true;
2529                                m_drsp.rdata   = cache_rdata;
2530#if DEBUG_DCACHE
2531if ( m_debug_dcache_fsm )
2532{
2533    std::cout << "  <PROC.DCACHE_IDLE> HIT in dcache" << std::endl;
2534}
2535#endif
2536                            }
2537                        }
2538                        else                                    // uncacheable read
2539                        {
2540                            r_dcache_vci_paddr    = paddr;
2541                            r_dcache_vci_unc_be   = m_dreq.be;
2542                            r_dcache_vci_unc_req  = true;
2543                            r_dcache_fsm          = DCACHE_UNC_WAIT;
2544                        }
2545
2546                        // makes reservation in case of LL
2547                        if ( m_dreq.type == iss_t::DATA_LL )
2548                        {
2549                            r_dcache_ll_valid = true;
2550                            r_dcache_ll_data  = cache_rdata;
2551                            r_dcache_ll_vaddr = m_dreq.addr;
2552                        }
2553                        r_dcache_p0_valid = false;
2554                    } // end READ or LL
2555
2556                    // WRITE request:
2557                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2558                    // the processor and set the Dirty bit before handling the write request.
2559                    // If we don't need to set the Dirty bit, we can acknowledge
2560                    // the processor request, as the write arguments (including the
2561                    // physical address) are registered in r_dcache_p0 registers:
2562                    // We simply activate the P1 pipeline stage.
2563                    else if ( m_dreq.type == iss_t::DATA_WRITE )
2564                    {
2565                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
2566                              and not tlb_flags.d )             // Dirty bit must be set
2567                        {
2568                            // The PTE physical address is obtained from the nline value (dtlb),
2569                            // and the word index (proper bits of the virtual address)
2570                            if ( tlb_flags.b )  // PTE1
2571                            {
2572                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2573                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2574                            }
2575                            else                // PTE2
2576                            {
2577                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2578                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2579                            }
2580                            r_dcache_fsm      = DCACHE_DIRTY_GET_PTE;
2581                            r_dcache_p0_valid = false;
2582                        }
2583                        else                                    // Write request accepted
2584                        {
2585#ifdef INSTRUMENTATION
2586m_cpt_data_write++;
2587#endif
2588                            m_drsp.valid      = true;
2589                            m_drsp.rdata      = 0;
2590                            r_dcache_p0_valid = true;
2591                        }
2592                    } // end WRITE
2593 
2594                    // SC request:
2595                    // The SC requests are taken only if the write pipe-line is empty.
2596                    // - if there is no valid registered LL, we just return rdata = 1
2597                    //   (atomic access failed) and the SC transaction is completed.
2598                    // - if a valid LL reservation (with the same address) is registered,
2599                    //   we test if a DIRTY bit update is required.
2600                    //   If the TLB is activated and the PTE Dirty bit is not set, we stall
2601                    //   the processor and set the Dirty bit before handling the write request.
2602                    //   If we don't need to set the Dirty bit, we request a SC transaction
2603                    //   to CMD FSM and go to DCACHE_SC_WAIT state, that will return
2604                    //   the response to the processor.
2605                    //   We don't check a possible write hit in dcache, as the cache update
2606                    //   is done by the coherence transaction induced by the SC...
2607                    else if ( ( m_dreq.type == iss_t::DATA_SC )
2608                        and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
2609                    {
2610                        if ( (r_dcache_ll_vaddr.read() != m_dreq.addr)
2611                             or not r_dcache_ll_valid.read() )  // no valid registered LL
2612                        { 
2613#ifdef INSTRUMENTATION
2614m_cpt_data_sc++;
2615#endif
2616                            m_drsp.valid        = true;
2617                            m_drsp.rdata        = 1;
2618                            r_dcache_ll_valid   = false;
2619                        }
2620                        else                                    // valid registered LL
2621                        {
2622                            if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
2623                                  and not tlb_flags.d )                 // Dirty bit must be set
2624                            {
2625                                // The PTE physical address is obtained from the nline value (dtlb),
2626                                // and the word index (proper bits of the virtual address)
2627                                if ( tlb_flags.b )      // PTE1
2628                                {
2629                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2630                                                           (paddr_t)((m_dreq.addr>>19) & 0x3c);
2631                                }
2632                                else                    // PTE2
2633                                {
2634                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2635                                                           (paddr_t)((m_dreq.addr>>9) & 0x38);
2636                                }
2637                                r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
2638                            }
2639                            else                                        // SC request accepted
2640                            {
2641#ifdef INSTRUMENTATION
2642m_cpt_data_sc++;
2643#endif
2644     
2645                                r_dcache_vci_paddr  = paddr;
2646                                r_dcache_vci_sc_req = true;
2647                                r_dcache_vci_sc_old = r_dcache_ll_data.read();
2648                                r_dcache_vci_sc_new = m_dreq.wdata;
2649                                r_dcache_ll_valid   = false;
2650                                r_dcache_fsm        = DCACHE_SC_WAIT;
2651                            }
2652                        }
2653                        r_dcache_p0_valid = false;
2654                    } // end SC
2655                    else
2656                    {
2657                        r_dcache_p0_valid = false;
2658                    }
2659                } // end valid_req
2660                else
2661                {
2662                    r_dcache_p0_valid = false;
2663                }
2664            }  // end if read/write/ll/sc request       
2665        } // end dreq.valid
2666        else
2667        {
2668            r_dcache_p0_valid = false;
2669        } // end P0 pipe stage
2670        break;
2671    } 
2672    /////////////////////
2673    case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss.
2674                          // Input arguments are:
2675                          // - r_dcache_tlb_vaddr
2676                          // - r_dcache_tlb_ins (true when itlb miss)
2677                          // The sub-fsm access the dcache to find the missing TLB entry,
2678                          // and activates the cache miss procedure in case of miss.
2679                          // It bypass the first level page table access if possible.
2680                          // It uses atomic access to update the R/L access bits
2681                          // in the page table if required.
2682                          // It directly updates the itlb or dtlb, and writes into the
2683                          // r_mmu_ins_* or r_mmu_data* error reporting registers.
2684    {
2685        uint32_t        ptba = 0;
2686        bool            bypass;
2687        paddr_t         pte_paddr;
2688
2689        // evaluate bypass in order to skip first level page table access
2690        if ( r_dcache_tlb_ins.read() )                          // itlb miss
2691        {
2692            bypass = r_itlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2693        }
2694        else                                                    // dtlb miss
2695        {
2696            bypass = r_dtlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2697        }
2698
2699        if ( not bypass )     // Try to read PTE1/PTD1 in dcache
2700        {
2701            pte_paddr = (paddr_t)r_mmu_ptpr.read() << (INDEX1_NBITS+2) |
2702                        (paddr_t)((r_dcache_tlb_vaddr.read() >> PAGE_M_NBITS) << 2);
2703            r_dcache_tlb_paddr = pte_paddr;
2704            r_dcache_fsm       = DCACHE_TLB_PTE1_GET;
2705        }
2706        else                  // Try to read PTE2 in dcache
2707        {
2708            pte_paddr = (paddr_t)ptba << PAGE_K_NBITS |
2709                        (paddr_t)(r_dcache_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
2710            r_dcache_tlb_paddr = pte_paddr;
2711            r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2712        }
2713
2714#if DEBUG_DCACHE
2715if ( m_debug_dcache_fsm )
2716{
2717    if ( r_dcache_tlb_ins.read() ) 
2718    {
2719        std::cout << "  <PROC.DCACHE_TLB_MISS> ITLB miss";
2720    }
2721    else
2722    {                           
2723        std::cout << "  <PROC.DCACHE_TLB_MISS> DTLB miss";
2724    }
2725    std::cout << " / VADDR = " << std::hex << r_dcache_tlb_vaddr.read()
2726              << " / BYPASS = " << bypass
2727              << " / PTE_ADR = " << pte_paddr << std::endl;
2728}
2729#endif
2730 
2731        break;
2732    }
2733    ///////////////////////// 
2734    case DCACHE_TLB_PTE1_GET:   // try to read a PT1 entry in dcache
2735    {
2736        uint32_t        entry;
2737        size_t          way;
2738        size_t          set;
2739        size_t          word;
2740
2741        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
2742                                      &entry,
2743                                      &way,
2744                                      &set,
2745                                      &word );
2746#ifdef INSTRUMENTATION
2747m_cpt_dcache_data_read++;
2748m_cpt_dcache_dir_read++;
2749#endif
2750        if ( hit )      //  hit in dcache
2751        {
2752            if ( not (entry & PTE_V_MASK) )     // unmapped
2753            {
2754                if ( r_dcache_tlb_ins.read() ) 
2755                {
2756                    r_mmu_ietr             = MMU_READ_PT1_UNMAPPED;
2757                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
2758                    r_icache_tlb_miss_req  = false;
2759                    r_icache_tlb_rsp_error = true;
2760                }
2761                else
2762                {
2763                    r_mmu_detr             = MMU_READ_PT1_UNMAPPED;
2764                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
2765                    m_drsp.valid             = true;
2766                    m_drsp.error             = true;
2767                }
2768                r_dcache_fsm          = DCACHE_IDLE;
2769
2770#if DEBUG_DCACHE
2771if ( m_debug_dcache_fsm )
2772{
2773    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped"
2774              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2775              << std::dec << " / way = " << way
2776              << std::dec << " / set = " << set
2777              << std::dec << " / word = " << word
2778              << std::hex << " / PTE1 = " << entry << std::endl;
2779}
2780#endif
2781 
2782            }
2783            else if( entry & PTE_T_MASK )       //  PTD : me must access PT2
2784            {
2785                // mark the cache line ac containing a PTD
2786                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
2787
2788                // register bypass
2789                if ( r_dcache_tlb_ins.read() )          // itlb
2790                {
2791                    r_itlb.set_bypass(r_dcache_tlb_vaddr.read(),
2792                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1), 
2793                                      r_dcache_tlb_paddr.read() >> (uint32_log2(m_icache_words<<2))); 
2794                }
2795                else                                    // dtlb
2796                {
2797                    r_dtlb.set_bypass(r_dcache_tlb_vaddr.read(),
2798                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
2799                                      r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2));
2800                }
2801                r_dcache_tlb_paddr = (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
2802                                     (paddr_t)(((r_dcache_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
2803                r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2804
2805#if DEBUG_DCACHE
2806if ( m_debug_dcache_fsm )
2807{
2808    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache"
2809              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2810              << std::dec << " / way = " << way
2811              << std::dec << " / set = " << set
2812              << std::dec << " / word = " << word
2813              << std::hex << " / PTD = " << entry << std::endl;
2814}
2815#endif
2816            }
2817            else                        //  PTE1 :  we must update the TLB
2818            {
2819                r_dcache_in_tlb[m_icache_sets*way+set] = true;
2820                r_dcache_tlb_pte_flags  = entry;
2821                r_dcache_tlb_cache_way  = way;
2822                r_dcache_tlb_cache_set  = set;
2823                r_dcache_tlb_cache_word = word;
2824                r_dcache_fsm            = DCACHE_TLB_PTE1_SELECT;
2825
2826#if DEBUG_DCACHE
2827if ( m_debug_dcache_fsm )
2828{
2829    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache"
2830              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2831              << std::dec << " / way = " << way
2832              << std::dec << " / set = " << set
2833              << std::dec << " / word = " << word
2834              << std::hex << " / PTE1 = " << entry << std::endl;
2835}
2836#endif
2837            }
2838        }
2839        else            // we must load the missing cache line in dcache
2840        {
2841            r_dcache_vci_miss_req  = true;             
2842            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read(); 
2843            r_dcache_miss_type     = PTE1_MISS;
2844            r_dcache_fsm           = DCACHE_MISS_VICTIM;         
2845
2846#if DEBUG_DCACHE
2847if ( m_debug_dcache_fsm )
2848{
2849    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> MISS in dcache:"
2850              << " PTE1 address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
2851}
2852#endif
2853        }
2854        break;
2855    }
2856    ////////////////////////////
2857    case DCACHE_TLB_PTE1_SELECT:        // select a slot for PTE1
2858    {
2859        size_t  way;
2860        size_t  set;
2861
2862        if ( r_dcache_tlb_ins.read() )
2863        {
2864            r_itlb.select( r_dcache_tlb_vaddr.read(),
2865                           true,  // PTE1
2866                           &way,
2867                           &set );
2868#ifdef INSTRUMENTATION
2869m_cpt_itlb_read++;
2870#endif
2871        }
2872        else
2873        {
2874            r_dtlb.select( r_dcache_tlb_vaddr.read(),
2875                           true,  // PTE1
2876                           &way,
2877                           &set );
2878#ifdef INSTRUMENTATION
2879m_cpt_dtlb_read++;
2880#endif
2881        }
2882        r_dcache_tlb_way = way;
2883        r_dcache_tlb_set = set;
2884        r_dcache_fsm     = DCACHE_TLB_PTE1_UPDT;
2885
2886#if DEBUG_DCACHE
2887if ( m_debug_dcache_fsm )
2888{
2889    if ( r_dcache_tlb_ins.read() ) 
2890        std::cout << "  <PROC.DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:";
2891    else                           
2892        std::cout << "  <PROC.DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:";
2893        std::cout << " way = " << std::dec << way
2894                  << " / set = " << set << std::endl;
2895}
2896#endif
2897        break;
2898    }
2899    //////////////////////////
2900    case DCACHE_TLB_PTE1_UPDT:  // write a new PTE1 in tlb after testing the L/R bit
2901                                // if L/R bit already set, exit the sub-fsm
2902                                // if not, the page table must be updated
2903    {
2904        paddr_t   nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
2905        uint32_t  pte   = r_dcache_tlb_pte_flags.read();
2906        bool      updt  = false;
2907        bool      local = true;
2908
2909        // We should compute the access locality:
2910        // The PPN MSB bits define the destination cluster index.
2911        // The m_srcid_d MSB bits define the source cluster index.
2912        // The number of bits to compare depends on the number of clusters,
2913        // and can be obtained in the mapping table.
2914        // As long as this computation is not done, all access are local.
2915
2916        if ( local )                                            // local access
2917        {
2918            if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
2919            {
2920                updt                = true;
2921                r_dcache_vci_sc_old = pte;
2922                r_dcache_vci_sc_new = pte | PTE_L_MASK;
2923                pte                 = pte | PTE_L_MASK;
2924            }
2925        }
2926        else                                                    // remote access
2927        {
2928            if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
2929            {
2930                updt                = true;
2931                r_dcache_vci_sc_old = pte;
2932                r_dcache_vci_sc_new = pte | PTE_R_MASK;
2933                pte                 = pte | PTE_R_MASK;
2934            }
2935        }
2936
2937        // update TLB
2938        if ( r_dcache_tlb_ins.read() ) 
2939        {
2940            r_itlb.write( true,         // 2M page
2941                          pte,
2942                          0,            // argument unused for a PTE1
2943                          r_dcache_tlb_vaddr.read(),   
2944                          r_dcache_tlb_way.read(), 
2945                          r_dcache_tlb_set.read(),
2946                          nline );
2947#ifdef INSTRUMENTATION
2948m_cpt_itlb_write++;
2949#endif
2950        }
2951        else
2952        {
2953            r_dtlb.write( true,         // 2M page
2954                          pte,
2955                          0,            // argument unused for a PTE1
2956                          r_dcache_tlb_vaddr.read(),   
2957                          r_dcache_tlb_way.read(), 
2958                          r_dcache_tlb_set.read(),
2959                          nline );
2960#ifdef INSTRUMENTATION
2961m_cpt_dtlb_write++;
2962#endif
2963        }
2964        // next state
2965        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
2966        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
2967
2968#if DEBUG_DCACHE
2969if ( m_debug_dcache_fsm )
2970{
2971    if ( r_dcache_tlb_ins.read() ) 
2972    {
2973        std::cout << "  <PROC.DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB";
2974        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
2975                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
2976        r_itlb.printTrace();
2977    }
2978    else                           
2979    {
2980        std::cout << "  <PROC.DCACHE_TLB_PTE1_UPDT> write PTE1 in DTLB";
2981        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
2982                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
2983        r_dtlb.printTrace();
2984    }
2985   
2986}
2987#endif
2988        break;
2989    }
2990    /////////////////////////
2991    case DCACHE_TLB_PTE2_GET:   // Try to get a PTE2 (64 bits) in the dcache
2992    {
2993        uint32_t        pte_flags;
2994        uint32_t        pte_ppn;
2995        size_t          way;
2996        size_t          set;
2997        size_t          word; 
2998 
2999        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
3000                                      &pte_flags,
3001                                      &pte_ppn,
3002                                      &way,
3003                                      &set,
3004                                      &word );
3005#ifdef INSTRUMENTATION
3006m_cpt_dcache_data_read++;
3007m_cpt_dcache_dir_read++;
3008#endif
3009        if ( hit )      // request hits in dcache
3010        {
3011            if ( not (pte_flags & PTE_V_MASK) ) // unmapped
3012            {
3013                if ( r_dcache_tlb_ins.read() ) 
3014                {
3015                    r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
3016                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3017                    r_icache_tlb_miss_req  = false;
3018                    r_icache_tlb_rsp_error = true;
3019                }
3020                else
3021                {
3022                    r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
3023                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3024                    m_drsp.valid             = true;
3025                    m_drsp.error             = true;
3026                }
3027                r_dcache_fsm          = DCACHE_IDLE;
3028
3029#if DEBUG_DCACHE
3030if ( m_debug_dcache_fsm )
3031{
3032    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE is unmapped"
3033              << " PTE_FLAGS = " << std::hex << pte_flags
3034              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3035}
3036#endif
3037            }
3038            else                                // mapped : we must update the TLB
3039            {
3040                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
3041                r_dcache_tlb_pte_flags  = pte_flags;
3042                r_dcache_tlb_pte_ppn    = pte_ppn;
3043                r_dcache_tlb_cache_way  = way;
3044                r_dcache_tlb_cache_set  = set;
3045                r_dcache_tlb_cache_word = word;
3046                r_dcache_fsm            = DCACHE_TLB_PTE2_SELECT;
3047
3048#if DEBUG_DCACHE
3049if ( m_debug_dcache_fsm )
3050{
3051    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> HIT in dcache:"
3052              << " PTE_FLAGS = " << std::hex << pte_flags
3053              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3054}
3055#endif
3056             }
3057        }
3058        else            // we must load the missing cache line in dcache
3059        {
3060            r_dcache_fsm          = DCACHE_MISS_VICTIM; 
3061            r_dcache_vci_miss_req = true;
3062            r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
3063            r_dcache_miss_type    = PTE2_MISS;
3064
3065#if DEBUG_DCACHE
3066if ( m_debug_dcache_fsm )
3067{
3068    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> MISS in dcache:"
3069              << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3070}
3071#endif
3072        }
3073        break;
3074    }
3075    ////////////////////////////
3076    case DCACHE_TLB_PTE2_SELECT:    // select a slot for PTE2
3077    {
3078        size_t way;
3079        size_t set;
3080
3081        if ( r_dcache_tlb_ins.read() )
3082        {
3083            r_itlb.select( r_dcache_tlb_vaddr.read(),
3084                           false,       // PTE2
3085                           &way,
3086                           &set );
3087#ifdef INSTRUMENTATION
3088m_cpt_itlb_read++;
3089#endif
3090        }
3091        else
3092        {
3093            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3094                           false,       // PTE2
3095                           &way,
3096                           &set );
3097#ifdef INSTRUMENTATION
3098m_cpt_dtlb_read++;
3099#endif
3100        }
3101
3102#if DEBUG_DCACHE
3103if ( m_debug_dcache_fsm )
3104{
3105    if ( r_dcache_tlb_ins.read() ) 
3106        std::cout << "  <PROC.DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
3107    else                           
3108        std::cout << "  <PROC.DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
3109        std::cout << " way = " << std::dec << way
3110                  << " / set = " << set << std::endl;
3111}
3112#endif
3113        r_dcache_tlb_way = way;
3114        r_dcache_tlb_set = set;
3115        r_dcache_fsm     = DCACHE_TLB_PTE2_UPDT;
3116        break;
3117    }
3118    //////////////////////////
3119    case DCACHE_TLB_PTE2_UPDT:          // write a new PTE2 in tlb after testing the L/R bit
3120                                        // if L/R bit already set, exit the sub-fsm
3121                                        // if not, the page table must be updated by an atomic access
3122    {
3123        paddr_t         nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
3124        uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
3125        uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
3126        bool            updt      = false;
3127        bool            local     = true;
3128
3129        // We should compute the access locality:
3130        // The PPN MSB bits define the destination cluster index.
3131        // The m_srcid_d MSB bits define the source cluster index.
3132        // The number of bits to compare depends on the number of clusters,
3133        // and can be obtained in the mapping table.
3134        // As long as this computation is not done, all access are local.
3135
3136        if ( local )                                            // local access
3137        {
3138            if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3139            {
3140                updt                = true;
3141                r_dcache_vci_sc_old = pte_flags;
3142                r_dcache_vci_sc_new = pte_flags | PTE_L_MASK;
3143                pte_flags           = pte_flags | PTE_L_MASK;
3144            }
3145        }
3146        else                                                    // remote access
3147        {
3148            if ( not ((pte_flags & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3149            {
3150                updt                   = true;
3151                r_dcache_vci_sc_old = pte_flags;
3152                r_dcache_vci_sc_new = pte_flags | PTE_R_MASK;
3153                pte_flags           = pte_flags | PTE_R_MASK;
3154            }
3155        }
3156       
3157        // update TLB for a PTE2
3158        if ( r_dcache_tlb_ins.read() ) 
3159        {
3160            r_itlb.write( false,        // 4K page
3161                          pte_flags,
3162                          pte_ppn,
3163                          r_dcache_tlb_vaddr.read(),   
3164                          r_dcache_tlb_way.read(), 
3165                          r_dcache_tlb_set.read(),
3166                          nline );
3167#ifdef INSTRUMENTATION
3168m_cpt_itlb_write++;
3169#endif
3170        }
3171        else
3172        {
3173            r_dtlb.write( false,        // 4K page
3174                          pte_flags,
3175                          pte_ppn,
3176                          r_dcache_tlb_vaddr.read(),   
3177                          r_dcache_tlb_way.read(), 
3178                          r_dcache_tlb_set.read(),
3179                          nline );
3180#ifdef INSTRUMENTATION
3181m_cpt_dtlb_write++;
3182#endif
3183        }
3184
3185#if DEBUG_DCACHE
3186if ( m_debug_dcache_fsm )
3187{
3188    if ( r_dcache_tlb_ins.read() ) 
3189    {
3190        std::cout << "  <PROC.DCACHE_TLB_PTE2_UPDT> write PTE2 in ITLB";
3191        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3192                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3193        r_itlb.printTrace();
3194    }
3195    else                           
3196    {
3197        std::cout << "  <PROC.DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB";
3198        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3199                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3200        r_dtlb.printTrace();
3201    }
3202}
3203#endif
3204        // next state
3205        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3206        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
3207        break;
3208    }
3209    ////////////////////////
3210    case DCACHE_TLB_LR_UPDT:            // update the dcache after a tlb miss (L/R bit),
3211                                        // request a SC transaction to CMD FSM
3212    {
3213#if DEBUG_DCACHE
3214if ( m_debug_dcache_fsm )
3215{
3216    std::cout << "  <PROC.DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
3217}
3218#endif
3219        r_dcache.write(r_dcache_tlb_cache_way.read(),
3220                       r_dcache_tlb_cache_set.read(),
3221                       r_dcache_tlb_cache_word.read(),
3222                       r_dcache_tlb_pte_flags.read());
3223#ifdef INSTRUMENTATION
3224m_cpt_dcache_data_write++;
3225#endif
3226        // r_dcache_vci_sc_old & r_dcache_vci_sc_new registers are already set
3227        r_dcache_vci_paddr   = r_dcache_tlb_paddr.read();
3228        r_dcache_vci_sc_req  = true;
3229        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
3230        break;
3231    }
3232    ////////////////////////
3233    case DCACHE_TLB_LR_WAIT:            // Waiting a response to SC transaction.
3234                                        // We consume the response in rsp FIFO,
3235                                        // and exit the sub-fsm, but we don't
3236                                        // analyse the response, because we don't
3237                                        // care if the L/R bit update is not done.
3238                                        // We must take the coherence requests because
3239                                        // there is a risk of dead-lock
3240
3241    {
3242        // external coherence request
3243        if ( r_tgt_dcache_req )
3244        {
3245            r_dcache_fsm = DCACHE_CC_CHECK;
3246            r_dcache_fsm_save = r_dcache_fsm;
3247            break;
3248        }
3249
3250        if ( r_vci_rsp_data_error.read() )      // bus error
3251        {
3252            std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl;
3253            std::cout << "This should not happen in this state" << std::endl;
3254            exit(0);
3255        }
3256        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3257        {
3258#if DEBUG_DCACHE
3259if ( m_debug_dcache_fsm )
3260{
3261    std::cout << "  <PROC.DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
3262}
3263#endif
3264            vci_rsp_fifo_dcache_get = true;     
3265            r_dcache_fsm            = DCACHE_TLB_RETURN;
3266        }
3267        break;
3268    }
3269    ///////////////////////
3270    case DCACHE_TLB_RETURN:             // return to caller depending on tlb miss type
3271    {
3272#if DEBUG_DCACHE
3273if ( m_debug_dcache_fsm )
3274{
3275    std::cout << "  <PROC.DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
3276}
3277#endif
3278        if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false;
3279        r_dcache_fsm = DCACHE_IDLE;
3280        break;
3281    }
3282    ///////////////////////
3283    case DCACHE_XTN_SWITCH:             // Both itlb and dtlb must be flushed
3284    {
3285        if ( not r_dcache_xtn_req.read() )
3286        {
3287            r_dtlb.flush();
3288            r_dcache_fsm = DCACHE_IDLE;
3289            m_drsp.valid = true;
3290        }
3291        break;
3292    }
3293    /////////////////////
3294    case DCACHE_XTN_SYNC:               // waiting until write buffer empty
3295                                        // The coherence request must be taken
3296                                        // as there is a risk of dead-lock
3297    {
3298        // external coherence request
3299        if ( r_tgt_dcache_req.read() )   
3300        {
3301            r_dcache_fsm = DCACHE_CC_CHECK;
3302            r_dcache_fsm_save = DCACHE_XTN_SYNC;
3303        }       
3304
3305        if ( r_wbuf.empty() )
3306        {
3307            m_drsp.valid   = true;
3308            r_dcache_fsm = DCACHE_IDLE;
3309        }
3310        break;
3311    }
3312    ////////////////////////
3313    case DCACHE_XTN_IC_FLUSH:           // Waiting completion of an XTN request to the ICACHE FSM
3314    case DCACHE_XTN_IC_INVAL_VA:        // Caution : the itlb miss requests must be taken
3315    case DCACHE_XTN_IC_INVAL_PA:        // because the XTN_ICACHE_INVAL request to icache
3316    case DCACHE_XTN_IT_INVAL:           // can generate an itlb miss...
3317    {
3318        // external coherence request
3319        if ( r_tgt_dcache_req )   
3320        {
3321            r_dcache_fsm = DCACHE_CC_CHECK;
3322            r_dcache_fsm_save = r_dcache_fsm;
3323            break;
3324        } 
3325
3326        // itlb miss request
3327        if ( r_icache_tlb_miss_req.read() )
3328        {
3329            r_dcache_tlb_ins    = true;
3330            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3331            r_dcache_fsm        = DCACHE_TLB_MISS;
3332            break;
3333        }
3334
3335        // test if XTN request to icache completed
3336        if ( not r_dcache_xtn_req.read() ) 
3337        {
3338            r_dcache_fsm = DCACHE_IDLE;
3339            m_drsp.valid = true;
3340        }
3341        break;
3342    }
3343    /////////////////////////
3344    case DCACHE_XTN_DC_FLUSH:   // Invalidate sequencially all cache lines, using
3345                                // the r_dcache_flush counter as a slot counter.
3346                                // We loop in this state until all slots have been visited.
3347                                // A cleanup request is generated for each valid line
3348                                // and we are blocked until the previous cleanup is completed
3349                                // Finally, both the itlb and dtlb are reset, because
3350                                // all TLB entries (including global entries) must be invalidated.
3351    {
3352        if ( not r_dcache_cleanup_req )
3353        {
3354            paddr_t     nline;
3355            size_t      way = r_dcache_flush_count.read()/m_icache_sets;
3356            size_t      set = r_dcache_flush_count.read()%m_icache_sets;
3357
3358            bool        cleanup_req = r_dcache.inval( way,
3359                                                      set,
3360                                                      &nline );
3361            if ( cleanup_req ) 
3362            {
3363                r_dcache_cleanup_req  = true;
3364                r_dcache_cleanup_line = nline;
3365            }
3366
3367            r_dcache_flush_count = r_dcache_flush_count.read() + 1;
3368
3369            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) )     // last slot
3370            {
3371                r_dtlb.reset();   
3372                r_itlb.reset(); 
3373                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
3374                {
3375                    r_dcache_in_tlb[line]       = false;
3376                    r_dcache_contains_ptd[line] = false;
3377                }
3378                r_dcache_fsm = DCACHE_IDLE;
3379                m_drsp.valid = true;
3380            }
3381        }
3382        break;
3383    }
3384    /////////////////////////
3385    case DCACHE_XTN_DT_INVAL:   // handling processor XTN_DTLB_INVAL request
3386    {
3387        r_dtlb.inval(r_dcache_p0_wdata.read());
3388        r_dcache_fsm        = DCACHE_IDLE;
3389        m_drsp.valid          = true;
3390        break;
3391    }
3392    ////////////////////////////
3393    case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
3394                                  // requires 3 cycles: access tlb, read cache, inval cache
3395                                  // we compute the physical address in this state
3396    {
3397        paddr_t paddr;
3398        bool    hit;
3399
3400        if ( r_mmu_mode.read() & DATA_TLB_MASK )        // dtlb activated
3401        {
3402#ifdef INSTRUMENTATION
3403m_cpt_dtlb_read++;
3404#endif
3405            hit = r_dtlb.translate( r_dcache_p0_wdata.read(),
3406                                    &paddr ); 
3407        }
3408        else                                            // dtlb not activated
3409        {
3410            paddr = (paddr_t)r_dcache_p0_wdata.read();
3411            hit   = true;
3412        }
3413
3414        if ( hit )              // tlb hit
3415        {
3416            r_dcache_p0_paddr = paddr;
3417            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_PA;
3418        }
3419        else                    // tlb miss
3420        {
3421#ifdef INSTRUMENTATION
3422m_cpt_dtlb_miss++;
3423#endif
3424            r_dcache_tlb_ins    = false;                // dtlb
3425            r_dcache_tlb_vaddr  = r_dcache_p0_wdata.read();
3426            r_dcache_fsm        = DCACHE_TLB_MISS; 
3427        } 
3428 
3429#if DEBUG_DCACHE
3430if ( m_debug_dcache_fsm )
3431{
3432    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
3433              << " / VADDR = " << r_dcache_p0_wdata.read()
3434              << " / PADDR = " << paddr << std::endl;
3435}
3436#endif
3437
3438        break;
3439    }
3440    ////////////////////////////
3441    case DCACHE_XTN_DC_INVAL_PA:  // selective cache line invalidate with physical address
3442                                  // requires 2 cycles: read cache / inval cache
3443                                  // In this state we read dcache.
3444    {
3445        uint32_t        data;
3446        size_t          way;
3447        size_t          set;
3448        size_t          word;
3449        bool            hit = r_dcache.read( r_dcache_p0_paddr.read(),
3450                                             &data,
3451                                             &way,
3452                                             &set,
3453                                             &word );
3454#ifdef INSTRUMENTATION
3455m_cpt_dcache_data_read++;
3456m_cpt_dcache_dir_read++;
3457#endif
3458        if ( hit )      // inval to be done
3459        {
3460            r_dcache_xtn_way = way;
3461            r_dcache_xtn_set = set;
3462            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
3463        }
3464        else            // miss : nothing to do
3465        {
3466            r_dcache_fsm      = DCACHE_IDLE;
3467            m_drsp.valid        = true;
3468        }
3469
3470#if DEBUG_DCACHE
3471if ( m_debug_dcache_fsm )
3472{
3473    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
3474              << " / PADDR = " << r_dcache_p0_paddr.read() << std::dec
3475              << " / HIT = " << hit
3476              << " / SET = " << set
3477              << " / WAY = " << way << std::endl;
3478}
3479#endif
3480        break;
3481    }
3482    ////////////////////////////
3483    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
3484                                  // Blocked if previous cleanup not completed
3485                                  // Test if itlb or dtlb inval is required   
3486    {
3487        if ( not r_dcache_cleanup_req.read() )
3488        {
3489            paddr_t     nline;
3490            size_t      way        = r_dcache_xtn_way.read();
3491            size_t      set        = r_dcache_xtn_set.read();
3492   
3493            r_dcache.inval( way,
3494                            set,
3495                            &nline );
3496
3497            // request cleanup
3498            r_dcache_cleanup_req  = true;
3499            r_dcache_cleanup_line = nline;
3500           
3501            // possible itlb & dtlb invalidate
3502            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3503            {
3504                r_dcache_tlb_inval_line  = nline;
3505                r_dcache_tlb_inval_count = 0;
3506                r_dcache_fsm_save        = DCACHE_XTN_DC_INVAL_END;
3507                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3508                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3509            }
3510            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3511            {
3512                r_itlb.reset();
3513                r_dtlb.reset();
3514                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3515                r_dcache_fsm = DCACHE_IDLE;
3516                m_drsp.valid = true;
3517            }
3518            else
3519            {
3520                r_dcache_fsm = DCACHE_IDLE;
3521                m_drsp.valid = true;
3522            }
3523
3524#if DEBUG_DCACHE
3525if ( m_debug_dcache_fsm )
3526{
3527    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
3528              << " / NLINE = " << nline << std::endl;
3529}
3530#endif
3531        }
3532        break;
3533    }
3534    //////////////////////////////
3535    case DCACHE_XTN_DC_INVAL_END:       // send response to processor XTN request
3536    {
3537        r_dcache_fsm = DCACHE_IDLE;
3538        m_drsp.valid = true;
3539        break;
3540    }
3541    ////////////////////////
3542    case DCACHE_MISS_VICTIM:            // Selects a victim line
3543                                        // Set the r_dcache_cleanup_req flip-flop
3544                                        // when the selected slot is not empty
3545    {
3546        bool      valid;
3547        size_t    way;
3548        size_t    set;
3549        paddr_t   victim;
3550
3551        valid = r_dcache.victim_select( r_dcache_vci_paddr.read(),
3552                                        &victim,
3553                                        &way,
3554                                        &set );
3555        r_dcache_miss_way = way;
3556        r_dcache_miss_set = set;
3557
3558        if ( valid )
3559        {
3560            r_dcache_cleanup_req  = true;
3561            r_dcache_cleanup_line = victim;
3562            r_dcache_fsm          = DCACHE_MISS_INVAL;
3563        }
3564        else
3565        {
3566            r_dcache_fsm          = DCACHE_MISS_WAIT;
3567        }
3568
3569#if DEBUG_DCACHE
3570if ( m_debug_dcache_fsm )
3571{
3572    std::cout << "  <PROC.DCACHE_MISS_VICTIM> Select a slot:"
3573              << " / way = "   << way
3574              << " / set = "   << set
3575              << " / valid = "  << valid
3576              << " / line = " << std::hex << victim << std::endl; 
3577}
3578#endif
3579        break;
3580    }
3581    ///////////////////////
3582    case DCACHE_MISS_INVAL:             // invalidate the victim line
3583                                        // and possibly request itlb or dtlb invalidate
3584    {
3585        paddr_t nline;
3586        size_t  way        = r_dcache_miss_way.read();
3587        size_t  set        = r_dcache_miss_set.read();
3588
3589        r_dcache.inval( way, 
3590                        set,
3591                        &nline );
3592
3593        // if selective itlb & dtlb invalidate are required
3594        // the miss response is not handled before invalidate completed
3595        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3596        {
3597            r_dcache_tlb_inval_line  = nline;
3598            r_dcache_tlb_inval_count = 0;
3599            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3600            r_dcache_fsm_save        = DCACHE_MISS_WAIT;
3601            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3602        }
3603        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3604        {
3605            r_itlb.reset();
3606            r_dtlb.reset();
3607            r_dcache_fsm             = DCACHE_MISS_WAIT;
3608        }
3609        else
3610        {
3611            r_dcache_fsm             = DCACHE_MISS_WAIT;
3612        }
3613        break;
3614    }
3615    //////////////////////
3616    case DCACHE_MISS_WAIT:      // waiting the response to a miss request from VCI_RSP FSM
3617                                // This state is in charge of error signaling
3618                                // There is 5 types of error depending on the requester
3619    {
3620        // external coherence request
3621        if ( r_tgt_dcache_req ) 
3622        {
3623            r_dcache_fsm = DCACHE_CC_CHECK;
3624            r_dcache_fsm_save = r_dcache_fsm;
3625            break;
3626        }
3627
3628        if ( r_vci_rsp_data_error.read() )                      // bus error
3629        {
3630            switch ( r_dcache_miss_type.read() )
3631            {
3632                case PROC_MISS: 
3633                {
3634                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS; 
3635                    r_mmu_dbvar           = r_dcache_p0_vaddr.read();
3636                    m_drsp.valid            = true;
3637                    m_drsp.error            = true;
3638                    r_dcache_fsm          = DCACHE_IDLE;
3639                    break;
3640                }
3641                case PTE1_MISS:
3642                {
3643                    if ( r_dcache_tlb_ins.read() )
3644                    {
3645                        r_mmu_ietr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3646                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3647                        r_icache_tlb_miss_req   = false;
3648                        r_icache_tlb_rsp_error  = true;
3649                    }
3650                    else
3651                    {
3652                        r_mmu_detr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3653                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3654                        m_drsp.valid              = true;
3655                        m_drsp.error              = true;
3656                    }
3657                    r_dcache_fsm                = DCACHE_IDLE;
3658                    break;
3659                }
3660                case PTE2_MISS: 
3661                {
3662                    if ( r_dcache_tlb_ins.read() )
3663                    {
3664                        r_mmu_ietr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3665                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3666                        r_icache_tlb_miss_req   = false;
3667                        r_icache_tlb_rsp_error  = true;
3668                    }
3669                    else
3670                    {
3671                        r_mmu_detr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3672                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3673                        m_drsp.valid              = true;
3674                        m_drsp.error              = true;
3675                    }
3676                    r_dcache_fsm                = DCACHE_IDLE;
3677                    break;
3678                }
3679            } // end switch type
3680            r_vci_rsp_data_error = false;
3681        }
3682        else if ( r_vci_rsp_fifo_dcache.rok() )         // valid response available
3683        {
3684            r_dcache_miss_word = 0;
3685            r_dcache_fsm       = DCACHE_MISS_UPDT;
3686        }       
3687        break;
3688    }
3689    //////////////////////
3690    case DCACHE_MISS_UPDT:      // update the dcache (one word per cycle)
3691                                // returns the response depending on the miss type
3692    {
3693        if ( r_vci_rsp_fifo_dcache.rok() )      // one word available
3694        {
3695            if ( r_dcache_miss_inval.read() )   // Matching coherence request
3696                                                // pop the FIFO, without cache update
3697                                                // send a cleanup for the missing line
3698                                                // if the previous cleanup is completed
3699            {
3700                if ( r_dcache_miss_word.read() < (m_dcache_words - 1) )     // not the last
3701                {
3702                    vci_rsp_fifo_dcache_get = true;
3703                    r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3704                }
3705                else                                                    // last word
3706                {
3707                    if ( not r_dcache_cleanup_req.read() )      // no pending cleanup
3708                    {
3709                        vci_rsp_fifo_dcache_get = true;
3710                        r_dcache_cleanup_req    = true;
3711                        r_dcache_cleanup_line   = r_dcache_vci_paddr.read() >> 
3712                                                     (uint32_log2(m_dcache_words)+2);
3713                        r_dcache_miss_inval     = false;
3714                        r_dcache_fsm            = DCACHE_IDLE;
3715                    }
3716                }
3717            }
3718            else                                // No matching coherence request
3719                                                // pop the FIFO and update the cache
3720                                                // update the directory at the last word
3721            {
3722                 size_t way  = r_dcache_miss_way.read();
3723                 size_t set  = r_dcache_miss_set.read();
3724                 size_t word = r_dcache_miss_word.read();
3725
3726#ifdef INSTRUMENTATION
3727m_cpt_dcache_data_write++;
3728#endif
3729                r_dcache.write( way,
3730                                set,
3731                                word,
3732                                r_vci_rsp_fifo_dcache.read());
3733
3734                vci_rsp_fifo_dcache_get = true;
3735                r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3736               
3737                // if last word, update directory, set in_tlb & contains_ptd bits
3738                if ( r_dcache_miss_word.read() == (m_dcache_words - 1) ) 
3739                {
3740
3741#ifdef INSTRUMENTATION
3742m_cpt_dcache_dir_write++;
3743#endif
3744                    r_dcache.victim_update_tag( r_dcache_vci_paddr.read(),
3745                                                r_dcache_miss_way.read(),
3746                                                r_dcache_miss_set.read() );
3747
3748                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3749                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3750                   
3751                    if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET; 
3752                    else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
3753                    else                                           r_dcache_fsm = DCACHE_IDLE;
3754                }
3755            }
3756
3757#if DEBUG_DCACHE
3758if ( m_debug_dcache_fsm )
3759{
3760    if ( r_dcache_miss_inval.read() )
3761    {
3762        if ( r_dcache_miss_word.read() < m_dcache_words-1 ) 
3763        {
3764            std::cout << "  <PROC.DCACHE_MISS_UPDT> Matching coherence request:"
3765                      << "  pop the FIFO, don't update the cache" << std::endl;
3766        }
3767        else
3768        {
3769            std::cout << "  <PROC.DCACHE_MISS_UPDT> Matching coherence request:"
3770                      << " last word : send a cleanup request " << std::endl;
3771        }
3772    }
3773    else
3774    {
3775        std::cout << "  <PROC.DCACHE_MISS_UPDT> Write one word:"
3776                  << " address = " << r_dcache_vci_paddr.read() 
3777                  << " / data = "  << r_vci_rsp_fifo_dcache.read()
3778                  << " / way = "   << r_dcache_miss_way.read() 
3779                  << " / set = "   << r_dcache_miss_set.read()
3780                  << " / word = "  << r_dcache_miss_word.read() << std::endl; 
3781    }
3782}
3783#endif
3784 
3785        } // end if rok
3786        break;
3787    }
3788    /////////////////////
3789    case DCACHE_UNC_WAIT:
3790    {
3791        // external coherence request
3792        if ( r_tgt_dcache_req.read() ) 
3793        {
3794            r_dcache_fsm = DCACHE_CC_CHECK;
3795            r_dcache_fsm_save = r_dcache_fsm;
3796            break;
3797        }
3798
3799        if ( r_vci_rsp_data_error.read() )      // bus error
3800        {
3801            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3802            r_mmu_dbvar          = m_dreq.addr;
3803            r_vci_rsp_data_error = false;
3804            m_drsp.error           = true;
3805            m_drsp.valid           = true;
3806            r_dcache_fsm         = DCACHE_IDLE;
3807            break;
3808        }
3809        else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
3810        {
3811            vci_rsp_fifo_dcache_get = true;     
3812            r_dcache_fsm            = DCACHE_IDLE;
3813            // we acknowledge the processor request if it has not been modified
3814            if ( m_dreq.valid and (m_dreq.addr == r_dcache_p0_vaddr.read()) )
3815            {
3816                m_drsp.valid          = true;
3817                m_drsp.rdata          = r_vci_rsp_fifo_dcache.read();
3818            }
3819        }       
3820        break;
3821    }
3822    ////////////////////
3823    case DCACHE_SC_WAIT:        // waiting VCI response after a processor SC request
3824    {
3825        // external coherence request
3826        if ( r_tgt_dcache_req.read() ) 
3827        {
3828            r_dcache_fsm = DCACHE_CC_CHECK;
3829            r_dcache_fsm_save = r_dcache_fsm;
3830            break;
3831        }
3832
3833        if ( r_vci_rsp_data_error.read() )              // bus error
3834        {
3835            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3836            r_mmu_dbvar          = m_dreq.addr;
3837            r_vci_rsp_data_error = false;
3838            m_drsp.error         = true;
3839            m_drsp.valid         = true;
3840            r_dcache_fsm         = DCACHE_IDLE;
3841            break;
3842        }
3843        else if ( r_vci_rsp_fifo_dcache.rok() )         // response available
3844        {
3845            vci_rsp_fifo_dcache_get = true;     
3846            m_drsp.valid            = true;
3847            m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
3848            r_dcache_fsm            = DCACHE_IDLE;
3849        }       
3850        break;
3851    }
3852    //////////////////////////
3853    case DCACHE_DIRTY_GET_PTE:          // This sub_fsm set the PTE Dirty bit in memory
3854                                        // before handling a processor WRITE or SC request 
3855                                        // Input argument is r_dcache_dirty_paddr
3856                                        // In this first state, we get PTE value in dcache
3857                                        // and post a SC request to CMD FSM
3858    {
3859        // get PTE in dcache
3860        uint32_t pte;
3861        size_t   way;
3862        size_t   set;
3863        size_t   word;  // unused
3864        bool     hit = r_dcache.read( r_dcache_dirty_paddr.read(),
3865                                      &pte,
3866                                      &way,
3867                                      &set,
3868                                      &word );
3869#ifdef INSTRUMENTATION
3870m_cpt_dcache_data_read++;
3871m_cpt_dcache_dir_read++;
3872#endif
3873        assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
3874
3875        // request sc transaction to CMD_FSM
3876        r_dcache_dirty_way  = way; 
3877        r_dcache_dirty_set  = set; 
3878        r_dcache_vci_sc_req = true;
3879        r_dcache_vci_paddr  = r_dcache_dirty_paddr.read();
3880        r_dcache_vci_sc_old = pte;
3881        r_dcache_vci_sc_new = pte | PTE_D_MASK;
3882        r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;
3883
3884#if DEBUG_DCACHE
3885if ( m_debug_dcache_fsm )
3886{
3887    std::cout << "  <PROC.DCACHE_DIRTY_GET_PTE> Get PTE in dcache" << std::hex
3888              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read() 
3889              << " / PTE_VALUE = " << pte << std::dec
3890              << " / CACHE_SET = " << set
3891              << " / CACHE_WAY = " << way << std::endl;
3892}
3893#endif
3894        break;
3895    }
3896    //////////////////////////
3897    case DCACHE_DIRTY_SC_WAIT:          // wait completion of SC for PTE Dirty bit
3898                                        // If the PTE update is a success, return to IDLE state.
3899                                        // If the PTE update is a failure, invalidate the cache line
3900                                        // in DCACHE and invalidate the matching TLB entries.
3901    {
3902        // external coherence request
3903        if ( r_tgt_dcache_req ) 
3904        {
3905            r_dcache_fsm = DCACHE_CC_CHECK;
3906            r_dcache_fsm_save = r_dcache_fsm;
3907            break;
3908        }
3909
3910        if ( r_vci_rsp_data_error.read() )      // bus error
3911        {
3912            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
3913            std::cout << "This should not happen in this state" << std::endl;
3914            exit(0);
3915        }
3916        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3917        {
3918            vci_rsp_fifo_dcache_get = true;
3919            if ( r_vci_rsp_fifo_dcache.read() == 0 )    // exit if dirty bit update atomic
3920            {
3921                r_dcache_fsm = DCACHE_IDLE;
3922
3923#if DEBUG_DCACHE
3924if ( m_debug_dcache_fsm )
3925{
3926    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> Dirty bit successfully set"
3927              << std::endl;
3928}
3929#endif
3930            }
3931            else                                // invalidate the cache line and TLBs
3932            {
3933                paddr_t nline;
3934                size_t  way = r_dcache_dirty_way.read();
3935                size_t  set = r_dcache_dirty_set.read();
3936
3937                r_dcache.inval( r_dcache_dirty_way.read(), 
3938                                r_dcache_dirty_set.read(),
3939                                &nline );
3940
3941                if ( r_dcache_in_tlb[way*m_dcache_sets+set] )           // contains PTE
3942                {
3943                    r_dcache_tlb_inval_line  = nline;
3944                    r_dcache_tlb_inval_count = 0;
3945                    r_dcache_fsm_save        = DCACHE_IDLE;
3946                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3947                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3948                } 
3949                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )     // contains PTD
3950                {
3951                    r_itlb.reset();
3952                    r_dtlb.reset();
3953                    r_dcache_fsm = DCACHE_IDLE;
3954                }
3955#if DEBUG_DCACHE
3956if ( m_debug_dcache_fsm )
3957{
3958    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs"
3959              << std::endl;
3960}
3961#endif
3962            }
3963        }
3964        break;
3965    }
3966    /////////////////////
3967    case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
3968                            // handling coherence requests.
3969                            // If there is a matching pending miss on the modified cache
3970                            // line this is signaled in the r_dcache_miss inval flip-flop.
3971                            // If the updated (or invalidated) cache line has copies in TLBs
3972                            // these TLB copies are invalidated.
3973                            // The return state is defined in r_dcache_fsm_save
3974    {
3975        paddr_t  paddr = r_tgt_paddr.read();
3976        paddr_t  mask = ~((m_dcache_words<<2)-1);
3977
3978
3979        if( (r_dcache_fsm_save == DCACHE_MISS_WAIT) and
3980            ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching pending miss
3981        {
3982            r_dcache_miss_inval = true;                 // signaling the match
3983            r_tgt_dcache_req    = false;                // coherence request completed
3984            r_tgt_dcache_rsp    = r_tgt_update.read();  // response required if update
3985            r_dcache_fsm        = r_dcache_fsm_save;
3986
3987#if DEBUG_DCACHE
3988if ( m_debug_dcache_fsm )
3989{
3990    std::cout << "  <PROC.DCACHE_CC_CHECK> Coherence request matching a pending miss:"
3991              << " address = " << std::hex << paddr << std::endl;
3992}
3993#endif
3994 
3995        }
3996        else                                                            // no match
3997        {
3998            uint32_t    rdata;
3999            size_t      way;
4000            size_t      set;
4001            size_t      word;
4002
4003            bool        hit = r_dcache.read(paddr,
4004                                            &rdata,     // unused
4005                                            &way, 
4006                                            &set,
4007                                            &word);     // unused
4008#ifdef INSTRUMENTATION
4009m_cpt_dcache_data_read++;
4010m_cpt_dcache_dir_read++;
4011#endif
4012            r_dcache_cc_way = way;
4013            r_dcache_cc_set = set;
4014
4015            if ( hit and r_tgt_update.read() )          // hit update
4016            {
4017                r_dcache_fsm     = DCACHE_CC_UPDT;
4018                r_dcache_cc_word = r_tgt_word_min.read();
4019            }
4020            else if ( hit and not r_tgt_update.read() ) // hit inval
4021            {
4022                r_dcache_fsm     = DCACHE_CC_INVAL;
4023            }
4024            else                                        // miss can happen
4025            {
4026                r_tgt_dcache_req = false;
4027                r_tgt_dcache_rsp = r_tgt_update.read();
4028                r_dcache_fsm     = r_dcache_fsm_save.read();
4029            }
4030
4031#if DEBUG_DCACHE
4032if ( m_debug_dcache_fsm )
4033{
4034   
4035    std::cout << "  <PROC.DCACHE_CC_CHECK> Coherence request received :"
4036              << " address = " << std::hex << paddr << std::dec;
4037    if ( hit ) 
4038    {
4039        std::cout << " / HIT" << " / way = " << way << " / set = " << set << std::endl;
4040    }
4041    else
4042    {
4043        std::cout << " / MISS" << std::endl;
4044    }
4045}
4046#endif
4047 
4048        }
4049        break;
4050    }
4051    /////////////////////
4052    case DCACHE_CC_INVAL:       // invalidate one cache line
4053                                // and test possible copies in TLBs
4054    {
4055        paddr_t nline;
4056        size_t  way        = r_dcache_cc_way.read();
4057        size_t  set        = r_dcache_cc_set.read();
4058
4059        r_dcache.inval( way, 
4060                        set,
4061                        &nline );
4062           
4063        // possible itlb & dtlb invalidate
4064        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )                   // selective inval
4065        {
4066            r_dcache_tlb_inval_line  = nline;
4067            r_dcache_tlb_inval_count = 0;
4068            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4069            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4070        }
4071        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )        // flush
4072        {
4073            r_itlb.reset();
4074            r_dtlb.reset();
4075            r_tgt_dcache_rsp = true;
4076            r_tgt_dcache_req = false;
4077            r_dcache_fsm     = r_dcache_fsm_save.read();
4078        }
4079        else                                                            // no inval
4080        {
4081            r_tgt_dcache_rsp = true;
4082            r_tgt_dcache_req = false;
4083            r_dcache_fsm     = r_dcache_fsm_save.read();
4084        }
4085
4086#if DEBUG_DCACHE
4087if ( m_debug_dcache_fsm )
4088{
4089    std::cout << "  <PROC.DCACHE_CC_INVAL> Invalidate cache line" << std::dec
4090              << " / WAY = " << way
4091              << " / SET = " << set << std::endl;
4092}
4093#endif
4094 
4095        break;
4096    }
4097    ///////////////////
4098    case DCACHE_CC_UPDT:        // write one word per cycle (from word_min to word_max)
4099                                // and test possible copies in TLBs
4100    {
4101        size_t   word       = r_dcache_cc_word.read();
4102        size_t   way        = r_dcache_cc_way.read();
4103        size_t   set        = r_dcache_cc_set.read();
4104        paddr_t  nline      = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2);
4105
4106        r_dcache.write( way,
4107                        set,
4108                        word,
4109                        r_tgt_buf[word],
4110                        r_tgt_be[word] );
4111#ifdef INSTRUMENTATION
4112m_cpt_dcache_data_write++;
4113#endif
4114        r_dcache_cc_word = word + 1;
4115
4116        if ( word == r_tgt_word_max.read() )    // last word
4117        {
4118            // possible itlb & dtlb invalidate
4119            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )               // selective inval
4120            {
4121                r_dcache_tlb_inval_line  = nline;
4122                r_dcache_tlb_inval_count = 0;
4123                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4124                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4125            }
4126            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )    // flush
4127            {
4128                r_itlb.reset();
4129                r_dtlb.reset();
4130                r_tgt_dcache_rsp = true;
4131                r_tgt_dcache_req = false;
4132                r_dcache_fsm     = r_dcache_fsm_save.read();
4133            }
4134            else                                                        // no inval
4135            {
4136                r_tgt_dcache_rsp = true;
4137                r_tgt_dcache_req = false;
4138                r_dcache_fsm     = r_dcache_fsm_save.read();
4139            }
4140        }
4141
4142#if DEBUG_DCACHE
4143if ( m_debug_dcache_fsm )
4144{
4145    std::cout << "  <PROC.DCACHE_CC_UPDT> Update one word" << std::dec
4146              << " / WAY = " << way
4147              << " / SET = " << set
4148              << " / WORD = " << word
4149              << " / VALUE = " << std::hex << r_tgt_buf[word] << std::endl;
4150}
4151#endif
4152 
4153        break;
4154    }
4155    ///////////////////////////
4156    case DCACHE_INVAL_TLB_SCAN:         // Scan sequencially all TLB entries for both ITLB & DTLB
4157                                        // It makes the assumption that (m_itlb_sets == m_dtlb_sets)
4158                                        // and (m_itlb_ways == m_dtlb_ways)
4159                                        // We enter this state when a DCACHE line is modified,
4160                                        // and there is a copy in itlb or dtlb.
4161                                        // It can be caused by:
4162                                        // - a coherence inval or updt transaction,
4163                                        // - a line inval caused by a cache miss
4164                                        // - a processor XTN inval request,
4165                                        // - a WRITE hit,
4166                                        // - a Dirty bit update failure
4167                                        // Input arguments are:
4168                                        // - r_dcache_tlb_inval_line
4169                                        // - r_dcache_tlb_inval_count
4170                                        // - r_dcache_fsm_save
4171    {
4172        paddr_t line = r_dcache_tlb_inval_line.read();                  // nline
4173        size_t  way  = r_dcache_tlb_inval_count.read()/m_itlb_sets;     // way
4174        size_t  set  = r_dcache_tlb_inval_count.read()%m_itlb_sets;     // set
4175        bool    ok;
4176
4177        ok = r_itlb.inval( line,
4178                            way,
4179                            set );
4180#if DEBUG_DCACHE
4181if ( m_debug_dcache_fsm and ok )
4182{
4183    std::cout << "  <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
4184              << " line = " << line << std::dec
4185              << " / set = " << set
4186              << " / way = " << way << std::endl;
4187    r_itlb.printTrace();
4188}
4189#endif
4190        ok = r_dtlb.inval( line,
4191                           way,
4192                           set );
4193#if DEBUG_DCACHE
4194if ( m_debug_dcache_fsm and ok )
4195{
4196    std::cout << "  <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex
4197              << " line = " << line << std::dec
4198              << " / set = " << set
4199              << " / way = " << way << std::endl;
4200    r_dtlb.printTrace();
4201}
4202#endif
4203
4204        // return to the calling state when TLB inval completed
4205        if ( r_dcache_tlb_inval_count.read() == (m_dtlb_sets*m_dtlb_ways-1) )
4206        {
4207            if ( r_tgt_dcache_req.read() ) // It's a coherence request
4208            {
4209                r_tgt_dcache_rsp    = true;
4210                r_tgt_dcache_req    = false;
4211            }
4212            r_dcache_fsm            = r_dcache_fsm_save.read();
4213        }
4214        r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1;
4215    }   
4216    } // end switch r_dcache_fsm
4217
4218    ///////////////// wbuf update //////////////////////////////////////////////////////
4219    r_wbuf.update();
4220
4221    //////////////// test processor frozen /////////////////////////////////////////////
4222    // The simulation exit if the number of consecutive frozen cycles
4223    // is larger than the m_max_frozen_cycles (constructor parameter)
4224    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )       
4225    {
4226        m_cpt_frz_cycles++;             // used for instrumentation
4227        m_cpt_stop_simulation++;        // used for debug
4228        if ( m_cpt_stop_simulation > m_max_frozen_cycles )
4229        {
4230            std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
4231                      << " stop at cycle " << m_cpt_total_cycles << std::endl
4232                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles
4233                      << std::endl;
4234            exit(1);
4235        }
4236    }
4237    else
4238    {
4239        m_cpt_stop_simulation = 0;
4240    }
4241
4242    /////////// execute one iss cycle /////////////////////////////////
4243    {
4244    uint32_t it = 0;
4245    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
4246    r_iss.executeNCycles(1, m_irsp, m_drsp, it);
4247    }
4248
4249    ////////////////////////////////////////////////////////////////////////////
4250    // The VCI_CMD FSM controls the following ressources:
4251    // - r_vci_cmd_fsm
4252    // - r_vci_cmd_min
4253    // - r_vci_cmd_max
4254    // - r_vci_cmd_cpt
4255    // - r_vci_cmd_imiss_prio
4256    // - wbuf (reset)
4257    // - r_icache_miss_req (reset)
4258    // - r_icache_unc_req (reset)
4259    // - r_dcache_vci_miss_req (reset)
4260    // - r_dcache_vci_unc_req (reset)
4261    // - r_dcache_vci_sc_req (reset)
4262    //
4263    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
4264    // There is 6 request types, with the following priorities :
4265    // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
4266    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req 
4267    // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
4268    // 4 - Instruction Uncachable : r_icache_unc_req
4269    // 5 - Data Write             : r_wbuf.rok()     
4270    // 6 - Data Store Conditionnal: r_dcache_vci_sc_req
4271    //
4272    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
4273    // and the VCI_RSP_FSM are fully desynchronized.
4274    //
4275    // VCI formats:
4276    // According to the VCI advanced specification, all read requests packets
4277    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
4278    // are one word packets.
4279    // For write burst packets, all words are in the same cache line,
4280    // and addresses must be contiguous (the BE field is 0 in case of "holes").
4281    // The sc command packet implements actually a compare-and-swap mechanism
4282    // and the packet contains two flits.
4283    ////////////////////////////////////////////////////////////////////////////////////
4284
4285    switch ( r_vci_cmd_fsm.read() ) 
4286    {
4287        //////////////
4288        case CMD_IDLE:
4289        {
4290            // r_dcache_vci_miss_req and r_icache_miss_req require both a write_buffer access
4291            // to check a possible pending write on the same cache line.
4292            // As there is only one possible access per cycle to write buffer, we implement
4293            // a round-robin priority for this access, using the r_vci_cmd_imiss_prio flip-flop.
4294
4295            size_t      wbuf_min;
4296            size_t      wbuf_max;
4297
4298            bool dcache_miss_req = r_dcache_vci_miss_req.read()
4299                 and ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
4300            bool icache_miss_req = r_icache_miss_req.read()
4301                 and ( not r_dcache_vci_miss_req.read() or r_vci_cmd_imiss_prio.read() );
4302
4303            // 1 - Data Read Miss
4304            if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
4305            {
4306                r_vci_cmd_fsm         = CMD_DATA_MISS;
4307                r_dcache_vci_miss_req = false;
4308                r_vci_cmd_imiss_prio  = true;
4309//                m_cpt_dmiss_transaction++;
4310            }
4311            // 2 - Data Read Uncachable
4312            else if ( r_dcache_vci_unc_req.read() )
4313            {
4314                r_vci_cmd_fsm        = CMD_DATA_UNC;
4315                r_dcache_vci_unc_req = false;
4316//                m_cpt_dunc_transaction++;
4317            }
4318            // 3 - Instruction Miss
4319            else if ( icache_miss_req and r_wbuf.miss(r_icache_vci_paddr.read()) )
4320            {
4321                r_vci_cmd_fsm        = CMD_INS_MISS;
4322                r_icache_miss_req    = false;
4323                r_vci_cmd_imiss_prio = false;
4324//                m_cpt_imiss_transaction++;
4325            }
4326            // 4 - Instruction Uncachable
4327            else if ( r_icache_unc_req.read() )
4328            {
4329                r_vci_cmd_fsm    = CMD_INS_UNC;
4330                r_icache_unc_req = false;
4331//                m_cpt_iunc_transaction++;
4332            }
4333            // 5 - Data Write
4334            else if ( r_wbuf.rok(&wbuf_min, &wbuf_max) )
4335            {
4336                r_vci_cmd_fsm       = CMD_DATA_WRITE;
4337                r_vci_cmd_cpt       = wbuf_min;
4338                r_vci_cmd_min       = wbuf_min;
4339                r_vci_cmd_max       = wbuf_max;
4340//                m_cpt_write_transaction++;
4341//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
4342            }
4343            // 6 - Data Store Conditionnal
4344            else if ( r_dcache_vci_sc_req.read() )
4345            {
4346                r_vci_cmd_fsm       = CMD_DATA_SC;
4347                r_dcache_vci_sc_req = false;
4348                r_vci_cmd_cpt       = 0;
4349//                m_cpt_sc_transaction++;
4350            }
4351            break;
4352        }
4353        ////////////////////
4354        case CMD_DATA_WRITE:
4355        {
4356            if ( p_vci_ini_d.cmdack.read() )
4357            {
4358//                m_conso_wbuf_read++;
4359                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4360                if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent
4361                {
4362                    r_vci_cmd_fsm = CMD_IDLE ;
4363                    r_wbuf.sent() ;
4364                }
4365            }
4366            break;
4367        }
4368        /////////////////
4369        case CMD_DATA_SC:
4370        {
4371            // The SC VCI command contains two flits
4372            if ( p_vci_ini_d.cmdack.read() )
4373            {
4374               r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4375               if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ;
4376            }
4377            break;
4378        }
4379        //////////////////
4380        case CMD_INS_MISS:
4381        case CMD_INS_UNC:
4382        case CMD_DATA_MISS:
4383        case CMD_DATA_UNC:
4384        {
4385            // all read VCI commands contain one single flit
4386            if ( p_vci_ini_d.cmdack.read() )  r_vci_cmd_fsm = CMD_IDLE;
4387            break;
4388        }
4389
4390    } // end  switch r_vci_cmd_fsm
4391
4392    //////////////////////////////////////////////////////////////////////////
4393    // The VCI_RSP FSM controls the following ressources:
4394    // - r_vci_rsp_fsm:
4395    // - r_vci_rsp_fifo_icache (push)
4396    // - r_vci_rsp_fifo_dcache (push)
4397    // - r_vci_rsp_data_error (set)
4398    // - r_vci_rsp_ins_error (set)
4399    // - r_vci_rsp_cpt
4400    //
4401    // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
4402    // simultaneous VCI transactions, this FSM uses the VCI TRDID field
4403    // to identify the transactions.
4404    //
4405    // VCI vormat:
4406    // This component checks the response packet length and accepts only
4407    // single word packets for write response packets.
4408    //
4409    // Error handling:
4410    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
4411    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
4412    // flip_flop and the error is signaled by the DCACHE FSM. 
4413    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
4414    // flip_flop and the error is signaled by the ICACHE FSM. 
4415    // In case of Cleanup Error, the simulation stops with an error message...
4416    //////////////////////////////////////////////////////////////////////////
4417
4418    switch ( r_vci_rsp_fsm.read() ) 
4419    {
4420    //////////////
4421    case RSP_IDLE:
4422    {
4423        if ( p_vci_ini_d.rspval.read() )
4424        {
4425            r_vci_rsp_cpt = 0;
4426
4427            if ( (p_vci_ini_d.rtrdid.read() >> (vci_param::T-1)) != 0 ) // Write transaction
4428            {
4429                r_vci_rsp_fsm = RSP_DATA_WRITE;
4430            }
4431            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_MISS )
4432            {
4433                r_vci_rsp_fsm = RSP_INS_MISS;
4434            }
4435            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_UNC )
4436            {
4437                r_vci_rsp_fsm = RSP_INS_UNC;
4438            }
4439            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_MISS )
4440            {
4441                r_vci_rsp_fsm = RSP_DATA_MISS;
4442            }
4443            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_UNC )
4444            {
4445                r_vci_rsp_fsm = RSP_DATA_UNC;
4446            }
4447            else
4448            {
4449                assert(false and "Unexpected VCI response");
4450            }
4451        }
4452        break;
4453    }
4454        //////////////////
4455        case RSP_INS_MISS:
4456        {
4457            if ( p_vci_ini_d.rspval.read() )
4458            {
4459                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4460                {
4461                    r_vci_rsp_ins_error = true;
4462                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4463                }
4464                else                                        // no error reported
4465                {
4466                    if ( r_vci_rsp_fifo_icache.wok() )
4467                    {
4468                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
4469                        "The VCI response packet for instruction miss is too long" );
4470
4471                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4472                        vci_rsp_fifo_icache_put       = true,
4473                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4474                        if ( p_vci_ini_d.reop.read() )
4475                        {
4476                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
4477                            "The VCI response packet for instruction miss is too short");
4478
4479                            r_vci_rsp_fsm    = RSP_IDLE;
4480                        }
4481                    }
4482                }
4483            }
4484            break;
4485        }
4486        /////////////////
4487        case RSP_INS_UNC:
4488        {
4489            if (p_vci_ini_d.rspval.read() )
4490            {
4491                assert( p_vci_ini_d.reop.read() and
4492                "illegal VCI response packet for uncachable instruction");
4493
4494                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4495                {
4496                    r_vci_rsp_ins_error = true;
4497                    r_vci_rsp_fsm = RSP_IDLE;
4498                }
4499                else                                         // no error reported
4500                {
4501                    if ( r_vci_rsp_fifo_icache.wok())
4502                    {
4503                        vci_rsp_fifo_icache_put       = true;
4504                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4505                        r_vci_rsp_fsm = RSP_IDLE;
4506                    }
4507                }
4508            }
4509            break;
4510        }
4511        ///////////////////
4512        case RSP_DATA_MISS:
4513        {
4514            if ( p_vci_ini_d.rspval.read() )
4515            {
4516                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4517                {
4518                    r_vci_rsp_data_error = true;
4519                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4520                }
4521                else                                        // no error reported
4522                {
4523                    if ( r_vci_rsp_fifo_dcache.wok() )
4524                    {
4525                        assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
4526                        "The VCI response packet for data miss is too long");
4527
4528                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4529                        vci_rsp_fifo_dcache_put       = true,
4530                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4531                        if ( p_vci_ini_d.reop.read() )
4532                        {
4533                            assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
4534                            "The VCI response packet for data miss is too short");
4535
4536                            r_vci_rsp_fsm     = RSP_IDLE;
4537                        }
4538                    }
4539                }
4540            }
4541            break;
4542        }
4543        //////////////////
4544        case RSP_DATA_UNC:
4545        {
4546            if (p_vci_ini_d.rspval.read() )
4547            {
4548                assert( p_vci_ini_d.reop.read() and
4549                "illegal VCI response packet for uncachable read data");
4550
4551                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4552                {
4553                    r_vci_rsp_data_error = true;
4554                    r_vci_rsp_fsm = RSP_IDLE;
4555                }
4556                else                                         // no error reported
4557                {
4558                    if ( r_vci_rsp_fifo_dcache.wok())
4559                    {
4560                        vci_rsp_fifo_dcache_put       = true;
4561                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4562                        r_vci_rsp_fsm = RSP_IDLE;
4563                    }
4564                }
4565            }
4566            break;
4567        }
4568        ////////////////////
4569        case RSP_DATA_WRITE:
4570        {
4571            if (p_vci_ini_d.rspval.read())
4572            {
4573                assert( p_vci_ini_d.reop.read() and
4574                "a VCI response packet must contain one flit for a write transaction");
4575
4576                r_vci_rsp_fsm = RSP_IDLE;
4577                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read() - (1<<(vci_param::T-1));
4578                bool       cacheable  = r_wbuf.completed(wbuf_index);
4579                if ( not cacheable ) r_dcache_pending_unc_write = false;
4580                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
4581            }
4582            break;
4583        }
4584    } // end switch r_vci_rsp_fsm
4585
4586    ////////////////////////////////////////////////////////////////////////////////
4587    // The CLEANUP FSM send the cleanup commands on the coherence network,
4588    // and supports simultaneous cleanup transactions, but two simultaneous
4589    // transactions mut address different cache lines.
4590    // Therefore, the line number is registered in an associative
4591    // registration buffer (Content Adressable Memory) by the CLEANUP FSM,
4592    // and the corresponding slot (identified by the VCI TRDID field) is cleared
4593    // when the cleanup transaction response is received.
4594    // It handles cleanup requests from both the DCACHE FSM & ICACHE FSM
4595    // with a round robin priority, and can support up to 4 simultaneous
4596    // cleanup transactions (4 slots in the registration buffer).
4597    // The r_dcache_cleanup_req (or r_icache_cleanup_req) flip-flops are reset
4598    // when the command has been sent.
4599    // The VCI TRDID field is used to distinguish data/instruction cleanups:
4600    // - if data cleanup        : TRDID = 2*index + 0
4601    // - if instruction cleanup : TRDID = 2*index + 1
4602    ////////////////////////////////////////////////////////////////////////////
4603
4604    switch ( r_cleanup_fsm.read() ) 
4605    {
4606        ///////////////////////
4607        case CLEANUP_DATA_IDLE:     // dcache has highest priority
4608        {
4609            size_t  index = 0;
4610            bool    ok;
4611            if ( r_dcache_cleanup_req.read() )      // dcache request
4612            {
4613                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(), 
4614                                                      &index );   
4615                if ( ok )   // successful registration
4616                {
4617                    r_cleanup_fsm   = CLEANUP_DATA_GO; 
4618                    r_cleanup_trdid = index<<1;
4619                }
4620            }
4621            else if ( r_icache_cleanup_req.read() ) // icache request
4622            {
4623                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(), 
4624                                                      &index );   
4625                if ( ok )   // successful registration
4626                {
4627                    r_cleanup_fsm   = CLEANUP_INS_GO; 
4628                    r_cleanup_trdid = (index<<1) + 1;
4629                }
4630            }
4631            break;
4632        }
4633        //////////////////////
4634        case CLEANUP_INS_IDLE:     // icache has highest priority
4635        {
4636            size_t  index = 0;
4637            bool    ok;
4638            if ( r_icache_cleanup_req.read() )      // icache request
4639            {
4640                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(),
4641                                                      &index );   
4642                if ( ok )   // successful registration
4643                {
4644                    r_cleanup_fsm   = CLEANUP_INS_GO;
4645                    r_cleanup_trdid = (index<<1) + 1;
4646                }
4647            }
4648            else if ( r_dcache_cleanup_req.read() ) // dcache request
4649            {
4650                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(),
4651                                                      &index );   
4652                if ( ok )   // successful registration
4653                {
4654                    r_cleanup_fsm   = CLEANUP_DATA_GO;
4655                    r_cleanup_trdid = index<<1;
4656                }
4657            }
4658            break;
4659        }
4660        /////////////////////
4661        case CLEANUP_DATA_GO:
4662        {
4663            if ( p_vci_ini_c.cmdack.read() )
4664            {
4665                r_dcache_cleanup_req = false;
4666                r_cleanup_fsm        = CLEANUP_INS_IDLE;
4667
4668#if DEBUG_CLEANUP
4669if ( m_debug_cleanup_fsm )
4670{
4671    std::cout << "  <PROC.CLEANUP_DATA_GO> Cleanup request for icache:" << std::hex
4672              << " address = " << (r_dcache_cleanup_line.read()*m_dcache_words*4)
4673              << " / trdid = " << r_cleanup_trdid.read() << std::endl;
4674}
4675#endif
4676            }
4677        }
4678        ////////////////////////
4679        case CLEANUP_INS_GO:
4680        {
4681            if ( p_vci_ini_c.cmdack.read() )
4682            {
4683                r_icache_cleanup_req = false;
4684                r_cleanup_fsm        = CLEANUP_DATA_IDLE;
4685
4686#if DEBUG_CLEANUP
4687if ( m_debug_cleanup_fsm )
4688{
4689    std::cout << "  <PROC.CLEANUP_INS_GO> Cleanup request for dcache:" << std::hex
4690              << " address = " << (r_icache_cleanup_line.read()*m_icache_words*4)
4691              << " / trdid = " << r_cleanup_trdid.read() << std::endl;
4692}
4693#endif
4694            }
4695        }
4696    } // end switch CLEANUP FSM
4697
4698    //////////////// Handling  cleanup responses //////////////////
4699    if ( p_vci_ini_c.rspval.read() )    // valid response
4700    {
4701        r_cleanup_buffer.cancel_index( p_vci_ini_c.rtrdid.read() >> 1);
4702    }
4703
4704    ///////////////// Response FIFOs update  //////////////////////
4705    r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get,
4706                                 vci_rsp_fifo_icache_put,
4707                                 vci_rsp_fifo_icache_data);
4708
4709    r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get,
4710                                 vci_rsp_fifo_dcache_put,
4711                                 vci_rsp_fifo_dcache_data);
4712} // end transition()
4713
4714///////////////////////
4715tmpl(void)::genMoore()
4716///////////////////////
4717{
4718    ////////////////////////////////////////////////////////////////
4719    // VCI initiator command on the coherence network (cleanup)
4720    // it depends on the CLEANUP FSM state
4721
4722    paddr_t  address;
4723
4724    if ( r_cleanup_fsm.read() == CLEANUP_DATA_GO )
4725        address = r_dcache_cleanup_line.read()*m_dcache_words*4;
4726    else if ( r_cleanup_fsm.read() == CLEANUP_INS_GO )
4727        address = r_icache_cleanup_line.read()*m_icache_words*4;
4728    else
4729        address = 0;
4730
4731    p_vci_ini_c.cmdval  = ((r_cleanup_fsm.read() == CLEANUP_DATA_GO) or
4732                           (r_cleanup_fsm.read() == CLEANUP_INS_GO) );
4733    p_vci_ini_c.address = address;
4734    p_vci_ini_c.wdata   = 0;
4735    p_vci_ini_c.be      = 0xF;
4736    p_vci_ini_c.plen    = 4;
4737    p_vci_ini_c.cmd     = vci_param::CMD_WRITE;
4738    p_vci_ini_c.trdid   = r_cleanup_trdid.read();
4739    p_vci_ini_c.pktid   = 0;
4740    p_vci_ini_c.srcid   = m_srcid_c;
4741    p_vci_ini_c.cons    = false;
4742    p_vci_ini_c.wrap    = false;
4743    p_vci_ini_c.contig  = false;
4744    p_vci_ini_c.clen    = 0;
4745    p_vci_ini_c.cfixed  = false;
4746    p_vci_ini_c.eop     = true;
4747
4748    /////////////////////////////////////////////////////////////////
4749    // VCI initiator response on the coherence network (cleanup)
4750    // We always consume the response, and we don't use it.
4751
4752    p_vci_ini_c.rspack  = true;
4753
4754    /////////////////////////////////////////////////////////////////
4755    // VCI initiator command on the direct network
4756    // it depends on the CMD FSM state
4757
4758    p_vci_ini_d.pktid  = 0;
4759    p_vci_ini_d.srcid  = m_srcid_d;
4760    p_vci_ini_d.cons   = (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4761    p_vci_ini_d.contig = not (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4762    p_vci_ini_d.wrap   = false;
4763    p_vci_ini_d.clen   = 0;
4764    p_vci_ini_d.cfixed = false;
4765
4766    switch ( r_vci_cmd_fsm.read() ) {
4767
4768    case CMD_IDLE:
4769        p_vci_ini_d.cmdval  = false;
4770        p_vci_ini_d.address = 0;
4771        p_vci_ini_d.wdata   = 0;
4772        p_vci_ini_d.be      = 0;
4773        p_vci_ini_d.trdid   = 0;
4774        p_vci_ini_d.plen    = 0;
4775        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
4776        p_vci_ini_d.eop     = false;
4777        break;
4778
4779    case CMD_INS_MISS:
4780        p_vci_ini_d.cmdval  = true;
4781        p_vci_ini_d.address = r_icache_vci_paddr.read() & m_icache_yzmask;
4782        p_vci_ini_d.wdata   = 0;
4783        p_vci_ini_d.be      = 0xF;
4784        p_vci_ini_d.trdid   = TYPE_INS_MISS;
4785        p_vci_ini_d.plen    = m_icache_words<<2;
4786        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4787        p_vci_ini_d.eop     = true;
4788        break;
4789
4790    case CMD_INS_UNC:
4791        p_vci_ini_d.cmdval  = true;
4792        p_vci_ini_d.address = r_icache_vci_paddr.read() & ~0x3;
4793        p_vci_ini_d.wdata   = 0;
4794        p_vci_ini_d.be      = 0xF;
4795        p_vci_ini_d.trdid   = TYPE_INS_UNC;
4796        p_vci_ini_d.plen    = 4;
4797        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4798        p_vci_ini_d.eop     = true;
4799        break;
4800
4801    case CMD_DATA_MISS:
4802        p_vci_ini_d.cmdval  = true;
4803        p_vci_ini_d.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
4804        p_vci_ini_d.wdata   = 0;
4805        p_vci_ini_d.be      = 0xF;
4806        p_vci_ini_d.trdid   = TYPE_DATA_MISS;
4807        p_vci_ini_d.plen    = m_dcache_words << 2;
4808        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4809        p_vci_ini_d.eop     = true;
4810        break;
4811
4812    case CMD_DATA_UNC:
4813        p_vci_ini_d.cmdval  = true;
4814        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4815        p_vci_ini_d.wdata   = 0;
4816        p_vci_ini_d.be      = r_dcache_vci_unc_be.read();
4817        p_vci_ini_d.trdid   = TYPE_DATA_UNC;
4818        p_vci_ini_d.plen    = 4;
4819        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4820        p_vci_ini_d.eop     = true;
4821        break;
4822
4823    case CMD_DATA_WRITE:
4824        p_vci_ini_d.cmdval  = true;
4825        p_vci_ini_d.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
4826        p_vci_ini_d.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
4827        p_vci_ini_d.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
4828        p_vci_ini_d.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
4829        p_vci_ini_d.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
4830        p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
4831        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
4832        break;
4833
4834    case CMD_DATA_SC:
4835        p_vci_ini_d.cmdval  = true;
4836        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4837        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_sc_old.read();
4838        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_new.read();
4839        p_vci_ini_d.be      = 0xF;
4840        p_vci_ini_d.trdid   = TYPE_DATA_UNC; 
4841        p_vci_ini_d.plen    = 8;
4842        p_vci_ini_d.cmd     = vci_param::CMD_STORE_COND;
4843        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
4844        break;     
4845    } // end switch r_vci_cmd_fsm
4846
4847    //////////////////////////////////////////////////////////
4848    // VCI initiator response on the direct network
4849    // it depends on the VCI RSP state
4850
4851    switch (r_vci_rsp_fsm.read() )
4852    {
4853        case RSP_DATA_WRITE : p_vci_ini_d.rspack = true; break;
4854        case RSP_INS_MISS   : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4855        case RSP_INS_UNC    : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4856        case RSP_DATA_MISS  : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4857        case RSP_DATA_UNC   : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4858        case RSP_IDLE       : p_vci_ini_d.rspack = false; break;
4859    } // end switch r_vci_rsp_fsm
4860
4861    ////////////////////////////////////////////////////////////////
4862    // VCI target command and response on the coherence network
4863    switch ( r_tgt_fsm.read() ) 
4864    {
4865    case TGT_IDLE:
4866    case TGT_UPDT_WORD:
4867    case TGT_UPDT_DATA:
4868        p_vci_tgt_c.cmdack  = true;
4869        p_vci_tgt_c.rspval  = false;
4870        break;
4871
4872    case TGT_RSP_BROADCAST:
4873        p_vci_tgt_c.cmdack  = false;
4874        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read()
4875                              and ( r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read() );
4876        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4877        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4878        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4879        p_vci_tgt_c.rdata   = 0;
4880        p_vci_tgt_c.rerror  = 0;
4881        p_vci_tgt_c.reop    = true;
4882        break;
4883
4884    case TGT_RSP_ICACHE:
4885        p_vci_tgt_c.cmdack  = false;
4886        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
4887        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4888        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4889        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4890        p_vci_tgt_c.rdata   = 0;
4891        p_vci_tgt_c.rerror  = 0;
4892        p_vci_tgt_c.reop    = true;
4893        break;
4894
4895    case TGT_RSP_DCACHE:
4896        p_vci_tgt_c.cmdack  = false;
4897        p_vci_tgt_c.rspval  = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read();
4898        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4899        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4900        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4901        p_vci_tgt_c.rdata   = 0;
4902        p_vci_tgt_c.rerror  = 0;
4903        p_vci_tgt_c.reop    = true;
4904        break;
4905
4906    case TGT_REQ_BROADCAST:
4907    case TGT_REQ_ICACHE:
4908    case TGT_REQ_DCACHE:
4909        p_vci_tgt_c.cmdack  = false;
4910        p_vci_tgt_c.rspval  = false;
4911        break;
4912
4913    } // end switch TGT_FSM
4914} // end genMoore
4915
4916}}
4917
4918// Local Variables:
4919// tab-width: 4
4920// c-basic-offset: 4
4921// c-file-offsets:((innamespace . 0)(inline-open . 0))
4922// indent-tabs-mode: nil
4923// End:
4924
4925// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
Note: See TracBrowser for help on using the repository browser.