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

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

DCACHE_DIRTY_SC_WAIT: when the SC fails, send a cleanup as we invalidate the
data in the dcache.
while there, add assert() that the line we invalidate is really in the
cache at various places.

File size: 187.1 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            bool hit;
1612            hit = r_icache.inval( r_icache_miss_way.read(),
1613                                  r_icache_miss_set.read(),
1614                                  &nline );
1615            assert(hit && "XTN_ICACHE_INVAL way/set should still be in icache");
1616 
1617            // request cleanup
1618            r_icache_cleanup_req  = true;
1619            r_icache_cleanup_line = nline;
1620            // acknowledge the XTN request and return
1621            r_dcache_xtn_req      = false; 
1622            r_icache_fsm          = ICACHE_IDLE;
1623        }
1624        break;
1625    }
1626
1627    ////////////////////////
1628    case ICACHE_MISS_VICTIM:               // Selects a victim line
1629                                           // Set the r_icache_cleanup_req flip-flop
1630                                           // when the selected slot is not empty
1631    {
1632        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1633
1634        bool    valid;
1635        size_t  way;
1636        size_t  set;
1637        paddr_t victim;
1638
1639        valid = r_icache.victim_select(r_icache_vci_paddr.read(),
1640                                       &victim, 
1641                                       &way, 
1642                                       &set);
1643        r_icache_miss_way     = way;
1644        r_icache_miss_set     = set;
1645
1646        if ( valid )
1647        {
1648            r_icache_cleanup_req  = true;
1649            r_icache_cleanup_line = victim;
1650            r_icache_fsm          = ICACHE_MISS_INVAL;
1651        }
1652        else
1653        {
1654            r_icache_fsm          = ICACHE_MISS_WAIT;
1655        }
1656        break;
1657    }
1658    ///////////////////////
1659    case ICACHE_MISS_INVAL:     // invalidate the victim line
1660    {
1661        paddr_t nline;
1662        bool hit;
1663
1664        hit = r_icache.inval( r_icache_miss_way.read(),
1665                        r_icache_miss_set.read(),
1666                        &nline );       // unused
1667        assert(hit && "selected way/set line should be in icache");
1668
1669        r_icache_fsm = ICACHE_MISS_WAIT;
1670        break;
1671    }
1672    //////////////////////
1673    case ICACHE_MISS_WAIT:      // waiting a response to a miss request from VCI_RSP FSM
1674    {
1675        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1676
1677        // external coherence request
1678        if ( r_tgt_icache_req.read() )     
1679        {
1680            r_icache_fsm = ICACHE_CC_CHECK;
1681            r_icache_fsm_save = r_icache_fsm.read();
1682            break;
1683        }
1684
1685        if ( r_vci_rsp_ins_error.read() ) // bus error
1686        {
1687            r_mmu_ietr = MMU_READ_DATA_ILLEGAL_ACCESS; 
1688            r_mmu_ibvar  = r_icache_vaddr_save.read();
1689            m_irsp.valid           = true;
1690            m_irsp.error           = true;
1691            r_vci_rsp_ins_error  = false;
1692            r_icache_fsm = ICACHE_IDLE;
1693        }
1694        else if ( r_vci_rsp_fifo_icache.rok() ) // response available
1695        {
1696            r_icache_miss_word = 0;
1697            r_icache_fsm       = ICACHE_MISS_UPDT; 
1698        }       
1699        break;
1700    }
1701    //////////////////////
1702    case ICACHE_MISS_UPDT:      // update the cache (one word per cycle)
1703    {
1704        if ( m_ireq.valid ) m_cost_ins_miss_frz++;
1705
1706        if ( r_vci_rsp_fifo_icache.rok() )      // response available
1707        {
1708            if ( r_icache_miss_inval )  // Matching coherence request
1709                                        // We pop the response FIFO, without updating the cache
1710                                        // We send a cleanup for the missing line at the last word
1711                                        // Blocked if the previous cleanup is not completed
1712            {
1713                if ( r_icache_miss_word.read() < m_icache_words-1 )     // not the last word
1714                {
1715                    vci_rsp_fifo_icache_get = true;
1716                    r_icache_miss_word = r_icache_miss_word.read() + 1;
1717                }
1718                else                                                    // last word
1719                {
1720                    if ( not r_icache_cleanup_req.read() )      // no pending cleanup
1721                    {
1722                        vci_rsp_fifo_icache_get = true;
1723                        r_icache_cleanup_req    = true;
1724                        r_icache_cleanup_line   = r_icache_vci_paddr.read() >> (uint32_log2(m_icache_words<<2));
1725                        r_icache_miss_inval     = false;
1726                        r_icache_fsm            = ICACHE_IDLE;
1727                    }
1728                }
1729            }
1730            else                        // No matching coherence request
1731                                        // We pop the FIFO and update the cache
1732                                        // We update the directory at the last word
1733            {
1734
1735#ifdef INSTRUMENTATION
1736m_cpt_icache_data_write++;
1737#endif
1738                r_icache.write( r_icache_miss_way.read(),
1739                                r_icache_miss_set.read(),
1740                                r_icache_miss_word.read(),
1741                                r_vci_rsp_fifo_icache.read() );
1742                vci_rsp_fifo_icache_get = true;
1743                r_icache_miss_word = r_icache_miss_word.read() + 1;
1744                if ( r_icache_miss_word.read() == m_icache_words-1 )  // last word
1745                {
1746
1747#ifdef INSTRUMENTATION
1748m_cpt_icache_dir_write++;
1749#endif
1750                    r_icache.victim_update_tag( r_icache_vci_paddr.read(),
1751                                                r_icache_miss_way.read(),
1752                                                r_icache_miss_set.read() );
1753                    r_icache_fsm = ICACHE_IDLE;
1754                }
1755            }
1756        }
1757        break;
1758    }
1759    ////////////////////
1760    case ICACHE_UNC_WAIT:       // waiting a response to an uncacheable read from VCI_RSP FSM
1761                                //
1762    {
1763        // external coherence request
1764        if ( r_tgt_icache_req.read() ) 
1765        {
1766            r_icache_fsm = ICACHE_CC_CHECK;
1767            r_icache_fsm_save = r_icache_fsm.read();
1768            break;
1769        }
1770
1771        if ( r_vci_rsp_ins_error.read() ) // bus error
1772        {
1773            r_mmu_ietr          = MMU_READ_DATA_ILLEGAL_ACCESS;   
1774            r_mmu_ibvar         = m_ireq.addr;
1775            r_vci_rsp_ins_error = false;
1776            m_irsp.valid          = true;
1777            m_irsp.error          = true;
1778            r_icache_fsm        = ICACHE_IDLE;
1779        }
1780        else if (r_vci_rsp_fifo_icache.rok() ) // instruction available
1781        {
1782            vci_rsp_fifo_icache_get = true;
1783            r_icache_fsm            = ICACHE_IDLE;
1784            if ( m_ireq.valid and (m_ireq.addr == r_icache_vaddr_save.read()) )  // request not modified
1785            {
1786                m_irsp.valid       = true;
1787                m_irsp.instruction = r_vci_rsp_fifo_icache.read();
1788            }
1789        }       
1790        break;
1791    }
1792    /////////////////////
1793    case ICACHE_CC_CHECK:       // This state is the entry point of a sub-fsm
1794                                // handling coherence requests.
1795                                // the return state is defined in r_icache_fsm_save.
1796    {
1797        paddr_t  paddr = r_tgt_paddr.read();
1798        paddr_t  mask  = ~((m_icache_words<<2)-1);
1799
1800        if( (r_icache_fsm_save.read() == ICACHE_MISS_WAIT) and
1801                ((r_icache_vci_paddr.read() & mask) == (paddr & mask)))         // matching a pending miss
1802        {
1803            r_icache_miss_inval = true;                         // signaling the matching
1804            r_tgt_icache_req    = false;                        // coherence request completed
1805            r_tgt_icache_rsp    = r_tgt_update.read();          // response required if update
1806            r_icache_fsm        = r_icache_fsm_save.read();
1807        }
1808        else                                                            // no match
1809        {
1810
1811#ifdef INSTRUMENTATION
1812m_cpt_icache_dir_read++;
1813#endif
1814            uint32_t    inst;
1815            size_t      way;
1816            size_t      set;
1817            size_t      word;
1818            bool        hit = r_icache.read(paddr, 
1819                                            &inst,
1820                                            &way, 
1821                                            &set, 
1822                                            &word);
1823            r_icache_cc_way = way;
1824            r_icache_cc_set = set;
1825
1826            if ( hit and r_tgt_update.read() )           // hit update
1827            {
1828                r_icache_fsm         = ICACHE_CC_UPDT;
1829                r_icache_cc_word     = r_tgt_word_min.read();
1830            }
1831            else if ( hit and not r_tgt_update.read() )  // hit inval
1832            {
1833                r_icache_fsm           = ICACHE_CC_INVAL;
1834            }
1835            else                                         // miss can happen
1836            {
1837                r_tgt_icache_req = false;
1838                r_tgt_icache_rsp = r_tgt_update.read();
1839                r_icache_fsm     = r_icache_fsm_save.read();
1840            }
1841        }
1842        break;
1843    }
1844
1845    /////////////////////
1846    case ICACHE_CC_INVAL:       // invalidate a cache line
1847    {                       
1848        paddr_t nline;
1849        bool hit;
1850        hit = r_icache.inval( r_icache_cc_way.read(),
1851                              r_icache_cc_set.read(), 
1852                              &nline );
1853        assert (hit && "ICACHE_CC_INVAL way/set should still be in icache");
1854        r_tgt_icache_req = false;
1855        r_tgt_icache_rsp = true;
1856        r_icache_fsm     = r_icache_fsm_save.read();
1857        break;
1858    }
1859    ////////////////////
1860    case ICACHE_CC_UPDT:        // write one word per cycle (from word_min to word_max)
1861    {
1862        size_t  word  = r_icache_cc_word.read();
1863        size_t  way   = r_icache_cc_way.read();
1864        size_t  set   = r_icache_cc_set.read();
1865
1866        r_icache.write( way,
1867                        set,
1868                        word,
1869                        r_tgt_buf[word],
1870                        r_tgt_be[word] );
1871
1872        r_icache_cc_word = word+1;
1873
1874        if ( word == r_tgt_word_max.read() )    // last word
1875        {
1876            r_tgt_icache_req = false;
1877            r_tgt_icache_rsp = true;
1878            r_icache_fsm     = r_icache_fsm_save.read();
1879        }
1880        break;
1881    }
1882
1883    } // end switch r_icache_fsm
1884
1885    ////////////////////////////////////////////////////////////////////////////////////
1886    //      DCACHE FSM
1887    //
1888    // Both the Cacheability Table, and the MMU cacheable bit are used to define
1889    // the cacheability, depending on the MMU mode.
1890    //
1891    // 1/ Coherence requests :
1892    //    There is a coherence request when the tgt_dcache_req flip-flop is set,
1893    //    requesting a line invalidation or a line update.
1894    //    Coherence requests are taken into account in IDLE, UNC_WAIT, MISS_WAIT states.
1895    //    The actions associated to the pre-empted state are not executed, the DCACHE FSM
1896    //    goes to the CC_CHECK state to execute the requested action, and returns to the
1897    //    pre-empted state.
1898    //
1899    // 2/ TLB miss
1900    //    The page tables can be cacheable.
1901    //    In case of miss in itlb or dtlb, the tlb miss is handled by a dedicated
1902    //    sub-fsm (DCACHE_TLB_MISS state), that handle possible miss in DCACHE,
1903    //    this sub-fsm implement the table-walk...
1904    //
1905    // 3/ processor requests :
1906    //    Processor READ, WRITE, LL or SC requests are taken in IDLE state only.
1907    //    The IDLE state implements a three stages pipe-line to handle write bursts:
1908    //    - The physical address is computed by dtlb in stage P0.
1909    //    - The registration in wbuf and the dcache hit are computed in stage P1.
1910    //    - The dcache update is done in stage P2. 
1911    //    WRITE or SC requests can require a PTE Dirty bit update (in memory),
1912    //    that is done (before handling the processor request) by a dedicated sub-fsm
1913    //    (DCACHE_DIRTY_TLB_SET state).
1914    //    If a PTE is modified, both the itlb and dtlb are selectively, but sequencially
1915    //    cleared by a dedicated sub_fsm (DCACHE_INVAL_TLB_SCAN state).
1916    //    If there is no write in the pipe, dcache and dtlb are accessed in parallel,
1917    //    (virtual address for itlb, and speculative physical address computed during
1918    //    previous cycle for dcache) in order to return the data in one cycle for a READ
1919    //    request. We just pay an extra cycle when the speculative access is failing.
1920    //
1921    // 4/ Atomic instructions LL/SC
1922    //    The LL/SC address can be cacheable or non cacheable.
1923    //    The reservation registers (r_dcache_ll_valid, r_dcache_ll_vaddr and
1924    //    r_dcache_ll_data are stored in the L1 cache controller, and not in the
1925    //    memory controller.
1926    //    - LL requests from the processor are transmitted as standard VCI
1927    //      READ transactions (one word / one line, depending on the cacheability).
1928    //    - SC requests from the processor are systematically transmitted to the
1929    //      memory cache as Compare&swap requests (both the data value stored in the
1930    //      r_dcache_ll_data register and the new value).
1931    //      The cache is not updated, as this is done in case of success by the
1932    //      coherence transaction.
1933    //
1934    // 5/ Non cacheable access:
1935    //    This component implement a strong order between non cacheable access
1936    //    (read or write) : A new non cacheable VCI transaction starts only when
1937    //    the previous non cacheable transaction is completed. Both cacheable and
1938    //    non cacheable transactions use the write buffer, but the DCACHE FSM registers
1939    //    a non cacheable write transaction posted in the write buffer by setting the
1940    //    r_dcache_pending_unc_write flip_flop. All other non cacheable requests
1941    //    are stalled until this flip-flop is reset by the VCI_RSP_FSM (when the
1942    //    pending non cacheable write transaction completes).
1943    //
1944    // 6/ Error handling: 
1945    //    When the MMU is not activated, Read Bus Errors are synchronous events,
1946    //    but Write Bus Errors are asynchronous events (processor is not frozen).
1947    //    - If a Read Bus Error is detected, the VCI_RSP FSM sets the
1948    //      r_vci_rsp_data_error flip-flop, without writing any data in the
1949    //      r_vci_rsp_fifo_dcache FIFO, and the synchronous error is signaled
1950    //      by the DCACHE FSM.
1951    //    - If a Write Bus Error is detected, the VCI_RSP FSM  signals
1952    //      the asynchronous error using the setWriteBerr() method.
1953    //    When the MMU is activated bus error are rare events, as the MMU
1954    //    checks the physical address before the VCI transaction starts.
1955    ////////////////////////////////////////////////////////////////////////////////////////
1956
1957    // default value for m_drsp
1958    m_drsp.valid = false;
1959    m_drsp.error = false;
1960    m_drsp.rdata = 0;
1961
1962    switch ( r_dcache_fsm.read() ) 
1963    {
1964    case DCACHE_IDLE:   // There is 8 conditions to exit the IDLE state :
1965                        // 1) Dirty bit update (processor)      => DCACHE_DIRTY_GET_PTE
1966                        // 2) Coherence request (TGT FSM)       => DCACHE_CC_CHECK
1967                        // 3) ITLB miss request (ICACHE FSM)    => DCACHE_TLB_MISS
1968                        // 4) XTN request (processor)           => DCACHE_XTN_*
1969                        // 5) DTLB miss (processor)             => DCACHE_TLB_MISS
1970                        // 6) Cacheable read miss (processor)   => DCACHE_MISS_VICTIM
1971                        // 7) Uncacheable read (processor)      => DCACHE_UNC_WAIT
1972                        // 8) SC access (processor)             => DCACHE_SC_WAIT
1973                        //
1974                        // The dtlb is unconditionally accessed to translate the
1975                        // virtual adress from processor.
1976                        //
1977                        // There is 4 configurations to access the cache,
1978                        // depending on the pipe-line state, defined
1979                        // by the r_dcache_p0_valid (V0) flip-flop : P1 stage activated
1980                        // and    r_dcache_p1_valid (V1) flip-flop : P2 stage activated
1981                        //  V0 / V1 / Data      / Directory / comment                   
1982                        //  0  / 0  / read(A0)  / read(A0)  / read speculative access 
1983                        //  0  / 1  / write(A2) / nop       / read request delayed
1984                        //  1  / 0  / nop       / read(A1)  / read request delayed
1985                        //  1  / 1  / write(A2) / read(A1)  / read request delayed
1986    { 
1987        ////////////////////////////////////////////////////////////////////////////////
1988        // Handling P2 pipe-line stage
1989        // Inputs are r_dcache_p1_* registers.
1990        // If r_dcache_p1_valid is true, we update the local copy in dcache.
1991        // If the modified cache line has copies in TLBs, we launch a TLB invalidate
1992        // operation, going to DCACHE_INVAL_TLB_SCAN state.
1993
1994        bool tlb_inval_required = false;
1995
1996        if ( r_dcache_p1_valid.read() )         // P2 stage activated
1997        {
1998            size_t   way        = r_dcache_p1_cache_way.read();
1999            size_t   set        = r_dcache_p1_cache_set.read();
2000            size_t   word       = r_dcache_p1_cache_word.read();
2001            uint32_t wdata      = r_dcache_p1_wdata.read();
2002            vci_be_t be         = r_dcache_p1_be.read();
2003
2004            r_dcache.write( way,
2005                            set,
2006                            word,
2007                            wdata,
2008                            be );
2009#ifdef INSTRUMENTATION
2010m_cpt_dcache_data_write++; 
2011#endif
2012            // cache update after a WRITE hit can require itlb & dtlb inval or flush
2013            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )
2014            {
2015                tlb_inval_required       = true;
2016                r_dcache_tlb_inval_count = 0;
2017                r_dcache_tlb_inval_line  = r_dcache_p1_paddr.read()>>(uint32_log2(m_dcache_words<<2)); 
2018                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
2019            }
2020            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )
2021            {
2022                r_itlb.reset();
2023                r_dtlb.reset();
2024                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
2025            }
2026
2027#if DEBUG_DCACHE
2028if ( m_debug_dcache_fsm )
2029{
2030    std::cout << "  <PROC.DCACHE_IDLE> Cache update in P2 stage" << std::dec
2031              << " / WAY = " << way
2032              << " / SET = " << set
2033              << " / WORD = " << word << std::hex
2034              << " / DATA = " << wdata
2035              << " / BE = " << be << std::endl;
2036}
2037#endif
2038        } // end P2 stage
2039
2040        ///////////////////////////////////////////////////////////////////////////
2041        // Handling P1 pipe-line stage
2042        // Inputs are r_dcache_p0_* registers.
2043        // We must write into wbuf and test the hit in dcache.
2044        // If the write request is non cacheable, and there is a pending
2045        // non cacheable write, or if the write buffer is full, we break,
2046        // because the P0 and P1 pipe-line stages are frozen until the write
2047        // request registration is possible, but he P2 stage is not frozen.
2048        // The r_dcache_p1_valid bit must be computed at all cycles, and
2049        // the P2 stage must be activated if there is local copy in dcache.
2050
2051        if ( r_dcache_p0_valid.read() )  // P1 stage activated
2052        {
2053            // write not cacheable, and previous non cacheable write registered
2054            if ( not r_dcache_p0_cacheable.read() and r_dcache_pending_unc_write.read() ) 
2055            {
2056                r_dcache_p1_valid = false;
2057                break;
2058            }
2059
2060            // try a registration into write buffer
2061            bool wok = r_wbuf.write( r_dcache_p0_paddr.read(),
2062                                     r_dcache_p0_be.read(),
2063                                     r_dcache_p0_wdata.read(),
2064                                     r_dcache_p0_cacheable.read() );
2065#ifdef INSTRUMENTATION
2066m_cpt_wbuf_write++;
2067#endif
2068            // write buffer full
2069            if ( not wok ) 
2070            {
2071                r_dcache_p1_valid = false;
2072                break; 
2073            }
2074            // update the write_buffer state extension
2075            r_dcache_pending_unc_write = not r_dcache_p0_cacheable.read();
2076
2077            // read directory to check local copy
2078            size_t  cache_way;
2079            size_t  cache_set;
2080            size_t  cache_word;
2081            bool    local_copy;
2082            if ( r_mmu_mode.read() & DATA_CACHE_MASK)   // cache activated
2083            {
2084                local_copy = r_dcache.hit( r_dcache_p0_paddr.read(),
2085                                           &cache_way,
2086                                           &cache_set,
2087                                           &cache_word );
2088#ifdef INSTRUMENTATION
2089m_cpt_dcache_dir_read++; 
2090#endif
2091            }
2092            else
2093            {
2094                local_copy = false;
2095            }
2096
2097            // store values for P2 pipe stage
2098            if ( local_copy )
2099            {
2100                r_dcache_p1_valid       = true;
2101                r_dcache_p1_wdata       = r_dcache_p0_wdata.read();
2102                r_dcache_p1_be          = r_dcache_p0_be.read();
2103                r_dcache_p1_paddr       = r_dcache_p0_paddr.read();
2104                r_dcache_p1_cache_way   = cache_way;
2105                r_dcache_p1_cache_set   = cache_set;
2106                r_dcache_p1_cache_word  = cache_word;
2107            }
2108            else
2109            {
2110                r_dcache_p1_valid       = false;
2111            }
2112        }
2113        else                            // P1 stage not activated
2114        {
2115            r_dcache_p1_valid = false; 
2116        } // end P1 stage
2117
2118        /////////////////////////////////////////////////////////////////////////////////
2119        // handling P0 pipe-line stage
2120        // This stage is controlling r_dcache_fsm and r_dcache_p0_* registers.
2121        // The r_dcache_p0_valid flip-flop is only set in case of a WRITE request.
2122        // - the TLB invalidate requests have the highest priority,
2123        // - then the external coherence requests,
2124        // - then the itlb miss requests,
2125        // - and finally the processor requests.
2126        // If dtlb is activated, there is an unconditionnal access to dtlb,
2127        // for address translation.
2128        // 1) A processor WRITE request is blocked if the Dirty bit mus be set, or if
2129        //    dtlb miss. If dtlb is OK, It enters the three stage pipe-line (fully
2130        //    handled by the IDLE state), and the processor request is acknowledged.
2131        // 2) A processor READ or LL request generate a simultaneouss access to
2132        //    both dcache data and dcache directoty, using speculative PPN, but
2133        //    is delayed if the write pipe-line is not empty.
2134        //    In case of miss, we wait the VCI response in DCACHE_UNC_WAIT or
2135        //    DCACHE_MISS_WAIT states.
2136        // 3) A processor SC request is delayed until the write pipe-line is empty.
2137        //    A VCI SC transaction is launched, and we wait the VCI response in
2138        //    DCACHE_SC_WAIT state. It can be completed by a "long write" if the
2139        //    PTE dirty bit must be updated in dtlb, dcache, and RAM.
2140        //    The data is not modified in dcache, as it will be done by the
2141        //    coherence transaction.   
2142
2143        // TLB inval required
2144        if ( tlb_inval_required )
2145        {
2146            r_dcache_fsm_save = DCACHE_IDLE;
2147            r_dcache_fsm      = DCACHE_INVAL_TLB_SCAN;
2148            r_dcache_p0_valid = false;
2149        }
2150        // external coherence request
2151        else if ( r_tgt_dcache_req.read() )   
2152        {
2153            r_dcache_fsm_save = DCACHE_IDLE;
2154            r_dcache_fsm      = DCACHE_CC_CHECK;
2155            r_dcache_p0_valid = false;
2156        }       
2157
2158        // itlb miss request
2159        else if ( r_icache_tlb_miss_req.read() )
2160        {
2161            r_dcache_tlb_ins    = true;
2162            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
2163            r_dcache_fsm        = DCACHE_TLB_MISS;
2164            r_dcache_p0_valid = false;
2165        }
2166
2167        // processor request
2168        else if ( m_dreq.valid )
2169        {
2170            // dcache access using speculative PPN only if pipe-line empty
2171            paddr_t     cache_paddr;
2172            size_t      cache_way;
2173            size_t      cache_set;
2174            size_t      cache_word;
2175            uint32_t    cache_rdata;
2176            bool        cache_hit;
2177
2178            if ( (r_mmu_mode.read() & DATA_CACHE_MASK) and      // cache activated
2179                 not r_dcache_p0_valid.read() and
2180                 not r_dcache_p1_valid.read() )                 // pipe-line empty
2181            {
2182                cache_paddr = (r_dcache_p0_paddr.read() & ~PAGE_K_MASK) | 
2183                              ((paddr_t)m_dreq.addr & PAGE_K_MASK);
2184
2185                cache_hit = r_dcache.read( cache_paddr,
2186                                           &cache_rdata,
2187                                           &cache_way,
2188                                           &cache_set,
2189                                           &cache_word );
2190#ifdef INSTRUMENTATION
2191m_cpt_dcache_dir_read++;
2192m_cpt_dcache_data_read++;
2193#endif
2194            }
2195            else
2196            {
2197                cache_hit = false;
2198            } // end dcache access   
2199
2200            // systematic dtlb access using virtual address
2201            paddr_t     tlb_paddr;
2202            pte_info_t  tlb_flags; 
2203            size_t      tlb_way; 
2204            size_t      tlb_set; 
2205            paddr_t     tlb_nline; 
2206            bool        tlb_hit;       
2207
2208            if ( r_mmu_mode.read() & DATA_TLB_MASK )    // DTLB activated
2209            {
2210                tlb_hit = r_dtlb.translate( m_dreq.addr,
2211                                            &tlb_paddr,
2212                                            &tlb_flags,
2213                                            &tlb_nline,
2214                                            &tlb_way,   
2215                                            &tlb_set ); 
2216#ifdef INSTRUMENTATION
2217m_cpt_dtlb_read++;
2218#endif
2219            }
2220            else
2221            {
2222                tlb_hit = false;
2223            } // end dtlb access
2224
2225            // register the processor request
2226            r_dcache_p0_vaddr = m_dreq.addr;
2227            r_dcache_p0_be    = m_dreq.be;
2228            r_dcache_p0_wdata = m_dreq.wdata;
2229
2230            // Handling READ XTN requests from processor
2231            // They are executed in this DCACHE_IDLE state.
2232            // The processor must not be in user mode
2233            if (m_dreq.type == iss_t::XTN_READ) 
2234            {
2235                int xtn_opcode = (int)m_dreq.addr/4;
2236
2237                // checking processor mode:
2238                if (m_dreq.mode  == iss_t::MODE_USER)
2239                {
2240                    r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION; 
2241                    r_mmu_dbvar  = m_dreq.addr;
2242                    m_drsp.valid            = true;
2243                    m_drsp.error            = true;
2244                    r_dcache_fsm          = DCACHE_IDLE;
2245                }
2246                else 
2247                {
2248                    switch( xtn_opcode ) 
2249                    {
2250                    case iss_t::XTN_INS_ERROR_TYPE:
2251                        m_drsp.rdata = r_mmu_ietr.read();
2252                        m_drsp.valid = true;
2253                        break;
2254
2255                    case iss_t::XTN_DATA_ERROR_TYPE:
2256                        m_drsp.rdata = r_mmu_detr.read();
2257                        m_drsp.valid = true;
2258                        break;
2259
2260                    case iss_t::XTN_INS_BAD_VADDR:
2261                        m_drsp.rdata = r_mmu_ibvar.read();       
2262                        m_drsp.valid = true;
2263                        break;
2264
2265                    case iss_t::XTN_DATA_BAD_VADDR:
2266                        m_drsp.rdata = r_mmu_dbvar.read();       
2267                        m_drsp.valid = true;
2268                        break;
2269
2270                    case iss_t::XTN_PTPR:
2271                        m_drsp.rdata = r_mmu_ptpr.read();
2272                        m_drsp.valid = true;
2273                        break;
2274
2275                    case iss_t::XTN_TLB_MODE:
2276                        m_drsp.rdata = r_mmu_mode.read();
2277                        m_drsp.valid = true;
2278                        break;
2279
2280                    case iss_t::XTN_MMU_PARAMS:
2281                        m_drsp.rdata = r_mmu_params;
2282                        m_drsp.valid = true;
2283                        break;
2284
2285                    case iss_t::XTN_MMU_RELEASE:
2286                        m_drsp.rdata = r_mmu_release;
2287                        m_drsp.valid = true;
2288                        break;
2289
2290                    case iss_t::XTN_MMU_WORD_LO:
2291                        m_drsp.rdata = r_mmu_word_lo.read();
2292                        m_drsp.valid = true;
2293                        break;
2294
2295                    case iss_t::XTN_MMU_WORD_HI:
2296                        m_drsp.rdata = r_mmu_word_hi.read();
2297                        m_drsp.valid = true;
2298                        break;
2299
2300                    default:
2301                        r_mmu_detr = MMU_READ_UNDEFINED_XTN; 
2302                        r_mmu_dbvar  = m_dreq.addr;
2303                        m_drsp.valid = true;
2304                        m_drsp.error = true;
2305                        break;
2306                    } // end switch xtn_opcode
2307                } // end else
2308                r_dcache_p0_valid = false;
2309            } // end if XTN_READ
2310
2311            // Handling WRITE XTN requests from processor.
2312            // They are not executed in this DCACHE_IDLE state,
2313            // if they require access to the caches or the TLBs
2314            // that are already accessed for speculative read.
2315            // Caches can be invalidated or flushed in user mode,
2316            // and the sync instruction can be executed in user mode
2317            else if (m_dreq.type == iss_t::XTN_WRITE) 
2318            {
2319                int xtn_opcode      = (int)m_dreq.addr/4;
2320                r_dcache_xtn_opcode = xtn_opcode;
2321
2322                // checking processor mode:
2323                if ( (m_dreq.mode  == iss_t::MODE_USER) &&
2324                     (xtn_opcode != iss_t:: XTN_SYNC) &&
2325                     (xtn_opcode != iss_t::XTN_DCACHE_INVAL) &&
2326                     (xtn_opcode != iss_t::XTN_DCACHE_FLUSH) &&
2327                     (xtn_opcode != iss_t::XTN_ICACHE_INVAL) &&
2328                     (xtn_opcode != iss_t::XTN_ICACHE_FLUSH) )
2329                {
2330                    r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION; 
2331                    r_mmu_dbvar  = m_dreq.addr;
2332                    m_drsp.valid          = true;
2333                    m_drsp.error          = true;
2334                    r_dcache_fsm        = DCACHE_IDLE;
2335                }
2336                else
2337                {
2338                    switch( xtn_opcode ) 
2339                    {     
2340                    case iss_t::XTN_PTPR:                       // itlb & dtlb must be flushed
2341                        r_mmu_ptpr       = m_dreq.wdata;
2342                        r_dcache_xtn_req = true;
2343                        r_dcache_fsm     = DCACHE_XTN_SWITCH;
2344                        break;
2345
2346                    case iss_t::XTN_TLB_MODE:                   // no cache or tlb access
2347                        r_mmu_mode = m_dreq.wdata;
2348                        m_drsp.valid = true;
2349                        r_dcache_fsm = DCACHE_IDLE;
2350                        break;
2351
2352                    case iss_t::XTN_DTLB_INVAL:                 // dtlb access
2353                        r_dcache_fsm = DCACHE_XTN_DT_INVAL; 
2354                        break;
2355
2356                    case iss_t::XTN_ITLB_INVAL:                 // itlb access
2357                        r_dcache_xtn_req = true;
2358                        r_dcache_fsm = DCACHE_XTN_IT_INVAL; 
2359                        break;
2360
2361                    case iss_t::XTN_DCACHE_INVAL:               // dcache, dtlb & itlb access
2362                        r_dcache_fsm = DCACHE_XTN_DC_INVAL_VA;
2363                        break;
2364
2365                    case iss_t::XTN_MMU_DCACHE_PA_INV:          // dcache, dtlb & itlb access
2366                        r_dcache_fsm   = DCACHE_XTN_DC_INVAL_PA;
2367                        if (sizeof(paddr_t) <= 32) {
2368                                assert(r_mmu_word_hi.read() == 0 &&
2369                                    "high bits should be 0 for 32bit paddr");
2370                                r_dcache_p0_paddr =
2371                                        (paddr_t)r_mmu_word_lo.read();
2372                        } else {
2373                                r_dcache_p0_paddr =
2374                                        (paddr_t)r_mmu_word_hi.read() << 32 | 
2375                                        (paddr_t)r_mmu_word_lo.read();
2376                        }
2377                        break;
2378
2379                    case iss_t::XTN_DCACHE_FLUSH:              // itlb and dtlb must be reset 
2380                        r_dcache_flush_count = 0;
2381                        r_dcache_fsm         = DCACHE_XTN_DC_FLUSH; 
2382                        break;
2383
2384                    case iss_t::XTN_ICACHE_INVAL:               // icache and itlb access
2385                        r_dcache_xtn_req = true;
2386                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_VA; 
2387                        break;
2388
2389                    case iss_t::XTN_MMU_ICACHE_PA_INV:          // icache access
2390                        r_dcache_xtn_req = true;
2391                        r_dcache_fsm     = DCACHE_XTN_IC_INVAL_PA; 
2392                        break;
2393
2394                    case iss_t::XTN_ICACHE_FLUSH:               // icache access
2395                        r_dcache_xtn_req = true; 
2396                        r_dcache_fsm     = DCACHE_XTN_IC_FLUSH;
2397                        break;
2398
2399                    case iss_t::XTN_SYNC:                       // wait until write buffer empty
2400                        r_dcache_fsm     = DCACHE_XTN_SYNC;
2401                        break;
2402
2403                    case iss_t::XTN_MMU_WORD_LO:                // no cache or tlb access
2404                        r_mmu_word_lo = m_dreq.wdata;
2405                        m_drsp.valid    = true;
2406                        r_dcache_fsm  = DCACHE_IDLE;
2407                        break;
2408
2409                    case iss_t::XTN_MMU_WORD_HI:                // no cache or tlb access
2410                        r_mmu_word_hi = m_dreq.wdata;
2411                        m_drsp.valid    = true;
2412                        r_dcache_fsm  = DCACHE_IDLE;
2413                        break;
2414
2415                    case iss_t::XTN_ICACHE_PREFETCH:            // not implemented : no action
2416                    case iss_t::XTN_DCACHE_PREFETCH:            // not implemented : no action
2417                        m_drsp.valid   = true;
2418                        r_dcache_fsm = DCACHE_IDLE;
2419                        break;
2420       
2421                    default:
2422                        r_mmu_detr = MMU_WRITE_UNDEFINED_XTN; 
2423                        r_mmu_dbvar  = m_dreq.addr;
2424                        m_drsp.valid = true;
2425                        m_drsp.error = true;
2426                        r_dcache_fsm = DCACHE_IDLE;
2427                        break;
2428                    } // end switch xtn_opcode
2429                } // end else
2430                r_dcache_p0_valid = false;
2431            } // end if XTN_WRITE
2432
2433            // Handling read/write/ll/sc processor requests.
2434            // The dtlb and dcache can be activated or not.
2435            // We compute the physical address, the cacheability, and check processor request.
2436            // - If DTLB not activated : cacheability is defined by the segment table,
2437            //   the physical address is equal to the virtual address (identity mapping)
2438            // - If DTLB activated : cacheability is defined by the C bit in the PTE,
2439            //   the physical address is obtained from the TLB, and the U & W bits
2440            //   of the PTE are checked.
2441            // The processor request is decoded only if the TLB is not activated or if
2442            // the virtual address hits in tLB and access rights are OK.
2443            // We call the TLB_MISS sub-fsm in case of dtlb miss.
2444            else
2445            {
2446                bool    valid_req = false;
2447                bool    cacheable = false;
2448                paddr_t paddr     = 0;
2449
2450                if ( not (r_mmu_mode.read() & DATA_TLB_MASK) )          // dtlb not activated
2451                {
2452                    valid_req     = true;
2453
2454                    // cacheability
2455                    if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2456                    else cacheable = m_cacheability_table[m_dreq.addr];
2457
2458                    // physical address
2459                    paddr       = (paddr_t)m_dreq.addr;
2460                }
2461                else                                                    // dtlb activated
2462                {
2463                    if ( tlb_hit )                                      // tlb hit
2464                    {
2465                        // cacheability
2466                        if ( not (r_mmu_mode.read() & DATA_CACHE_MASK) ) cacheable = false;
2467                        else cacheable = tlb_flags.c;
2468
2469                        // access rights checking
2470                        if ( not tlb_flags.u and (m_dreq.mode == iss_t::MODE_USER)) 
2471                        {
2472                            if ( (m_dreq.type == iss_t::DATA_READ) or (m_dreq.type == iss_t::DATA_LL) )
2473                                r_mmu_detr = MMU_READ_PRIVILEGE_VIOLATION;
2474                            else 
2475                                r_mmu_detr = MMU_WRITE_PRIVILEGE_VIOLATION;
2476
2477                            r_mmu_dbvar  = m_dreq.addr;
2478                            m_drsp.valid   = true;
2479                            m_drsp.error   = true;
2480                            m_drsp.rdata   = 0;
2481#if DEBUG_DCACHE
2482if ( m_debug_dcache_fsm )
2483{
2484    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but privilege violation" << std::endl;
2485}
2486#endif
2487                        }
2488                        else if ( not tlb_flags.w and
2489                                  ((m_dreq.type == iss_t::DATA_WRITE) or
2490                                   (m_dreq.type == iss_t::DATA_SC)) ) 
2491                        {
2492                            r_mmu_detr   = MMU_WRITE_ACCES_VIOLATION; 
2493                            r_mmu_dbvar  = m_dreq.addr;
2494                            m_drsp.valid   = true;
2495                            m_drsp.error   = true;
2496                            m_drsp.rdata   = 0;
2497#if DEBUG_DCACHE
2498if ( m_debug_dcache_fsm )
2499{
2500    std::cout << "  <PROC.DCACHE_IDLE> HIT in dtlb, but writable violation" << std::endl;
2501}
2502#endif
2503                        }
2504                        else
2505                        {
2506                            valid_req    = true;
2507                        }
2508
2509                        // physical address
2510                        paddr = tlb_paddr;
2511                    }
2512                    else                                                // tlb miss
2513                    {
2514                        r_dcache_tlb_vaddr   = m_dreq.addr;
2515                        r_dcache_tlb_ins     = false; 
2516                        r_dcache_fsm         = DCACHE_TLB_MISS;
2517                    }
2518                }    // end DTLB activated
2519
2520                if ( valid_req )        // processor request is valid after TLB check
2521                {
2522                    // physical address and cacheability registration
2523                    r_dcache_p0_paddr          = paddr;
2524                    r_dcache_p0_cacheable      = cacheable;
2525
2526                    // READ or LL request
2527                    // The read requests are taken only if the write pipe-line is empty.
2528                    // If dcache hit, dtlb hit, and speculative PPN OK, data in one cycle.
2529                    // If speculative access is KO we just pay one extra cycle.
2530                    // If dcache miss, we go to DCACHE_MISS_VICTIM state.
2531                    // If uncacheable, we go to DCACHE_UNC_WAIT state.
2532                    if ( ((m_dreq.type == iss_t::DATA_READ) or (m_dreq.type == iss_t::DATA_LL)) 
2533                        and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
2534                    { 
2535                        if ( cacheable )                        // cacheable read
2536                        {
2537                            // if the speculative access is illegal, we pay an extra cycle
2538                            if ( (r_dcache_p0_paddr.read() & ~PAGE_K_MASK) 
2539                                 != (paddr & ~PAGE_K_MASK))
2540                            {
2541#ifdef INSTRUMENTATION
2542m_cpt_dcache_spec_miss++;
2543#endif
2544                            }
2545                            // if cache miss, try to get the missing line
2546                            else if ( not cache_hit )
2547                            {
2548#ifdef INSTRUMENTATION
2549m_cpt_dcache_miss++;
2550#endif
2551                                // blocked in IDLE state if previous cleanup not completed
2552                                if ( not r_dcache_cleanup_req.read() )
2553                                {
2554                                    r_dcache_vci_paddr    = paddr;
2555                                    r_dcache_vci_miss_req = true;
2556                                    r_dcache_miss_type    = PROC_MISS;
2557                                    r_dcache_fsm          = DCACHE_MISS_VICTIM;
2558                                }
2559                            }
2560                            // if cache hit return the data
2561                            else                   
2562                            {
2563#ifdef INSTRUMENTATION
2564m_cpt_data_read++;
2565#endif
2566                                m_drsp.valid   = true;
2567                                m_drsp.rdata   = cache_rdata;
2568#if DEBUG_DCACHE
2569if ( m_debug_dcache_fsm )
2570{
2571    std::cout << "  <PROC.DCACHE_IDLE> HIT in dcache" << std::endl;
2572}
2573#endif
2574                            }
2575                        }
2576                        else                                    // uncacheable read
2577                        {
2578                            r_dcache_vci_paddr    = paddr;
2579                            r_dcache_vci_unc_be   = m_dreq.be;
2580                            r_dcache_vci_unc_req  = true;
2581                            r_dcache_fsm          = DCACHE_UNC_WAIT;
2582                        }
2583
2584                        // makes reservation in case of LL
2585                        if ( m_dreq.type == iss_t::DATA_LL )
2586                        {
2587                            r_dcache_ll_valid = true;
2588                            r_dcache_ll_data  = cache_rdata;
2589                            r_dcache_ll_vaddr = m_dreq.addr;
2590                        }
2591                        r_dcache_p0_valid = false;
2592                    } // end READ or LL
2593
2594                    // WRITE request:
2595                    // If the TLB is activated and the PTE Dirty bit is not set, we stall
2596                    // the processor and set the Dirty bit before handling the write request.
2597                    // If we don't need to set the Dirty bit, we can acknowledge
2598                    // the processor request, as the write arguments (including the
2599                    // physical address) are registered in r_dcache_p0 registers:
2600                    // We simply activate the P1 pipeline stage.
2601                    else if ( m_dreq.type == iss_t::DATA_WRITE )
2602                    {
2603                        if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
2604                              and not tlb_flags.d )             // Dirty bit must be set
2605                        {
2606                            // The PTE physical address is obtained from the nline value (dtlb),
2607                            // and the word index (proper bits of the virtual address)
2608                            if ( tlb_flags.b )  // PTE1
2609                            {
2610                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2611                                                       (paddr_t)((m_dreq.addr>>19) & 0x3c);
2612                            }
2613                            else                // PTE2
2614                            {
2615                                r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2616                                                       (paddr_t)((m_dreq.addr>>9) & 0x38);
2617                            }
2618                            r_dcache_fsm      = DCACHE_DIRTY_GET_PTE;
2619                            r_dcache_p0_valid = false;
2620                        }
2621                        else                                    // Write request accepted
2622                        {
2623#ifdef INSTRUMENTATION
2624m_cpt_data_write++;
2625#endif
2626                            m_drsp.valid      = true;
2627                            m_drsp.rdata      = 0;
2628                            r_dcache_p0_valid = true;
2629                        }
2630                    } // end WRITE
2631 
2632                    // SC request:
2633                    // The SC requests are taken only if the write pipe-line is empty.
2634                    // - if there is no valid registered LL, we just return rdata = 1
2635                    //   (atomic access failed) and the SC transaction is completed.
2636                    // - if a valid LL reservation (with the same address) is registered,
2637                    //   we test if a DIRTY bit update is required.
2638                    //   If the TLB is activated and the PTE Dirty bit is not set, we stall
2639                    //   the processor and set the Dirty bit before handling the write request.
2640                    //   If we don't need to set the Dirty bit, we request a SC transaction
2641                    //   to CMD FSM and go to DCACHE_SC_WAIT state, that will return
2642                    //   the response to the processor.
2643                    //   We don't check a possible write hit in dcache, as the cache update
2644                    //   is done by the coherence transaction induced by the SC...
2645                    else if ( ( m_dreq.type == iss_t::DATA_SC )
2646                        and not r_dcache_p0_valid.read() and not r_dcache_p1_valid.read() )
2647                    {
2648                        if ( (r_dcache_ll_vaddr.read() != m_dreq.addr)
2649                             or not r_dcache_ll_valid.read() )  // no valid registered LL
2650                        { 
2651#ifdef INSTRUMENTATION
2652m_cpt_data_sc++;
2653#endif
2654                            m_drsp.valid        = true;
2655                            m_drsp.rdata        = 1;
2656                            r_dcache_ll_valid   = false;
2657                        }
2658                        else                                    // valid registered LL
2659                        {
2660                            if ( (r_mmu_mode.read() & DATA_TLB_MASK ) 
2661                                  and not tlb_flags.d )                 // Dirty bit must be set
2662                            {
2663                                // The PTE physical address is obtained from the nline value (dtlb),
2664                                // and the word index (proper bits of the virtual address)
2665                                if ( tlb_flags.b )      // PTE1
2666                                {
2667                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2668                                                           (paddr_t)((m_dreq.addr>>19) & 0x3c);
2669                                }
2670                                else                    // PTE2
2671                                {
2672                                    r_dcache_dirty_paddr = (paddr_t)(tlb_nline*(m_dcache_words<<2)) |
2673                                                           (paddr_t)((m_dreq.addr>>9) & 0x38);
2674                                }
2675                                r_dcache_fsm           = DCACHE_DIRTY_GET_PTE;
2676                            }
2677                            else                                        // SC request accepted
2678                            {
2679#ifdef INSTRUMENTATION
2680m_cpt_data_sc++;
2681#endif
2682     
2683                                r_dcache_vci_paddr  = paddr;
2684                                r_dcache_vci_sc_req = true;
2685                                r_dcache_vci_sc_old = r_dcache_ll_data.read();
2686                                r_dcache_vci_sc_new = m_dreq.wdata;
2687                                r_dcache_ll_valid   = false;
2688                                r_dcache_fsm        = DCACHE_SC_WAIT;
2689                            }
2690                        }
2691                        r_dcache_p0_valid = false;
2692                    } // end SC
2693                    else
2694                    {
2695                        r_dcache_p0_valid = false;
2696                    }
2697                } // end valid_req
2698                else
2699                {
2700                    r_dcache_p0_valid = false;
2701                }
2702            }  // end if read/write/ll/sc request       
2703        } // end dreq.valid
2704        else
2705        {
2706            r_dcache_p0_valid = false;
2707        } // end P0 pipe stage
2708        break;
2709    } 
2710    /////////////////////
2711    case DCACHE_TLB_MISS: // This is the entry point for the sub-fsm handling all tlb miss.
2712                          // Input arguments are:
2713                          // - r_dcache_tlb_vaddr
2714                          // - r_dcache_tlb_ins (true when itlb miss)
2715                          // The sub-fsm access the dcache to find the missing TLB entry,
2716                          // and activates the cache miss procedure in case of miss.
2717                          // It bypass the first level page table access if possible.
2718                          // It uses atomic access to update the R/L access bits
2719                          // in the page table if required.
2720                          // It directly updates the itlb or dtlb, and writes into the
2721                          // r_mmu_ins_* or r_mmu_data* error reporting registers.
2722    {
2723        uint32_t        ptba = 0;
2724        bool            bypass;
2725        paddr_t         pte_paddr;
2726
2727        // evaluate bypass in order to skip first level page table access
2728        if ( r_dcache_tlb_ins.read() )                          // itlb miss
2729        {
2730            bypass = r_itlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2731        }
2732        else                                                    // dtlb miss
2733        {
2734            bypass = r_dtlb.get_bypass(r_dcache_tlb_vaddr.read(), &ptba);
2735        }
2736
2737        if ( not bypass )     // Try to read PTE1/PTD1 in dcache
2738        {
2739            pte_paddr = (paddr_t)r_mmu_ptpr.read() << (INDEX1_NBITS+2) |
2740                        (paddr_t)((r_dcache_tlb_vaddr.read() >> PAGE_M_NBITS) << 2);
2741            r_dcache_tlb_paddr = pte_paddr;
2742            r_dcache_fsm       = DCACHE_TLB_PTE1_GET;
2743        }
2744        else                  // Try to read PTE2 in dcache
2745        {
2746            pte_paddr = (paddr_t)ptba << PAGE_K_NBITS |
2747                        (paddr_t)(r_dcache_tlb_vaddr.read()&PTD_ID2_MASK)>>(PAGE_K_NBITS-3);
2748            r_dcache_tlb_paddr = pte_paddr;
2749            r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2750        }
2751
2752#if DEBUG_DCACHE
2753if ( m_debug_dcache_fsm )
2754{
2755    if ( r_dcache_tlb_ins.read() ) 
2756    {
2757        std::cout << "  <PROC.DCACHE_TLB_MISS> ITLB miss";
2758    }
2759    else
2760    {                           
2761        std::cout << "  <PROC.DCACHE_TLB_MISS> DTLB miss";
2762    }
2763    std::cout << " / VADDR = " << std::hex << r_dcache_tlb_vaddr.read()
2764              << " / BYPASS = " << bypass
2765              << " / PTE_ADR = " << pte_paddr << std::endl;
2766}
2767#endif
2768 
2769        break;
2770    }
2771    ///////////////////////// 
2772    case DCACHE_TLB_PTE1_GET:   // try to read a PT1 entry in dcache
2773    {
2774        uint32_t        entry;
2775        size_t          way;
2776        size_t          set;
2777        size_t          word;
2778
2779        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
2780                                      &entry,
2781                                      &way,
2782                                      &set,
2783                                      &word );
2784#ifdef INSTRUMENTATION
2785m_cpt_dcache_data_read++;
2786m_cpt_dcache_dir_read++;
2787#endif
2788        if ( hit )      //  hit in dcache
2789        {
2790            if ( not (entry & PTE_V_MASK) )     // unmapped
2791            {
2792                if ( r_dcache_tlb_ins.read() ) 
2793                {
2794                    r_mmu_ietr             = MMU_READ_PT1_UNMAPPED;
2795                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
2796                    r_icache_tlb_miss_req  = false;
2797                    r_icache_tlb_rsp_error = true;
2798                }
2799                else
2800                {
2801                    r_mmu_detr             = MMU_READ_PT1_UNMAPPED;
2802                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
2803                    m_drsp.valid             = true;
2804                    m_drsp.error             = true;
2805                }
2806                r_dcache_fsm          = DCACHE_IDLE;
2807
2808#if DEBUG_DCACHE
2809if ( m_debug_dcache_fsm )
2810{
2811    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache, but unmapped"
2812              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2813              << std::dec << " / way = " << way
2814              << std::dec << " / set = " << set
2815              << std::dec << " / word = " << word
2816              << std::hex << " / PTE1 = " << entry << std::endl;
2817}
2818#endif
2819 
2820            }
2821            else if( entry & PTE_T_MASK )       //  PTD : me must access PT2
2822            {
2823                // mark the cache line ac containing a PTD
2824                r_dcache_contains_ptd[m_dcache_sets*way+set] = true;
2825
2826                // register bypass
2827                if ( r_dcache_tlb_ins.read() )          // itlb
2828                {
2829                    r_itlb.set_bypass(r_dcache_tlb_vaddr.read(),
2830                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1), 
2831                                      r_dcache_tlb_paddr.read() >> (uint32_log2(m_icache_words<<2))); 
2832                }
2833                else                                    // dtlb
2834                {
2835                    r_dtlb.set_bypass(r_dcache_tlb_vaddr.read(),
2836                                      entry & ((1 << (m_paddr_nbits-PAGE_K_NBITS)) - 1),
2837                                      r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2));
2838                }
2839                r_dcache_tlb_paddr = (paddr_t)(entry & ((1<<(m_paddr_nbits-PAGE_K_NBITS))-1)) << PAGE_K_NBITS |
2840                                     (paddr_t)(((r_dcache_tlb_vaddr.read() & PTD_ID2_MASK) >> PAGE_K_NBITS) << 3);
2841                r_dcache_fsm       = DCACHE_TLB_PTE2_GET;
2842
2843#if DEBUG_DCACHE
2844if ( m_debug_dcache_fsm )
2845{
2846    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache"
2847              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2848              << std::dec << " / way = " << way
2849              << std::dec << " / set = " << set
2850              << std::dec << " / word = " << word
2851              << std::hex << " / PTD = " << entry << std::endl;
2852}
2853#endif
2854            }
2855            else                        //  PTE1 :  we must update the TLB
2856            {
2857                r_dcache_in_tlb[m_icache_sets*way+set] = true;
2858                r_dcache_tlb_pte_flags  = entry;
2859                r_dcache_tlb_cache_way  = way;
2860                r_dcache_tlb_cache_set  = set;
2861                r_dcache_tlb_cache_word = word;
2862                r_dcache_fsm            = DCACHE_TLB_PTE1_SELECT;
2863
2864#if DEBUG_DCACHE
2865if ( m_debug_dcache_fsm )
2866{
2867    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> HIT in dcache"
2868              << std::hex << " / paddr = " << r_dcache_tlb_paddr.read()
2869              << std::dec << " / way = " << way
2870              << std::dec << " / set = " << set
2871              << std::dec << " / word = " << word
2872              << std::hex << " / PTE1 = " << entry << std::endl;
2873}
2874#endif
2875            }
2876        }
2877        else            // we must load the missing cache line in dcache
2878        {
2879            r_dcache_vci_miss_req  = true;             
2880            r_dcache_vci_paddr     = r_dcache_tlb_paddr.read(); 
2881            r_dcache_miss_type     = PTE1_MISS;
2882            r_dcache_fsm           = DCACHE_MISS_VICTIM;         
2883
2884#if DEBUG_DCACHE
2885if ( m_debug_dcache_fsm )
2886{
2887    std::cout << "  <PROC.DCACHE_TLB_PTE1_GET> MISS in dcache:"
2888              << " PTE1 address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
2889}
2890#endif
2891        }
2892        break;
2893    }
2894    ////////////////////////////
2895    case DCACHE_TLB_PTE1_SELECT:        // select a slot for PTE1
2896    {
2897        size_t  way;
2898        size_t  set;
2899
2900        if ( r_dcache_tlb_ins.read() )
2901        {
2902            r_itlb.select( r_dcache_tlb_vaddr.read(),
2903                           true,  // PTE1
2904                           &way,
2905                           &set );
2906#ifdef INSTRUMENTATION
2907m_cpt_itlb_read++;
2908#endif
2909        }
2910        else
2911        {
2912            r_dtlb.select( r_dcache_tlb_vaddr.read(),
2913                           true,  // PTE1
2914                           &way,
2915                           &set );
2916#ifdef INSTRUMENTATION
2917m_cpt_dtlb_read++;
2918#endif
2919        }
2920        r_dcache_tlb_way = way;
2921        r_dcache_tlb_set = set;
2922        r_dcache_fsm     = DCACHE_TLB_PTE1_UPDT;
2923
2924#if DEBUG_DCACHE
2925if ( m_debug_dcache_fsm )
2926{
2927    if ( r_dcache_tlb_ins.read() ) 
2928        std::cout << "  <PROC.DCACHE_TLB_PTE1_SELECT> Select a slot in ITLB:";
2929    else                           
2930        std::cout << "  <PROC.DCACHE_TLB_PTE1_SELECT> Select a slot in DTLB:";
2931        std::cout << " way = " << std::dec << way
2932                  << " / set = " << set << std::endl;
2933}
2934#endif
2935        break;
2936    }
2937    //////////////////////////
2938    case DCACHE_TLB_PTE1_UPDT:  // write a new PTE1 in tlb after testing the L/R bit
2939                                // if L/R bit already set, exit the sub-fsm
2940                                // if not, the page table must be updated
2941    {
2942        paddr_t   nline = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
2943        uint32_t  pte   = r_dcache_tlb_pte_flags.read();
2944        bool      updt  = false;
2945        bool      local = true;
2946
2947        // We should compute the access locality:
2948        // The PPN MSB bits define the destination cluster index.
2949        // The m_srcid_d MSB bits define the source cluster index.
2950        // The number of bits to compare depends on the number of clusters,
2951        // and can be obtained in the mapping table.
2952        // As long as this computation is not done, all access are local.
2953
2954        if ( local )                                            // local access
2955        {
2956            if ( not ((pte & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
2957            {
2958                updt                = true;
2959                r_dcache_vci_sc_old = pte;
2960                r_dcache_vci_sc_new = pte | PTE_L_MASK;
2961                pte                 = pte | PTE_L_MASK;
2962            }
2963        }
2964        else                                                    // remote access
2965        {
2966            if ( not ((pte & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
2967            {
2968                updt                = true;
2969                r_dcache_vci_sc_old = pte;
2970                r_dcache_vci_sc_new = pte | PTE_R_MASK;
2971                pte                 = pte | PTE_R_MASK;
2972            }
2973        }
2974
2975        // update TLB
2976        if ( r_dcache_tlb_ins.read() ) 
2977        {
2978            r_itlb.write( true,         // 2M page
2979                          pte,
2980                          0,            // argument unused for a PTE1
2981                          r_dcache_tlb_vaddr.read(),   
2982                          r_dcache_tlb_way.read(), 
2983                          r_dcache_tlb_set.read(),
2984                          nline );
2985#ifdef INSTRUMENTATION
2986m_cpt_itlb_write++;
2987#endif
2988        }
2989        else
2990        {
2991            r_dtlb.write( true,         // 2M page
2992                          pte,
2993                          0,            // argument unused for a PTE1
2994                          r_dcache_tlb_vaddr.read(),   
2995                          r_dcache_tlb_way.read(), 
2996                          r_dcache_tlb_set.read(),
2997                          nline );
2998#ifdef INSTRUMENTATION
2999m_cpt_dtlb_write++;
3000#endif
3001        }
3002        // next state
3003        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3004        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
3005
3006#if DEBUG_DCACHE
3007if ( m_debug_dcache_fsm )
3008{
3009    if ( r_dcache_tlb_ins.read() ) 
3010    {
3011        std::cout << "  <PROC.DCACHE_TLB_PTE1_UPDT> write PTE1 in ITLB";
3012        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3013                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3014        r_itlb.printTrace();
3015    }
3016    else                           
3017    {
3018        std::cout << "  <PROC.DCACHE_TLB_PTE1_UPDT> write PTE1 in DTLB";
3019        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3020                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3021        r_dtlb.printTrace();
3022    }
3023   
3024}
3025#endif
3026        break;
3027    }
3028    /////////////////////////
3029    case DCACHE_TLB_PTE2_GET:   // Try to get a PTE2 (64 bits) in the dcache
3030    {
3031        uint32_t        pte_flags;
3032        uint32_t        pte_ppn;
3033        size_t          way;
3034        size_t          set;
3035        size_t          word; 
3036 
3037        bool     hit = r_dcache.read( r_dcache_tlb_paddr.read(),
3038                                      &pte_flags,
3039                                      &pte_ppn,
3040                                      &way,
3041                                      &set,
3042                                      &word );
3043#ifdef INSTRUMENTATION
3044m_cpt_dcache_data_read++;
3045m_cpt_dcache_dir_read++;
3046#endif
3047        if ( hit )      // request hits in dcache
3048        {
3049            if ( not (pte_flags & PTE_V_MASK) ) // unmapped
3050            {
3051                if ( r_dcache_tlb_ins.read() ) 
3052                {
3053                    r_mmu_ietr             = MMU_READ_PT2_UNMAPPED;
3054                    r_mmu_ibvar            = r_dcache_tlb_vaddr.read();
3055                    r_icache_tlb_miss_req  = false;
3056                    r_icache_tlb_rsp_error = true;
3057                }
3058                else
3059                {
3060                    r_mmu_detr             = MMU_READ_PT2_UNMAPPED;
3061                    r_mmu_dbvar            = r_dcache_tlb_vaddr.read();
3062                    m_drsp.valid             = true;
3063                    m_drsp.error             = true;
3064                }
3065                r_dcache_fsm          = DCACHE_IDLE;
3066
3067#if DEBUG_DCACHE
3068if ( m_debug_dcache_fsm )
3069{
3070    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> HIT in dcache, but PTE is unmapped"
3071              << " PTE_FLAGS = " << std::hex << pte_flags
3072              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3073}
3074#endif
3075            }
3076            else                                // mapped : we must update the TLB
3077            {
3078                r_dcache_in_tlb[m_dcache_sets*way+set] = true;
3079                r_dcache_tlb_pte_flags  = pte_flags;
3080                r_dcache_tlb_pte_ppn    = pte_ppn;
3081                r_dcache_tlb_cache_way  = way;
3082                r_dcache_tlb_cache_set  = set;
3083                r_dcache_tlb_cache_word = word;
3084                r_dcache_fsm            = DCACHE_TLB_PTE2_SELECT;
3085
3086#if DEBUG_DCACHE
3087if ( m_debug_dcache_fsm )
3088{
3089    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> HIT in dcache:"
3090              << " PTE_FLAGS = " << std::hex << pte_flags
3091              << " PTE_PPN = " << std::hex << pte_ppn << std::endl;
3092}
3093#endif
3094             }
3095        }
3096        else            // we must load the missing cache line in dcache
3097        {
3098            r_dcache_fsm          = DCACHE_MISS_VICTIM; 
3099            r_dcache_vci_miss_req = true;
3100            r_dcache_vci_paddr    = r_dcache_tlb_paddr.read();
3101            r_dcache_miss_type    = PTE2_MISS;
3102
3103#if DEBUG_DCACHE
3104if ( m_debug_dcache_fsm )
3105{
3106    std::cout << "  <PROC.DCACHE_TLB_PTE2_GET> MISS in dcache:"
3107              << " PTE address = " << std::hex << r_dcache_tlb_paddr.read() << std::endl;
3108}
3109#endif
3110        }
3111        break;
3112    }
3113    ////////////////////////////
3114    case DCACHE_TLB_PTE2_SELECT:    // select a slot for PTE2
3115    {
3116        size_t way;
3117        size_t set;
3118
3119        if ( r_dcache_tlb_ins.read() )
3120        {
3121            r_itlb.select( r_dcache_tlb_vaddr.read(),
3122                           false,       // PTE2
3123                           &way,
3124                           &set );
3125#ifdef INSTRUMENTATION
3126m_cpt_itlb_read++;
3127#endif
3128        }
3129        else
3130        {
3131            r_dtlb.select( r_dcache_tlb_vaddr.read(),
3132                           false,       // PTE2
3133                           &way,
3134                           &set );
3135#ifdef INSTRUMENTATION
3136m_cpt_dtlb_read++;
3137#endif
3138        }
3139
3140#if DEBUG_DCACHE
3141if ( m_debug_dcache_fsm )
3142{
3143    if ( r_dcache_tlb_ins.read() ) 
3144        std::cout << "  <PROC.DCACHE_TLB_PTE2_SELECT> Select a slot in ITLB:";
3145    else                           
3146        std::cout << "  <PROC.DCACHE_TLB_PTE2_SELECT> Select a slot in DTLB:";
3147        std::cout << " way = " << std::dec << way
3148                  << " / set = " << set << std::endl;
3149}
3150#endif
3151        r_dcache_tlb_way = way;
3152        r_dcache_tlb_set = set;
3153        r_dcache_fsm     = DCACHE_TLB_PTE2_UPDT;
3154        break;
3155    }
3156    //////////////////////////
3157    case DCACHE_TLB_PTE2_UPDT:          // write a new PTE2 in tlb after testing the L/R bit
3158                                        // if L/R bit already set, exit the sub-fsm
3159                                        // if not, the page table must be updated by an atomic access
3160    {
3161        paddr_t         nline     = r_dcache_tlb_paddr.read() >> (uint32_log2(m_dcache_words)+2);   
3162        uint32_t        pte_flags = r_dcache_tlb_pte_flags.read();
3163        uint32_t        pte_ppn   = r_dcache_tlb_pte_ppn.read();
3164        bool            updt      = false;
3165        bool            local     = true;
3166
3167        // We should compute the access locality:
3168        // The PPN MSB bits define the destination cluster index.
3169        // The m_srcid_d MSB bits define the source cluster index.
3170        // The number of bits to compare depends on the number of clusters,
3171        // and can be obtained in the mapping table.
3172        // As long as this computation is not done, all access are local.
3173
3174        if ( local )                                            // local access
3175        {
3176            if ( not ((pte_flags & PTE_L_MASK) == PTE_L_MASK) ) // we must set the L bit
3177            {
3178                updt                = true;
3179                r_dcache_vci_sc_old = pte_flags;
3180                r_dcache_vci_sc_new = pte_flags | PTE_L_MASK;
3181                pte_flags           = pte_flags | PTE_L_MASK;
3182            }
3183        }
3184        else                                                    // remote access
3185        {
3186            if ( not ((pte_flags & PTE_R_MASK) == PTE_R_MASK) ) // we must set the R bit
3187            {
3188                updt                   = true;
3189                r_dcache_vci_sc_old = pte_flags;
3190                r_dcache_vci_sc_new = pte_flags | PTE_R_MASK;
3191                pte_flags           = pte_flags | PTE_R_MASK;
3192            }
3193        }
3194       
3195        // update TLB for a PTE2
3196        if ( r_dcache_tlb_ins.read() ) 
3197        {
3198            r_itlb.write( false,        // 4K page
3199                          pte_flags,
3200                          pte_ppn,
3201                          r_dcache_tlb_vaddr.read(),   
3202                          r_dcache_tlb_way.read(), 
3203                          r_dcache_tlb_set.read(),
3204                          nline );
3205#ifdef INSTRUMENTATION
3206m_cpt_itlb_write++;
3207#endif
3208        }
3209        else
3210        {
3211            r_dtlb.write( false,        // 4K page
3212                          pte_flags,
3213                          pte_ppn,
3214                          r_dcache_tlb_vaddr.read(),   
3215                          r_dcache_tlb_way.read(), 
3216                          r_dcache_tlb_set.read(),
3217                          nline );
3218#ifdef INSTRUMENTATION
3219m_cpt_dtlb_write++;
3220#endif
3221        }
3222
3223#if DEBUG_DCACHE
3224if ( m_debug_dcache_fsm )
3225{
3226    if ( r_dcache_tlb_ins.read() ) 
3227    {
3228        std::cout << "  <PROC.DCACHE_TLB_PTE2_UPDT> write PTE2 in ITLB";
3229        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3230                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3231        r_itlb.printTrace();
3232    }
3233    else                           
3234    {
3235        std::cout << "  <PROC.DCACHE_TLB_PTE2_UPDT> write PTE2 in DTLB";
3236        std::cout << " / set = " << std::dec << r_dcache_tlb_set.read()
3237                  << " / way = " << r_dcache_tlb_way.read() << std::endl;
3238        r_dtlb.printTrace();
3239    }
3240}
3241#endif
3242        // next state
3243        if ( updt ) r_dcache_fsm = DCACHE_TLB_LR_UPDT;  // dcache and page table update
3244        else        r_dcache_fsm = DCACHE_TLB_RETURN;   // exit sub-fsm
3245        break;
3246    }
3247    ////////////////////////
3248    case DCACHE_TLB_LR_UPDT:            // update the dcache after a tlb miss (L/R bit),
3249                                        // request a SC transaction to CMD FSM
3250    {
3251#if DEBUG_DCACHE
3252if ( m_debug_dcache_fsm )
3253{
3254    std::cout << "  <PROC.DCACHE_TLB_LR_UPDT> Update dcache: (L/R) bit" << std::endl;
3255}
3256#endif
3257        r_dcache.write(r_dcache_tlb_cache_way.read(),
3258                       r_dcache_tlb_cache_set.read(),
3259                       r_dcache_tlb_cache_word.read(),
3260                       r_dcache_tlb_pte_flags.read());
3261#ifdef INSTRUMENTATION
3262m_cpt_dcache_data_write++;
3263#endif
3264        // r_dcache_vci_sc_old & r_dcache_vci_sc_new registers are already set
3265        r_dcache_vci_paddr   = r_dcache_tlb_paddr.read();
3266        r_dcache_vci_sc_req  = true;
3267        r_dcache_fsm         = DCACHE_TLB_LR_WAIT;
3268        break;
3269    }
3270    ////////////////////////
3271    case DCACHE_TLB_LR_WAIT:            // Waiting a response to SC transaction.
3272                                        // We consume the response in rsp FIFO,
3273                                        // and exit the sub-fsm, but we don't
3274                                        // analyse the response, because we don't
3275                                        // care if the L/R bit update is not done.
3276                                        // We must take the coherence requests because
3277                                        // there is a risk of dead-lock
3278
3279    {
3280        // external coherence request
3281        if ( r_tgt_dcache_req )
3282        {
3283            r_dcache_fsm = DCACHE_CC_CHECK;
3284            r_dcache_fsm_save = r_dcache_fsm;
3285            break;
3286        }
3287
3288        if ( r_vci_rsp_data_error.read() )      // bus error
3289        {
3290            std::cout << "BUS ERROR in DCACHE_TLB_LR_WAIT state" << std::endl;
3291            std::cout << "This should not happen in this state" << std::endl;
3292            exit(0);
3293        }
3294        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3295        {
3296#if DEBUG_DCACHE
3297if ( m_debug_dcache_fsm )
3298{
3299    std::cout << "  <PROC.DCACHE_TLB_LR_WAIT> SC response received" << std::endl;
3300}
3301#endif
3302            vci_rsp_fifo_dcache_get = true;     
3303            r_dcache_fsm            = DCACHE_TLB_RETURN;
3304        }
3305        break;
3306    }
3307    ///////////////////////
3308    case DCACHE_TLB_RETURN:             // return to caller depending on tlb miss type
3309    {
3310#if DEBUG_DCACHE
3311if ( m_debug_dcache_fsm )
3312{
3313    std::cout << "  <PROC.DCACHE_TLB_RETURN> TLB MISS completed" << std::endl;
3314}
3315#endif
3316        if ( r_dcache_tlb_ins.read() ) r_icache_tlb_miss_req = false;
3317        r_dcache_fsm = DCACHE_IDLE;
3318        break;
3319    }
3320    ///////////////////////
3321    case DCACHE_XTN_SWITCH:             // Both itlb and dtlb must be flushed
3322    {
3323        if ( not r_dcache_xtn_req.read() )
3324        {
3325            r_dtlb.flush();
3326            r_dcache_fsm = DCACHE_IDLE;
3327            m_drsp.valid = true;
3328        }
3329        break;
3330    }
3331    /////////////////////
3332    case DCACHE_XTN_SYNC:               // waiting until write buffer empty
3333                                        // The coherence request must be taken
3334                                        // as there is a risk of dead-lock
3335    {
3336        // external coherence request
3337        if ( r_tgt_dcache_req.read() )   
3338        {
3339            r_dcache_fsm = DCACHE_CC_CHECK;
3340            r_dcache_fsm_save = DCACHE_XTN_SYNC;
3341        }       
3342
3343        if ( r_wbuf.empty() )
3344        {
3345            m_drsp.valid   = true;
3346            r_dcache_fsm = DCACHE_IDLE;
3347        }
3348        break;
3349    }
3350    ////////////////////////
3351    case DCACHE_XTN_IC_FLUSH:           // Waiting completion of an XTN request to the ICACHE FSM
3352    case DCACHE_XTN_IC_INVAL_VA:        // Caution : the itlb miss requests must be taken
3353    case DCACHE_XTN_IC_INVAL_PA:        // because the XTN_ICACHE_INVAL request to icache
3354    case DCACHE_XTN_IT_INVAL:           // can generate an itlb miss...
3355    {
3356        // external coherence request
3357        if ( r_tgt_dcache_req )   
3358        {
3359            r_dcache_fsm = DCACHE_CC_CHECK;
3360            r_dcache_fsm_save = r_dcache_fsm;
3361            break;
3362        } 
3363
3364        // itlb miss request
3365        if ( r_icache_tlb_miss_req.read() )
3366        {
3367            r_dcache_tlb_ins    = true;
3368            r_dcache_tlb_vaddr  = r_icache_vaddr_save.read();
3369            r_dcache_fsm        = DCACHE_TLB_MISS;
3370            break;
3371        }
3372
3373        // test if XTN request to icache completed
3374        if ( not r_dcache_xtn_req.read() ) 
3375        {
3376            r_dcache_fsm = DCACHE_IDLE;
3377            m_drsp.valid = true;
3378        }
3379        break;
3380    }
3381    /////////////////////////
3382    case DCACHE_XTN_DC_FLUSH:   // Invalidate sequencially all cache lines, using
3383                                // the r_dcache_flush counter as a slot counter.
3384                                // We loop in this state until all slots have been visited.
3385                                // A cleanup request is generated for each valid line
3386                                // and we are blocked until the previous cleanup is completed
3387                                // Finally, both the itlb and dtlb are reset, because
3388                                // all TLB entries (including global entries) must be invalidated.
3389    {
3390        if ( not r_dcache_cleanup_req )
3391        {
3392            paddr_t     nline;
3393            size_t      way = r_dcache_flush_count.read()/m_icache_sets;
3394            size_t      set = r_dcache_flush_count.read()%m_icache_sets;
3395
3396            bool        cleanup_req = r_dcache.inval( way,
3397                                                      set,
3398                                                      &nline );
3399            if ( cleanup_req ) 
3400            {
3401                r_dcache_cleanup_req  = true;
3402                r_dcache_cleanup_line = nline;
3403            }
3404
3405            r_dcache_flush_count = r_dcache_flush_count.read() + 1;
3406
3407            if ( r_dcache_flush_count.read() == (m_dcache_sets*m_dcache_ways - 1) )     // last slot
3408            {
3409                r_dtlb.reset();   
3410                r_itlb.reset(); 
3411                for (size_t line = 0; line < m_dcache_ways*m_dcache_sets; line++)
3412                {
3413                    r_dcache_in_tlb[line]       = false;
3414                    r_dcache_contains_ptd[line] = false;
3415                }
3416                r_dcache_fsm = DCACHE_IDLE;
3417                m_drsp.valid = true;
3418            }
3419        }
3420        break;
3421    }
3422    /////////////////////////
3423    case DCACHE_XTN_DT_INVAL:   // handling processor XTN_DTLB_INVAL request
3424    {
3425        r_dtlb.inval(r_dcache_p0_wdata.read());
3426        r_dcache_fsm        = DCACHE_IDLE;
3427        m_drsp.valid          = true;
3428        break;
3429    }
3430    ////////////////////////////
3431    case DCACHE_XTN_DC_INVAL_VA:  // selective cache line invalidate with virtual address
3432                                  // requires 3 cycles: access tlb, read cache, inval cache
3433                                  // we compute the physical address in this state
3434    {
3435        paddr_t paddr;
3436        bool    hit;
3437
3438        if ( r_mmu_mode.read() & DATA_TLB_MASK )        // dtlb activated
3439        {
3440#ifdef INSTRUMENTATION
3441m_cpt_dtlb_read++;
3442#endif
3443            hit = r_dtlb.translate( r_dcache_p0_wdata.read(),
3444                                    &paddr ); 
3445        }
3446        else                                            // dtlb not activated
3447        {
3448            paddr = (paddr_t)r_dcache_p0_wdata.read();
3449            hit   = true;
3450        }
3451
3452        if ( hit )              // tlb hit
3453        {
3454            r_dcache_p0_paddr = paddr;
3455            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_PA;
3456        }
3457        else                    // tlb miss
3458        {
3459#ifdef INSTRUMENTATION
3460m_cpt_dtlb_miss++;
3461#endif
3462            r_dcache_tlb_ins    = false;                // dtlb
3463            r_dcache_tlb_vaddr  = r_dcache_p0_wdata.read();
3464            r_dcache_fsm        = DCACHE_TLB_MISS; 
3465        } 
3466 
3467#if DEBUG_DCACHE
3468if ( m_debug_dcache_fsm )
3469{
3470    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_VA> Compute physical address" << std::hex
3471              << " / VADDR = " << r_dcache_p0_wdata.read()
3472              << " / PADDR = " << paddr << std::endl;
3473}
3474#endif
3475
3476        break;
3477    }
3478    ////////////////////////////
3479    case DCACHE_XTN_DC_INVAL_PA:  // selective cache line invalidate with physical address
3480                                  // requires 2 cycles: read cache / inval cache
3481                                  // In this state we read dcache.
3482    {
3483        uint32_t        data;
3484        size_t          way;
3485        size_t          set;
3486        size_t          word;
3487        bool            hit = r_dcache.read( r_dcache_p0_paddr.read(),
3488                                             &data,
3489                                             &way,
3490                                             &set,
3491                                             &word );
3492#ifdef INSTRUMENTATION
3493m_cpt_dcache_data_read++;
3494m_cpt_dcache_dir_read++;
3495#endif
3496        if ( hit )      // inval to be done
3497        {
3498            r_dcache_xtn_way = way;
3499            r_dcache_xtn_set = set;
3500            r_dcache_fsm      = DCACHE_XTN_DC_INVAL_GO;
3501        }
3502        else            // miss : nothing to do
3503        {
3504            r_dcache_fsm      = DCACHE_IDLE;
3505            m_drsp.valid        = true;
3506        }
3507
3508#if DEBUG_DCACHE
3509if ( m_debug_dcache_fsm )
3510{
3511    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_PA> Test hit in dcache" << std::hex
3512              << " / PADDR = " << r_dcache_p0_paddr.read() << std::dec
3513              << " / HIT = " << hit
3514              << " / SET = " << set
3515              << " / WAY = " << way << std::endl;
3516}
3517#endif
3518        break;
3519    }
3520    ////////////////////////////
3521    case DCACHE_XTN_DC_INVAL_GO:  // In this state, we invalidate the cache line
3522                                  // Blocked if previous cleanup not completed
3523                                  // Test if itlb or dtlb inval is required   
3524    {
3525        if ( not r_dcache_cleanup_req.read() )
3526        {
3527            paddr_t     nline;
3528            size_t      way        = r_dcache_xtn_way.read();
3529            size_t      set        = r_dcache_xtn_set.read();
3530            bool hit;
3531   
3532            hit = r_dcache.inval( way,
3533                                  set,
3534                                  &nline );
3535            assert(hit && "XTN_DC_INVAL way/set should still be in cache");
3536
3537            // request cleanup
3538            r_dcache_cleanup_req  = true;
3539            r_dcache_cleanup_line = nline;
3540           
3541            // possible itlb & dtlb invalidate
3542            if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3543            {
3544                r_dcache_tlb_inval_line  = nline;
3545                r_dcache_tlb_inval_count = 0;
3546                r_dcache_fsm_save        = DCACHE_XTN_DC_INVAL_END;
3547                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3548                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3549            }
3550            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3551            {
3552                r_itlb.reset();
3553                r_dtlb.reset();
3554                r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3555                r_dcache_fsm = DCACHE_IDLE;
3556                m_drsp.valid = true;
3557            }
3558            else
3559            {
3560                r_dcache_fsm = DCACHE_IDLE;
3561                m_drsp.valid = true;
3562            }
3563
3564#if DEBUG_DCACHE
3565if ( m_debug_dcache_fsm )
3566{
3567    std::cout << "  <PROC.DCACHE_XTN_DC_INVAL_GO> Actual dcache inval" << std::hex
3568              << " / NLINE = " << nline << std::endl;
3569}
3570#endif
3571        }
3572        break;
3573    }
3574    //////////////////////////////
3575    case DCACHE_XTN_DC_INVAL_END:       // send response to processor XTN request
3576    {
3577        r_dcache_fsm = DCACHE_IDLE;
3578        m_drsp.valid = true;
3579        break;
3580    }
3581    ////////////////////////
3582    case DCACHE_MISS_VICTIM:            // Selects a victim line
3583                                        // Set the r_dcache_cleanup_req flip-flop
3584                                        // when the selected slot is not empty
3585    {
3586        bool      valid;
3587        size_t    way;
3588        size_t    set;
3589        paddr_t   victim;
3590
3591        valid = r_dcache.victim_select( r_dcache_vci_paddr.read(),
3592                                        &victim,
3593                                        &way,
3594                                        &set );
3595        r_dcache_miss_way = way;
3596        r_dcache_miss_set = set;
3597
3598        if ( valid )
3599        {
3600            r_dcache_cleanup_req  = true;
3601            r_dcache_cleanup_line = victim;
3602            r_dcache_fsm          = DCACHE_MISS_INVAL;
3603        }
3604        else
3605        {
3606            r_dcache_fsm          = DCACHE_MISS_WAIT;
3607        }
3608
3609#if DEBUG_DCACHE
3610if ( m_debug_dcache_fsm )
3611{
3612    std::cout << "  <PROC.DCACHE_MISS_VICTIM> Select a slot:"
3613              << " / way = "   << way
3614              << " / set = "   << set
3615              << " / valid = "  << valid
3616              << " / line = " << std::hex << victim << std::endl; 
3617}
3618#endif
3619        break;
3620    }
3621    ///////////////////////
3622    case DCACHE_MISS_INVAL:             // invalidate the victim line
3623                                        // and possibly request itlb or dtlb invalidate
3624    {
3625        paddr_t nline;
3626        size_t  way        = r_dcache_miss_way.read();
3627        size_t  set        = r_dcache_miss_set.read();
3628        bool hit;
3629
3630        hit = r_dcache.inval( way, 
3631                        set,
3632                        &nline );
3633        assert(hit && "selected way/set line should be in dcache");
3634
3635#if DEBUG_DCACHE
3636if ( m_debug_dcache_fsm )
3637{
3638    std::cout << "  <PROC.DCACHE_MISS_INVAL> inval line:"
3639              << " / way = "   << way
3640              << " / set = "   << set
3641              << " / nline = "  << std::hex << nline << std::endl; 
3642}
3643#endif
3644        // if selective itlb & dtlb invalidate are required
3645        // the miss response is not handled before invalidate completed
3646        if ( r_dcache_in_tlb[way*m_dcache_sets+set] ) 
3647        {
3648            r_dcache_tlb_inval_line  = nline;
3649            r_dcache_tlb_inval_count = 0;
3650            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
3651            r_dcache_fsm_save        = DCACHE_MISS_WAIT;
3652            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3653        }
3654        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] ) 
3655        {
3656            r_itlb.reset();
3657            r_dtlb.reset();
3658            r_dcache_fsm             = DCACHE_MISS_WAIT;
3659        }
3660        else
3661        {
3662            r_dcache_fsm             = DCACHE_MISS_WAIT;
3663        }
3664        break;
3665    }
3666    //////////////////////
3667    case DCACHE_MISS_WAIT:      // waiting the response to a miss request from VCI_RSP FSM
3668                                // This state is in charge of error signaling
3669                                // There is 5 types of error depending on the requester
3670    {
3671        // external coherence request
3672        if ( r_tgt_dcache_req ) 
3673        {
3674            r_dcache_fsm = DCACHE_CC_CHECK;
3675            r_dcache_fsm_save = r_dcache_fsm;
3676            break;
3677        }
3678
3679        if ( r_vci_rsp_data_error.read() )                      // bus error
3680        {
3681            switch ( r_dcache_miss_type.read() )
3682            {
3683                case PROC_MISS: 
3684                {
3685                    r_mmu_detr            = MMU_READ_DATA_ILLEGAL_ACCESS; 
3686                    r_mmu_dbvar           = r_dcache_p0_vaddr.read();
3687                    m_drsp.valid            = true;
3688                    m_drsp.error            = true;
3689                    r_dcache_fsm          = DCACHE_IDLE;
3690                    break;
3691                }
3692                case PTE1_MISS:
3693                {
3694                    if ( r_dcache_tlb_ins.read() )
3695                    {
3696                        r_mmu_ietr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3697                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3698                        r_icache_tlb_miss_req   = false;
3699                        r_icache_tlb_rsp_error  = true;
3700                    }
3701                    else
3702                    {
3703                        r_mmu_detr              = MMU_READ_PT1_ILLEGAL_ACCESS;
3704                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3705                        m_drsp.valid              = true;
3706                        m_drsp.error              = true;
3707                    }
3708                    r_dcache_fsm                = DCACHE_IDLE;
3709                    break;
3710                }
3711                case PTE2_MISS: 
3712                {
3713                    if ( r_dcache_tlb_ins.read() )
3714                    {
3715                        r_mmu_ietr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3716                        r_mmu_ibvar             = r_dcache_tlb_vaddr.read();
3717                        r_icache_tlb_miss_req   = false;
3718                        r_icache_tlb_rsp_error  = true;
3719                    }
3720                    else
3721                    {
3722                        r_mmu_detr              = MMU_READ_PT2_ILLEGAL_ACCESS;
3723                        r_mmu_dbvar             = r_dcache_tlb_vaddr.read();
3724                        m_drsp.valid              = true;
3725                        m_drsp.error              = true;
3726                    }
3727                    r_dcache_fsm                = DCACHE_IDLE;
3728                    break;
3729                }
3730            } // end switch type
3731            r_vci_rsp_data_error = false;
3732        }
3733        else if ( r_vci_rsp_fifo_dcache.rok() )         // valid response available
3734        {
3735            r_dcache_miss_word = 0;
3736            r_dcache_fsm       = DCACHE_MISS_UPDT;
3737        }       
3738        break;
3739    }
3740    //////////////////////
3741    case DCACHE_MISS_UPDT:      // update the dcache (one word per cycle)
3742                                // returns the response depending on the miss type
3743    {
3744        if ( r_vci_rsp_fifo_dcache.rok() )      // one word available
3745        {
3746            if ( r_dcache_miss_inval.read() )   // Matching coherence request
3747                                                // pop the FIFO, without cache update
3748                                                // send a cleanup for the missing line
3749                                                // if the previous cleanup is completed
3750            {
3751                if ( r_dcache_miss_word.read() < (m_dcache_words - 1) )     // not the last
3752                {
3753                    vci_rsp_fifo_dcache_get = true;
3754                    r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3755                }
3756                else                                                    // last word
3757                {
3758                    if ( not r_dcache_cleanup_req.read() )      // no pending cleanup
3759                    {
3760                        vci_rsp_fifo_dcache_get = true;
3761                        r_dcache_cleanup_req    = true;
3762                        r_dcache_cleanup_line   = r_dcache_vci_paddr.read() >> 
3763                                                     (uint32_log2(m_dcache_words)+2);
3764                        r_dcache_miss_inval     = false;
3765                        r_dcache_fsm            = DCACHE_IDLE;
3766                    }
3767                }
3768            }
3769            else                                // No matching coherence request
3770                                                // pop the FIFO and update the cache
3771                                                // update the directory at the last word
3772            {
3773                 size_t way  = r_dcache_miss_way.read();
3774                 size_t set  = r_dcache_miss_set.read();
3775                 size_t word = r_dcache_miss_word.read();
3776
3777#ifdef INSTRUMENTATION
3778m_cpt_dcache_data_write++;
3779#endif
3780                r_dcache.write( way,
3781                                set,
3782                                word,
3783                                r_vci_rsp_fifo_dcache.read());
3784
3785                vci_rsp_fifo_dcache_get = true;
3786                r_dcache_miss_word = r_dcache_miss_word.read() + 1;
3787               
3788                // if last word, update directory, set in_tlb & contains_ptd bits
3789                if ( r_dcache_miss_word.read() == (m_dcache_words - 1) ) 
3790                {
3791
3792#ifdef INSTRUMENTATION
3793m_cpt_dcache_dir_write++;
3794#endif
3795                    r_dcache.victim_update_tag( r_dcache_vci_paddr.read(),
3796                                                r_dcache_miss_way.read(),
3797                                                r_dcache_miss_set.read() );
3798
3799                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
3800                    r_dcache_contains_ptd[way*m_dcache_sets+set] = false;
3801                   
3802                    if      (r_dcache_miss_type.read()==PTE1_MISS) r_dcache_fsm = DCACHE_TLB_PTE1_GET; 
3803                    else if (r_dcache_miss_type.read()==PTE2_MISS) r_dcache_fsm = DCACHE_TLB_PTE2_GET;
3804                    else                                           r_dcache_fsm = DCACHE_IDLE;
3805                }
3806            }
3807
3808#if DEBUG_DCACHE
3809if ( m_debug_dcache_fsm )
3810{
3811    if ( r_dcache_miss_inval.read() )
3812    {
3813        if ( r_dcache_miss_word.read() < m_dcache_words-1 ) 
3814        {
3815            std::cout << "  <PROC.DCACHE_MISS_UPDT> Matching coherence request:"
3816                      << "  pop the FIFO, don't update the cache" << std::endl;
3817        }
3818        else
3819        {
3820            std::cout << "  <PROC.DCACHE_MISS_UPDT> Matching coherence request:"
3821                      << " last word : send a cleanup request " << std::endl;
3822        }
3823    }
3824    else
3825    {
3826        std::cout << "  <PROC.DCACHE_MISS_UPDT> Write one word:"
3827                  << " address = " << r_dcache_vci_paddr.read() 
3828                  << " / data = "  << r_vci_rsp_fifo_dcache.read()
3829                  << " / way = "   << r_dcache_miss_way.read() 
3830                  << " / set = "   << r_dcache_miss_set.read()
3831                  << " / word = "  << r_dcache_miss_word.read() << std::endl; 
3832    }
3833}
3834#endif
3835 
3836        } // end if rok
3837        break;
3838    }
3839    /////////////////////
3840    case DCACHE_UNC_WAIT:
3841    {
3842        // external coherence request
3843        if ( r_tgt_dcache_req.read() ) 
3844        {
3845            r_dcache_fsm = DCACHE_CC_CHECK;
3846            r_dcache_fsm_save = r_dcache_fsm;
3847            break;
3848        }
3849
3850        if ( r_vci_rsp_data_error.read() )      // bus error
3851        {
3852            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3853            r_mmu_dbvar          = m_dreq.addr;
3854            r_vci_rsp_data_error = false;
3855            m_drsp.error           = true;
3856            m_drsp.valid           = true;
3857            r_dcache_fsm         = DCACHE_IDLE;
3858            break;
3859        }
3860        else if ( r_vci_rsp_fifo_dcache.rok() )     // data available
3861        {
3862            vci_rsp_fifo_dcache_get = true;     
3863            r_dcache_fsm            = DCACHE_IDLE;
3864            // we acknowledge the processor request if it has not been modified
3865            if ( m_dreq.valid and (m_dreq.addr == r_dcache_p0_vaddr.read()) )
3866            {
3867                m_drsp.valid          = true;
3868                m_drsp.rdata          = r_vci_rsp_fifo_dcache.read();
3869            }
3870        }       
3871        break;
3872    }
3873    ////////////////////
3874    case DCACHE_SC_WAIT:        // waiting VCI response after a processor SC request
3875    {
3876        // external coherence request
3877        if ( r_tgt_dcache_req.read() ) 
3878        {
3879            r_dcache_fsm = DCACHE_CC_CHECK;
3880            r_dcache_fsm_save = r_dcache_fsm;
3881            break;
3882        }
3883
3884        if ( r_vci_rsp_data_error.read() )              // bus error
3885        {
3886            r_mmu_detr           = MMU_READ_DATA_ILLEGAL_ACCESS; 
3887            r_mmu_dbvar          = m_dreq.addr;
3888            r_vci_rsp_data_error = false;
3889            m_drsp.error         = true;
3890            m_drsp.valid         = true;
3891            r_dcache_fsm         = DCACHE_IDLE;
3892            break;
3893        }
3894        else if ( r_vci_rsp_fifo_dcache.rok() )         // response available
3895        {
3896            vci_rsp_fifo_dcache_get = true;     
3897            m_drsp.valid            = true;
3898            m_drsp.rdata            = r_vci_rsp_fifo_dcache.read();
3899            r_dcache_fsm            = DCACHE_IDLE;
3900        }       
3901        break;
3902    }
3903    //////////////////////////
3904    case DCACHE_DIRTY_GET_PTE:          // This sub_fsm set the PTE Dirty bit in memory
3905                                        // before handling a processor WRITE or SC request 
3906                                        // Input argument is r_dcache_dirty_paddr
3907                                        // In this first state, we get PTE value in dcache
3908                                        // and post a SC request to CMD FSM
3909    {
3910        // get PTE in dcache
3911        uint32_t pte;
3912        size_t   way;
3913        size_t   set;
3914        size_t   word;  // unused
3915        bool     hit = r_dcache.read( r_dcache_dirty_paddr.read(),
3916                                      &pte,
3917                                      &way,
3918                                      &set,
3919                                      &word );
3920#ifdef INSTRUMENTATION
3921m_cpt_dcache_data_read++;
3922m_cpt_dcache_dir_read++;
3923#endif
3924        assert( hit and "error in DCACHE_DIRTY_TLB_SET: the PTE should be in dcache" );
3925
3926        // request sc transaction to CMD_FSM
3927        r_dcache_dirty_way  = way; 
3928        r_dcache_dirty_set  = set; 
3929        r_dcache_vci_sc_req = true;
3930        r_dcache_vci_paddr  = r_dcache_dirty_paddr.read();
3931        r_dcache_vci_sc_old = pte;
3932        r_dcache_vci_sc_new = pte | PTE_D_MASK;
3933        r_dcache_fsm        = DCACHE_DIRTY_SC_WAIT;
3934
3935#if DEBUG_DCACHE
3936if ( m_debug_dcache_fsm )
3937{
3938    std::cout << "  <PROC.DCACHE_DIRTY_GET_PTE> Get PTE in dcache" << std::hex
3939              << " / PTE_PADDR = " << r_dcache_dirty_paddr.read() 
3940              << " / PTE_VALUE = " << pte << std::dec
3941              << " / CACHE_SET = " << set
3942              << " / CACHE_WAY = " << way << std::endl;
3943}
3944#endif
3945        break;
3946    }
3947    //////////////////////////
3948    case DCACHE_DIRTY_SC_WAIT:          // wait completion of SC for PTE Dirty bit
3949                                        // If the PTE update is a success, return to IDLE state.
3950                                        // If the PTE update is a failure, invalidate the cache line
3951                                        // in DCACHE and invalidate the matching TLB entries.
3952    {
3953        // external coherence request
3954        if ( r_tgt_dcache_req ) 
3955        {
3956            r_dcache_fsm = DCACHE_CC_CHECK;
3957            r_dcache_fsm_save = r_dcache_fsm;
3958            break;
3959        }
3960
3961        if ( r_vci_rsp_data_error.read() )      // bus error
3962        {
3963            std::cout << "BUS ERROR in DCACHE_DIRTY_SC_WAIT state" << std::endl;
3964            std::cout << "This should not happen in this state" << std::endl;
3965            exit(0);
3966        }
3967        else if ( r_vci_rsp_fifo_dcache.rok() ) // response available
3968        {
3969            vci_rsp_fifo_dcache_get = true;
3970            if ( r_vci_rsp_fifo_dcache.read() == 0 )    // exit if dirty bit update atomic
3971            {
3972                r_dcache_fsm = DCACHE_IDLE;
3973
3974#if DEBUG_DCACHE
3975if ( m_debug_dcache_fsm )
3976{
3977    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> Dirty bit successfully set"
3978              << std::endl;
3979}
3980#endif
3981            }
3982            else                                // invalidate the cache line and TLBs
3983            {
3984                paddr_t nline;
3985                size_t  way = r_dcache_dirty_way.read();
3986                size_t  set = r_dcache_dirty_set.read();
3987                bool hit;
3988
3989                hit = r_dcache.inval( r_dcache_dirty_way.read(), 
3990                                r_dcache_dirty_set.read(),
3991                                &nline );
3992                assert(hit && "PTE should still be in dcache");
3993                // request cleanup
3994                r_dcache_cleanup_req  = true;
3995                r_dcache_cleanup_line = nline;
3996
3997                if ( r_dcache_in_tlb[way*m_dcache_sets+set] )           // contains PTE
3998                {
3999                    r_dcache_tlb_inval_line  = nline;
4000                    r_dcache_tlb_inval_count = 0;
4001                    r_dcache_fsm_save        = DCACHE_IDLE;
4002                    r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4003                    r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4004                } 
4005                if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )     // contains PTD
4006                {
4007                    r_itlb.reset();
4008                    r_dtlb.reset();
4009                    r_dcache_fsm = DCACHE_IDLE;
4010                }
4011#if DEBUG_DCACHE
4012if ( m_debug_dcache_fsm )
4013{
4014    std::cout << "  <PROC.DCACHE_DIRTY_SC_WAIT> PTE modified : Inval cache line & TLBs"
4015              << std::endl;
4016}
4017#endif
4018            }
4019        }
4020        break;
4021    }
4022    /////////////////////
4023    case DCACHE_CC_CHECK:   // This state is the entry point for the sub-FSM
4024                            // handling coherence requests.
4025                            // If there is a matching pending miss on the modified cache
4026                            // line this is signaled in the r_dcache_miss inval flip-flop.
4027                            // If the updated (or invalidated) cache line has copies in TLBs
4028                            // these TLB copies are invalidated.
4029                            // The return state is defined in r_dcache_fsm_save
4030    {
4031        paddr_t  paddr = r_tgt_paddr.read();
4032        paddr_t  mask = ~((m_dcache_words<<2)-1);
4033
4034
4035        if( (r_dcache_fsm_save == DCACHE_MISS_WAIT) and
4036            ((r_dcache_vci_paddr.read() & mask) == (paddr & mask)) ) // matching pending miss
4037        {
4038            r_dcache_miss_inval = true;                 // signaling the match
4039            r_tgt_dcache_req    = false;                // coherence request completed
4040            r_tgt_dcache_rsp    = r_tgt_update.read();  // response required if update
4041            r_dcache_fsm        = r_dcache_fsm_save;
4042
4043#if DEBUG_DCACHE
4044if ( m_debug_dcache_fsm )
4045{
4046    std::cout << "  <PROC.DCACHE_CC_CHECK> Coherence request matching a pending miss:"
4047              << " address = " << std::hex << paddr << std::endl;
4048}
4049#endif
4050 
4051        }
4052        else                                                            // no match
4053        {
4054            uint32_t    rdata;
4055            size_t      way;
4056            size_t      set;
4057            size_t      word;
4058
4059            bool        hit = r_dcache.read(paddr,
4060                                            &rdata,     // unused
4061                                            &way, 
4062                                            &set,
4063                                            &word);     // unused
4064#ifdef INSTRUMENTATION
4065m_cpt_dcache_data_read++;
4066m_cpt_dcache_dir_read++;
4067#endif
4068            r_dcache_cc_way = way;
4069            r_dcache_cc_set = set;
4070
4071            if ( hit and r_tgt_update.read() )          // hit update
4072            {
4073                r_dcache_fsm     = DCACHE_CC_UPDT;
4074                r_dcache_cc_word = r_tgt_word_min.read();
4075            }
4076            else if ( hit and not r_tgt_update.read() ) // hit inval
4077            {
4078                r_dcache_fsm     = DCACHE_CC_INVAL;
4079            }
4080            else                                        // miss can happen
4081            {
4082                r_tgt_dcache_req = false;
4083                r_tgt_dcache_rsp = r_tgt_update.read();
4084                r_dcache_fsm     = r_dcache_fsm_save.read();
4085            }
4086
4087#if DEBUG_DCACHE
4088if ( m_debug_dcache_fsm )
4089{
4090   
4091    std::cout << "  <PROC.DCACHE_CC_CHECK> Coherence request received :"
4092              << " address = " << std::hex << paddr << std::dec;
4093    if ( hit ) 
4094    {
4095        std::cout << " / HIT" << " / way = " << way << " / set = " << set << std::endl;
4096    }
4097    else
4098    {
4099        std::cout << " / MISS" << std::endl;
4100    }
4101}
4102#endif
4103 
4104        }
4105        break;
4106    }
4107    /////////////////////
4108    case DCACHE_CC_INVAL:       // invalidate one cache line
4109                                // and test possible copies in TLBs
4110    {
4111        paddr_t nline;
4112        size_t  way        = r_dcache_cc_way.read();
4113        size_t  set        = r_dcache_cc_set.read();
4114        bool hit;
4115
4116        hit = r_dcache.inval( way, 
4117                              set,
4118                              &nline );
4119        assert(hit && "CC_INVAL way/set should still be in dcache");
4120           
4121        // possible itlb & dtlb invalidate
4122        if ( r_dcache_in_tlb[way*m_dcache_sets+set] )                   // selective inval
4123        {
4124            r_dcache_tlb_inval_line  = nline;
4125            r_dcache_tlb_inval_count = 0;
4126            r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4127            r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4128        }
4129        else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )        // flush
4130        {
4131            r_itlb.reset();
4132            r_dtlb.reset();
4133            r_tgt_dcache_rsp = true;
4134            r_tgt_dcache_req = false;
4135            r_dcache_fsm     = r_dcache_fsm_save.read();
4136        }
4137        else                                                            // no inval
4138        {
4139            r_tgt_dcache_rsp = true;
4140            r_tgt_dcache_req = false;
4141            r_dcache_fsm     = r_dcache_fsm_save.read();
4142        }
4143
4144#if DEBUG_DCACHE
4145if ( m_debug_dcache_fsm )
4146{
4147    std::cout << "  <PROC.DCACHE_CC_INVAL> Invalidate cache line" << std::dec
4148              << " / WAY = " << way
4149              << " / SET = " << set << std::endl;
4150}
4151#endif
4152 
4153        break;
4154    }
4155    ///////////////////
4156    case DCACHE_CC_UPDT:        // write one word per cycle (from word_min to word_max)
4157                                // and test possible copies in TLBs
4158    {
4159        size_t   word       = r_dcache_cc_word.read();
4160        size_t   way        = r_dcache_cc_way.read();
4161        size_t   set        = r_dcache_cc_set.read();
4162        paddr_t  nline      = r_tgt_paddr.read() >> (uint32_log2(m_dcache_words)+2);
4163
4164        r_dcache.write( way,
4165                        set,
4166                        word,
4167                        r_tgt_buf[word],
4168                        r_tgt_be[word] );
4169#ifdef INSTRUMENTATION
4170m_cpt_dcache_data_write++;
4171#endif
4172        r_dcache_cc_word = word + 1;
4173
4174        if ( word == r_tgt_word_max.read() )    // last word
4175        {
4176            // possible itlb & dtlb invalidate
4177            if ( r_dcache_in_tlb[way*m_dcache_sets+set] )               // selective inval
4178            {
4179                r_dcache_tlb_inval_line  = nline;
4180                r_dcache_tlb_inval_count = 0;
4181                r_dcache_fsm             = DCACHE_INVAL_TLB_SCAN;
4182                r_dcache_in_tlb[way*m_dcache_sets+set] = false;
4183            }
4184            else if ( r_dcache_contains_ptd[way*m_dcache_sets+set] )    // flush
4185            {
4186                r_itlb.reset();
4187                r_dtlb.reset();
4188                r_tgt_dcache_rsp = true;
4189                r_tgt_dcache_req = false;
4190                r_dcache_fsm     = r_dcache_fsm_save.read();
4191            }
4192            else                                                        // no inval
4193            {
4194                r_tgt_dcache_rsp = true;
4195                r_tgt_dcache_req = false;
4196                r_dcache_fsm     = r_dcache_fsm_save.read();
4197            }
4198        }
4199
4200#if DEBUG_DCACHE
4201if ( m_debug_dcache_fsm )
4202{
4203    std::cout << "  <PROC.DCACHE_CC_UPDT> Update one word" << std::dec
4204              << " / WAY = " << way
4205              << " / SET = " << set
4206              << " / WORD = " << word
4207              << " / VALUE = " << std::hex << r_tgt_buf[word] << std::endl;
4208}
4209#endif
4210 
4211        break;
4212    }
4213    ///////////////////////////
4214    case DCACHE_INVAL_TLB_SCAN:         // Scan sequencially all TLB entries for both ITLB & DTLB
4215                                        // It makes the assumption that (m_itlb_sets == m_dtlb_sets)
4216                                        // and (m_itlb_ways == m_dtlb_ways)
4217                                        // We enter this state when a DCACHE line is modified,
4218                                        // and there is a copy in itlb or dtlb.
4219                                        // It can be caused by:
4220                                        // - a coherence inval or updt transaction,
4221                                        // - a line inval caused by a cache miss
4222                                        // - a processor XTN inval request,
4223                                        // - a WRITE hit,
4224                                        // - a Dirty bit update failure
4225                                        // Input arguments are:
4226                                        // - r_dcache_tlb_inval_line
4227                                        // - r_dcache_tlb_inval_count
4228                                        // - r_dcache_fsm_save
4229    {
4230        paddr_t line = r_dcache_tlb_inval_line.read();                  // nline
4231        size_t  way  = r_dcache_tlb_inval_count.read()/m_itlb_sets;     // way
4232        size_t  set  = r_dcache_tlb_inval_count.read()%m_itlb_sets;     // set
4233        bool    ok;
4234
4235        ok = r_itlb.inval( line,
4236                            way,
4237                            set );
4238#if DEBUG_DCACHE
4239if ( m_debug_dcache_fsm and ok )
4240{
4241    std::cout << "  <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate ITLB entry:" << std::hex
4242              << " line = " << line << std::dec
4243              << " / set = " << set
4244              << " / way = " << way << std::endl;
4245    r_itlb.printTrace();
4246}
4247#endif
4248        ok = r_dtlb.inval( line,
4249                           way,
4250                           set );
4251#if DEBUG_DCACHE
4252if ( m_debug_dcache_fsm and ok )
4253{
4254    std::cout << "  <PROC.DCACHE_INVAL_TLB_SCAN> Invalidate DTLB entry:" << std::hex
4255              << " line = " << line << std::dec
4256              << " / set = " << set
4257              << " / way = " << way << std::endl;
4258    r_dtlb.printTrace();
4259}
4260#endif
4261
4262        // return to the calling state when TLB inval completed
4263        if ( r_dcache_tlb_inval_count.read() == (m_dtlb_sets*m_dtlb_ways-1) )
4264        {
4265            if ( r_tgt_dcache_req.read() ) // It's a coherence request
4266            {
4267                r_tgt_dcache_rsp    = true;
4268                r_tgt_dcache_req    = false;
4269            }
4270            r_dcache_fsm            = r_dcache_fsm_save.read();
4271        }
4272        r_dcache_tlb_inval_count = r_dcache_tlb_inval_count.read() + 1;
4273    }   
4274    } // end switch r_dcache_fsm
4275
4276    ///////////////// wbuf update //////////////////////////////////////////////////////
4277    r_wbuf.update();
4278
4279    //////////////// test processor frozen /////////////////////////////////////////////
4280    // The simulation exit if the number of consecutive frozen cycles
4281    // is larger than the m_max_frozen_cycles (constructor parameter)
4282    if ( (m_ireq.valid and not m_irsp.valid) or (m_dreq.valid and not m_drsp.valid) )       
4283    {
4284        m_cpt_frz_cycles++;             // used for instrumentation
4285        m_cpt_stop_simulation++;        // used for debug
4286        if ( m_cpt_stop_simulation > m_max_frozen_cycles )
4287        {
4288            std::cout << std::dec << "ERROR in CC_VCACHE_WRAPPER " << name() << std::endl
4289                      << " stop at cycle " << m_cpt_total_cycles << std::endl
4290                      << " frozen since cycle " << m_cpt_total_cycles - m_max_frozen_cycles
4291                      << std::endl;
4292            exit(1);
4293        }
4294    }
4295    else
4296    {
4297        m_cpt_stop_simulation = 0;
4298    }
4299
4300    /////////// execute one iss cycle /////////////////////////////////
4301    {
4302    uint32_t it = 0;
4303    for (size_t i=0; i<(size_t)iss_t::n_irq; i++) if(p_irq[i].read()) it |= (1<<i);
4304    r_iss.executeNCycles(1, m_irsp, m_drsp, it);
4305    }
4306
4307    ////////////////////////////////////////////////////////////////////////////
4308    // The VCI_CMD FSM controls the following ressources:
4309    // - r_vci_cmd_fsm
4310    // - r_vci_cmd_min
4311    // - r_vci_cmd_max
4312    // - r_vci_cmd_cpt
4313    // - r_vci_cmd_imiss_prio
4314    // - wbuf (reset)
4315    // - r_icache_miss_req (reset)
4316    // - r_icache_unc_req (reset)
4317    // - r_dcache_vci_miss_req (reset)
4318    // - r_dcache_vci_unc_req (reset)
4319    // - r_dcache_vci_sc_req (reset)
4320    //
4321    // This FSM handles requests from both the DCACHE FSM & the ICACHE FSM.
4322    // There is 6 request types, with the following priorities :
4323    // 1 - Data Read Miss         : r_dcache_vci_miss_req and miss in the write buffer
4324    // 2 - Data Read Uncachable   : r_dcache_vci_unc_req 
4325    // 3 - Instruction Miss       : r_icache_miss_req and miss in the write buffer
4326    // 4 - Instruction Uncachable : r_icache_unc_req
4327    // 5 - Data Write             : r_wbuf.rok()     
4328    // 6 - Data Store Conditionnal: r_dcache_vci_sc_req
4329    //
4330    // As we want to support several simultaneous VCI transactions, the VCI_CMD_FSM
4331    // and the VCI_RSP_FSM are fully desynchronized.
4332    //
4333    // VCI formats:
4334    // According to the VCI advanced specification, all read requests packets
4335    // (data Uncached, Miss data, instruction Uncached, Miss instruction)
4336    // are one word packets.
4337    // For write burst packets, all words are in the same cache line,
4338    // and addresses must be contiguous (the BE field is 0 in case of "holes").
4339    // The sc command packet implements actually a compare-and-swap mechanism
4340    // and the packet contains two flits.
4341    ////////////////////////////////////////////////////////////////////////////////////
4342
4343    switch ( r_vci_cmd_fsm.read() ) 
4344    {
4345        //////////////
4346        case CMD_IDLE:
4347        {
4348            // r_dcache_vci_miss_req and r_icache_miss_req require both a write_buffer access
4349            // to check a possible pending write on the same cache line.
4350            // As there is only one possible access per cycle to write buffer, we implement
4351            // a round-robin priority for this access, using the r_vci_cmd_imiss_prio flip-flop.
4352
4353            size_t      wbuf_min;
4354            size_t      wbuf_max;
4355
4356            bool dcache_miss_req = r_dcache_vci_miss_req.read()
4357                 and ( not r_icache_miss_req.read() or not r_vci_cmd_imiss_prio.read() );
4358            bool icache_miss_req = r_icache_miss_req.read()
4359                 and ( not r_dcache_vci_miss_req.read() or r_vci_cmd_imiss_prio.read() );
4360
4361            // 1 - Data Read Miss
4362            if ( dcache_miss_req and r_wbuf.miss(r_dcache_vci_paddr.read()) )
4363            {
4364                r_vci_cmd_fsm         = CMD_DATA_MISS;
4365                r_dcache_vci_miss_req = false;
4366                r_vci_cmd_imiss_prio  = true;
4367//                m_cpt_dmiss_transaction++;
4368            }
4369            // 2 - Data Read Uncachable
4370            else if ( r_dcache_vci_unc_req.read() )
4371            {
4372                r_vci_cmd_fsm        = CMD_DATA_UNC;
4373                r_dcache_vci_unc_req = false;
4374//                m_cpt_dunc_transaction++;
4375            }
4376            // 3 - Instruction Miss
4377            else if ( icache_miss_req and r_wbuf.miss(r_icache_vci_paddr.read()) )
4378            {
4379                r_vci_cmd_fsm        = CMD_INS_MISS;
4380                r_icache_miss_req    = false;
4381                r_vci_cmd_imiss_prio = false;
4382//                m_cpt_imiss_transaction++;
4383            }
4384            // 4 - Instruction Uncachable
4385            else if ( r_icache_unc_req.read() )
4386            {
4387                r_vci_cmd_fsm    = CMD_INS_UNC;
4388                r_icache_unc_req = false;
4389//                m_cpt_iunc_transaction++;
4390            }
4391            // 5 - Data Write
4392            else if ( r_wbuf.rok(&wbuf_min, &wbuf_max) )
4393            {
4394                r_vci_cmd_fsm       = CMD_DATA_WRITE;
4395                r_vci_cmd_cpt       = wbuf_min;
4396                r_vci_cmd_min       = wbuf_min;
4397                r_vci_cmd_max       = wbuf_max;
4398//                m_cpt_write_transaction++;
4399//                m_length_write_transaction += (wbuf_max-wbuf_min+1);
4400            }
4401            // 6 - Data Store Conditionnal
4402            else if ( r_dcache_vci_sc_req.read() )
4403            {
4404                r_vci_cmd_fsm       = CMD_DATA_SC;
4405                r_dcache_vci_sc_req = false;
4406                r_vci_cmd_cpt       = 0;
4407//                m_cpt_sc_transaction++;
4408            }
4409            break;
4410        }
4411        ////////////////////
4412        case CMD_DATA_WRITE:
4413        {
4414            if ( p_vci_ini_d.cmdack.read() )
4415            {
4416//                m_conso_wbuf_read++;
4417                r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4418                if (r_vci_cmd_cpt == r_vci_cmd_max) // last flit sent
4419                {
4420                    r_vci_cmd_fsm = CMD_IDLE ;
4421                    r_wbuf.sent() ;
4422                }
4423            }
4424            break;
4425        }
4426        /////////////////
4427        case CMD_DATA_SC:
4428        {
4429            // The SC VCI command contains two flits
4430            if ( p_vci_ini_d.cmdack.read() )
4431            {
4432               r_vci_cmd_cpt = r_vci_cmd_cpt + 1;
4433               if (r_vci_cmd_cpt == 1) r_vci_cmd_fsm = CMD_IDLE ;
4434            }
4435            break;
4436        }
4437        //////////////////
4438        case CMD_INS_MISS:
4439        case CMD_INS_UNC:
4440        case CMD_DATA_MISS:
4441        case CMD_DATA_UNC:
4442        {
4443            // all read VCI commands contain one single flit
4444            if ( p_vci_ini_d.cmdack.read() )  r_vci_cmd_fsm = CMD_IDLE;
4445            break;
4446        }
4447
4448    } // end  switch r_vci_cmd_fsm
4449
4450    //////////////////////////////////////////////////////////////////////////
4451    // The VCI_RSP FSM controls the following ressources:
4452    // - r_vci_rsp_fsm:
4453    // - r_vci_rsp_fifo_icache (push)
4454    // - r_vci_rsp_fifo_dcache (push)
4455    // - r_vci_rsp_data_error (set)
4456    // - r_vci_rsp_ins_error (set)
4457    // - r_vci_rsp_cpt
4458    //
4459    // As the VCI_RSP and VCI_CMD are fully desynchronized to support several
4460    // simultaneous VCI transactions, this FSM uses the VCI TRDID field
4461    // to identify the transactions.
4462    //
4463    // VCI vormat:
4464    // This component checks the response packet length and accepts only
4465    // single word packets for write response packets.
4466    //
4467    // Error handling:
4468    // This FSM analyzes the VCI error code and signals directly the Write Bus Error.
4469    // In case of Read Data Error, the VCI_RSP FSM sets the r_vci_rsp_data_error
4470    // flip_flop and the error is signaled by the DCACHE FSM. 
4471    // In case of Instruction Error, the VCI_RSP FSM sets the r_vci_rsp_ins_error
4472    // flip_flop and the error is signaled by the ICACHE FSM. 
4473    // In case of Cleanup Error, the simulation stops with an error message...
4474    //////////////////////////////////////////////////////////////////////////
4475
4476    switch ( r_vci_rsp_fsm.read() ) 
4477    {
4478    //////////////
4479    case RSP_IDLE:
4480    {
4481        if ( p_vci_ini_d.rspval.read() )
4482        {
4483            r_vci_rsp_cpt = 0;
4484
4485            if ( (p_vci_ini_d.rtrdid.read() >> (vci_param::T-1)) != 0 ) // Write transaction
4486            {
4487                r_vci_rsp_fsm = RSP_DATA_WRITE;
4488            }
4489            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_MISS )
4490            {
4491                r_vci_rsp_fsm = RSP_INS_MISS;
4492            }
4493            else if ( p_vci_ini_d.rtrdid.read() == TYPE_INS_UNC )
4494            {
4495                r_vci_rsp_fsm = RSP_INS_UNC;
4496            }
4497            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_MISS )
4498            {
4499                r_vci_rsp_fsm = RSP_DATA_MISS;
4500            }
4501            else if ( p_vci_ini_d.rtrdid.read() == TYPE_DATA_UNC )
4502            {
4503                r_vci_rsp_fsm = RSP_DATA_UNC;
4504            }
4505            else
4506            {
4507                assert(false and "Unexpected VCI response");
4508            }
4509        }
4510        break;
4511    }
4512        //////////////////
4513        case RSP_INS_MISS:
4514        {
4515            if ( p_vci_ini_d.rspval.read() )
4516            {
4517                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4518                {
4519                    r_vci_rsp_ins_error = true;
4520                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4521                }
4522                else                                        // no error reported
4523                {
4524                    if ( r_vci_rsp_fifo_icache.wok() )
4525                    {
4526                        assert( (r_vci_rsp_cpt.read() < m_icache_words) and
4527                        "The VCI response packet for instruction miss is too long" );
4528
4529                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4530                        vci_rsp_fifo_icache_put       = true,
4531                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4532                        if ( p_vci_ini_d.reop.read() )
4533                        {
4534                            assert( (r_vci_rsp_cpt.read() == m_icache_words - 1) and
4535                            "The VCI response packet for instruction miss is too short");
4536
4537                            r_vci_rsp_fsm    = RSP_IDLE;
4538                        }
4539                    }
4540                }
4541            }
4542            break;
4543        }
4544        /////////////////
4545        case RSP_INS_UNC:
4546        {
4547            if (p_vci_ini_d.rspval.read() )
4548            {
4549                assert( p_vci_ini_d.reop.read() and
4550                "illegal VCI response packet for uncachable instruction");
4551
4552                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4553                {
4554                    r_vci_rsp_ins_error = true;
4555                    r_vci_rsp_fsm = RSP_IDLE;
4556                }
4557                else                                         // no error reported
4558                {
4559                    if ( r_vci_rsp_fifo_icache.wok())
4560                    {
4561                        vci_rsp_fifo_icache_put       = true;
4562                        vci_rsp_fifo_icache_data      = p_vci_ini_d.rdata.read();
4563                        r_vci_rsp_fsm = RSP_IDLE;
4564                    }
4565                }
4566            }
4567            break;
4568        }
4569        ///////////////////
4570        case RSP_DATA_MISS:
4571        {
4572            if ( p_vci_ini_d.rspval.read() )
4573            {
4574                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4575                {
4576                    r_vci_rsp_data_error = true;
4577                    if ( p_vci_ini_d.reop.read() ) r_vci_rsp_fsm = RSP_IDLE;
4578                }
4579                else                                        // no error reported
4580                {
4581                    if ( r_vci_rsp_fifo_dcache.wok() )
4582                    {
4583                        assert( (r_vci_rsp_cpt.read() < m_dcache_words) and
4584                        "The VCI response packet for data miss is too long");
4585
4586                        r_vci_rsp_cpt                 = r_vci_rsp_cpt.read() + 1;
4587                        vci_rsp_fifo_dcache_put       = true,
4588                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4589                        if ( p_vci_ini_d.reop.read() )
4590                        {
4591                            assert( (r_vci_rsp_cpt.read() == m_dcache_words - 1) and
4592                            "The VCI response packet for data miss is too short");
4593
4594                            r_vci_rsp_fsm     = RSP_IDLE;
4595                        }
4596                    }
4597                }
4598            }
4599            break;
4600        }
4601        //////////////////
4602        case RSP_DATA_UNC:
4603        {
4604            if (p_vci_ini_d.rspval.read() )
4605            {
4606                assert( p_vci_ini_d.reop.read() and
4607                "illegal VCI response packet for uncachable read data");
4608
4609                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 )  // error reported
4610                {
4611                    r_vci_rsp_data_error = true;
4612                    r_vci_rsp_fsm = RSP_IDLE;
4613                }
4614                else                                         // no error reported
4615                {
4616                    if ( r_vci_rsp_fifo_dcache.wok())
4617                    {
4618                        vci_rsp_fifo_dcache_put       = true;
4619                        vci_rsp_fifo_dcache_data      = p_vci_ini_d.rdata.read();
4620                        r_vci_rsp_fsm = RSP_IDLE;
4621                    }
4622                }
4623            }
4624            break;
4625        }
4626        ////////////////////
4627        case RSP_DATA_WRITE:
4628        {
4629            if (p_vci_ini_d.rspval.read())
4630            {
4631                assert( p_vci_ini_d.reop.read() and
4632                "a VCI response packet must contain one flit for a write transaction");
4633
4634                r_vci_rsp_fsm = RSP_IDLE;
4635                uint32_t   wbuf_index = p_vci_ini_d.rtrdid.read() - (1<<(vci_param::T-1));
4636                bool       cacheable  = r_wbuf.completed(wbuf_index);
4637                if ( not cacheable ) r_dcache_pending_unc_write = false;
4638                if ( (p_vci_ini_d.rerror.read()&0x1) != 0 ) r_iss.setWriteBerr();
4639            }
4640            break;
4641        }
4642    } // end switch r_vci_rsp_fsm
4643
4644    ////////////////////////////////////////////////////////////////////////////////
4645    // The CLEANUP FSM send the cleanup commands on the coherence network,
4646    // and supports simultaneous cleanup transactions, but two simultaneous
4647    // transactions mut address different cache lines.
4648    // Therefore, the line number is registered in an associative
4649    // registration buffer (Content Adressable Memory) by the CLEANUP FSM,
4650    // and the corresponding slot (identified by the VCI TRDID field) is cleared
4651    // when the cleanup transaction response is received.
4652    // It handles cleanup requests from both the DCACHE FSM & ICACHE FSM
4653    // with a round robin priority, and can support up to 4 simultaneous
4654    // cleanup transactions (4 slots in the registration buffer).
4655    // The r_dcache_cleanup_req (or r_icache_cleanup_req) flip-flops are reset
4656    // when the command has been sent.
4657    // The VCI TRDID field is used to distinguish data/instruction cleanups:
4658    // - if data cleanup        : TRDID = 2*index + 0
4659    // - if instruction cleanup : TRDID = 2*index + 1
4660    ////////////////////////////////////////////////////////////////////////////
4661
4662    switch ( r_cleanup_fsm.read() ) 
4663    {
4664        ///////////////////////
4665        case CLEANUP_DATA_IDLE:     // dcache has highest priority
4666        {
4667            size_t  index = 0;
4668            bool    ok;
4669            if ( r_dcache_cleanup_req.read() )      // dcache request
4670            {
4671                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(), 
4672                                                      &index );   
4673                if ( ok )   // successful registration
4674                {
4675                    r_cleanup_fsm   = CLEANUP_DATA_GO; 
4676                    r_cleanup_trdid = index<<1;
4677                }
4678            }
4679            else if ( r_icache_cleanup_req.read() ) // icache request
4680            {
4681                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(), 
4682                                                      &index );   
4683                if ( ok )   // successful registration
4684                {
4685                    r_cleanup_fsm   = CLEANUP_INS_GO; 
4686                    r_cleanup_trdid = (index<<1) + 1;
4687                }
4688            }
4689            break;
4690        }
4691        //////////////////////
4692        case CLEANUP_INS_IDLE:     // icache has highest priority
4693        {
4694            size_t  index = 0;
4695            bool    ok;
4696            if ( r_icache_cleanup_req.read() )      // icache request
4697            {
4698                ok = r_cleanup_buffer.register_value( r_icache_cleanup_line.read(),
4699                                                      &index );   
4700                if ( ok )   // successful registration
4701                {
4702                    r_cleanup_fsm   = CLEANUP_INS_GO;
4703                    r_cleanup_trdid = (index<<1) + 1;
4704                }
4705            }
4706            else if ( r_dcache_cleanup_req.read() ) // dcache request
4707            {
4708                ok = r_cleanup_buffer.register_value( r_dcache_cleanup_line.read(),
4709                                                      &index );   
4710                if ( ok )   // successful registration
4711                {
4712                    r_cleanup_fsm   = CLEANUP_DATA_GO;
4713                    r_cleanup_trdid = index<<1;
4714                }
4715            }
4716            break;
4717        }
4718        /////////////////////
4719        case CLEANUP_DATA_GO:
4720        {
4721            if ( p_vci_ini_c.cmdack.read() )
4722            {
4723                r_dcache_cleanup_req = false;
4724                r_cleanup_fsm        = CLEANUP_INS_IDLE;
4725
4726#if DEBUG_CLEANUP
4727if ( m_debug_cleanup_fsm )
4728{
4729    std::cout << "  <PROC.CLEANUP_DATA_GO> Cleanup request for icache:" << std::hex
4730              << " address = " << (r_dcache_cleanup_line.read()*m_dcache_words*4)
4731              << " / trdid = " << r_cleanup_trdid.read() << std::endl;
4732}
4733#endif
4734            }
4735            break;
4736        }
4737        ////////////////////////
4738        case CLEANUP_INS_GO:
4739        {
4740            if ( p_vci_ini_c.cmdack.read() )
4741            {
4742                r_icache_cleanup_req = false;
4743                r_cleanup_fsm        = CLEANUP_DATA_IDLE;
4744
4745#if DEBUG_CLEANUP
4746if ( m_debug_cleanup_fsm )
4747{
4748    std::cout << "  <PROC.CLEANUP_INS_GO> Cleanup request for dcache:" << std::hex
4749              << " address = " << (r_icache_cleanup_line.read()*m_icache_words*4)
4750              << " / trdid = " << r_cleanup_trdid.read() << std::endl;
4751}
4752#endif
4753            }
4754            break;
4755        }
4756    } // end switch CLEANUP FSM
4757
4758    //////////////// Handling  cleanup responses //////////////////
4759    if ( p_vci_ini_c.rspval.read() )    // valid response
4760    {
4761        r_cleanup_buffer.cancel_index( p_vci_ini_c.rtrdid.read() >> 1);
4762    }
4763
4764    ///////////////// Response FIFOs update  //////////////////////
4765    r_vci_rsp_fifo_icache.update(vci_rsp_fifo_icache_get,
4766                                 vci_rsp_fifo_icache_put,
4767                                 vci_rsp_fifo_icache_data);
4768
4769    r_vci_rsp_fifo_dcache.update(vci_rsp_fifo_dcache_get,
4770                                 vci_rsp_fifo_dcache_put,
4771                                 vci_rsp_fifo_dcache_data);
4772} // end transition()
4773
4774///////////////////////
4775tmpl(void)::genMoore()
4776///////////////////////
4777{
4778    ////////////////////////////////////////////////////////////////
4779    // VCI initiator command on the coherence network (cleanup)
4780    // it depends on the CLEANUP FSM state
4781
4782    paddr_t  address;
4783
4784    if ( r_cleanup_fsm.read() == CLEANUP_DATA_GO )
4785        address = r_dcache_cleanup_line.read()*m_dcache_words*4;
4786    else if ( r_cleanup_fsm.read() == CLEANUP_INS_GO )
4787        address = r_icache_cleanup_line.read()*m_icache_words*4;
4788    else
4789        address = 0;
4790
4791    p_vci_ini_c.cmdval  = ((r_cleanup_fsm.read() == CLEANUP_DATA_GO) or
4792                           (r_cleanup_fsm.read() == CLEANUP_INS_GO) );
4793    p_vci_ini_c.address = address;
4794    p_vci_ini_c.wdata   = 0;
4795    p_vci_ini_c.be      = 0xF;
4796    p_vci_ini_c.plen    = 4;
4797    p_vci_ini_c.cmd     = vci_param::CMD_WRITE;
4798    p_vci_ini_c.trdid   = r_cleanup_trdid.read();
4799    p_vci_ini_c.pktid   = 0;
4800    p_vci_ini_c.srcid   = m_srcid_c;
4801    p_vci_ini_c.cons    = false;
4802    p_vci_ini_c.wrap    = false;
4803    p_vci_ini_c.contig  = false;
4804    p_vci_ini_c.clen    = 0;
4805    p_vci_ini_c.cfixed  = false;
4806    p_vci_ini_c.eop     = true;
4807
4808    /////////////////////////////////////////////////////////////////
4809    // VCI initiator response on the coherence network (cleanup)
4810    // We always consume the response, and we don't use it.
4811
4812    p_vci_ini_c.rspack  = true;
4813
4814    /////////////////////////////////////////////////////////////////
4815    // VCI initiator command on the direct network
4816    // it depends on the CMD FSM state
4817
4818    p_vci_ini_d.pktid  = 0;
4819    p_vci_ini_d.srcid  = m_srcid_d;
4820    p_vci_ini_d.cons   = (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4821    p_vci_ini_d.contig = not (r_vci_cmd_fsm.read() == CMD_DATA_SC);
4822    p_vci_ini_d.wrap   = false;
4823    p_vci_ini_d.clen   = 0;
4824    p_vci_ini_d.cfixed = false;
4825
4826    switch ( r_vci_cmd_fsm.read() ) {
4827
4828    case CMD_IDLE:
4829        p_vci_ini_d.cmdval  = false;
4830        p_vci_ini_d.address = 0;
4831        p_vci_ini_d.wdata   = 0;
4832        p_vci_ini_d.be      = 0;
4833        p_vci_ini_d.trdid   = 0;
4834        p_vci_ini_d.plen    = 0;
4835        p_vci_ini_d.cmd     = vci_param::CMD_NOP;
4836        p_vci_ini_d.eop     = false;
4837        break;
4838
4839    case CMD_INS_MISS:
4840        p_vci_ini_d.cmdval  = true;
4841        p_vci_ini_d.address = r_icache_vci_paddr.read() & m_icache_yzmask;
4842        p_vci_ini_d.wdata   = 0;
4843        p_vci_ini_d.be      = 0xF;
4844        p_vci_ini_d.trdid   = TYPE_INS_MISS;
4845        p_vci_ini_d.plen    = m_icache_words<<2;
4846        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4847        p_vci_ini_d.eop     = true;
4848        break;
4849
4850    case CMD_INS_UNC:
4851        p_vci_ini_d.cmdval  = true;
4852        p_vci_ini_d.address = r_icache_vci_paddr.read() & ~0x3;
4853        p_vci_ini_d.wdata   = 0;
4854        p_vci_ini_d.be      = 0xF;
4855        p_vci_ini_d.trdid   = TYPE_INS_UNC;
4856        p_vci_ini_d.plen    = 4;
4857        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4858        p_vci_ini_d.eop     = true;
4859        break;
4860
4861    case CMD_DATA_MISS:
4862        p_vci_ini_d.cmdval  = true;
4863        p_vci_ini_d.address = r_dcache_vci_paddr.read() & m_dcache_yzmask;
4864        p_vci_ini_d.wdata   = 0;
4865        p_vci_ini_d.be      = 0xF;
4866        p_vci_ini_d.trdid   = TYPE_DATA_MISS;
4867        p_vci_ini_d.plen    = m_dcache_words << 2;
4868        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4869        p_vci_ini_d.eop     = true;
4870        break;
4871
4872    case CMD_DATA_UNC:
4873        p_vci_ini_d.cmdval  = true;
4874        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4875        p_vci_ini_d.wdata   = 0;
4876        p_vci_ini_d.be      = r_dcache_vci_unc_be.read();
4877        p_vci_ini_d.trdid   = TYPE_DATA_UNC;
4878        p_vci_ini_d.plen    = 4;
4879        p_vci_ini_d.cmd     = vci_param::CMD_READ;
4880        p_vci_ini_d.eop     = true;
4881        break;
4882
4883    case CMD_DATA_WRITE:
4884        p_vci_ini_d.cmdval  = true;
4885        p_vci_ini_d.address = r_wbuf.getAddress(r_vci_cmd_cpt.read()) & ~0x3;
4886        p_vci_ini_d.wdata   = r_wbuf.getData(r_vci_cmd_cpt.read());
4887        p_vci_ini_d.be      = r_wbuf.getBe(r_vci_cmd_cpt.read());
4888        p_vci_ini_d.trdid   = r_wbuf.getIndex() + (1<<(vci_param::T-1));
4889        p_vci_ini_d.plen    = (r_vci_cmd_max.read() - r_vci_cmd_min.read() + 1) << 2;
4890        p_vci_ini_d.cmd     = vci_param::CMD_WRITE;
4891        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == r_vci_cmd_max.read());
4892        break;
4893
4894    case CMD_DATA_SC:
4895        p_vci_ini_d.cmdval  = true;
4896        p_vci_ini_d.address = r_dcache_vci_paddr.read() & ~0x3;
4897        if ( r_vci_cmd_cpt.read() == 0 ) p_vci_ini_d.wdata = r_dcache_vci_sc_old.read();
4898        else                             p_vci_ini_d.wdata = r_dcache_vci_sc_new.read();
4899        p_vci_ini_d.be      = 0xF;
4900        p_vci_ini_d.trdid   = TYPE_DATA_UNC; 
4901        p_vci_ini_d.plen    = 8;
4902        p_vci_ini_d.cmd     = vci_param::CMD_STORE_COND;
4903        p_vci_ini_d.eop     = (r_vci_cmd_cpt.read() == 1);
4904        break;     
4905    } // end switch r_vci_cmd_fsm
4906
4907    //////////////////////////////////////////////////////////
4908    // VCI initiator response on the direct network
4909    // it depends on the VCI RSP state
4910
4911    switch (r_vci_rsp_fsm.read() )
4912    {
4913        case RSP_DATA_WRITE : p_vci_ini_d.rspack = true; break;
4914        case RSP_INS_MISS   : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4915        case RSP_INS_UNC    : p_vci_ini_d.rspack = r_vci_rsp_fifo_icache.wok(); break;
4916        case RSP_DATA_MISS  : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4917        case RSP_DATA_UNC   : p_vci_ini_d.rspack = r_vci_rsp_fifo_dcache.wok(); break;
4918        case RSP_IDLE       : p_vci_ini_d.rspack = false; break;
4919    } // end switch r_vci_rsp_fsm
4920
4921    ////////////////////////////////////////////////////////////////
4922    // VCI target command and response on the coherence network
4923    switch ( r_tgt_fsm.read() ) 
4924    {
4925    case TGT_IDLE:
4926    case TGT_UPDT_WORD:
4927    case TGT_UPDT_DATA:
4928        p_vci_tgt_c.cmdack  = true;
4929        p_vci_tgt_c.rspval  = false;
4930        break;
4931
4932    case TGT_RSP_BROADCAST:
4933        p_vci_tgt_c.cmdack  = false;
4934        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and not r_tgt_dcache_req.read()
4935                              and ( r_tgt_icache_rsp.read() or r_tgt_dcache_rsp.read() );
4936        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4937        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4938        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4939        p_vci_tgt_c.rdata   = 0;
4940        p_vci_tgt_c.rerror  = 0;
4941        p_vci_tgt_c.reop    = true;
4942        break;
4943
4944    case TGT_RSP_ICACHE:
4945        p_vci_tgt_c.cmdack  = false;
4946        p_vci_tgt_c.rspval  = not r_tgt_icache_req.read() and r_tgt_icache_rsp.read();
4947        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4948        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4949        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4950        p_vci_tgt_c.rdata   = 0;
4951        p_vci_tgt_c.rerror  = 0;
4952        p_vci_tgt_c.reop    = true;
4953        break;
4954
4955    case TGT_RSP_DCACHE:
4956        p_vci_tgt_c.cmdack  = false;
4957        p_vci_tgt_c.rspval  = not r_tgt_dcache_req.read() and r_tgt_dcache_rsp.read();
4958        p_vci_tgt_c.rsrcid  = r_tgt_srcid.read();
4959        p_vci_tgt_c.rpktid  = r_tgt_pktid.read();
4960        p_vci_tgt_c.rtrdid  = r_tgt_trdid.read();
4961        p_vci_tgt_c.rdata   = 0;
4962        p_vci_tgt_c.rerror  = 0;
4963        p_vci_tgt_c.reop    = true;
4964        break;
4965
4966    case TGT_REQ_BROADCAST:
4967    case TGT_REQ_ICACHE:
4968    case TGT_REQ_DCACHE:
4969        p_vci_tgt_c.cmdack  = false;
4970        p_vci_tgt_c.rspval  = false;
4971        break;
4972
4973    } // end switch TGT_FSM
4974} // end genMoore
4975
4976}}
4977
4978// Local Variables:
4979// tab-width: 4
4980// c-basic-offset: 4
4981// c-file-offsets:((innamespace . 0)(inline-open . 0))
4982// indent-tabs-mode: nil
4983// End:
4984
4985// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
Note: See TracBrowser for help on using the repository browser.