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

Last change on this file since 262 was 262, checked in by alain, 12 years ago

Bug fixing: The handling of L/R bit update has been modified in DCACHE FSM.
If the L/R bit must be updated after a TLB MISS, the DCACHE FSM request a SC
transaction to update the Page Table, but the PTE copies in the
dcache and in the tlb are not modified. They will be updated
by the coherence mechanism.

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