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

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

cache_monitor(): monitor the icache as well as the dcache
Add missing break for CLEANUP_INS_GO and CLEANUP_DATA_GO (this cause
the INS cleanup to be missed if one occurs one cycle after a DATA cleanup
is being sent)

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