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

Last change on this file since 239 was 239, checked in by cfuguet, 12 years ago

Bug fix: When there is a pending write in the stage 1 of the write pipeline (DCACHE_IDLE) and the pipeline is frozen (write uncacheable and pending unc write or not write ok in the wbuf), we must not invalidate this write with the next requests to the DCACHE

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